diff --git a/.github/workflows/_deploy-app.yml b/.github/workflows/_deploy-app.yml index 794ed910..81806c71 100644 --- a/.github/workflows/_deploy-app.yml +++ b/.github/workflows/_deploy-app.yml @@ -89,27 +89,27 @@ jobs: echo "Image: ${IMAGE}" echo "Tag: ${TAG}" - deploy-terraform: - name: Run terraform deployment - - if: inputs.terraform - - strategy: - fail-fast: false - matrix: - environment: [at21, at22] - - needs: - - build-push - - uses: ./.github/workflows/_deploy-app-terraform.yml - with: - environment: ${{ matrix.environment }} - working_dir: ${{ inputs.path }}/deploy - tf_state: ${{ inputs.terraformStateFile }} - tf_args: "-var image=${{ needs.build-push.outputs.image }}" - - databaseBootstrap: ${{ inputs.databaseBootstrap }} - databaseName: ${{ inputs.databaseName }} - databaseRoleprefix: ${{ inputs.databaseRoleprefix }} - databaseSchema: ${{ inputs.databaseSchema }} + # deploy-terraform: + # name: Run terraform deployment + + # if: inputs.terraform + + # strategy: + # fail-fast: false + # matrix: + # environment: [at21, at22] + + # needs: + # - build-push + + # uses: ./.github/workflows/_deploy-app-terraform.yml + # with: + # environment: ${{ matrix.environment }} + # working_dir: ${{ inputs.path }}/deploy + # tf_state: ${{ inputs.terraformStateFile }} + # tf_args: "-var image=${{ needs.build-push.outputs.image }}" + + # databaseBootstrap: ${{ inputs.databaseBootstrap }} + # databaseName: ${{ inputs.databaseName }} + # databaseRoleprefix: ${{ inputs.databaseRoleprefix }} + # databaseSchema: ${{ inputs.databaseSchema }} diff --git a/.justfile b/.justfile index e75e5016..c13aa508 100644 --- a/.justfile +++ b/.justfile @@ -5,22 +5,22 @@ # Install node packages required to run scripts - uses pnpm to install the packages [private] @install-script-packages: - #!pwsh + #!/usr/bin/env pwsh pushd .github/scripts pnpm install [private] @install-script-packages-frozen: - #!pwsh + #!/usr/bin/env pwsh pushd .github/scripts pnpm install --frozen-lockfile # Run the script to update solution files @update-sln-files: install-script-packages-frozen - #!pwsh + #!/usr/bin/env pwsh ./.github/scripts/node_modules/.bin/tsx ./.github/scripts/update-sln-files.mts # Print all projects metadata @get-metadata: install-script-packages-frozen - #!pwsh + #!/usr/bin/env pwsh ./.github/scripts/node_modules/.bin/tsx ./.github/scripts/get-metadata.mts diff --git a/Altinn.Authorization.sln b/Altinn.Authorization.sln index 1570f66f..64725550 100644 --- a/Altinn.Authorization.sln +++ b/Altinn.Authorization.sln @@ -3,55 +3,87 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{975139F1-669A-47EF-B6FB-9514471F6058}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DE24A865-2B94-42FE-84BF-F21C06B28927}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{7A57912A-A922-4866-8BD8-A55CEB91B2FD}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.AccessPackages", "Altinn.Authorization.AccessPackages", "{4563D148-CDCF-4126-9888-BD57F293BC37}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.AccessManagement", "Altinn.Authorization.AccessManagement", "{78BCBBBB-4B3F-4621-999E-ADC3D49C3400}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3BF6354A-38B6-44FA-8372-C297B02593AD}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3EE68CF0-E104-414F-978D-AAAFE606E706}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.AccessPackages", "src\apps\Altinn.Authorization.AccessPackages\src\Altinn.Authorization.AccessPackages\Altinn.Authorization.AccessPackages.csproj", "{3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Core", "src\apps\Altinn.Authorization.AccessManagement\src\Altinn.AccessManagement.Core\Altinn.AccessManagement.Core.csproj", "{307E7D19-617B-4CA7-9D21-05ECD210E742}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.DeployApi", "Altinn.Authorization.DeployApi", "{D257B57A-E3D7-4D91-AFBA-43C0A892ABDC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Integration", "src\apps\Altinn.Authorization.AccessManagement\src\Altinn.AccessManagement.Integration\Altinn.AccessManagement.Integration.csproj", "{2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C2A52F6B-FA60-49E5-A74B-F508EE7BE4F9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Persistence", "src\apps\Altinn.Authorization.AccessManagement\src\Altinn.AccessManagement.Persistence\Altinn.AccessManagement.Persistence.csproj", "{835EE660-767B-42F7-AD06-3748F6A0CAFC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.DeployApi", "src\apps\Altinn.Authorization.DeployApi\src\Altinn.Authorization.DeployApi\Altinn.Authorization.DeployApi.csproj", "{FB9E7D21-3AAA-40A8-A1D2-9140671838EF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement", "src\apps\Altinn.Authorization.AccessManagement\src\Altinn.Authorization.AccessManagement\Altinn.AccessManagement.csproj", "{DF6C3D34-D5D8-4FF6-BD65-972B58979AD7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.AccessPackages.Models", "src\apps\Altinn.Authorization.AccessPackages\src\Altinn.Authorization.AccessPackages.Models\Altinn.Authorization.AccessPackages.Models.csproj", "{6AAC3869-D894-45B7-9339-94774CC1F321}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C60F699D-057F-4FD5-B65A-DF94D4D8B6E7}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Index", "Altinn.Authorization.Index", "{C417CFA9-3AEE-42FF-A70D-C50CA927CA3D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Tests", "src\apps\Altinn.Authorization.AccessManagement\test\Altinn.AccessManagement.Tests\Altinn.AccessManagement.Tests.csproj", "{E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6D228887-7EEA-4E7F-A6FA-06B34D614141}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.AccessPackages", "Altinn.Authorization.AccessPackages", "{F5BD7A32-3249-462D-9DBB-B0199E30789C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Index", "src\apps\Altinn.Authorization.Index\src\Altinn.Authorization.Index\Altinn.Authorization.Index.csproj", "{9776299B-47AE-4602-8A34-2A53F8EBAF22}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E02F98B0-98F1-4B74-B69D-EE820433360A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{8A0804D3-795C-4D1B-B896-EFBF61F275DC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.AccessPackages", "src\apps\Altinn.Authorization.AccessPackages\src\Altinn.Authorization.AccessPackages\Altinn.Authorization.AccessPackages.csproj", "{D64F8AE2-486C-4A4B-A683-3E7BA3074E84}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Configuration", "Altinn.Authorization.Configuration", "{B80707D6-12E4-41EC-B72E-D93A264FCD65}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.AccessPackages.Models", "src\apps\Altinn.Authorization.AccessPackages\src\Altinn.Authorization.AccessPackages.Models\Altinn.Authorization.AccessPackages.Models.csproj", "{86977C4D-7BEB-4420-AD9A-40AC2F41DD12}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C37C79A6-1256-4EAC-BC21-918743D0E7EF}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.DeployApi", "Altinn.Authorization.DeployApi", "{2AEAF5A1-3548-40F9-8EF9-16CCE43B21CB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.Postgres", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration.Postgres\Altinn.Authorization.Configuration.Postgres.csproj", "{2296F778-A71F-40B2-818E-23F077D63722}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{54F6103D-EF1A-4AB4-8E4C-AD89552D130E}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{12944668-5C16-4E7B-878D-16797DE5307C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.DeployApi", "src\apps\Altinn.Authorization.DeployApi\src\Altinn.Authorization.DeployApi\Altinn.Authorization.DeployApi.csproj", "{9C38BBCB-A82D-49B8-9E33-9BEADDF029E5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.Tests", "src\libs\Altinn.Authorization.Configuration\tests\Altinn.Authorization.Configuration.Tests\Altinn.Authorization.Configuration.Tests.csproj", "{886728F4-7632-45A6-9C0F-147F71325F12}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Index", "Altinn.Authorization.Index", "{02ECB7FC-14D1-4310-884E-C0FC79F787FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration\Altinn.Authorization.Configuration.csproj", "{A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E4043CB1-7F13-45F3-B62F-5306971435EB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.OpenTelemetry", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration.OpenTelemetry\Altinn.Authorization.Configuration.OpenTelemetry.csproj", "{C9A0D181-700B-4B54-995E-6AAB62584B15}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Index", "src\apps\Altinn.Authorization.Index\src\Altinn.Authorization.Index\Altinn.Authorization.Index.csproj", "{D6D1724F-873B-48BD-A8AD-F6E0915ABD67}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Hosting", "Altinn.Authorization.Hosting", "{EB54B6F3-D4CE-4C49-90AC-993D59327008}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{5514C81E-13A7-40C9-A695-19ECFCD23DE8}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D4E493DD-D9AB-4D68-BD8E-9BE156CD175A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Configuration", "Altinn.Authorization.Configuration", "{FE9CEC6D-C72C-4F7B-AF91-AEBAF175C3C9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Hosting", "src\libs\Altinn.Authorization.Hosting\src\Altinn.Authorization.Hosting\Altinn.Authorization.Hosting.csproj", "{C7F9BA45-8010-4B92-8CC7-5050107F2BFE}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FFE61949-10AB-475C-B45D-E405B72C48AF}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7E2E4A16-8A53-4E6A-BC22-832D541E1B92}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration\Altinn.Authorization.Configuration.csproj", "{B35658FD-6786-4E62-8E33-A16E850A0681}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Hosting.Tests", "src\libs\Altinn.Authorization.Hosting\tests\Altinn.Authorization.Hosting.Tests\Altinn.Authorization.Hosting.Tests.csproj", "{53F3961A-B2F9-4BF8-9365-80D93DB621B2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.OpenTelemetry", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration.OpenTelemetry\Altinn.Authorization.Configuration.OpenTelemetry.csproj", "{1C8DAFC4-5436-4B88-B755-C714B3AF55D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.Postgres", "src\libs\Altinn.Authorization.Configuration\src\Altinn.Authorization.Configuration.Postgres\Altinn.Authorization.Configuration.Postgres.csproj", "{D363DDF3-2B0F-4982-B169-A3D13F3DC227}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7274498B-9227-4C4D-8FA1-FEB39C237092}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Configuration.Tests", "src\libs\Altinn.Authorization.Configuration\tests\Altinn.Authorization.Configuration.Tests\Altinn.Authorization.Configuration.Tests.csproj", "{A90481D9-6811-42DC-982B-CD6B43173F22}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.Authorization.Hosting", "Altinn.Authorization.Hosting", "{D847014E-BF21-47CB-84EE-609BBA9DC0FA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2324178C-A39A-4D66-B389-47715534DCD4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Hosting", "src\libs\Altinn.Authorization.Hosting\src\Altinn.Authorization.Hosting\Altinn.Authorization.Hosting.csproj", "{8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{07BEEFD7-EF32-4213-B94B-D0911252FBFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.Authorization.Hosting.Tests", "src\libs\Altinn.Authorization.Hosting\tests\Altinn.Authorization.Hosting.Tests\Altinn.Authorization.Hosting.Tests.csproj", "{F592F818-1762-4BD4-A0B4-829246053E6F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Altinn.AccessManagement", "Altinn.AccessManagement", "{51F9AEC3-3367-427F-867E-E4F4A0169A5C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1B272AAB-1044-4E8C-988B-090D6F838FFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement", "src\apps\Altinn.AccessManagement\src\Altinn.AccessManagement\Altinn.AccessManagement.csproj", "{70DDC969-E82E-4A85-9651-86A5D3B68D3E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Core", "src\apps\Altinn.AccessManagement\src\Altinn.AccessManagement.Core\Altinn.AccessManagement.Core.csproj", "{7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Integration", "src\apps\Altinn.AccessManagement\src\Altinn.AccessManagement.Integration\Altinn.AccessManagement.Integration.csproj", "{7D93124A-8BD9-4BB4-8605-126BA6D6E7D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Persistence", "src\apps\Altinn.AccessManagement\src\Altinn.AccessManagement.Persistence\Altinn.AccessManagement.Persistence.csproj", "{EFBF6A37-CB36-4323-A6D2-5A914C29C838}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6AF3BDE5-F14C-496C-90A9-29DDC108A8FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Tests", "src\apps\Altinn.AccessManagement\test\Altinn.AccessManagement.Tests\Altinn.AccessManagement.Tests.csproj", "{0DA470DA-7794-4352-89E0-0F22546DF2E4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -62,71 +94,127 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA}.Release|Any CPU.Build.0 = Release|Any CPU - {FB9E7D21-3AAA-40A8-A1D2-9140671838EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB9E7D21-3AAA-40A8-A1D2-9140671838EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB9E7D21-3AAA-40A8-A1D2-9140671838EF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB9E7D21-3AAA-40A8-A1D2-9140671838EF}.Release|Any CPU.Build.0 = Release|Any CPU - {6AAC3869-D894-45B7-9339-94774CC1F321}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6AAC3869-D894-45B7-9339-94774CC1F321}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6AAC3869-D894-45B7-9339-94774CC1F321}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6AAC3869-D894-45B7-9339-94774CC1F321}.Release|Any CPU.Build.0 = Release|Any CPU - {9776299B-47AE-4602-8A34-2A53F8EBAF22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9776299B-47AE-4602-8A34-2A53F8EBAF22}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9776299B-47AE-4602-8A34-2A53F8EBAF22}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9776299B-47AE-4602-8A34-2A53F8EBAF22}.Release|Any CPU.Build.0 = Release|Any CPU - {2296F778-A71F-40B2-818E-23F077D63722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2296F778-A71F-40B2-818E-23F077D63722}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2296F778-A71F-40B2-818E-23F077D63722}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2296F778-A71F-40B2-818E-23F077D63722}.Release|Any CPU.Build.0 = Release|Any CPU - {886728F4-7632-45A6-9C0F-147F71325F12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {886728F4-7632-45A6-9C0F-147F71325F12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {886728F4-7632-45A6-9C0F-147F71325F12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {886728F4-7632-45A6-9C0F-147F71325F12}.Release|Any CPU.Build.0 = Release|Any CPU - {A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B}.Release|Any CPU.Build.0 = Release|Any CPU - {C9A0D181-700B-4B54-995E-6AAB62584B15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9A0D181-700B-4B54-995E-6AAB62584B15}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9A0D181-700B-4B54-995E-6AAB62584B15}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9A0D181-700B-4B54-995E-6AAB62584B15}.Release|Any CPU.Build.0 = Release|Any CPU - {C7F9BA45-8010-4B92-8CC7-5050107F2BFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7F9BA45-8010-4B92-8CC7-5050107F2BFE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7F9BA45-8010-4B92-8CC7-5050107F2BFE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7F9BA45-8010-4B92-8CC7-5050107F2BFE}.Release|Any CPU.Build.0 = Release|Any CPU - {53F3961A-B2F9-4BF8-9365-80D93DB621B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {53F3961A-B2F9-4BF8-9365-80D93DB621B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F3961A-B2F9-4BF8-9365-80D93DB621B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53F3961A-B2F9-4BF8-9365-80D93DB621B2}.Release|Any CPU.Build.0 = Release|Any CPU + {307E7D19-617B-4CA7-9D21-05ECD210E742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {307E7D19-617B-4CA7-9D21-05ECD210E742}.Debug|Any CPU.Build.0 = Debug|Any CPU + {307E7D19-617B-4CA7-9D21-05ECD210E742}.Release|Any CPU.ActiveCfg = Release|Any CPU + {307E7D19-617B-4CA7-9D21-05ECD210E742}.Release|Any CPU.Build.0 = Release|Any CPU + {2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A}.Release|Any CPU.Build.0 = Release|Any CPU + {835EE660-767B-42F7-AD06-3748F6A0CAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {835EE660-767B-42F7-AD06-3748F6A0CAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {835EE660-767B-42F7-AD06-3748F6A0CAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {835EE660-767B-42F7-AD06-3748F6A0CAFC}.Release|Any CPU.Build.0 = Release|Any CPU + {DF6C3D34-D5D8-4FF6-BD65-972B58979AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF6C3D34-D5D8-4FF6-BD65-972B58979AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF6C3D34-D5D8-4FF6-BD65-972B58979AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF6C3D34-D5D8-4FF6-BD65-972B58979AD7}.Release|Any CPU.Build.0 = Release|Any CPU + {E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7}.Release|Any CPU.Build.0 = Release|Any CPU + {D64F8AE2-486C-4A4B-A683-3E7BA3074E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D64F8AE2-486C-4A4B-A683-3E7BA3074E84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D64F8AE2-486C-4A4B-A683-3E7BA3074E84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D64F8AE2-486C-4A4B-A683-3E7BA3074E84}.Release|Any CPU.Build.0 = Release|Any CPU + {86977C4D-7BEB-4420-AD9A-40AC2F41DD12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86977C4D-7BEB-4420-AD9A-40AC2F41DD12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86977C4D-7BEB-4420-AD9A-40AC2F41DD12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86977C4D-7BEB-4420-AD9A-40AC2F41DD12}.Release|Any CPU.Build.0 = Release|Any CPU + {9C38BBCB-A82D-49B8-9E33-9BEADDF029E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C38BBCB-A82D-49B8-9E33-9BEADDF029E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C38BBCB-A82D-49B8-9E33-9BEADDF029E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C38BBCB-A82D-49B8-9E33-9BEADDF029E5}.Release|Any CPU.Build.0 = Release|Any CPU + {D6D1724F-873B-48BD-A8AD-F6E0915ABD67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6D1724F-873B-48BD-A8AD-F6E0915ABD67}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6D1724F-873B-48BD-A8AD-F6E0915ABD67}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6D1724F-873B-48BD-A8AD-F6E0915ABD67}.Release|Any CPU.Build.0 = Release|Any CPU + {B35658FD-6786-4E62-8E33-A16E850A0681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B35658FD-6786-4E62-8E33-A16E850A0681}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B35658FD-6786-4E62-8E33-A16E850A0681}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B35658FD-6786-4E62-8E33-A16E850A0681}.Release|Any CPU.Build.0 = Release|Any CPU + {1C8DAFC4-5436-4B88-B755-C714B3AF55D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C8DAFC4-5436-4B88-B755-C714B3AF55D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C8DAFC4-5436-4B88-B755-C714B3AF55D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C8DAFC4-5436-4B88-B755-C714B3AF55D1}.Release|Any CPU.Build.0 = Release|Any CPU + {D363DDF3-2B0F-4982-B169-A3D13F3DC227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D363DDF3-2B0F-4982-B169-A3D13F3DC227}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D363DDF3-2B0F-4982-B169-A3D13F3DC227}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D363DDF3-2B0F-4982-B169-A3D13F3DC227}.Release|Any CPU.Build.0 = Release|Any CPU + {A90481D9-6811-42DC-982B-CD6B43173F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A90481D9-6811-42DC-982B-CD6B43173F22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A90481D9-6811-42DC-982B-CD6B43173F22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A90481D9-6811-42DC-982B-CD6B43173F22}.Release|Any CPU.Build.0 = Release|Any CPU + {8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1}.Release|Any CPU.Build.0 = Release|Any CPU + {F592F818-1762-4BD4-A0B4-829246053E6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F592F818-1762-4BD4-A0B4-829246053E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F592F818-1762-4BD4-A0B4-829246053E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F592F818-1762-4BD4-A0B4-829246053E6F}.Release|Any CPU.Build.0 = Release|Any CPU + {70DDC969-E82E-4A85-9651-86A5D3B68D3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70DDC969-E82E-4A85-9651-86A5D3B68D3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70DDC969-E82E-4A85-9651-86A5D3B68D3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70DDC969-E82E-4A85-9651-86A5D3B68D3E}.Release|Any CPU.Build.0 = Release|Any CPU + {7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F}.Release|Any CPU.Build.0 = Release|Any CPU + {7D93124A-8BD9-4BB4-8605-126BA6D6E7D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D93124A-8BD9-4BB4-8605-126BA6D6E7D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D93124A-8BD9-4BB4-8605-126BA6D6E7D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D93124A-8BD9-4BB4-8605-126BA6D6E7D0}.Release|Any CPU.Build.0 = Release|Any CPU + {EFBF6A37-CB36-4323-A6D2-5A914C29C838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFBF6A37-CB36-4323-A6D2-5A914C29C838}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFBF6A37-CB36-4323-A6D2-5A914C29C838}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFBF6A37-CB36-4323-A6D2-5A914C29C838}.Release|Any CPU.Build.0 = Release|Any CPU + {0DA470DA-7794-4352-89E0-0F22546DF2E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DA470DA-7794-4352-89E0-0F22546DF2E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DA470DA-7794-4352-89E0-0F22546DF2E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DA470DA-7794-4352-89E0-0F22546DF2E4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution - {7A57912A-A922-4866-8BD8-A55CEB91B2FD} = {975139F1-669A-47EF-B6FB-9514471F6058} - {4563D148-CDCF-4126-9888-BD57F293BC37} = {7A57912A-A922-4866-8BD8-A55CEB91B2FD} - {3BF6354A-38B6-44FA-8372-C297B02593AD} = {4563D148-CDCF-4126-9888-BD57F293BC37} - {3BE07AA7-161E-447E-AB3E-1EF3EBC0CFAA} = {3BF6354A-38B6-44FA-8372-C297B02593AD} - {D257B57A-E3D7-4D91-AFBA-43C0A892ABDC} = {7A57912A-A922-4866-8BD8-A55CEB91B2FD} - {C2A52F6B-FA60-49E5-A74B-F508EE7BE4F9} = {D257B57A-E3D7-4D91-AFBA-43C0A892ABDC} - {FB9E7D21-3AAA-40A8-A1D2-9140671838EF} = {C2A52F6B-FA60-49E5-A74B-F508EE7BE4F9} - {6AAC3869-D894-45B7-9339-94774CC1F321} = {3BF6354A-38B6-44FA-8372-C297B02593AD} - {C417CFA9-3AEE-42FF-A70D-C50CA927CA3D} = {7A57912A-A922-4866-8BD8-A55CEB91B2FD} - {6D228887-7EEA-4E7F-A6FA-06B34D614141} = {C417CFA9-3AEE-42FF-A70D-C50CA927CA3D} - {9776299B-47AE-4602-8A34-2A53F8EBAF22} = {6D228887-7EEA-4E7F-A6FA-06B34D614141} - {8A0804D3-795C-4D1B-B896-EFBF61F275DC} = {975139F1-669A-47EF-B6FB-9514471F6058} - {B80707D6-12E4-41EC-B72E-D93A264FCD65} = {8A0804D3-795C-4D1B-B896-EFBF61F275DC} - {C37C79A6-1256-4EAC-BC21-918743D0E7EF} = {B80707D6-12E4-41EC-B72E-D93A264FCD65} - {2296F778-A71F-40B2-818E-23F077D63722} = {C37C79A6-1256-4EAC-BC21-918743D0E7EF} - {12944668-5C16-4E7B-878D-16797DE5307C} = {B80707D6-12E4-41EC-B72E-D93A264FCD65} - {886728F4-7632-45A6-9C0F-147F71325F12} = {12944668-5C16-4E7B-878D-16797DE5307C} - {A0B4E5A8-D7AE-4566-BEEB-40670F1AB32B} = {C37C79A6-1256-4EAC-BC21-918743D0E7EF} - {C9A0D181-700B-4B54-995E-6AAB62584B15} = {C37C79A6-1256-4EAC-BC21-918743D0E7EF} - {EB54B6F3-D4CE-4C49-90AC-993D59327008} = {8A0804D3-795C-4D1B-B896-EFBF61F275DC} - {D4E493DD-D9AB-4D68-BD8E-9BE156CD175A} = {EB54B6F3-D4CE-4C49-90AC-993D59327008} - {C7F9BA45-8010-4B92-8CC7-5050107F2BFE} = {D4E493DD-D9AB-4D68-BD8E-9BE156CD175A} - {7E2E4A16-8A53-4E6A-BC22-832D541E1B92} = {EB54B6F3-D4CE-4C49-90AC-993D59327008} - {53F3961A-B2F9-4BF8-9365-80D93DB621B2} = {7E2E4A16-8A53-4E6A-BC22-832D541E1B92} + {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} = {DE24A865-2B94-42FE-84BF-F21C06B28927} + {78BCBBBB-4B3F-4621-999E-ADC3D49C3400} = {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} + {3EE68CF0-E104-414F-978D-AAAFE606E706} = {78BCBBBB-4B3F-4621-999E-ADC3D49C3400} + {307E7D19-617B-4CA7-9D21-05ECD210E742} = {3EE68CF0-E104-414F-978D-AAAFE606E706} + {2FFBF1A5-5F7D-4DEB-B119-E395F6F89C9A} = {3EE68CF0-E104-414F-978D-AAAFE606E706} + {835EE660-767B-42F7-AD06-3748F6A0CAFC} = {3EE68CF0-E104-414F-978D-AAAFE606E706} + {DF6C3D34-D5D8-4FF6-BD65-972B58979AD7} = {3EE68CF0-E104-414F-978D-AAAFE606E706} + {C60F699D-057F-4FD5-B65A-DF94D4D8B6E7} = {78BCBBBB-4B3F-4621-999E-ADC3D49C3400} + {E951B93E-1CDB-4553-9AF1-FB04AE3E3FF7} = {C60F699D-057F-4FD5-B65A-DF94D4D8B6E7} + {F5BD7A32-3249-462D-9DBB-B0199E30789C} = {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} + {E02F98B0-98F1-4B74-B69D-EE820433360A} = {F5BD7A32-3249-462D-9DBB-B0199E30789C} + {D64F8AE2-486C-4A4B-A683-3E7BA3074E84} = {E02F98B0-98F1-4B74-B69D-EE820433360A} + {86977C4D-7BEB-4420-AD9A-40AC2F41DD12} = {E02F98B0-98F1-4B74-B69D-EE820433360A} + {2AEAF5A1-3548-40F9-8EF9-16CCE43B21CB} = {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} + {54F6103D-EF1A-4AB4-8E4C-AD89552D130E} = {2AEAF5A1-3548-40F9-8EF9-16CCE43B21CB} + {9C38BBCB-A82D-49B8-9E33-9BEADDF029E5} = {54F6103D-EF1A-4AB4-8E4C-AD89552D130E} + {02ECB7FC-14D1-4310-884E-C0FC79F787FF} = {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} + {E4043CB1-7F13-45F3-B62F-5306971435EB} = {02ECB7FC-14D1-4310-884E-C0FC79F787FF} + {D6D1724F-873B-48BD-A8AD-F6E0915ABD67} = {E4043CB1-7F13-45F3-B62F-5306971435EB} + {5514C81E-13A7-40C9-A695-19ECFCD23DE8} = {DE24A865-2B94-42FE-84BF-F21C06B28927} + {FE9CEC6D-C72C-4F7B-AF91-AEBAF175C3C9} = {5514C81E-13A7-40C9-A695-19ECFCD23DE8} + {FFE61949-10AB-475C-B45D-E405B72C48AF} = {FE9CEC6D-C72C-4F7B-AF91-AEBAF175C3C9} + {B35658FD-6786-4E62-8E33-A16E850A0681} = {FFE61949-10AB-475C-B45D-E405B72C48AF} + {1C8DAFC4-5436-4B88-B755-C714B3AF55D1} = {FFE61949-10AB-475C-B45D-E405B72C48AF} + {D363DDF3-2B0F-4982-B169-A3D13F3DC227} = {FFE61949-10AB-475C-B45D-E405B72C48AF} + {7274498B-9227-4C4D-8FA1-FEB39C237092} = {FE9CEC6D-C72C-4F7B-AF91-AEBAF175C3C9} + {A90481D9-6811-42DC-982B-CD6B43173F22} = {7274498B-9227-4C4D-8FA1-FEB39C237092} + {D847014E-BF21-47CB-84EE-609BBA9DC0FA} = {5514C81E-13A7-40C9-A695-19ECFCD23DE8} + {2324178C-A39A-4D66-B389-47715534DCD4} = {D847014E-BF21-47CB-84EE-609BBA9DC0FA} + {8853EEFF-C485-4ED4-B107-EB8CFBC6B1B1} = {2324178C-A39A-4D66-B389-47715534DCD4} + {07BEEFD7-EF32-4213-B94B-D0911252FBFA} = {D847014E-BF21-47CB-84EE-609BBA9DC0FA} + {F592F818-1762-4BD4-A0B4-829246053E6F} = {07BEEFD7-EF32-4213-B94B-D0911252FBFA} + {51F9AEC3-3367-427F-867E-E4F4A0169A5C} = {3ABDFDEE-A4D9-4553-B232-E7D5FCDB2143} + {1B272AAB-1044-4E8C-988B-090D6F838FFC} = {51F9AEC3-3367-427F-867E-E4F4A0169A5C} + {70DDC969-E82E-4A85-9651-86A5D3B68D3E} = {1B272AAB-1044-4E8C-988B-090D6F838FFC} + {7BCEAA14-AF6A-4C03-8DF6-E4461C0A612F} = {1B272AAB-1044-4E8C-988B-090D6F838FFC} + {7D93124A-8BD9-4BB4-8605-126BA6D6E7D0} = {1B272AAB-1044-4E8C-988B-090D6F838FFC} + {EFBF6A37-CB36-4323-A6D2-5A914C29C838} = {1B272AAB-1044-4E8C-988B-090D6F838FFC} + {6AF3BDE5-F14C-496C-90A9-29DDC108A8FB} = {51F9AEC3-3367-427F-867E-E4F4A0169A5C} + {0DA470DA-7794-4352-89E0-0F22546DF2E4} = {6AF3BDE5-F14C-496C-90A9-29DDC108A8FB} EndGlobalSection EndGlobal diff --git a/Makefile b/Makefile deleted file mode 100644 index a41a8cbc..00000000 --- a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -SLN=Altinn.Authorization - -dotnet_solution: clean - dotnet new sln -n $(SLN) - find src -name "*.csproj" -print0 | xargs -0 dotnet sln add - -clean: - @rm -f $(SLN).sln - echo "** Clean Solution **" \ No newline at end of file diff --git a/global.json b/global.json index 501e79a8..d5bf446d 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + "version": "9.0.100", "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index 0103007d..00000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "devDependencies": { - "@types/node": "^22.7.5" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index fcc75539..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,29 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@types/node': - specifier: ^22.7.5 - version: 22.7.5 - -packages: - - '@types/node@22.7.5': - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - -snapshots: - - '@types/node@22.7.5': - dependencies: - undici-types: 6.19.8 - - undici-types@6.19.8: {} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 163dfa2d..f2c13c12 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,8 @@ - net8.0 + Altinn.Authorization + net9.0 enable 12.0 diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 6aeb1641..2f13c8c9 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -1,54 +1,96 @@ - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/Altinn.AccessManagement.sln b/src/apps/Altinn.AccessManagement/Altinn.AccessManagement.sln new file mode 100644 index 00000000..a9876f49 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/Altinn.AccessManagement.sln @@ -0,0 +1,57 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{960E20A2-19CD-4579-9E93-D2E7C02D3629}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement", "src\Altinn.AccessManagement\Altinn.AccessManagement.csproj", "{A3F09A0C-0978-4F23-9F35-A7343DC76D03}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7EBD92A3-BEBF-4608-9535-F419BF22EE83}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Tests", "test\Altinn.AccessManagement.Tests\Altinn.AccessManagement.Tests.csproj", "{DC83D8C7-BE67-451D-AD00-172CE364468C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Integration", "src\Altinn.AccessManagement.Integration\Altinn.AccessManagement.Integration.csproj", "{F6682422-0B31-4E83-8B03-BE21267A95C4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Core", "src\Altinn.AccessManagement.Core\Altinn.AccessManagement.Core.csproj", "{601CE177-6CC3-4D7B-8CC5-5B173598ECAE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.AccessManagement.Persistence", "src\Altinn.AccessManagement.Persistence\Altinn.AccessManagement.Persistence.csproj", "{8482BD82-0121-4B24-B7E9-4688E41584F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A3F09A0C-0978-4F23-9F35-A7343DC76D03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3F09A0C-0978-4F23-9F35-A7343DC76D03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3F09A0C-0978-4F23-9F35-A7343DC76D03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3F09A0C-0978-4F23-9F35-A7343DC76D03}.Release|Any CPU.Build.0 = Release|Any CPU + {DC83D8C7-BE67-451D-AD00-172CE364468C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC83D8C7-BE67-451D-AD00-172CE364468C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC83D8C7-BE67-451D-AD00-172CE364468C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC83D8C7-BE67-451D-AD00-172CE364468C}.Release|Any CPU.Build.0 = Release|Any CPU + {F6682422-0B31-4E83-8B03-BE21267A95C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6682422-0B31-4E83-8B03-BE21267A95C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6682422-0B31-4E83-8B03-BE21267A95C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6682422-0B31-4E83-8B03-BE21267A95C4}.Release|Any CPU.Build.0 = Release|Any CPU + {601CE177-6CC3-4D7B-8CC5-5B173598ECAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {601CE177-6CC3-4D7B-8CC5-5B173598ECAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {601CE177-6CC3-4D7B-8CC5-5B173598ECAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {601CE177-6CC3-4D7B-8CC5-5B173598ECAE}.Release|Any CPU.Build.0 = Release|Any CPU + {8482BD82-0121-4B24-B7E9-4688E41584F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8482BD82-0121-4B24-B7E9-4688E41584F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8482BD82-0121-4B24-B7E9-4688E41584F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8482BD82-0121-4B24-B7E9-4688E41584F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A3F09A0C-0978-4F23-9F35-A7343DC76D03} = {960E20A2-19CD-4579-9E93-D2E7C02D3629} + {DC83D8C7-BE67-451D-AD00-172CE364468C} = {7EBD92A3-BEBF-4608-9535-F419BF22EE83} + {F6682422-0B31-4E83-8B03-BE21267A95C4} = {960E20A2-19CD-4579-9E93-D2E7C02D3629} + {601CE177-6CC3-4D7B-8CC5-5B173598ECAE} = {960E20A2-19CD-4579-9E93-D2E7C02D3629} + {8482BD82-0121-4B24-B7E9-4688E41584F8} = {960E20A2-19CD-4579-9E93-D2E7C02D3629} + EndGlobalSection +EndGlobal diff --git a/src/apps/Altinn.AccessManagement/Dockerfile b/src/apps/Altinn.AccessManagement/Dockerfile new file mode 100644 index 00000000..5d1c310f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +WORKDIR /app + +# Copy everything and build +COPY . . +RUN dotnet restore + +# Copy everything else and build +RUN dotnet publish -c Release -o out ./src/Altinn.AccessManagement/Altinn.AccessManagement.csproj + +# Build runtime image +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final +EXPOSE 5110 +WORKDIR /app +COPY --from=build /app/out . + +# setup the user and group +# the user will have no password, using shell /bin/false and using the group dotnet +RUN addgroup -g 3000 dotnet && adduser -u 1000 -G dotnet -D -s /bin/false dotnet +# update permissions of files if neccessary before becoming dotnet user +USER dotnet +RUN mkdir /tmp/logtelemetry +ENTRYPOINT ["dotnet", "Altinn.AccessManagement.dll"] diff --git a/src/apps/Altinn.AccessManagement/README.md b/src/apps/Altinn.AccessManagement/README.md new file mode 100644 index 00000000..aeeabb33 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/README.md @@ -0,0 +1,45 @@ +# altinn-access-management + +This component will handle backend functionality related to Access Management +- Administration of rights for apps, resources +- Administration of rights for api schemes + +## Getting started + +The fastest way to get development going is to open the main solution Altinn.AccessManagement.sln and selecting 'Altinn.AccessManagement' as the start up project from Visual Studio. Browser should open automatically to the swagger ui for the API. + +Alternatively: + +- Start the backend in `/src/Altinn.AccessManagement/Altinn.AccessManagement` with `dotnet run` or `dotnet watch` + +## Project organisation + +This is a typical backend API solution written in .NET C#. + +- The main back end project is in `/src/Altinn.Authorizationadmin` and it has [its own README](backend/src/Altinn.Authorizationadmin/Altinn.Authorizationadmin/README.md) + +- There is also a "bridge" between the back end and older APIs. For local development, this is implemented in `/development/src/LocalBridge` + + +## Setting up database + +To run Access Management locally you need to have PostgreSQL database installed + +- Download [PostgreSQL](https://www.postgresql.org/download/) (Currently using 14 in Azure, but 15 works locally) +- Install database server (choose your own admin password and save it some place you can find it again) +- Start PG admin + + +Create database authorizationdb + +Create the following users (with priveliges for authorizationdb) +-platform_authorization_admin (superuser, canlogin) +-platform_authorization (canlogin) +password: Password + +Create schema delegations in authorizationdb + +Set platform_authorization_admin as owner + + + diff --git a/src/apps/Altinn.AccessManagement/conf.json b/src/apps/Altinn.AccessManagement/conf.json new file mode 100644 index 00000000..50009f85 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/conf.json @@ -0,0 +1,8 @@ +{ + "image": {}, + "infra": { + "terraform": { + "stateFile": "Altinn.Authorization.AccessManagement.tfstate" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Altinn.AccessManagement.Core.csproj b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Altinn.AccessManagement.Core.csproj new file mode 100644 index 00000000..61037b5b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Altinn.AccessManagement.Core.csproj @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\..\..\..\..\.nuget\packages\altinn.common.accesstokenclient\1.0.6\lib\netstandard2.0\Altinn.Common.AccessTokenClient.dll + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Asserter.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Asserter.cs new file mode 100644 index 00000000..00e5a754 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Asserter.cs @@ -0,0 +1,137 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Core.Asserters; + +/// +/// The function signature of an Assertion that validates data +/// +public delegate void Assertion(IDictionary errors, IEnumerable attributes); + +/// +public class Asserter : IAssert +{ + /// + public Assertion Any(params Assertion[] actions) => (errors, values) => + { + var result = new List>(); + foreach (var action in actions) + { + var err = new Dictionary(); + action(err, values); + if (err.Count == 0) + { + return; + } + + result.Add(err); + } + + foreach (var entry in result) + { + foreach (var err in errors) + { + AddError(errors, err); + } + } + }; + + /// + public Assertion All(params Assertion[] actions) => (errors, values) => + { + foreach (var action in actions) + { + action(errors, values); + } + }; + + /// + public Assertion Single(params Assertion[] actions) => (errors, values) => + { + var result = new List>(); + foreach (var action in actions) + { + var err = new Dictionary(); + action(err, values); + if (err.Count > 0) + { + result.Add(err); + } + } + + if (result.Count + 1 == actions.Length) + { + return; + } + + if (result.Count == 0) + { + errors.Add(nameof(Single), ["all assertions passed while it should only be one that passed"]); + } + + foreach (var err in result) + { + foreach (var entry in err) + { + AddError(errors, entry); + } + } + }; + + /// + public ValidationProblemDetails Evaluate(IEnumerable values, params Assertion[] actions) + { + var result = new Dictionary(); + foreach (var action in actions) + { + action(result, values); + } + + if (result.Count > 0) + { + return new ValidationProblemDetails(result); + } + + return null; + } + + /// + public ValidationProblemDetails Join(params ValidationProblemDetails[] evaluations) + { + var result = new ValidationProblemDetails() + { + Status = StatusCodes.Status400BadRequest, + Title = "there is an issue with provided input", + }; + + foreach (var evaluation in evaluations) + { + if (evaluation != null) + { + foreach (var error in evaluation.Errors) + { + AddError(result.Errors, error); + } + } + } + + return result.Errors.Count > 0 ? result : null; + } + + /// + /// add error to the dictionary + /// + /// error dictionary + /// the key-value pair that should be written to the error dict + private static void AddError(IDictionary errors, KeyValuePair entry) + { + if (errors.TryGetValue(entry.Key, out var value)) + { + errors[entry.Key] = value == null ? entry.Value : value.Concat(entry.Value ?? Enumerable.Empty()).Distinct().ToArray(); + } + else + { + errors.Add(entry); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/AttributeMatchAsserter.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/AttributeMatchAsserter.cs new file mode 100644 index 00000000..f9240d70 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/AttributeMatchAsserter.cs @@ -0,0 +1,191 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Resolvers; + +namespace Altinn.AccessManagement.Core.Asserters; + +/// +/// Asserts values for model . +/// +public static class AttributeMatchAsserter +{ + private static string StringifyAttributeIds(IEnumerable values) => $"[{string.Join(",", values.Select(v => v.Id).OrderDescending())}]"; + + private static string StringifyStrings(IEnumerable values) => $"[{string.Join(",", values.OrderDescending())}]"; + + /// + /// Passes if all the given attribute types are contained in the given list of attributes. + /// + public static Assertion HasAttributeTypes(this IAssert _, params string[] attributes) => (errors, values) => + { + IEnumerable intersection = values.Select(v => v.Id).Intersect(attributes); + if (intersection.Count() == attributes.Count() && intersection.Count() == values.Count()) + { + return; + } + + errors.Add(nameof(HasAttributeTypes), [$"attributes {StringifyAttributeIds(values)} is not a combination of {StringifyStrings(attributes)}"]); + }; + + /// + /// Checks if all given types has a value of type integer. Attributes that don't exist in the list of attributes are ignored. + /// + /// list of attributes + /// URN of the types that should be integers + public static Assertion AttributesAreIntegers(this IAssert assert, params string[] types) => (errors, values) => + { + var matchingAttributes = values.Where(attribute => types.Any(type => type.Equals(attribute.Id, StringComparison.InvariantCultureIgnoreCase))); + if (matchingAttributes.Where(attribute => !int.TryParse(attribute.Value, out _)) is var assertedNoneIntegers && assertedNoneIntegers.Any()) + { + errors.Add(nameof(AttributesAreIntegers), [$"attributes {StringifyAttributeIds(values)} can't be parsed as integers"]); + } + }; + + /// + /// Checks if all given types has a value of type boolean. Attributes that don't exist in the list of attributes are ignored. + /// + /// list of attributes + /// URN of the types that should be boolean + public static Assertion AttributesAreBoolean(this IAssert assert, params string[] types) => (errors, values) => + { + var matchingAttributes = values.Where(attribute => types.Any(type => type.Equals(attribute.Id, StringComparison.InvariantCultureIgnoreCase))); + if (matchingAttributes.Where(attribute => !bool.TryParse(attribute.Value, out _)) is var assertedNoneIntegers && assertedNoneIntegers.Any()) + { + errors.Add(nameof(AttributesAreIntegers), [$"attributes {StringifyAttributeIds(values)} can't be parsed as boolean"]); + } + }; + + /// + /// Can pass a custom compare function that compares a single attribute an return a boolean that specifies if it passed or not. + /// + /// list of attributes + /// compare function + public static Assertion AttributeCompare(string type, Func cmp) => (errors, values) => + { + if (values.FirstOrDefault(value => value.Id.Equals(type, StringComparison.InvariantCultureIgnoreCase)) is var value && value != null) + { + if (cmp(value)) + { + return; + } + + errors.Add(nameof(AttributeCompare), [$"comparable functions for attribute {type} gave inequal result"]); + } + else + { + errors.Add(nameof(AttributeCompare), [$"could not find an attribute with type {StringifyAttributeIds(values)}"]); + } + }; + + /// + /// Passes if all attributes has a populated value field. Content is irrelevant, but it can't be an empty string or null + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void AllAttributesHasValues(this IAssert assert, IDictionary errors, IEnumerable values) + { + var attributesWithEmptyValues = values.Where(attribute => string.IsNullOrEmpty(attribute?.Value)); + if (attributesWithEmptyValues.Any()) + { + errors.Add(nameof(AllAttributesHasValues), StringifyAttributeIds(attributesWithEmptyValues).Select(type => $"attribute {type} contains empty value").ToArray()); + } + } + + /// + /// Checks if a resource is delegable. The resource must be in the list of attributes otherwise it fails. + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void IsDelegatableResource(this IAssert assert, IDictionary errors, IEnumerable values) + { + if (values.FirstOrDefault(value => value.Id.Equals(BaseUrn.Altinn.Resource.Delegable, StringComparison.InvariantCultureIgnoreCase)) is var attribute && attribute != null) + { + if (bool.TryParse(attribute.Value, out var value) && value) + { + return; + } + else + { + errors.Add(nameof(IsDelegatableResource), [$"resource is not delegable"]); + } + } + else + { + errors.Add(nameof(IsDelegatableResource), [$"failed to find any attributes with value {BaseUrn.Altinn.Resource.Delegable}"]); + } + } + + /// + /// A default list of assertions that contains the baseline for validating in input delegaton to an entity. + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void DefaultTo(this IAssert assert, IDictionary errors, IEnumerable values) => + assert.All( + assert.Single( + assert.HasAttributeTypes(BaseUrn.Altinn.Person.IdentifierNo), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.Uuid), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.UserId), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.PartyId), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.IdentifierNo), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.Uuid), + assert.HasAttributeTypes(BaseUrn.Altinn.EnterpriseUser.Username), + assert.HasAttributeTypes(BaseUrn.Altinn.EnterpriseUser.Uuid), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.PartyId), + assert.HasAttributeTypes(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute), + assert.HasAttributeTypes(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute)), + assert.AllAttributesHasValues, + assert.AttributesAreIntegers(BaseUrn.InternalIds))(errors, values); + + /// + /// A default list of assertions that contains the baseline for validating in input delegaton from an entity. + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void DefaultFrom(this IAssert assert, IDictionary errors, IEnumerable values) => + assert.All( + assert.Single( + assert.HasAttributeTypes(BaseUrn.Altinn.Person.IdentifierNo), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.Uuid), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.UserId), + assert.HasAttributeTypes(BaseUrn.Altinn.Person.PartyId), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.IdentifierNo), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.Uuid), + assert.HasAttributeTypes(BaseUrn.Altinn.Organization.PartyId), + assert.HasAttributeTypes(BaseUrn.Altinn.EnterpriseUser.Username), + assert.HasAttributeTypes(BaseUrn.Altinn.EnterpriseUser.Uuid), + assert.HasAttributeTypes(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute)), + assert.AllAttributesHasValues, + assert.AttributesAreIntegers(BaseUrn.InternalIds))(errors, values); + + /// + /// A list of assertions for validating input is a single value of either of the internal Altinn 2 identifiers: UserId or PartyId. + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void Altinn2InternalIds(this IAssert assert, IDictionary errors, IEnumerable values) => + assert.All( + assert.Single( + assert.HasAttributeTypes(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute), + assert.HasAttributeTypes(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute)), + assert.AllAttributesHasValues, + assert.AttributesAreIntegers(BaseUrn.Altinn2InternalIds))(errors, values); + + /// + /// A default list of assertions that contains the baseline for validating input for a resource. + /// + /// list of assertions + /// dictionary for writing assertion errors + /// list of attributes + public static void DefaultResource(this IAssert assert, IDictionary errors, IEnumerable values) => + assert.All( + assert.Single( + assert.HasAttributeTypes(BaseUrn.Altinn.Resource.AppOwner, BaseUrn.Altinn.Resource.AppId), + assert.HasAttributeTypes(BaseUrn.Altinn.Resource.ResourceRegistryId)), + assert.AllAttributesHasValues)(errors, values); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Interfaces/IAssert.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Interfaces/IAssert.cs new file mode 100644 index 00000000..30df8984 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Asserters/Interfaces/IAssert.cs @@ -0,0 +1,59 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Core.Asserters; + +/// +/// Contains the basic methods for combining and nesting assertions. +/// Use the to make assertions for one dataset. If you have multiple datasets, +/// you can pass the evaluations to the to get a single assertions result for all +/// the datasets. +/// +/// the model that should +public interface IAssert +{ + /// + /// Joins multiple evaluations to a single result + /// + /// evaluations + /// + /// returns null if all the assertions passed. If an assertion generated an error then these errors will be present in + /// dictionary where the keys should be named the assertion method and value should contain the message(s). + /// + public ValidationProblemDetails Join(params ValidationProblemDetails[] evaluations); + + /// + /// Executes all the assertions using the given dataset + /// + /// the values to be asserted + /// assertions + /// + /// returns null if all the assertions passed. If an assertion generated an error then these errors will be present in + /// dictionary where the keys should be named the assertion method and value should contain the message(s). + /// + ValidationProblemDetails Evaluate(IEnumerable values, params Assertion[] actions); + + /// + /// Single will omit writing to the error dict if there is just one assertion that passes. + /// Can be combined with and + /// to create even more complex assertion. + /// + /// assertions + /// + Assertion Single(params Assertion[] actions); + + /// + /// All errors are directly written to the errors dictionary. This method works as calling the Evaluate method directly + /// with a set of asserts. However, this can also be combined inside or + /// to create even more complex assertion. + /// + /// assertions + /// + Assertion All(params Assertion[] actions); + + /// + /// If any given asserts don't add an error to the errors dictionary parameter, then all other errors are ignored + /// + /// assertions + /// + Assertion Any(params Assertion[] actions); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAccessListsAuthorizationClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAccessListsAuthorizationClient.cs new file mode 100644 index 00000000..0ad47b74 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAccessListsAuthorizationClient.cs @@ -0,0 +1,17 @@ +using Altinn.AccessManagement.Core.Models.AccessList; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces; + +/// +/// Access list authorization interface. +/// +public interface IAccessListsAuthorizationClient +{ + /// + /// Authorization of a given subject for resource access through access lists. + /// + /// The + /// The + /// A representing the result of the asynchronous operation. + Task AuthorizePartyForAccessList(AccessListAuthorizationRequest request, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinn2RightsClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinn2RightsClient.cs new file mode 100644 index 00000000..4e5fc5c9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinn2RightsClient.cs @@ -0,0 +1,39 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces +{ + /// + /// Interface for client for getting Altinn rights from AltinnII SBL Bridge + /// + public interface IAltinn2RightsClient + { + /// + /// Get Altinn rights from AltinnII SBL bridge + /// + /// the authenticated user id + /// the party id of the reportee/from party + /// the service code + /// the service edition code + /// Delegation Check Response + Task PostDelegationCheck(int authenticatedUserId, int reporteePartyId, string serviceCode, string serviceEditionCode); + + /// + /// Post delegation of Altinn 2 service rights to SBL bridge + /// + /// the authenticated user id + /// the party id of the reportee/from party + /// the delegation request model + /// Delegation Response + Task PostDelegation(int authenticatedUserId, int reporteePartyId, SblRightDelegationRequest delegationRequest); + + /// + /// Operation to clear a recipients cached rights from a given reportee/from party, and the recipients authorized parties/reportees + /// + /// The party id of the from party + /// The party id of the to party + /// The user id of the to party (if the recipient is a user) + /// Cancellation token + /// HttpResponse + Task ClearReporteeRights(int fromPartyId, int toPartyId, int toUserId = 0, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinnRolesClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinnRolesClient.cs new file mode 100644 index 00000000..c8df3f84 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAltinnRolesClient.cs @@ -0,0 +1,37 @@ +using Altinn.AccessManagement.Core.Models; +using Authorization.Platform.Authorization.Models; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces; + +/// +/// Interface for client for getting Altinn roles from AltinnII SBL Bridge +/// +public interface IAltinnRolesClient +{ + /// + /// Get the decision point roles for the loggedin user for a selected party + /// + /// the logged in user id + /// the partyid of the person/org the logged in user is representing + /// Cancellation token for the request + /// list of actors that the logged in user can represent + Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default); + + /// + /// Get the roles the user has for a given reportee, as basis for evaluating rights for delegation. + /// For any user having HADM this means, getting additional roles as DAGL etc. + /// + /// the user id + /// the partyid of the person/org the user is representing + /// Cancellation token for the request + /// list of actors that the logged in user can represent + Task> GetRolesForDelegation(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default); + + /// + /// Get the list of authorized parties from Altinn 2 that a given user have one or more accesses for, including + /// + /// The user to get the list of AuthorizedParties for + /// Cancellation token for the request + /// + Task> GetAuthorizedPartiesWithRoles(int userId, CancellationToken cancellationToken = default); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAuthenticationClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAuthenticationClient.cs new file mode 100644 index 00000000..da0aefa7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IAuthenticationClient.cs @@ -0,0 +1,35 @@ +using Altinn.AccessManagement.Core.Models.Authentication; +using DefaultRight = Altinn.AccessManagement.Core.Models.Authentication.DefaultRight; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces +{ + /// + /// Authentication interface. + /// + public interface IAuthenticationClient + { + /// + /// Refreshes the AltinnStudioRuntime JwtToken. + /// + /// Cancellation token + /// Response message from Altinn Platform with refreshed token. + Task RefreshToken(CancellationToken cancellationToken = default); + + /// + /// Fetching a System user from Authentication + /// + /// The party id of the party the systemUSer is registered on + /// The uuid identifying the systemUser + /// Cancellation token + /// + Task GetSystemUser(int partyId, string systemUserId, CancellationToken cancellationToken = default); + + /// + /// Get defined rights for a given System + /// + /// The uuid identifier of the system + /// Cancellation token + /// + Task> GetDefaultRightsForRegisteredSystem(string systemId, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IPartiesClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IPartiesClient.cs new file mode 100644 index 00000000..71d9246a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IPartiesClient.cs @@ -0,0 +1,72 @@ +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces; + +/// +/// Interface for a client wrapper for integration with SBL bridge delegation request API +/// +public interface IPartiesClient +{ + /// + /// Returns partyInfo + /// + /// The party ID to lookup + /// The + /// party information + Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default); + + /// + /// Returns a list of parties + /// + /// List of party IDs to lookup + /// (Optional) Whether subunits should be included as ChildParties, if any of the lookup party IDs are for a main unit + /// The + /// List of parties + Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Returns a list of parties + /// + /// List of party uuids to lookup + /// (Optional) Whether subunits should be included as ChildParties, if any of the parties are a main unit + /// The + /// List of parties + Task> GetPartiesAsync(List partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Returns a list of parties for user + /// + /// The user id + /// The + /// List of parties + Task> GetPartiesForUserAsync(int userId, CancellationToken cancellationToken = default); + + /// + /// Method that fetches a list of PartyIds the given user id has key role access to (where the user inherit delegations to their organization) + /// + /// The user id + /// The + /// list of PartyIds where the logged in user have key role access + Task> GetKeyRoleParties(int userId, CancellationToken cancellationToken = default); + + /// + /// Method that fetches a list of main units for the input list of sub unit partyIds. If any of the input partyIds are not a sub unit the response model will have null values for main unit properties. + /// + /// The list of PartyIds to check and retrieve any main units for + /// The + /// list of main units + Task> GetMainUnits(MainUnitQuery subunitPartyIds, CancellationToken cancellationToken = default); + + /// + /// Looks up a party based on SSN or OrgNumber. + /// + /// + /// SSN or OrgNumber as a PartyLookup object. + /// + /// The + /// + /// The party that represents the given SSN or OrgNumber. + /// + Task LookupPartyBySSNOrOrgNo(PartyLookup partyLookup, CancellationToken cancellationToken = default); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IProfileClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IProfileClient.cs new file mode 100644 index 00000000..141feefd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IProfileClient.cs @@ -0,0 +1,23 @@ +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces +{ + /// + /// Interface for Profile functionality. + /// + public interface IProfileClient + { + /// + /// Method for getting the userprofile for a given user identified by one of the available types of user identifiers: + /// UserId (from Altinn 2 Authn UserProfile) + /// Username (from Altinn 2 Authn UserProfile) + /// SSN/Dnr (from Freg) + /// Uuid (from Altinn 2 Party/UserProfile implementation will be added later) + /// + /// Model for specifying the user identifier to use for the UserProfile lookup + /// The + /// The UserProfile for the given user + Task GetUser(UserProfileLookup userProfileLookup, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IResourceRegistryClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IResourceRegistryClient.cs new file mode 100644 index 00000000..e1637fc5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Clients/Interfaces/IResourceRegistryClient.cs @@ -0,0 +1,41 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Clients.Interfaces +{ + /// + /// Interface for client integration with the Resource Registry + /// + public interface IResourceRegistryClient + { + /// + /// Integration point for retrieving a single resoure by it's resource id + /// + /// The identifier of the resource in the Resource Registry + /// The + /// The resource if exists + Task GetResource(string resourceId, CancellationToken cancellationToken = default); + + /// + /// Integration point for retrieving a list of resources + /// + /// The + /// The resource list if exists + Task> GetResources(CancellationToken cancellationToken = default); + + /// + /// Integration point for retrieving the full list of resources + /// + /// The + /// The resource full list of all resources if exists + Task> GetResourceList(CancellationToken cancellationToken = default); + + /// + /// Integration point for retrieving all resources having any of the request subjects in one or more resource policy rules + /// + /// Urn string representation of the subjects to lookup resources for + /// The + /// Dictionary of all resources per subject, having policy rules with the subject + Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/CacheConfig.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/CacheConfig.cs new file mode 100644 index 00000000..1b035d8b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/CacheConfig.cs @@ -0,0 +1,48 @@ +namespace Altinn.AccessManagement.Core.Configuration +{ + /// + /// Cache configuration settings + /// + public class CacheConfig + { + /// + /// Gets or sets the policy cache timeout (in minutes) + /// + public int PolicyCacheTimeout { get; set; } + + /// + /// Gets or sets the Altinn role cache timeout (in minutes) + /// + public int AltinnRoleCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of party information + /// + public int PartyCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of mainunits + /// + public int MainUnitCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of keyrole partyIds + /// + public int KeyRolePartyIdsCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of a resource from the resource registry + /// + public int ResourceRegistryResourceCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of a subject resources from the resourceregistry + /// + public int ResourceRegistrySubjectResourcesCacheTimeout { get; set; } + + /// + /// Gets or sets the cache timeout (in minutes) for lookup of a rights + /// + public int RightsCacheTimeout { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/FeatureFlags.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/FeatureFlags.cs new file mode 100644 index 00000000..959d9346 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/FeatureFlags.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Configuration +{ + /// + /// Feature management flags + /// + public static class FeatureFlags + { + /// + /// Feature flag for activating the Rights Delegation API + /// + public const string RightsDelegationApi = "RightsDelegationApi"; + + /// + /// Feature flag for activating the Rights Delegation API External + /// + public const string RightsDelegationApiExternal = nameof(RightsDelegationApiExternal); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/GeneralSettings.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/GeneralSettings.cs new file mode 100644 index 00000000..be3b44bc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/GeneralSettings.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Core.Configuration +{ + /// + /// General configuration settings + /// + public class GeneralSettings + { + /// + /// Gets or sets the host name. + /// + public string Hostname { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/UserProfileLookupSettings.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/UserProfileLookupSettings.cs new file mode 100644 index 00000000..7e3cd073 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Configuration/UserProfileLookupSettings.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Configuration +{ + /// + /// UserProfile Lookup Settings + /// + public class UserProfileLookupSettings + { + /// + /// Gets or sets the cache timeout for number of failed lookup attempts (in seconds) + /// + public int FailedAttemptsCacheLifetimeSeconds { get; set; } + + /// + /// Gets or sets the maximum number of failed attempts before lockout + /// + public int MaximumFailedAttempts { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnCoreClaimTypes.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnCoreClaimTypes.cs new file mode 100644 index 00000000..13dd2d68 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnCoreClaimTypes.cs @@ -0,0 +1,63 @@ +namespace Altinn.AccessManagement.Core.Constants +{ + /// + /// The different claim types. + /// + public static class AltinnCoreClaimTypes + { + /// + /// AuthenticationLevel. + /// + public const string AuthenticationLevel = "urn:altinn:authlevel"; + + /// + /// User id. + /// + public const string UserId = "urn:altinn:userid"; + + /// + /// Party id. + /// + public const string PartyID = "urn:altinn:partyid"; + + /// + /// The representing party id. + /// + public const string RepresentingPartyId = "urn:altinn:representingpartyid"; + + /// + /// Usernam. + /// + public const string UserName = "urn:altinn:username"; + + /// + /// Developer. + /// + public const string Developer = "urn:altinn:developer"; + + /// + /// Developertoken. + /// + public const string DeveloperToken = "urn:altinn:developertoken"; + + /// + /// Developertoken id. + /// + public const string DeveloperTokenId = "urn:altinn:developertokenid"; + + /// + /// Method of authentication. + /// + public const string AuthenticateMethod = "urn:altinn:authenticatemethod"; + + /// + /// Organization. + /// + public const string Org = "urn:altinn:org"; + + /// + /// Organization number. + /// + public const string OrgNumber = "urn:altinn:orgNumber"; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnXacmlConstants.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnXacmlConstants.cs new file mode 100644 index 00000000..bad1be53 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AltinnXacmlConstants.cs @@ -0,0 +1,186 @@ +namespace Altinn.AccessManagement.Core.Constants +{ + /// + /// Altinn specific XACML constants used for urn identifiers and attributes + /// + public static class AltinnXacmlConstants + { + /// + /// Altinn specific prefixes + /// + public static class Prefixes + { + /// + /// The Policy Id prefix. + /// + public const string PolicyId = "urn:altinn:policyid:"; + + /// + /// The Obligation Id prefix. + /// + public const string ObligationId = "urn:altinn:obligationid:"; + + /// + /// The Obligation Assignment Id prefix. + /// + public const string ObligationAssignmentid = "urn:altinn:obligation-assignmentid:"; + } + + /// + /// Match attribute identifiers + /// + public static class MatchAttributeIdentifiers + { + /// + /// Org attribute match indentifier + /// + public const string OrgAttribute = "urn:altinn:org"; + + /// + /// App attribute match indentifier + /// + public const string AppAttribute = "urn:altinn:app"; + + /// + /// Instance attribute match indentifier + /// + public const string InstanceAttribute = "urn:altinn:instance-id"; + + /// + /// ResouceRegistry Instance attribute match indentifier + /// + public const string ResourceInstanceAttribute = "urn:altinn:resource:instance-id"; + + /// + /// App resource attribute match indentifier + /// + public const string AppResourceAttribute = "urn:altinn:appresource"; + + /// + /// Task attribute match indentifier + /// + public const string TaskAttribute = "urn:altinn:task"; + + /// + /// End-event attribute match indentifier + /// + public const string EndEventAttribute = "urn:altinn:end-event"; + + /// + /// Party Id attribute match indentifier + /// + public const string PartyAttribute = "urn:altinn:partyid"; + + /// + /// Party uuid attribute match indentifier + /// + public const string PartyUuidAttribute = "urn:altinn:party:uuid"; + + /// + /// User Id attribute match indentifier + /// > + public const string UserAttribute = "urn:altinn:userid"; + + /// + /// Role Code attribute match indentifier + /// + public const string RoleAttribute = "urn:altinn:rolecode"; + + /// + /// Resource Registry attribute match indentifier + /// + public const string ResourceRegistryAttribute = "urn:altinn:resource"; + + /// + /// Resource delegation urn prefix used in Xacml policy rule subjects to identify rights the resourceId value of the attribute, is allowed to perform delegation of. + /// + public const string ResourceDelegationAttribute = "urn:altinn:resource:delegation"; + + /// + /// Organization name + /// + public const string OrganizationName = "urn:altinn:organization:name"; + + /// + /// Organization number attribute match indentifier + /// + public const string OrganizationNumberAttribute = "urn:altinn:organizationnumber"; + + /// + /// Social security number attribute match indentifier + /// + public const string SocialSecurityNumberAttribute = "urn:altinn:ssn"; + + /// + /// Altinn 2 service code attribute match indentifier + /// + public const string ServiceCodeAttribute = "urn:altinn:servicecode"; + + /// + /// Altinn 2 service edition code attribute match indentifier + /// + public const string ServiceEditionCodeAttribute = "urn:altinn:serviceeditioncode"; + + /// + /// Person uuid + /// + public const string PersonUuid = "urn:altinn:person:uuid"; + + /// + /// National identity number for a person + /// + public const string PersonId = "urn:altinn:person:identifier-no"; + + /// + /// Last name of a person + /// + public const string PersonLastName = "urn:altinn:person:lastname"; + + /// + /// Person username + /// + public const string PersonUserName = "urn:altinn:person:username"; + + /// + /// Enterprise user uuid + /// + public const string EnterpriseUserUuid = "urn:altinn:enterpriseuser:uuid"; + + /// + /// Enterprise user username + /// + public const string EnterpriseUserName = "urn:altinn:enterpriseuser:username"; + + /// + /// Organization uuid + /// + public const string OrganizationUuid = "urn:altinn:organization:uuid"; + + /// + /// Organization number + /// + public const string OrganizationId = "urn:altinn:organization:identifier-no"; + + /// + /// SystemUser uuid + /// + public const string SystemUserUuid = "urn:altinn:systemuser:uuid"; + } + + /// + /// Attribute categories. + /// + public static class MatchAttributeCategory + { + /// + /// The minimum authentication level category. + /// + public const string MinimumAuthenticationLevel = "urn:altinn:minimum-authenticationlevel"; + + /// + /// The minimum authentication level for organization category + /// + public const string MinimumAuthenticationLevelOrg = "urn:altinn:minimum-authenticationlevel-org"; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AuthzConstants.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AuthzConstants.cs new file mode 100644 index 00000000..a8470e32 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/AuthzConstants.cs @@ -0,0 +1,98 @@ +namespace Altinn.AccessManagement.Core.Constants +{ + /// + /// Constants related to authorization. + /// + public static class AuthzConstants + { + /// + /// Policy tag for authorizing Altinn.Platform.Authorization API access from AltinnII Authorization + /// + public const string ALTINNII_AUTHORIZATION = "AltinnIIAuthorizationAccess"; + + /// + /// Policy tag for authorizing internal Altinn.Platform.Authorization API access + /// + public const string INTERNAL_AUTHORIZATION = "InternalAuthorizationAccess"; + + /// + /// Policy tag for authorizing Altinn.Platform.Authorization API access + /// + public const string PLATFORM_ACCESS_AUTHORIZATION = "PlatformAccess"; + + /// + /// Policy tag for reading an maskinporten delegation + /// + public const string POLICY_MASKINPORTEN_DELEGATION_READ = "MaskinportenDelegationRead"; + + /// + /// Policy tag for writing an maskinporten delegation + /// + public const string POLICY_MASKINPORTEN_DELEGATION_WRITE = "MaskinportenDelegationWrite"; + + /// + /// Policy tag for reading access management information + /// + public const string POLICY_ACCESS_MANAGEMENT_READ = "AccessManagementRead"; + + /// + /// Policy tag for writing access management delegations + /// + public const string POLICY_ACCESS_MANAGEMENT_WRITE = "AccessManagementWrite"; + + /// + /// Policy tag for scope authorization on the proxy API from Altinn II for the maskinporten integration API + /// + public const string POLICY_MASKINPORTEN_DELEGATIONS_PROXY = "MaskinportenDelegationsProxy"; + + /// + /// Policy tag for scope authorization on the resource owner API for getting the Authorized Party list for a third party + /// + public const string POLICY_RESOURCEOWNER_AUTHORIZEDPARTIES = "ResourceOwnerAuthorizedParty"; + + /// + /// Policy tag for scope authorization on the instance delegation API for Apps + /// + public const string POLICY_APPS_INSTANCEDELEGATION = "AppsInstanceDelegation"; + + /// + /// Scope giving access to getting authorized parties for a given subject. + /// + public const string SCOPE_AUTHORIZEDPARTIES_ENDUSERSYSTEM = "altinn:accessmanagement/authorizedparties"; + + /// + /// Scope giving access to getting authorized parties for any third party, for which the third party have access to one or more of the resource owners services, apps or resources. + /// + public const string SCOPE_AUTHORIZEDPARTIES_RESOURCEOWNER = "altinn:accessmanagement/authorizedparties.resourceowner"; + + /// + /// Scope giving access to getting all authorized parties for any third party + /// + public const string SCOPE_AUTHORIZEDPARTIES_ADMIN = "altinn:accessmanagement/authorizedparties.admin"; + + /// + /// Scope giving access to delegations for Maskinporten schemes owned by authenticated party + /// + public const string SCOPE_MASKINPORTEN_DELEGATIONS = "altinn:maskinporten/delegations"; + + /// + /// Scope giving access to delegations for arbitrary Maskinporten schemes + /// + public const string SCOPE_MASKINPORTEN_DELEGATIONS_ADMIN = "altinn:maskinporten/delegations.admin"; + + /// + /// Claim for scopes from maskinporten token + /// + public const string CLAIM_MASKINPORTEN_SCOPE = "scope"; + + /// + /// Claim for full consumer from maskinporten token + /// + public const string CLAIM_MASKINPORTEN_CONSUMER = "consumer"; + + /// + /// Claim for consumer prefixes from maskinporten token + /// + public const string CLAIM_MASKINPORTEN_CONSUMER_PREFIX = "consumer_prefix"; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/XacmlRequestAttribute.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/XacmlRequestAttribute.cs new file mode 100644 index 00000000..19b16ad3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Constants/XacmlRequestAttribute.cs @@ -0,0 +1,63 @@ +namespace Altinn.AccessManagement.Core.Constants +{ + /// + /// Attribute representations in XACML + /// + public static class XacmlRequestAttribute + { + /// + /// xacml string that represents org + /// + public const string OrgAttribute = "urn:altinn:org"; + + /// + /// xacml string that represents app + /// + public const string AppAttribute = "urn:altinn:app"; + + /// + /// xacml string that represents instanceid + /// + public const string InstanceAttribute = "urn:altinn:instance-id"; + + /// + /// xacm string that represents appresource + /// + public const string AppResourceAttribute = "urn:altinn:appresource"; + + /// + /// xacml string that represents task + /// + public const string TaskAttribute = "urn:altinn:task"; + + /// + /// xacml string that represents end event + /// + public const string EndEventAttribute = "urn:altinn:end-event"; + + /// + /// xacml string that represents party + /// + public const string PartyAttribute = "urn:altinn:partyid"; + + /// + /// xacml string that represents organization number + /// + public const string OrganizationNumberAttribute = "urn:altinn:organizationnumber"; + + /// + /// xacml string that represents user + /// + public const string UserAttribute = "urn:altinn:userid"; + + /// + /// xacml string that represents role + /// + public const string RoleAttribute = "urn:altinn:rolecode"; + + /// + /// xacml string that represents resource + /// + public const string ResourceRegistryAttribute = "urn:altinn:resource"; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/AuthorizedPartyType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/AuthorizedPartyType.cs new file mode 100644 index 00000000..49f0f536 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/AuthorizedPartyType.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Enums; + +/// +/// Enum for different types of Authorized Party +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum AuthorizedPartyType +{ + /// + /// Unknown or unspecified + /// + None = 0, + + /// + /// Party Type is a Person + /// + Person = 1, + + /// + /// Party Type is an Organization + /// + Organization = 2, + + /// + /// Party Type is a Self Identified user + /// + SelfIdentified = 3 +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegableStatus.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegableStatus.cs new file mode 100644 index 00000000..8e5c7627 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegableStatus.cs @@ -0,0 +1,22 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for different right delegation status responses + /// + public enum DelegableStatus + { + /// + /// User is not able to delegate the right + /// + [EnumMember(Value = "NotDelegable")] + NotDelegable = 0, + + /// + /// User is able to delegate the right + /// + [EnumMember(Value = "Delegable")] + Delegable = 1 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationActionType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationActionType.cs new file mode 100644 index 00000000..0745bc37 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationActionType.cs @@ -0,0 +1,23 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for the different delegation action types + /// + public enum DelegationActionType + { + /// + /// Default value + /// + Unknown = 0, + + /// + /// Delegation action + /// + Delegation = 1, + + /// + /// Revoke action + /// + Revoke = 2 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationStatus.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationStatus.cs new file mode 100644 index 00000000..0182cbd4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationStatus.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for different right delegation status responses + /// + public enum DelegationStatus + { + /// + /// Right was not delegated + /// + NotDelegated = 0, + + /// + /// Right was delegated + /// + Delegated = 1 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationType.cs new file mode 100644 index 00000000..3eecc6d5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DelegationType.cs @@ -0,0 +1,43 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for the different the types of delegations exist for a delegated right in Altinn Authorization + /// + public enum DelegationType + { + /// + /// Default value + /// + Unknown = 0, + + /// + /// Delegated to user + /// + DirectUserDelegation = 1, + + /// + /// Delegated to user, from main unit + /// + DirectUserDelegationFromMainUnit = 2, + + /// + /// Delegated to organization + /// + DirectOrgDelegation = 3, + + /// + /// Delegated to organization, from main unit + /// + DirectOrgDelegationFromMainUnit = 4, + + /// + /// Delegated to key role relation + /// + KeyRoleDelegation = 5, + + /// + /// Delegated to key role relation, from main unit + /// + KeyRoleDelegationFromMainUnit = 6 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DetailCode.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DetailCode.cs new file mode 100644 index 00000000..4cb3f291 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/DetailCode.cs @@ -0,0 +1,66 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Fixed values for DetailCodes + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum DetailCode + { + /// + /// Unknown reason + /// + Unknown = 0, + + /// + /// Has access by a delegated role in ER or Altinn + /// + RoleAccess = 1, + + /// + /// Has access by direct delegation + /// + DelegationAccess = 2, + + /// + /// The service requires explicit access in SRR and the reportee has this + /// + SrrRightAccess = 3, + + /// + /// Has not access by a delegation of role in ER or Altinn + /// + MissingRoleAccess = 4, + + /// + /// Has not access by direct delegation + /// + MissingDelegationAccess = 5, + + /// + /// The service requires explicit access in SRR and the reportee is missing this + /// + MissingSrrRightAccess = 6, + + /// + /// The service requires explicit authentication level and the reportee is missing this + /// + InsufficientAuthenticationLevel = 7, + + /// + /// The receiver already has the right + /// + AlreadyDelegated = 8, + + /// + /// The receiver has the right based on Access List delegation + /// + AccessListValidationPass = 9, + + /// + /// The receiver does not have the right based on Access List delegation + /// + AccessListValidationFail = 10, + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationMode.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationMode.cs new file mode 100644 index 00000000..7a5d0403 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationMode.cs @@ -0,0 +1,27 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum defining delegation mode (normal or paralellsigning) + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum InstanceDelegationMode + { + /// + /// Normal instance delegation + /// + [EnumMember(Value = "normal")] + [PgName("normal")] + Normal, + + /// + /// Special case of instance delegation extends delegations to organizations to all users in the receiving organization with parallel role/package to also getting access to the instance + /// + [EnumMember(Value = "parallelSigning")] + [PgName("parallelsigning")] + ParallelSigning + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationSource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationSource.cs new file mode 100644 index 00000000..786ac8ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/InstanceDelegationSource.cs @@ -0,0 +1,25 @@ +using System.Runtime.Serialization; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum defining delegation source (app or user) + /// + public enum InstanceDelegationSource + { + /// + /// Delegation by user + /// + [EnumMember(Value = "user")] + [PgName("user")] + User, + + /// + /// Delegation by app + /// + [EnumMember(Value = "app")] + [PgName("app")] + App + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/PolicyAccountType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/PolicyAccountType.cs new file mode 100644 index 00000000..aea0d673 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/PolicyAccountType.cs @@ -0,0 +1,14 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Storage Account + /// + public enum PolicyAccountType + { + ResourceRegister, + + Delegations, + + Metadata, + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceAttributeMatchType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceAttributeMatchType.cs new file mode 100644 index 00000000..8b9dc16d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceAttributeMatchType.cs @@ -0,0 +1,28 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum representation of the different types of resource attribute match types supported + /// + public enum ResourceAttributeMatchType + { + /// + /// Default value + /// + None = 0, + + /// + /// Resource registered in the Altinn Resource Registry + /// + ResourceRegistry = 1, + + /// + /// Legacy App resource identified by org owner and app name + /// + AltinnAppId = 2, + + /// + /// Legacy Altinn 2 service resource identified by service codes + /// + Altinn2Service = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceSource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceSource.cs new file mode 100644 index 00000000..f4ac9282 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceSource.cs @@ -0,0 +1,25 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Enum for the different reference sources for resources in the resource registry + /// + public enum ReferenceSource : int + { + [EnumMember(Value = "Default")] + Default = 0, + + [EnumMember(Value = "Altinn1")] + Altinn1 = 1, + + [EnumMember(Value = "Altinn2")] + Altinn2 = 2, + + [EnumMember(Value = "Altinn3")] + Altinn3 = 3, + + [EnumMember(Value = "ExternalPlatform")] + ExternalPlatform = 4 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceType.cs new file mode 100644 index 00000000..bf7ab2da --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ReferenceType.cs @@ -0,0 +1,31 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Enum for reference types of resources in the resource registry + /// + public enum ReferenceType : int + { + [EnumMember(Value = "Default")] + Default = 0, + + [EnumMember(Value = "Uri")] + Uri = 1, + + [EnumMember(Value = "DelegationSchemeId")] + DelegationSchemeId = 2, + + [EnumMember(Value = "MaskinportenScope")] + MaskinportenScope = 3, + + [EnumMember(Value = "ServiceCode")] + ServiceCode = 4, + + [EnumMember(Value = "ServiceEditionCode")] + ServiceEditionCode = 5, + + [EnumMember(Value = "ApplicationId")] + ApplicationId = 6 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceAccessListMode.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceAccessListMode.cs new file mode 100644 index 00000000..8a11f72d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceAccessListMode.cs @@ -0,0 +1,12 @@ +namespace Altinn.AccessManagement.Core.Enums.ResourceRegistry +{ + /// + /// Enum representation of the different types of ResourceAccessListModes supported by the resource registry + /// + public enum ResourceAccessListMode + { + Disabled = 0, + + Enabled = 1, + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourcePartyType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourcePartyType.cs new file mode 100644 index 00000000..a954027b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourcePartyType.cs @@ -0,0 +1,27 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Enums.ResourceRegistry +{ + /// + /// Defines the type of party that a resource is targeting + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum ResourcePartyType + { + [EnumMember(Value = "PrivatePerson")] + PrivatePerson = 0, + + [EnumMember(Value = "LegalEntityEnterprise")] + LegalEntityEnterprise = 1, + + [EnumMember(Value = "Company")] + Company = 2, + + [EnumMember(Value = "BankruptcyEstate")] + BankruptcyEstate = 3, + + [EnumMember(Value = "SelfRegisteredUser")] + SelfRegisteredUser = 4 + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceType.cs new file mode 100644 index 00000000..292c8e17 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/ResourceRegistry/ResourceType.cs @@ -0,0 +1,37 @@ +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Enum representation of the different types of resources supported by the resource registry + /// + [Flags] + public enum ResourceType + { + [PgName("default")] + Default = 0, + + [PgName("systemresource")] + Systemresource = 1 << 0, + + [PgName("maskinportenschema")] + MaskinportenSchema = 1 << 1, + + [PgName("altinn2service")] + Altinn2Service = 1 << 2, + + [PgName("altinnapp")] + AltinnApp = 1 << 3, + + [PgName("genericaccessresource")] + GenericAccessResource = 1 << 4, + + [PgName("brokerservice")] + BrokerService = 1 << 5, + + [PgName("correspondenceservice")] + CorrespondenceService = 1 << 6, + + All = ~Default + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestDirection.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestDirection.cs new file mode 100644 index 00000000..0eab777a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestDirection.cs @@ -0,0 +1,28 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for deciding which authRequests to get + /// + public enum RestAuthorizationRequestDirection + { + /// + /// Default none + /// + None = 0, + + /// + /// Incoming requests + /// + Incoming = 1, + + /// + /// Outgoing requests + /// + Outgoing = 2, + + /// + /// Both incoming and outgoing + /// + Both = 3, + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestStatus.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestStatus.cs new file mode 100644 index 00000000..ae20e2a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RestAuthorizationRequestStatus.cs @@ -0,0 +1,38 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Enum for determining the status of an Authorization Request + /// + public enum RestAuthorizationRequestStatus + { + /// + /// Should not be used as a status for an AuthorizationRequest. + /// + None = 0, + + /// + /// Used when a AuthorizationRequest is unopened. + /// + Unopened = 1, + + /// + /// Used when a AuthorizationRequest is opened. + /// + Opened = 2, + + /// + /// Used when a AuthorizationRequest is accepted. + /// + Accepted = 3, + + /// + /// Used when a AuthorizationRequest is rejected. + /// + Rejected = 4, + + /// + /// Used when a AuthorizationRequest is created. + /// + Created = 6 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RevokeStatus.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RevokeStatus.cs new file mode 100644 index 00000000..f6f70708 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RevokeStatus.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for different right revoke status responses + /// + public enum RevokeStatus + { + /// + /// Right was not revoked + /// + NotRevoked = 0, + + /// + /// Right was revoked + /// + Revoked = 1 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightSourceType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightSourceType.cs new file mode 100644 index 00000000..21de2ff7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightSourceType.cs @@ -0,0 +1,28 @@ +namespace Altinn.AccessManagement.Core.Enums +{ + /// + /// Enum for different the source types exist for a right in Altinn Authorization + /// + public enum RightSourceType + { + /// + /// Default value + /// + Unknown = 0, + + /// + /// XACML policy for an Altinn app + /// + AppPolicy = 1, + + /// + /// XACML policy for a resource from the resource registry + /// + ResourceRegistryPolicy = 2, + + /// + /// Altinn delegation policy + /// + DelegationPolicy = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightsQueryType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightsQueryType.cs new file mode 100644 index 00000000..a7b60abd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/RightsQueryType.cs @@ -0,0 +1,22 @@ +namespace Altinn.AccessManagement.Core.Enums; + +/// +/// Enum for different types of rights queries in Altinn Authorization +/// +public enum RightsQueryType +{ + /// + /// Default + /// + NotSet = 0, + + /// + /// Rights query where the recipient is a user + /// + User = 1, + + /// + /// Rights query where the recipient is an Altinn app + /// + AltinnApp = 2 +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/UuidType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/UuidType.cs new file mode 100644 index 00000000..3cf755f2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Enums/UuidType.cs @@ -0,0 +1,54 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Enums +{ + /// + /// Enum defining the different uuids used for defining parts in a delegation + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum UuidType + { + /// + /// Placeholder when type is not specified should only happen when there is no Uuid to match it with + /// + [EnumMember] + NotSpecified, + + /// + /// Defining a person this could also be identified with "Fødselsnummer"/"Dnummer" + /// + [EnumMember(Value = "urn:altinn:person:uuid")] + [PgName("urn:altinn:person:uuid")] + Person, + + /// + /// Identifies a unit could also be identified with a Organization number + /// + [EnumMember(Value = "urn:altinn:organization:uuid")] + [PgName("urn:altinn:organization:uuid")] + Organization, + + /// + /// Identifies a systemuser this is a identifier for machine integration it could also be identified with a unique name + /// + [EnumMember(Value = "urn:altinn:systemuser:uuid")] + [PgName("urn:altinn:systemuser:uuid")] + SystemUser, + + /// + /// Identifies a enterpriseuser this is marked as obsolete and is used for existing integration is also identified with an unique username + /// + [EnumMember(Value = "urn:altinn:enterpriseuser:uuid")] + [PgName("urn:altinn:enterpriseuser:uuid")] + EnterpriseUser, + + /// + /// Identifies a enterpriseuser this is marked as obsolete and is used for existing integration is also identified with an unique username + /// + [EnumMember(Value = "urn:altinn:resource")] + [PgName("urn:altinn:resource")] + Resource + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Errors/ValidationErrors.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Errors/ValidationErrors.cs new file mode 100644 index 00000000..d71f8d40 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Errors/ValidationErrors.cs @@ -0,0 +1,44 @@ +#nullable enable + +using Altinn.Authorization.ProblemDetails; + +namespace Altinn.AccessManagement.Core.Errors; + +/// +/// Validation errors for the Access Management. +/// +public static class ValidationErrors +{ + private static readonly ValidationErrorDescriptorFactory _factory + = ValidationErrorDescriptorFactory.New("AM"); + + /// + /// Gets a validation error descriptor for when an invalid party URN is provided. + /// + public static ValidationErrorDescriptor InvalidPartyUrn { get; } + = _factory.Create(1, "Invalid party URN."); + + /// + /// Gets a validation error descriptor for when an invalid Resource URN is provided. + /// + public static ValidationErrorDescriptor InvalidResource { get; } + = _factory.Create(2, $"Resource must be valid."); + + /// + /// Gets a validation error descriptor for when a resource is missing policy file + /// + public static ValidationErrorDescriptor MissingPolicy { get; } + = _factory.Create(3, $"Resource must have a policy."); + + /// + /// Gets a validation error descriptor for when a Resource not has any delegable rights for the app + /// + public static ValidationErrorDescriptor MissingDelegableRights { get; } + = _factory.Create(4, $"The Resource must have a policy giving the app rights to delegate at least one right."); + + /// + /// Gets a validation error descriptor for when a Resource not has any delegable rights for the app + /// + public static ValidationErrorDescriptor ToManyDelegationsToRevoke { get; } + = _factory.Create(5, $"There must be 10 or less policy files to update."); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Exceptions/TooManyFailedLookupsException.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Exceptions/TooManyFailedLookupsException.cs new file mode 100644 index 00000000..d5da786e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Exceptions/TooManyFailedLookupsException.cs @@ -0,0 +1,24 @@ +namespace Altinn.AccessManagement.Core; + +/// +/// Represents a situation where a user has performed too many failed lookup requests. +/// +[Serializable] +public class TooManyFailedLookupsException : Exception +{ + /// + /// Initializes a new instance of the class. + /// + public TooManyFailedLookupsException() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The message that descibes the error. + public TooManyFailedLookupsException(string message) + : base(message) + { + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Extensions/CoreDependencyInjectionExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Extensions/CoreDependencyInjectionExtensions.cs new file mode 100644 index 00000000..5a533166 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Extensions/CoreDependencyInjectionExtensions.cs @@ -0,0 +1,57 @@ +using Altinn.AccessManagement.Core.Asserters; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Services; +using Altinn.AccessManagement.Core.Services.Implementation; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Resolvers; +using Altinn.Common.AccessTokenClient.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +namespace Altinn.AccessManagement.Core.Extensions; + +/// +/// Extension methods for adding access management core services to the dependency injection container. +/// +public static class CoreDependencyInjectionExtensions +{ + /// + /// Extension methods for adding access management core services to the dependency injection container. + /// + /// web application builder + public static void AddAccessManagementCore(this WebApplicationBuilder builder) + { + builder.Services.AddTransient(); + builder.Services.AddTransient, Asserter>(); + builder.Services.AddTransient(); + + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + builder.Services.AddSingleton(); + builder.Services.AddTransient(); + + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/AuthenticationHelper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/AuthenticationHelper.cs new file mode 100644 index 00000000..b76f3e43 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/AuthenticationHelper.cs @@ -0,0 +1,59 @@ +using Altinn.AccessManagement.Core.Constants; +using Microsoft.AspNetCore.Http; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// helper class for authentication + /// + public static class AuthenticationHelper + { + /// + /// Gets the users id + /// + /// the http context + /// the logged in users id + public static int GetUserId(HttpContext context) + { + var claim = context.User?.Claims.FirstOrDefault(c => c.Type.Equals(AltinnCoreClaimTypes.UserId)); + if (claim != null && int.TryParse(claim.Value, out int userId)) + { + return userId; + } + + return 0; + } + + /// + /// Gets the authenticated user's party id + /// + /// the http context + /// the logged in users party id + public static int GetPartyId(HttpContext context) + { + var claim = context.User?.Claims.FirstOrDefault(c => c.Type.Equals(AltinnCoreClaimTypes.PartyID)); + if (claim != null && int.TryParse(claim.Value, out int partyId)) + { + return partyId; + } + + return 0; + } + + /// + /// Gets the users authentication level + /// + /// the http context + /// the logged in users authentication level + public static int GetUserAuthenticationLevel(HttpContext context) + { + var claim = context.User?.Claims.FirstOrDefault(c => c.Type.Equals(AltinnCoreClaimTypes.AuthenticationLevel)); + if (claim != null && int.TryParse(claim.Value, out int authenticationLevel)) + { + return authenticationLevel; + } + + return 0; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/DelegationHelper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/DelegationHelper.cs new file mode 100644 index 00000000..2e2927ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/DelegationHelper.cs @@ -0,0 +1,997 @@ +using System.Text; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Enums; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// Delegation helper methods + /// + public static class DelegationHelper + { + /// + /// Sort rules for delegation by delegation policy file path, i.e. Org/App/OfferedBy/CoveredBy + /// + /// The list of rules to be sorted + /// The list of rules not able to sort by org/app/offeredBy/CoveredBy + /// A dictionary with key being the filepath for the delegation policy file, and value being the list of rules to be written to the delegation policy + public static Dictionary> SortRulesByDelegationPolicyPath(List rules, out List unsortableRules) + { + Dictionary> result = new Dictionary>(); + unsortableRules = new List(); + + foreach (Rule rule in rules) + { + if (!TryGetDelegationPolicyPathFromRule(rule, out string path)) + { + unsortableRules.Add(rule); + continue; + } + + if (result.ContainsKey(path)) + { + result[path].Add(rule); + } + else + { + result.Add(path, new List { rule }); + } + } + + return result; + } + + /// + /// Tries to get the PartyId attribute value from a list of AttributeMatch models + /// + /// The true if party id is found as the single attribute in the collection + public static bool TryGetPartyIdFromAttributeMatch(List match, out int partyid) + { + partyid = 0; + AttributeMatch partyIdAttribute = match?.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute); + if (partyIdAttribute != null) + { + return int.TryParse(partyIdAttribute.Value, out partyid) && partyid != 0; + } + + return false; + } + + /// + /// Tries to get the Uuid attribute value from a list of AttributeMatch models and specifies which type it finds by setting based on the id in the attribute match + /// + /// The true if party id is found as the single attribute in the collection + public static bool TryGetUuidFromAttributeMatch(List match, out Guid uuid, out UuidType type) + { + uuid = Guid.Empty; + type = UuidType.NotSpecified; + + if (match == null) + { + return false; + } + + AttributeMatch currentAttributeMatch = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid); + if (currentAttributeMatch != null) + { + type = UuidType.Person; + return Guid.TryParse(currentAttributeMatch.Value, out uuid) && uuid != Guid.Empty; + } + + currentAttributeMatch = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid); + if (currentAttributeMatch != null) + { + type = UuidType.Organization; + return Guid.TryParse(currentAttributeMatch.Value, out uuid) && uuid != Guid.Empty; + } + + currentAttributeMatch = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid); + if (currentAttributeMatch != null) + { + type = UuidType.SystemUser; + return Guid.TryParse(currentAttributeMatch.Value, out uuid) && uuid != Guid.Empty; + } + + currentAttributeMatch = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid); + if (currentAttributeMatch != null) + { + type = UuidType.EnterpriseUser; + return Guid.TryParse(currentAttributeMatch.Value, out uuid) && uuid != Guid.Empty; + } + + return false; + } + + /// + /// Trys to get the UserId attribute value from a list of AttributeMatch models + /// + /// The true if user id is found as the single attribute in the collection + public static bool TryGetUserIdFromAttributeMatch(List match, out int userid) + { + userid = 0; + AttributeMatch userIdAttribute = match?.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute); + if (userIdAttribute != null) + { + return int.TryParse(userIdAttribute.Value, out userid) && userid != 0; + } + + return false; + } + + /// + /// Trys to get the organization number attribute value from a list of AttributeMatch models + /// + /// The true if organization number is found as the single attribute in the collection + public static bool TryGetOrganizationNumberFromAttributeMatch(List match, out string orgNo) + { + orgNo = string.Empty; + if (match != null && match.Count == 1 && match[0].Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute) + { + orgNo = match[0].Value; + return true; + } + + return false; + } + + /// + /// Trys to get the social security number attribute value from a list of AttributeMatch models + /// + /// The true if social security number is found as the single attribute in the collection + public static bool TryGetSocialSecurityNumberAttributeMatch(List match, out string ssn) + { + ssn = string.Empty; + if (match != null && match.Count == 1 && match[0].Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId) + { + ssn = match[0].Value; + return true; + } + + return false; + } + + /// + /// Trys to get both social security number and last name attribute value from a list of AttributeMatch models + /// + /// The true if both social security number and last name is found as the only attributes in the collection + public static bool TryGetSocialSecurityNumberAndLastNameAttributeMatch(List match, out string ssn, out string lastName) + { + ssn = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId)?.Value; + lastName = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonLastName)?.Value; + + if (match.Count == 2 && !string.IsNullOrWhiteSpace(ssn) && !string.IsNullOrWhiteSpace(lastName)) + { + return true; + } + + return false; + } + + /// + /// Trys to get both username and last name attribute value from a list of AttributeMatch models + /// + /// The true if both username and last name is found as the only attributes in the collection + public static bool TryGetUsernameAndLastNameAttributeMatch(List match, out string username, out string lastName) + { + username = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUserName)?.Value; + lastName = match.Find(m => m.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PersonLastName)?.Value; + + if (match.Count == 2 && !string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(lastName)) + { + return true; + } + + return false; + } + + /// + /// Trys to get enterprise username attribute value from a list of AttributeMatch models + /// + /// The true if both enterprise username is found as the only attributes in the collection + public static bool TryGetEnterpriseUserNameAttributeMatch(List match, out string enterpriseUserName) + { + enterpriseUserName = string.Empty; + if (match != null && match.Count == 1 && match[0].Id == AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserName) + { + enterpriseUserName = match[0].Value; + return true; + } + + return false; + } + + /// + /// Trys to get an single specific attribute value from a list of AttributeMatch models, if it's the only attribute in the list + /// + /// The true if person uuid is found as the only attributes in the collection + public static bool TryGetSingleAttributeMatchValue(List match, string matchAttributeIdentifier, out string value) + { + value = string.Empty; + if (match != null && match.Count == 1 && match[0].Id == matchAttributeIdentifier) + { + value = match[0].Value; + return true; + } + + return false; + } + + /// + /// Check if i given AttributeMatch list is in a list of defaultRights so it is valid for delegation to SystemUsers + /// + /// List of default rights to check if resource is included + /// The rights to delegate to check for existence in list of defaultRights + /// true if all the rights is valid for in the given defaultRights list + public static bool CheckResourceIsInListOfDefaultRights(List defaultRights, List resource) + { + return defaultRights.Exists(defaultRight => CheckAllPartsInDefaultRightsIsInActualDelegatedResource(defaultRight.Resource, resource)); + } + + /// + /// Compares a list of Resource details from allowed default rights with the list of Resource details in the actual delegation so all of the defined resource details + /// in the allowed resource must be present in the actual delegation but the actual delegation can have more details narrowing the actual delegation more granulated than + /// the allowed resource but not the other way round + /// + /// List describing the allowed resource + /// List describing the actual delegation + /// True if the delegation is allowed false if not. + public static bool CheckAllPartsInDefaultRightsIsInActualDelegatedResource(List allowedResource, List actualResource) + { + return allowedResource.TrueForAll(attributeMatch => actualResource.Exists(r => r.Id == attributeMatch.Id && r.Value == attributeMatch.Value)); + } + + /// + /// Gets a int representation of the CoveredByUserId and CoverdByPartyId from an AttributeMatch list. + /// This works under the asumptions that any valid search for Ã¥ valid policy contains a CoveredBy and this must be in the form + /// of a PartyId or a UserId. So any valid search containing a PartyId should not contain a USerId and vice versa. + /// If the search does not contain any of those this should be considered as an invalid search. + /// + /// the list to fetch coveredBy from + /// The value for coveredByUserId or null if not present + /// The value for coveredByPartyId or null if not present + /// The uuid of the covered by found in the AttributeMatch list + /// The uuid type of the covered by found in the AttributeMatch list + /// The CoveredByUserId or CoveredByPartyId in the input AttributeMatch list as a string primarily used to create a policy path for fetching a delegated policy file. + public static string GetCoveredByFromMatch(List match, out int? coveredByUserId, out int? coveredByPartyId, out Guid? coveredByUuid, out UuidType coveredByUuidType) + { + bool validUser = TryGetUserIdFromAttributeMatch(match, out int coveredByUserIdTemp); + bool validParty = TryGetPartyIdFromAttributeMatch(match, out int coveredByPartyIdTemp); + bool validUuid = TryGetUuidFromAttributeMatch(match, out Guid coveredByUuidIdTemp, out coveredByUuidType); + + coveredByPartyId = validParty ? coveredByPartyIdTemp : null; + coveredByUserId = validUser ? coveredByUserIdTemp : null; + coveredByUuid = validUuid ? coveredByUuidIdTemp : null; + + if (validUser) + { + return coveredByUserIdTemp.ToString(); + } + else if (validParty) + { + return coveredByPartyIdTemp.ToString(); + } + else if (validUuid) + { + return coveredByUuidIdTemp.ToString(); + } + else + { + return null; + } + } + + /// + /// Gets the resource attribute values as out params from a Resource specified as a List of AttributeMatches + /// + /// The resource to fetch org and app from + /// the resource match type + /// the resource id. Either a resource registry id or org/app + /// the org part of the resource + /// the app part of the resource + /// altinn 2 service code + /// altinn 2 service edition code + /// A bool indicating whether params where found + public static bool TryGetResourceFromAttributeMatch(List input, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string serviceCode, out string serviceEditionCode) + { + resourceMatchType = ResourceAttributeMatchType.None; + resourceId = null; + org = null; + app = null; + serviceCode = null; + serviceEditionCode = null; + + AttributeMatch resourceRegistryMatch = input.Find(am => am.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute); + AttributeMatch orgMatch = input.Find(am => am.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute); + AttributeMatch appMatch = input.Find(am => am.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute); + AttributeMatch serviceCodeMatch = input.Find(am => am.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.ServiceCodeAttribute); + AttributeMatch serviceEditionMatch = input.Find(am => am.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.ServiceEditionCodeAttribute); + + if (resourceRegistryMatch != null && orgMatch == null && appMatch == null) + { + resourceMatchType = ResourceAttributeMatchType.ResourceRegistry; + resourceId = resourceRegistryMatch.Value; + return true; + } + + if (orgMatch != null && appMatch != null && resourceRegistryMatch == null) + { + resourceMatchType = ResourceAttributeMatchType.AltinnAppId; + org = orgMatch.Value; + app = appMatch.Value; + resourceId = $"{org}/{app}"; + return true; + } + + if (serviceCodeMatch != null && serviceEditionMatch != null && resourceRegistryMatch == null && orgMatch == null && appMatch == null) + { + resourceMatchType = ResourceAttributeMatchType.Altinn2Service; + serviceCode = serviceCodeMatch.Value; + serviceEditionCode = serviceEditionMatch.Value; + return true; + } + + return false; + } + + /// + /// Gets ResourceType, ResourceRegistryId, Org, App, OfferedBy and CoveredBy as out params from a single Rule + /// + /// A bool indicating whether sufficent params where found + public static bool TryGetDelegationParamsFromRule(Rule rule, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out int offeredByPartyId, out Guid? fromUuid, out UuidType fromUuidType, out Guid? toUuid, out UuidType toUuidType, out int? coveredByPartyId, out int? coveredByUserId, out int? delegatedByUserId, out int? delegatedByPartyId, out DateTime delegatedDateTime) + { + resourceMatchType = ResourceAttributeMatchType.None; + resourceId = null; + org = null; + app = null; + offeredByPartyId = 0; + fromUuid = null; + fromUuidType = UuidType.NotSpecified; + coveredByPartyId = null; + coveredByUserId = null; + toUuid = null; + toUuidType = UuidType.NotSpecified; + + delegatedByUserId = null; + delegatedByPartyId = null; + delegatedDateTime = DateTime.UtcNow; + + try + { + TryGetResourceFromAttributeMatch(rule.Resource, out resourceMatchType, out resourceId, out org, out app, out string _, out string _); + offeredByPartyId = rule.OfferedByPartyId; + fromUuid = rule.OfferedByPartyUuid; + fromUuidType = rule.OfferedByPartyType; + coveredByPartyId = TryGetPartyIdFromAttributeMatch(rule.CoveredBy, out int coveredByParty) ? coveredByParty : null; + coveredByUserId = TryGetUserIdFromAttributeMatch(rule.CoveredBy, out int coveredByUser) ? coveredByUser : null; + bool validUuid = TryGetUuidFromAttributeMatch(rule.CoveredBy, out Guid toUuidTemp, out toUuidType); + if (validUuid) + { + toUuid = toUuidTemp; + } + + delegatedByUserId = rule.DelegatedByUserId; + delegatedByPartyId = rule.DelegatedByPartyId; + delegatedDateTime = rule.DelegatedDateTime ?? DateTime.UtcNow; + + if (resourceMatchType != ResourceAttributeMatchType.None + && offeredByPartyId != 0 + && (coveredByPartyId.HasValue || coveredByUserId.HasValue || toUuid.HasValue) + && (delegatedByUserId.HasValue || delegatedByPartyId.HasValue)) + { + return true; + } + } + catch (Exception) + { + // Any exceptions here are caused by invalid input which should be handled and logged by the calling entity + } + + return false; + } + + /// + /// Gets the delegation policy path for a single Rule + /// + /// A bool indicating whether necessary params to build the path where found + public static bool TryGetDelegationPolicyPathFromRule(Rule rule, out string delegationPolicyPath) + { + delegationPolicyPath = null; + if (TryGetDelegationParamsFromRule(rule, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out int offeredBy, out Guid? fromUuid, out UuidType fromUuidType, out Guid? toUuid, out UuidType toUuidType, out int? coveredByPartyId, out int? coveredByUserId, out _, out _, out _)) + { + try + { + delegationPolicyPath = PolicyHelper.GetDelegationPolicyPath(resourceMatchType, resourceId, org, app, offeredBy.ToString(), coveredByUserId, coveredByPartyId, toUuid, toUuidType); + return true; + } + catch (Exception) + { + return false; + } + } + + return false; + } + + /// + /// Gets the delegation policy path for a single Rule + /// + /// A bool indicating whether necessary params to build the path where found + public static bool TryGetDelegationPolicyPathFromInstanceRule(InstanceRight rule, out string instanceDelegationPolicyPath) + { + instanceDelegationPolicyPath = null; + StringBuilder sb = new StringBuilder(); + + sb.Append("resourceregistry"); + sb.Append('/'); + + sb.Append(rule.ResourceId); + sb.Append('/'); + + sb.Append("instances"); + sb.Append('/'); + + try + { + sb.Append(rule.InstanceId.AsFileName()); + sb.Append('/'); + } + catch (Exception) + { + return false; + } + + sb.Append(rule.ToType); + sb.Append('-'); + sb.Append(rule.ToUuid); + sb.Append('/'); + + sb.Append(rule.InstanceDelegationSource); + sb.Append('/'); + + sb.Append(rule.InstanceDelegationMode); + sb.Append('/'); + + sb.Append("delegationpolicy.xml"); + instanceDelegationPolicyPath = sb.ToString(); + + return true; + } + + /// + /// Returns the count of unique Policies in a list of Rules + /// + /// List of rules to check how many individual policies exist + /// count of policies + public static int GetPolicyCount(List rules) + { + List policyPaths = new List(); + foreach (Rule rule in rules) + { + bool pathOk = TryGetDelegationPolicyPathFromRule(rule, out string delegationPolicyPath); + if (pathOk && !policyPaths.Contains(delegationPolicyPath)) + { + policyPaths.Add(delegationPolicyPath); + } + } + + return policyPaths.Count; + } + + /// + /// Returns the count of unique ruleids in a list dele + /// + /// List of rules and policies to check how many individual ruleids exist + /// count of rules + public static int GetRulesCountToDeleteFromRequestToDelete(List rulesToDelete) + { + int result = 0; + foreach (RequestToDelete ruleToDelete in rulesToDelete) + { + result += ruleToDelete.RuleIds.Count; + } + + return result; + } + + /// + /// Checks whether the provided XacmlPolicy contains a rule having an identical Resource signature and contains the Action from the rule, + /// to be used for checking for duplicate rules in delegation, or that the rule exists in the Apps Xacml policy. + /// + /// A bool + public static bool PolicyContainsMatchingInstanceRule(XacmlPolicy policy, InstanceRule rule) + { + string ruleResourceKey = GetAttributeMatchKey(rule.Resource.ToList()); + + foreach (XacmlRule policyRule in policy.Rules) + { + if (!policyRule.Effect.Equals(XacmlEffectType.Permit) || policyRule.Target == null) + { + continue; + } + + bool matchingActionFound = MatchingActionFound(policyRule.Target.AnyOf, rule, out List> policyResourceMatches); + + if (policyResourceMatches.Exists(resourceMatch => GetAttributeMatchKey(resourceMatch) == ruleResourceKey) && matchingActionFound) + { + rule.RuleId = policyRule.RuleId; + return true; + } + } + + return false; + } + + /// + /// Returns Xacml rule in the provided XacmlPolicy that contains a rule having an identical Resource signature and contains the Action from the InstanceRule null if no match, + /// to be used for finding rules to revoke. + /// + /// A bool + public static XacmlRule GetXamlRuleContainsMatchingInstanceRule(XacmlPolicy policy, InstanceRule rule) + { + string ruleResourceKey = GetAttributeMatchKey(rule.Resource.ToList()); + + foreach (XacmlRule policyRule in policy.Rules) + { + if (!policyRule.Effect.Equals(XacmlEffectType.Permit) || policyRule.Target == null) + { + continue; + } + + bool matchingActionFound = MatchingActionFound(policyRule.Target.AnyOf, rule, out List> policyResourceMatches); + + if (policyResourceMatches.Exists(resourceMatch => GetAttributeMatchKey(resourceMatch) == ruleResourceKey) && matchingActionFound) + { + rule.RuleId = policyRule.RuleId; + return policyRule; + } + } + + return null; + } + + private static bool MatchingActionFound(ICollection input, InstanceRule rule, out List> policyResourceMatches) + { + policyResourceMatches = []; + bool matchingActionFound = false; + + foreach (XacmlAnyOf anyOf in input) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + matchingActionFound = GetResourceMatch(allOf.Matches, rule, out List resourceMatch); + + if (resourceMatch.Count > 0) + { + policyResourceMatches.Add(resourceMatch); + } + } + } + + return matchingActionFound; + } + + private static bool GetResourceMatch(ICollection input, InstanceRule rule, out List resourceMatch) + { + resourceMatch = []; + bool matchingActionFound = false; + foreach (XacmlMatch xacmlMatch in input) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + resourceMatch.Add(new AttributeMatch { Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, Value = xacmlMatch.AttributeValue.Value }); + } + else if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action) && + xacmlMatch.AttributeDesignator.AttributeId.OriginalString == rule.Action.PrefixSpan.ToString() && + xacmlMatch.AttributeValue.Value == rule.Action.ValueSpan.ToString()) + { + matchingActionFound = true; + } + } + + return matchingActionFound; + } + + /// + /// Checks whether the provided XacmlPolicy contains a rule having an identical Resource signature and contains the Action from the rule, + /// to be used for checking for duplicate rules in delegation, or that the rule exists in the Apps Xacml policy. + /// + /// A bool + public static bool PolicyContainsMatchingRule(XacmlPolicy policy, Rule rule) + { + string ruleResourceKey = GetAttributeMatchKey(rule.Resource); + + foreach (XacmlRule policyRule in policy.Rules) + { + if (!policyRule.Effect.Equals(XacmlEffectType.Permit) || policyRule.Target == null) + { + continue; + } + + List> policyResourceMatches = new List>(); + bool matchingActionFound = false; + foreach (XacmlAnyOf anyOf in policyRule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + List resourceMatch = new List(); + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + resourceMatch.Add(new AttributeMatch { Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, Value = xacmlMatch.AttributeValue.Value }); + } + else if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action) && + xacmlMatch.AttributeDesignator.AttributeId.OriginalString == rule.Action.Id && + xacmlMatch.AttributeValue.Value == rule.Action.Value) + { + matchingActionFound = true; + } + } + + if (resourceMatch.Any()) + { + policyResourceMatches.Add(resourceMatch); + } + } + } + + if (policyResourceMatches.Any(resourceMatch => GetAttributeMatchKey(resourceMatch) == ruleResourceKey) && matchingActionFound) + { + rule.RuleId = policyRule.RuleId; + return true; + } + } + + return false; + } + + /// + /// Gets a string key representing the a list of attributematches + /// + /// A key string + public static string GetAttributeMatchKey(List attributeMatches) + { + return string.Concat(attributeMatches.OrderBy(r => r.Id).Select(r => r.Id + r.Value)); + } + + /// + /// Gets a string key representing the a list of attributematches + /// + /// A key string + public static string GetAttributeMatchKey(List attributeMatches) + { + return string.Concat(attributeMatches.OrderBy(r => r.Value.KeySpan.ToString()).Select(r => r.Value.PrefixSpan.ToString() + r.Value.ValueSpan.ToString())); + } + + /// + /// Extract UuidType and Uuid from a AttributeMatch list + /// + /// The lsit to fetch data from + /// The id of the party in the + /// The resulting type + /// true if a valid type and id was extracted else false + public static bool TryGetPerformerFromAttributeMatches(IEnumerable performer, out string id, out UuidType type) + { + string org = null, app = null, person = null, organization = null, enterpriseUser = null, systemUser = null; + id = null; + type = UuidType.NotSpecified; + int counter = 0; + + foreach (AttributeMatch match in performer) + { + counter++; + switch (match.Id) + { + case AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute: + org = match.Value; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute: + app = match.Value; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid: + organization = match.Value; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid: + person = match.Value; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid: + enterpriseUser = match.Value; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid: + systemUser = match.Value; + break; + } + } + + if (org != null && app != null && person == null && organization == null && enterpriseUser == null && systemUser == null && counter == 2) + { + id = $"app_{org}_{app}"; + type = UuidType.Resource; + return true; + } + + if (org == null && app == null && person != null && organization == null && enterpriseUser == null && systemUser == null && counter == 1) + { + id = person; + type = UuidType.Person; + return true; + } + + if (org == null && app == null && person == null && organization != null && enterpriseUser == null && systemUser == null && counter == 1) + { + id = organization; + type = UuidType.Organization; + return true; + } + + if (org == null && app == null && person == null && organization == null && enterpriseUser != null && systemUser == null && counter == 1) + { + id = enterpriseUser; + type = UuidType.EnterpriseUser; + return true; + } + + if (org == null && app == null && person == null && organization == null && enterpriseUser == null && systemUser != null && counter == 1) + { + id = systemUser; + type = UuidType.SystemUser; + return true; + } + + return false; + } + + /// + /// Sets the RuleType on each rule in the given list + /// + public static void SetRuleType(List rulesList, int offeredByPartyId, List keyRolePartyIds, List coveredBy, int parentPartyId = 0) + { + foreach (Rule rule in rulesList) + { + if (TryGetDelegationParamsFromRule(rule, out _, out _, out _, out _, out _, out Guid? fromUuid, out UuidType fromUuidType, out Guid? toUuid, out UuidType toUuidType, out int? coveredByPartyId, out int? coveredByUserId, out _, out _, out _) + && rule.Type == RuleType.None) + { + SetTypeForSingleRule(keyRolePartyIds, offeredByPartyId, coveredBy, parentPartyId, rule, coveredByPartyId, coveredByUserId); + } + } + } + + /// + /// Extracts the (assumed) party ID from the given 'who' string. + /// + /// + /// Who, valid values are an organization number, or a party ID (the letter R followed by + /// the party ID as used in SBL). + /// + /// Party ID extracted from 'who', or NULL if 'who' contains no party id. + public static int? TryParsePartyId(string who) + { + int partyId; + if (!int.TryParse(who, out partyId)) + { + return 0; + } + + return partyId; + } + + /// + /// Gets the reference value for a given resourcereference type + /// + /// resource + /// reference source + /// reference type + public static string GetReferenceValue(ServiceResource resource, ReferenceSource referenceSource, ReferenceType referenceType) + { + ResourceReference reference = resource.ResourceReferences.Find(rf => rf.ReferenceSource == referenceSource && rf.ReferenceType == referenceType); + return reference.Reference; + } + + /// + /// Builds a RequestToDelete request model for revoking all delegated rules for a resource registry service + /// + public static List GetRequestToDeleteResourceRegistryService(int authenticatedUserId, string resourceRegistryId, int fromPartyId, int toPartyId) + { + return new List + { + new RequestToDelete + { + DeletedByUserId = authenticatedUserId, + PolicyMatch = new PolicyMatch + { + OfferedByPartyId = fromPartyId, + CoveredBy = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = toPartyId.ToString() }.SingleToList(), + Resource = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute, Value = resourceRegistryId }.SingleToList() + } + } + }; + } + + /// + /// Builds a RequestToDelete request model for revoking all delegated rules for the resource if delegated between the from and to parties + /// + public static List GetRequestToDeleteResource(int authenticatedUserId, IEnumerable resource, int fromPartyId, AttributeMatch to) + { + return new List + { + new RequestToDelete + { + DeletedByUserId = authenticatedUserId, + PolicyMatch = new PolicyMatch + { + OfferedByPartyId = fromPartyId, + CoveredBy = to.SingleToList(), + Resource = resource.ToList() + } + } + }; + } + + /// + /// Gets the list of Rules as a list of RightDelegationResult + /// + /// The rules output from a delegation to convert + /// List of RightDelegationResult + public static List GetRightDelegationResultsFromRules(List rules) + { + return rules.Select(rule => new RightDelegationResult + { + Resource = rule.Resource, + Action = rule.Action, + Status = rule.CreatedSuccessfully ? DelegationStatus.Delegated : DelegationStatus.NotDelegated + }).ToList(); + } + + /// + /// Gets the list of Rules as a list of RightDelegationResult + /// + /// The rules output from a delegation to convert + /// List of RightDelegationResult + public static IEnumerable GetRightDelegationResultsFromInstanceRules(InstanceRight rules) + { + return rules.InstanceRules.Select(rule => new InstanceRightDelegationResult + { + Resource = rule.Resource, + Action = rule.Action, + Status = rule.CreatedSuccessfully ? DelegationStatus.Delegated : DelegationStatus.NotDelegated + }); + } + + /// + /// Gets the list of Rules as a list of RightDelegationResult + /// + /// The rules output from a delegation to convert + /// List of RightDelegationResult + public static IEnumerable GetRightRevokeResultsFromInstanceRules(InstanceRight rules) + { + return rules.InstanceRules.Select(rule => new InstanceRightRevokeResult + { + Resource = rule.Resource, + Action = rule.Action, + Status = rule.CreatedSuccessfully ? RevokeStatus.Revoked : RevokeStatus.NotRevoked + }); + } + + /// + /// Gets the list of Rights as a list of RightDelegationResult + /// + /// The rights to convert + /// List of RightDelegationResult + public static List GetRightDelegationResultsFromFailedRights(List rights) + { + return rights.Select(right => new RightDelegationResult + { + Resource = right.Resource, + Action = right.Action, + Status = DelegationStatus.NotDelegated + }).ToList(); + } + + /// + /// Gets the list of Rights as a list of RightDelegationResult + /// + /// The rights to convert + /// List of RightDelegationResult + public static IEnumerable GetRightDelegationResultsFromFailedInternalRights(List rights) + { + return rights.Select(right => new InstanceRightDelegationResult + { + Resource = right.Resource, + Action = right.Action, + Status = DelegationStatus.NotDelegated + }); + } + + /// + /// Evaluates the party type in order to return the correct uuid type and value for a party + /// + /// The party to get uuid info from + /// UuidType and Uuid + public static (UuidType DelegationType, Guid Uuid) GetUuidTypeAndValueFromParty(Party party) + { + if (party?.Organization != null) + { + return (UuidType.Organization, party.PartyUuid.Value); + } + else if (party?.Person != null) + { + return (UuidType.Person, party.PartyUuid.Value); + } + + return (UuidType.NotSpecified, Guid.Empty); + } + + /// + /// Gets the list of Rights as a list of RightDelegationResult + /// + /// The rights to convert + /// List of RightDelegationResult + public static IEnumerable GetRightRevokeResultsFromFailedInternalRights(List rights) + { + return rights.Select(right => new InstanceRightRevokeResult + { + Resource = right.Resource, + Action = right.Action, + Status = RevokeStatus.NotRevoked + }); + } + + /// + /// Checks if AccessList feature is enabled and applicable for the given right, resource, and fromParty. The AccessListMode feature is currently enabled only for orgs. + /// + /// The right to be delegated + /// The resource we are making delegations for + /// The party we are making delegations on behalf of + /// True if Access List authorization mode is enabled and applicable + public static bool IsAccessListModeEnabledAndApplicable(Right right, ServiceResource resource, Party fromParty) + { + if (right.CanDelegate.HasValue && right.CanDelegate.Value + && resource.AccessListMode == Enums.ResourceRegistry.ResourceAccessListMode.Enabled + && fromParty.PartyTypeName == PartyType.Organisation) + { + return true; + } + + return false; + } + + private static void SetTypeForSingleRule(List keyRolePartyIds, int offeredByPartyId, List coveredBy, int parentPartyId, Rule rule, int? coveredByPartyId, int? coveredByUserId) + { + bool isUserId = TryGetUserIdFromAttributeMatch(coveredBy, out int coveredByUserIdFromRequest); + bool isPartyId = TryGetPartyIdFromAttributeMatch(coveredBy, out int coveredByPartyIdFromRequest); + + if (((isUserId && coveredByUserIdFromRequest == coveredByUserId) || (isPartyId && coveredByPartyIdFromRequest == coveredByPartyId)) + && rule.OfferedByPartyId == offeredByPartyId) + { + rule.Type = RuleType.DirectlyDelegated; + } + else if (isUserId && keyRolePartyIds.Any(id => id == coveredByPartyId) && rule.OfferedByPartyId == offeredByPartyId) + { + rule.Type = RuleType.InheritedViaKeyRole; + } + else if (((isUserId && coveredByUserIdFromRequest == coveredByUserId) || (isPartyId && coveredByPartyIdFromRequest == coveredByPartyId)) + && parentPartyId != 0 && rule.OfferedByPartyId == parentPartyId) + { + rule.Type = RuleType.InheritedAsSubunit; + } + else if (isUserId && keyRolePartyIds.Any(id => id == coveredByPartyId) && parentPartyId != 0 && rule.OfferedByPartyId == parentPartyId) + { + rule.Type = RuleType.InheritedAsSubunitViaKeyrole; + } + else + { + rule.Type = RuleType.None; + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/EnumExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/EnumExtensions.cs new file mode 100644 index 00000000..d7370515 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/EnumExtensions.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Helpers.Extensions +{ + /// + /// Enum Extensions + /// + public static class EnumExtensions + { + /// + /// Fetch the content of the Value for a defined EnumMemberAttribute or just returns the name if no such declaration exists + /// + /// The enum to fetch data from + /// The content of the declared EnumMemberAttribute.Value for the defined enum or just ToString if no EnumMemberAttribute is defined + public static string EnumMemberAttributeValueOrName(this Enum value) + { + var enumType = value.GetType(); + var enumMemeberAttribute = enumType + .GetTypeInfo() + .DeclaredMembers + .Single(x => x.Name == value.ToString()) + .GetCustomAttribute(false); + + if (enumMemeberAttribute == null || enumMemeberAttribute.Value == null) + { + return value.ToString(); + } + + return enumMemeberAttribute.Value; + } + + /// + /// Tries to parse a string as a given Enum on the EnumMemberAttribute rater than the Name of the value in the enum returns false if no matching vale was found true if parsed ok + /// + /// The string to use for value in the enum + /// Out parameter containing The parsed enum or default value + /// The Enum type to Parse + /// Value indicating the parsing went ok or not + public static bool EnumValue(string value, out T enumValue) + { + string[] names = Enum.GetNames(typeof(T)); + string name = Array.Find(names, name => EnumMemberAttributeValueOrName((Enum)Enum.Parse(typeof(T), name)).Equals(value)); + + if (name != null) + { + enumValue = (T)Enum.Parse(typeof(T), name); + return true; + } + + enumValue = default; + return false; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/GenericExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/GenericExtensions.cs new file mode 100644 index 00000000..8bd67717 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/GenericExtensions.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Helpers.Extensions +{ + /// + /// Generic Extensions + /// + public static class GenericExtensions + { + /// + /// Creates a new List of objects type, containing just the single object + /// + /// The object to create a list of + /// A list containing the object + public static List SingleToList(this T @object) + { + return new List { @object }; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/HttpClientExtension.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/HttpClientExtension.cs new file mode 100644 index 00000000..32f10ed0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/HttpClientExtension.cs @@ -0,0 +1,97 @@ +#nullable enable + +namespace Altinn.AccessManagement.Core.Extensions; + +/// +/// This extension is created to make it easy to add a bearer token to a HttpRequests. +/// +public static class HttpClientExtension +{ + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The http content + /// The platformAccess tokens + /// The + /// A HttpResponseMessage + public static Task PostAsync(this HttpClient httpClient, string authorizationToken, string requestUri, HttpContent content, string? platformAccessToken = null, CancellationToken cancellationToken = default) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + request.Content = content; + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, cancellationToken); + } + + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The http content + /// The platformAccess tokens + /// The + /// A HttpResponseMessage + public static Task PutAsync(this HttpClient httpClient, string authorizationToken, string requestUri, HttpContent content, string? platformAccessToken = null, CancellationToken cancellationToken = default) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + request.Content = content; + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, cancellationToken); + } + + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The platformAccess tokens + /// The + /// A HttpResponseMessage + public static Task GetAsync(this HttpClient httpClient, string authorizationToken, string requestUri, string? platformAccessToken = null, CancellationToken cancellationToken = default) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken); + } + + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The platformAccess tokens + /// The + /// A HttpResponseMessage + public static Task DeleteAsync(this HttpClient httpClient, string authorizationToken, string requestUri, string? platformAccessToken = null, CancellationToken cancellationToken = default) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, cancellationToken); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/StringExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/StringExtensions.cs new file mode 100644 index 00000000..11b8fda8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/Extensions/StringExtensions.cs @@ -0,0 +1,109 @@ +using System.Globalization; +using System.Text; + +namespace Altinn.AccessManagement.Core.Helpers.Extensions +{ + /// + /// Extensions to facilitate sanitization of string values + /// + public static class StringExtensions + { + /// + /// Sanitize the input as a file name. + /// + /// The input variable to be sanitized + /// Throw exception instead of replacing invalid characters with '-' + /// + public static string AsFileName(this string input, bool throwExceptionOnInvalidCharacters = true) + { + if (string.IsNullOrWhiteSpace(input)) + { + return input; + } + + char[] illegalFileNameCharacters = Path.GetInvalidFileNameChars(); + if (throwExceptionOnInvalidCharacters) + { + if (illegalFileNameCharacters.Any(ic => input.Any(i => ic == i))) + { + throw new ArgumentOutOfRangeException(nameof(input)); + } + + return input; + } + + return illegalFileNameCharacters.Aggregate(input, (current, c) => current.Replace(c, '-')); + } + + /// + /// Compare to strings doing a loose compare ignoring case and diacritics + /// + /// First text + /// Second text + /// true if the texts are similar. + public static bool IsSimilarTo(this string text1, string text2) + { + const int CompareLength = 4; + + text1 ??= string.Empty; + text2 ??= string.Empty; + + text1 = text1.Trim().Length > CompareLength ? text1.Remove(CompareLength).Trim() : text1.Trim(); + text2 = text2.Trim().Length > CompareLength ? text2.Remove(CompareLength).Trim() : text2.Trim(); + + text1 = text1.RemoveDiacritics(); + text2 = text2.RemoveDiacritics(); + + return text1.Equals(text2, StringComparison.InvariantCultureIgnoreCase); + } + + /// + /// Remove diacritics from a string while normalizing it. + /// + /// The text to normalize. + /// The normalized text. + public static string RemoveDiacritics(this string text) + { + string normalizedText; + + // Å is not a special character in Norwegian hence handling this character differently + if (text.ToUpper().Contains('Å')) + { + StringBuilder firstPassBuilder = new(); + foreach (char ch in text) + { + if (ch == 'Å' || ch == 'å') + { + // NormalizationForm C doesn't convert Å to A + firstPassBuilder.Append(ch.ToString().Normalize(NormalizationForm.FormC)); + } + else + { + firstPassBuilder.Append(ch.ToString().Normalize(NormalizationForm.FormD)); + } + } + + normalizedText = firstPassBuilder.ToString(); + } + else + { + normalizedText = text.Normalize(NormalizationForm.FormD); + } + + StringBuilder secondPassBuilder = new(); + foreach (char ch in normalizedText) + { + // Unicode information of the characters, e.g. Uppercase, Lowercase, NonSpacingMark, etc. + UnicodeCategory unicode = CharUnicodeInfo.GetUnicodeCategory(ch); + + if (unicode != UnicodeCategory.NonSpacingMark) + { + // StringBuilder is appended with the characters that are not diacritics + secondPassBuilder.Append(ch); + } + } + + return secondPassBuilder.ToString().Normalize(NormalizationForm.FormC); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/JwtTokenUtil.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/JwtTokenUtil.cs new file mode 100644 index 00000000..6a87620e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/JwtTokenUtil.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Http; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// This class contains utilities for handling JWT tokens + /// + public static class JwtTokenUtil + { + /// + /// Retrieves JWT token value from HTTP context. + /// + /// The HTTP context that contains the token + /// The name of the cookie where the token might be stored + /// The JWT token string. + public static string GetTokenFromContext(HttpContext context, string cookieName) + { + // Get the cookie from request + string token = context.Request.Cookies[cookieName]; + + // If no cookie present + if (string.IsNullOrEmpty(token)) + { + string authorization = context.Request.Headers["Authorization"]; + + // If no authorization header found, nothing to process further + if (string.IsNullOrEmpty(authorization)) + { + return string.Empty; + } + + if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) + { + token = authorization.Substring("Bearer ".Length).Trim(); + } + } + + return token; + } + + /// + /// Updates http client by including authorization token in request header + /// + /// The HTTP client + /// The authorization token + public static void AddTokenToRequestHeader(HttpClient client, string token) + { + if (client.DefaultRequestHeaders.Contains("Authorization")) + { + client.DefaultRequestHeaders.Remove("Authorization"); + } + + client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/PolicyHelper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/PolicyHelper.cs new file mode 100644 index 00000000..9879f243 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/PolicyHelper.cs @@ -0,0 +1,1065 @@ +using System.Collections.ObjectModel; +using System.Text; +using System.Xml; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Enums; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Authorization.ABAC.Utils; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// Policy helper methods + /// + public static class PolicyHelper + { + private const string CoveredByNotDefined = "CoveredBy was not defined"; + + /// + /// Extracts a list of all roles codes mentioned in a permit rule in a policy. + /// + /// The policy + /// List of role codes + public static List GetRolesWithAccess(XacmlPolicy policy) + { + HashSet roleCodes = new HashSet(); + + foreach (XacmlRule rule in policy.Rules) + { + if (rule.Effect.Equals(XacmlEffectType.Permit) && rule.Target != null) + { + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.AttributeId.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute)) + { + roleCodes.Add(xacmlMatch.AttributeValue.Value); + } + } + } + } + } + } + + return roleCodes.ToList(); + } + + /// + /// Finds the correct policy path based on a XacmlContextRequest + /// + /// Xacml context request to use for finding the org and app for building the path + /// + public static string GetPolicyPath(XacmlContextRequest request) + { + string org = string.Empty; + string app = string.Empty; + + foreach (XacmlContextAttributes attr in request.Attributes.Where(attr => attr.Category.OriginalString.Equals(XacmlConstants.MatchAttributeCategory.Resource))) + { + foreach (XacmlAttribute asd in attr.Attributes) + { + if (asd.AttributeId.OriginalString.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute)) + { + XacmlAttributeValue orgAttr = asd.AttributeValues.FirstOrDefault(); + org = orgAttr != null ? orgAttr.Value : string.Empty; + } + + if (asd.AttributeId.OriginalString.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute)) + { + XacmlAttributeValue appAttr = asd.AttributeValues.FirstOrDefault(); + app = appAttr != null ? appAttr.Value : string.Empty; + } + } + } + + return GetAltinnAppsPolicyPath(org, app); + } + + /// + /// Builds the policy path based on org and app names + /// + /// The organization name/identifier + /// The altinn app name + /// + public static string GetAltinnAppsPolicyPath(string org, string app) + { + if (string.IsNullOrWhiteSpace(org)) + { + throw new ArgumentException("Org was not defined"); + } + + if (string.IsNullOrWhiteSpace(app)) + { + throw new ArgumentException("App was not defined"); + } + + return $"{org.AsFileName()}/{app.AsFileName()}/policy.xml"; + } + + /// + /// Builds the policy path based on resourceRegistryId + /// + /// The resource registry Id + /// Returns the path to the policyfile. + public static string GetResourceRegistryPolicyPath(string resourceRegistryId) + { + if (string.IsNullOrWhiteSpace(resourceRegistryId)) + { + throw new ArgumentException("ResourceRegistryId was not defined"); + } + + return $"{resourceRegistryId.AsFileName()}/resourcepolicy.xml"; + } + + /// + /// Creates a Rule representation based on a search and a xacmlRule found in a XacmlPolicyFile based on the search + /// + /// The search used to find the correct rule + /// XacmlRule found by the search param to enrich the result with Action and Resource + /// The created Rule + public static Rule CreateRuleFromPolicyAndRuleMatch(RequestToDelete search, XacmlRule xacmlRule) + { + Rule rule = new Rule + { + RuleId = xacmlRule.RuleId, + CreatedSuccessfully = true, + DelegatedByUserId = search.DeletedByUserId, + OfferedByPartyId = search.PolicyMatch.OfferedByPartyId, + CoveredBy = search.PolicyMatch.CoveredBy, + Resource = GetResourceFromXcamlRule(xacmlRule), + Action = GetActionValueFromRule(xacmlRule) + }; + + return rule; + } + + /// + /// Builds the delegation policy path based on org and app names, as well as identifiers for the delegating and receiving entities + /// + /// the resource match type + /// The id of the resource. Either a resource registry id or org/app + /// The organization name/identifier + /// The altinn app name + /// The party id of the entity offering the delegated the policy + /// The user id of the entity having received the delegated policy or null if party id + /// The party id of the entity having received the delegated policy or null if user id + /// the uuid of the coveredBy only valid value when the receiver is a system user + /// the type of uuid to set as prefix for the coveredBy + /// policypath matching input data + public static string GetDelegationPolicyPath(ResourceAttributeMatchType resourceMatchType, string resourceId, string org, string app, string offeredBy, int? coveredByUserId, int? coveredByPartyId, Guid? coveredByUuid, UuidType uuidType) + { + if (string.IsNullOrWhiteSpace(offeredBy)) + { + throw new ArgumentException("OfferedBy was not defined"); + } + + if (coveredByPartyId == null && coveredByUserId == null && coveredByUuid == null) + { + throw new ArgumentException(CoveredByNotDefined); + } + + if (coveredByPartyId <= 0) + { + throw new ArgumentException(CoveredByNotDefined); + } + + if (coveredByUserId <= 0) + { + throw new ArgumentException(CoveredByNotDefined); + } + + if (coveredByUuid == Guid.Empty) + { + throw new ArgumentException(CoveredByNotDefined); + } + + string coveredByPrefix; + string coveredBy; + if (coveredByPartyId != null) + { + coveredByPrefix = "p"; + coveredBy = coveredByPartyId.ToString(); + } + else if (coveredByUserId != null) + { + coveredByPrefix = "u"; + coveredBy = coveredByUserId.ToString(); + } + else + { + coveredByPrefix = uuidType.ToString(); + coveredBy = coveredByUuid.ToString(); + } + + if (resourceMatchType == ResourceAttributeMatchType.None) + { + throw new ArgumentException("Resource could not be identified. Resource must be for either a single resource from the resource registry or for a single Altinn app identified by org owner and app name"); + } + + if (resourceMatchType == ResourceAttributeMatchType.ResourceRegistry) + { + if (string.IsNullOrWhiteSpace(resourceId)) + { + throw new ArgumentException("ResourceRegistryId was not defined"); + } + + return $"resourceregistry/{resourceId.AsFileName()}/{offeredBy.AsFileName()}/{coveredByPrefix}{coveredBy.AsFileName()}/delegationpolicy.xml"; + } + + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + if (string.IsNullOrWhiteSpace(org)) + { + throw new ArgumentException("Org was not defined"); + } + + if (string.IsNullOrWhiteSpace(app)) + { + throw new ArgumentException("App was not defined"); + } + + return $"{org.AsFileName()}/{app.AsFileName()}/{offeredBy.AsFileName()}/{coveredByPrefix}{coveredBy.AsFileName()}/delegationpolicy.xml"; + } + + throw new ArgumentException("Unable to build a valid delegation policy path from the provided parameters"); + } + + /// + /// Builds the delegation policy path based on input policyMatch + /// + /// param to build policypath from + /// policypath matching input data + public static string GetAltinnAppDelegationPolicyPath(PolicyMatch policyMatch) + { + DelegationHelper.TryGetResourceFromAttributeMatch(policyMatch.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string _, out string _); + DelegationHelper.GetCoveredByFromMatch(policyMatch.CoveredBy, out int? coveredByUserId, out int? coveredByPartyId, out Guid? coveredByUuid, out UuidType coveredByUuidType); + + return GetDelegationPolicyPath(resourceMatchType, resourceId, org, app, policyMatch.OfferedByPartyId.ToString(), coveredByUserId, coveredByPartyId, coveredByUuid, coveredByUuidType); + } + + /// + /// Takes the file IO stream and parses the policy file to a XacmlPolicy + /// + /// The file IO stream + /// XacmlPolicy + public static XacmlPolicy ParsePolicy(Stream stream) + { + stream.Position = 0; + XacmlPolicy policy; + using (XmlReader reader = XmlReader.Create(stream)) + { + policy = XacmlParser.ParseXacmlPolicy(reader); + } + + return policy; + } + + /// + /// Serializes the XacmlPolicy to Xml and returns it as a Memory stream + /// + /// The XacmlPolicy model to serialize to a memory stream + /// MemoryStream of the Xml serialized policy + public static MemoryStream GetXmlMemoryStreamFromXacmlPolicy(XacmlPolicy policy) + { + MemoryStream stream = new MemoryStream(); + XmlWriter writer = XmlWriter.Create(stream); + + XacmlSerializer.WritePolicy(writer, policy); + + writer.Flush(); + stream.Position = 0; + return stream; + } + + /// + /// Check the input and returns a vale for CoveredBy and a urn to be used when creating a Attribute match given taht the covered by could be a user, party or SystemUser. + /// + /// PartyId to evaluate for coveredBy + /// UserId to evaluate for coveredBy + /// Uuid to evaluate for coveredBy + /// The type of covered by to evaluate for type and chose what input to use for covered by value + /// coveredBy value and type of value + /// When no valid coveredBy is defined + public static (string CoveredBy, string CoveredByType) GetCoveredByAndType(int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toType) + { + string coveredBy = null; + string coveredByType = null; + + if (coveredByPartyId.HasValue) + { + coveredBy = coveredByPartyId.Value.ToString(); + coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute; + } + else if (coveredByUserId.HasValue) + { + coveredBy = coveredByUserId.Value.ToString(); + coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + } + else if (toType.Equals(UuidType.SystemUser)) + { + coveredBy = toUuid.ToString(); + coveredByType = toType.EnumMemberAttributeValueOrName(); + } + + if (coveredBy == null) + { + throw new ArgumentException($"No valid coveredBy was provided"); + } + + return (coveredBy, coveredByType); + } + + /// + /// Builds a XacmlPolicy representation based on the DelegationPolicy input + /// + /// The identifier of the resource, either a resource in the resource registry or altinn app + /// The party id of the entity offering the delegated the policy + /// The party of the entity having received the delegated policy, if the receiving entity is an organization + /// The user id of the entity having received the delegated policy, if the receiving entity is a user + /// The uuid id of the entity having received the delegated policy + /// The uuid type id of the entity having received the delegated policy + /// The set of rules to be delegated + public static XacmlPolicy BuildDelegationPolicy(string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toType, IList rules) + { + XacmlPolicy delegationPolicy = new XacmlPolicy(new Uri($"{AltinnXacmlConstants.Prefixes.PolicyId}{1}"), new Uri(XacmlConstants.CombiningAlgorithms.PolicyDenyOverrides), new XacmlTarget(new List())); + delegationPolicy.Version = "1.0"; + + (string coveredBy, string coveredByType) = GetCoveredByAndType(coveredByPartyId, coveredByUserId, toUuid, toType); + + delegationPolicy.Description = $"Delegation policy containing all delegated rights/actions from {offeredByPartyId} to {coveredBy}, for the resource; {resourceId}"; + + foreach (Rule rule in rules) + { + if (!DelegationHelper.PolicyContainsMatchingRule(delegationPolicy, rule)) + { + delegationPolicy.Rules.Add(BuildDelegationRule(resourceId, offeredByPartyId, coveredBy, coveredByType, rule)); + } + } + + return delegationPolicy; + } + + /// + /// Extracts policy data from InstanceRight + /// + /// The rules that is delegated + public static PolicyParameters GetPolicyDataFromInstanceRight(InstanceRight rules) + { + PolicyParameters result = new PolicyParameters + { + ResourceId = rules.ResourceId, + InstanceId = rules.InstanceId, + FromType = rules.FromType.EnumMemberAttributeValueOrName(), + FromId = rules.FromUuid.ToString().ToLowerInvariant(), + ToType = rules.ToType.EnumMemberAttributeValueOrName(), + ToId = rules.ToUuid.ToString().ToLowerInvariant(), + PerformedById = rules.PerformedBy, + PerformedByType = rules.PerformedByType.EnumMemberAttributeValueOrName() + }; + + return result; + } + + /// + /// Builds a XacmlPolicy representation based on the DelegationPolicy input + /// + /// The set of rules to be delegated + public static XacmlPolicy BuildInstanceDelegationPolicy(InstanceRight rules) + { + XacmlPolicy delegationPolicy = new XacmlPolicy(new Uri($"{AltinnXacmlConstants.Prefixes.PolicyId}{1}"), new Uri(XacmlConstants.CombiningAlgorithms.PolicyPermidOverrides), new XacmlTarget(new List())); + delegationPolicy.Version = "1.0"; + PolicyParameters policydata = GetPolicyDataFromInstanceRight(rules); + + delegationPolicy.Description = $"Delegation policy containing all delegated rights/actions from {policydata.FromType}:{policydata.FromId} to {policydata.ToType}:{policydata.ToId}, for the resource: {policydata.ResourceId} and InstanceId: {policydata.InstanceId}"; + + foreach (InstanceRule rule in rules.InstanceRules) + { + if (!DelegationHelper.PolicyContainsMatchingInstanceRule(delegationPolicy, rule)) + { + delegationPolicy.Rules.Add(BuildDelegationInstanceRule(policydata, rule)); + } + } + + return delegationPolicy; + } + + /// + /// Builds a XacmlRule representation based on the Rule input + /// + /// container with data to inclue in policy + /// The rule to be delegated + public static XacmlRule BuildDelegationInstanceRule(PolicyParameters policyData, InstanceRule rule) + { + rule.RuleId = Guid.NewGuid().ToString(); + + XacmlRule delegationRule = new XacmlRule(rule.RuleId, XacmlEffectType.Permit) + { + Description = $"Delegation of a right/action from {policyData.FromType}:{policyData.FromId} to {policyData.ToType}:{policyData.ToId}, for the resourceId: {policyData.ResourceId} instanceId: {policyData.InstanceId}, by: {policyData.PerformedByType}:{policyData.PerformedById}", + Target = BuildInstanceDelegationRuleTarget(policyData.ToId, policyData.ToType, rule) + }; + return delegationRule; + } + + /// + /// Builds a XacmlRule representation based on the Rule input + /// + /// The identifier of the resource, either a resource in the resource registry or altinn app + /// The id of the entity offering the delegated the policy + /// The type of the entity offering the delegated policy + /// The id of the entity having received the delegated policy + /// The type of the entity having received the delegated policy + /// The id of the entity delegated the policy + /// The type of the entity delegated the policy + /// The rule to be delegated + public static XacmlRule BuildDelegationInstanceRule(string resourceId, string fromId, string fromType, string toId, string toType, string performedById, string performedByType, InstanceRule rule) + { + rule.RuleId = Guid.NewGuid().ToString(); + + XacmlRule delegationRule = new XacmlRule(rule.RuleId, XacmlEffectType.Permit) + { + Description = $"Delegation of a right/action from {fromType}:{fromId} to {toType}:{toId}, for the resource: {resourceId}, by: {performedByType}:{performedById}", + Target = BuildInstanceDelegationRuleTarget(toId, toType, rule) + }; + return delegationRule; + } + + /// + /// Builds a XacmlRule representation based on the Rule input + /// + /// The identifier of the resource, either a resource in the resource registry or altinn app + /// The party id of the entity offering the delegated the policy + /// The id of the entity having received the delegated policy + /// The type of the entity having received the delegated policy + /// The rule to be delegated + public static XacmlRule BuildDelegationRule(string resourceId, int offeredByPartyId, string coveredBy, string toType, Rule rule) + { + rule.RuleId = Guid.NewGuid().ToString(); + + XacmlRule delegationRule = new XacmlRule(rule.RuleId, XacmlEffectType.Permit) + { + Description = $"Delegation of a right/action from {offeredByPartyId} to {coveredBy}, for the resource: {resourceId}, by user; {rule.DelegatedByUserId}", + Target = BuildDelegationRuleTarget(coveredBy, toType, rule) + }; + return delegationRule; + } + + /// + /// Builds a XacmlTarget representation based on the Rule input + /// + /// The the entity having received the delegated policy + /// The type of identifier received the delegated policy user, party or system user + /// The rule to be delegated + public static XacmlTarget BuildDelegationRuleTarget(string coveredBy, string toType, Rule rule) + { + List targetList = new List(); + + // Build Subject + List subjectAllOfs = new List(); + + subjectAllOfs.Add(new XacmlAllOf(new List + { + new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqual), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), coveredBy), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Subject), new Uri(toType), new Uri(XacmlConstants.DataTypes.XMLString), false)) + })); + + // Build Resource + List resourceMatches = new List(); + foreach (AttributeMatch resourceMatch in rule.Resource) + { + resourceMatches.Add( + new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqual), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), resourceMatch.Value), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Resource), new Uri(resourceMatch.Id), new Uri(XacmlConstants.DataTypes.XMLString), false))); + } + + List resourceAllOfs = new List { new XacmlAllOf(resourceMatches) }; + + // Build Action + List actionAllOfs = new List(); + actionAllOfs.Add(new XacmlAllOf(new List + { + new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqual), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), rule.Action.Value), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Action), new Uri(XacmlConstants.MatchAttributeIdentifiers.ActionId), new Uri(XacmlConstants.DataTypes.XMLString), false)) + })); + + targetList.Add(new XacmlAnyOf(subjectAllOfs)); + targetList.Add(new XacmlAnyOf(resourceAllOfs)); + targetList.Add(new XacmlAnyOf(actionAllOfs)); + + return new XacmlTarget(targetList); + } + + /// + /// Builds a XacmlTarget representation based on the Rule input + /// + /// The the entity having received the delegated policy + /// The type of identifier received the delegated policy user, party or system user + /// The rule to be delegated + public static XacmlTarget BuildInstanceDelegationRuleTarget(string toId, string toType, InstanceRule rule) + { + List targetList = new List(); + + // Build Subject + List subjectAllOfs = new List(); + + subjectAllOfs.Add(new XacmlAllOf(new List + { + new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqualIgnoreCase), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), toId), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Subject), new Uri(toType), new Uri(XacmlConstants.DataTypes.XMLString), false)) + })); + + // Build Resource + List resourceMatches = []; + resourceMatches.AddRange(rule.Resource.Select(resourceMatch => new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqualIgnoreCase), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), resourceMatch.Value.ValueSpan.ToString()), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Resource), new Uri(resourceMatch.Value.PrefixSpan.ToString()), new Uri(XacmlConstants.DataTypes.XMLString), false)))); + List resourceAllOfs = new List { new XacmlAllOf(resourceMatches) }; + + // Build Action + List actionAllOfs = new List(); + actionAllOfs.Add(new XacmlAllOf(new List + { + new XacmlMatch( + new Uri(XacmlConstants.AttributeMatchFunction.StringEqualIgnoreCase), + new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), rule.Action.ValueSpan.ToString()), + new XacmlAttributeDesignator(new Uri(XacmlConstants.MatchAttributeCategory.Action), new Uri(rule.Action.PrefixSpan.ToString()), new Uri(XacmlConstants.DataTypes.XMLString), false)) + })); + + targetList.Add(new XacmlAnyOf(subjectAllOfs)); + targetList.Add(new XacmlAnyOf(resourceAllOfs)); + targetList.Add(new XacmlAnyOf(actionAllOfs)); + + return new XacmlTarget(targetList); + } + + /// + /// Builds a XacmlMatch model + /// + /// The compare function type + /// The attribute data type + /// The attribute value + /// The attribute id + /// The attribute category + /// Whether the attribute value must be present + public static XacmlMatch BuildDelegationPolicyMatch(string function, string datatype, string attributeValue, string attributeId, string category, bool mustBePresent = false) + { + return new XacmlMatch( + new Uri(function), + new XacmlAttributeValue(new Uri(datatype), attributeValue), + new XacmlAttributeDesignator(new Uri(category), new Uri(attributeId), new Uri(datatype), mustBePresent)); + } + + /// + /// Gets the entire policy as a list of . + /// + /// The policy + /// The language (not in use yet; exactly how is yet to be determined) + /// List of resource policies + public static List GetResourcePoliciesFromXacmlPolicy(XacmlPolicy policy, string language) + { + Dictionary resourcePolicies = new Dictionary(); + + foreach (XacmlRule rule in policy.Rules) + { + if (rule.Effect.Equals(XacmlEffectType.Permit) && rule.Target != null) + { + List roles = GetRolesFromRule(rule); + if (roles.Count == 0) + { + continue; + } + + List policyKeys = GetResourcePoliciesFromRule(resourcePolicies, rule); + List actions = GetActionsFromRule(rule, roles); + + foreach (string policyKey in policyKeys) + { + ResourcePolicy resourcePolicy = resourcePolicies.GetValueOrDefault(policyKey); + + if (policy.Description != null && resourcePolicy.Description == null) + { + resourcePolicy.Description = policy.Description; + } + + AddActionsToResourcePolicy(actions, resourcePolicy); + } + } + } + + return resourcePolicies.Values.ToList(); + } + + /// + /// Gets the authentication level requirement from the obligation expression of the XacmlPolicy if specified + /// + /// The policy + /// Minimum authentication level requirement + public static int GetMinimumAuthenticationLevelFromXacmlPolicy(XacmlPolicy policy) + { + foreach (XacmlObligationExpression oblExpr in policy.ObligationExpressions) + { + foreach (XacmlAttributeAssignmentExpression attrExpr in oblExpr.AttributeAssignmentExpressions) + { + if (attrExpr.Category.OriginalString == AltinnXacmlConstants.MatchAttributeCategory.MinimumAuthenticationLevel && + attrExpr.Property is XacmlAttributeValue attrValue && + int.TryParse(attrValue.Value, out int minAuthLevel)) + { + return minAuthLevel; + } + } + } + + return 0; + } + + /// + /// Decomposes the provided XacmlPolicy with individual XacmlRules pr. Subject, Resource and Action AllOf combinations + /// + /// The XacmlPolicy to decompose + /// A decomposed XacmlPolicy + public static XacmlPolicy GetDecomposedXacmlPolicy(XacmlPolicy policy) + { + XacmlPolicy decomposedPolicy = new XacmlPolicy(new Uri($"{policy.PolicyId}_decomposed"), policy.RuleCombiningAlgId, policy.Target); + decomposedPolicy.Description = $"Decomposed policy of policyid: {policy.PolicyId}. Original description: {policy.Description}"; + + foreach (XacmlRule rule in policy.Rules) + { + ICollection subjectAllOfs = GetAllOfsByCategory(rule, XacmlConstants.MatchAttributeCategory.Subject); + ICollection resourceAllOfs = GetAllOfsByCategory(rule, XacmlConstants.MatchAttributeCategory.Resource); + ICollection actionAllOfs = GetAllOfsByCategory(rule, XacmlConstants.MatchAttributeCategory.Action); + + int decomposedRuleCount = 0; + foreach (XacmlAllOf subject in subjectAllOfs) + { + foreach (XacmlAllOf resource in resourceAllOfs) + { + foreach (XacmlAllOf action in actionAllOfs) + { + decomposedRuleCount++; + + XacmlRule decomposedRule = new XacmlRule($"{rule.RuleId}_{decomposedRuleCount}", rule.Effect); + decomposedRule.Description = $"Decomposed rule from policyid: {policy.PolicyId} ruleid: {rule.RuleId}. Original description: {rule.Description}"; + decomposedRule.Target = new XacmlTarget(new List + { + new XacmlAnyOf(new List { subject }), + new XacmlAnyOf(new List { resource }), + new XacmlAnyOf(new List { action }) + }); + + decomposedPolicy.Rules.Add(decomposedRule); + } + } + } + } + + return decomposedPolicy; + } + + /// + /// Builds a collection of XacmlContextAttributes which can be used for a decision request, based on a list of subject attributes and an already decomposed XacmlRule (has a single combination of subject, resource and action AllOfs) + /// + /// The list of subject values to add to the context (Roles, access groups, delegation recipients etc.) + /// The decomposed XacmlRule (has a single combination of subject, resource and action AllOfs) + /// A collection of XacmlContextAttributes which can be used for a decision request + public static ICollection GetContextAttributes(List subjects, XacmlRule decomposedRule) + { + ICollection resourceAllOfs = GetAllOfsByCategory(decomposedRule, XacmlConstants.MatchAttributeCategory.Resource); + ICollection actionAllOfs = GetAllOfsByCategory(decomposedRule, XacmlConstants.MatchAttributeCategory.Action); + + List resource = GetAttributeMatchFromXacmlAllOfs(resourceAllOfs.FirstOrDefault()); + List action = GetAttributeMatchFromXacmlAllOfs(actionAllOfs.FirstOrDefault()); + + return GetContextAttributes(subjects, resource, action); + } + + /// + /// Takes an already decomposed XacmlRule (has a single combination of subject, resource and action AllOfs) and builds a collection of XacmlContextAttributes which can be used for a decision request + /// + /// The list of subject values to add to the context (Roles, access groups, delegation recipients etc.) + /// The list of attribute values identifying a single resource to add to the context (Org/App, ResourceRegistryId) + /// The list of action attribute values identifying a single action to add to the context (Read, Write etc.) + /// A collection of XacmlContextAttributes which can be used for a decision request + public static ICollection GetContextAttributes(List subjects, List resource, List action) + { + ICollection contextAttributes = new Collection(); + + ICollection subjectsAttributes = new Collection(); + foreach (AttributeMatch subjectMatch in subjects) + { + XacmlAttribute subjectAttribute = new XacmlAttribute(new Uri(subjectMatch.Id), true); + subjectAttribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), subjectMatch.Value)); + subjectsAttributes.Add(subjectAttribute); + } + + ICollection resourceAttributes = new Collection(); + foreach (AttributeMatch resourceMatch in resource) + { + XacmlAttribute resourceAttribute = new XacmlAttribute(new Uri(resourceMatch.Id), true); + resourceAttribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), resourceMatch.Value)); + resourceAttributes.Add(resourceAttribute); + } + + ICollection actionAttributes = new Collection(); + foreach (AttributeMatch actionMatch in action) + { + XacmlAttribute actionAttribute = new XacmlAttribute(new Uri(actionMatch.Id), true); + actionAttribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), actionMatch.Value)); + actionAttributes.Add(actionAttribute); + } + + contextAttributes.Add(new XacmlContextAttributes(new Uri(XacmlConstants.MatchAttributeCategory.Subject), subjectsAttributes)); + contextAttributes.Add(new XacmlContextAttributes(new Uri(XacmlConstants.MatchAttributeCategory.Resource), resourceAttributes)); + contextAttributes.Add(new XacmlContextAttributes(new Uri(XacmlConstants.MatchAttributeCategory.Action), actionAttributes)); + return contextAttributes; + } + + /// + /// Creates a collection of Rights (single Resource and Action combinations) from the provided collection of XacmlRules + /// + /// The collection of XacmlRules + /// A collection of Rights + public static ICollection GetRightsFromXacmlRules(ICollection xacmlRules) + { + Dictionary rights = new Dictionary(); + + foreach (XacmlRule rule in xacmlRules) + { + ICollection resourceAllOfs = GetAllOfsByCategory(rule, XacmlConstants.MatchAttributeCategory.Resource); + ICollection actionAllOfs = GetAllOfsByCategory(rule, XacmlConstants.MatchAttributeCategory.Action); + + foreach (XacmlAllOf resource in resourceAllOfs) + { + foreach (XacmlAllOf action in actionAllOfs) + { + Right right = new Right + { + RightSources = new List(), + Resource = GetAttributeMatchFromXacmlAllOfs(resource), + Action = GetAttributeMatchFromXacmlAllOfs(action).FirstOrDefault() + }; + + if (!rights.ContainsKey(right.RightKey)) + { + rights.Add(right.RightKey, right); + } + } + } + } + + return rights.Values; + } + + /// + /// Gets a collection of distinct AttributeId used in XacmlMatch instances matching the specified attribute category. + /// + /// The xacml rule to find match attribute ids in + /// The attribute category to match + /// Collection of AttributeId + public static ICollection GetRuleMatchAttributeIdsForCategory(XacmlRule rule, string category) + { + SortedList attributeIds = new SortedList(); + + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(category) && !attributeIds.ContainsKey(xacmlMatch.AttributeDesignator.AttributeId.OriginalString)) + { + attributeIds.Add(xacmlMatch.AttributeDesignator.AttributeId.OriginalString, xacmlMatch.AttributeDesignator.AttributeId.OriginalString); + } + } + } + } + + return attributeIds.Keys.ToList(); + } + + /// + /// Gets a nested list of AttributeMatche models for all XacmlMatch instances matching the specified attribute category. + /// + /// The xacml rule to process + /// The attribute category to match + /// Nested list of PolicyAttributeMatch models + public static List> GetRulePolicyAttributeMatchesForCategory(XacmlRule rule, string category) + { + List> ruleAttributeMatches = new(); + + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + List anyOfAttributeMatches = new(); + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(category)) + { + anyOfAttributeMatches.Add(new PolicyAttributeMatch { Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, Value = xacmlMatch.AttributeValue.Value }); + } + } + + if (anyOfAttributeMatches.Any()) + { + ruleAttributeMatches.Add(anyOfAttributeMatches); + } + } + } + + return ruleAttributeMatches; + } + + /// + /// Check of a given app definition exist as a subject in a list of subjects + /// + /// The subject list to check + /// the app to check for + /// true if the app deffinion exist in list of subjects and false if not + public static bool ContainsDelegatorAppInSubject(List> ruleSubjects, IEnumerable delegaterApp) + { + bool result = false; + + foreach (List subject in ruleSubjects) + { + result = true; + foreach (var match in delegaterApp) + { + if (subject.Exists(s => s.Id == match.Id && s.Value == match.Value)) + { + continue; + } + + result = false; + break; + } + } + + return result; + } + + private static List GetAttributeMatchFromXacmlAllOfs(XacmlAllOf allOf) + { + List attributeMatches = new List(); + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + attributeMatches.Add(new AttributeMatch + { + Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, + Value = xacmlMatch.AttributeValue.Value + }); + } + + return attributeMatches; + } + + /// + /// Gets a collection of all XacmlAllOfs containing all XacmlMatch instances matching the specified attribute category, from a given XacmlRule + /// + /// The xacml rule + /// The attribute category to match + /// Collection of AllOfs + private static ICollection GetAllOfsByCategory(XacmlRule rule, string category) + { + ICollection allOfs = new Collection(); + + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + ICollection allOfMatchesFound = new Collection(); + + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(category)) + { + allOfMatchesFound.Add(xacmlMatch); + } + } + + if (allOfMatchesFound.Count > 0) + { + allOfs.Add(new XacmlAllOf(allOfMatchesFound)); + } + } + } + + return allOfs; + } + + private static void AddActionsToResourcePolicy(List actions, ResourcePolicy resourcePolicy) + { + if (resourcePolicy.Actions == null) + { + resourcePolicy.Actions = new List(); + resourcePolicy.Actions.AddRange(actions); + } + else + { + foreach (ResourceAction resourceAction in actions) + { + if (!resourcePolicy.Actions.Any(action => action.Match.Value == resourceAction.Match.Value && action.Match.Id == resourceAction.Match.Id)) + { + resourcePolicy.Actions.Add(resourceAction); + } + else + { + ResourceAction existingAction = resourcePolicy.Actions.First(action => action.Match.Value == resourceAction.Match.Value && action.Match.Id == resourceAction.Match.Id); + existingAction.RoleGrants.AddRange(resourceAction.RoleGrants.Where(roleGrant => !existingAction.RoleGrants.Any(existingRoleGrant => existingRoleGrant.RoleTypeCode == roleGrant.RoleTypeCode))); + } + } + } + } + + private static AttributeMatch GetActionValueFromRule(XacmlRule rule) + { + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + XacmlMatch action = allOf.Matches.FirstOrDefault(m => m.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action)); + + if (action != null) + { + return new AttributeMatch { Id = action.AttributeDesignator.AttributeId.OriginalString, Value = action.AttributeValue.Value }; + } + } + } + + return null; + } + + private static List GetResourceFromXcamlRule(XacmlRule rule) + { + List result = new List(); + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches.Where(m => m.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource))) + { + result.Add(new AttributeMatch { Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, Value = xacmlMatch.AttributeValue.Value }); + } + } + } + + return result; + } + + private static List GetActionsFromRule(XacmlRule rule, List roles) + { + List actions = new List(); + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + AttributeMatch actionAttributeMatch = new AttributeMatch(); + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action)) + { + actionAttributeMatch.Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString; + actionAttributeMatch.Value = xacmlMatch.AttributeValue.Value; + ResourceAction resourceAction = new ResourceAction + { + Match = actionAttributeMatch, + RoleGrants = new List(), + Title = xacmlMatch.AttributeValue.Value + }; + resourceAction.RoleGrants.AddRange(roles); + if (!actions.Contains(resourceAction)) + { + actions.Add(resourceAction); + } + } + } + } + } + + return actions; + } + + private static List GetRolesFromRule(XacmlRule rule) + { + List roles = new List(); + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Subject) && xacmlMatch.AttributeDesignator.AttributeId.Equals(XacmlRequestAttribute.RoleAttribute)) + { + roles.Add(new RoleGrant { RoleTypeCode = xacmlMatch.AttributeValue.Value, IsDelegable = true }); + } + } + } + } + + return roles; + } + + private static List GetResourcePoliciesFromRule(Dictionary resourcePolicies, XacmlRule rule) + { + List policyKeys = new List(); + foreach (XacmlAnyOf anyOf in rule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + StringBuilder bld = new StringBuilder(); + string resourceKey = string.Empty; + List resourceMatches = new List(); + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + bld.Append(xacmlMatch.AttributeDesignator.AttributeId); + bld.Append(xacmlMatch.AttributeValue.Value); + resourceKey = bld.ToString(); + resourceMatches.Add(new AttributeMatch { Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, Value = xacmlMatch.AttributeValue.Value }); + } + } + + CreateUniqueResourcePolicy(resourceKey, policyKeys, resourcePolicies, resourceMatches); + } + } + + return policyKeys; + } + + private static void CreateUniqueResourcePolicy(string resourceKey, List policyKeys, Dictionary resourcePolicies, List resourceMatches) + { + if (!string.IsNullOrEmpty(resourceKey)) + { + policyKeys.Add(resourceKey); + + if (!resourcePolicies.ContainsKey(resourceKey)) + { + string title = string.Join("/", resourceMatches.Select(rm => rm.Value)); + ResourcePolicy newPolicy = new ResourcePolicy + { + Resource = resourceMatches, + Title = title + }; + + resourcePolicies.Add(resourceKey, newPolicy); + } + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/RightsHelper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/RightsHelper.cs new file mode 100644 index 00000000..fde4f291 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/RightsHelper.cs @@ -0,0 +1,218 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.AccessList; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Authorization.Platform.Authorization.Models; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// Helper methods for rights retrieval + /// + public static class RightsHelper + { + /// + /// Gets the list of Roles as a list of AttributeMatch elements + /// + /// The list of altinn role codes + /// List of attribute matches + public static List GetRoleAttributeMatches(List roles) + { + List roleMatches = new List(); + foreach (Role role in roles) + { + roleMatches.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute, Value = role.Value }); + } + + return roleMatches; + } + + /// + /// Gets the subject list for a given delegation change, for building a XacmlContextRequest + /// + /// The delegation change to retrieve subject from + /// List of attribute matches + public static List GetDelegationSubjectAttributeMatches(DelegationChange delegationChange) + { + if (delegationChange.CoveredByUserId.HasValue) + { + return new List() + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, Value = delegationChange.CoveredByUserId.Value.ToString() } + }; + } + + if (delegationChange.CoveredByPartyId.HasValue) + { + return new List() + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = delegationChange.CoveredByPartyId.Value.ToString() } + }; + } + + return new(); + } + + /// + /// Builds a RightsQuery request model for lookup of a users rights for a given service resource on behalf of the given reportee party + /// + public static RightsQuery GetRightsQuery(int userId, int fromPartyId, ServiceResource resource) + { + return new RightsQuery() + { + Type = RightsQueryType.User, + To = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, Value = userId.ToString() } }, + From = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = fromPartyId.ToString() } }, + Resource = resource + }; + } + + /// + /// Check if it exist any roles giving access to the resource if there is no such access rules this must be a rule defined for the service owner as there is not any way the end user could gain access + /// + /// the right to analyze + /// the decision + public static bool CheckIfRuleIsAnEndUserRule(Right right) + { + List roleAccessSources = right.RightSources.Where(rs => rs.RightSourceType != RightSourceType.DelegationPolicy).ToList(); + if (roleAccessSources.Any()) + { + List roles = GetAttributeMatches(roleAccessSources.SelectMany(roleAccessSource => roleAccessSource.PolicySubjects)).FindAll(policySubject => policySubject.Id.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute, StringComparison.OrdinalIgnoreCase)); + return roles.Count != 0; + } + + return false; + } + + /// + /// Analyzes a Right model for a reason for the rights delegation access status + /// + public static List AnalyzeDelegationAccessReason(Right right, AccessListAuthorizationResult accessListAuthorizationResult = AccessListAuthorizationResult.NotApplicable) + { + List reasons = new(); + + // Analyze why able to delegate + if (right.CanDelegate.HasValue && right.CanDelegate.Value) + { + // Analyze for role access + List roleAccessSources = right.RightSources.Where(rs => rs.RightSourceType != Enums.RightSourceType.DelegationPolicy && rs.CanDelegate.HasValue && rs.CanDelegate.Value).ToList(); + if (roleAccessSources.Count != 0) + { + List roles = GetAttributeMatches(roleAccessSources.SelectMany(roleAccessSource => roleAccessSource.PolicySubjects)).FindAll(policySubject => policySubject.Id.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute, StringComparison.OrdinalIgnoreCase)); + string requiredRoles = string.Join(", ", roles); + + if (roles.Count != 0) + { + reasons.Add(new Detail + { + Code = DetailCode.RoleAccess, + Description = $"Delegator have access through having one of the following role(s) for the reportee party: {requiredRoles}. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + Parameters = new Dictionary>() + { + { + "RoleRequirementsMatches", roles + } + } + }); + } + } + + // Analyze for delegation policy access + List delegationPolicySources = right.RightSources.Where(rs => rs.RightSourceType == Enums.RightSourceType.DelegationPolicy && rs.CanDelegate.HasValue && rs.CanDelegate.Value).ToList(); + if (delegationPolicySources.Count != 0) + { + string delegationRecipients = string.Join(", ", delegationPolicySources.SelectMany(delegationPolicySource => delegationPolicySource.PolicySubjects.SelectMany(policySubjects => policySubjects))); + + reasons.Add(new Detail + { + Code = DetailCode.DelegationAccess, + Description = $"The user have access through delegation(s) of the right to the following recipient(s): {delegationRecipients}", + Parameters = new Dictionary>() { { "DelegationRecipients", GetAttributeMatches(delegationPolicySources.SelectMany(delegationAccessSource => delegationAccessSource.PolicySubjects)) } } + }); + } + + // Analyze accessListAuthorizationResult + if (accessListAuthorizationResult != AccessListAuthorizationResult.NotApplicable) + { + if (accessListAuthorizationResult == AccessListAuthorizationResult.Authorized) + { + reasons.Add(new Detail + { + Code = DetailCode.AccessListValidationPass, + Description = "The fromParty has the right based on Access List delegation", + }); + } + else if (accessListAuthorizationResult == AccessListAuthorizationResult.NotAuthorized) + { + right.CanDelegate = false; + + reasons.Add(new Detail + { + Code = DetailCode.AccessListValidationFail, + Description = "The fromParty does not have the right based on Access List delegation" + }); + } + } + } + else if (right.CanDelegate.HasValue && !right.CanDelegate.Value) + { + // Analyze for role access failure + List roleAccessSources = right.RightSources.Where(rs => rs.RightSourceType != Enums.RightSourceType.DelegationPolicy).ToList(); + if (roleAccessSources.Count != 0) + { + List roles = GetAttributeMatches(roleAccessSources.SelectMany(roleAccessSource => roleAccessSource.PolicySubjects)).FindAll(policySubject => policySubject.Id.Equals(AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute, StringComparison.OrdinalIgnoreCase)); + string requiredRoles = string.Join(", ", roles); + + if (roles.Count != 0) + { + reasons.Add(new Detail + { + Code = DetailCode.MissingRoleAccess, + Description = $"Delegator does not have any required role(s) for the reportee party: ({requiredRoles}), which would give access to delegate the right.", + Parameters = new Dictionary>() { { "RequiredRoles", roles } } + }); + } + } + + // Analyze for delegation policy failure + List delegationPolicySources = right.RightSources.Where(rs => rs.RightSourceType == Enums.RightSourceType.DelegationPolicy).ToList(); + if (delegationPolicySources.Count == 0) + { + reasons.Add(new Detail + { + Code = DetailCode.MissingDelegationAccess, + Description = $"The user does not have access through delegation(s) of the right" + }); + } + } + + if (reasons.Count == 0) + { + reasons.Add(new Detail + { + Code = DetailCode.Unknown, + Description = $"Unknown" + }); + } + + return reasons; + } + + /// + /// Converts a list of policy attribute matches into a list of attribute matches + /// + /// a list of policy attribute matches + /// a list of attribute matches + private static List GetAttributeMatches(IEnumerable> policySubjects) + { + List attributeMatches = new List(); + foreach (List attributeMatch in policySubjects) + { + attributeMatches.AddRange(attributeMatch); + } + + return attributeMatches; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/ServiceResourceHelper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/ServiceResourceHelper.cs new file mode 100644 index 00000000..9e23eafe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Helpers/ServiceResourceHelper.cs @@ -0,0 +1,16 @@ +using System.Text.RegularExpressions; + +namespace Altinn.AccessManagement.Core.Helpers +{ + /// + /// ServiceResource helper methods + /// + public static partial class ServiceResourceHelper + { + /// + /// Resource identifier regex. + /// + [GeneratedRegex("^[a-z0-9_-]{4,}$")] + internal static partial Regex ResourceIdentifierRegex(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationRequest.cs new file mode 100644 index 00000000..94d20cd0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationRequest.cs @@ -0,0 +1,35 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models.AccessList; + +/// +/// Contains attribute match info about the reportee party and resource that's to be authorized +/// +public class AccessListAuthorizationRequest +{ + /// + /// Gets or sets the attributes identifying the party to be authorized + /// + [Required] + [JsonRequired] + public UrnJsonTypeValue Subject { get; set; } + + /// + /// Gets or sets the attributes identifying the resource to authorize the party for + /// + [Required] + [JsonRequired] + public UrnJsonTypeValue Resource { get; set; } + + /// + /// Gets or sets an optional action value to authorize + /// + public UrnJsonTypeValue Action { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResponse.cs new file mode 100644 index 00000000..cccccba0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResponse.cs @@ -0,0 +1,51 @@ +using System; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models.AccessList; + +/// +/// Contains attribute match info about the reportee party and resource that's to be authorized +/// +public class AccessListAuthorizationResponse +{ + /// + /// Creates a new from an . + /// + /// The request. + /// The mapped . + public static AccessListAuthorizationResponse From(AccessListAuthorizationRequest request) + { + request = request ?? throw new ArgumentNullException(nameof(request)); + + return new AccessListAuthorizationResponse + { + Subject = request.Subject, + Resource = request.Resource, + Action = request.Action, + Result = AccessListAuthorizationResult.NotDetermined + }; + } + + /// + /// Gets or sets the attributes identifying the party to be authorized + /// + public UrnJsonTypeValue Subject { get; set; } + + /// + /// Gets or sets the attributes identifying the resource to authorize the party for + /// + public UrnJsonTypeValue Resource { get; set; } + + /// + /// Gets or sets an optional action value to authorize + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets the result of the access list authorization + /// + public AccessListAuthorizationResult Result { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResult.cs new file mode 100644 index 00000000..b889752e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessList/AccessListAuthorizationResult.cs @@ -0,0 +1,35 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models.AccessList; + +/// +/// Enum defining the different results of an access list authorization +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum AccessListAuthorizationResult +{ + /// + /// If PartyType is not Organization then access lists are not applicable + /// + [EnumMember(Value = "NotApplicable")] + NotApplicable, + + /// + /// Result is not yet determined + /// + [EnumMember(Value = "NotDetermined")] + NotDetermined, + + /// + /// Subject is not authorized to access the resource through any access lists + /// + [EnumMember(Value = "NotAuthorized")] + NotAuthorized, + + /// + /// Subject is authorized to access the resource through one or more access lists + /// + [EnumMember(Value = "Authorized")] + Authorized +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessManagementResource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessManagementResource.cs new file mode 100644 index 00000000..dbbed9e5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AccessManagementResource.cs @@ -0,0 +1,42 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Entity holding resource information for storing in AccessManagement + /// + public class AccessManagementResource + { + #nullable enable + /// + /// Primary key created when inserted in Access management + /// + public int? ResourceId { get; set; } + #nullable disable + + /// + /// The resource registry id + /// + [Required] + public string ResourceRegistryId { get; set; } + + /// + /// The type of resource + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResourceType ResourceType { get; set; } + + /// + /// When the resource was created in access management + /// + public DateTime? Created { get; set; } + + /// + /// The last time modified in access management + /// + public DateTime? Modified { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationRequest.cs new file mode 100644 index 00000000..0f533770 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationRequest.cs @@ -0,0 +1,57 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Request model for performing delegation of access to an app instance from Apps +/// +public class AppsInstanceDelegationRequest +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public PartyUrn From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public PartyUrn To { get; set; } + + /// + /// Gets or sets a value indicating whether the instance delegation is for a parallel task + /// + [Required] + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// Gets or sets a value indicating whether the instance delegation is from a user or app + /// + [Required] + public InstanceDelegationSource InstanceDelegationSource { get; set; } + + /// + /// The instanceid to the spesific resource + /// + public string InstanceId { get; set; } + + /// + /// The ResourceId for the specific resource + /// + public string ResourceId { get; set; } + + /// + /// The app performing the delegation + /// + public ResourceIdUrn PerformedBy { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationResponse.cs new file mode 100644 index 00000000..e7ce8922 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceDelegationResponse.cs @@ -0,0 +1,51 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.Swashbuckle.Examples; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Request model for performing delegation of access to an app instance from Apps +/// +public class AppsInstanceDelegationResponse +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public PartyUrn From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public PartyUrn To { get; set; } + + /// + /// Gets or sets the urn identifying the resource of the instance + /// + [Required] + public string ResourceId { get; set; } + + /// + /// Gets or sets the urn identifying the instance id + /// + [Required] + public string InstanceId { get; set; } + + /// + /// Gets or sets a value indicating whether the instance delegation is for a parallel task + /// + [Required] + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceGetRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceGetRequest.cs new file mode 100644 index 00000000..c62b928e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceGetRequest.cs @@ -0,0 +1,35 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Request model for getting delegation of access to an app instance from Apps +/// +public class AppsInstanceGetRequest +{ + /// + /// Gets or sets a value indicating whether the instance delegation is from a user or app + /// + [Required] + public InstanceDelegationSource InstanceDelegationSource { get; set; } + + /// + /// The App performing the get request + /// + [Required] + public ResourceIdUrn.ResourceId PerformingResourceId { get; set; } + + /// + /// The instanceid to the spesific resource + /// + [Required] + public string InstanceId { get; set; } + + /// + /// The ResourceId for the specific resource + /// + [Required] + public string ResourceId { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceRevokeResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceRevokeResponse.cs new file mode 100644 index 00000000..1dcf4afa --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AppsInstanceRevokeResponse.cs @@ -0,0 +1,47 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Register; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Response model for performing revoke of access to a respource from Apps +/// +public class AppsInstanceRevokeResponse +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public PartyUrn From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public PartyUrn To { get; set; } + + /// + /// Gets or sets the urn identifying the resource of the instance + /// + [Required] + public string ResourceId { get; set; } + + /// + /// Gets or sets the urn identifying the instance id + /// + [Required] + public string InstanceId { get; set; } + + /// + /// Gets or sets a value indicating whether the instance delegation is for a parallel task + /// + [Required] + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AttributeMatch.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AttributeMatch.cs new file mode 100644 index 00000000..4eb61c8a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AttributeMatch.cs @@ -0,0 +1,70 @@ +using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a pair of AttributeId and AttributeValue for use in matching in XACML policies, for instance a resource, a user, a party or an action. + /// + public class AttributeMatch : IEqualityComparer + { + /// + /// ctor + /// + public AttributeMatch() + { + } + + /// + /// ctor + /// + /// type + /// value + public AttributeMatch(string id, object value) + { + Id = id; + Value = value?.ToString() ?? string.Empty; + } + + /// + /// Gets or sets the attribute id for the match + /// + [Required] + public string Id { get; set; } + + /// + /// Gets or sets the attribute value for the match + /// + [Required] + public string Value { get; set; } + + /// + public bool Equals(AttributeMatch x, AttributeMatch y) => x.Equals(y); + + /// + public override bool Equals(object obj) => Equals(obj as AttributeMatch); + + private bool Equals(AttributeMatch other) => Id.Equals(other?.Id, StringComparison.InvariantCultureIgnoreCase) && Value == other?.Value; + + /// + public int GetHashCode([DisallowNull] AttributeMatch obj) => obj.GetHashCode(); + + /// + public override int GetHashCode() => (Id, Value).GetHashCode(); + + /// + /// String representation of the attribute + /// + /// + public override string ToString() => + $"{Id.ToLowerInvariant()}:{Value}"; + + /// + /// Creates a KeyValueUrn from the attribute match + /// + /// KeyValueUrn + public KeyValueUrn ToKeyValueUrn() => + KeyValueUrn.CreateUnchecked($"{Id.ToLowerInvariant()}:{Value}", Id.Length + 1); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/DefaultRight.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/DefaultRight.cs new file mode 100644 index 00000000..d78a5677 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/DefaultRight.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Core.Models.Authentication +{ + /// + /// DTO for a Default Right on a Registered System + /// + public class DefaultRight + { + /// + /// The list of resources at the Service Provider which the Right is for. + /// + public List Resource { get; set; } = []; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/SystemUser.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/SystemUser.cs new file mode 100644 index 00000000..6b5eeadb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Authentication/SystemUser.cs @@ -0,0 +1,91 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models.Authentication +{ +#nullable enable + /// + /// The model of the System User response given in the CRUD API in SystemUserController.cs + /// This model will be exchanged between this Authentication component, the PostGress db and the BFF for the Frontend. + /// The BFF will provide a tailored DTO to the Frontend. + /// + [ExcludeFromCodeCoverage] + public class SystemUser + { + /// + /// GUID created by the "real" Authentication Component + /// When the Frontend send a request for the creation of a new SystemUser the Id is null + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + + /// + /// The Title is by default the same as the System's Display Name + /// + [JsonPropertyName("integrationTitle")] + public string IntegrationTitle { get; set; } = string.Empty; + + /// + /// Identifier for off the shelf systems, registered in the SystemRegister db. + /// Should be human readable (instead of a GUID) and unique string without whitespace. + /// + [JsonPropertyName("systemId")] + public string SystemId { get; set; } = string.Empty; + + /// + /// Identifier for off the shelf systems, registered in the SystemRegister db. + /// Should be human readable (instead of a GUID) and unique string without whitespace. + /// To be deprecated, use the systemId field going forward, it contains the same value. + /// + [JsonPropertyName("productName")] + public string ProductName { get; set; } = string.Empty; + + /// + /// The underlying identifier for the System for persistance in the db. + /// + [JsonPropertyName("systemInternalId")] + public Guid? SystemInternalId { get; set; } + + /// + /// The PartyID identifies the end-user Organisation, and is fetched from the login Context and + /// user party serivces + /// + [JsonPropertyName("partyId")] + public string PartyId { get; set; } = string.Empty; + + /// + /// The Organization Number for the end-user as it is stored in ER Registry + /// + [JsonPropertyName("reporteeOrgNo")] + public string ReporteeOrgNo { get; set; } = string.Empty; + + /// + /// Nice to have for debugging and logging. + /// + [JsonPropertyName("created")] + public System.DateTime Created { get; set; } = DateTime.UtcNow; + + /// + /// False by default, if a SystemUser is deleted in the API, + /// it is marked as IsDeleted ("tombstoned") rather than actually deleted + /// from the database. This is to avoid complications with cascade delete, + /// and the need to maintain consistent logging, and possible compliance rules. + /// + [JsonPropertyName("isDeleted")] + public bool IsDeleted { get; set; } = false; + + /// + /// The name of the Supplier of the Product used in this Integration. + /// In later phases, it will be possible to use non-supplier based Products, in which case the ClientId property should be filled out. + /// + [JsonPropertyName("supplierName")] + public string SupplierName { get; set; } = string.Empty; + + /// + /// The organization number for the Supplier of the Product + /// In later phases, it will be possible to use non-supplier based Products, in which case the ClientId property should be filled out. + /// + [JsonPropertyName("supplierOrgno")] + public string SupplierOrgNo { get; set; } = string.Empty; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizationRequestResource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizationRequestResource.cs new file mode 100644 index 00000000..05362aba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizationRequestResource.cs @@ -0,0 +1,33 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Model definition for a resource on an authorization request + /// + public class AuthorizationRequestResource + { + /// + /// Gets or sets The ServiceCode that request need + /// + public string ServiceCode { get; set; } + + /// + /// Gets or sets The ServiceEditionCode that request need + /// + public int ServiceEditionCode { get; set; } + + /// + /// Gets or sets The AltinnAppId that request need + /// + public string AltinnAppId { get; set; } + + /// + /// Gets or sets The OperationType that request need + /// + public List Operations { get; set; } + + /// + /// Gets or sets The Metadata that request need + /// + public Dictionary Metadata { get; set; } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedPartiesResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedPartiesResult.cs new file mode 100644 index 00000000..9321c5b5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedPartiesResult.cs @@ -0,0 +1,12 @@ +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Wrapper model for the response from a AuthorizedParties lookup request +/// +public class AuthorizedPartiesResult +{ + /// + /// The list of authorized parties + /// + public List AuthorizedParties { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedParty.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedParty.cs new file mode 100644 index 00000000..e01b5013 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/AuthorizedParty/AuthorizedParty.cs @@ -0,0 +1,203 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Model representing an authorized party, meaning a party for which a user has been authorized for one or more rights (either directly or through role(s), rightspackage +/// Used in new implementation of what has previously been named ReporteeList in Altinn 2. +/// +public class AuthorizedParty +{ + /// + /// Initializes a new instance of the class. + /// + public AuthorizedParty() + { + } + + /// + /// Initializes a new instance of the class based on a class. + /// + /// Party model from registry + /// Whether model should also build list of subunits if any exists + public AuthorizedParty(Party party, bool includeSubunits = true) + { + PartyId = party.PartyId; + PartyUuid = party.PartyUuid.Value; + Name = party.Name; + Type = (AuthorizedPartyType)party.PartyTypeName; + + if (Type == AuthorizedPartyType.Organization) + { + OrganizationNumber = party.OrgNumber; + UnitType = party.UnitType; + IsDeleted = party.IsDeleted; + OnlyHierarchyElementWithNoAccess = party.OnlyHierarchyElementWithNoAccess; + Subunits = includeSubunits ? party.ChildParties?.Select(subunit => new AuthorizedParty(subunit)).ToList() ?? [] : []; + } + else if (Type == AuthorizedPartyType.Person) + { + PersonId = party.SSN; + } + } + + /// + /// Initializes a new instance of the class based on a class. + /// + /// Authorized Party model from Altinn 2 SBL Bridge + /// Whether model should also build list of subunits if any exists + public AuthorizedParty(SblAuthorizedParty sblAuthorizedParty, bool includeSubunits = true) + { + PartyId = sblAuthorizedParty.PartyId; + PartyUuid = sblAuthorizedParty.PartyUuid.Value; + Name = sblAuthorizedParty.Name; + Type = (AuthorizedPartyType)sblAuthorizedParty.PartyTypeName; + AuthorizedRoles = sblAuthorizedParty.AuthorizedRoles; + + if (Type == AuthorizedPartyType.Organization) + { + OrganizationNumber = sblAuthorizedParty.OrgNumber; + UnitType = sblAuthorizedParty.UnitType; + IsDeleted = sblAuthorizedParty.IsDeleted; + OnlyHierarchyElementWithNoAccess = sblAuthorizedParty.OnlyHierarchyElementWithNoAccess; + Subunits = includeSubunits ? sblAuthorizedParty.ChildParties?.Select(subunit => new AuthorizedParty(subunit)).ToList() ?? [] : []; + } + else if (Type == AuthorizedPartyType.Person) + { + PersonId = sblAuthorizedParty.SSN; + } + } + + /// + /// Gets or sets the universally unique identifier of the party + /// + public Guid PartyUuid { get; set; } + + /// + /// Gets or sets the name of the party + /// + public string Name { get; set; } + + /// + /// Gets the organization number if the party is an organization + /// + public string OrganizationNumber { get; set; } + + /// + /// Gets the national identity number if the party is a person + /// + public string PersonId { get; set; } + + /// + /// Gets or sets the party id + /// + public int PartyId { get; set; } + + /// + /// Gets or sets the type of party + /// + public AuthorizedPartyType Type { get; set; } + + /// + /// Gets or sets the unit type if the party is an organization + /// + public string UnitType { get; set; } + + /// + /// Gets or sets whether this party is marked as deleted in the Central Coordinating Register for Legal Entities + /// + public bool IsDeleted { get; set; } + + /// + /// Gets or sets a value indicating whether the party is only included as a hierarchy element without any access. Meaning a main unit where the authorized subject only have access to one or more of the subunits. + /// + public bool OnlyHierarchyElementWithNoAccess { get; set; } + + /// + /// Gets or sets a collection of all resource identifier the authorized subject has some access to on behalf of this party + /// + public List AuthorizedResources { get; set; } = []; + + /// + /// Gets or sets a collection of all rolecodes for roles from either Enhetsregisteret or Altinn 2 which the authorized subject has been authorized for on behalf of this party + /// + public List AuthorizedRoles { get; set; } = []; + + /// + /// Gets or sets a set of subunits of this party, which the authorized subject also has some access to. + /// + public List Subunits { get; set; } = []; + + /// + /// Gets or sets a collection of all Authorized Instances + /// + public List AuthorizedInstances { get; set; } = []; + + /// + /// Enriches this authorized party and any subunits with a resource access + /// + /// The resource ID to add to the authorized party (and any subunits) list of authorized resources + public void EnrichWithResourceAccess(string resourceId) + { + resourceId = MapAppIdToResourceId(resourceId); + OnlyHierarchyElementWithNoAccess = false; + AuthorizedResources.Add(resourceId); + + if (Subunits != null) + { + foreach (var subunit in Subunits) + { + subunit.EnrichWithResourceAccess(resourceId); + } + } + } + + /// + /// Enriches this authorized party with a resource instance access + /// + /// The resource ID of the instance delegation to add to the authorized party + /// The instance ID of the instance delegation to add to the authorized party + public void EnrichWithResourceInstanceAccess(string resourceId, string instanceId) + { + // Ensure that we dont't add duplicates + if (AuthorizedInstances.Exists(instance => instance.InstanceId == instanceId && instance.ResourceId == resourceId)) + { + return; + } + + OnlyHierarchyElementWithNoAccess = false; + AuthorizedInstances.Add(new() + { + ResourceId = resourceId, + InstanceId = instanceId + }); + } + + private static string MapAppIdToResourceId(string altinnAppId) + { + string[] orgAppSplit = altinnAppId.Split('/'); + if (orgAppSplit.Length == 2) + { + return $"app_{orgAppSplit[0]}_{orgAppSplit[1]}"; + } + + return altinnAppId; + } + + /// + /// Composite Key instances + /// + public class AuthorizedResource + { + /// + /// Resource ID + /// + public string ResourceId { get; set; } + + /// + /// Instance ID + /// + public string InstanceId { get; set; } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/BaseAttribute.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/BaseAttribute.cs new file mode 100644 index 00000000..1cf0ba08 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/BaseAttribute.cs @@ -0,0 +1,64 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// This model describes a an Attribute consisting of an Attribute Type and Attribute Value which can also be represented as a Urn by combining the properties as '{type}:{value}' +/// It's used both for external API input/output but also internally for working with attributes and matching to XACML-attributes used in policies, indentifying for instance a resource, a user, a party or an action. +/// +public class BaseAttribute +{ + /// + /// Initializes a new instance of the class. + /// + public BaseAttribute() + { + } + + /// + /// Initializes a new instance of the class. + /// + public BaseAttribute(string type, string value) + { + Type = type; + Value = value; + Urn = $"{type}:{value}"; + } + + /// + /// Initializes a new instance of the class. + /// + public BaseAttribute(UuidType type, Guid value) : this(type.ToString(), value.ToString()) + { + } + + /// + /// Initializes a new instance of the class. + /// + public BaseAttribute(string urn) + { + int valuePos = urn.LastIndexOf(':') + 1; + Urn = urn; + Type = urn.Substring(0, valuePos - 1); + Value = urn.Substring(valuePos); + } + + /// + /// Gets or sets the attribute id for the match + /// + [JsonPropertyName("type")] + public string Type { get; set; } + + /// + /// Gets or sets the attribute value for the match + /// + [JsonPropertyName("value")] + public string Value { get; set; } + + /// + /// Gets or sets the attribute value for the match + /// + [JsonPropertyName("urn")] + public string Urn { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Delegation.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Delegation.cs new file mode 100644 index 00000000..243b052e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Delegation.cs @@ -0,0 +1,95 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// An enriched delegation model describing a delegation of a resource between two parties. Combines information from , + /// as well as Party information for both the offering and receiving parties. + /// + public class Delegation + { + /// + /// Gets or sets the party id of the party which have offered the delegation + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets the name of the party which have offered the delegation + /// + public string OfferedByName { get; set; } + + /// + /// Gets or sets the organization number of the party which have offered the delegation + /// + public string OfferedByOrganizationNumber { get; set; } + + /// + /// Gets or sets the party id of the party which have received the delegation + /// + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the name of the party which have received the delegation + /// + public string CoveredByName { get; set; } + + /// + /// Gets or sets the organization number of the party which have received the delegation + /// + public string CoveredByOrganizationNumber { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation + /// + [JsonPropertyName("performedbyuserid")] + public int? PerformedByUserId { get; set; } + + /// + /// Gets or sets the party id of the party that performed the delegation + /// + [JsonPropertyName("performedbypartyid")] + public int? PerformedByPartyId { get; set; } + + /// + /// Gets or sets the date and timestamp the delegation was performed + /// + public DateTime Created { get; set; } + + /// + /// Gets or sets the resource id of the resource registered in the resource registry which have been delegated + /// + public string ResourceId { get; set; } + + /// + /// Gets or sets the type of resource which have been delegated + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResourceType ResourceType { get; set; } + + /// + /// Dictionary of the title of resource in all registered languages + /// + public Dictionary ResourceTitle { get; set; } + + /// + /// List of reference values associated with the resource. This can be service codes from Altinn II, Delegation Scheme Id from Altinn II, Scopes from Maskinporten or just an external URL. + /// + public List ResourceReferences { get; set; } + + /// + /// HasCompetentAuthority + /// + public CompetentAuthority HasCompetentAuthority { get; set; } + + /// + /// Dictionary of the description of the resource in all registered languages + /// + public Dictionary Description { get; set; } + + /// + /// Dictionary of the delegation description of the resource in all registered languages. THe delegation description gives additional information about what the consequence and rights the recipient of a delegation will receive. + /// + public Dictionary RightDescription { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationActionResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationActionResult.cs new file mode 100644 index 00000000..ed76a390 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationActionResult.cs @@ -0,0 +1,23 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model for the result of a delegation or revoke of one or more rights between two parties. + /// + public class DelegationActionResult : ValidationErrorResult + { + /// + /// Gets or sets a set of attribute id and attribute value for the party offering rights + /// + public List From { get; set; } + + /// + /// Gets or sets a set of attribute id and attribute value for the party receiving rights + /// + public List To { get; set; } + + /// + /// Gets or sets a list of rights + /// + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChange.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChange.cs new file mode 100644 index 00000000..1b929f9a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChange.cs @@ -0,0 +1,126 @@ +#nullable enable +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a delegation change as stored in the Authorization postgre DelegationChanges table. + /// + public class DelegationChange + { + /// + /// Gets or sets the delegation change id + /// + [JsonPropertyName("delegationchangeid")] + public int DelegationChangeId { get; set; } + + /// + /// Gets or sets the resource registry delegation change id + /// + [JsonPropertyName("resourceregistrydelegationchangeid")] + public int ResourceRegistryDelegationChangeId { get; set; } + + /// + /// Gets or sets the delegation change type + /// + [JsonPropertyName("delegationchangetype")] + public DelegationChangeType DelegationChangeType { get; set; } + + /// + /// Gets or sets the resource id. + /// + [JsonPropertyName("resourceid")] + public string ResourceId { get; set; } = string.Empty; + + /// + /// Gets or sets the resourcetype. + /// + [JsonPropertyName("resourcetype")] + public string ResourceType { get; set; } = string.Empty; + + /// + /// Gets or sets the resource instance id. + /// + [JsonPropertyName("instanceid")] + public string? InstanceId { get; set; } + + /// + /// Gets or sets the offeredbypartyid, refering to the party id of the user or organization offering the delegation. + /// + [JsonPropertyName("offeredbypartyid")] + public int OfferedByPartyId { get; set; } + + /// + /// The uuid of the party the right is on behalf of + /// + public Guid? FromUuid { get; set; } + + /// + /// The type of party the right is on behalf of (Person, Organization, SystemUser) + /// + public UuidType FromUuidType { get; set; } + + /// + /// Gets or sets the coveredbypartyid, refering to the party id of the organization having received the delegation. Otherwise Null if the recipient is a user. + /// + [JsonPropertyName("coveredbypartyid")] + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the coveredbyuserid, refering to the user id of the user having received the delegation. Otherwise Null if the recipient is an organization. + /// + [JsonPropertyName("coveredbyuserid")] + public int? CoveredByUserId { get; set; } + + /// + /// The uuid of the party holding the right + /// + public Guid? ToUuid { get; set; } + + /// + /// The type of party holding the right + /// + public UuidType ToUuidType { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("performedbyuserid")] + public int? PerformedByUserId { get; set; } + + /// + /// Gets or sets the party id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("performedbypartyid")] + public int? PerformedByPartyId { get; set; } + + /// + /// The uuid of the party that performed the delegation + /// + public string? PerformedByUuid { get; set; } + + /// + /// The type of the party that performed the delegation + /// + public UuidType PerformedByUuidType { get; set; } + + /// + /// Gets or sets blobstoragepolicypath. + /// + [JsonPropertyName("blobstoragepolicypath")] + public string BlobStoragePolicyPath { get; set; } = string.Empty; + + /// + /// Gets or sets the blobstorage versionid + /// + [JsonPropertyName("blobstorageversionid")] + public string BlobStorageVersionId { get; set; } = string.Empty; + + /// + /// Gets or sets the created date and timestamp for the delegation change + /// + [JsonPropertyName("created")] + public DateTime? Created { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEvent.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEvent.cs new file mode 100644 index 00000000..7fd38a97 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEvent.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Internal model for a delegation change event used between Altinn.Platform.Authorization and this function app + /// + public class DelegationChangeEvent + { + /// + /// Gets or sets the type of the event. + /// + /// + /// The type of the event. + /// + [JsonPropertyName("e")] + public DelegationChangeEventType EventType { get; set; } + + /// + /// Gets or sets the delegation change. + /// + /// + /// The delegation change. + /// + [JsonPropertyName("d")] + public SimpleDelegationChange DelegationChange { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventList.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventList.cs new file mode 100644 index 00000000..230c1319 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventList.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// The internal wrapper model for expressing a list of delegation change events sent from Altinn.Platform.Authorization + /// + public class DelegationChangeEventList + { + /// + /// Gets or sets the delegation change events. + /// + /// + /// The delegation change events. + /// + [JsonPropertyName("l")] + public List DelegationChangeEvents { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventType.cs new file mode 100644 index 00000000..667bd950 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeEventType.cs @@ -0,0 +1,29 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// The type of delegation change event + /// + public enum DelegationChangeEventType + { + /// + /// Undefined default value + /// + // ReSharper disable UnusedMember.Global + Undefined = 0, + + /// + /// Grant event + /// + Grant = 1, + + /// + /// Revoke event + /// + Revoke = 2, + + /// + /// Revoke last right event + /// + RevokeLast = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeInput.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeInput.cs new file mode 100644 index 00000000..0186c398 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeInput.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Contains attribute match info about user, reportee, resource and resourceMatchType that's being used to check all delegation changes for the resource + /// + public class DelegationChangeInput + { + /// + /// Id and value of the subject getting delegation changes info + /// + [Required] + public AttributeMatch Subject { get; set; } + + /// + /// Id and value of party + /// + [Required] + public AttributeMatch Party { get; set; } + + /// + /// Gets the Resource's id + /// + [Required] + public List Resource { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeList.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeList.cs new file mode 100644 index 00000000..07e9e18d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeList.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model for the list of delegation changes for a resource/app that handles validation errors + /// + public class DelegationChangeList : ValidationErrorResult + { + /// + /// The list of delegation changes for a resource/app + /// + public List DelegationChanges { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeType.cs new file mode 100644 index 00000000..be0b1bc9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationChangeType.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// The type of delegation change + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum DelegationChangeType + { + /// + /// Undefined default value + /// + // ReSharper disable UnusedMember.Global + Undefined = 0, + + /// + /// Grant event + /// + Grant = 1, + + /// + /// Revoke event + /// + Revoke = 2, + + /// + /// Revoke last right event + /// + RevokeLast = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationCheckResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationCheckResponse.cs new file mode 100644 index 00000000..3bd569af --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationCheckResponse.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model for the result of a delegation status check, for which rights a user is able to delegate between two parties. + /// + public class DelegationCheckResponse : ValidationErrorResult + { + /// + /// Gets or sets a set of attribute id and attribute value for the party offering rights + /// + public List From { get; set; } + + /// + /// Gets or sets a list of right delegation status models + /// + public List RightDelegationCheckResults { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationLookup.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationLookup.cs new file mode 100644 index 00000000..46c9ffc4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationLookup.cs @@ -0,0 +1,23 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Model for looking up, identify or represent a delegation of one or more rights delegated from one party/organization/user to another party/organization/user + /// + public class DelegationLookup + { + /// + /// Gets or sets a set of attribute id and attribute value for the party offering rights + /// + public List From { get; set; } + + /// + /// Gets or sets a set of attribute id and attribute value for the party receiving rights + /// + public List To { get; set; } + + /// + /// Gets or sets a list of rights + /// + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationRequest.cs new file mode 100644 index 00000000..a29c8748 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/DelegationRequest.cs @@ -0,0 +1,113 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This element describe a public class DelegationRequest + /// + [DataContract] + public class DelegationRequest + { + /// + /// Gets or sets the Guid of a valid DelegationRequest + /// + public Guid Guid { get; set; } + + /// + /// Gets or sets the status of an AuthorizationRequest + /// + public RestAuthorizationRequestStatus RequestStatus { get; set; } + + /// + /// Gets or sets The OrgID/personalID for who gets the delegation when the delegationRequest is approved + /// + [DataMember(IsRequired = true)] + public string CoveredBy { get; set; } + + /// + /// Gets or sets The OrgID/personalID for who gets the delegation when the delegationRequest is approved + /// + [DataMember(IsRequired = true)] + public string CoveredByName { get; set; } + + /// + /// Gets or sets The personalID who offer the delegation + /// + [DataMember(IsRequired = true)] + public string OfferedBy { get; set; } + + /// + /// Gets or sets The name who offer the delegation + /// + [DataMember(IsRequired = true)] + public string OfferedByName { get; set; } + + /// + /// Gets or sets The RedirectUrl is a link that sends the user back to the external website after he/she made an operation in Altinn + /// + [DataMember] + public string RedirectUrl { get; set; } + + /// + /// Gets or sets the RequestMessage if any + /// + [DataMember(IsRequired = false, EmitDefaultValue = false)] + public string RequestMessage { get; set; } + + /// + /// Gets or sets a value indicating whether the session should be kept alive after a redirect + /// + [DataMember(IsRequired = false, EmitDefaultValue = false)] + public bool KeepSessionAlive { get; set; } + + /// + /// Gets or sets the date of when the request was created + /// + [DataMember] + public DateTime Created { get; set; } + + /// + /// Gets or sets the date of when the request was last changed + /// + [DataMember] + public DateTime LastChanged { get; set; } + + /// + /// Gets or sets The RequestServices are all information of services which the DelegationRequest need + /// + [DataMember(IsRequired = true)] + public List RequestResources { get; set; } + } + + /// + /// Represents a list of DelegationRequests + /// + public class DelegationRequests : List + { + /// + /// Initializes a new instance of the class. + /// + public DelegationRequests() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// List of consents + public DelegationRequests(List list) : base(list) + { + } + + /// + /// Gets or sets the Continuation Token used for pagination and + /// sequential retrieval. The returned value consists of the + /// lastChanged timestamp of the last consent element returned and the + /// ID. When this token is sent as an argument in the continue + /// parameter, the request will limit the responses only to consents + /// that are changed after this time. The ID will prevent endless + /// loops if many elements have the same timestamp. + /// + public string ContinuationToken { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Detail.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Detail.cs new file mode 100644 index 00000000..4fd64868 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Detail.cs @@ -0,0 +1,26 @@ +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a detail while providing a specific code for identifying a specific recurring detail and parameters needed for context and understanding. + /// Can be extended for specific detailing/metadata/informational purposes. + /// + public class Detail + { + /// + /// Gets or sets the detail identifier code + /// + public DetailCode Code { get; set; } + + /// + /// Gets or sets a human readable (english) description of the detail + /// + public string Description { get; set; } + + /// + /// Gets or sets a dictionary of parameters which is related to the detail code and description + /// + public Dictionary> Parameters { get; set; } = new Dictionary>(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChange.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChange.cs new file mode 100644 index 00000000..89cb95f2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChange.cs @@ -0,0 +1,94 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// InstanceDelegationChange + /// + public class InstanceDelegationChange + { + /// + /// Gets or sets the instance delegation change id + /// + [JsonPropertyName("instancedelegationchangeid")] + public int InstanceDelegationChangeId { get; set; } + + /// + /// Gets or sets the DelegationChangeType. + /// + public DelegationChangeType DelegationChangeType { get; set; } + + /// + /// Gets or sets the InstanceDelegationType. + /// + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// Gets or sets the resource. + /// + [JsonPropertyName("resource")] + public string ResourceId { get; set; } + + /// + /// Gets or sets the instance. + /// + [JsonPropertyName("instance")] + public string InstanceId { get; set; } + + /// + /// The uuid of the party the right is on behalf of + /// + [JsonPropertyName("from")] + public Guid FromUuid { get; set; } + + /// + /// The type of party the right is on behalf of (Person, Organization, SystemUser) + /// + [JsonPropertyName("fromtype")] + public UuidType FromUuidType { get; set; } + + /// + /// The uuid of the party holding the right + /// + [JsonPropertyName("to")] + public Guid ToUuid { get; set; } + + /// + /// The type of party holding the right + /// + [JsonPropertyName("totype")] + public UuidType ToUuidType { get; set; } + + /// + /// The uuid of the party that performed the delegation + /// + [JsonPropertyName("performedby")] + public string PerformedBy { get; set; } + + /// + /// The type of the party that performed the delegation + /// + [JsonPropertyName("performedbytype")] + public UuidType PerformedByType { get; set; } + + /// + /// Gets or sets blobstoragepolicypath. + /// + [JsonPropertyName("blobstoragepolicypath")] + public string BlobStoragePolicyPath { get; set; } = string.Empty; + + /// + /// Gets or sets the blobstorage versionid + /// + [JsonPropertyName("blobstorageversionid")] + public string BlobStorageVersionId { get; set; } = string.Empty; + + /// + /// Gets or sets the created date and timestamp for the delegation change + /// + [JsonPropertyName("created")] + public DateTime? Created { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChangeRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChangeRequest.cs new file mode 100644 index 00000000..44ac6246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceDelegationChangeRequest.cs @@ -0,0 +1,52 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// DTO for sending a instance delegation request internaly +/// +public class InstanceDelegationChangeRequest +{ + /// + /// Gets or sets the resource. + /// + [JsonPropertyName("resource")] + public string Resource { get; set; } + + /// + /// Gets or sets the instance. + /// + [JsonPropertyName("instance")] + public string Instance { get; set; } + + /// + /// Gets or sets the InstanceDelegationType. + /// + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// The uuid of the party the right is on behalf of + /// + [JsonPropertyName("from")] + public Guid FromUuid { get; set; } + + /// + /// The type of party the right is on behalf of (Person, Organization, SystemUser) + /// + [JsonPropertyName("fromtype")] + public UuidType FromType { get; set; } + + /// + /// The uuid of the party holding the right + /// + [JsonPropertyName("to")] + public Guid ToUuid { get; set; } + + /// + /// The type of party holding the right + /// + [JsonPropertyName("totype")] + public UuidType ToType { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRight.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRight.cs new file mode 100644 index 00000000..ed42baa4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRight.cs @@ -0,0 +1,73 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// DTO to send instance delegation to Authorization Administration point +/// +public class InstanceRight +{ + /// + /// Constructor setting the list of rules to a list ready to add data to + /// + public InstanceRight() + { + InstanceRules = []; + } + + /// + /// Uuid of the receiver of the right + /// + public Guid ToUuid { get; set; } + + /// + /// The type of receiver of the right + /// + public UuidType ToType { get; set; } + + /// + /// The uuid of the party the right is for + /// + public Guid FromUuid { get; set; } + + /// + /// The type of the party the right is for + /// + public UuidType FromType { get; set; } + + /// + /// The identficator of the party performing the delegation + /// + public string PerformedBy { get; set; } + + /// + /// The type of the party performing the delegation + /// + public UuidType PerformedByType { get; set; } + + /// + /// The resourceId of the delegating rule + /// + public string ResourceId { get; set; } + + /// + /// The urn for this instance + /// + public string InstanceId { get; set; } + + /// + /// The mode of delegation for now Parallel Signing and normal + /// + public InstanceDelegationMode InstanceDelegationMode { get; set; } + + /// + /// The source of delegation for now app or user + /// + public InstanceDelegationSource InstanceDelegationSource { get; set; } + + /// + /// List of rule specific data not shared between the difrent rules + /// + public List InstanceRules { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightDelegationResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightDelegationResult.cs new file mode 100644 index 00000000..3fbbf8fd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightDelegationResult.cs @@ -0,0 +1,26 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// This model describes a single right +/// +public class InstanceRightDelegationResult +{ + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully delegated or not + /// + public DelegationStatus Status { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightRevokeResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightRevokeResult.cs new file mode 100644 index 00000000..6b167e9b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRightRevokeResult.cs @@ -0,0 +1,26 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// This model describes a single right +/// +public class InstanceRightRevokeResult +{ + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully revoked or not + /// + public RevokeStatus Status { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRule.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRule.cs new file mode 100644 index 00000000..9a946617 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/InstanceRule.cs @@ -0,0 +1,30 @@ +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// DTO for delegation rules +/// +public class InstanceRule +{ + /// + /// Gets or sets the unique identifier for a specific rule within a policy (Output only). + /// + public string RuleId { get; set; } + + /// + /// The resource delegating for + /// + public List Resource { get; set; } + + /// + /// The action to delegate + /// + public ActionUrn Action { get; set; } + + /// + /// Flag identifying if this instance rule was created successfully + /// + public bool CreatedSuccessfully { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ListObjectResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ListObjectResult.cs new file mode 100644 index 00000000..d199eb5b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ListObjectResult.cs @@ -0,0 +1,23 @@ +#nullable enable + +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// A list object is a wrapper around a list of items to allow for the API to be +/// extended in the future without breaking backwards compatibility. +/// +public abstract record ListObjectResult +{ +} + +/// +/// A concrete list object. +/// +/// The item type. +/// The items. +public record ListObjectResult( + [property: JsonPropertyName("data")] + IEnumerable Items) + : ListObjectResult; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/OperationTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/OperationTypeExternal.cs new file mode 100644 index 00000000..a6e183ee --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/OperationTypeExternal.cs @@ -0,0 +1,36 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Enum definition of the AltinnII external operation types + /// + public enum OperationTypeExternal + { + /// + /// Operation type is Read operation in ServiceEngine database + /// + [EnumMember] + Read, + + /// + /// Operation Type is Write in ServiceEngine database. + /// This represents Create, FillIn, SendIn, SendBack and Delete actions. + /// + [EnumMember] + Write, + + /// + /// Operation Type is Sign in ServiceEngine database . + /// + [EnumMember] + Sign, + + /// + /// Operation used for Link services (at least for now) which are external services + /// which only require a single general operation + /// + [EnumMember] + Access + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PaginatedResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PaginatedResult.cs new file mode 100644 index 00000000..4d31fde7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PaginatedResult.cs @@ -0,0 +1,39 @@ +#nullable enable + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// A paginated . +/// +public static class PaginatedResult +{ + /// + /// Create a new . + /// + /// The type of items + /// The items + /// The optional next-link + /// A new . + public static PaginatedResult Create( + IEnumerable items, + string? next) + => new(new(next), items); +} + +/// +/// A paginated . +/// +/// The item type. +/// Pagination links. +/// The items. +public record PaginatedResult( + PaginatedResultLinks Links, + IEnumerable Items) + : ListObjectResult(Items); + +/// +/// Pagination links. +/// +/// Link to the next page of items (if any). +public record PaginatedResultLinks( + string? Next); diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyAttributeMatch.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyAttributeMatch.cs new file mode 100644 index 00000000..a97e5aaa --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyAttributeMatch.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model extends the AttributeMatch model with a boolean value indicating whether the ABAC found a match for the attribute + /// + public class PolicyAttributeMatch : AttributeMatch + { + /// + /// Gets or sets a value indicating whether the ABAC found a match for the attribute + /// + [Required] + public bool? MatchFound { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyMatch.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyMatch.cs new file mode 100644 index 00000000..c14b1ef9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyMatch.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a single rule in a delegated policy + /// + public class PolicyMatch + { + /// + /// Gets or sets the unique identifier for a specific party for which the requested rule in the policy applies + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets resource match which uniquely identifies the resource this policy applies to. + /// + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the coveredby id + /// + [Required] + public List CoveredBy { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyParameters.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyParameters.cs new file mode 100644 index 00000000..bac57198 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyParameters.cs @@ -0,0 +1,47 @@ +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Conteiner for parameters used to build policy files and rules +/// +public class PolicyParameters +{ + /// + /// ResourceId as a string + /// + public string ResourceId { get; set; } + + /// + /// Instance id as a string + /// + public string InstanceId { get; set; } + + /// + /// From type as urn string + /// + public string FromType { get; set; } + + /// + /// from uuid as string + /// + public string FromId { get; set; } + + /// + /// to type urn string + /// + public string ToType { get; set; } + + /// + /// to uuid as string + /// + public string ToId { get; set; } + + /// + /// performed by uuid as string + /// + public string PerformedById { get; set; } + + /// + /// performed by type urn string + /// + public string PerformedByType { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyWriteOutput.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyWriteOutput.cs new file mode 100644 index 00000000..4f69fd5c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/PolicyWriteOutput.cs @@ -0,0 +1,40 @@ +using Altinn.AccessManagement.Core.Repositories.Interfaces; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Conteiner holding the data required for DB update from a written policy file + /// + public class PolicyWriteOutput + { + /// + /// The path the policy is written to + /// + public string PolicyPath { get; set; } + + /// + /// The Version id of the written Policy file + /// + public string VersionId { get; set; } + + /// + /// The LeaseId for the policy lease + /// + public string LeaseId { get; set; } + + /// + /// The delegation change type used to + /// + public DelegationChangeType ChangeType { get; set; } + + /// + /// The client to handle the policy file + /// + public IPolicyRepository PolicyClient { get; set; } + + /// + /// The rules corresponding to this policy file + /// + public InstanceRight Rules { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Profile/UserProfileLookup.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Profile/UserProfileLookup.cs new file mode 100644 index 00000000..690b0bab --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Profile/UserProfileLookup.cs @@ -0,0 +1,34 @@ +#nullable enable + +namespace Altinn.AccessManagement.Core.Models.Profile +{ + /// + /// Input model for internal UserProfile lookup requests, where one of the lookup identifiers available must be set for performing the lookup request: + /// UserId (from Altinn 2 Authn UserProfile) + /// Username (from Altinn 2 Authn UserProfile) + /// SSN/Dnr (from Freg) + /// Uuid (from Altinn 2 Party/UserProfile implementation will be added later) + /// + public class UserProfileLookup + { + /// + /// Gets or sets the users UserId if the lookup is to be performed based on this identifier + /// + public int UserId { get; set; } + + /// + /// Gets or sets the users Username if the lookup is to be performed based on this identifier + /// + public string? Username { get; set; } + + /// + /// Gets or sets the users social security number or d-number from Folkeregisteret if the lookup is to be performed based on this identifier + /// + public string? Ssn { get; set; } + + /// + /// Gets or sets the user uuid if the lookup is to be performed based on this identifier + /// + public Guid? UserUuid { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/OrganizationNumber.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/OrganizationNumber.cs new file mode 100644 index 00000000..e72a9644 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/OrganizationNumber.cs @@ -0,0 +1,133 @@ +#nullable enable + +using System.Buffers; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.Swashbuckle.Examples; + +namespace Altinn.AccessManagement.Core.Models.Register; + +/// +/// A organization number (a string of 9 digits). +/// +[JsonConverter(typeof(OrganizationNumber.JsonConverter))] +public class OrganizationNumber : ISpanParsable, + ISpanFormattable, + IExampleDataProvider +{ + private static readonly SearchValues NUMBERS = SearchValues.Create(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']); + + private readonly string _value; + + private OrganizationNumber(string value) + { + _value = value; + } + + /// + /// Creates a new from the specified value without validation. + /// + /// The organization identifier. + /// A . + public static OrganizationNumber CreateUnchecked(string value) + => new(value); + + /// + public static IEnumerable? GetExamples(ExampleDataOptions options) + { + yield return new OrganizationNumber("987654321"); + yield return new OrganizationNumber("123456789"); + } + + /// + public static OrganizationNumber Parse(string s) + => Parse(s, provider: null); + + /// + public static OrganizationNumber Parse(string s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid organization number"); + + /// + public static OrganizationNumber Parse(ReadOnlySpan s) + => Parse(s, provider: null); + + /// + public static OrganizationNumber Parse(ReadOnlySpan s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid organization number"); + + /// + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out OrganizationNumber result) + => TryParse(s.AsSpan(), s, out result); + + /// + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out OrganizationNumber result) + => TryParse(s, original: null, out result); + + private static bool TryParse(ReadOnlySpan s, string? original, [MaybeNullWhen(false)] out OrganizationNumber result) + { + if (s.Length != 9) + { + result = null; + return false; + } + + if (s.ContainsAnyExcept(NUMBERS)) + { + result = null; + return false; + } + + result = new OrganizationNumber(original ?? new string(s)); + return true; + } + + /// + public override string ToString() + => _value; + + /// + public string ToString(string? format) + => _value; + + /// + public string ToString(string? format, IFormatProvider? formatProvider) + => _value; + + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + if (destination.Length < _value.Length) + { + charsWritten = 0; + return false; + } + + _value.AsSpan().CopyTo(destination); + charsWritten = _value.Length; + return true; + } + + private sealed class JsonConverter : JsonConverter + { + public override OrganizationNumber? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var str = reader.GetString(); + if (!TryParse(str, null, out var result)) + { + throw new JsonException("Invalid organization number"); + } + + return result; + } + + public override void Write(Utf8JsonWriter writer, OrganizationNumber value, JsonSerializerOptions options) + { + writer.WriteStringValue(value._value); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/PartyUrn.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/PartyUrn.cs new file mode 100644 index 00000000..cd4a6b30 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Register/PartyUrn.cs @@ -0,0 +1,28 @@ +#nullable enable + +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models.Register; + +/// +/// A unique reference to a party in the form of an URN. +/// +[KeyValueUrn] +public abstract partial record PartyUrn +{ + /// + /// Try to get the urn as a party uuid. + /// + /// The resulting party uuid. + /// if this party reference is a party uuid, otherwise . + [UrnKey("altinn:party:uuid")] + public partial bool IsPartyUuid(out Guid partyUuid); + + /// + /// Try to get the urn as an organization number. + /// + /// The resulting organization number. + /// if this party reference is an organization number, otherwise . + [UrnKey("altinn:organization:identifier-no")] + public partial bool IsOrganizationIdentifier(out OrganizationNumber organizationNumber); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RequestToDelete.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RequestToDelete.cs new file mode 100644 index 00000000..82871e0f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RequestToDelete.cs @@ -0,0 +1,127 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Helpers; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a list of rules to delete from a single policyfile + /// + public class RequestToDelete : IValidatableObject + { + /// + /// Gets or sets a list of unique identifier for specific rules within a policy. + /// + public List RuleIds { get; set; } + + /// + /// Gets or sets the user id of the user who performed the deletion. + /// + [Required] + public int DeletedByUserId { get; set; } + + /// + /// Gets or sets the policy to delete from + /// + [Required] + public PolicyMatch PolicyMatch { get; set; } + + /// + /// Method validating the model + /// + /// The context to validate for + /// + public IEnumerable Validate(ValidationContext validationContext) + { + List validationResult = new List(); + + if (this.DeletedByUserId == 0) + { + validationResult.Add(new ValidationResult("Not all RequestToDelete has a value for the user performing the delete")); + } + + return validationResult; + } + } + + /// + /// Class to wrap a list of RequestToDelete + /// + public class RequestToDeleteRuleList : List, IValidatableObject + { + /// + /// Method validating the model + /// + /// The context to validate for + /// + public IEnumerable Validate(ValidationContext validationContext) + { + List validationResult = new List(); + + if (this.Count < 1) + { + validationResult.Add(new ValidationResult("Missing rulesToDelete in body")); + return validationResult; + } + + if (this.Any(r => r.RuleIds == null || r.RuleIds.Count == 0)) + { + validationResult.Add(new ValidationResult("Not all RequestToDelete has RuleId")); + return validationResult; + } + + try + { + if (this.GroupBy(x => PolicyHelper.GetAltinnAppDelegationPolicyPath(x.PolicyMatch)).Any(g => g.Count() > 1)) + { + validationResult.Add(new ValidationResult("Input should not contain any duplicate policies")); + return validationResult; + } + } + catch + { + validationResult.Add(new ValidationResult("Not all requests to delete contains valid policy paths")); + return validationResult; + } + + return validationResult; + } + } + + /// + /// Class to wrap a list of RequestToDelete + /// + public class RequestToDeletePolicyList : List, IValidatableObject + { + /// + /// Method validating the model + /// + /// The context to validate for + /// + public IEnumerable Validate(ValidationContext validationContext) + { + List validationResult = new List(); + + if (this.Count < 1) + { + validationResult.Add(new ValidationResult("Missing policiesToDelete in body")); + return validationResult; + } + + try + { + if (this.GroupBy(x => PolicyHelper.GetAltinnAppDelegationPolicyPath(x.PolicyMatch)).Any(g => g.Count() > 1)) + { + validationResult.Add(new ValidationResult("Input should not contain any duplicate policies")); + return validationResult; + } + } + catch + { + validationResult.Add(new ValidationResult("Not all requests to delete contains valid policy paths")); + return validationResult; + } + + return validationResult; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceAction.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceAction.cs new file mode 100644 index 00000000..81704747 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceAction.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes an action that may be used in a rule describing a right. + /// + public class ResourceAction + { + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the specific action, from the original app policy + /// + [Required] + public AttributeMatch Match { get; set; } + + /// + /// Gets or sets a title for the action + /// + public string Title { get; set; } + + /// + /// Gets or sets a description of the action. + /// + public string Description { get; set; } + + /// + /// Gets or sets which roles are granted access to this action on this resource + /// + public List RoleGrants { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckRequest.cs new file mode 100644 index 00000000..00b53b16 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckRequest.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Request model for a list of all delegable rights for a specific resource. +/// +public class ResourceDelegationCheckRequest +{ + /// + /// Gets or sets the urn for identifying the resource of the rights to be checked + /// + [Required] + public ResourceIdUrn ResourceId { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckResponse.cs new file mode 100644 index 00000000..8ea1cebb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceDelegationCheckResponse.cs @@ -0,0 +1,19 @@ +using Altinn.AccessManagement.Core.Models.Register; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Response model for the result of a delegation status check, for which rights a user is able to delegate between two parties. +/// +public class ResourceDelegationCheckResponse +{ + /// + /// Gets or sets the urn identifying the party the rights can be delegated from + /// + public required PartyUrn From { get; set; } + + /// + /// Gets or sets a list of right delegation status models + /// + public List ResourceRightDelegationCheckResults { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourcePolicy.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourcePolicy.cs new file mode 100644 index 00000000..af884d48 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourcePolicy.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes the actions that can be performed for a particular resource + /// + public class ResourcePolicy + { + /// + /// Gets or sets a description of the resource policy. + /// + public string Description { get; set; } + + /// + /// Gets or sets a title for the resource policy to be used for displaying the resource in AltinnII. + /// + public string Title { get; set; } + + /// + /// Gets or sets the actions associcated with this particular resource including which roles have been granted access to it + /// + public List Actions { get; set; } + + /// + /// Gets or sets the list of resource matches which together uniquely identifies the resource in the app policy, e.g. org, app and/or tasks, events etc. + /// + [Required] + public List Resource { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/CompetentAuthority.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/CompetentAuthority.cs new file mode 100644 index 00000000..b48b93bc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/CompetentAuthority.cs @@ -0,0 +1,23 @@ +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model representation of Competent Authority part of the ServiceResource model + /// + public class CompetentAuthority + { + /// + /// The organization number + /// + public string Organization { get; set; } + + /// + /// The organization code + /// + public string Orgcode { get; set; } + + /// + /// The organization name. If not set it will be retrived from register based on Organization number + /// + public Dictionary Name { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ContactPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ContactPoint.cs new file mode 100644 index 00000000..f2c18947 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ContactPoint.cs @@ -0,0 +1,28 @@ +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Defines a contact point + /// + public class ContactPoint + { + /// + /// The type of contact point, phone, email ++ + /// + public string Category { get; set; } + + /// + /// The contact details. The actual phone number, email adress + /// + public string Email { get; set; } + + /// + /// Phone details + /// + public string Telephone { get; set; } + + /// + /// Contact page + /// + public string ContactPage { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/Keyword.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/Keyword.cs new file mode 100644 index 00000000..e6023efb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/Keyword.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model for defining keywords + /// + public class Keyword + { + /// + /// The key word + /// + public string Word { get; set; } + + /// + /// Language of the key word + /// + public string Language { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdUrn.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdUrn.cs new file mode 100644 index 00000000..bb8fd06d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdUrn.cs @@ -0,0 +1,20 @@ +#nullable enable + +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry; + +/// +/// A unique reference to a resource in the form of an URN. +/// +[KeyValueUrn] +public abstract partial record ResourceIdUrn +{ + /// + /// Try to get the urn as a resource id. + /// + /// The resulting resource id. + /// if this resource reference is a resource id, otherwise . + [UrnKey("altinn:resource")] + public partial bool IsResourceId(out ResourceIdentifier resourceId); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdentifier.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdentifier.cs new file mode 100644 index 00000000..cfdb7858 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceIdentifier.cs @@ -0,0 +1,130 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.Swashbuckle.Examples; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry; + +/// +/// A valid resource identifier. +/// +[JsonConverter(typeof(JsonConverter))] +[DebuggerDisplay("{_value}")] +public sealed record ResourceIdentifier + : ISpanParsable, + ISpanFormattable, + IExampleDataProvider +{ + private readonly string _value; + + private ResourceIdentifier(string value) + { + _value = value; + } + + /// + public static IEnumerable? GetExamples(ExampleDataOptions options) + { + yield return new ResourceIdentifier("example-resourceid"); + yield return new ResourceIdentifier("app_skd_flyttemelding"); + } + + /// + /// Creates a new from the specified value without validation. + /// + /// The resource identifier. + /// A . + public static ResourceIdentifier CreateUnchecked(string value) + => new(value); + + /// + public static ResourceIdentifier Parse(string s) + => Parse(s, provider: null); + + /// + public static ResourceIdentifier Parse(string s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid resource identifier"); + + /// + public static ResourceIdentifier Parse(ReadOnlySpan s) + => Parse(s, provider: null); + + /// + public static ResourceIdentifier Parse(ReadOnlySpan s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid resource identifier"); + + /// + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out ResourceIdentifier result) + => TryParse(s.AsSpan(), s, out result); + + /// + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out ResourceIdentifier result) + => TryParse(s, original: null, out result); + + private static bool TryParse(ReadOnlySpan s, string? original, [MaybeNullWhen(false)] out ResourceIdentifier result) + { + if (!ServiceResourceHelper.ResourceIdentifierRegex().IsMatch(s)) + { + result = null; + return false; + } + + result = new ResourceIdentifier(original ?? new string(s)); + return true; + } + + /// + public override string ToString() + => _value; + + /// + public string ToString(string? format) + => _value; + + /// + public string ToString(string? format, IFormatProvider? formatProvider) + => _value; + + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + if (destination.Length < _value.Length) + { + charsWritten = 0; + return false; + } + + _value.AsSpan().CopyTo(destination); + charsWritten = _value.Length; + return true; + } + + private sealed class JsonConverter : JsonConverter + { + public override ResourceIdentifier? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var str = reader.GetString(); + if (!TryParse(str, null, out var result)) + { + throw new JsonException("Invalid resource identifier"); + } + + return result; + } + + public override void Write(Utf8JsonWriter writer, ResourceIdentifier value, JsonSerializerOptions options) + { + writer.WriteStringValue(value._value); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceIdentifier.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceIdentifier.cs new file mode 100644 index 00000000..18aa432f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceIdentifier.cs @@ -0,0 +1,123 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.Swashbuckle.Examples; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry; + +/// +/// A valid resource identifier. +/// +[JsonConverter(typeof(JsonConverter))] +[DebuggerDisplay("{_value}")] +public sealed record ResourceInstanceIdentifier + : ISpanParsable, + ISpanFormattable, + IExampleDataProvider +{ + private readonly string _value; + + private ResourceInstanceIdentifier(string value) + { + _value = value; + } + + /// + public static IEnumerable? GetExamples(ExampleDataOptions options) + { + yield return new ResourceInstanceIdentifier("0191579e-72bc-7977-af5d-f9e92af4393b"); + yield return new ResourceInstanceIdentifier("ext_1337"); + } + + /// + /// Creates a new from the specified value without validation. + /// + /// The resource instance identifier. + /// A . + public static ResourceInstanceIdentifier CreateUnchecked(string value) + => new(value); + + /// + public static ResourceInstanceIdentifier Parse(string s) + => Parse(s, provider: null); + + /// + public static ResourceInstanceIdentifier Parse(string s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid resource instance identifier"); + + /// + public static ResourceInstanceIdentifier Parse(ReadOnlySpan s) + => Parse(s, provider: null); + + /// + public static ResourceInstanceIdentifier Parse(ReadOnlySpan s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid resource instance identifier"); + + /// + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out ResourceInstanceIdentifier result) + => TryParse(s.AsSpan(), s, out result); + + /// + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out ResourceInstanceIdentifier result) + => TryParse(s, original: null, out result); + + private static bool TryParse(ReadOnlySpan s, string? original, [MaybeNullWhen(false)] out ResourceInstanceIdentifier result) + { + result = new ResourceInstanceIdentifier(original ?? new string(s)); + return true; + } + + /// + public override string ToString() + => _value; + + /// + public string ToString(string? format) + => _value; + + /// + public string ToString(string? format, IFormatProvider? formatProvider) + => _value; + + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + if (destination.Length < _value.Length) + { + charsWritten = 0; + return false; + } + + _value.AsSpan().CopyTo(destination); + charsWritten = _value.Length; + return true; + } + + private sealed class JsonConverter : JsonConverter + { + public override ResourceInstanceIdentifier? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var str = reader.GetString(); + if (!TryParse(str, null, out var result)) + { + throw new JsonException("Invalid resource instance identifier"); + } + + return result; + } + + public override void Write(Utf8JsonWriter writer, ResourceInstanceIdentifier value, JsonSerializerOptions options) + { + writer.WriteStringValue(value._value); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceUrn.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceUrn.cs new file mode 100644 index 00000000..746c84c7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceInstanceUrn.cs @@ -0,0 +1,20 @@ +#nullable enable + +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry; + +/// +/// A unique reference to a resource instance in the form of an URN. +/// +[KeyValueUrn] +public abstract partial record ResourceInstanceUrn +{ + /// + /// Try to get the urn as a resource instance id. + /// + /// The resulting resource instance id. + /// if this resource instance reference is a resource instance id, otherwise . + [UrnKey("altinn:resource:instance-id")] + public partial bool IsResourceInstanceId(out ResourceInstanceIdentifier resourceId); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceReference.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceReference.cs new file mode 100644 index 00000000..2bfcf246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceReference.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model representation of the resource reference part of the ServiceResource model + /// + public class ResourceReference + { + /// + /// The source the reference identifier points to + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ReferenceSource? ReferenceSource { get; set; } + + /// + /// The reference identifier + /// + public string Reference { get; set; } + + /// + /// The reference type + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ReferenceType? ReferenceType { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceSearch.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceSearch.cs new file mode 100644 index 00000000..8ae3cc45 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ResourceSearch.cs @@ -0,0 +1,33 @@ +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model for performing search for resources in the resource registry + /// + public class ResourceSearch + { + /// + /// ID + /// + public string Id { get; set; } + + /// + /// Title + /// + public string Title { get; set; } + + /// + /// Description + /// + public string Description { get; set; } + + /// + /// ResourceType + /// + public ResourceType? ResourceType { get; set; } + + /// + /// Keywords + /// + public string Keyword { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ServiceResource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ServiceResource.cs new file mode 100644 index 00000000..47f43d0c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/ServiceResource.cs @@ -0,0 +1,134 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Enums.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model describing a complete resource from the resource registry. + /// + public class ServiceResource + { + /// + /// The identifier of the resource + /// + public string Identifier { get; set; } + + /// + /// The title of service + /// + public Dictionary Title { get; set; } + + /// + /// Description + /// + public Dictionary Description { get; set; } + + /// + /// Description explaining the rights a recipient will receive if given access to the resource + /// + public Dictionary RightDescription { get; set; } + + /// + /// The homepage + /// + public string Homepage { get; set; } + + /// + /// The status + /// + public string Status { get; set; } + + /// + /// spatial coverage + /// This property represents that area(s) a Public Service is likely to be available only within, typically the area(s) covered by a particular public authority. + /// + public List Spatial { get; set; } + + /// + /// List of possible contact points + /// + public List ContactPoints { get; set; } + + /// + /// Linkes to the outcome of a public service + /// + public List Produces { get; set; } + + /// + /// IsPartOf + /// + public string IsPartOf { get; set; } + + /// + /// ThematicAreas + /// + public List ThematicAreas { get; set; } + + /// + /// ResourceReference + /// + public List ResourceReferences { get; set; } + + /// + /// Is this resource possible to delegate to others or not + /// + public bool Delegable { get; set; } = true; + + /// + /// The visibility of the resource + /// + public bool Visible { get; set; } = true; + + /// + /// HasCompetentAuthority + /// + public CompetentAuthority HasCompetentAuthority { get; set; } + + /// + /// Keywords + /// + public List Keywords { get; set; } + + /// + /// Sets the access list mode for the resource + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResourceAccessListMode AccessListMode { get; set; } + + /// + /// The user acting on behalf of party can be a selfidentifed users + /// + public bool SelfIdentifiedUserEnabled { get; set; } + + /// + /// The user acting on behalf of party can be an enterprise users + /// + public bool EnterpriseUserEnabled { get; set; } + + /// + /// ResourceType + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResourceType ResourceType { get; set; } + + /// + /// Available for type defines which type of entity / person that resource targets + /// + public List AvailableForType { get; set; } + + /// + /// List of autorizationReference attributes to reference this resource in authorization API + /// + public List AuthorizationReference { get; set; } + + /// + /// Writes key information when this object is written to Log. + /// + /// + public override string ToString() + { + return $"Identifier: {Identifier}, ResourceType: {ResourceType}"; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/SubjectResources.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/SubjectResources.cs new file mode 100644 index 00000000..05c389a9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRegistry/SubjectResources.cs @@ -0,0 +1,18 @@ +#nullable enable +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry; + +/// +/// Defines resources that a given subject have access to +/// +public class SubjectResources +{ + /// + /// The subject + /// + public required BaseAttribute Subject { get; set; } + + /// + /// List of resources that the given subject has access to + /// + public required IEnumerable Resources { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRightDelegationCheckResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRightDelegationCheckResult.cs new file mode 100644 index 00000000..8b8b2397 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ResourceRightDelegationCheckResult.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Response model describing the delegation status for a given single right, whether the authenticated user is able to delegate the right or not on behalf of the from part. +/// +public class ResourceRightDelegationCheckResult +{ + /// + /// Gets or sets the right key + /// + [Required] + public string RightKey { get; set; } + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + [Required] + public ActionUrn Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right is delegable or not + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public DelegableStatus Status { get; set; } + + /// + /// Gets or sets a list of details describing why or why not the right is valid in the current user and reportee party context + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List Details { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RightInternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RightInternal.cs new file mode 100644 index 00000000..8272bcdd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RightInternal.cs @@ -0,0 +1,20 @@ +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// DTO for holding resource and action for instance delegations +/// +public class RightInternal +{ + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public ActionUrn Action { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionIdentifier.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionIdentifier.cs new file mode 100644 index 00000000..8e654c1d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionIdentifier.cs @@ -0,0 +1,123 @@ +#nullable enable + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.Swashbuckle.Examples; +using Altinn.Swashbuckle.Filters; + +namespace Altinn.AccessManagement.Core.Models.Rights; + +/// +/// A xacml action string. +/// +[JsonConverter(typeof(ActionIdentifier.JsonConverter))] +[SwaggerString] +public class ActionIdentifier : ISpanParsable, + ISpanFormattable, + IExampleDataProvider +{ + private readonly string _value; + + private ActionIdentifier(string value) + { + _value = value; + } + + /// + /// Creates a new from the specified value without validation. + /// + /// The action identifier. + /// A . + public static ActionIdentifier CreateUnchecked(string value) + => new(value); + + /// + public static IEnumerable? GetExamples(ExampleDataOptions options) + { + yield return new ActionIdentifier("read"); + yield return new ActionIdentifier("write"); + } + + /// + public static ActionIdentifier Parse(string s) + => Parse(s, provider: null); + + /// + public static ActionIdentifier Parse(string s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid action"); + + /// + public static ActionIdentifier Parse(ReadOnlySpan s) + => Parse(s, provider: null); + + /// + public static ActionIdentifier Parse(ReadOnlySpan s, IFormatProvider? provider) + => TryParse(s, provider, out var result) + ? result + : throw new FormatException("Invalid action"); + + /// + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out ActionIdentifier result) + => TryParse(s.AsSpan(), s, out result); + + /// + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out ActionIdentifier result) + => TryParse(s, original: null, out result); + + private static bool TryParse(ReadOnlySpan s, string? original, [MaybeNullWhen(false)] out ActionIdentifier result) + { + result = new ActionIdentifier(original ?? new string(s)); + return true; + } + + /// + public override string ToString() + => _value; + + /// + public string ToString(string? format) + => _value; + + /// + public string ToString(string? format, IFormatProvider? formatProvider) + => _value; + + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + if (destination.Length < _value.Length) + { + charsWritten = 0; + return false; + } + + _value.AsSpan().CopyTo(destination); + charsWritten = _value.Length; + return true; + } + + private sealed class JsonConverter : JsonConverter + { + public override ActionIdentifier? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var str = reader.GetString(); + if (!TryParse(str, null, out var result)) + { + throw new JsonException("Invalid action"); + } + + return result; + } + + public override void Write(Utf8JsonWriter writer, ActionIdentifier value, JsonSerializerOptions options) + { + writer.WriteStringValue(value._value); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionUrn.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionUrn.cs new file mode 100644 index 00000000..29e1e5ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/ActionUrn.cs @@ -0,0 +1,20 @@ +#nullable enable + +using Altinn.Urn; + +namespace Altinn.AccessManagement.Core.Models.Rights; + +/// +/// A unique reference to an action in the form of an URN. +/// +[KeyValueUrn] +public abstract partial record ActionUrn +{ + /// + /// Try to get the urn as an action. + /// + /// The resulting action. + /// if this is an action, otherwise . + [UrnKey("oasis:names:tc:xacml:1.0:action:action-id")] + public partial bool IsActionId(out ActionIdentifier action); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/Right.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/Right.cs new file mode 100644 index 00000000..b2a4db7b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/Right.cs @@ -0,0 +1,55 @@ +namespace Altinn.AccessManagement.Core.Models; + +/// +/// This model describes a single right +/// +public class Right +{ + /// + /// Gets or sets the right key + /// + public string RightKey + { + get + { + return string.Join(",", Resource.OrderBy(m => m.Id).Select(m => m.Value)) + ":" + Action.Value; + } + } + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public AttributeMatch Action { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party has the right + /// + public bool? HasPermit { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party is permitted to delegate the right to others + /// + public bool? CanDelegate { get; set; } + + /// + /// Gets or sets the set of identified sources providing the right + /// + public List RightSources { get; set; } + + /// + public override bool Equals(object obj) + { + return obj is Right right && string.Equals(RightKey, right.RightKey, StringComparison.OrdinalIgnoreCase); + } + + /// + public override int GetHashCode() + { + return RightKey.GetHashCode(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegation.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegation.cs new file mode 100644 index 00000000..022c2d83 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegation.cs @@ -0,0 +1,22 @@ +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Describes the delegation result for a given single right. +/// +public record RightDelegation +{ + /// + /// Specifies who have delegated permissions + /// + public List From { get; set; } = []; + + /// + /// Receiver of the permissions + /// + public List To { get; set; } = []; + + /// + /// Specifies the permissions + /// + public List Resource { get; set; } = []; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationCheckResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationCheckResult.cs new file mode 100644 index 00000000..d20a0184 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationCheckResult.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model describing the delegation status for a given single right, whether the authenticated user is able to delegate the right or not on behalf of the from part, or whether the to recipient party already have the right. + /// + public class RightDelegationCheckResult + { + /// + /// Gets or sets the right key + /// + [Required] + public string RightKey { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource the rights + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + [Required] + public AttributeMatch Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right is delegable or not + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public DelegableStatus Status { get; set; } + + /// + /// Gets or sets a list of details describing the reasons why or why not the right is valid in the current user and reportee party context + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List Details { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationResult.cs new file mode 100644 index 00000000..80c3034b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightDelegationResult.cs @@ -0,0 +1,42 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model describing the delegation result for a given single right, whether the authenticated user was able to delegate the right or not on behalf of the from part. + /// + public class RightDelegationResult + { + /// + /// Gets or sets the right key + /// + public string RightKey + { + get + { + return string.Join(",", Resource.OrderBy(m => m.Id).Select(m => m.Value)) + ":" + Action.Value; + } + } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource which the right provides access to + /// + public List Resource { get; set; } + + /// + /// Gets or sets the Attribute Id and Attribute Value identifying action the right gives access to perform on the resource + /// + public AttributeMatch Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully delegated or not + /// + public DelegationStatus Status { get; set; } + + /// + /// Gets or sets a list of details describing the reason(s) behind the status (if any can be provided) + /// + public List Details { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightQueryForApp.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightQueryForApp.cs new file mode 100644 index 00000000..492f2fd7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightQueryForApp.cs @@ -0,0 +1,17 @@ +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Queries for rights delegable by the resource itself those must be defined in the policy with subject set to the resource. +/// +public class RightQueryForApp +{ + /// + /// The resource to check for delegable rights + /// + public IEnumerable OwnerApp { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource the rights + /// + public List Resource { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightSource.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightSource.cs new file mode 100644 index 00000000..bcfb0654 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightSource.cs @@ -0,0 +1,60 @@ +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a source from where a right exist for a user or party + /// + public class RightSource + { + /// + /// Gets or sets the set of type of source this right originated from (Role, AccessGroup, AppDelegation, ResourceRegistryDelegation etc.) + /// + public RightSourceType RightSourceType { get; set; } + + /// + /// Gets or sets the unique identifier for the specific policy the right originates (Output only). + /// + public string PolicyId { get; set; } + + /// + /// Gets or sets the version of the policy which the right originates (Output only). + /// + public string PolicyVersion { get; set; } + + /// + /// Gets or sets the unique identifier for the specific rule within the policy the right originates (Output only). + /// + public string RuleId { get; set; } + + /// + /// Gets or sets the party offering the rights to the receiving (CoveredBy) entity. + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party has the right + /// + public bool? HasPermit { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party is permitted to delegate the right to others + /// + public bool? CanDelegate { get; set; } + + /// + /// Gets or sets a value specifying the minimum required authentication level + /// + public int MinimumAuthenticationLevel { get; set; } + + /// + /// Gets or sets the list of subject matches the user has. + /// + public List UserSubjects { get; set; } + + /// + /// Gets or sets the list of subject matches which provides access to this right in the resource policy + /// + public List> PolicySubjects { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsDelegationCheckRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsDelegationCheckRequest.cs new file mode 100644 index 00000000..1b7adfa7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsDelegationCheckRequest.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Request model for a list of all rights for a specific resource, that a user can delegate from a given reportee to a given recipient. + /// + public class RightsDelegationCheckRequest + { + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the reportee party to delegate rights on behalf of + /// + [Required] + public List From { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource of the rights to be checked + /// + [Required] + public List Resource { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsQuery.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsQuery.cs new file mode 100644 index 00000000..8fcfcf16 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rights/RightsQuery.cs @@ -0,0 +1,33 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Queries for a list of all rights between two parties for a specific resource. + /// If coveredby user has any key roles, those party ids should be included in the query to have the 3.0 PIP lookup rights inheirited through those as well. + /// If offeredby is a sub unit, parenty party id should be supplied to include inheirited rights received through the main unit. + /// + public class RightsQuery + { + /// + /// Gets or sets the type of rights query to perform + /// + public RightsQueryType Type { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the entity having offered rights + /// + public List From { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the entity having received rights + /// + public List To { get; set; } + + /// + /// Gets or sets the service resource model of the rights + /// + public ServiceResource Resource { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RoleGrant.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RoleGrant.cs new file mode 100644 index 00000000..4015b082 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RoleGrant.cs @@ -0,0 +1,19 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a role which a particular action is given to. + /// example: RoleGrant { "RoleTypeCode": "DAGL", "IsDelegable": true } + /// + public class RoleGrant + { + /// + /// Gets or sets role type code the grant is for. + /// + public string RoleTypeCode { get; set; } + + /// + /// Gets or sets a value indicating whether having the specified role also permits the user to delegate the right specified by the ResourceAction to other recipients (if the receiver of the role also have administrative rights). + /// + public bool IsDelegable { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rule.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rule.cs new file mode 100644 index 00000000..ed428ce1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/Rule.cs @@ -0,0 +1,80 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a single rule in a delegated policy + /// + public class Rule + { + /// + /// Gets or sets the unique identifier for a specific rule within a policy (Output only). + /// + public string RuleId { get; set; } + + /// + /// Gets or sets the type of rule this is and why it is relevant for a given coveredby (recipient). Only part of output model when querying rules. + /// Policies may apply(grant rights) in four different ways: + /// 1. Direct delegations. This rule applies given directly to the recipient. + /// 2. Inherited via key role. This rule grants a right given to a party where the recipient has a key role, thus inheriting all rights given to the party. + /// 3. Inherited as subunit. If offeredby is a subunit, rights given from its parent to the recipient also applies to the subunit. + /// 4. Inherited as subunit via keyrole.If offeredby is a subunit, rights given from its parent to a party in which the recipient has a key role also applies to the subunit. + /// + public RuleType Type { get; set; } + + /// + /// Gets or sets the a value indicating whered the result of the create operation finished successfully (Output only). + /// + public bool CreatedSuccessfully { get; set; } + + /// + /// Gets or sets the user id of the user who performed the delegation. When creating new rules, this is supplied to indicate who performed the delegation, allowing the 3.0 PAP to determine whether or not the user is allowed to do so and to log accordingly. Only part of input model when adding single rules. + /// + public int? DelegatedByUserId { get; set; } + + /// + /// Gets or sets the party id of the entity who performed the delegation. When creating new rules, this is supplied to indicate who performed the delegation, allowing the 3.0 PAP to determine whether or not the user is allowed to do so and to log accordingly. Only part of input model when adding single rules. + /// + public int? DelegatedByPartyId { get; set; } + + /// + /// Datetime used to override now if the Rule is imported from a source with existing Delegation information + /// + public DateTime? DelegatedDateTime { get; set; } + + /// + /// Gets or sets the party offering the rights to the receiving (CoveredBy) entity. + /// + [Required] + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets the uuid of the party offering the rights to the receiving (CoveredBy) entity. + /// + public Guid? OfferedByPartyUuid { get; set; } + + /// + /// Gets or sets the type of the party offering the rights to the receiving (CoveredBy) entity. + /// + public UuidType OfferedByPartyType { get; set; } + + /// + /// Gets or sets the party receiving (covered by) the rights from the delegating (OfferedByPartyId) entity + /// + [Required] + public List CoveredBy { get; set; } + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this rule applies to. + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action from the original App Policy + /// + [Required] + public AttributeMatch Action { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleQuery.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleQuery.cs new file mode 100644 index 00000000..5d1f4df1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleQuery.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Queries for a list of already delegated rules from the supplied offeredby for the supplied app. If coveredby + /// has any key roles, those party ids can be included in the query to have the 3.0 PIP lookup those as well. + /// If offeredby is a sub unit, parenty party id can be supplied to include rules given from that party as well. + /// + public class RuleQuery + { + /// + /// Gets or sets the unique identifier for a the parent party id + /// + public int ParentPartyId { get; set; } + + /// + /// Gets or sets the list of key role party ids + /// + [Required] + public List KeyRolePartyIds { get; set; } + + /// + /// Gets or sets the unique identifier for a specific party for which the requested rule in the policy applies + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets resource match which uniquely identifies the resource this policy applies to. + /// + public List> Resources { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the coveredby id + /// + [Required] + public List CoveredBy { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleType.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleType.cs new file mode 100644 index 00000000..6bb2a107 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/RuleType.cs @@ -0,0 +1,33 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model defines the different types of rules and why it is relevant for a given coveredby (recipient). + /// + public enum RuleType + { + /// + /// Not set + /// + None = 0, + + /// + /// Direct delegations. The policy includes rights given directly to the recipient. + /// + DirectlyDelegated = 1, + + /// + /// Inherited via key role. The policy includes rights given to a party where the recipient has a key role, thus inheriting all rights given to the party. + /// + InheritedViaKeyRole = 2, + + /// + /// Inherited as subunit. If offeredby is a subunit, rights given from its parent to the recipient also applies to the subunit. + /// + InheritedAsSubunit = 3, + + /// + /// Inherited as subunit via keyrole. If offeredby is a subunit, rights given from its parent to a party in which the recipient has a key role also applies to the subunit. + /// + InheritedAsSubunitViaKeyrole = 4 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnit.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnit.cs new file mode 100644 index 00000000..929577ec --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnit.cs @@ -0,0 +1,34 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models.SblBridge +{ + /// + /// Model returned by SBL Bridge partyparents endpoint, describing a main unit (hovedenhet). + /// + public class MainUnit + { + /// + /// Gets or sets the PartyId of the main unit + /// + [JsonPropertyName("ParentPartyId")] + public int? PartyId { get; set; } + + /// + /// Gets or sets the PartyId of the subunit + /// + [JsonPropertyName("PartyId")] + public int SubunitPartyId { get; set; } + + /// + /// Gets or sets the organization number of the main unit + /// + [JsonPropertyName("ParentOrganizationNumber")] + public string OrganizationNumber { get; set; } + + /// + /// Gets or sets the name of the main unit + /// + [JsonPropertyName("ParentOrganizationName")] + public string OrganizationName { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnitQuery.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnitQuery.cs new file mode 100644 index 00000000..adcc4693 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/MainUnitQuery.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Core.Models.SblBridge +{ + /// + /// Input Model used by SBL Bridge partyparents endpoint, for listing the subunit partyIds to retrieve mainunit information for. + /// + public class MainUnitQuery + { + /// + /// Gets or sets the PartyId of the main unit + /// + public List PartyIds { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblAuthorizedParty.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblAuthorizedParty.cs new file mode 100644 index 00000000..a484de8b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblAuthorizedParty.cs @@ -0,0 +1,65 @@ +using Altinn.Platform.Register.Enums; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Model representing an authorized party as returned by the SBL Bridge, meaning a party for which a user has been authorized for one or more rights or role(s) in Altinn 2 +/// Used in new implementation of what has previously been named ReporteeList in Altinn 2. +/// +public class SblAuthorizedParty +{ + /// + /// Gets or sets the ID of the party + /// + public int PartyId { get; set; } + + /// + /// Gets or sets the UUID of the party + /// + public Guid? PartyUuid { get; set; } + + /// + /// Gets or sets the type of party + /// + public PartyType PartyTypeName { get; set; } + + /// + /// Gets the parties org number + /// + public string OrgNumber { get; set; } + + /// + /// Gets the parties ssn of the party is a person + /// + public string SSN { get; set; } + + /// + /// Gets or sets the UnitType if the party is an organization + /// + public string UnitType { get; set; } + + /// + /// Gets or sets the name of the party + /// + public string Name { get; set; } + + /// + /// Gets or sets whether this party is marked as deleted in Enhetsregisteret + /// + public bool IsDeleted { get; set; } + + /// + /// Gets or sets a value indicating whether the party is only for showing the hierarchy (a parent unit with no access) + /// + public bool OnlyHierarchyElementWithNoAccess { get; set; } + + /// + /// Gets or sets a collection of all rolecodes for roles from either Enhetsregisteret or Altinn 2 which the authorized actor has been authorized for, on behalf of this party + /// + public List AuthorizedRoles { get; set; } = []; + + /// + /// Gets or sets the value of ChildParties + /// + public List ChildParties { get; set; } = []; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblRightDelegationRequest.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblRightDelegationRequest.cs new file mode 100644 index 00000000..88f5d96e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblRightDelegationRequest.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Model for delegation of rights to SBL Bridge, identify or represent a delegation of one or more rights for an Altinn 2 service to be delegated to a party or user + /// + public class SblRightDelegationRequest + { + /// + /// Gets or sets the attribute id and attribute value for the user or party receiving rights + /// + public AttributeMatch To { get; set; } + + /// + /// Gets or sets a list of rights + /// + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblValidationProblemResponse.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblValidationProblemResponse.cs new file mode 100644 index 00000000..3607193e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SblBridge/SblValidationProblemResponse.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Core.Models.SblBridge +{ + /// + /// Model for validation problem error messages from SBL Bridge + /// + public class SblValidationProblemResponse + { + /// + /// Gets or sets the error message + /// + public string Message { get; set; } + + /// + /// Gets or sets the model state + /// + public Dictionary> ModelState { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SimpleDelegationChange.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SimpleDelegationChange.cs new file mode 100644 index 00000000..3b9c6a6a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/SimpleDelegationChange.cs @@ -0,0 +1,60 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// This model describes a delegation change as stored in the PostgreSQL-database Authorization in the table DelegatedPolicy. + /// + public class SimpleDelegationChange + { + /// + /// Gets or sets the delegation change id + /// + [JsonPropertyName("i")] + public int DelegationChangeId { get; set; } + + /// + /// Gets or sets the altinnappid. E.g. skd/skattemelding + /// + [JsonPropertyName("a")] + public string AltinnAppId { get; set; } + + /// + /// Gets or sets the offeredbypartyid, refering to the party id of the user or organization offering the delegation. + /// + [JsonPropertyName("o")] + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets the coveredbypartyid, refering to the party id of the organization having received the delegation. Otherwise Null if the recipient is a user. + /// + [JsonPropertyName("cp")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the coveredbyuserid, refering to the user id of the user having received the delegation. Otherwise Null if the recipient is an organization. + /// + [JsonPropertyName("cu")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? CoveredByUserId { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("u")] + public int? PerformedByUserId { get; set; } + + /// + /// Gets or sets the party id of the party that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("p")] + public int? PerformedByPartyId { get; set; } + + /// + /// Gets or sets the created date and timestamp for the delegation change + /// + [JsonPropertyName("t")] + public DateTime Created { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ValidationErrorResult.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ValidationErrorResult.cs new file mode 100644 index 00000000..afd6fe33 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Models/ValidationErrorResult.cs @@ -0,0 +1,21 @@ +namespace Altinn.AccessManagement.Core.Models +{ + /// + /// Response model for any errors occuring during processing of a model in the core service layer + /// + public class ValidationErrorResult + { + /// + /// Gets or sets a value indicating whether the processing was a success i.e. no errors has been added + /// + public bool IsValid + { + get { return Errors.Count == 0; } + } + + /// + /// Gets or sets a dictionary of errors occured during processing + /// + public Dictionary Errors { get; set; } = new Dictionary(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationChangeEventQueue.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationChangeEventQueue.cs new file mode 100644 index 00000000..5aad1a24 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationChangeEventQueue.cs @@ -0,0 +1,18 @@ +using Altinn.AccessManagement.Core.Models; +using Azure.Storage.Queues.Models; + +namespace Altinn.AccessManagement.Core.Repositories.Interfaces +{ + /// + /// The service used to map internal delegation change to delegation change events and push them to the event queue. + /// + public interface IDelegationChangeEventQueue + { + /// + /// Converts the delegation change to a delegation change event and pushes it to the event queue. + /// Throws exception if something fails + /// + /// The delegation change stored in postgresql + Task Push(DelegationChange delegationChange); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationMetadataRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationMetadataRepository.cs new file mode 100644 index 00000000..fbce37f4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IDelegationMetadataRepository.cs @@ -0,0 +1,192 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Repositories.Interfaces; + +/// +/// Interface for PostgreSQL operations on delegations. +/// +public interface IDelegationMetadataRepository +{ + /// + /// Writes the delegation change metadata to the delegation database + /// + /// The resource match type specifying whether the lookup is for an Altinn App delegation or a resource from the Resource Registry + /// The DelegationChange model describing the delegation, to insert in the database + /// The + /// The complete DelegationChange record stored in the database + Task InsertDelegation(ResourceAttributeMatchType resourceMatchType, DelegationChange delegationChange, CancellationToken cancellationToken = default); + + /// + /// Fetch all the latest Instance delegations for a given instance + /// + /// The source to fetch delegations for + /// The resource to fetch delegations for + /// The instance to fetch delegations for + /// The + /// All the last InstanceDelegationChange records stored in the database corresponding to the request + Task> GetAllLatestInstanceDelegationChanges(InstanceDelegationSource source, string resourceID, string instanceID, CancellationToken cancellationToken = default); + + /// + /// Returns all received instance delegations from db + /// + /// party uuid that received the delegation + /// The + /// + Task> GetAllCurrentReceivedInstanceDelegations(List toUuid, CancellationToken cancellationToken = default); + + /// + /// Returns the last change from db to fetch the current policy version and path to policy file + /// + /// The parameters to request the latest change for + /// The + /// The last InstanceDelegationChange record stored in the database corresponding to the request + Task GetLastInstanceDelegationChange(InstanceDelegationChangeRequest request, CancellationToken cancellationToken = default); + + /// + /// Writes the delegation change metadata to the delegation database + /// + /// The InstanceDelegationChange model describing the delegation, to insert in the database + /// The + /// The complete InstanceDelegationChange record stored in the database + Task InsertInstanceDelegation(InstanceDelegationChange instanceDelegationChange, CancellationToken cancellationToken = default); + + /// + /// Writes multiple delegation change metadata to the delegation database + /// + /// List of policies changed + /// The + /// + Task InsertMultipleInstanceDelegations(List policyWriteOutputs, CancellationToken cancellationToken = default); + + /// + /// Gets all the currently active instance delegations existing between the from and to parties + /// + /// Collection of all resourceIds to lookup + /// The From party to use for lookup + /// All To parties to use for lookup + /// The + /// The complete InstanceDelegationChange record stored in the database + Task> GetActiveInstanceDelegations(List resourceIds, Guid from, List to, CancellationToken cancellationToken = default); + + /// + /// Gets the latest delegation change matching the filter values + /// + /// The resource match type specifying whether the lookup is for an Altinn App delegation or a resource from the Resource Registry + /// The resourceId to look up. Either Altinn app id (org/app) or resource registry id + /// The party id of the entity offering the delegated the policy + /// The party id of the entity having received the delegated policy, if the entity is an organization + /// The user id of the entity having received the delegated policy, if the entity is a user + /// The receiver uuid + /// The type of uuid the reciver is + /// The + Task GetCurrentDelegationChange(ResourceAttributeMatchType resourceMatchType, string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default); + + /// + /// Gets all the delegation change records matching the filter values for a complete changelog + /// + /// The Altinn app id (org/app) + /// The party id of the entity offering the delegated the policy + /// The party id of the entity having received the delegated policy, if the entity is an organization + /// The user id of the entity having received the delegated policy, if the entity is a user + /// The + Task> GetAllAppDelegationChanges(string altinnAppId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default); + + /// + /// Gets all the current app delegation change records matching the filter values + /// + /// The list of party id of the entity offering the delegated the policy + /// The list of altinn app ids to look up + /// The list of party id of the entity having received the delegated policy, if the entity is an organization + /// The list of user id of the entity having received the delegated policy, if the entity is a user + /// Cancellation token for cancelling the request + Task> GetAllCurrentAppDelegationChanges(List offeredByPartyIds, List altinnAppIds, List coveredByPartyIds = null, List coveredByUserIds = null, CancellationToken cancellationToken = default); + + /// + /// Gets all the current altinn app delegation change records matching the filter values + /// + /// The list of altinn app IDs to look up delegations of + /// The list of from parties having delegated resources + /// The type of the to uuid recipient of delegated resources + /// The uuid of the recipient of delegated resources + /// The + Task> GetAllCurrentAppDelegationChanges(List altinnAppIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default); + + /// + /// Gets all the current resource registry delegation change records matching the filter values + /// + /// The list of party id of the entity offering the delegated the policy + /// The list of resource registry ids to look up + /// The list of party id of the entity having received the delegated policy, if the entity is an organization + /// The user id of the user having received the delegated policy + /// The + Task> GetAllCurrentResourceRegistryDelegationChanges(List offeredByPartyIds, List resourceRegistryIds, List coveredByPartyIds = null, int? coveredByUserId = null, CancellationToken cancellationToken = default); + + /// + /// Gets all the current resource registry delegation change records matching the filter values + /// + /// The list of resource registry IDs to look up delegations of + /// The list of from parties having delegated resources + /// The type of the to uuid recipient of delegated resources + /// The uuid of the recipient of delegated resources + /// The + Task> GetAllCurrentResourceRegistryDelegationChanges(List resourceRegistryIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default); + + /// + /// Gets all the active resource registry delegations a given party have delegated to others + /// + /// The party id of the entity offering the delegations + /// The resource registry ids of resources to find delegations of + /// The types of resources to find delegations of + /// Cancellation token for cancelling the request + Task> GetOfferedResourceRegistryDelegations(int offeredByPartyId, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default); + + /// + /// Gets all the active delegation given party has offered to others + /// + /// a + /// b + /// A representing the result of the asynchronous operation. + Task> GetOfferedDelegations(List offeredByPartyIds, CancellationToken cancellationToken = default); + + /// + /// Gets all the active resource registry delegations a list of parties have received from others + /// + /// The list of party ids of the entities receiving the delegations + /// The list of party ids of the entities offering the delegations + /// The resource registry ids of resources to find delegations of + /// The types of resources to find delegations of + /// The + Task> GetReceivedResourceRegistryDelegationsForCoveredByPartys(List coveredByPartyIds, List offeredByPartyIds = null, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default); + + /// + /// Gets all the active resource registry delegations a given user have received from others + /// + /// The user id of the entity that received the delegation + /// The party ids of the entities offering the delegations + /// The resource registry ids of resources to find delegations of + /// The types of resources to find delegations of + /// The + Task> GetReceivedResourceRegistryDelegationsForCoveredByUser(int coveredByUserId, List offeredByPartyIds, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default); + + /// + /// Gets the delgations for a given supplier, consumer and resourcetype based on resourceids + /// + /// the resource ids + /// the party id of the entity that offered the delegation + /// The party id of the entity that received the delegation + /// the type of resource + /// The + Task> GetResourceRegistryDelegationChanges(List resourceIds, int offeredByPartyId, int coveredByPartyId, ResourceType resourceType, CancellationToken cancellationToken = default); + + /// + /// Gets all the active app or resource delegations (except MaskinportenSchema delegations) for the set of covered userIds or partyIds + /// + /// The user ids of the users to get received delegation for + /// The party ids of the organizations to get received delegation for + /// The + Task> GetAllDelegationChangesForAuthorizedParties(List coveredByUserIds, List coveredByPartyIds, CancellationToken cancellationToken = default); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyFactory.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyFactory.cs new file mode 100644 index 00000000..067428fc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyFactory.cs @@ -0,0 +1,24 @@ +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Core.Repositories.Interfaces; + +/// +/// Create clients for interacting with files +/// +public interface IPolicyFactory +{ + /// + /// Creates a client for interacting with storage + /// + /// which storage account to write blob + /// path of the file + /// + IPolicyRepository Create(PolicyAccountType account, string filepath); + + /// + /// Creates a client for interacting with storage. assuming storage accoutn based on filename. + /// + /// path of the file + /// + IPolicyRepository Create(string filepath); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyRepository.cs new file mode 100644 index 00000000..c1f821d7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IPolicyRepository.cs @@ -0,0 +1,71 @@ +using Azure; +using Azure.Storage.Blobs.Models; + +namespace Altinn.AccessManagement.Core.Repositories.Interfaces; + +/// +/// Interface for operations on policy files. +/// +public interface IPolicyRepository +{ + /// + /// Gets file stream for the policy file from blob storage, if it exists at the specified path. + /// + /// cancellation token + /// File stream of the policy file + Task GetPolicyAsync(CancellationToken cancellationToken = default); + + /// + /// Gets file stream for the specified version of a policy file from blob storage, if it exists at the specified path. + /// + /// The blob storage version + /// cancellation token + /// File stream of the policy file + Task GetPolicyVersionAsync(string version, CancellationToken cancellationToken = default); + + /// + /// Writes a file stream to blobstorage to the specified path. + /// + /// File stream of the policy file to be written + /// cancellation token + /// Azure response BlobContentInfo + Task> WritePolicyAsync(Stream fileStream, CancellationToken cancellationToken = default); + + /// + /// Writes a file stream to blobstorage to the specified path, including the conditional check that the provided blob lease id is valid. + /// + /// File stream of the policy file to be written + /// The blob lease id, required to be able to write after a lock + /// cancellation token + /// Azure response BlobContentInfo + Task> WritePolicyConditionallyAsync(Stream fileStream, string blobLeaseId, CancellationToken cancellationToken = default); + + /// + /// Deletes a specific version of a blob storage file if it exits on the specified path. + /// + /// The blob storage version + /// cancellation token + /// + Task DeletePolicyVersionAsync(string version, CancellationToken cancellationToken = default); + + /// + /// Tries to acquire a blob lease on the base blob for the provided filepath. + /// + /// cancellation token + /// The LeaseId if a release was possible, otherwise null + Task TryAcquireBlobLease(CancellationToken cancellationToken = default); + + /// + /// Releases a blob lease on the base blob for the provided filepath using the provided leaseId. + /// + /// The lease id from to release + /// cancellation token + void ReleaseBlobLease(string leaseId, CancellationToken cancellationToken = default); + + /// + /// Checks whether there exists a blob at the specified path + /// + /// cancellation token + /// Bool whether the blob exists or not + Task PolicyExistsAsync(CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IResourceMetadataRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IResourceMetadataRepository.cs new file mode 100644 index 00000000..135bceaf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Repositories/Interfaces/IResourceMetadataRepository.cs @@ -0,0 +1,18 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Repositories.Interfaces +{ + /// + /// Repository implementation for PostgreSQL operations on resource register data in access management. + /// + public interface IResourceMetadataRepository + { + /// + /// Inserts a placeholder for a resource in Resource Registry into Access Managment + /// + /// Data to insert + /// CancellationToken + /// The inserted data with data generated/fetched in db + Task InsertAccessManagementResource(AccessManagementResource resource, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnEnterpriseUserResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnEnterpriseUserResolver.cs new file mode 100644 index 00000000..2a340db3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnEnterpriseUserResolver.cs @@ -0,0 +1,39 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; + +namespace Altinn.AccessManagement.Resolvers; + +/// +/// Resolves attributes for +/// +public class AltinnEnterpriseUserResolver : AttributeResolver +{ + private readonly IProfileClient _profile; + + /// + /// ctor + /// + public AltinnEnterpriseUserResolver(IProfileClient profile) : base(BaseUrn.Altinn.EnterpriseUser.String()) + { + AddLeaf([BaseUrn.Altinn.EnterpriseUser.Username], [BaseUrn.Altinn.EnterpriseUser.UserId], ResolveUsername()); + _profile = profile; + } + + /// + /// Resolves an enterprise user if given + /// + public LeafResolver ResolveUsername() => async (attributes, cancellationToken) => + { + if (await _profile.GetUser(new UserProfileLookup { Username = attributes.GetRequiredString(BaseUrn.Altinn.EnterpriseUser.Username) }) is var profile && profile != null) + { + return + [ + new(BaseUrn.Altinn.EnterpriseUser.UserId, profile.UserId), + ]; + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnOrganizationResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnOrganizationResolver.cs new file mode 100644 index 00000000..8d8652d5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnOrganizationResolver.cs @@ -0,0 +1,62 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Resolvers; + +/// +/// Resolves attributes for +/// +public class AltinnOrganizationResolver : AttributeResolver +{ + private readonly IContextRetrievalService _contextRetrievalService; + + /// + /// ctor + /// + public AltinnOrganizationResolver(IContextRetrievalService contextRetrievalService) : base(BaseUrn.Altinn.Organization.String()) + { + AddLeaf([BaseUrn.Altinn.Organization.PartyId], [BaseUrn.Altinn.Organization.Name, BaseUrn.Altinn.Organization.IdentifierNo], ResolvePartyId()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], [BaseUrn.Altinn.Organization.Name, BaseUrn.Altinn.Organization.IdentifierNo], ResolvePartyId()); + AddLeaf([BaseUrn.Altinn.Organization.IdentifierNo], [BaseUrn.Altinn.Organization.Name, BaseUrn.Altinn.Organization.PartyId], ResolveOrganizationNumber()); + _contextRetrievalService = contextRetrievalService; + } + + /// + /// Resolves an organization if given + /// + public LeafResolver ResolvePartyId() => async (attributes, cancellationToken) => + { + if (await _contextRetrievalService.GetPartyAsync(attributes.GetRequiredInt(BaseUrn.Altinn.Organization.PartyId)) is var party && party != null) + { + if (party.Organization != null) + { + return + [ + new(BaseUrn.Altinn.Organization.Name, party.Name), + new(BaseUrn.Altinn.Organization.IdentifierNo, party.Organization.OrgNumber), + ]; + } + } + + return []; + }; + + /// + /// Resolves an organization if given + /// + public LeafResolver ResolveOrganizationNumber() => async (attributes, cancellationToken) => + { + if (await _contextRetrievalService.GetPartyForOrganization(attributes.GetRequiredString(BaseUrn.Altinn.Organization.IdentifierNo)) is var party && party != null) + { + return + [ + new(BaseUrn.Altinn.Organization.PartyId, party.PartyId), + new(BaseUrn.Altinn.Organization.Name, party.Name) + ]; + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnPersonResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnPersonResolver.cs new file mode 100644 index 00000000..af8e3c03 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnPersonResolver.cs @@ -0,0 +1,119 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Resolvers; + +/// +/// Resolves attributes for +/// +public class AltinnPersonResolver : AttributeResolver +{ + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IProfileClient _profile; + + /// + /// ctor + /// + /// service init + /// profile client + public AltinnPersonResolver(IContextRetrievalService contextRetrievalService, IProfileClient profile) : base(BaseUrn.Altinn.Person.String()) + { + AddLeaf([BaseUrn.Altinn.Person.IdentifierNo], [BaseUrn.Altinn.Person.UserId, BaseUrn.Altinn.Person.PartyId, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolveProfileUsingIdentifierNo()); + AddLeaf([BaseUrn.Altinn.Person.UserId], [BaseUrn.Altinn.Person.IdentifierNo, BaseUrn.Altinn.Person.PartyId, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolveProfileUsingUserId()); + AddLeaf([BaseUrn.Altinn.Person.PartyId], [BaseUrn.Altinn.Person.IdentifierNo, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolvePartyUsingPartyId()); + AddLeaf([BaseUrn.Altinn.Person.PartyId], [BaseUrn.Altinn.Person.UserId, BaseUrn.Altinn.Person.PartyId, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolveProfileUsingPartyId()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], [BaseUrn.Altinn.Person.IdentifierNo, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolvePartyUsingPartyId()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], [BaseUrn.Altinn.Person.UserId, BaseUrn.Altinn.Person.PartyId, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolveProfileUsingPartyId()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute], [BaseUrn.Altinn.Person.IdentifierNo, BaseUrn.Altinn.Person.PartyId, BaseUrn.Altinn.Person.Shortname, BaseUrn.Altinn.Person.Firstname, BaseUrn.Altinn.Person.Middlename, BaseUrn.Altinn.Person.Lastname], ResolveProfileUsingUserId()); + + _contextRetrievalService = contextRetrievalService; + _profile = profile; + } + + /// + /// Resolves a person if given + /// + public LeafResolver ResolveProfileUsingIdentifierNo() => async (attributes, cancellationToken) => + { + var user = await _profile.GetUser(new() + { + Ssn = attributes.GetString(BaseUrn.Altinn.Person.IdentifierNo) + }); + + if (user?.Party?.Person != null) + { + return + [ + new(BaseUrn.Altinn.Person.UserId, user.UserId), + new(BaseUrn.Altinn.Person.PartyId, user.PartyId), + new(BaseUrn.Altinn.Person.Shortname, user.Party.Person.Name), + new(BaseUrn.Altinn.Person.Firstname, user.Party.Person.FirstName), + new(BaseUrn.Altinn.Person.Middlename, user.Party.Person.MiddleName), + new(BaseUrn.Altinn.Person.Lastname, user.Party.Person.LastName), + ]; + } + + return []; + }; + + /// + /// Resolves a profile if given + /// + public LeafResolver ResolveProfileUsingPartyId() => async (attributes, cancellationToken) => + { + var party = await ResolvePartyUsingPartyId()(attributes, cancellationToken); + return await ResolveProfileUsingIdentifierNo()(party, cancellationToken); + }; + + /// + /// Resolves a profile if given + /// + public LeafResolver ResolveProfileUsingUserId() => async (attributes, cancellationToken) => + { + var user = await _profile.GetUser(new() + { + UserId = attributes.GetRequiredInt(BaseUrn.Altinn.Person.UserId, AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute) + }); + + if (user?.Party?.Person != null) + { + return + [ + new(BaseUrn.Altinn.Person.IdentifierNo, user.Party.Person.SSN), + new(BaseUrn.Altinn.Person.PartyId, user.PartyId), + new(BaseUrn.Altinn.Person.Shortname, user.Party.Person.Name), + new(BaseUrn.Altinn.Person.Firstname, user.Party.Person.FirstName), + new(BaseUrn.Altinn.Person.Middlename, user.Party.Person.MiddleName), + new(BaseUrn.Altinn.Person.Lastname, user.Party.Person.LastName), + ]; + } + + return []; + }; + + /// + /// Resolves a person if given or + /// + public LeafResolver ResolvePartyUsingPartyId() => async (attributes, cancellationToken) => + { + if (await _contextRetrievalService.GetPartyAsync(attributes.GetRequiredInt(BaseUrn.Altinn.Person.PartyId, AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute)) is var party && party != null) + { + if (party.Person != null) + { + return + [ + new(BaseUrn.Altinn.Person.IdentifierNo, party.Person.SSN), + new(BaseUrn.Altinn.Person.Shortname, party.Person.Name), + new(BaseUrn.Altinn.Person.Firstname, party.Person.FirstName), + new(BaseUrn.Altinn.Person.Middlename, party.Person.MiddleName), + new(BaseUrn.Altinn.Person.Lastname, party.Person.LastName), + ]; + } + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResolver.cs new file mode 100644 index 00000000..ea35b4d3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResolver.cs @@ -0,0 +1,11 @@ +using Altinn.AccessManagement.Resolvers; + +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Resolves attributes for +/// +public class AltinnResolver(AltinnResourceResolver resource, PartyAttributeResolver partyAttributeResolver, UserAttributeResolver userAttributeResolver, AltinnPersonResolver personResolver, AltinnOrganizationResolver organizationResolver) + : AttributeResolver(BaseUrn.Altinn.String(), resource, partyAttributeResolver, userAttributeResolver, personResolver, organizationResolver) +{ +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResourceResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResourceResolver.cs new file mode 100644 index 00000000..2ca31043 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/AltinnResourceResolver.cs @@ -0,0 +1,59 @@ +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Resolves attributes for +/// +public class AltinnResourceResolver : AttributeResolver +{ + private readonly IContextRetrievalService _contextRetrievalService; + + /// + /// ctor + /// + public AltinnResourceResolver(IContextRetrievalService contextRetrievalService) : base(BaseUrn.Altinn.Resource.String()) + { + AddLeaf([BaseUrn.Altinn.Resource.AppOwner, BaseUrn.Altinn.Resource.AppId], [BaseUrn.Altinn.Resource.Delegable, BaseUrn.Altinn.Resource.Type, BaseUrn.Altinn.Resource.ResourceRegistryId], ResolveAppOwnerAndAppId()); + AddLeaf([BaseUrn.Altinn.Resource.ResourceRegistryId], [BaseUrn.Altinn.Resource.Delegable, BaseUrn.Altinn.Resource.Type], ResolveResourceRegistryId()); + _contextRetrievalService = contextRetrievalService; + } + + /// + /// Resolves a resource if given and + /// + public LeafResolver ResolveAppOwnerAndAppId() => async (attributes, cancellationToken) => + { + var resource = await _contextRetrievalService.GetResourceFromResourceList(null, attributes.GetRequiredString(BaseUrn.Altinn.Resource.AppOwner), attributes.GetRequiredString(BaseUrn.Altinn.Resource.AppId), null, null); + if (resource != null) + { + return + [ + new(BaseUrn.Altinn.Resource.Delegable, resource.Delegable), + new(BaseUrn.Altinn.Resource.Type, resource.ResourceType), + new(BaseUrn.Altinn.Resource.ResourceRegistryId, resource.Identifier), + ]; + } + + return []; + }; + + /// + /// /// Resolves a resource if given + /// + public LeafResolver ResolveResourceRegistryId() => async (attributes, cancellationToken) => + { + var resource = await _contextRetrievalService.GetResourceFromResourceList(attributes.GetRequiredString(BaseUrn.Altinn.Resource.ResourceRegistryId), null, null, null, null); + if (resource != null) + { + return + [ + new(BaseUrn.Altinn.Resource.Delegable, resource.Delegable), + new(BaseUrn.Altinn.Resource.Type, resource.ResourceType), + ]; + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/PartyAttributeResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/PartyAttributeResolver.cs new file mode 100644 index 00000000..3340c47d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/PartyAttributeResolver.cs @@ -0,0 +1,61 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Resolvers; + +/// +/// Resolves Party attribute as a PartyId +/// +public class PartyAttributeResolver : AttributeResolver +{ + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IProfileClient _profile; + + /// + /// Resolves Party attribute as a PartyId + /// + /// service init + /// profile client + public PartyAttributeResolver(IContextRetrievalService contextRetrievalService, IProfileClient profile) : base(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute) + { + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], [AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], ResolvePartyIdFromParty()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute], [AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], ResolvePartyIdFromUser()); + + _contextRetrievalService = contextRetrievalService; + _profile = profile; + } + + /// + /// Resolves a PartyId if given exists + /// + public LeafResolver ResolvePartyIdFromUser() => async (attributes, cancellationToken) => + { + UserProfile user = await _profile.GetUser( + new() { UserId = attributes.GetRequiredInt(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute) }, + cancellationToken); + + if (user != null) + { + return [new(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, user.Party.PartyId)]; + } + + return []; + }; + + /// + /// Resolves a PartyId if given exists + /// + public LeafResolver ResolvePartyIdFromParty() => async (attributes, cancellationToken) => + { + if (await _contextRetrievalService.GetPartyAsync(attributes.GetRequiredInt(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute), cancellationToken) is var party && party != null) + { + return [new(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, party.PartyId)]; + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/UserAttributeResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/UserAttributeResolver.cs new file mode 100644 index 00000000..7f758b70 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Altinn/UserAttributeResolver.cs @@ -0,0 +1,81 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Resolvers; + +/// +/// Resolves From attribute as a PartyId +/// +public class UserAttributeResolver : AttributeResolver +{ + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IProfileClient _profile; + + /// + /// Resolves To attribute as a either a PartyId (if found as an organization) or a UserId (if found as a user) + /// + /// service init + /// profile client + public UserAttributeResolver(IContextRetrievalService contextRetrievalService, IProfileClient profile) : base(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute) + { + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], [AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute], ResolveFromParty()); + AddLeaf([AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute], [AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute], ResolveFromUser()); + + _contextRetrievalService = contextRetrievalService; + _profile = profile; + } + + /// + /// Resolves a UserId if given exists + /// + public LeafResolver ResolveFromUser() => async (attributes, cancellationToken) => + { + UserProfile user = await _profile.GetUser( + new() { UserId = attributes.GetRequiredInt(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute) }, + cancellationToken); + + if (user != null) + { + return [new(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, user.UserId)]; + } + + return []; + }; + + /// + /// Resolves a party if given a + /// + public LeafResolver ResolveFromParty() => async (attributes, cancellationToken) => + { + if (await _contextRetrievalService.GetPartyAsync(attributes.GetRequiredInt(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute), cancellationToken) is var party && party?.Person != null) + { + return await ResolveUserIdUsingIdentifierNo()([new(BaseUrn.Altinn.Person.IdentifierNo, party.Person.SSN)], cancellationToken); + } + + return []; + }; + + /// + /// Resolves a person to a userId + /// + public LeafResolver ResolveUserIdUsingIdentifierNo() => async (attributes, cancellationToken) => + { + var user = await _profile.GetUser( + new() { Ssn = attributes.GetRequiredString(BaseUrn.Altinn.Person.IdentifierNo) }, + cancellationToken); + + if (user != null) + { + return + [ + new(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, user.UserId) + ]; + } + + return []; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolution.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolution.cs new file mode 100644 index 00000000..87672893 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolution.cs @@ -0,0 +1,22 @@ +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// A data container that encapsulates the needed parameters in order to run a resolver. +/// +public class AttributeResolution(IEnumerable needs, IEnumerable resolves, LeafResolver resolver) +{ + /// + /// The required attributes to be present in order for the resolver to run. + /// + public IEnumerable Needs { get; } = needs; + + /// + /// The attributes the resolver is able to fetch if provided its needs. + /// + public IEnumerable Resolves { get; } = resolves; + + /// + /// A function reference which, when called upon, does the work. + /// + public LeafResolver Resolver { get; } = resolver; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolver.cs new file mode 100644 index 00000000..5d6bcf81 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/AttributeResolver.cs @@ -0,0 +1,150 @@ +using System.Collections.Concurrent; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Leaf resolver is a function that fetches new requested attributes based on given attributes +/// +/// current attributes +/// Cancellation token +public delegate Task> LeafResolver(IEnumerable attributes, CancellationToken cancellationToken); + +/// +/// A generic node in the parse tree. Root node should be the UrnResolver +/// +/// Name of the resource / Urn +/// Internal nodes in the parse tree +public abstract class AttributeResolver(string resourceName, params IAttributeResolver[] internalNodes) : IAttributeResolver +{ + /// + /// Name / URN of the resource. + /// + public string ResourceName { get; } = resourceName; + + /// + /// List of internal nodes + /// + public IAttributeResolver[] InternalNodes { get; } = internalNodes; + + /// + /// List of Leaf Nodes / + /// + public virtual List LeafResolvers { get; } = []; + + /// + /// Adds a leaf node this internal node + /// + /// The required attributes to be present in order for the attribute to run + /// The attributes the resolver are able to fetch if provided it needs. + /// A function reference which when called upon does the work. + public virtual IAttributeResolver AddLeaf(IEnumerable needs, IEnumerable resolves, LeafResolver resolver) + { + LeafResolvers.Add(new(needs, resolves, resolver)); + return this; + } + + /// + public virtual async Task> Resolve(IEnumerable attributes, IEnumerable wants, CancellationToken cancellationToken) + { + var result = new ConcurrentBag(); + foreach (var attribute in attributes) + { + result.Add(attribute); + } + + for (int count = 0; count != result.Count; count = result.Count) + { + await ResolveInternalNodes(attributes, wants, result, cancellationToken); + await ResolveLeafNodes(wants, result, cancellationToken); + } + + return result.Distinct(); + } + + /// + /// Executes all leaf nodes if following conditions are met + /// - The resolver has all required attributes (needs) + /// - The resolver actually add new attributes based on requested attributes (wants) + /// - The attributes haven't already been added by other resolvers + /// + /// list of attribute types that are requested by callee + /// current result of all attributes + /// Cancellation token + private async Task ResolveLeafNodes(IEnumerable wants, ConcurrentBag result, CancellationToken cancellationToken) => + await Task.WhenAll(LeafResolvers.Select(async resolver => + { + var resolverExecutionCondtions = new List() + { + DoesResolverHaveItsNeeds(resolver, result), + DoesResolverAddTheWants(wants, resolver), + DoesResolverAddNewAttributes(result, resolver) + }; + + if (resolverExecutionCondtions.TrueForAll(condition => condition)) + { + foreach (var attribute in await resolver.Resolver(result, cancellationToken)) + { + result.Add(attribute); + } + } + })).WaitAsync(cancellationToken); + + /// + /// Traverses the internal tree + /// + /// list of given attributes + /// list of attribute types that are requested by callee + /// current result of all attributes + /// Cancellation token + private async Task ResolveInternalNodes(IEnumerable attributes, IEnumerable wants, ConcurrentBag result, CancellationToken cancellationToken) => + await Task.WhenAll(InternalNodes.Select(async resolver => + { + foreach (var attribute in await resolver.Resolve(attributes, wants, cancellationToken)) + { + result.Add(attribute); + } + })).WaitAsync(cancellationToken); + + /// + /// Adds the attributes to the result list + /// + /// current list + /// attribute type + /// attribute value + protected static void AddResult(List result, string type, object value) + { + result.Add(new() + { + Id = type, + Value = value.ToString(), + }); + } + + /// + /// Checks if the resolver has all required attributes (needs). + /// + /// leaf resolver + /// current result + /// + private static bool DoesResolverHaveItsNeeds(AttributeResolution resolution, ConcurrentBag result) => + resolution.Needs.All(need => result.Any(result => result.Id.Equals(need, StringComparison.InvariantCultureIgnoreCase))); + + /// + /// Checks if the resolver actually adds new attributes based on requested attributes (wants). + /// + /// a + /// b + /// + private static bool DoesResolverAddTheWants(IEnumerable wants, AttributeResolution resolver) => + wants.Any(want => resolver.Resolves.Any(resolve => resolve.StartsWith(want, StringComparison.InvariantCultureIgnoreCase))) || !wants.Any(); + + /// + /// Checks if the attributes haven't already been added by other resolvers. + /// + /// a + /// b + /// + private static bool DoesResolverAddNewAttributes(ConcurrentBag result, AttributeResolution resolver) => + !resolver.Resolves.All(resolve => result.Any(attribute => attribute.Id.Equals(resolve, StringComparison.InvariantCultureIgnoreCase))); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/BaseUrn.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/BaseUrn.cs new file mode 100644 index 00000000..dabdc175 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/BaseUrn.cs @@ -0,0 +1,196 @@ +using Altinn.AccessManagement.Core.Constants; + +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Urn +/// +public static class BaseUrn +{ + /// + /// Urn + /// + /// + public static string String() => $"urn"; + + /// + /// InternalIds of delegatable entities + /// + public static string[] InternalIds => [Altinn.Organization.PartyId, Altinn.Person.PartyId, Altinn.Person.UserId, Altinn.EnterpriseUser.UserId, AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute]; + + /// + /// InternalIds from Altinn 2 + /// + public static string[] Altinn2InternalIds => [AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute]; + + /// + /// Resources that belongs to Altinn + /// + public static class Altinn + { + /// + /// Urn.Altinn + /// + public static string String() => $"{BaseUrn.String()}:{nameof(Altinn)}".ToLower(); + + /// + /// Urn.Altinn.Person + /// + public static class Person + { + /// + /// A person Social security number + /// + public static string IdentifierNo => $"{String()}:identifier-no"; + + /// + /// Uuid + /// + public static string Uuid => $"{String()}:uuid"; + + /// + /// UserId + /// + public static string UserId => $"{String()}:userid"; + + /// + /// PartyId + /// + public static string PartyId => $"{String()}:partyid"; + + /// + /// A person's first name + /// + public static string Firstname => $"{String()}:firstname"; + + /// + /// A Person's shortname + /// + public static string Shortname => $"{String()}:shortname"; + + /// + /// A Person's middlename + /// + public static string Middlename => $"{String()}:middlename"; + + /// + /// A Person's lastname + /// + public static string Lastname => $"{String()}:lastname"; + + /// + /// Urn.Altinn.Person + /// + public static string String() => $"{Altinn.String()}:{nameof(Person)}".ToLower(); + } + + /// + /// Urn.Altinn.Organization + /// + public static class Organization + { + /// + /// An organization brreg number + /// + public static string IdentifierNo => $"{String()}:identifier-no"; + + /// + /// Organization's name + /// + public static string Name => $"{String()}:name"; + + /// + /// Organzation's Party Id + /// + public static string PartyId => $"{String()}:partyid"; + + /// + /// Uuid of organization + /// + public static string Uuid => $"{String()}:uuid"; + + /// + /// Urn.Altinn.Organization + /// + public static string String() => $"{Altinn.String()}:{nameof(Organization)}".ToLower(); + } + + /// + /// Urn.Altinn.EnterpriseUser + /// + public static class EnterpriseUser + { + /// + /// username + /// + public static string Username => $"{String()}:username"; + + /// + /// uuid + /// + public static string Uuid => $"{String()}:uuid"; + + /// + /// UserId + /// + public static string UserId => $"{String()}:userid"; + + /// + /// Urn.Altinn.EnterpriseUser.Organization + /// + public static class Organization + { + /// + /// uuid + /// + public static string Uuid => $"{String()}:uuid"; + + /// + /// Urn.Altinn.EnterpriseUser.Organization + /// + public static string String() => $"{EnterpriseUser.String()}:{nameof(Organization)}".ToLower(); + } + + /// + /// Urn.Altinn.EnterpriseUser + /// + public static string String() => $"{Altinn.String()}:{nameof(EnterpriseUser)}".ToLower(); + } + + /// + /// Urn.Altinn.Resource + /// + public static class Resource + { + /// + /// The resource regigistry identifier + /// + public static string ResourceRegistryId => "urn:altinn:resource"; + + /// + /// Owner of the altinn App + /// + public static string AppOwner => "urn:altinn:org"; + + /// + /// Altinn AppId + /// + public static string AppId => "urn:altinn:app"; + + /// + /// Specifies the type of the resource + /// + public static string Type => $"{String()}:type".ToLower(); + + /// + /// boolean that specifies of the resource is delegable or not + /// + public static string Delegable => $"{String()}:delegable".ToLower(); + + /// + /// Urn.Altinn.Resource + /// + public static string String() => $"{Altinn.String()}:{nameof(Resource)}".ToLower(); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Extensions/ResolverExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Extensions/ResolverExtensions.cs new file mode 100644 index 00000000..d63e7a1d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/Extensions/ResolverExtensions.cs @@ -0,0 +1,57 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Resolvers; +using Microsoft.Extensions.DependencyInjection; + +namespace Altinn.AccessManagement.Core.Resolvers.Extensions; + +/// +/// General extensions for the resolvers +/// +public static class ResolverExtensions +{ + /// + /// Gets first match of specific attribute value as string + /// + /// list of attributes + /// attributes types / URN's + /// + public static string GetRequiredString(this IEnumerable values, params string[] attributes) + { + foreach (var attribute in attributes) + { + if (values.FirstOrDefault(value => value.Id.Equals(attribute, StringComparison.InvariantCultureIgnoreCase)) is var result && result != null) + { + return result.Value; + } + } + + throw new ArgumentException($"couldn't find any [{string.Join(",", attributes)}] in list of attributes"); + } + + /// + /// Gets first match of specific attribute value as string + /// + /// list of attributes + /// attributes types / URN's + /// + public static string GetString(this IEnumerable values, params string[] attributes) + { + foreach (var attribute in attributes) + { + if (values.FirstOrDefault(value => value.Id.Equals(attribute, StringComparison.InvariantCultureIgnoreCase)) is var result && result != null) + { + return result.Value; + } + } + + return string.Empty; + } + + /// + /// Gets first match of specific attribute value as integer. + /// + /// list of attributes + /// attributes types / URN's + /// + public static int GetRequiredInt(this IEnumerable values, params string[] attributes) => int.Parse(values.GetRequiredString(attributes)); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/IAttributeResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/IAttributeResolver.cs new file mode 100644 index 00000000..7569de60 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/IAttributeResolver.cs @@ -0,0 +1,19 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Resolves attributes. +/// +public interface IAttributeResolver +{ + /// + /// Allows the caller to fetch new requested attributes specified by the wants parameter. + /// Given attributes should contain values that allow the user to resolve/fetch wanted attributes. + /// + /// Current attributes. + /// Attributes wanted by the callee. + /// Cancellation token. + /// New list of attributes containing given attributes and wanted attributes. + Task> Resolve(IEnumerable attributes, IEnumerable wants, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/UrnResolver.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/UrnResolver.cs new file mode 100644 index 00000000..80c43cf4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Resolvers/UrnResolver.cs @@ -0,0 +1,8 @@ +namespace Altinn.AccessManagement.Core.Resolvers; + +/// +/// Resolves attributes for +/// +public class UrnResolver(AltinnResolver altinn) : AttributeResolver(BaseUrn.String(), altinn) +{ +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Altinn2RightsService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Altinn2RightsService.cs new file mode 100644 index 00000000..e85fa13b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Altinn2RightsService.cs @@ -0,0 +1,131 @@ +using System.Runtime.CompilerServices; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Register.Enums; + +namespace Altinn.AccessManagement.Core.Services; + +/// +public class Altinn2RightsService : IAltinn2RightsService +{ + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IPolicyInformationPoint _pip; + private readonly IAltinn2RightsClient _altinn2RightsClient; + private readonly IProfileClient _profile; + + /// + /// Initializes a new instance of the class. + /// + /// Service for retrieving context information + /// Service for getting policy information + /// SBL Bridge client implementation for rights operations on Altinn 2 services + /// Profile lookup client + public Altinn2RightsService(IContextRetrievalService contextRetrievalService, IPolicyInformationPoint pip, IAltinn2RightsClient altinn2RightsClient, IProfileClient profileClient) + { + _contextRetrievalService = contextRetrievalService; + _pip = pip; + _altinn2RightsClient = altinn2RightsClient; + _profile = profileClient; + } + + /// + public async Task> GetOfferedRights(int partyId, CancellationToken cancellationToken = default) + { + var delegations = await _pip.GetOfferedDelegationsFromRepository(partyId, cancellationToken); + return await MapDelegationResponse(delegations); + } + + /// + public async Task> GetReceivedRights(int partyId, CancellationToken cancellationToken = default) + { + var delegations = await _pip.GetReceivedDelegationFromRepository(partyId, cancellationToken); + return await MapDelegationResponse(delegations); + } + + /// + public async Task ClearReporteeRights(int fromPartyId, BaseAttribute toAttribute, CancellationToken cancellationToken = default) => toAttribute.Type switch + { + AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid => await ClearReporteeRightsForUser(fromPartyId, toAttribute.Value, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid => await ClearReporteeRightsForParty(fromPartyId, toAttribute.Value, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid => await ClearReporteeRightsForUser(fromPartyId, toAttribute.Value, cancellationToken), + _ => throw new ArgumentException(message: $"Unknown attribute type: {toAttribute.Type}", paramName: nameof(toAttribute)) + }; + + private async Task ClearReporteeRightsForUser(int fromPartyId, string toUserUuid, CancellationToken cancellationToken) + { + if (!Guid.TryParse(toUserUuid, out Guid userUuid)) + { + return new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) { ReasonPhrase = $"Not a well-formed uuid: {toUserUuid}" }; + } + + if (await _profile.GetUser(new Models.Profile.UserProfileLookup { UserUuid = userUuid }, cancellationToken) is var profile && profile != null) + { + return await _altinn2RightsClient.ClearReporteeRights(fromPartyId, profile.PartyId, profile.UserId, cancellationToken); + } + + return new HttpResponseMessage(System.Net.HttpStatusCode.OK); + } + + private async Task ClearReporteeRightsForParty(int fromPartyId, string toPartyUuid, CancellationToken cancellationToken) + { + if (!Guid.TryParse(toPartyUuid, out Guid partyUuid)) + { + return new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) { ReasonPhrase = $"Not a well-formed uuid: {toPartyUuid}" }; + } + + if (await _contextRetrievalService.GetPartyByUuid(partyUuid, false, cancellationToken) is var party && party != null && party.PartyTypeName == PartyType.Organisation) + { + return await _altinn2RightsClient.ClearReporteeRights(fromPartyId, party.PartyId, cancellationToken: cancellationToken); + } + + return new HttpResponseMessage(System.Net.HttpStatusCode.OK); + } + + private async Task> MapDelegationResponse(IEnumerable delegations) + { + var result = new List(); + + foreach (var delegation in delegations) + { + var entry = new RightDelegation(); + + if (delegation.CoveredByUserId == null && delegation.CoveredByPartyId == null) + { + // This is a temporary fix just to remove delegations given to system users so they do not give problems for the use from Altinn II to be changed later + continue; + } + + if (delegation.CoveredByUserId != null) + { + entry.To.Add(new(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, delegation.CoveredByUserId.ToString())); + } + + if (delegation.CoveredByPartyId != null) + { + entry.To.Add(new(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, delegation.CoveredByPartyId.ToString())); + } + + entry.From.Add(new(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, delegation.OfferedByPartyId.ToString())); + + if (delegation.ResourceType.Contains("AltinnApp", StringComparison.InvariantCultureIgnoreCase)) + { + var app = delegation.ResourceId.Split("/"); + entry.Resource.AddRange([ + new(AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute, app[0]), + new(AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute, app[1]) + ]); + } + else + { + var resources = await _contextRetrievalService.GetResourceList(); + entry.Resource.AddRange(resources.Find(r => r.Identifier == delegation.ResourceId).AuthorizationReference ?? []); + } + + result.Add(entry); + } + + return result; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AppsInstanceDelegationService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AppsInstanceDelegationService.cs new file mode 100644 index 00000000..d44ea1c1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AppsInstanceDelegationService.cs @@ -0,0 +1,675 @@ +using System.ComponentModel.DataAnnotations; +using System.Formats.Asn1; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Errors; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.Authorization.ProblemDetails; +using Altinn.Platform.Register.Models; +using Altinn.Urn; +using Altinn.Urn.Json; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace Altinn.AccessManagement.Core.Services.Implementation; + +/// +/// Contains all actions related to app instance delegation from Apps +/// +public class AppsInstanceDelegationService : IAppsInstanceDelegationService +{ + private readonly IPartiesClient _partiesClient; + private readonly IPolicyInformationPoint _pip; + private readonly IPolicyAdministrationPoint _pap; + private readonly IResourceRegistryClient _resourceRegistryClient; + private readonly string appInstanceResourcePath = "appInstanceDelegationRequest.Resource"; + + /// + /// Initializes a new instance of the class. + /// + public AppsInstanceDelegationService(IPartiesClient partiesClient, IResourceRegistryClient resourceRegistryClient, IPolicyInformationPoint pip, IPolicyAdministrationPoint pap) + { + _partiesClient = partiesClient; + _pip = pip; + _resourceRegistryClient = resourceRegistryClient; + _pap = pap; + } + + private async Task<(UuidType DelegationType, Guid? Uuid)> TranslatePartyUuidToPersonOrganizationUuid(PartyUrn partyId) + { + Party party = null; + + if (partyId.IsOrganizationIdentifier(out OrganizationNumber orgNumber)) + { + PartyLookup lookup = new PartyLookup + { + OrgNo = orgNumber.ToString() + }; + + party = await _partiesClient.LookupPartyBySSNOrOrgNo(lookup); + } + else if (partyId.IsPartyUuid(out Guid partyUuid)) + { + party = (await _partiesClient.GetPartiesAsync(partyUuid.SingleToList())).FirstOrDefault(); + } + + return DelegationHelper.GetUuidTypeAndValueFromParty(party); + } + + private static bool CheckIfInstanceIsDelegable(List delegableRights, RightInternal rightToDelegate) + { + return delegableRights.Exists(delegableRight => InstanceRightComparesEqualToDelegableRight(delegableRight, rightToDelegate)); + } + + private static bool InstanceRightComparesEqualToDelegableRight(Right right, RightInternal instanceRight) + { + if (right.Action.Value != instanceRight.Action.ValueSpan.ToString()) + { + return false; + } + + foreach (var resourcePart in right.Resource) + { + bool valid = instanceRight.Resource.Exists(r => r.Value.PrefixSpan.ToString() == resourcePart.Id && r.Value.ValueSpan.ToString() == resourcePart.Value); + + if (!valid) + { + return false; + } + } + + return true; + } + + private static bool ValidateAndGetSignificantResourcePartsFromResource(IEnumerable input, out List resource, string resourceTag) + { + resource = new List(); + + if (input == null || !input.Any()) + { + return false; + } + + string org = null, app = null, resourceRegistryId = null; + int significantParts = 0; + foreach (UrnJsonTypeValue urnJsonTypeValue in input) + { + if (urnJsonTypeValue.HasValue) + { + switch (urnJsonTypeValue.Value.PrefixSpan.ToString()) + { + case AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute: + resource.Add(urnJsonTypeValue); + org = urnJsonTypeValue.Value.ValueSpan.ToString(); + significantParts++; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute: + resource.Add(urnJsonTypeValue); + app = urnJsonTypeValue.Value.ValueSpan.ToString(); + significantParts++; + break; + case AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute: + resource.Add(urnJsonTypeValue); + resourceRegistryId = urnJsonTypeValue.Value.ValueSpan.ToString(); + significantParts++; + break; + } + } + } + + if (org != null && app != null && resourceRegistryId == null && significantParts == 2) + { + return $"app_{org}_{app}" == resourceTag; + } + + if (org == null && app == null && resourceRegistryId != null && significantParts == 1) + { + return resourceRegistryId == resourceTag; + } + + return false; + } + + private static void AddValidationErrorsForResourceInstance(ref ValidationErrorBuilder errors, IEnumerable rights, string resourceid) + { + ValidateAndGetSignificantResourcePartsFromResource(rights.FirstOrDefault()?.Resource, out List firstResource, resourceid); + int counter = -1; + + foreach (RightInternal rightV2 in rights) + { + counter++; + + bool valid = ValidateAndGetSignificantResourcePartsFromResource(rightV2.Resource, out List currentResource, resourceid); + if (!valid) + { + errors.Add(ValidationErrors.InvalidResource, $"Rights[{counter}]/Resource"); + continue; + } + + foreach (UrnJsonTypeValue urnJsonTypeValue in currentResource) + { + if (!firstResource.Contains(urnJsonTypeValue)) + { + errors.Add(ValidationErrors.InvalidResource, $"Rights[{counter}]/Resource"); + } + } + } + } + + /// + public async Task> DelegationCheck(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default) + { + ResourceDelegationCheckResponse result = new ResourceDelegationCheckResponse() { From = null, ResourceRightDelegationCheckResults = new List() }; + + ValidationErrorBuilder errors = default; + + ServiceResource resource = (await _resourceRegistryClient.GetResourceList(cancellationToken)).Find(r => r.Identifier == request.ResourceId); + List delegableRights = null; + + if (resource == null) + { + errors.Add(ValidationErrors.InvalidResource, appInstanceResourcePath); + } + else + { + RightsQuery rightsQueryForApp = new RightsQuery + { + Type = RightsQueryType.AltinnApp, + To = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceDelegationAttribute, Value = request.PerformedBy.ValueSpan.ToString() }.SingleToList(), + From = resource.AuthorizationReference, + Resource = resource + }; + + try + { + delegableRights = await _pip.GetDelegableRightsByApp(rightsQueryForApp, cancellationToken); + } + catch (ValidationException) + { + errors.Add(ValidationErrors.MissingPolicy, appInstanceResourcePath); + } + } + + if (errors.TryBuild(out var errorResult)) + { + return errorResult; + } + + if (delegableRights == null || delegableRights.Count == 0) + { + return result; + } + + foreach (Right right in delegableRights) + { + result.ResourceRightDelegationCheckResults.Add(new() + { + RightKey = right.RightKey, + Resource = right.Resource.Select(r => r.ToKeyValueUrn()).ToList(), + Action = ActionUrn.ActionId.Create(ActionIdentifier.CreateUnchecked(right.Action.Value)), + Status = (right.CanDelegate.HasValue && right.CanDelegate.Value) ? DelegableStatus.Delegable : DelegableStatus.NotDelegable + }); + } + + return await Task.FromResult(result); + } + + /// + public async Task> Delegate(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default) + { + (ValidationErrorBuilder Errors, InstanceRight RulesToHandle, List RightsAppCantHandle) input = await SetUpDelegationOrRevokeRequest(request, cancellationToken); + + if (input.Errors.TryBuild(out var errorResult)) + { + return errorResult; + } + + AppsInstanceDelegationResponse result = new() + { + From = request.From, + To = request.To, + ResourceId = request.ResourceId, + InstanceId = request.InstanceId, + InstanceDelegationMode = request.InstanceDelegationMode + }; + + List rights = await DelegateRights(input.RulesToHandle, input.RightsAppCantHandle, cancellationToken); + result.Rights = rights; + result = RemoveInstanceIdFromResourceForDelegationResponse(result); + + return result; + } + + /// + public async Task>> RevokeAll(AppsInstanceGetRequest request, CancellationToken cancellationToken = default) + { + ValidationErrorBuilder errors = default; + + // Fetch rights valid for delegation + ServiceResource resource = (await _resourceRegistryClient.GetResourceList(cancellationToken)).Find(r => r.Identifier == request.ResourceId); + List delegableRights = null; + + if (resource == null) + { + errors.Add(ValidationErrors.InvalidResource, "ResourceId"); + } + else + { + RightsQuery rightsQueryForApp = new RightsQuery + { + Type = RightsQueryType.AltinnApp, + To = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceDelegationAttribute, Value = request.PerformingResourceId.ValueSpan.ToString() }.SingleToList(), + From = resource.AuthorizationReference, + Resource = resource + }; + + try + { + delegableRights = await _pip.GetDelegableRightsByApp(rightsQueryForApp, cancellationToken); + } + catch (ValidationException) + { + errors.Add(ValidationErrors.MissingPolicy, "ResourceId"); + } + } + + if (errors.TryBuild(out var errorResult)) + { + return errorResult; + } + + // Fetch all existing delegations + List delegations = await _pip.GetInstanceDelegations(request, cancellationToken); + + // If nothing to delete just return with empty result set and no errors + if (delegations.Count == 0) + { + return new List(); + } + + List rightsToRevoke = await GetDelegationsToRevoke(delegations, delegableRights, request.InstanceDelegationSource, request.PerformingResourceId); + + if (rightsToRevoke.Count == 0) + { + errors.Add(ValidationErrors.MissingDelegableRights, "ResourceId"); + + if (errors.TryBuild(out errorResult)) + { + return errorResult; + } + } + + // Perform Revoke + List revokedResult = await _pap.TryWriteInstanceRevokeAllPolicyRules(rightsToRevoke, cancellationToken); + List result = TransformInstanceRightListToAppsInstanceDelegationResponseList(revokedResult); + result = RemoveInstanceIdFromResourceForRevokeResponseList(result); + + return result; + } + + private async Task> GetDelegationsToRevoke(List delegations, List delegableRights, InstanceDelegationSource instanceDelegationSource, ResourceIdUrn.ResourceId performingResourceId) + { + List rightsToRevoke = []; + + // Loop over delegations to deside wich to revoke + foreach (AppsInstanceDelegationResponse rules in delegations) + { + InstanceRight currentRightSetToRevoke = new() + { + InstanceRules = [] + }; + + // Check if the current right is delegable/revokable by the app and add it to the right list to revoke + foreach (InstanceRightDelegationResult right in rules.Rights.Where(r => delegableRights.Exists(d => RightMatch(d, r)))) + { + currentRightSetToRevoke.InstanceRules.Add(new InstanceRule { Action = ActionUrn.Parse(right.Action.Value.ToString()), Resource = right.Resource }); + } + + // If anything can be revoked add the rightSet to the list to revoke + if (currentRightSetToRevoke.InstanceRules.Count > 0) + { + (UuidType Type, Guid? Uuid) from = await TranslatePartyUuidToPersonOrganizationUuid(rules.From); + currentRightSetToRevoke.FromUuid = from.Uuid.Value; + currentRightSetToRevoke.FromType = from.Type; + (UuidType Type, Guid? Uuid) to = await TranslatePartyUuidToPersonOrganizationUuid(rules.To); + currentRightSetToRevoke.ToUuid = to.Uuid.Value; + currentRightSetToRevoke.ToType = to.Type; + currentRightSetToRevoke.ResourceId = rules.ResourceId; + currentRightSetToRevoke.InstanceId = rules.InstanceId; + currentRightSetToRevoke.InstanceDelegationSource = instanceDelegationSource; + currentRightSetToRevoke.InstanceDelegationMode = InstanceDelegationMode.Normal; + currentRightSetToRevoke.PerformedBy = performingResourceId.ValueSpan.ToString(); + currentRightSetToRevoke.PerformedByType = UuidType.Resource; + + // Add data to current rule and add it to the list + rightsToRevoke.Add(currentRightSetToRevoke); + } + } + + return rightsToRevoke; + } + + private static List TransformInstanceRightListToAppsInstanceDelegationResponseList(List input) + { + List result = []; + + foreach (InstanceRight instanceRight in input) + { + result.Add(TransformInstanceRightToAppsInstanceDelegationResponse(instanceRight)); + } + + return result; + } + + private static AppsInstanceRevokeResponse TransformInstanceRightToAppsInstanceDelegationResponse(InstanceRight input) + { + return new AppsInstanceRevokeResponse + { + From = PartyUrn.Parse(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyUuidAttribute + ":" + input.FromUuid.ToString()), + To = PartyUrn.Parse(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyUuidAttribute + ":" + input.ToUuid.ToString()), + ResourceId = input.ResourceId, + InstanceId = input.InstanceId, + InstanceDelegationMode = input.InstanceDelegationMode, + Rights = TransformInstanceRuleListToInstanceRightRevokeResultList(input.InstanceRules) + }; + } + + private static List TransformInstanceRuleListToInstanceRightRevokeResultList(List input) + { + List result = []; + + foreach (InstanceRule instanceRule in input) + { + result.Add(TransformInstanceRuleToInstanceRightRevokeResult(instanceRule)); + } + + return result; + } + + private static InstanceRightRevokeResult TransformInstanceRuleToInstanceRightRevokeResult(InstanceRule input) + { + return new InstanceRightRevokeResult + { + Action = ActionUrn.Parse(input.Action.ToString()), + Resource = input.Resource, + Status = input.CreatedSuccessfully ? RevokeStatus.Revoked : RevokeStatus.NotRevoked + }; + } + + private static bool RightMatch(Right rightAlowed, InstanceRightDelegationResult rightToRevoke) + { + if (rightAlowed.Action.Value != rightToRevoke.Action.Value.ValueSpan.ToString()) + { + return false; + } + + foreach (var resourcePart in rightAlowed.Resource) + { + bool valid = rightToRevoke.Resource.Exists(r => r.Value.PrefixSpan.ToString() == resourcePart.Id && r.Value.ValueSpan.ToString() == resourcePart.Value); + + if (!valid) + { + return false; + } + } + + return true; + } + + /// + public async Task> Revoke(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default) + { + (ValidationErrorBuilder Errors, InstanceRight RulesToHandle, List RightsAppCantHandle) input = await SetUpDelegationOrRevokeRequest(request, cancellationToken); + + if (input.Errors.TryBuild(out var errorResult)) + { + return errorResult; + } + + AppsInstanceRevokeResponse result = new() + { + From = request.From, + To = request.To, + ResourceId = request.ResourceId, + InstanceId = request.InstanceId, + InstanceDelegationMode = request.InstanceDelegationMode + }; + + List rights = await RevokeRights(input.RulesToHandle, input.RightsAppCantHandle, cancellationToken); + result.Rights = rights; + result = RemoveInstanceIdFromResourceForRevokeResponse(result); + + return result; + } + + private async Task<(ValidationErrorBuilder Errors, InstanceRight RulesToHandle, List RightsAppCantHandle)> SetUpDelegationOrRevokeRequest(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default) + { + ValidationErrorBuilder errors = default; + List rightsAppCantHandle = null; + InstanceRight rulesToHandle = null; + + // Fetch from and to from partyuuid + (UuidType Type, Guid? Uuid) from = await TranslatePartyUuidToPersonOrganizationUuid(request.From); + (UuidType Type, Guid? Uuid) to = await TranslatePartyUuidToPersonOrganizationUuid(request.To); + + if (from.Type == UuidType.NotSpecified) + { + errors.Add(ValidationErrors.InvalidPartyUrn, "From"); + } + + if (to.Type == UuidType.NotSpecified) + { + errors.Add(ValidationErrors.InvalidPartyUrn, "To"); + } + + // Validate Resource and instance 1. All rights include resource 2. All rights resource is identical to central value + AddValidationErrorsForResourceInstance(ref errors, request.Rights, request.ResourceId); + + // Fetch rights valid for delegation + ServiceResource resource = (await _resourceRegistryClient.GetResourceList(cancellationToken)).Find(r => r.Identifier == request.ResourceId); + List delegableRights = null; + + if (resource == null) + { + errors.Add(ValidationErrors.InvalidResource, appInstanceResourcePath); + } + else + { + RightsQuery rightsQueryForApp = new RightsQuery + { + Type = RightsQueryType.AltinnApp, + To = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceDelegationAttribute, Value = request.PerformedBy.ValueSpan.ToString() }.SingleToList(), + From = resource.AuthorizationReference, + Resource = resource + }; + + try + { + delegableRights = await _pip.GetDelegableRightsByApp(rightsQueryForApp, cancellationToken); + } + catch (ValidationException) + { + errors.Add(ValidationErrors.MissingPolicy, appInstanceResourcePath); + } + + if (delegableRights == null || delegableRights.Count == 0) + { + errors.Add(ValidationErrors.MissingDelegableRights, appInstanceResourcePath); + } + } + + if (!errors.IsEmpty) + { + return (errors, rulesToHandle, rightsAppCantHandle); + } + + rightsAppCantHandle = []; + + rulesToHandle = new InstanceRight + { + FromUuid = (Guid)from.Uuid, + FromType = from.Type, + ToUuid = (Guid)to.Uuid, + ToType = to.Type, + PerformedBy = request.PerformedBy.ValueSpan.ToString(), + PerformedByType = UuidType.Resource, + ResourceId = request.ResourceId, + InstanceId = request.InstanceId, + InstanceDelegationMode = request.InstanceDelegationMode, + InstanceDelegationSource = request.InstanceDelegationSource, + }; + + UrnJsonTypeValue instanceId = KeyValueUrn.CreateUnchecked($"{AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceInstanceAttribute}:{request.InstanceId}", AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceInstanceAttribute.Length + 1); + + foreach (RightInternal rightToHandle in request.Rights) + { + if (CheckIfInstanceIsDelegable(delegableRights, rightToHandle)) + { + rightToHandle.Resource.Add(instanceId); + rulesToHandle.InstanceRules.Add(new InstanceRule + { + Resource = rightToHandle.Resource, + Action = rightToHandle.Action + }); + } + else + { + rightsAppCantHandle.Add(rightToHandle); + } + } + + return (errors, rulesToHandle, rightsAppCantHandle); + } + + private async Task> RevokeRights(InstanceRight rulesToRevoke, List rightsAppCantRevoke, CancellationToken cancellationToken) + { + List rights = new List(); + + if (rulesToRevoke.InstanceRules.Count > 0) + { + InstanceRight delegationResult = await _pap.TryWriteInstanceRevokePolicyRules(rulesToRevoke, cancellationToken); + rights.AddRange(DelegationHelper.GetRightRevokeResultsFromInstanceRules(delegationResult)); + } + + if (rightsAppCantRevoke.Count > 0) + { + rights.AddRange(DelegationHelper.GetRightRevokeResultsFromFailedInternalRights(rightsAppCantRevoke)); + } + + return rights; + } + + private async Task> DelegateRights(InstanceRight rulesToDelegate, List rightsAppCantDelegate, CancellationToken cancellationToken) + { + List rights = new List(); + + if (rulesToDelegate.InstanceRules.Count > 0) + { + InstanceRight delegationResult = await _pap.TryWriteInstanceDelegationPolicyRules(rulesToDelegate, cancellationToken); + rights.AddRange(DelegationHelper.GetRightDelegationResultsFromInstanceRules(delegationResult)); + } + + if (rightsAppCantDelegate.Count > 0) + { + rights.AddRange(DelegationHelper.GetRightDelegationResultsFromFailedInternalRights(rightsAppCantDelegate)); + } + + return rights; + } + + /// + public async Task>> Get(AppsInstanceGetRequest request, CancellationToken cancellationToken = default) + { + ValidationErrorBuilder errors = default; + + // Fetch rights valid for delegation + ServiceResource resource = (await _resourceRegistryClient.GetResourceList(cancellationToken)).Find(r => r.Identifier == request.ResourceId); + List delegableRights = null; + + if (resource == null) + { + errors.Add(ValidationErrors.InvalidResource, "request.Resource"); + } + else + { + RightsQuery rightsQueryForApp = new RightsQuery + { + Type = RightsQueryType.AltinnApp, + To = new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceDelegationAttribute, Value = request.PerformingResourceId.ValueSpan.ToString() }.SingleToList(), + From = resource.AuthorizationReference, + Resource = resource + }; + + try + { + delegableRights = await _pip.GetDelegableRightsByApp(rightsQueryForApp, cancellationToken); + } + catch (ValidationException) + { + errors.Add(ValidationErrors.MissingPolicy, "request.Resource"); + } + + // The app must be able to do at least one delegation to be able to do GET call + if (delegableRights == null || !delegableRights.Exists(r => r.CanDelegate.HasValue && r.CanDelegate.Value)) + { + errors.Add(ValidationErrors.MissingDelegableRights, "request.Resource"); + } + } + + if (errors.TryBuild(out var errorResult)) + { + return errorResult; + } + + List result = await _pip.GetInstanceDelegations(request, cancellationToken); + result = RemoveInstanceIdFromResourceForDelegationResponseList(result); + return result; + } + + private static AppsInstanceRevokeResponse RemoveInstanceIdFromResourceForRevokeResponse(AppsInstanceRevokeResponse input) + { + foreach (var right in input.Rights) + { + right.Resource.RemoveAll(r => r.HasValue && r.Value.PrefixSpan.ToString() == AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceInstanceAttribute); + } + + return input; + } + + private static List RemoveInstanceIdFromResourceForRevokeResponseList(List input) + { + foreach (AppsInstanceRevokeResponse item in input) + { + RemoveInstanceIdFromResourceForRevokeResponse(item); + } + + return input; + } + + private static List RemoveInstanceIdFromResourceForDelegationResponseList(List input) + { + foreach (AppsInstanceDelegationResponse item in input) + { + RemoveInstanceIdFromResourceForDelegationResponse(item); + } + + return input; + } + + private static AppsInstanceDelegationResponse RemoveInstanceIdFromResourceForDelegationResponse(AppsInstanceDelegationResponse input) + { + foreach (var right in input.Rights) + { + right.Resource.RemoveAll(r => r.HasValue && r.Value.PrefixSpan.ToString() == AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceInstanceAttribute); + } + + return input; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AuthorizedPartiesService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AuthorizedPartiesService.cs new file mode 100644 index 00000000..61066f9e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AuthorizedPartiesService.cs @@ -0,0 +1,363 @@ +using System.Diagnostics; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Core.Services; + +/// +public class AuthorizedPartiesService : IAuthorizedPartiesService +{ + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IDelegationMetadataRepository _delegations; + private readonly IAltinnRolesClient _altinnRolesClient; + private readonly IProfileClient _profile; + + /// + /// Initializes a new instance of the class. + /// + /// Service for retrieving context information + /// Database repository for delegations + /// SBL bridge client for role and reportee information from Altinn 2 + /// Service implementation for user profile retrieval + public AuthorizedPartiesService(IContextRetrievalService contextRetrievalService, IDelegationMetadataRepository delegations, IAltinnRolesClient altinn2, IProfileClient profile) + { + _contextRetrievalService = contextRetrievalService; + _delegations = delegations; + _altinnRolesClient = altinn2; + _profile = profile; + } + + /// + public async Task> GetAuthorizedParties(BaseAttribute subjectAttribute, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) => subjectAttribute.Type switch + { + AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId => await GetAuthorizedPartiesForPerson(subjectAttribute.Value.ToString(), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationId => await GetAuthorizedPartiesForOrganization(subjectAttribute.Value, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserName => await GetAuthorizedPartiesForEnterpriseUser(subjectAttribute.Value, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid => await GetAuthorizedPartiesForPersonUuid(subjectAttribute.Value, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid => await GetAuthorizedPartiesForOrganizationUuid(subjectAttribute.Value, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid => await GetAuthorizedPartiesForEnterpriseUserUuid(subjectAttribute.Value, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute => await GetAuthorizedPartiesForParty(int.Parse(subjectAttribute.Value), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute => await GetAuthorizedPartiesForUser(int.Parse(subjectAttribute.Value), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken), + _ => throw new ArgumentException(message: $"Unknown attribute type: {subjectAttribute.Type}", paramName: nameof(subjectAttribute)) + }; + + /// + public async Task> GetAuthorizedPartiesForParty(int subjectPartyId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + Party subject = await _contextRetrievalService.GetPartyAsync(subjectPartyId, cancellationToken); + if (subject?.PartyTypeName == PartyType.Person) + { + UserProfile user = await _profile.GetUser(new() { Ssn = subject.SSN }, cancellationToken); + if (user != null) + { + return await GetAuthorizedPartiesForUser(user.UserId, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + } + + if (subject?.PartyTypeName == PartyType.Organisation) + { + return await BuildAuthorizedParties(0, subject.PartyId.SingleToList(), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForUser(int subjectUserId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + List keyRoleUnits = await _contextRetrievalService.GetKeyRolePartyIds(subjectUserId, cancellationToken); + return await BuildAuthorizedParties(subjectUserId, keyRoleUnits, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + /// + public async Task> GetAuthorizedPartiesForPerson(string subjectNationalId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + UserProfile user = await _profile.GetUser(new() { Ssn = subjectNationalId }, cancellationToken); + if (user != null) + { + return await GetAuthorizedPartiesForUser(user.UserId, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForPersonUuid(string subjectPersonUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + if (!Guid.TryParse(subjectPersonUuid, out Guid personUuid)) + { + throw new ArgumentException(message: $"Not a well-formed uuid: {subjectPersonUuid}", paramName: nameof(subjectPersonUuid)); + } + + UserProfile user = await _profile.GetUser(new() { UserUuid = personUuid }, cancellationToken); + if (user != null && user.Party.PartyTypeName == PartyType.Person) + { + return await GetAuthorizedPartiesForUser(user.UserId, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForOrganization(string subjectOrganizationNumber, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + Party subject = await _contextRetrievalService.GetPartyForOrganization(subjectOrganizationNumber, cancellationToken); + if (subject != null) + { + return await BuildAuthorizedParties(0, subject.PartyId.SingleToList(), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForOrganizationUuid(string subjectOrganizationUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + if (!Guid.TryParse(subjectOrganizationUuid, out Guid orgUuid)) + { + throw new ArgumentException(message: $"Not a well-formed uuid: {subjectOrganizationUuid}", paramName: nameof(subjectOrganizationUuid)); + } + + Party subject = await _contextRetrievalService.GetPartyByUuid(orgUuid, cancellationToken: cancellationToken); + if (subject != null && subject.PartyTypeName == PartyType.Organisation) + { + return await BuildAuthorizedParties(0, subject.PartyId.SingleToList(), includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForEnterpriseUser(string subjectEnterpriseUsername, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + UserProfile user = await _profile.GetUser(new() { Username = subjectEnterpriseUsername }, cancellationToken); + if (user != null && user.Party.PartyTypeName == PartyType.Organisation) + { + return await GetAuthorizedPartiesForUser(user.UserId, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + /// + public async Task> GetAuthorizedPartiesForEnterpriseUserUuid(string subjectEnterpriseUserUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken) + { + if (!Guid.TryParse(subjectEnterpriseUserUuid, out Guid enterpriseUserUuid)) + { + throw new ArgumentException(message: $"Not a well-formed uuid: {subjectEnterpriseUserUuid}", paramName: nameof(subjectEnterpriseUserUuid)); + } + + UserProfile user = await _profile.GetUser(new() { UserUuid = enterpriseUserUuid }, cancellationToken); + if (user != null && user.Party.PartyTypeName == PartyType.Organisation) + { + return await GetAuthorizedPartiesForUser(user.UserId, includeAltinn2AuthorizedParties, includeAuthorizedResourcesThroughRoles, cancellationToken); + } + + return await Task.FromResult(new List()); + } + + private async Task AddInstanceDelegations(List delegations, int subjectUserId, List subjectPartyIds, CancellationToken cancellationToken) + { + var toParties = new List(); + if (subjectPartyIds?.Count > 0) + { + toParties.AddRange(await _contextRetrievalService.GetPartiesAsync(subjectPartyIds, false, cancellationToken) ?? []); + } + + if (subjectUserId != 0) + { + var userProfile = await _profile.GetUser(new() { UserId = subjectUserId }, cancellationToken); + if (userProfile != null) + { + toParties.Add(userProfile.Party); + } + } + + if (toParties.Count > 0) + { + IEnumerable instanceDelegations = await _delegations.GetAllCurrentReceivedInstanceDelegations(toParties.Select(p => (Guid)p.PartyUuid).ToList(), cancellationToken); + var fromParties = await _contextRetrievalService.GetPartiesByUuids(instanceDelegations.Select(i => i.FromUuid), false, cancellationToken); + + foreach (var instanceDelegation in instanceDelegations) + { + if (fromParties.TryGetValue(instanceDelegation.FromUuid.ToString(), out Party fromParty)) + { + delegations.Add(new DelegationChange + { + ResourceId = instanceDelegation.ResourceId, + InstanceId = instanceDelegation.InstanceId, + FromUuidType = instanceDelegation.FromUuidType, + FromUuid = instanceDelegation.FromUuid, + OfferedByPartyId = fromParty.PartyId, + ToUuidType = instanceDelegation.ToUuidType, + ToUuid = instanceDelegation.ToUuid, + PerformedByUuidType = instanceDelegation.PerformedByType, + PerformedByUuid = instanceDelegation.PerformedBy, + DelegationChangeType = instanceDelegation.DelegationChangeType, + BlobStoragePolicyPath = instanceDelegation.BlobStoragePolicyPath, + BlobStorageVersionId = instanceDelegation.BlobStorageVersionId, + Created = instanceDelegation.Created + }); + } + } + } + } + + private async Task> BuildAuthorizedParties(int subjectUserId, List subjectPartyIds, bool includeAltinn2AuthorizedParties, bool includeResourcesThroughRoles, CancellationToken cancellationToken) + { + List result = []; + List a3AuthParties = []; + SortedDictionary authorizedPartyDict = []; + + if ((includeAltinn2AuthorizedParties || includeResourcesThroughRoles) && subjectUserId != 0) + { + List a2AuthParties = await _altinnRolesClient.GetAuthorizedPartiesWithRoles(subjectUserId, cancellationToken); + foreach (AuthorizedParty a2AuthParty in a2AuthParties) + { + if (includeResourcesThroughRoles) + { + await EnrichPartyWithAuthorizedResourcesThroughRoles(a2AuthParty, cancellationToken); + } + + authorizedPartyDict.Add(a2AuthParty.PartyId, a2AuthParty); + if (a2AuthParty.Subunits != null) + { + foreach (AuthorizedParty a2PartySubunit in a2AuthParty.Subunits) + { + authorizedPartyDict.Add(a2PartySubunit.PartyId, a2PartySubunit); + } + } + } + + result = a2AuthParties; + } + + List delegations = await _delegations.GetAllDelegationChangesForAuthorizedParties(subjectUserId != 0 ? subjectUserId.SingleToList() : null, subjectPartyIds, cancellationToken: cancellationToken); + await AddInstanceDelegations(delegations, subjectUserId, subjectPartyIds, cancellationToken); + + List fromPartyIds = delegations.Select(dc => dc.OfferedByPartyId).Distinct().ToList(); + List mainUnits = await _contextRetrievalService.GetMainUnits(fromPartyIds, cancellationToken); + + fromPartyIds.AddRange(mainUnits.Where(m => m.PartyId > 0).Select(m => m.PartyId.Value)); + SortedDictionary delegationParties = await _contextRetrievalService.GetPartiesAsSortedDictionaryAsync(fromPartyIds, true, cancellationToken); + + foreach (var delegation in delegations) + { + if (!authorizedPartyDict.TryGetValue(delegation.OfferedByPartyId, out AuthorizedParty authorizedParty)) + { + // Check if offering party has a main unit / is itself a subunit. + MainUnit mainUnit = await _contextRetrievalService.GetMainUnit(delegation.OfferedByPartyId, cancellationToken); // Since all mainunits were retrieved earlier results are in cache. + if (mainUnit?.PartyId > 0) + { + if (authorizedPartyDict.TryGetValue(mainUnit.PartyId.Value, out AuthorizedParty mainUnitAuthParty)) + { + authorizedParty = mainUnitAuthParty.Subunits.Find(p => p.PartyId == delegation.OfferedByPartyId); + + if (authorizedParty == null) + { + if (!delegationParties.TryGetValue(delegation.OfferedByPartyId, out Party party)) + { + throw new UnreachableException($"Get AuthorizedParties failed to find subunit party for an existing active delegation from OfferedByPartyId: {delegation.OfferedByPartyId}"); + } + + authorizedParty = new AuthorizedParty(party); + mainUnitAuthParty.Subunits.Add(authorizedParty); + } + + authorizedPartyDict.Add(authorizedParty.PartyId, authorizedParty); + } + else + { + if (!delegationParties.TryGetValue(mainUnit.PartyId.Value, out Party mainUnitParty)) + { + throw new UnreachableException($"Get AuthorizedParties failed to find mainunit party: {mainUnit.PartyId.Value} for an existing active delegation from subunit OfferedByPartyId: {delegation.OfferedByPartyId}"); + } + + mainUnitParty.OnlyHierarchyElementWithNoAccess = true; + mainUnitAuthParty = new AuthorizedParty(mainUnitParty, false); + + // Find the authorized party as a subunit on the main unit + Party subunit = mainUnitParty.ChildParties.Find(p => p.PartyId == delegation.OfferedByPartyId); + if (subunit == null) + { + throw new UnreachableException($"Get AuthorizedParties failed to find subunit party: {delegation.OfferedByPartyId}, as child on the mainunit: {mainUnitParty.PartyId}"); + } + + authorizedParty = new(subunit); + mainUnitAuthParty.Subunits = new() { authorizedParty }; + authorizedPartyDict.Add(mainUnitParty.PartyId, mainUnitAuthParty); + authorizedPartyDict.Add(authorizedParty.PartyId, authorizedParty); + a3AuthParties.Add(mainUnitAuthParty); + } + } + else + { + // Authorized party is not a subunit. Find party to add. + if (!delegationParties.TryGetValue(delegation.OfferedByPartyId, out Party party)) + { + throw new UnreachableException($"Get AuthorizedParties failed to find party for an existing active delegation from OfferedByPartyId: {delegation.OfferedByPartyId}"); + } + + authorizedParty = new AuthorizedParty(party); + authorizedPartyDict.Add(authorizedParty.PartyId, authorizedParty); + a3AuthParties.Add(authorizedParty); + } + } + + if (authorizedParty.OnlyHierarchyElementWithNoAccess) + { + // Delegation is from a MainUnit which has been added previously as hierarchy element. All children need to be added before resource enrichment + if (!delegationParties.TryGetValue(authorizedParty.PartyId, out Party mainUnitParty)) + { + throw new UnreachableException($"Get AuthorizedParties failed to find mainunit party: {authorizedParty.PartyId} already added previously. Should not be possible."); + } + + foreach (Party subunit in mainUnitParty.ChildParties) + { + // Only add subunits which so far has not been already processed with some authorized access + if (!authorizedPartyDict.TryGetValue(subunit.PartyId, out AuthorizedParty authorizedSubUnit)) + { + authorizedParty.Subunits.Add(new(subunit)); + } + } + } + + if (!string.IsNullOrWhiteSpace(delegation.InstanceId)) + { + authorizedParty.EnrichWithResourceInstanceAccess(delegation.ResourceId, delegation.InstanceId); + } + else + { + authorizedParty.EnrichWithResourceAccess(delegation.ResourceId); + } + } + + result.AddRange(a3AuthParties); + return result; + } + + private async Task EnrichPartyWithAuthorizedResourcesThroughRoles(AuthorizedParty party, CancellationToken cancellationToken) + { + if (party.AuthorizedRoles?.Count > 0) + { + IDictionary> subjectResources = await _contextRetrievalService.GetSubjectResources(party.AuthorizedRoles.Select(r => $"{AltinnXacmlConstants.MatchAttributeIdentifiers.RoleAttribute}:{r.ToLower()}"), cancellationToken); + party.AuthorizedResources.AddRange(subjectResources.Keys.SelectMany(subject => subjectResources[subject].Where(resource => resource != null && resource.Value != null).Select(resource => resource.Value))); + } + + if (party.Subunits?.Count > 0) + { + foreach (AuthorizedParty subunit in party.Subunits) + { + await EnrichPartyWithAuthorizedResourcesThroughRoles(subunit, cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ContextRetrievalService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ContextRetrievalService.cs new file mode 100644 index 00000000..f137ca51 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ContextRetrievalService.cs @@ -0,0 +1,522 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Register.Models; +using Authorization.Platform.Authorization.Models; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Core.Services; + +/// +/// Context Retrieval Service +/// +public class ContextRetrievalService : IContextRetrievalService +{ + private readonly CacheConfig _cacheConfig; + private readonly IMemoryCache _memoryCache; + private readonly IResourceRegistryClient _resourceRegistryClient; + private readonly IAltinnRolesClient _altinnRolesClient; + private readonly IPartiesClient _partiesClient; + private readonly IAuthenticationClient _authenticationClient; + + /// + /// Initializes a new instance of the class + /// + /// Cache config + /// The cache handler + /// The client for integration with the ResourceRegistry + /// The client for integration with the SBL Bridge for role information + /// The client for integration + /// The client for integration with authentication + public ContextRetrievalService(IOptions cacheConfig, IMemoryCache memoryCache, IResourceRegistryClient resourceRegistryClient, IAltinnRolesClient altinnRolesClient, IPartiesClient partiesClient, IAuthenticationClient authenticationClient) + { + _cacheConfig = cacheConfig.Value; + _memoryCache = memoryCache; + _resourceRegistryClient = resourceRegistryClient; + _altinnRolesClient = altinnRolesClient; + _partiesClient = partiesClient; + _authenticationClient = authenticationClient; + } + + /// + public async Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + string cacheKey = $"Roles_u:{coveredByUserId}_p:{offeredByPartyId}"; + + if (!_memoryCache.TryGetValue(cacheKey, out List roles)) + { + roles = await _altinnRolesClient.GetDecisionPointRolesForUser(coveredByUserId, offeredByPartyId, cancellationToken) ?? new List(); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.AltinnRoleCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, roles, cacheEntryOptions); + } + + return roles; + } + + /// + public async Task> GetRolesForDelegation(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + string cacheKey = $"DelgRoles_u:{coveredByUserId}_p:{offeredByPartyId}"; + + if (!_memoryCache.TryGetValue(cacheKey, out List roles)) + { + roles = await _altinnRolesClient.GetRolesForDelegation(coveredByUserId, offeredByPartyId, cancellationToken) ?? new List(); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.AltinnRoleCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, roles, cacheEntryOptions); + } + + return roles; + } + + /// + public async Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default) + { + List result = await GetPartiesAsync(partyId.SingleToList(), cancellationToken: cancellationToken); + return result.FirstOrDefault(); + } + + /// + public async Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + List parties = new List(); + List partyIdsNotInCache = new List(); + + foreach (int partyId in partyIds.Distinct()) + { + if (_memoryCache.TryGetValue($"p:{partyId}|inclSubunits:{includeSubunits}", out Party party)) + { + parties.Add(party); + } + else + { + partyIdsNotInCache.Add(partyId); + } + } + + if (partyIdsNotInCache.Count == 0) + { + return parties; + } + + List remainingParties = await _partiesClient.GetPartiesAsync(partyIdsNotInCache, includeSubunits, cancellationToken); + if (remainingParties.Count > 0) + { + foreach (Party party in remainingParties) + { + if (party?.PartyId != null) + { + parties.Add(party); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PartyCacheTimeout, 0)); + _memoryCache.Set($"p:{party.PartyId}|inclSubunits:{includeSubunits}", party, cacheEntryOptions); + } + } + } + + return parties; + } + + /// + public async Task> GetPartiesAsSortedDictionaryAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + SortedDictionary dict = []; + + List parties = await GetPartiesAsync(partyIds, includeSubunits, cancellationToken); + foreach (Party party in parties) + { + dict.Add(party.PartyId, party); + } + + return dict; + } + + /// + public async Task GetPartyByUuid(Guid partyUuid, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + Dictionary parties = await GetPartiesByUuids(partyUuid.SingleToList(), includeSubunits, cancellationToken); + parties.TryGetValue(partyUuid.ToString(), out Party result); + return result; + } + + /// + public async Task GetSystemUserById(int partyId, string systemUserUuid, CancellationToken cancellationToken = default) + { + SystemUser systemUser = await _authenticationClient.GetSystemUser(partyId, systemUserUuid, cancellationToken); + return systemUser; + } + + /// + public async Task> GetDefaultRightsForRegisteredSystem(string productId, CancellationToken cancellationToken = default) + { + List defaultRight = await _authenticationClient.GetDefaultRightsForRegisteredSystem(productId, cancellationToken); + return defaultRight; + } + + /// + public async Task> GetPartiesByUuids(IEnumerable partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + Dictionary parties = new Dictionary(); + List partyKeysNotInCache = new List(); + + foreach (Guid partyKey in partyUuids.Distinct()) + { + if (_memoryCache.TryGetValue($"uuid:{partyKey}|inclSubunits:{includeSubunits}", out Party party)) + { + parties.Add($"{party.PartyUuid}", party); + } + else + { + partyKeysNotInCache.Add(partyKey); + } + } + + if (partyKeysNotInCache.Count == 0) + { + return parties; + } + + List remainingParties = await _partiesClient.GetPartiesAsync(partyKeysNotInCache, includeSubunits, cancellationToken); + if (remainingParties.Count > 0) + { + foreach (Party party in remainingParties) + { + if (party != null && party.PartyUuid != Guid.Empty) + { + parties.Add($"{party.PartyUuid}", party); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PartyCacheTimeout, 0)); + _memoryCache.Set($"uuid:{party.PartyUuid}|inclSubunits:{includeSubunits}", party, cacheEntryOptions); + } + } + } + + return parties; + } + + /// + public async Task GetPartyForOrganization(string organizationNumber, CancellationToken cancellationToken = default) + { + string cacheKey = $"orgNo:{organizationNumber}"; + + if (!_memoryCache.TryGetValue(cacheKey, out Party party)) + { + party = await _partiesClient.LookupPartyBySSNOrOrgNo(new PartyLookup { OrgNo = organizationNumber }, cancellationToken); + + if (party != null) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PartyCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, party, cacheEntryOptions); + } + } + + return party; + } + + /// + public async Task GetPartyForPerson(string ssn, CancellationToken cancellationToken = default) + { + string cacheKey = $"ssn:{ssn}"; + + if (!_memoryCache.TryGetValue(cacheKey, out Party party)) + { + party = await _partiesClient.LookupPartyBySSNOrOrgNo(new PartyLookup { Ssn = ssn }, cancellationToken); + + if (party != null) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PartyCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, party, cacheEntryOptions); + } + } + + return party; + } + + /// + public async Task> GetKeyRolePartyIds(int userId, CancellationToken cancellationToken = default) + { + string cacheKey = $"KeyRolePartyIds_u:{userId}"; + if (!_memoryCache.TryGetValue(cacheKey, out List keyrolePartyIds)) + { + keyrolePartyIds = await _partiesClient.GetKeyRoleParties(userId, cancellationToken); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.KeyRolePartyIdsCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, keyrolePartyIds, cacheEntryOptions); + } + + return keyrolePartyIds; + } + + /// + public async Task> GetMainUnits(List subunitPartyIds, CancellationToken cancellationToken = default) + { + List allMainUnits = new List(); + List subunitsNotInCache = new List(); + + foreach (int subunitPartyId in subunitPartyIds.Distinct()) + { + if (_memoryCache.TryGetValue($"subunit:{subunitPartyId}", out MainUnit mainUnit)) + { + allMainUnits.Add(mainUnit); + } + else + { + subunitsNotInCache.Add(subunitPartyId); + } + } + + if (subunitsNotInCache.Count == 0) + { + return allMainUnits; + } + + List remainingMainUnits = await _partiesClient.GetMainUnits(new MainUnitQuery { PartyIds = subunitsNotInCache }, cancellationToken); + if (remainingMainUnits.Count > 0) + { + foreach (MainUnit mainUnit in remainingMainUnits) + { + allMainUnits.Add(mainUnit); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.MainUnitCacheTimeout, 0)); + _memoryCache.Set($"subunit:{mainUnit.SubunitPartyId}", mainUnit, cacheEntryOptions); + } + } + + return allMainUnits; + } + + /// + public async Task GetMainUnit(int subunitPartyId, CancellationToken cancellationToken = default) + { + if (_memoryCache.TryGetValue($"subunit:{subunitPartyId}", out MainUnit mainUnit)) + { + return mainUnit; + } + + List mainUnits = await GetMainUnits(subunitPartyId.SingleToList(), cancellationToken); + return mainUnits.FirstOrDefault(); + } + + /// + public async Task GetResource(string resourceRegistryId, CancellationToken cancellationToken = default) + { + string cacheKey = $"rrId:{resourceRegistryId}"; + + if (!_memoryCache.TryGetValue(cacheKey, out ServiceResource resource)) + { + resource = await _resourceRegistryClient.GetResource(resourceRegistryId, cancellationToken); + + if (resource != null) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.ResourceRegistryResourceCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, resource, cacheEntryOptions); + } + } + + return resource; + } + + /// + public async Task> GetResources(CancellationToken cancellationToken = default) + { + string cacheKey = $"resources:all"; + + if (!_memoryCache.TryGetValue(cacheKey, out List resources)) + { + resources = await _resourceRegistryClient.GetResources(cancellationToken); + + if (resources?.Count > 0) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.ResourceRegistryResourceCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, resources, cacheEntryOptions); + } + } + + return resources; + } + + /// + public async Task> GetResourceList(CancellationToken cancellationToken = default) + { + string cacheKey = $"resources:resourceList"; + + if (!_memoryCache.TryGetValue(cacheKey, out List resources)) + { + resources = await _resourceRegistryClient.GetResourceList(cancellationToken); + + if (resources?.Count > 0) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.ResourceRegistryResourceCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, resources, cacheEntryOptions); + } + } + + return resources; + } + + /// + public async Task GetResourceFromResourceList(string resourceId = null, string org = null, string app = null, string serviceCode = null, string serviceEditionCode = null, CancellationToken cancellationToken = default) + { + string cacheKey = $"r:{resourceId},o:{org},a:{app},sc:{serviceCode},sec:{serviceEditionCode}"; + + if (!_memoryCache.TryGetValue(cacheKey, out ServiceResource resource)) + { + List resources = await GetResourceList(cancellationToken); + foreach (ServiceResource serviceResource in resources) + { + if (resourceId != null && (serviceResource.ResourceType != ResourceType.Altinn2Service || serviceResource.ResourceType != ResourceType.AltinnApp) && + serviceResource.Identifier == resourceId) + { + resource = serviceResource; + break; + } + + if (org != null && app != null && serviceResource.ResourceType == ResourceType.AltinnApp && + serviceResource.ResourceReferences.Exists(rf => rf.ReferenceType == ReferenceType.ApplicationId && string.Equals(rf.Reference, $"{org}/{app}", StringComparison.OrdinalIgnoreCase))) + { + resource = serviceResource; + break; + } + + if (serviceCode != null && serviceEditionCode != null && serviceResource.ResourceType == ResourceType.Altinn2Service && + serviceResource.ResourceReferences.Exists(rf => rf.ReferenceType == ReferenceType.ServiceCode && string.Equals(rf.Reference, $"{serviceCode}", StringComparison.OrdinalIgnoreCase)) && + serviceResource.ResourceReferences.Exists(rf => rf.ReferenceType == ReferenceType.ServiceEditionCode && string.Equals(rf.Reference, $"{serviceEditionCode}", StringComparison.OrdinalIgnoreCase))) + { + resource = serviceResource; + break; + } + } + + if (resource != null) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.ResourceRegistryResourceCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, resource, cacheEntryOptions); + } + } + + return resource; + } + + /// + public async Task GetPartyForUser(int userId, int partyId, CancellationToken cancellationToken = default) + { + List partyList = await GetPartiesForUser(userId, cancellationToken); + + foreach (Party party in partyList) + { + if (party?.PartyId == partyId) + { + return party; + } + + Party childParty = party?.ChildParties?.FirstOrDefault(p => p.PartyId == partyId); + if (childParty != null) + { + return childParty; + } + } + + return null; + } + + /// + public async Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default) + { + Dictionary> subjectResources = new Dictionary>(); + List subjectKeysNotInCache = new List(); + + foreach (string subjectKey in subjects.Distinct()) + { + if (_memoryCache.TryGetValue(subjectKey, out IEnumerable resources)) + { + subjectResources.Add(subjectKey, resources); + } + else + { + subjectKeysNotInCache.Add(subjectKey); + } + } + + if (subjectKeysNotInCache.Count == 0) + { + return subjectResources; + } + + IDictionary> remainingSubjectResources = await _resourceRegistryClient.GetSubjectResources(subjectKeysNotInCache, cancellationToken); + foreach (string subject in subjectKeysNotInCache) + { + IEnumerable resources; + if (remainingSubjectResources.TryGetValue(subject, out resources)) + { + subjectResources.Add(subject, resources); + } + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.ResourceRegistrySubjectResourcesCacheTimeout, 0)); + _memoryCache.Set(subject, resources ?? Enumerable.Empty(), cacheEntryOptions); + } + + return subjectResources; + } + + private async Task> GetPartiesForUser(int userId, CancellationToken cancellationToken = default) + { + string cacheKey = $"userId:{userId}"; + + if (_memoryCache.TryGetValue(cacheKey, out List partyListFromCache)) + { + return partyListFromCache; + } + + List partyList = await _partiesClient.GetPartiesForUserAsync(userId, cancellationToken); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PartyCacheTimeout, 0)); + + _memoryCache.Set(cacheKey, partyList, cacheEntryOptions); + + return partyList; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/DelegationRequestService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/DelegationRequestService.cs new file mode 100644 index 00000000..ced6e5e0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/DelegationRequestService.cs @@ -0,0 +1,29 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + /// The servcie implementation for operations related to working with delegation requests + /// + public class DelegationRequestService : IDelegationRequests + { + private readonly IDelegationRequestsWrapper _delegationRequestsWrapper; + + /// + /// Initializes a new instance of the class + /// + /// Delegation request client wrapper + public DelegationRequestService(IDelegationRequestsWrapper delegationRequestsWrapper) + { + _delegationRequestsWrapper = delegationRequestsWrapper; + } + + /// + public async Task GetDelegationRequestsAsync(string who, string serviceCode, int? serviceEditionCode, RestAuthorizationRequestDirection direction, List status = null, string continuation = "") + { + return await _delegationRequestsWrapper.GetDelegationRequestsAsync(who, serviceCode, serviceEditionCode, direction, status, continuation); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAltinn2RightsService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAltinn2RightsService.cs new file mode 100644 index 00000000..92e0c683 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAltinn2RightsService.cs @@ -0,0 +1,34 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces; + +/// +/// Used by Altinn for managing delegations +/// +public interface IAltinn2RightsService +{ + /// + /// Gets all offered single rights delegations for a reportee + /// + /// reportee + /// Cancellation token + /// list of delgations + Task> GetOfferedRights(int partyId, CancellationToken cancellationToken = default); + + /// + /// Gets all received single rights delegations for a reportee + /// + /// reportee + /// Cancellation token + /// list of delgations + Task> GetReceivedRights(int partyId, CancellationToken cancellationToken = default); + + /// + /// Operation to clear a recipients cached rights from a given reportee/from party, and the recipients authorized parties/reportees + /// + /// The party id of the from party + /// Attribute model identifying the recipient/to party + /// Cancellation token + /// HttpResponse + Task ClearReporteeRights(int fromPartyId, BaseAttribute toAttribute, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAppsInstanceDelegationService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAppsInstanceDelegationService.cs new file mode 100644 index 00000000..7a74a542 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAppsInstanceDelegationService.cs @@ -0,0 +1,50 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.Authorization.ProblemDetails; + +namespace Altinn.AccessManagement.Core.Services.Interfaces; + +/// +/// Contains all actions related to app instance delegation from Apps +/// +public interface IAppsInstanceDelegationService +{ + /// + /// Gets all rights available for delegation by an app for a given app instance + /// + /// App instance delegation check request model + /// The + /// Boolean whether the app instance delegation was successful + public Task> DelegationCheck(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default); + + /// + /// Delegate access to an app instance + /// + /// App instance delegation request model + /// The + /// Boolean whether the app instance delegation was successful + public Task> Delegate(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default); + + /// + /// Revokes access to an app instance + /// + /// the request data collected in a dto + /// The + /// An entity containing the list of instance delegation rights that was revoked + public Task> Revoke(AppsInstanceDelegationRequest request, CancellationToken cancellationToken = default); + + /// + /// Revokes all access to an app instance tha app is authorized to handle + /// + /// the request data + /// The + /// A list of entities containing a list of instance delegation rights that was revoked + public Task>> RevokeAll(AppsInstanceGetRequest request, CancellationToken cancellationToken = default); + + /// + /// Gets app instance delegation + /// + /// the request data collected in a dto + /// The + /// Boolean whether the app instance delegation was found + public Task>> Get(AppsInstanceGetRequest request, CancellationToken cancellationToken = default); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAuthorizedPartiesService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAuthorizedPartiesService.cs new file mode 100644 index 00000000..0612041c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IAuthorizedPartiesService.cs @@ -0,0 +1,99 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces; + +/// +/// Service for operations regarding retrieval of authorized parties (aka reporteelist) +/// +public interface IAuthorizedPartiesService +{ + /// + /// Gets the full unfiltered list of all authorized parties a given user or organization have some access for in Altinn + /// + /// Attribute identifying the user or organization retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedParties(BaseAttribute subjectAttribute, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given user can represent in Altinn + /// + /// The user id of the user to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForUser(int subjectUserId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given user or organization have some access for in Altinn + /// + /// The party id of the user or organization to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForParty(int subjectPartyId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given person can represent in Altinn + /// + /// The national identity number of the person to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForPerson(string subjectNationalId, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given person can represent in Altinn + /// + /// The uuid of the person to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForPersonUuid(string subjectPersonUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given organization can represent in Altinn + /// + /// The organization number of the organization to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForOrganization(string subjectOrganizationNumber, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given organization can represent in Altinn + /// + /// The organization uuid of the organization to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForOrganizationUuid(string subjectOrganizationUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given enterprise user can represent in Altinn + /// + /// The username of the enterprise user to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForEnterpriseUser(string subjectEnterpriseUsername, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); + + /// + /// Gets the full unfiltered list of authorized parties the given enterprise user can represent in Altinn + /// + /// The uuid of the enterprise user to retrieve the authorized party list for + /// Whether Authorized Parties from Altinn 2 should be included in the result set + /// Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// The unfiltered party list + Task> GetAuthorizedPartiesForEnterpriseUserUuid(string subjectEnterpriseUserUuid, bool includeAltinn2AuthorizedParties, bool includeAuthorizedResourcesThroughRoles, CancellationToken cancellationToken); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IContextRetrievalService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IContextRetrievalService.cs new file mode 100644 index 00000000..a59f6feb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IContextRetrievalService.cs @@ -0,0 +1,185 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.Platform.Register.Models; +using Authorization.Platform.Authorization.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces; + +/// +/// Defines the interface for the context retrieval service defining operations for getting external context information for decision point requests +/// +public interface IContextRetrievalService +{ + /// + /// Get the decision point roles for the loggedin user for a selected party + /// + /// the logged in user id + /// the partyid of the person/org the logged in user is representing + /// The + /// list of actors that the logged in user can represent + Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default); + + /// + /// Get the roles the user has for a given reportee, as basis for evaluating rights for delegation. + /// For any user having HADM this means, getting additional roles as DAGL etc. + /// + /// the user id + /// the partyid of the person/org the user is representing + /// The + /// list of actors that the logged in user can represent + Task> GetRolesForDelegation(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default); + + /// + /// Gets a single party by its party id + /// + /// The party id + /// The + /// Party + Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default); + + /// + /// Gets a list of parties by their party ids + /// + /// List of partyIds to lookup + /// (Optional) Whether subunits should be included as ChildParties, if any of the lookup party IDs are for a main unit + /// The + /// List of parties + Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Gets a dictionary of parties by their party ids + /// + /// List of partyIds to lookup + /// (Optional) Whether subunits should be included as ChildParties, if any of the lookup party IDs are for a main unit + /// The + /// List of parties + Task> GetPartiesAsSortedDictionaryAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Gets a single party by its party uuid + /// + /// The party uuid + /// (Optional) Whether subunits should be included as ChildParties, if any of the parties are a main unit + /// The + /// Party + Task GetPartyByUuid(Guid partyUuid, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Gets a dictionary of parties by their party uuids + /// + /// Collection of party uuids to lookup + /// (Optional) Whether subunits should be included as ChildParties, if any of the parties are a main unit + /// The + /// Dictionary of parties + Task> GetPartiesByUuids(IEnumerable partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default); + + /// + /// Gets a system user by the uuid and owning party + /// + /// partyId for the system user owning party + /// the identifier og the system user + /// The + /// + Task GetSystemUserById(int partyId, string systemUserUuid, CancellationToken cancellationToken = default); + + /// + /// Gets the registered default rights for a given system type + /// + /// the system to fetch the default rights for + /// The + /// + Task> GetDefaultRightsForRegisteredSystem(string productId, CancellationToken cancellationToken = default); + + /// + /// Gets the party of an organization + /// + /// The organization number to lookup party + /// The + /// Party + Task GetPartyForOrganization(string organizationNumber, CancellationToken cancellationToken = default); + + /// + /// Gets the party of a person + /// + /// The social security number to lookup party + /// The + /// Party + Task GetPartyForPerson(string ssn, CancellationToken cancellationToken = default); + + /// + /// Gets a list of PartyIds the given user id has key role access to (where the user inherit delegations to their organization) + /// + /// The user id + /// The + /// list of PartyIds where the logged in user have key role access + Task> GetKeyRolePartyIds(int userId, CancellationToken cancellationToken = default); + + /// + /// Gets a main unit for the input sub unit partyId. If the input partyId is not a sub unit the response model will have null values for main unit properties. + /// + /// The list of PartyId to check and retrieve any main units for + /// The + /// main units + Task> GetMainUnits(List subunitPartyIds, CancellationToken cancellationToken = default); + + /// + /// Gets a main unit for the input sub unit partyId. If the input partyId is not a sub unit the response model will have null values for main unit properties. + /// + /// The PartyId to check and retrieve any main unit for + /// The + /// main unit + Task GetMainUnit(int subunitPartyId, CancellationToken cancellationToken = default); + + /// + /// Gets a single resoure by it's resource id if registered in the Resource Registry + /// + /// The identifier of the resource in the Resource Registry + /// The + /// The resource if exists + Task GetResource(string resourceRegistryId, CancellationToken cancellationToken = default); + + /// + /// Gets a list of all resources from the Resource Registry + /// + /// The + /// The resource list + Task> GetResources(CancellationToken cancellationToken = default); + + /// + /// Gets a list of all available resources including Altinn Apps, Altinn 2 services and resources from the Resource Registry + /// + /// The + /// The resource list + Task> GetResourceList(CancellationToken cancellationToken = default); + + /// + /// Gets a single resource from the list of all available resources including Altinn Apps, Altinn 2 services and resources from the Resource Registry, if it exists. + /// + /// The resource id + /// Org code of the resource/app owner + /// The app name + /// Tha Altinn 2 Service Code + /// The Altinn 2 Service Edition Code + /// The + /// The resource if exists + Task GetResourceFromResourceList(string resourceId = null, string org = null, string app = null, string serviceCode = null, string serviceEditionCode = null, CancellationToken cancellationToken = default); + + /// + /// Gets a Party based on partyId if the party is in the users reporteelist + /// + /// The id of the authenticated user + /// The party Id of the party to retrieve + /// The + /// Party that corresponds to partyId parameter if it's in the users reporteelist + Task GetPartyForUser(int userId, int partyId, CancellationToken cancellationToken = default); + + /// + /// Gets all resources having any of the request subjects in one or more resource policy rules + /// + /// Urn string representation of the subjects to lookup resources for + /// The + /// Dictionary of all resources per subject, having policy rules with the subject + Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequests.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequests.cs new file mode 100644 index 00000000..84f2c2b0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequests.cs @@ -0,0 +1,23 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Interface for the delegation request service, defining operations for working with delegation requests + /// + public interface IDelegationRequests + { + /// + /// Returns a list of DelegationRequests + /// + /// The reportee to get delegation requests for + /// Optional filter parameter for serviceCode + /// Optional filter parameter for serviceEditionCode + /// Optional filter parameter for directions (incoming, outgoing). If no direction is specified, both incoming and outgoing requests will be returned + /// Optional filter parameter for status. (created, unopened, approved, rejected, deleted) + /// Optional filter parameter for continuationToken + /// List of delegation requests + Task GetDelegationRequestsAsync(string who, string serviceCode, int? serviceEditionCode, RestAuthorizationRequestDirection direction, List status, string continuation); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequestsWrapper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequestsWrapper.cs new file mode 100644 index 00000000..fdfa119e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IDelegationRequestsWrapper.cs @@ -0,0 +1,23 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Interface for a client wrapper for integration with SBL bridge delegation request API + /// + public interface IDelegationRequestsWrapper + { + /// + /// Returns a list of DelegationRequests + /// + /// The reportee to get delegation requests for + /// Optional filter parameter for serviceCode + /// Optional filter parameter for serviceEditionCode + /// Optional filter parameter for directions (incoming, outgoing). If no direction is specified, both incoming and outgoing requests will be returned + /// Optional filter parameter for status. (created, unopened, approved, rejected, deleted) + /// Optional filter parameter for continuationToken + /// List of delegation requests + Task GetDelegationRequestsAsync(string who, string serviceCode, int? serviceEditionCode, RestAuthorizationRequestDirection direction, List status, string continuation); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IEventMapperService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IEventMapperService.cs new file mode 100644 index 00000000..306e380f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IEventMapperService.cs @@ -0,0 +1,17 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Service mapping internal delegation changes to delegation change events + /// + public interface IEventMapperService + { + /// + /// Maps to DelegationChangeEventList used for pushing delegation events to the event queue + /// + /// List of delegation changes from postgreSQL + /// DelegationChangeEventList + public DelegationChangeEventList MapToDelegationChangeEventList(List delegationChanges); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IMaskinportenSchemaService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IMaskinportenSchemaService.cs new file mode 100644 index 00000000..2ceed7f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IMaskinportenSchemaService.cs @@ -0,0 +1,65 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Service for operations regarding MaskinportenSchema delegations + /// + public interface IMaskinportenSchemaService + { + /// + /// Performs a delegation check for the authenticated user on behalf of the from party, to find if and what rights the user can delegate to the to party, for the given maskinportenschema. + /// + /// The user id of the authenticated user performing the delegation + /// The authentication level of the authenticated user performing the delegation + /// The model describing the right delegation check to perform + /// CancellationToken + /// The result of the delegation status check + public Task DelegationCheck(int authenticatedUserId, int authenticatedUserAuthlevel, RightsDelegationCheckRequest request, CancellationToken cancellationToken = default); + + /// + /// Gets all offered maskinporten schema delegations for a reportee + /// + /// reportee that delegated resources + /// CancellationToken + /// list of delgations + public Task> GetOfferedMaskinportenSchemaDelegations(AttributeMatch party, CancellationToken cancellationToken = default); + + /// + /// Gets all received maskinporten schema delegations for a reportee + /// + /// reportee that delegated resources + /// CancellationToken + /// list of delgations + public Task> GetReceivedMaskinportenSchemaDelegations(AttributeMatch party, CancellationToken cancellationToken = default); + + /// + /// Gets all the delegations for an admin or owner + /// + /// the organisation number of the supplier org + /// the organisation number of the consumer of the resource + /// the scope of the resource + /// CancellationToken + /// list of delgations + public Task> GetMaskinportenDelegations(string supplierOrg, string consumerOrg, string scope, CancellationToken cancellationToken = default); + + /// + /// Performs the delegation on behalf of the from party + /// + /// The user id of the authenticated user performing the delegation + /// The authentication level of the authenticated user performing the delegation + /// The delegation + /// CancellationToken + /// The result of the delegation + public Task DelegateMaskinportenSchema(int authenticatedUserId, int authenticatedUserAuthlevel, DelegationLookup delegation, CancellationToken cancellationToken = default); + + /// + /// Operation to revoke a maskinporten schema delegation + /// + /// The user id of the authenticated user deleting the delegation + /// The delegation lookup model + /// CancellationToken + /// The result of the deletion + public Task RevokeMaskinportenSchemaDelegation(int authenticatedUserId, DelegationLookup delegation, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyAdministrationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyAdministrationPoint.cs new file mode 100644 index 00000000..7e29e7b7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyAdministrationPoint.cs @@ -0,0 +1,68 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Defines the interface for the Policy Administration Point + /// + public interface IPolicyAdministrationPoint + { + /// + /// Returns a bool based on writing file to storage was successful + /// + /// Unique identifier of the organisation responsible for the app. + /// Application identifier which is unique within an organisation. + /// A stream containing the content of the policy file + /// CancellationToken + /// + Task WritePolicyAsync(string org, string app, Stream fileStream, CancellationToken cancellationToken = default); + + /// + /// Trys to sort and store the set of rules as delegation policy files in blob storage. + /// + /// The set of rules to be delegated + /// CancellationToken + /// The list of rules with created Id and result status + Task> TryWriteDelegationPolicyRules(List rules, CancellationToken cancellationToken = default); + + /// + /// Trys to sort and store the set of rules as delegation policy files in blob storage. + /// + /// The set of instance rules to be delegated + /// CancellationToke + /// The list of instance rules with created Id and result status + Task TryWriteInstanceDelegationPolicyRules(InstanceRight rules, CancellationToken cancellationToken = default); + + /// + /// Trys to sort and revoke the set of rules as delegation policy files in blob storage. + /// + /// The set of instance rules to be revoked + /// CancellationToke + /// The list of instance rules with created Id and result status + Task TryWriteInstanceRevokePolicyRules(InstanceRight rules, CancellationToken cancellationToken = default); + + /// + /// Trys to sort and revoke the set of rules as delegation policy files in blob storage. + /// + /// The set of instance rules to be revoked + /// CancellationToke + /// The list of instance rules with created Id and result status + Task> TryWriteInstanceRevokeAllPolicyRules(List rights, CancellationToken cancellationToken = default); + + /// + /// Trys to sort and delete the set of rules matching the list of ruleMatches to delete from delegation policy files in blob storage. + /// + /// Entity to define which rules to be deleted + /// CancellationToken + /// The list of rules with created Id and result status + Task> TryDeleteDelegationPolicyRules(List rulesToDelete, CancellationToken cancellationToken = default); + + /// + /// Deletes a List of policies based on input list of matches to remove + /// + /// entity containing match for all the policies to delete + /// CancellationToken + /// A list containing all the policies that is deleted + Task> TryDeleteDelegationPolicies(List policiesToDelete, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyInformationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyInformationPoint.cs new file mode 100644 index 00000000..96d7388a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyInformationPoint.cs @@ -0,0 +1,72 @@ +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Defines the required methods for an implementation of a policy information point. + /// + public interface IPolicyInformationPoint + { + /// + /// Gets the rules for a list of authorization resources, given by a list of offeredbyPartyIds to a list of coveredbyIds + /// + /// The list of resource identifiers, either from the resource registry or altinn app ids + /// the list of offeredby party ids + /// the list of coveredby party ids + /// the list of coveredby user ids + /// CancellationToken + /// a list of rules that match the lists of org/apps, offeredby ids, and coveredby ids + Task> GetRulesAsync(List resourceIds, List offeredByPartyIds, List coveredByPartyIds, List coveredByUserIds, CancellationToken cancellationToken = default); + + /// + /// Gets the all rights a user have for a given reportee and resource + /// + /// The query model + /// Whether the response should return all possible rights for the resource, not just the rights the user have access to + /// Whether the query is only rights the user is allowed to delegate to others + /// The + /// A list of rights + Task> GetRights(RightsQuery rightsQuery, bool returnAllPolicyRights = false, bool getDelegableRights = false, CancellationToken cancellationToken = default); + + /// + /// Gets the all rights an app have right to delegate + /// + /// The query model + /// The + /// A list of rights + Task> GetDelegableRightsByApp(RightsQuery rightsQuery, CancellationToken cancellationToken = default); + + /// + /// Finds all delegation changes for a given user, reportee and app/resource context + /// + /// The object containing the resource/app that's checked for delegation changes + /// Whether instance delegations should be included in the lookup + /// The + /// A list of delegation changes that's stored in the database + Task GetAllDelegations(DelegationChangeInput request, bool includeInstanceDelegations = false, CancellationToken cancellationToken = default); + + /// + /// Finds all InstanceDelegations for a given Resource/Instance combination + /// + /// The request to descripe what delegations to fetch + /// The + /// all delegations for a given Resource/Instance combination + Task> GetInstanceDelegations(AppsInstanceGetRequest request, CancellationToken cancellationToken); + + /// + /// Finds all active received delegations (not including maskinporten schema) from db, both directly delegated to the party or through key roles if the party is a person + /// + /// Party id of a user or organization + /// The + /// + Task> GetReceivedDelegationFromRepository(int partyId, CancellationToken cancellationToken = default); + + /// + /// Finds all active offered delegations (not including maskinporten schema) from db, both directly delegated from the party or from it's main unit if the party is a subunit + /// + /// Party id of a user or organization + /// The + /// + Task> GetOfferedDelegationsFromRepository(int partyId, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyRetrievalPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyRetrievalPoint.cs new file mode 100644 index 00000000..efa83951 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IPolicyRetrievalPoint.cs @@ -0,0 +1,44 @@ +using Altinn.Authorization.ABAC.Xacml; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Defines the interface for the Policy Retrival Point + /// + public interface IPolicyRetrievalPoint + { + /// + /// Returns a policy based on the context request + /// + /// The context request + /// The + /// XacmlPolicy + Task GetPolicyAsync(XacmlContextRequest request, CancellationToken cancellationToken = default); + + /// + /// Returns a policy based the org and app + /// + /// The organisation + /// The app + /// The + /// XacmlPolicy + Task GetPolicyAsync(string org, string app, CancellationToken cancellationToken = default); + + /// + /// Returns a policy based the resourceRegistryId + /// + /// The Resource Registry Id + /// The + /// XacmlPolicy + Task GetPolicyAsync(string resourceRegistry, CancellationToken cancellationToken = default); + + /// + /// Returns a specific version of a policy if it exits on the provided path + /// + /// The blobstorage path to the policy file + /// The specific blob storage version to get + /// The + /// XacmlPolicy and ETag tuple + Task GetPolicyVersionAsync(string policyPath, string version, CancellationToken cancellationToken = default); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IResourceAdministrationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IResourceAdministrationPoint.cs new file mode 100644 index 00000000..897d9a15 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IResourceAdministrationPoint.cs @@ -0,0 +1,39 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Service for creating and updating Resources in AccessMAnagment existing in the ResourceRegister + /// + public interface IResourceAdministrationPoint + { + /// + /// Creates or Updates a list of Resources from ResourceRegister + /// + /// The resources to add or update + /// + Task> TryWriteResourceFromResourceRegister(List resources); + + /// + /// Gets a list of Resources from ResourceRegister + /// + /// The type of resource to be filtered + /// resource list based on resource type + Task> GetResources(ResourceType resourceType); + + /// + /// Gets a list of Resources from ResourceRegister + /// + /// The scope of the resource + /// resource list based on given scope + Task> GetResources(string scope); + + /// + /// Integration point for retrieving a single resoure by it's resource id + /// + /// The identifier of the resource in the Resource Registry + /// The resource if exists + Task GetResource(string resourceRegistryId); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/ISingleRightsService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/ISingleRightsService.cs new file mode 100644 index 00000000..0a366a03 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/ISingleRightsService.cs @@ -0,0 +1,55 @@ +using Altinn.AccessManagement.Core.Models; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Service for operations regarding single rights delegations + /// + public interface ISingleRightsService + { + /// + /// Performs a delegation check for the authenticated user on behalf of the from party, to find if and what rights the user can delegate to the to party, for the given resource. + /// + /// The user id of the authenticated user performing the delegation + /// The authentication level of the authenticated user performing the delegation + /// The model describing the right delegation check to perform + /// The result of the delegation status check + public Task RightsDelegationCheck(int authenticatedUserId, int authenticatedUserAuthlevel, RightsDelegationCheckRequest request); + + /// + /// Performs the delegation on behalf of the from party + /// + /// The user id of the authenticated user performing the delegation + /// The authentication level of the authenticated user performing the delegation + /// The delegation + /// CancellationToken + /// The result of the delegation + public Task DelegateRights(int authenticatedUserId, int authenticatedUserAuthlevel, DelegationLookup delegation, CancellationToken cancellationToken = default); + + /// + /// Gets all offered single rights delegations for a reportee + /// + /// reportee + /// Cancellation token + /// list of delgations + Task> GetOfferedRights(AttributeMatch reportee, CancellationToken cancellationToken = default); + + /// + /// Gets all received single rights delegations for a reportee + /// + /// reportee + /// Cancellation token + /// list of delgations + public Task> GetReceivedRights(AttributeMatch reportee, CancellationToken cancellationToken = default); + + /// + /// Operation to revoke a single rights delegation + /// + /// authenticed user + /// delegation + /// http context token + /// The result of the deletion + Task RevokeRightsDelegation(int authenticatedUserId, DelegationLookup delegation, CancellationToken cancellationToken); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IUserProfileLookupService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IUserProfileLookupService.cs new file mode 100644 index 00000000..cb3faa1e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/Interfaces/IUserProfileLookupService.cs @@ -0,0 +1,17 @@ +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Core.Services.Interfaces +{ + /// + /// Defines the interface for the service wrapping UserProfile lookup with lastname verification and preventing users for guessing too many faulty combination of SSN/Username and Last Name + /// + public interface IUserProfileLookupService + { + /// + /// Gets the UserProfile of a user if the provided identifier and lastname is matching last name from freg + /// + /// Party + Task GetUserProfile(int authnUserId, UserProfileLookup lookupIdentifier, string lastName); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/MaskinportenSchemaService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/MaskinportenSchemaService.cs new file mode 100644 index 00000000..b690f81e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/MaskinportenSchemaService.cs @@ -0,0 +1,485 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Core.Utilities; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using Microsoft.Extensions.Logging; +using static Altinn.AccessManagement.Core.Constants.AltinnXacmlConstants; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + public class MaskinportenSchemaService : IMaskinportenSchemaService + { + private readonly ILogger _logger; + private readonly IDelegationMetadataRepository _delegationRepository; + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IResourceAdministrationPoint _resourceAdministrationPoint; + private readonly IPolicyInformationPoint _pip; + private readonly IPolicyAdministrationPoint _pap; + + /// + /// Initializes a new instance of the class. + /// + /// handler for logger + /// delegation change handler + /// Service for retrieving context information + /// handler for resource registry + /// Service implementation for policy information point + /// Service implementation for policy administration point + public MaskinportenSchemaService(ILogger logger, IDelegationMetadataRepository delegationRepository, IContextRetrievalService contextRetrievalService, IResourceAdministrationPoint resourceAdministrationPoint, IPolicyInformationPoint pip, IPolicyAdministrationPoint pap) + { + _logger = logger; + _delegationRepository = delegationRepository; + _contextRetrievalService = contextRetrievalService; + _resourceAdministrationPoint = resourceAdministrationPoint; + _pip = pip; + _pap = pap; + } + + /// + public async Task DelegationCheck(int authenticatedUserId, int authenticatedUserAuthlevel, RightsDelegationCheckRequest request, CancellationToken cancellationToken = default) + { + (DelegationCheckResponse result, ServiceResource resource, Party fromParty) = await ValidateDelegationCheckRequest(request); + if (!result.IsValid) + { + return result; + } + + // Get all delegable rights + RightsQuery rightsQuery = RightsHelper.GetRightsQuery(authenticatedUserId, fromParty.PartyId, resource); + List allDelegableRights = await _pip.GetRights(rightsQuery, getDelegableRights: true, returnAllPolicyRights: true, cancellationToken: cancellationToken); + if (allDelegableRights == null || allDelegableRights.Count == 0) + { + result.Errors.Add("right[0].Resource", $"No delegable rights could be found for the resource: {resource}"); + return result; + } + + // Build result model with status + foreach (Right right in allDelegableRights) + { + RightDelegationCheckResult rightDelegationStatus = new RightDelegationCheckResult + { + RightKey = right.RightKey, + Resource = right.Resource, + Action = right.Action, + Status = (right.CanDelegate.HasValue && right.CanDelegate.Value) ? DelegableStatus.Delegable : DelegableStatus.NotDelegable + }; + + if (right.RightSources.Exists(rs => rs.MinimumAuthenticationLevel > authenticatedUserAuthlevel) && rightDelegationStatus.Status == DelegableStatus.Delegable) + { + // Only relevant if delegationCheck passes the other requirements + int minimumAuthenticationLevel = right.RightSources.Find(rs => rs.MinimumAuthenticationLevel > authenticatedUserAuthlevel).MinimumAuthenticationLevel; + rightDelegationStatus.Status = DelegableStatus.NotDelegable; + rightDelegationStatus.Details = new List + { + new Detail + { + Code = DetailCode.InsufficientAuthenticationLevel, + Description = $"Authenticated user does not meet the required security level for resource. Minimum authentication level is {minimumAuthenticationLevel}", + Parameters = new Dictionary>() + { + { + "MinimumAuthenticationLevel", new List { new AttributeMatch { Id = MatchAttributeCategory.MinimumAuthenticationLevel, Value = minimumAuthenticationLevel.ToString() } } + } + } + }, + }; + } + else + { + rightDelegationStatus.Details = RightsHelper.AnalyzeDelegationAccessReason(right); + } + + result.RightDelegationCheckResults.Add(rightDelegationStatus); + } + + return result; + } + + /// + public async Task DelegateMaskinportenSchema(int authenticatedUserId, int authenticatedUserAuthlevel, DelegationLookup delegation, CancellationToken cancellationToken = default) + { + (DelegationActionResult result, ServiceResource resource, Party fromParty, Party toParty) = await ValidateMaskinportenDelegationModel(DelegationActionType.Delegation, delegation); + if (!result.IsValid) + { + return result; + } + + // Verify authenticated users delegable rights + RightsQuery rightsQuery = RightsHelper.GetRightsQuery(authenticatedUserId, fromParty.PartyId, resource); + List usersDelegableRights = await _pip.GetRights(rightsQuery, getDelegableRights: true, cancellationToken: cancellationToken); + if (usersDelegableRights == null || usersDelegableRights.Count == 0) + { + result.Errors.Add("right[0].Resource", $"Authenticated user does not have any delegable rights for the resource: {resource.Identifier}"); + return result; + } + + if (usersDelegableRights.Any(r => r.RightSources.Any(rs => rs.MinimumAuthenticationLevel > authenticatedUserAuthlevel))) + { + result.Errors.Add("right[0].Resource", $"Authenticated user does not meet the required security level requirement for resource: {resource.Identifier}"); + return result; + } + + // Perform delegation + List rulesToDelegate = new List(); + foreach (Right rightToDelegate in usersDelegableRights) + { + rulesToDelegate.Add(new Rule + { + DelegatedByUserId = authenticatedUserId, + OfferedByPartyId = fromParty.PartyId, + CoveredBy = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = toParty.PartyId.ToString() } }, + Resource = rightToDelegate.Resource, + Action = rightToDelegate.Action + }); + } + + List delegationResult = await _pap.TryWriteDelegationPolicyRules(rulesToDelegate, cancellationToken); + + // Map response + if (delegationResult.All(r => r.CreatedSuccessfully)) + { + result.Rights = DelegationHelper.GetRightDelegationResultsFromRules(delegationResult); + return await Task.FromResult(result); + } + else if (delegationResult.Any(r => r.CreatedSuccessfully)) + { + // Partial delegation of rules should not really be possible. Return success but log error? + _logger.LogError("One or more rules could not be delegated.\n{result}", delegationResult); + result.Rights = DelegationHelper.GetRightDelegationResultsFromRules(delegationResult); + return await Task.FromResult(result); + } + + result.Errors.Add("Rights", "Delegation was not able complete"); + return result; + } + + /// + public async Task> GetOfferedMaskinportenSchemaDelegations(AttributeMatch party, CancellationToken cancellationToken = default) + { + if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.SocialSecurityNumberAttribute) + { + throw new ArgumentException($"Maskinporten schema delegations is not supported between persons. Invalid argument: {party.Id}"); + } + + int offeredByPartyId = 0; + if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute) + { + Party offeredByParty = await _contextRetrievalService.GetPartyForOrganization(party.Value, cancellationToken); + offeredByPartyId = offeredByParty.PartyId; + } + else if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute && (!int.TryParse(party.Value, out offeredByPartyId) || offeredByPartyId == 0)) + { + throw new ArgumentException($"The specified PartyId is not a valid. Invalid argument: {party.Value}"); + } + + return await GetOfferedDelegations(offeredByPartyId, ResourceType.MaskinportenSchema); + } + + /// + public async Task> GetReceivedMaskinportenSchemaDelegations(AttributeMatch party, CancellationToken cancellationToken = default) + { + if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.SocialSecurityNumberAttribute) + { + throw new ArgumentException($"Maskinporten schema delegations is not supported between persons. Invalid argument: {party.Id}"); + } + + int coveredByPartyId = 0; + if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute) + { + Party coveredByParty = await _contextRetrievalService.GetPartyForOrganization(party.Value, cancellationToken); + coveredByPartyId = coveredByParty.PartyId; + } + else if (party.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute && (!int.TryParse(party.Value, out coveredByPartyId) || coveredByPartyId == 0)) + { + throw new ArgumentException($"The specified PartyId is not a valid. Invalid argument: {party.Value}"); + } + + return await GetReceivedDelegations(coveredByPartyId, ResourceType.MaskinportenSchema); + } + + /// + public async Task> GetMaskinportenDelegations(string supplierOrg, string consumerOrg, string scope, CancellationToken cancellationToken = default) + { + int consumerPartyId = 0; + if (!string.IsNullOrEmpty(consumerOrg)) + { + Party consumerParty = await _contextRetrievalService.GetPartyForOrganization(consumerOrg, cancellationToken); + if (consumerParty == null) + { + throw new ArgumentException($"The specified consumerOrg: {consumerOrg}, is not a valid organization number", nameof(consumerOrg)); + } + + consumerPartyId = consumerParty.PartyId; + } + + int supplierPartyId = 0; + if (!string.IsNullOrEmpty(supplierOrg)) + { + Party supplierParty = await _contextRetrievalService.GetPartyForOrganization(supplierOrg, cancellationToken); + if (supplierParty == null) + { + throw new ArgumentException($"The specified supplierOrg: {supplierOrg}, is not a valid organization number", nameof(supplierOrg)); + } + + supplierPartyId = supplierParty.PartyId; + } + + if (!RegexUtil.IsValidMaskinportenScope(scope)) + { + throw new ArgumentException($"Is not well formatted: {scope}", nameof(scope)); + } + + return await GetAllMaskinportenSchemaDelegations(supplierPartyId, consumerPartyId, scope, cancellationToken); + } + + /// + public async Task RevokeMaskinportenSchemaDelegation(int authenticatedUserId, DelegationLookup delegation, CancellationToken cancellationToken = default) + { + (DelegationActionResult result, ServiceResource resource, Party fromParty, Party toParty) = await ValidateMaskinportenDelegationModel(DelegationActionType.Revoke, delegation); + if (!result.IsValid) + { + return result; + } + + List policiesToDelete = DelegationHelper.GetRequestToDeleteResourceRegistryService(authenticatedUserId, resource.Identifier, fromParty.PartyId, toParty.PartyId); + + await _pap.TryDeleteDelegationPolicies(policiesToDelete, cancellationToken); + return result; + } + + private async Task<(DelegationActionResult Result, ServiceResource ServiceResource, Party FromParty, Party ToParty)> ValidateMaskinportenDelegationModel(DelegationActionType delegationAction, DelegationLookup delegation) + { + DelegationActionResult result = new DelegationActionResult { To = delegation.To, Rights = new List() }; + + // Verify request is for single resource registry id + if (delegation.Rights?.Count != 1) + { + result.Errors.Add("Rights", "This operation only support requests specifying a single right identifying a Maskinporten schema resource registered in the Altinn Resource Registry"); + return (result, null, null, null); + } + + Right right = delegation.Rights.First(); + DelegationHelper.TryGetResourceFromAttributeMatch(right.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + + if (resourceMatchType != ResourceAttributeMatchType.ResourceRegistry) + { + result.Errors.Add("right[0].Resource", $"This operation only support requests for resources from the Altinn Resource Registry using the {AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute} attribute id"); + return (result, null, null, null); + } + + // Verify resource registry id is a valid MaskinportenSchema + ServiceResource resource = await _contextRetrievalService.GetResourceFromResourceList(resourceRegistryId, org, app, serviceCode, serviceEditionCode); + if (resource == null || (delegationAction == DelegationActionType.Delegation && !resource.Delegable)) + { + result.Errors.Add("right[0].Resource", $"The resource: {resourceRegistryId}, does not exist or is not available for delegation"); + return (result, null, null, null); + } + + if (resource.ResourceType != ResourceType.MaskinportenSchema) + { + result.Errors.Add("right[0].Resource", $"This operation only support requests for Maskinporten schema resources. Invalid resource: {resource}"); + return (result, null, null, null); + } + + // Verify and get From reportee party of the delegation + Party fromParty = null; + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(delegation.From, out string fromOrgNo)) + { + fromParty = await _contextRetrievalService.GetPartyForOrganization(fromOrgNo); + } + else if (DelegationHelper.TryGetPartyIdFromAttributeMatch(delegation.From, out int fromPartyId)) + { + List fromPartyLookup = await _contextRetrievalService.GetPartiesAsync(fromPartyId.SingleToList()); + fromParty = fromPartyLookup.FirstOrDefault(); + } + + if (fromParty == null || fromParty.PartyTypeName != PartyType.Organisation) + { + result.Errors.Add("From", $"Maskinporten schema delegation can only be delegated from a valid organization (identified by either {AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute} or {AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute} attribute id). Invalid value: {delegation.From.FirstOrDefault()?.Value}"); + return (result, resource, null, null); + } + + // Verify and get To recipient party of the delegation + Party toParty = null; + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(delegation.To, out string toOrgNo)) + { + toParty = await _contextRetrievalService.GetPartyForOrganization(toOrgNo); + } + else if (DelegationHelper.TryGetPartyIdFromAttributeMatch(delegation.To, out int toPartyId)) + { + List toPartyLookup = await _contextRetrievalService.GetPartiesAsync(toPartyId.SingleToList()); + toParty = toPartyLookup.FirstOrDefault(); + } + + if (toParty == null || toParty.PartyTypeName != PartyType.Organisation) + { + result.Errors.Add("To", $"Maskinporten schema delegation can only be delegated to a valid organization (identified by either {AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute} or {AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute} attribute id). Invalid value: {delegation.To.FirstOrDefault()?.Value}"); + return (result, resource, null, null); + } + + if (fromParty.PartyId.Equals(toParty.PartyId) && delegationAction == DelegationActionType.Delegation) + { + result.Errors.Add("To", $"Maskinporten schema delegation can not have the same party in the From and To Attributes: {delegation.To.FirstOrDefault()?.Value}"); + return (result, resource, null, null); + } + + return (result, resource, fromParty, toParty); + } + + private async Task> GetOfferedDelegations(int offeredByPartyId, ResourceType resourceType) + { + List delegations = new List(); + List delegationChanges = await _delegationRepository.GetOfferedResourceRegistryDelegations(offeredByPartyId, resourceTypes: resourceType.SingleToList()); + + if (delegationChanges?.Count == 0) + { + return delegations; + } + + return await BuildDelegationsResponse(delegationChanges); + } + + private async Task> GetReceivedDelegations(int coveredByPartyId, ResourceType resourceType) + { + List delegations = new List(); + List delegationChanges = await _delegationRepository.GetReceivedResourceRegistryDelegationsForCoveredByPartys(coveredByPartyId.SingleToList(), resourceTypes: resourceType.SingleToList()); + + if (delegationChanges?.Count == 0) + { + return delegations; + } + + return await BuildDelegationsResponse(delegationChanges); + } + + private async Task> GetAllMaskinportenSchemaDelegations(int supplierPartyId, int consumerPartyId, string scopes, CancellationToken cancellationToken = default) + { + List delegations = new List(); + + List resources = await _resourceAdministrationPoint.GetResources(scopes); + if (resources.Count == 0) + { + return delegations; + } + + List delegationChanges = await _delegationRepository.GetResourceRegistryDelegationChanges(resources.Select(d => d.Identifier).ToList(), consumerPartyId, supplierPartyId, ResourceType.MaskinportenSchema, cancellationToken); + if (delegationChanges.Count == 0) + { + return delegations; + } + + return await BuildDelegationsResponse(delegationChanges, resources); + } + + private async Task> BuildDelegationsResponse(List delegationChanges, List resources = null) + { + List delegations = new List(); + List parties = delegationChanges.Select(d => d.OfferedByPartyId).ToList(); + parties.AddRange(delegationChanges.Select(d => d.CoveredByPartyId).Select(ds => Convert.ToInt32(ds)).ToList()); + + List partyList = await _contextRetrievalService.GetPartiesAsync(parties); + + foreach (DelegationChange delegationChange in delegationChanges) + { + Party offeredByParty = partyList.Find(p => p.PartyId == delegationChange.OfferedByPartyId); + Party coveredByParty = partyList.Find(p => p.PartyId == delegationChange.CoveredByPartyId); + ServiceResource resource = resources?.FirstOrDefault(r => r.Identifier == delegationChange.ResourceId); + delegations.Add(BuildDelegationModel(delegationChange, offeredByParty, coveredByParty, resource)); + } + + return delegations; + } + + private static Delegation BuildDelegationModel(DelegationChange delegationChange, Party offeredByParty, Party coveredByParty, ServiceResource resource) + { + ResourceType resourceType = Enum.TryParse(delegationChange.ResourceType, true, out ResourceType type) ? type : ResourceType.Default; + Delegation delegation = new Delegation + { + OfferedByPartyId = delegationChange.OfferedByPartyId, + OfferedByName = offeredByParty?.Name, + OfferedByOrganizationNumber = offeredByParty?.OrgNumber, + CoveredByPartyId = delegationChange.CoveredByPartyId, + CoveredByName = coveredByParty?.Name, + CoveredByOrganizationNumber = coveredByParty?.OrgNumber, + PerformedByUserId = delegationChange.PerformedByUserId, + PerformedByPartyId = delegationChange.PerformedByPartyId, + Created = delegationChange.Created ?? DateTime.MinValue, + ResourceId = delegationChange.ResourceId, + ResourceType = resourceType + }; + + if (resource != null) + { + delegation.ResourceTitle = resource?.Title; + delegation.Description = resource?.Description; + delegation.RightDescription = resource?.RightDescription; + delegation.ResourceReferences = resource?.ResourceReferences; + delegation.HasCompetentAuthority = resource?.HasCompetentAuthority; + } + + return delegation; + } + + private async Task<(DelegationCheckResponse Result, ServiceResource Resource, Party FromParty)> ValidateDelegationCheckRequest(RightsDelegationCheckRequest request) + { + DelegationCheckResponse result = new DelegationCheckResponse { From = request.From, RightDelegationCheckResults = new() }; + + DelegationHelper.TryGetResourceFromAttributeMatch(request.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + + if (resourceMatchType == ResourceAttributeMatchType.None) + { + result.Errors.Add("right[0].Resource", $"The specified resource is not recognized. The operation only support requests for a single resource from the Altinn Resource Registry, identified by using the {AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute} attribute id."); + return (result, null, null); + } + + // Verify resource is valid + ServiceResource resource = await _contextRetrievalService.GetResourceFromResourceList(resourceRegistryId, org, app, serviceCode, serviceEditionCode); + if (resource == null || !resource.Delegable) + { + result.Errors.Add("right[0].Resource", $"The resource does not exist or is not available for delegation"); + return (result, resource, null); + } + + if (resource.ResourceType != ResourceType.MaskinportenSchema) + { + result.Errors.Add("right[0].Resource", $"This operation only supports MaskinportenSchema resources. Please use the Single Rights DelegationCheck API. Invalid resource: {resourceRegistryId}. Invalid resource type: {resource.ResourceType}"); + return (result, resource, null); + } + + // Verify and get From reportee party of the delegation + Party fromParty = null; + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(request.From, out string fromOrgNo)) + { + fromParty = await _contextRetrievalService.GetPartyForOrganization(fromOrgNo); + } + else if (DelegationHelper.TryGetPartyIdFromAttributeMatch(request.From, out int fromPartyId)) + { + List fromPartyLookup = await _contextRetrievalService.GetPartiesAsync(fromPartyId.SingleToList()); + fromParty = fromPartyLookup.FirstOrDefault(); + } + + if (fromParty == null) + { + // This shouldn't really happen, as to get here the request must have been authorized for the From reportee, but the register integration could fail. + result.Errors.Add("From", $"Could not identify the From party. Please try again."); + return (result, resource, null); + } + + if (fromParty.Organization == null) + { + result.Errors.Add("From", $"Delegation of MaskinportenSchema can only be performed by organizations."); + return (result, resource, null); + } + + return (result, resource, fromParty); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyAdministrationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyAdministrationPoint.cs new file mode 100644 index 00000000..affbe1bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyAdministrationPoint.cs @@ -0,0 +1,985 @@ +using System.Collections.Generic; +using System.Net; +using System.Text.Json; +using System.Threading; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Platform.Register.Models; +using Azure; +using Azure.Storage.Blobs.Models; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Logging; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + /// The Policy Administration Point responsible for storing and modifying delegation policies + /// + public class PolicyAdministrationPoint : IPolicyAdministrationPoint + { + private readonly ILogger _logger; + private readonly IPolicyRetrievalPoint _prp; + private readonly IPolicyFactory _policyFactory; + private readonly IDelegationMetadataRepository _delegationRepository; + private readonly IDelegationChangeEventQueue _eventQueue; + private readonly int delegationChangeEventQueueErrorId = 911; + + /// + /// Initializes a new instance of the class. + /// + /// The policy retrieval point. + /// The policy repository (blob storage). + /// The delegation change repository (postgresql). + /// The delegation change event queue service to post events for any delegation change. + /// Logger instance. + public PolicyAdministrationPoint(IPolicyRetrievalPoint policyRetrievalPoint, IPolicyFactory policyFactory, IDelegationMetadataRepository delegationRepository, IDelegationChangeEventQueue eventQueue, ILogger logger) + { + _prp = policyRetrievalPoint; + _policyFactory = policyFactory; + _delegationRepository = delegationRepository; + _eventQueue = eventQueue; + _logger = logger; + } + + /// + public async Task WritePolicyAsync(string org, string app, Stream fileStream, CancellationToken cancellationToken = default) + { + if (fileStream == null) + { + throw new ArgumentException("The policy file can not be null"); + } + + string filePath = PolicyHelper.GetAltinnAppsPolicyPath(org, app); + Response response = await _policyFactory.Create(filePath).WritePolicyAsync(fileStream, cancellationToken: cancellationToken); + + return response?.GetRawResponse()?.Status == (int)HttpStatusCode.Created; + } + + private async Task WriteInstanceRevokePolicyInternal(InstanceRight rules, CancellationToken cancellationToken = default) + { + // Check for a current delegation change from postgresql + (XacmlPolicy ExistingDelegationPolicy, string PolicyPath) policyData = await GetExistingPolicy(null, rules, cancellationToken); + string policyPath = policyData.PolicyPath; + + // if no delegations exist all revoke must already be performed + if (policyData.ExistingDelegationPolicy == null) + { + return true; + } + + var policyClient = _policyFactory.Create(policyPath); + + if (!await policyClient.PolicyExistsAsync(cancellationToken)) + { + return false; + } + + string leaseId = await policyClient.TryAcquireBlobLease(cancellationToken); + if (leaseId != null) + { + try + { + // Build delegation XacmlPolicy either as a new policy or add rules to existing + XacmlPolicy delegationPolicy = BuildInstanceRevokePolicy(policyData.ExistingDelegationPolicy, rules); + + // Write delegation policy to blob storage + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(delegationPolicy); + Response blobResponse = + await policyClient.WritePolicyConditionallyAsync(dataStream, leaseId, cancellationToken); + Response httpResponse = blobResponse.GetRawResponse(); + if (httpResponse.Status != (int)HttpStatusCode.Created) + { + int status = httpResponse.Status; + string reasonPhrase = httpResponse.ReasonPhrase; + _logger.LogError( + "Writing of delegation policy at path: {policyPath} failed. Response Status Code:\n{status}. Response Reason Phrase:\n{reasonPhrase}", + policyPath, + status, + reasonPhrase); + return false; + } + + int rulesInPolicy = delegationPolicy.Rules.Count; + DelegationChangeType changeType; + if (rulesInPolicy > 0) + { + changeType = DelegationChangeType.Revoke; + } + else + { + changeType = DelegationChangeType.RevokeLast; + } + + // Update db and use new version from latest update + return await WritePolicyUpdateToDB(policyPath, blobResponse.Value.VersionId, changeType, rules, cancellationToken); + } + finally + { + policyClient.ReleaseBlobLease(leaseId, CancellationToken.None); + } + } + + LogLeaseLockError(policyPath); + return false; + } + + private void LogLeaseLockError(string policyPath, bool logAsError = false) + { + if (logAsError) + { + _logger.LogError("Could not acquire blob lease lock on delegation policy at path: {policyPath}", policyPath); + } + else + { + _logger.LogInformation("Could not acquire blob lease lock on delegation policy at path: {policyPath}", policyPath); + } + } + + private async Task WriteInstanceDelegationPolicyInternal(string policyPath, InstanceRight rules, CancellationToken cancellationToken = default) + { + // Check for a current delegation change from postgresql + (XacmlPolicy ExistingDelegationPolicy, string PolicyPath) policyData = await GetExistingPolicy(policyPath, rules, cancellationToken); + policyPath = policyData.PolicyPath; + var policyClient = _policyFactory.Create(policyPath); + + if (!await policyClient.PolicyExistsAsync(cancellationToken)) + { + // Create a new empty blob for lease locking + await policyClient.WritePolicyAsync(new MemoryStream(), cancellationToken: cancellationToken); + } + + string leaseId = await policyClient.TryAcquireBlobLease(cancellationToken); + if (leaseId != null) + { + try + { + // Build delegation XacmlPolicy either as a new policy or add rules to existing + XacmlPolicy delegationPolicy = BuildInstanceDelegationPolicy(policyData.ExistingDelegationPolicy, rules); + + // Write delegation policy to blob storage + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(delegationPolicy); + Response blobResponse = + await policyClient.WritePolicyConditionallyAsync(dataStream, leaseId, cancellationToken); + Response httpResponse = blobResponse.GetRawResponse(); + if (httpResponse.Status != (int)HttpStatusCode.Created) + { + int status = httpResponse.Status; + string reasonPhrase = httpResponse.ReasonPhrase; + _logger.LogError( + "Writing of delegation policy at path: {policyPath} failed. Response Status Code:\n{status}. Response Reason Phrase:\n{reasonPhrase}", + policyPath, + status, + reasonPhrase); + return false; + } + + // Update db and use new version from latest update + return await WritePolicyUpdateToDB(policyPath, blobResponse.Value.VersionId, DelegationChangeType.Grant, rules, cancellationToken); + } + finally + { + policyClient.ReleaseBlobLease(leaseId, CancellationToken.None); + } + } + + LogLeaseLockError(policyPath); + return false; + } + + private async Task WritePolicyUpdateToDB(string policyPath, string versionId, DelegationChangeType changeType, InstanceRight rules, CancellationToken cancellationToken) + { + // Update db and use new version from latest update + InstanceDelegationChange instanceDelegationChange = new InstanceDelegationChange + { + DelegationChangeType = changeType, + InstanceDelegationMode = rules.InstanceDelegationMode, + ResourceId = rules.ResourceId, + InstanceId = rules.InstanceId, + + BlobStoragePolicyPath = policyPath, + BlobStorageVersionId = versionId, + + FromUuid = rules.FromUuid, + FromUuidType = rules.FromType, + ToUuid = rules.ToUuid, + ToUuidType = rules.ToType, + + PerformedBy = rules.PerformedBy, + PerformedByType = rules.PerformedByType + }; + + instanceDelegationChange = + await _delegationRepository.InsertInstanceDelegation(instanceDelegationChange, cancellationToken); + if (instanceDelegationChange == null || instanceDelegationChange.InstanceDelegationChangeId <= 0) + { + // Comment: + // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. + // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. + _logger.LogError( + "Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}", + policyPath); + return false; + } + + return true; + } + + private async Task<(XacmlPolicy Policy, string PolicyPath)> GetExistingPolicy(string policyPath, InstanceRight rules, CancellationToken cancellationToken) + { + // Check for a current delegation change from postgresql + InstanceDelegationChangeRequest requestLastChanged = new InstanceDelegationChangeRequest + { + FromType = rules.FromType, + FromUuid = rules.FromUuid, + ToType = rules.ToType, + ToUuid = rules.ToUuid, + Resource = rules.ResourceId, + InstanceDelegationMode = rules.InstanceDelegationMode, + Instance = rules.InstanceId + }; + + InstanceDelegationChange currentChange = + await _delegationRepository.GetLastInstanceDelegationChange( + requestLastChanged, + cancellationToken); + + XacmlPolicy existingDelegationPolicy = null; + if (currentChange != null && currentChange.DelegationChangeType != DelegationChangeType.RevokeLast) + { + policyPath = currentChange.BlobStoragePolicyPath; + existingDelegationPolicy = await _prp.GetPolicyVersionAsync( + policyPath, + currentChange.BlobStorageVersionId, + cancellationToken); + } + + return (existingDelegationPolicy, policyPath); + } + + private static XacmlPolicy BuildInstanceDelegationPolicy(XacmlPolicy existingDelegationPolicy, InstanceRight rules) + { + // Build delegation XacmlPolicy either as a new policy or add rules to existing + XacmlPolicy delegationPolicy; + if (existingDelegationPolicy != null) + { + delegationPolicy = existingDelegationPolicy; + PolicyParameters policyData = PolicyHelper.GetPolicyDataFromInstanceRight(rules); + + foreach (InstanceRule rule in rules.InstanceRules) + { + if (!DelegationHelper.PolicyContainsMatchingInstanceRule(delegationPolicy, rule)) + { + delegationPolicy.Rules.Add(PolicyHelper.BuildDelegationInstanceRule(policyData, rule)); + } + } + } + else + { + delegationPolicy = PolicyHelper.BuildInstanceDelegationPolicy(rules); + } + + return delegationPolicy; + } + + private static XacmlPolicy BuildInstanceRevokePolicy(XacmlPolicy delegationPolicy, InstanceRight rules) + { + // Build delegation XacmlPolicy by removing the rules revoked + foreach (InstanceRule rule in rules.InstanceRules) + { + XacmlRule xacmlRule = DelegationHelper.GetXamlRuleContainsMatchingInstanceRule(delegationPolicy, rule); + if (xacmlRule != null) + { + delegationPolicy.Rules.Remove(xacmlRule); + } + } + + return delegationPolicy; + } + + /// + public async Task TryWriteInstanceDelegationPolicyRules(InstanceRight rules, CancellationToken cancellationToken = default) + { + bool validPath = DelegationHelper.TryGetDelegationPolicyPathFromInstanceRule(rules, out string path); + + if (validPath) + { + bool writePolicySuccess = false; + + try + { + writePolicySuccess = await WriteInstanceDelegationPolicyInternal(path, rules, cancellationToken); + } + catch (Exception ex) + { + _logger.LogError( + ex, + "An exception occured while processing authorization rules for delegation on delegation policy path: {path}", + path); + } + + foreach (InstanceRule rule in rules.InstanceRules) + { + if (writePolicySuccess) + { + rule.CreatedSuccessfully = true; + } + else + { + rule.RuleId = string.Empty; + rule.CreatedSuccessfully = false; + } + } + } + else + { + string unsortablesJson = JsonSerializer.Serialize(rules); + _logger.LogError("One or more rules could not be processed because of incomplete input:\n{unsortablesJson}", unsortablesJson); + } + + return rules; + } + + /// + public async Task TryWriteInstanceRevokePolicyRules(InstanceRight rules, CancellationToken cancellationToken = default) + { + bool writePolicySuccess = false; + + try + { + writePolicySuccess = await WriteInstanceRevokePolicyInternal(rules, cancellationToken); + } + catch (Exception ex) + { + bool validPath = DelegationHelper.TryGetDelegationPolicyPathFromInstanceRule(rules, out string path); + if (validPath) + { + _logger.LogError(ex, "An exception occured while processing authorization rules for delegation on delegation policy path: {path}", path); + } + else + { + string unsortablesJson = JsonSerializer.Serialize(rules); + _logger.LogError("One or more rules could not be processed because of incomplete input:\n{unsortablesJson}", unsortablesJson); + } + } + + foreach (InstanceRule rule in rules.InstanceRules) + { + if (writePolicySuccess) + { + rule.CreatedSuccessfully = true; + } + else + { + rule.RuleId = string.Empty; + rule.CreatedSuccessfully = false; + } + } + + return rules; + } + + /// + public async Task> TryWriteInstanceRevokeAllPolicyRules(List rights, CancellationToken cancellationToken = default) + { + bool writePolicySuccess = false; + + try + { + writePolicySuccess = await WriteInstanceRevokeAllPolicyInternal(rights, cancellationToken); + } + catch (Exception e) + { + string resourceId = rights[0].ResourceId; + string instanceId = rights[0].InstanceId; + _logger.LogError(e, "One or more rules could not be processed when writing policy files ResourceId: {resourceId}, InstanceId: {instanceId}", resourceId, instanceId); + } + + foreach (InstanceRight rules in rights) + { + foreach (InstanceRule rule in rules.InstanceRules) + { + if (writePolicySuccess) + { + rule.CreatedSuccessfully = true; + } + else + { + rule.RuleId = string.Empty; + rule.CreatedSuccessfully = false; + } + } + } + + return rights; + } + + private async Task WriteInstanceRevokeAllPolicyInternal(List rights, CancellationToken cancellationToken = default) + { + List policyWriteOutputs = []; + try + { + foreach (InstanceRight rules in rights) + { + PolicyWriteOutput currentPolicyWrite = new PolicyWriteOutput(); + policyWriteOutputs.Add(currentPolicyWrite); + currentPolicyWrite.Rules = rules; + + // Check for a current delegation change from postgresql + (XacmlPolicy ExistingDelegationPolicy, string PolicyPath) policyData = await GetExistingPolicy(null, rules, cancellationToken); + currentPolicyWrite.PolicyPath = policyData.PolicyPath; + + // if no delegations exist all revoke must already be performed + if (policyData.ExistingDelegationPolicy == null) + { + continue; + } + + currentPolicyWrite.PolicyClient = _policyFactory.Create(currentPolicyWrite.PolicyPath); + + if (!await currentPolicyWrite.PolicyClient.PolicyExistsAsync(cancellationToken)) + { + return false; + } + + currentPolicyWrite.LeaseId = await currentPolicyWrite.PolicyClient.TryAcquireBlobLease(cancellationToken); + if (currentPolicyWrite.LeaseId != null) + { + // Build delegation XacmlPolicy either as a new policy or add rules to existing + XacmlPolicy delegationPolicy = BuildInstanceRevokePolicy(policyData.ExistingDelegationPolicy, rules); + + // Write delegation policy to blob storage + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(delegationPolicy); + Response blobResponse = await currentPolicyWrite.PolicyClient.WritePolicyConditionallyAsync(dataStream, currentPolicyWrite.LeaseId, cancellationToken); + currentPolicyWrite.VersionId = blobResponse.Value.VersionId; + Response httpResponse = blobResponse.GetRawResponse(); + if (httpResponse.Status != (int)HttpStatusCode.Created) + { + int status = httpResponse.Status; + string reasonPhrase = httpResponse.ReasonPhrase; + _logger.LogError( + "Writing of delegation policy at path: {policyPath} failed. Response Status Code:\n{status}. Response Reason Phrase:\n{reasonPhrase}", + currentPolicyWrite.PolicyPath, + status, + reasonPhrase); + return false; + } + + currentPolicyWrite.ChangeType = (delegationPolicy.Rules.Count > 0) ? DelegationChangeType.Revoke : DelegationChangeType.RevokeLast; + } + else + { + string policyPath = currentPolicyWrite.PolicyPath; + LogLeaseLockError(policyPath); + return false; + } + } + + // Update db and use new version from latest update + return await _delegationRepository.InsertMultipleInstanceDelegations(policyWriteOutputs, cancellationToken); + } + finally + { + foreach (var policy in policyWriteOutputs.Where(p => p.LeaseId != null)) + { + policy.PolicyClient.ReleaseBlobLease(policy.LeaseId, CancellationToken.None); + } + } + } + + /// + public async Task> TryWriteDelegationPolicyRules(List rules, CancellationToken cancellationToken = default) + { + List result = new List(); + Dictionary> delegationDict = DelegationHelper.SortRulesByDelegationPolicyPath(rules, out List unsortables); + + foreach (string delegationPolicypath in delegationDict.Keys) + { + bool writePolicySuccess = false; + + try + { + writePolicySuccess = await WriteDelegationPolicyInternal(delegationPolicypath, delegationDict[delegationPolicypath], cancellationToken); + } + catch (Exception ex) + { + _logger.LogError(ex, "An exception occured while processing authorization rules for delegation on delegation policy path: {delegationPolicypath}", delegationPolicypath); + } + + foreach (Rule rule in delegationDict[delegationPolicypath]) + { + if (writePolicySuccess) + { + rule.CreatedSuccessfully = true; + rule.Type = RuleType.DirectlyDelegated; + } + else + { + rule.RuleId = string.Empty; + } + + result.Add(rule); + } + } + + if (unsortables.Count > 0) + { + string unsortablesJson = JsonSerializer.Serialize(unsortables); + _logger.LogError("One or more rules could not be processed because of incomplete input:\n{unsortablesJson}", unsortablesJson); + result.AddRange(unsortables); + } + + return result; + } + + /// + public async Task> TryDeleteDelegationPolicyRules(List rulesToDelete, CancellationToken cancellationToken = default) + { + List result = new List(); + + foreach (RequestToDelete deleteRequest in rulesToDelete) + { + List currentRules = await DeleteRulesInPolicy(deleteRequest, cancellationToken); + if (currentRules != null) + { + result.AddRange(currentRules); + } + } + + return result; + } + + /// + public async Task> TryDeleteDelegationPolicies(List policiesToDelete, CancellationToken cancellationToken = default) + { + List result = new List(); + + foreach (RequestToDelete policyToDelete in policiesToDelete) + { + List currentRules = await DeleteAllRulesInPolicy(policyToDelete, cancellationToken); + if (currentRules != null) + { + result.AddRange(currentRules); + } + } + + return result; + } + + private async Task WriteDelegationPolicyInternal(string policyPath, List rules, CancellationToken cancellationToken = default) + { + if (!DelegationHelper.TryGetDelegationParamsFromRule(rules[0], out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out int offeredByPartyId, out Guid? fromUuid, out UuidType fromUuidType, out Guid? toUuid, out UuidType toUuidType, out int? coveredByPartyId, out int? coveredByUserId, out int? delegatedByUserId, out int? delegatedByPartyId, out DateTime delegatedDateTime) + || resourceMatchType == ResourceAttributeMatchType.None) + { + _logger.LogWarning("This should not happen. Incomplete rule model received for delegation to delegation policy at: {policyPath}. Incomplete model should have been returned in unsortable rule set by TryWriteDelegationPolicyRules. DelegationHelper.SortRulesByDelegationPolicyPath might be broken.", policyPath); + return false; + } + + if (resourceMatchType == ResourceAttributeMatchType.ResourceRegistry) + { + XacmlPolicy resourcePolicy = await _prp.GetPolicyAsync(resourceId, cancellationToken); + if (resourcePolicy == null) + { + _logger.LogWarning("No valid resource policy found for delegation policy path: {policyPath}", policyPath); + return false; + } + + foreach (Rule rule in rules) + { + if (!DelegationHelper.PolicyContainsMatchingRule(resourcePolicy, rule)) + { + _logger.LogWarning("Matching rule not found in resource policy. Action might not exist for Resource, or Resource itself might not exist. Delegation policy path: {policyPath}. Rule: {rule}", policyPath, rule); + return false; + } + } + } + else if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + XacmlPolicy appPolicy = await _prp.GetPolicyAsync(org, app, cancellationToken); + if (appPolicy == null) + { + _logger.LogWarning("No valid App policy found for delegation policy path: {policyPath}", policyPath); + return false; + } + + foreach (Rule rule in rules) + { + if (!DelegationHelper.PolicyContainsMatchingRule(appPolicy, rule)) + { + _logger.LogWarning("Matching rule not found in app policy. Action might not exist for Resource, or Resource itself might not exist. Delegation policy path: {policyPath}. Rule: {rule}", policyPath, rule); + return false; + } + } + } + + var policyClient = _policyFactory.Create(policyPath); + if (!await policyClient.PolicyExistsAsync(cancellationToken)) + { + // Create a new empty blob for lease locking + await policyClient.WritePolicyAsync(new MemoryStream(), cancellationToken: cancellationToken); + } + + string leaseId = await policyClient.TryAcquireBlobLease(cancellationToken); + if (leaseId != null) + { + try + { + // Check for a current delegation change from postgresql + DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange(resourceMatchType, resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, toUuid, toUuidType, cancellationToken); + + XacmlPolicy existingDelegationPolicy = null; + if (currentChange != null && currentChange.DelegationChangeType != DelegationChangeType.RevokeLast) + { + existingDelegationPolicy = await _prp.GetPolicyVersionAsync(policyPath, currentChange.BlobStorageVersionId, cancellationToken); + } + + // Build delegation XacmlPolicy either as a new policy or add rules to existing + XacmlPolicy delegationPolicy; + if (existingDelegationPolicy != null) + { + delegationPolicy = existingDelegationPolicy; + foreach (Rule rule in rules) + { + if (!DelegationHelper.PolicyContainsMatchingRule(delegationPolicy, rule)) + { + (string coveredBy, string coveredByType) = PolicyHelper.GetCoveredByAndType(coveredByPartyId, coveredByUserId, toUuid, toUuidType); + delegationPolicy.Rules.Add(PolicyHelper.BuildDelegationRule(resourceId, offeredByPartyId, coveredBy, coveredByType, rule)); + } + } + } + else + { + delegationPolicy = PolicyHelper.BuildDelegationPolicy(resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, toUuid, toUuidType, rules); + } + + // Write delegation policy to blob storage + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(delegationPolicy); + Response blobResponse = await policyClient.WritePolicyConditionallyAsync(dataStream, leaseId, cancellationToken); + Response httpResponse = blobResponse.GetRawResponse(); + if (httpResponse.Status != (int)HttpStatusCode.Created) + { + _logger.LogError("Writing of delegation policy at path: {policyPath} failed. Response Status Code:\n{httpResponse.Status}. Response Reason Phrase:\n{httpResponse.ReasonPhrase}", policyPath, httpResponse.Status, httpResponse.ReasonPhrase); + return false; + } + + string performedUuid = null; + UuidType performedUuidType = UuidType.NotSpecified; + + // Write delegation change to postgresql + DelegationChange change = new DelegationChange + { + DelegationChangeType = DelegationChangeType.Grant, + ResourceId = resourceId, + OfferedByPartyId = offeredByPartyId, + FromUuid = fromUuid, + FromUuidType = fromUuidType, + CoveredByPartyId = coveredByPartyId, + CoveredByUserId = coveredByUserId, + ToUuid = toUuid, + ToUuidType = toUuidType, + PerformedByUserId = delegatedByUserId, + PerformedByPartyId = delegatedByPartyId, + PerformedByUuid = performedUuid, + PerformedByUuidType = performedUuidType, + Created = delegatedDateTime, + BlobStoragePolicyPath = policyPath, + BlobStorageVersionId = blobResponse.Value.VersionId + }; + + change = await _delegationRepository.InsertDelegation(resourceMatchType, change, cancellationToken); + if (change == null || (change.DelegationChangeId <= 0 && change.ResourceRegistryDelegationChangeId <= 0)) + { + // Comment: + // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. + // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. + _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}", policyPath); + return false; + } + + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + try + { + await _eventQueue.Push(change); + } + catch (Exception ex) + { + _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "AddRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); + } + } + + return true; + } + finally + { + policyClient.ReleaseBlobLease(leaseId, CancellationToken.None); + } + } + + LogLeaseLockError(policyPath); + return false; + } + + private async Task> ProcessPolicyFile(string policyPath, ResourceAttributeMatchType resourceMatchType, string resourceId, RequestToDelete deleteRequest, CancellationToken cancellationToken = default) + { + List currentRules = new List(); + var policyClient = _policyFactory.Create(policyPath); + string leaseId = await policyClient.TryAcquireBlobLease(cancellationToken); + + if (leaseId == null) + { + LogLeaseLockError(policyPath, true); + return null; + } + + try + { + bool isAllRulesDeleted = false; + string coveredBy = DelegationHelper.GetCoveredByFromMatch(deleteRequest.PolicyMatch.CoveredBy, out int? coveredByUserId, out int? coveredByPartyId, out Guid? coveredByUuid, out UuidType coveredByUuidType); + string offeredBy = deleteRequest.PolicyMatch.OfferedByPartyId.ToString(); + + DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange(resourceMatchType, resourceId, deleteRequest.PolicyMatch.OfferedByPartyId, coveredByPartyId, coveredByUserId, coveredByUuid, coveredByUuidType, cancellationToken); + + XacmlPolicy existingDelegationPolicy = null; + if (currentChange.DelegationChangeType == DelegationChangeType.RevokeLast) + { + _logger.LogWarning("The policy is already deleted for: {resourceId} CoveredBy: {coveredBy} OfferedBy: {offeredBy}", resourceId, coveredBy, offeredBy); + return null; + } + + existingDelegationPolicy = await _prp.GetPolicyVersionAsync(currentChange.BlobStoragePolicyPath, currentChange.BlobStorageVersionId, cancellationToken); + + foreach (string ruleId in deleteRequest.RuleIds) + { + XacmlRule xacmlRuleToRemove = existingDelegationPolicy.Rules.FirstOrDefault(r => r.RuleId == ruleId); + if (xacmlRuleToRemove == null) + { + _logger.LogWarning("The rule with id: {ruleId} does not exist in policy with path: {policyPath}", ruleId, policyPath); + continue; + } + + existingDelegationPolicy.Rules.Remove(xacmlRuleToRemove); + Rule currentRule = PolicyHelper.CreateRuleFromPolicyAndRuleMatch(deleteRequest, xacmlRuleToRemove); + currentRules.Add(currentRule); + } + + isAllRulesDeleted = existingDelegationPolicy.Rules.Count == 0; + + // if nothing is deleted no update has been done and policy and postgree update can be skipped + if (currentRules.Count > 0) + { + Response response; + try + { + // Write delegation policy to blob storage + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(existingDelegationPolicy); + response = await policyClient.WritePolicyConditionallyAsync(dataStream, leaseId, cancellationToken); + } + catch (Exception ex) + { + _logger.LogError(ex, "Writing of delegation policy at path: {policyPath} failed. Is delegation blob storage account alive and well?", policyPath); + return null; + } + + // Write delegation change to postgresql + DelegationChange change = new DelegationChange + { + DelegationChangeType = isAllRulesDeleted ? DelegationChangeType.RevokeLast : DelegationChangeType.Revoke, + ResourceId = resourceId, + OfferedByPartyId = deleteRequest.PolicyMatch.OfferedByPartyId, + CoveredByPartyId = coveredByPartyId, + CoveredByUserId = coveredByUserId, + PerformedByUserId = deleteRequest.DeletedByUserId, + BlobStoragePolicyPath = policyPath, + BlobStorageVersionId = response.Value.VersionId + }; + + change = await _delegationRepository.InsertDelegation(resourceMatchType, change, cancellationToken); + if (change == null || (change.DelegationChangeId <= 0 && change.ResourceRegistryDelegationChangeId <= 0)) + { + // Comment: + // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. + // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. + _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}. is authorization postgresql database alive and well?", policyPath); + return null; + } + + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + try + { + await _eventQueue.Push(change); + } + catch (Exception ex) + { + _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "DeleteRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); + } + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "An exception occured while processing rules to delete in policy: {policyPath}", policyPath); + return null; + } + finally + { + policyClient.ReleaseBlobLease(leaseId, CancellationToken.None); + } + + return currentRules; + } + + private async Task> DeleteAllRulesInPolicy(RequestToDelete policyToDelete, CancellationToken cancellationToken = default) + { + string coveredBy = DelegationHelper.GetCoveredByFromMatch(policyToDelete.PolicyMatch.CoveredBy, out int? coveredByUserId, out int? coveredByPartyId, out Guid? coveredByUuid, out UuidType coveredByUuidType); + + if (!DelegationHelper.TryGetResourceFromAttributeMatch(policyToDelete.PolicyMatch.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string _, out string _)) + { + _logger.LogError("The resource cannot be identified."); + return null; + } + + string policyPath; + try + { + policyPath = PolicyHelper.GetDelegationPolicyPath(resourceMatchType, resourceId, org, app, policyToDelete.PolicyMatch.OfferedByPartyId.ToString(), coveredByUserId, coveredByPartyId, coveredByUuid, coveredByUuidType); + } + catch (Exception ex) + { + _logger.LogError(ex, "Not possible to build policy path for: {resourceId} CoveredBy: {coveredBy} OfferedBy: {policyToDelete.PolicyMatch.OfferedByPartyId}", resourceId, coveredBy, policyToDelete.PolicyMatch.OfferedByPartyId); + return null; + } + + var policyClient = _policyFactory.Create(policyPath); + if (!await policyClient.PolicyExistsAsync(cancellationToken)) + { + _logger.LogWarning("No blob was found for the expected path: {policyPath} this must be removed without upading the database", policyPath); + return null; + } + + string leaseId = await policyClient.TryAcquireBlobLease(cancellationToken); + if (leaseId == null) + { + _logger.LogError("Could not acquire blob lease on delegation policy at path: {policyPath}", policyPath); + return null; + } + + try + { + DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange(resourceMatchType, resourceId, policyToDelete.PolicyMatch.OfferedByPartyId, coveredByPartyId, coveredByUserId, coveredByUuid, coveredByUuidType, cancellationToken); + + if (currentChange.DelegationChangeType == DelegationChangeType.RevokeLast) + { + _logger.LogWarning("The policy is already deleted for: {resourceId} CoveredBy: {coveredBy} OfferedBy: {policyToDelete.PolicyMatch.OfferedByPartyId}", resourceId, coveredBy, policyToDelete.PolicyMatch.OfferedByPartyId); + return null; + } + + XacmlPolicy existingDelegationPolicy = await _prp.GetPolicyVersionAsync(currentChange.BlobStoragePolicyPath, currentChange.BlobStorageVersionId, cancellationToken); + List currentPolicyRules = new List(); + foreach (XacmlRule xacmlRule in existingDelegationPolicy.Rules) + { + currentPolicyRules.Add(PolicyHelper.CreateRuleFromPolicyAndRuleMatch(policyToDelete, xacmlRule)); + } + + existingDelegationPolicy.Rules.Clear(); + + Response response; + try + { + MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(existingDelegationPolicy); + response = await policyClient.WritePolicyConditionallyAsync(dataStream, leaseId, cancellationToken); + } + catch (Exception ex) + { + _logger.LogError(ex, "Writing of delegation policy at path: {policyPath} failed. Is delegation blob storage account alive and well?}", policyPath); + return null; + } + + DelegationChange change = new DelegationChange + { + DelegationChangeType = DelegationChangeType.RevokeLast, + ResourceId = resourceId, + OfferedByPartyId = policyToDelete.PolicyMatch.OfferedByPartyId, + CoveredByPartyId = coveredByPartyId, + CoveredByUserId = coveredByUserId, + PerformedByUserId = policyToDelete.DeletedByUserId, + BlobStoragePolicyPath = policyPath, + BlobStorageVersionId = response.Value.VersionId + }; + + change = await _delegationRepository.InsertDelegation(resourceMatchType, change, cancellationToken); + if (change == null || (change.DelegationChangeId <= 0 && change.ResourceRegistryDelegationChangeId <= 0)) + { + // Comment: + // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. + // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. + _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}. is authorization postgresql database alive and well?", policyPath); + return null; + } + + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + try + { + await _eventQueue.Push(change); + } + catch (Exception ex) + { + _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "DeletePolicy could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); + } + } + + return currentPolicyRules; + } + catch (Exception ex) + { + _logger.LogError(ex, "An exception occured while processing rules to delete in policy: {policyPath}", policyPath); + return null; + } + finally + { + policyClient.ReleaseBlobLease(leaseId, CancellationToken.None); + } + } + + private async Task> DeleteRulesInPolicy(RequestToDelete rulesToDelete, CancellationToken cancellationToken = default) + { + string coveredBy = DelegationHelper.GetCoveredByFromMatch(rulesToDelete.PolicyMatch.CoveredBy, out int? coveredByUserId, out int? coveredByPartyId, out Guid? coveredByUuid, out UuidType coveredByUuidType); + + if (!DelegationHelper.TryGetResourceFromAttributeMatch(rulesToDelete.PolicyMatch.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string _, out string _)) + { + _logger.LogError("The resource cannot be identified."); + return null; + } + + string policyPath; + try + { + policyPath = PolicyHelper.GetDelegationPolicyPath(resourceMatchType, resourceId, org, app, rulesToDelete.PolicyMatch.OfferedByPartyId.ToString(), coveredByUserId, coveredByPartyId, coveredByUuid, coveredByUuidType); + } + catch (Exception ex) + { + string rulesToDeleteString = string.Join(", ", rulesToDelete.RuleIds); + _logger.LogError(ex, "Not possible to build policy path for: {resourceId} CoveredBy: {coveredBy} OfferedBy: {policyToDelete.PolicyMatch.OfferedByPartyId} RuleIds: {rulesToDeleteString}", resourceId, coveredBy, rulesToDelete.PolicyMatch.OfferedByPartyId, rulesToDeleteString); + return null; + } + + var policyClient = _policyFactory.Create(policyPath); + if (!await policyClient.PolicyExistsAsync(cancellationToken)) + { + _logger.LogWarning("No blob was found for the expected path: {policyPath} this must be removed without updating the database", policyPath); + return null; + } + + List currentRules = await ProcessPolicyFile(policyPath, resourceMatchType, resourceId, rulesToDelete, cancellationToken); + + return currentRules; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyInformationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyInformationPoint.cs new file mode 100644 index 00000000..35dce29c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyInformationPoint.cs @@ -0,0 +1,615 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.Authorization.ABAC; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using Altinn.Urn; +using Altinn.Urn.Json; +using Authorization.Platform.Authorization.Models; +using Microsoft.Extensions.Logging; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + /// The Policy Information Point responsible for storing and modifying delegation policies + /// + public class PolicyInformationPoint : IPolicyInformationPoint + { + private readonly ILogger _logger; + private readonly IPolicyRetrievalPoint _prp; + private readonly IDelegationMetadataRepository _delegationRepository; + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IProfileClient _profile; + + /// + /// Initializes a new instance of the class. + /// + /// The logger + /// The policy retrieval point + /// The delegation change repository + /// Service for retrieving context information + /// Service for retrieving user profile information + public PolicyInformationPoint(ILogger logger, IPolicyRetrievalPoint policyRetrievalPoint, IDelegationMetadataRepository delegationRepository, IContextRetrievalService contextRetrievalService, IProfileClient profile) + { + _logger = logger; + _prp = policyRetrievalPoint; + _delegationRepository = delegationRepository; + _contextRetrievalService = contextRetrievalService; + _profile = profile; + } + + /// + public async Task> GetRulesAsync(List resourceIds, List offeredByPartyIds, List coveredByPartyIds, List coveredByUserIds, CancellationToken cancellationToken = default) + { + List rules = new List(); + List delegationChanges = await _delegationRepository.GetAllCurrentAppDelegationChanges(offeredByPartyIds, resourceIds, coveredByPartyIds, coveredByUserIds, cancellationToken); + foreach (DelegationChange delegationChange in delegationChanges) + { + if (delegationChange.DelegationChangeType != DelegationChangeType.RevokeLast) + { + XacmlPolicy policy = await _prp.GetPolicyVersionAsync(delegationChange.BlobStoragePolicyPath, delegationChange.BlobStorageVersionId, cancellationToken); + rules.AddRange(GetRulesFromPolicyAndDelegationChange(policy.Rules, delegationChange)); + } + } + + return rules; + } + + /// + public async Task> GetRights(RightsQuery rightsQuery, bool returnAllPolicyRights = false, bool getDelegableRights = false, CancellationToken cancellationToken = default) + { + Dictionary result = new Dictionary(); + XacmlPolicy policy = null; + + if (rightsQuery.Type != RightsQueryType.User) + { + return result.Values.ToList(); + } + + // TODO: Caching?? + + // Verify resource + if (!DelegationHelper.TryGetResourceFromAttributeMatch(rightsQuery.Resource.AuthorizationReference, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string serviceCode, out string serviceEditionCode) + || resourceMatchType == ResourceAttributeMatchType.None) + { + throw new ValidationException($"RightsQuery must specify a valid Resource. Valid resource can either be a single resource from the Altinn resource registry ({AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute}) or an Altinn app (identified by both {AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute} and {AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute})"); + } + + if (resourceMatchType == ResourceAttributeMatchType.ResourceRegistry) + { + policy = await _prp.GetPolicyAsync(resourceId, cancellationToken); + } + else if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + policy = await _prp.GetPolicyAsync(org, app, cancellationToken); + } + + if (policy == null) + { + throw new ValidationException($"No valid policy found for the specified resource"); + } + + // Verify From/OfferedBy + if (!DelegationHelper.TryGetPartyIdFromAttributeMatch(rightsQuery.From, out int offeredByPartyId)) + { + throw new ValidationException($"Rights query currently only support lookup of rights FROM partyid ({AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute})"); + } + + // Verify To/CoveredBy + if (!DelegationHelper.TryGetUserIdFromAttributeMatch(rightsQuery.To, out int coveredByUserId)) + { + throw new ValidationException($"Rights query currently only support lookup of rights TO a userid: ({AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute})"); + } + + // Policy Rights + List userRoles; + if (getDelegableRights) + { + userRoles = await _contextRetrievalService.GetRolesForDelegation(coveredByUserId, offeredByPartyId, cancellationToken); + } + else + { + userRoles = await _contextRetrievalService.GetDecisionPointRolesForUser(coveredByUserId, offeredByPartyId, cancellationToken); + } + + int minimumAuthenticationLevel = PolicyHelper.GetMinimumAuthenticationLevelFromXacmlPolicy(policy); + if (userRoles.Any() || returnAllPolicyRights || getDelegableRights) + { + List userRoleAttributeMatches = RightsHelper.GetRoleAttributeMatches(userRoles); + RightSourceType policyType = resourceMatchType == ResourceAttributeMatchType.ResourceRegistry ? RightSourceType.ResourceRegistryPolicy : RightSourceType.AppPolicy; + EnrichRightsDictionaryWithRightsFromPolicy(result, policy, policyType, userRoleAttributeMatches, minimumAuthenticationLevel: minimumAuthenticationLevel, returnAllPolicyRights: returnAllPolicyRights, getDelegableRights: getDelegableRights); + } + + // Delegation Policy Rights + List delegations = await FindAllDelegations(coveredByUserId, 0, Guid.Empty, UuidType.NotSpecified, offeredByPartyId, resourceId, resourceMatchType, cancellationToken: cancellationToken); + + foreach (DelegationChange delegation in delegations) + { + XacmlPolicy delegationPolicy = await _prp.GetPolicyVersionAsync(delegation.BlobStoragePolicyPath, delegation.BlobStorageVersionId, cancellationToken); + List subjects = RightsHelper.GetDelegationSubjectAttributeMatches(delegation); + EnrichRightsDictionaryWithRightsFromPolicy(result, delegationPolicy, RightSourceType.DelegationPolicy, subjects, minimumAuthenticationLevel: minimumAuthenticationLevel, delegationOfferedByPartyId: delegation.OfferedByPartyId, getDelegableRights: getDelegableRights); + } + + if (returnAllPolicyRights) + { + return result.Values.ToList(); + } + + if (getDelegableRights) + { + return result.Values.Where(r => r.CanDelegate.HasValue && r.CanDelegate.Value).ToList(); + } + + return result.Values.Where(r => r.HasPermit.HasValue && r.HasPermit.Value).ToList(); + } + + /// + public async Task> GetDelegableRightsByApp(RightsQuery rightsQuery, CancellationToken cancellationToken = default) + { + Dictionary result = new Dictionary(); + if (rightsQuery.Type != RightsQueryType.AltinnApp) + { + return result.Values.ToList(); + } + + XacmlPolicy policy = await GetPolicy(rightsQuery.Resource.AuthorizationReference, cancellationToken); + + int minimumAuthenticationLevel = PolicyHelper.GetMinimumAuthenticationLevelFromXacmlPolicy(policy); + RightSourceType policyType = rightsQuery.Resource.ResourceType == ResourceType.AltinnApp ? RightSourceType.AppPolicy : RightSourceType.ResourceRegistryPolicy; + EnrichRightsDictionaryWithRightsFromPolicy(result, policy, policyType, rightsQuery.To, minimumAuthenticationLevel: minimumAuthenticationLevel, returnAllPolicyRights: false, getDelegableRights: true); + + return result.Values.Where(r => r.CanDelegate.HasValue && r.CanDelegate.Value).ToList(); + } + + private async Task GetPolicy(List resource, CancellationToken cancellationToken) + { + XacmlPolicy policy = null; + + // Verify resource + if (!DelegationHelper.TryGetResourceFromAttributeMatch(resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string org, out string app, out string _, out string _) + || resourceMatchType == ResourceAttributeMatchType.None) + { + throw new ValidationException($"RightsQuery must specify a valid Resource. Valid resource can either be a single resource from the Altinn resource registry ({AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute}) or an Altinn app (identified by both {AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute} and {AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute})"); + } + + if (resourceMatchType == ResourceAttributeMatchType.ResourceRegistry) + { + policy = await _prp.GetPolicyAsync(resourceId, cancellationToken); + } + else if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + policy = await _prp.GetPolicyAsync(org, app, cancellationToken); + } + + if (policy == null) + { + throw new ValidationException($"No valid policy found for the specified resource"); + } + + return policy; + } + + /// + public async Task> GetReceivedDelegationFromRepository(int partyId, CancellationToken cancellationToken = default) + { + var party = await _contextRetrievalService.GetPartyAsync(partyId, cancellationToken); + + if (party?.PartyTypeName == PartyType.Person) + { + var user = await _profile.GetUser(new() { Ssn = party.SSN }, cancellationToken); + + var keyRoles = await _contextRetrievalService.GetKeyRolePartyIds(user.UserId, cancellationToken); + return await _delegationRepository.GetAllDelegationChangesForAuthorizedParties(user.UserId.SingleToList(), keyRoles, cancellationToken); + } + + if (party?.PartyTypeName == PartyType.Organisation) + { + return await _delegationRepository.GetAllDelegationChangesForAuthorizedParties(null, party.PartyId.SingleToList(), cancellationToken); + } + + throw new ArgumentException($"failed to handle party with id '{partyId}'"); + } + + /// + public async Task> GetOfferedDelegationsFromRepository(int partyId, CancellationToken cancellationToken = default) + { + var party = await _contextRetrievalService.GetPartyAsync(partyId, cancellationToken); + + if (party.PartyTypeName == PartyType.Person) + { + return await _delegationRepository.GetOfferedDelegations(partyId.SingleToList(), cancellationToken); + } + + if (party.PartyTypeName == PartyType.Organisation) + { + var mainUnits = await _contextRetrievalService.GetMainUnits(party.PartyId.SingleToList(), cancellationToken); + var parties = party.PartyId.SingleToList(); + if (mainUnits?.FirstOrDefault() is var mainUnit && mainUnit?.PartyId != null) + { + parties.Add((int)mainUnit.PartyId); + } + + return await _delegationRepository.GetOfferedDelegations(parties, cancellationToken); + } + + throw new ArgumentException($"failed to handle party with id '{partyId}'"); + } + + /// + public async Task GetAllDelegations(DelegationChangeInput request, bool includeInstanceDelegations = false, CancellationToken cancellationToken = default) + { + DelegationChangeList result = new DelegationChangeList(); + bool validSubjectUser = DelegationHelper.TryGetUserIdFromAttributeMatch(request.Subject.SingleToList(), out int subjectUserId); + bool validSubjectParty = DelegationHelper.TryGetPartyIdFromAttributeMatch(request.Subject.SingleToList(), out int subjectPartyId); + bool validSubjectUuid = DelegationHelper.TryGetUuidFromAttributeMatch(request.Subject.SingleToList(), out Guid subjectUuid, out UuidType subjectUuidType); + bool validParty = DelegationHelper.TryGetPartyIdFromAttributeMatch(request.Party.SingleToList(), out int partyId); + bool validResourceMatchType = DelegationHelper.TryGetResourceFromAttributeMatch(request.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out string _, out string _, out string _, out string _); + + if (!validSubjectUser && !validSubjectParty && (!validSubjectUuid || subjectUuidType != UuidType.SystemUser)) + { + result.Errors.Add("request.Subject", $"Missing valid subject on request. Valid subject attribute types: either {AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute}, {AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute} or {AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid}"); + return result; + } + + if (!validParty) + { + result.Errors.Add("request.Party", $"Missing valid party on request. Valid party attribute type: {AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute}"); + return result; + } + + if (!validResourceMatchType) + { + result.Errors.Add("request.Resource", $"Missing valid resource on request. Valid resource attribute types: either a single {AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute} or combination of both {AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute} and {AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute}"); + return result; + } + + result.DelegationChanges = await FindAllDelegations(subjectUserId, subjectPartyId, subjectUuid, subjectUuidType, partyId, resourceId, resourceMatchType, includeInstanceDelegations, cancellationToken); + return result; + } + + /// + public async Task> GetInstanceDelegations(AppsInstanceGetRequest request, CancellationToken cancellationToken) + { + List result = new List(); + + List delegations = await _delegationRepository.GetAllLatestInstanceDelegationChanges(request.InstanceDelegationSource, request.ResourceId, request.InstanceId, cancellationToken); + + foreach (InstanceDelegationChange delegation in delegations) + { + AppsInstanceDelegationResponse appsInstanceDelegationResponse = new AppsInstanceDelegationResponse + { + From = GetPartyUrnFromUuidTypeAndUuid(delegation.FromUuid, delegation.FromUuidType), + To = GetPartyUrnFromUuidTypeAndUuid(delegation.ToUuid, delegation.ToUuidType), + InstanceDelegationMode = delegation.InstanceDelegationMode, + ResourceId = delegation.ResourceId, + InstanceId = delegation.InstanceId + }; + + XacmlPolicy policy = await _prp.GetPolicyVersionAsync(delegation.BlobStoragePolicyPath, delegation.BlobStorageVersionId, cancellationToken); + appsInstanceDelegationResponse.Rights = GetRightsFromPolicy(policy); + result.Add(appsInstanceDelegationResponse); + } + + return result; + } + + private static List GetRightsFromPolicy(XacmlPolicy policy) + { + List result = new List(); + + foreach (XacmlRule xacmlRule in policy.Rules) + { + result.Add(GetInstanceRightDelegationResultFromPolicyRule(xacmlRule)); + } + + return result; + } + + private static InstanceRightDelegationResult GetInstanceRightDelegationResultFromPolicyRule(XacmlRule xacmlRule) + { + InstanceRightDelegationResult rule = new InstanceRightDelegationResult { Resource = [], Status = DelegationStatus.Delegated }; + + foreach (XacmlAnyOf anyOf in xacmlRule.Target.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action)) + { + rule.Action = ActionUrn.Parse($"{xacmlMatch.AttributeDesignator.AttributeId.OriginalString}:{xacmlMatch.AttributeValue.Value}"); + } + + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + UrnJsonTypeValue resourcePart = KeyValueUrn.Create($"{xacmlMatch.AttributeDesignator.AttributeId.OriginalString}:{xacmlMatch.AttributeValue.Value}", xacmlMatch.AttributeDesignator.AttributeId.OriginalString.Length + 1); + rule.Resource.Add(resourcePart); + } + } + } + } + + return rule; + } + + private static PartyUrn GetPartyUrnFromUuidTypeAndUuid(Guid uuid, UuidType type) + { + string urnString = null; + + switch (type) + { + case UuidType.Person: + case UuidType.Organization: + urnString = $"urn:altinn:party:uuid:{uuid.ToString()}"; + break; + } + + bool validParty = PartyUrn.TryParse(urnString, out PartyUrn result); + + return validParty ? result : null; + } + + private async Task> FindAllDelegations(int subjectUserId, int subjectPartyId, Guid subjectUuid, UuidType subjectUuidType, int reporteePartyId, string resourceId, ResourceAttributeMatchType resourceMatchType, bool includeInstanceDelegations = false, CancellationToken cancellationToken = default) + { + if (resourceMatchType == ResourceAttributeMatchType.None) + { + throw new NotSupportedException("Must specify the resource match type"); + } + + if ((subjectUserId == 0 ^ subjectPartyId == 0 ^ subjectUuidType == UuidType.NotSpecified) || (subjectUserId != 0 && subjectPartyId != 0 && subjectUuidType != UuidType.NotSpecified)) + { + throw new NotSupportedException("Must specify the single subjectUserId, subjectPartyId or subjectUuid"); + } + + List delegations = new List(); + List offeredByPartyIds = reporteePartyId.SingleToList(); + List resourceIds = resourceId.SingleToList(); + + // Check if request should include instance delegations, which will require lookup of reportee party uuid + Guid? fromParty = null; + List toParties = null; + if (includeInstanceDelegations) + { + Party reporteeParty = await _contextRetrievalService.GetPartyAsync(reporteePartyId, cancellationToken); + fromParty = reporteeParty?.PartyUuid; + toParties = new List(); + } + + // Check if mainunit exists + MainUnit mainunit = await _contextRetrievalService.GetMainUnit(reporteePartyId, cancellationToken); + if (mainunit?.PartyId > 0) + { + offeredByPartyIds.Add(mainunit.PartyId.Value); + } + + // 1. Direct user delegations + if (subjectUserId > 0) + { + delegations = resourceMatchType == ResourceAttributeMatchType.AltinnAppId + ? await _delegationRepository.GetAllCurrentAppDelegationChanges(offeredByPartyIds, resourceIds, coveredByUserIds: subjectUserId.SingleToList(), cancellationToken: cancellationToken) + : await _delegationRepository.GetAllCurrentResourceRegistryDelegationChanges(offeredByPartyIds, resourceIds, coveredByUserId: subjectUserId, cancellationToken: cancellationToken); + + if (includeInstanceDelegations) + { + UserProfile subjectUserProfile = await _profile.GetUser(new UserProfileLookup { UserId = subjectUserId }, cancellationToken: cancellationToken); + if (subjectUserProfile != null) + { + toParties.Add(subjectUserProfile.Party.PartyUuid.Value); + } + } + } + else if (subjectUuidType == UuidType.SystemUser) + { + delegations = resourceMatchType == ResourceAttributeMatchType.AltinnAppId + ? await _delegationRepository.GetAllCurrentAppDelegationChanges(resourceIds, offeredByPartyIds, subjectUuidType, subjectUuid, cancellationToken) + : await _delegationRepository.GetAllCurrentResourceRegistryDelegationChanges(resourceIds, offeredByPartyIds, subjectUuidType, subjectUuid, cancellationToken); + } + + // 2. Direct party delegations incl. any keyrole units + List coveredByPartyIds = subjectPartyId > 0 ? new List { subjectPartyId } : new List(); + + if (subjectUserId > 0) + { + coveredByPartyIds = await _contextRetrievalService.GetKeyRolePartyIds(subjectUserId, cancellationToken); + } + + if (coveredByPartyIds.Count > 0) + { + List partyDelegations = resourceMatchType == ResourceAttributeMatchType.AltinnAppId + ? await _delegationRepository.GetAllCurrentAppDelegationChanges(offeredByPartyIds, resourceIds, coveredByPartyIds: coveredByPartyIds, cancellationToken: cancellationToken) + : await _delegationRepository.GetAllCurrentResourceRegistryDelegationChanges(offeredByPartyIds, resourceIds, coveredByPartyIds: coveredByPartyIds, cancellationToken: cancellationToken); + delegations.AddRange(partyDelegations); + + if (includeInstanceDelegations) + { + List coveredByPartys = await _contextRetrievalService.GetPartiesAsync(coveredByPartyIds, cancellationToken: cancellationToken); + if (coveredByPartys.Count > 0) + { + toParties.AddRange(coveredByPartys.Select(p => p.PartyUuid.Value)); + } + } + } + + // 3. Get all instance delegations of the resource both directly delegated to user and indirectly through keyrole units + if (includeInstanceDelegations && fromParty.HasValue && toParties.Count > 0) + { + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + string[] resourceOrgApp = resourceId.Split('/'); + resourceIds = $"app_{resourceOrgApp[0]}_{resourceOrgApp[1]}".SingleToList(); + } + + delegations.AddRange(await GetInstanceDelegations(resourceIds, fromParty.Value, toParties, cancellationToken)); + } + + return delegations; + } + + private async Task> GetInstanceDelegations(List resourceIds, Guid from, List to, CancellationToken cancellationToken = default) + { + IEnumerable instanceDelegations = await _delegationRepository.GetActiveInstanceDelegations(resourceIds, from, to, cancellationToken); + return from InstanceDelegationChange instanceDelegation in instanceDelegations + let delegationChange = new DelegationChange + { + ResourceId = instanceDelegation.ResourceId, + InstanceId = instanceDelegation.InstanceId, + FromUuidType = instanceDelegation.FromUuidType, + FromUuid = instanceDelegation.FromUuid, + ToUuidType = instanceDelegation.ToUuidType, + ToUuid = instanceDelegation.ToUuid, + PerformedByUuidType = instanceDelegation.PerformedByType, + PerformedByUuid = instanceDelegation.PerformedBy, + DelegationChangeType = instanceDelegation.DelegationChangeType, + BlobStoragePolicyPath = instanceDelegation.BlobStoragePolicyPath, + BlobStorageVersionId = instanceDelegation.BlobStorageVersionId, + Created = instanceDelegation.Created + } + select delegationChange; + } + + private static List GetRulesFromPolicyAndDelegationChange(ICollection xacmlRules, DelegationChange delegationChange) + { + List rules = new List(); + foreach (XacmlRule xacmlRule in xacmlRules) + { + if (xacmlRule.Effect.Equals(XacmlEffectType.Permit) && xacmlRule.Target != null) + { + Rule rule = new Rule + { + RuleId = xacmlRule.RuleId, + OfferedByPartyId = delegationChange.OfferedByPartyId, + DelegatedByUserId = delegationChange.PerformedByUserId, + CoveredBy = new List(), + Resource = new List() + }; + AddAttributeMatchesToRule(xacmlRule.Target, rule); + rules.Add(rule); + } + } + + return rules; + } + + private static void AddAttributeMatchesToRule(XacmlTarget xacmlTarget, Rule rule) + { + foreach (XacmlAnyOf anyOf in xacmlTarget.AnyOf) + { + foreach (XacmlAllOf allOf in anyOf.AllOf) + { + foreach (XacmlMatch xacmlMatch in allOf.Matches) + { + AddAttributeMatchToRule(xacmlMatch, rule); + } + } + } + } + + private static void AddAttributeMatchToRule(XacmlMatch xacmlMatch, Rule rule) + { + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Action)) + { + rule.Action = new AttributeMatch + { + Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, + Value = xacmlMatch.AttributeValue.Value + }; + } + + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Subject)) + { + rule.CoveredBy.Add(new AttributeMatch + { + Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, + Value = xacmlMatch.AttributeValue.Value + }); + } + + if (xacmlMatch.AttributeDesignator.Category.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + rule.Resource.Add(new AttributeMatch + { + Id = xacmlMatch.AttributeDesignator.AttributeId.OriginalString, + Value = xacmlMatch.AttributeValue.Value + }); + } + } + + private static void EnrichRightsDictionaryWithRightsFromPolicy(Dictionary rights, XacmlPolicy policy, RightSourceType policySourceType, List subjectMatches, int minimumAuthenticationLevel = 0, int delegationOfferedByPartyId = 0, bool returnAllPolicyRights = false, bool getDelegableRights = false) + { + PolicyDecisionPoint pdp = new PolicyDecisionPoint(); + + foreach (XacmlRule rule in policy.Rules) + { + XacmlPolicy singleRulePolicy = new XacmlPolicy(new Uri($"{policy.PolicyId}_{rule.RuleId}"), policy.RuleCombiningAlgId, policy.Target); + singleRulePolicy.Rules.Add(rule); + + List> ruleSubjects = PolicyHelper.GetRulePolicyAttributeMatchesForCategory(rule, XacmlConstants.MatchAttributeCategory.Subject); + ICollection ruleRights = PolicyHelper.GetRightsFromXacmlRules(rule.SingleToList()); + foreach (Right ruleRight in ruleRights) + { + ICollection contextAttributes = PolicyHelper.GetContextAttributes(subjectMatches, ruleRight.Resource, ruleRight.Action.SingleToList()); + XacmlContextRequest authRequest = new XacmlContextRequest(false, false, contextAttributes); + + XacmlContextResponse response = pdp.Authorize(authRequest, singleRulePolicy); + XacmlContextResult decisionResult = response.Results.First(); + + // If getting rights for delegation, the right source is a delegation policy and the right does no longer exist in the app/resource policy: it should NOT be added as a delegable right + if (getDelegableRights && policySourceType == RightSourceType.DelegationPolicy && !rights.ContainsKey(ruleRight.RightKey)) + { + continue; + } + + if (!rights.TryGetValue(ruleRight.RightKey, out Right right)) + { + rights.Add(ruleRight.RightKey, ruleRight); + right = ruleRight; + } + + // If getting rights for delegation, the xacml decision is to be used for indicating if the user can delegate the right. Otherwise the decision indicate whether the user actually have the right. + if (getDelegableRights) + { + right.CanDelegate = (right.CanDelegate.HasValue && right.CanDelegate.Value) || decisionResult.Decision.Equals(XacmlContextDecision.Permit); + } + else + { + right.HasPermit = (right.HasPermit.HasValue && right.HasPermit.Value) || decisionResult.Decision.Equals(XacmlContextDecision.Permit); + } + + if (decisionResult.Decision.Equals(XacmlContextDecision.Permit) || returnAllPolicyRights) + { + right.RightSources.Add( + new RightSource + { + PolicyId = policy.PolicyId.OriginalString, + PolicyVersion = policy.Version, + RuleId = rule.RuleId, + RightSourceType = policySourceType, + HasPermit = getDelegableRights ? null : decisionResult.Decision.Equals(XacmlContextDecision.Permit), + CanDelegate = getDelegableRights ? decisionResult.Decision.Equals(XacmlContextDecision.Permit) : null, + MinimumAuthenticationLevel = minimumAuthenticationLevel, + OfferedByPartyId = delegationOfferedByPartyId, + UserSubjects = subjectMatches, + PolicySubjects = ruleSubjects + }); + } + } + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyRetrievalPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyRetrievalPoint.cs new file mode 100644 index 00000000..094bc6e2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyRetrievalPoint.cs @@ -0,0 +1,88 @@ +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Authorization.ABAC.Xacml; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + /// The Policy Retrieval point responsible to find the correct policy + /// based on the context Request + /// + public class PolicyRetrievalPoint : IPolicyRetrievalPoint + { + private readonly IPolicyFactory _policyFactory; + private readonly IMemoryCache _memoryCache; + private readonly CacheConfig _cacheConfig; + + /// + /// Initializes a new instance of the class. + /// + /// The policy factory + /// The cache handler + /// The cache config settings + public PolicyRetrievalPoint(IPolicyFactory policyFactory, IMemoryCache memoryCache, IOptions cacheConfig) + { + _policyFactory = policyFactory; + _memoryCache = memoryCache; + _cacheConfig = cacheConfig.Value; + } + + /// + public async Task GetPolicyAsync(XacmlContextRequest request, CancellationToken cancellationToken = default) + { + string policyPath = PolicyHelper.GetPolicyPath(request); + return await GetPolicyInternalAsync(policyPath, cancellationToken: cancellationToken); + } + + /// + public async Task GetPolicyAsync(string org, string app, CancellationToken cancellationToken = default) + { + string policyPath = PolicyHelper.GetAltinnAppsPolicyPath(org, app); + return await GetPolicyInternalAsync(policyPath, cancellationToken: cancellationToken); + } + + /// + public async Task GetPolicyAsync(string resourceRegistryId, CancellationToken cancellationToken = default) + { + string policyPath = PolicyHelper.GetResourceRegistryPolicyPath(resourceRegistryId); + return await GetPolicyInternalAsync(policyPath, cancellationToken: cancellationToken); + } + + /// + public async Task GetPolicyVersionAsync(string policyPath, string version, CancellationToken cancellationToken = default) + { + return await GetPolicyInternalAsync(policyPath, version, cancellationToken); + } + + private async Task GetPolicyInternalAsync(string policyPath, string version = "", CancellationToken cancellationToken = default) + { + if (!_memoryCache.TryGetValue(policyPath + version, out XacmlPolicy policy)) + { + Stream policyBlob = string.IsNullOrEmpty(version) ? + await _policyFactory.Create(policyPath).GetPolicyAsync(cancellationToken) : + await _policyFactory.Create(policyPath).GetPolicyVersionAsync(version, cancellationToken); + using (policyBlob) + { + policy = (policyBlob.Length > 0) ? PolicyHelper.ParsePolicy(policyBlob) : null; + } + + PutXacmlPolicyInCache(policyPath, policy); + } + + return policy; + } + + private void PutXacmlPolicyInCache(string policyPath, XacmlPolicy policy) + { + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetPriority(CacheItemPriority.High) + .SetAbsoluteExpiration(new TimeSpan(0, _cacheConfig.PolicyCacheTimeout, 0)); + + _memoryCache.Set(policyPath, policy, cacheEntryOptions); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ResourceAdministrationPoint.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ResourceAdministrationPoint.cs new file mode 100644 index 00000000..902dd1ba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/ResourceAdministrationPoint.cs @@ -0,0 +1,89 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Microsoft.Extensions.Logging; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + public class ResourceAdministrationPoint : IResourceAdministrationPoint + { + private readonly ILogger _logger; + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IResourceMetadataRepository _resourceRepository; + + /// + /// Initializes a new instance of the class. + /// + /// The data layer to handle Resource related persistence + /// Logger instance. + /// the handler for resource registry client + public ResourceAdministrationPoint( + IResourceMetadataRepository resourceRepository, + ILogger logger, + IContextRetrievalService contextRetrievalService) + { + _resourceRepository = resourceRepository; + _logger = logger; + _contextRetrievalService = contextRetrievalService; + } + + /// + public async Task> GetResources(ResourceType resourceType) + { + try + { + List resources = await _contextRetrievalService.GetResources(); + return resources.FindAll(r => r.ResourceType == resourceType); + } + catch (Exception) + { + _logger.LogError("//ResourceAdministrationPoint // GetResources by resourcetype failed to fetch resources"); + throw; + } + } + + /// + public async Task> GetResources(string scope) + { + List filteredResources = new List(); + + List resources = await _contextRetrievalService.GetResources(); + + foreach (ServiceResource resource in resources.Where(r => r.ResourceType == ResourceType.MaskinportenSchema && r.ResourceReferences != null)) + { + foreach (ResourceReference reference in resource.ResourceReferences.Where(rf => rf.ReferenceType == ReferenceType.MaskinportenScope && rf.Reference.Equals(scope))) + { + filteredResources.Add(resource); + } + } + + return filteredResources; + } + + /// + public async Task GetResource(string resourceRegistryId) + { + return await _contextRetrievalService.GetResource(resourceRegistryId); + } + + /// + public async Task> TryWriteResourceFromResourceRegister(List resources) + { + List result = new List(); + + foreach (AccessManagementResource resource in resources) + { + AccessManagementResource current = await _resourceRepository.InsertAccessManagementResource(resource); + + if (current != null) + { + result.Add(current); + } + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs new file mode 100644 index 00000000..0ea569c8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs @@ -0,0 +1,533 @@ +using System.Reflection; +using Altinn.AccessManagement.Core.Asserters; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.AccessList; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.Platform.Profile.Enums; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using Altinn.Urn.Json; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + public class SingleRightsService : ISingleRightsService + { + private readonly IContextRetrievalService _contextRetrievalService; + private readonly IPolicyInformationPoint _pip; + private readonly IPolicyAdministrationPoint _pap; + private readonly IAltinn2RightsClient _altinn2RightsClient; + private readonly IAccessListsAuthorizationClient _accessListsAuthorizationClient; + private readonly IProfileClient _profile; + private readonly IUserProfileLookupService _profileLookup; + private readonly IAttributeResolver _resolver; + private readonly IAssert _asserter; + + /// + /// Initializes a new instance of the class. + /// + /// a + /// b + /// Service for retrieving context information + /// Service implementation for policy information point + /// Service implementation for policy administration point + /// SBL Bridge client implementation for rights operations on Altinn 2 services + /// A client for access list authorization actions. + /// Client implementation for getting user profile + /// Service implementation for lookup of userprofile with lastname verification + public SingleRightsService(IAttributeResolver resolver, IAssert asserter, IContextRetrievalService contextRetrievalService, IPolicyInformationPoint pip, IPolicyAdministrationPoint pap, IAltinn2RightsClient altinn2RightsClient, IAccessListsAuthorizationClient accessListsAuthorizationClient, IProfileClient profile, IUserProfileLookupService profileLookup) + { + _resolver = resolver; + _asserter = asserter; + _contextRetrievalService = contextRetrievalService; + _pip = pip; + _pap = pap; + _altinn2RightsClient = altinn2RightsClient; + _accessListsAuthorizationClient = accessListsAuthorizationClient; + _profile = profile; + _profileLookup = profileLookup; + } + + /// + public async Task RightsDelegationCheck(int authenticatedUserId, int authenticatedUserAuthlevel, RightsDelegationCheckRequest request) + { + (DelegationCheckResponse result, ServiceResource resource, Party fromParty) = await ValidateRightDelegationCheckRequest(request); + if (!result.IsValid) + { + return result; + } + + RightsQuery rightsQuery; + DelegationHelper.TryGetResourceFromAttributeMatch(request.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + if (resource.ResourceType == ResourceType.Altinn2Service) + { + return await _altinn2RightsClient.PostDelegationCheck(authenticatedUserId, fromParty.PartyId, serviceCode, serviceEditionCode); + } + + rightsQuery = RightsHelper.GetRightsQuery(authenticatedUserId, fromParty.PartyId, resource); + + List allDelegableRights = await _pip.GetRights(rightsQuery, getDelegableRights: true, returnAllPolicyRights: true); + if (allDelegableRights == null || allDelegableRights.Count == 0) + { + result.Errors.Add("right[0].Resource", $"No delegable rights could be found for the resource: {resource}"); + return result; + } + + // Build result model with status + foreach (Right right in allDelegableRights) + { + if (!RightsHelper.CheckIfRuleIsAnEndUserRule(right)) + { + continue; + } + + AccessListAuthorizationResult accessListAuthorizationResult = AccessListAuthorizationResult.NotApplicable; + + if (DelegationHelper.IsAccessListModeEnabledAndApplicable(right, resource, fromParty)) + { + AccessListAuthorizationRequest accessListAuthorizationRequest = new AccessListAuthorizationRequest + { + Subject = PartyUrn.OrganizationIdentifier.Create(OrganizationNumber.CreateUnchecked(fromParty.OrgNumber)), + Resource = ResourceIdUrn.ResourceId.Create(ResourceIdentifier.CreateUnchecked(resource.Identifier)), + Action = ActionUrn.ActionId.Create(ActionIdentifier.CreateUnchecked(right.Action.Value)) + }; + + AccessListAuthorizationResponse accessListAuthorizationResponse = await _accessListsAuthorizationClient.AuthorizePartyForAccessList(accessListAuthorizationRequest); + accessListAuthorizationResult = accessListAuthorizationResponse.Result; + } + + RightDelegationCheckResult rightDelegationStatus = new() + { + RightKey = right.RightKey, + Resource = right.Resource, + Action = right.Action, + Details = RightsHelper.AnalyzeDelegationAccessReason(right, accessListAuthorizationResult) + }; + + rightDelegationStatus.Status = (right.CanDelegate.HasValue && right.CanDelegate.Value) ? DelegableStatus.Delegable : DelegableStatus.NotDelegable; + + result.RightDelegationCheckResults.Add(rightDelegationStatus); + } + + return result; + } + + /// + public async Task DelegateRights(int authenticatedUserId, int authenticatedUserAuthlevel, DelegationLookup delegation, CancellationToken cancellationToken = default) + { + (DelegationActionResult result, ServiceResource resource, Party fromParty, List to) = await ValidateDelegationLookupModel(DelegationActionType.Delegation, delegation, authenticatedUserId); + if (!result.IsValid) + { + return result; + } + + // Altinn 2 service delegation is handled by SBL Bridge + if (resource.ResourceType == ResourceType.Altinn2Service) + { + SblRightDelegationRequest sblRightDelegationRequest = new SblRightDelegationRequest { To = to.FirstOrDefault(), Rights = delegation.Rights }; + DelegationActionResult sblResult = await _altinn2RightsClient.PostDelegation(authenticatedUserId, fromParty.PartyId, sblRightDelegationRequest); + + sblResult.To = result.To; // Set result.To to match original input + return sblResult; + } + + // Verify authenticated users delegable rights + RightsQuery rightsQuery = RightsHelper.GetRightsQuery(authenticatedUserId, fromParty.PartyId, resource); + List usersDelegableRights = await _pip.GetRights(rightsQuery, getDelegableRights: true, cancellationToken: cancellationToken); + if (usersDelegableRights == null || usersDelegableRights.Count == 0) + { + result.Errors.Add("right[0].Resource", $"Authenticated user does not have any delegable rights for the resource: {resource.Identifier}"); + return result; + } + + // Perform delegation + List rulesToDelegate = new List(); + List rightsUserCantDelegate = new List(); + foreach (Right rightToDelegate in delegation.Rights) + { + if (usersDelegableRights.Contains(rightToDelegate)) + { + // If delegable and serviceResource.AccessListMode is enabled, call accessListAuthorizationClient + AccessListAuthorizationResult accessListAuthorizationResult = AccessListAuthorizationResult.NotApplicable; + if (DelegationHelper.IsAccessListModeEnabledAndApplicable(rightToDelegate, resource, fromParty)) + { + AccessListAuthorizationRequest accessListAuthorizationRequest = new AccessListAuthorizationRequest + { + Subject = PartyUrn.OrganizationIdentifier.Create(OrganizationNumber.CreateUnchecked(fromParty.OrgNumber)), + Resource = ResourceIdUrn.ResourceId.Create(ResourceIdentifier.CreateUnchecked(resource.Identifier)), + Action = ActionUrn.ActionId.Create(ActionIdentifier.CreateUnchecked(rightToDelegate.Action.Value)) + }; + + AccessListAuthorizationResponse accessListAuthorizationResponse = await _accessListsAuthorizationClient.AuthorizePartyForAccessList(accessListAuthorizationRequest); + accessListAuthorizationResult = accessListAuthorizationResponse.Result; + } + + if (resource.AccessListMode == Enums.ResourceRegistry.ResourceAccessListMode.Enabled && accessListAuthorizationResult != AccessListAuthorizationResult.Authorized) + { + rightToDelegate.CanDelegate = false; + rightsUserCantDelegate.Add(rightToDelegate); + } + else + { + rulesToDelegate.Add(new Rule + { + DelegatedByUserId = authenticatedUserId, + OfferedByPartyId = fromParty.PartyId, + OfferedByPartyUuid = fromParty.PartyUuid, + OfferedByPartyType = fromParty.Person != null ? UuidType.Person : UuidType.Organization, + CoveredBy = to, + Resource = rightToDelegate.Resource, + Action = rightToDelegate.Action + }); + } + } + else + { + rightsUserCantDelegate.Add(rightToDelegate); + } + } + + List delegationResult = await _pap.TryWriteDelegationPolicyRules(rulesToDelegate); + result.Rights = DelegationHelper.GetRightDelegationResultsFromRules(delegationResult); + + if (rightsUserCantDelegate.Any()) + { + result.Rights.AddRange(DelegationHelper.GetRightDelegationResultsFromFailedRights(rightsUserCantDelegate)); + } + + return await Task.FromResult(result); + } + + /// + public Task> GetOfferedRights(AttributeMatch reportee, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task> GetReceivedRights(AttributeMatch reportee, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public async Task RevokeRightsDelegation(int authenticatedUserId, DelegationLookup delegation, CancellationToken cancellationToken) + { + var assertion = AssertRevokeDelegationInput(delegation); + if (assertion != null) + { + return assertion; + } + + var fromAttribute = await _resolver.Resolve(delegation.From, [AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute], cancellationToken); + var toAttribute = await _resolver.Resolve(delegation.To, BaseUrn.Altinn2InternalIds, cancellationToken); + + var to = toAttribute.Any(p => p.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute) + ? new AttributeMatch(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, toAttribute.First(p => p.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute).Value) + : new AttributeMatch(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, toAttribute.First(p => p.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute).Value); + + var policiesToDelete = DelegationHelper.GetRequestToDeleteResource(authenticatedUserId, delegation.Rights[0].Resource, fromAttribute.GetRequiredInt(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute), to); + + await _pap.TryDeleteDelegationPolicies(policiesToDelete, cancellationToken); + return assertion; + } + + /// + /// Ensures that given input for revoking a delegations contains a combination of attributes that + /// the service layer can process. If the method return null then input should be processable. + /// + /// input parameters from API callee + private ValidationProblemDetails AssertRevokeDelegationInput(DelegationLookup delegation) => + _asserter.Join( + _asserter.Evaluate( + delegation.From, + _asserter.Altinn2InternalIds), + _asserter.Evaluate( + delegation.To, + _asserter.Altinn2InternalIds), + _asserter.Evaluate( + delegation.Rights?.FirstOrDefault()?.Resource ?? [], + _asserter.DefaultResource)); + + private async Task<(DelegationCheckResponse Result, ServiceResource Resource, Party FromParty)> ValidateRightDelegationCheckRequest(RightsDelegationCheckRequest request) + { + DelegationCheckResponse result = new DelegationCheckResponse { From = request.From, RightDelegationCheckResults = new() }; + + DelegationHelper.TryGetResourceFromAttributeMatch(request.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + + if (resourceMatchType == ResourceAttributeMatchType.None) + { + result.Errors.Add("right[0].Resource", $"The specified resource is not recognized. The operation only support requests for a single resource from either the Altinn Resource Registry identified by using the {AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute} attribute id, Altinn Apps identified by using {AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute} and {AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute}, or Altinn 2 services identified by using {AltinnXacmlConstants.MatchAttributeIdentifiers.ServiceCodeAttribute}"); + return (result, null, null); + } + + // Verify resource is valid + ServiceResource resource = await _contextRetrievalService.GetResourceFromResourceList(resourceRegistryId, org, app, serviceCode, serviceEditionCode); + if (resource == null || !resource.Delegable) + { + result.Errors.Add("right[0].Resource", $"The resource does not exist or is not available for delegation"); + return (result, resource, null); + } + + if (resource.ResourceType == ResourceType.MaskinportenSchema) + { + result.Errors.Add("right[0].Resource", $"This operation does not support MaskinportenSchema resources. Please use the MaskinportenSchema DelegationCheck API. Invalid resource: {resourceRegistryId}. Invalid resource type: {resource.ResourceType}"); + return (result, resource, null); + } + + // Verify and get From reportee party of the delegation + Party fromParty = null; + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(request.From, out string fromOrgNo)) + { + fromParty = await _contextRetrievalService.GetPartyForOrganization(fromOrgNo); + } + else if (DelegationHelper.TryGetSocialSecurityNumberAttributeMatch(request.From, out string fromSsn)) + { + // ToDo: Can we do this based on SSN alone for the Reportee or do we need last name? + fromParty = await _contextRetrievalService.GetPartyForPerson(fromSsn); + } + else if (DelegationHelper.TryGetPartyIdFromAttributeMatch(request.From, out int fromPartyId)) + { + List fromPartyLookup = await _contextRetrievalService.GetPartiesAsync(fromPartyId.SingleToList()); + fromParty = fromPartyLookup.FirstOrDefault(); + } + + if (fromParty == null) + { + // This shouldn't really happen, as to get here the request must have been authorized for the From reportee, but the register integration could fail. + result.Errors.Add("From", $"Could not identify the From party. Please try again."); + return (result, resource, null); + } + + return (result, resource, fromParty); + } + + private async Task<(DelegationActionResult Result, ServiceResource Resource, Party FromParty, List To)> ValidateDelegationLookupModel(DelegationActionType delegationAction, DelegationLookup delegation, int authenticatedUserId) + { + DelegationActionResult result = new DelegationActionResult { From = delegation.From, To = delegation.To, Rights = new List() }; + + if (delegation.Rights.Count == 0) + { + result.Errors.Add("Rights", "Request must contain at least one right to be delegated"); + return (result, null, null, null); + } + + // Verify request is for single resource, app or Altinn 2 service + if (delegation.Rights.Count > 1 && !ValidateAllRightsAreForTheSameResource(delegation.Rights)) + { + result.Errors.Add("Rights", "Rights delegation only support requests where all rights are for the same resource, app or Altinn 2 service"); + return (result, null, null, null); + } + + DelegationHelper.TryGetResourceFromAttributeMatch(delegation.Rights[0].Resource, out ResourceAttributeMatchType _, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + + ServiceResource resource = await _contextRetrievalService.GetResourceFromResourceList(resourceRegistryId, org, app, serviceCode, serviceEditionCode); + if (resource == null || !resource.Delegable) + { + result.Errors.Add("right[0].Resource", $"The resource does not exist or is not available for delegation"); + return (result, resource, null, null); + } + + if (resource.ResourceType == ResourceType.MaskinportenSchema) + { + result.Errors.Add("right[0].Resource", $"This operation does not support delegations for MaskinportenSchema resources. Please use the MaskinportenSchema Delegations API. Invalid resource: {resourceRegistryId}. Invalid resource type: {resource.ResourceType}"); + return (result, resource, null, null); + } + + // Verify and get From reportee party of the delegation + Party fromParty = null; + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(delegation.From, out string fromOrgNo)) + { + fromParty = await _contextRetrievalService.GetPartyForOrganization(fromOrgNo); + } + else if (DelegationHelper.TryGetSocialSecurityNumberAttributeMatch(delegation.From, out string fromSsn)) + { + fromParty = await _contextRetrievalService.GetPartyForPerson(fromSsn); + } + else if (DelegationHelper.TryGetPartyIdFromAttributeMatch(delegation.From, out int fromPartyId)) + { + List fromPartyLookup = await _contextRetrievalService.GetPartiesAsync(fromPartyId.SingleToList()); + fromParty = fromPartyLookup.FirstOrDefault(); + } + + if (fromParty == null) + { + // This shouldn't really happen, as to get here the request must have been authorized for the From reportee, but the register integration could fail. + result.Errors.Add("From", $"Could not identify the From party. Please try again."); + return (result, resource, null, null); + } + + // Verify and get To recipient party of the delegation + Party toParty = null; + UserProfile toUser = null; + SystemUser toSystemUser = null; + + if (DelegationHelper.TryGetOrganizationNumberFromAttributeMatch(delegation.To, out string toOrgNo)) + { + toParty = await _contextRetrievalService.GetPartyForOrganization(toOrgNo); + } + else if (DelegationHelper.TryGetSocialSecurityNumberAndLastNameAttributeMatch(delegation.To, out string toSsn, out string toLastName)) + { + toUser = await _profileLookup.GetUserProfile(authenticatedUserId, new UserProfileLookup { Ssn = toSsn }, toLastName); + } + else if (DelegationHelper.TryGetUsernameAndLastNameAttributeMatch(delegation.To, out string toUsername, out toLastName)) + { + toUser = await _profileLookup.GetUserProfile(authenticatedUserId, new UserProfileLookup { Username = toUsername }, toLastName); + } + else if (DelegationHelper.TryGetEnterpriseUserNameAttributeMatch(delegation.To, out string enterpriseUserName)) + { + toUser = await _profile.GetUser(new UserProfileLookup { Username = enterpriseUserName }); + + if (toUser != null && toUser.Party.PartyTypeName != PartyType.Organisation && toUser.Party.PartyId != fromParty.PartyId) + { + result.Errors.Add("To", $"Enterpriseuser either does not exist or does not belong to the From party and cannot be delegated to."); + return (result, resource, null, null); + } + } + else if (DelegationHelper.TryGetSingleAttributeMatchValue(delegation.To, AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid, out string toPersonUuidAttrValue)) + { + if (Guid.TryParse(toPersonUuidAttrValue, out Guid toPersonUuid)) + { + toUser = await _profile.GetUser(new UserProfileLookup { UserUuid = toPersonUuid }); + } + + if (toUser != null && toUser.Party.PartyTypeName != PartyType.Person) + { + result.Errors.Add("To", $"The provided To attribute value could not be found as a valid person."); + return (result, resource, null, null); + } + } + else if (DelegationHelper.TryGetSingleAttributeMatchValue(delegation.To, AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid, out string toEnterpriseUserUuidAttrValue)) + { + if (Guid.TryParse(toEnterpriseUserUuidAttrValue, out Guid toEnterpriseUserUuid)) + { + toUser = await _profile.GetUser(new UserProfileLookup { UserUuid = toEnterpriseUserUuid }); + } + + if (toUser != null && toUser.Party.PartyTypeName != PartyType.Organisation && toUser.Party.PartyId != fromParty.PartyId) + { + result.Errors.Add("To", $"Enterpriseuser either does not exist or does not belong to the From party and cannot be delegated to."); + return (result, resource, null, null); + } + } + else if (DelegationHelper.TryGetSingleAttributeMatchValue(delegation.To, AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid, out string toOrganizationUuidAttrValue)) + { + if (Guid.TryParse(toOrganizationUuidAttrValue, out Guid toOrganizationUuid)) + { + toParty = await _contextRetrievalService.GetPartyByUuid(toOrganizationUuid); + } + + if (toParty != null && toParty.PartyTypeName != PartyType.Organisation) + { + result.Errors.Add("To", $"The provided To attribute value could not be found as a valid organization."); + return (result, resource, null, null); + } + } + else if (DelegationHelper.TryGetSingleAttributeMatchValue(delegation.To, AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid, out string toSystemUserUuidAttrValue)) + { + toSystemUser = await _contextRetrievalService.GetSystemUserById(fromParty.PartyId, toSystemUserUuidAttrValue); + + if (toSystemUser == null) + { + result.Errors.Add("To", $"The provided To attribute value could not be found as a valid systemuser."); + return (result, resource, null, null); + } + + // Verify the resource is on the list of resources for system if this is a delegation + if (delegationAction == DelegationActionType.Delegation) + { + List defaultRights = await _contextRetrievalService.GetDefaultRightsForRegisteredSystem(toSystemUser.SystemId); + bool resourceValid = DelegationHelper.CheckResourceIsInListOfDefaultRights(defaultRights, delegation.Rights[0].Resource); + + if (!resourceValid) + { + result.Errors.Add("right[0].Resource", $"The resource does not exist or is not available for delegation to this systemuser"); + return (result, resource, null, null); + } + } + } + + if (toParty == null && toUser == null && toSystemUser == null) + { + result.Errors.Add("To", $"A distinct recipient party for the delegation, could not be identified by the supplied attributes. A recipient can be identified by either a single {AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute} or {AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserName} attribute, or a combination of {AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId} and {AltinnXacmlConstants.MatchAttributeIdentifiers.PersonLastName} attributes, {AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUserName} and {AltinnXacmlConstants.MatchAttributeIdentifiers.PersonLastName} attributes or {AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid} attribute."); + return (result, resource, null, null); + } + + // Verify delegation From and To is not the same party (with exception for Altinn 2 Enterprise users) + if (fromParty.PartyId == toParty?.PartyId || (toUser != null && fromParty.PartyId == toUser.PartyId && toUser.Party.PartyTypeName != PartyType.Organisation)) + { + result.Errors.Add("To", $"The From party and the To recipient are the same. Self-delegation is not supported as it serves no purpose."); + return (result, resource, null, null); + } + + // Build To AttributeMatch to be used for the delegation rules + List to = new List(); + if (toParty != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = toParty.PartyId.ToString() }); + if (toParty.PartyTypeName == PartyType.Organisation && toParty.PartyUuid != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid, Value = toParty.PartyUuid.ToString() }); + } + } + + if (toUser != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, Value = toUser.UserId.ToString() }); + if (toUser.UserType == UserType.EnterpriseIdentified && toUser.UserUuid != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid, Value = toUser.UserUuid.ToString() }); + } + + if (toUser.UserType == UserType.SSNIdentified && toUser.UserUuid != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid, Value = toUser.UserUuid.ToString() }); + } + } + + if (toSystemUser != null) + { + to.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid, Value = toSystemUser.Id }); + } + + return (result, resource, fromParty, to); + } + + private static bool ValidateAllRightsAreForTheSameResource(List rights) + { + string firstResourceKey = string.Empty; + foreach (Right right in rights) + { + DelegationHelper.TryGetResourceFromAttributeMatch(right.Resource, out ResourceAttributeMatchType resourceMatchType, out string resourceRegistryId, out string org, out string app, out string serviceCode, out string serviceEditionCode); + string currentResourceKey = $"{resourceMatchType}{resourceRegistryId}{org}{app}{serviceCode}{serviceEditionCode}"; + + if (firstResourceKey == string.Empty) + { + firstResourceKey = currentResourceKey; + } + + if (firstResourceKey != currentResourceKey) + { + return false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/UserProfileLookupService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/UserProfileLookupService.cs new file mode 100644 index 00000000..535a2ed6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/UserProfileLookupService.cs @@ -0,0 +1,72 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Profile.Models; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Core.Services +{ + /// + /// Service implementation wrapping UserProfile lookup with lastname verification and preventing users for guessing too many faulty combination of SSN/Username and Last Name + /// + public class UserProfileLookupService : IUserProfileLookupService + { + private const string UserProfileLookupFailedAttempts = "UserProfile-Lookup-Failed-Attempts"; + + private readonly UserProfileLookupSettings _userProfileLookupSettings; + private readonly ILogger _logger; + private readonly IMemoryCache _memoryCache; + private readonly IProfileClient _profile; + + /// + /// Initializes a new instance of the class + /// + /// Logger service + /// Cache config + /// The cache handler + /// The client for integration with profile API + public UserProfileLookupService(ILogger logger, IOptions userProfileLookupSettings, IMemoryCache memoryCache, IProfileClient profile) + { + _userProfileLookupSettings = userProfileLookupSettings.Value; + _logger = logger; + _memoryCache = memoryCache; + _profile = profile; + } + + /// + public async Task GetUserProfile(int authnUserId, UserProfileLookup lookupIdentifier, string lastName) + { + string uniqueCacheKey = UserProfileLookupFailedAttempts + authnUserId; + + _ = _memoryCache.TryGetValue(uniqueCacheKey, out int failedAttempts); + if (failedAttempts >= _userProfileLookupSettings.MaximumFailedAttempts) + { + _logger.LogInformation( + "User {userId} has performed too many failed UserProfile lookup attempts.", authnUserId); + + throw new TooManyFailedLookupsException(); + } + + UserProfile userProfile = await _profile.GetUser(lookupIdentifier); + + string nameFromParty = userProfile?.Party.Person.LastName ?? string.Empty; + + if (nameFromParty.Length > 0 && nameFromParty.IsSimilarTo(lastName)) + { + return userProfile; + } + + failedAttempts += 1; + MemoryCacheEntryOptions memoryCacheOptions = new() + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_userProfileLookupSettings.FailedAttemptsCacheLifetimeSeconds) + }; + _memoryCache.Set(uniqueCacheKey, failedAttempts, memoryCacheOptions); + return null; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Utilities/RegexUtil.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Utilities/RegexUtil.cs new file mode 100644 index 00000000..ed0c1ae3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Utilities/RegexUtil.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Altinn.AccessManagement.Core.Utilities +{ + /// + /// Compilation of different regex checks + /// + public static class RegexUtil + { + private static readonly Regex OrgNumber = new Regex(@"^\d{9}$"); + + private static readonly Regex SSN = new Regex(@"^\d{11}$"); + + private static readonly Regex Username = new Regex(@"(?!^\d+$)^[a-zA-Z0-9._@\-]{6,64}$"); + + private static readonly Regex MaskinportenScopes = new Regex(@"^([a-z0-9]+:)([a-z0-9]+\/?)+[a-z0-9]+(\.[a-z0-9]+)?$"); + + /// + /// Check for Orgnumber + /// Should be 9 numbers + /// + /// orgnumer to check + /// result of regex match + public static bool CheckOrgNumber(string orgnumber) + { + return OrgNumber.IsMatch(orgnumber); + } + + /// + /// Checks if it is a valid username + /// Should be between 6-64, can contain number, letters, ., _, @, - + /// Can not only be numbers + /// + /// the username + /// the result of the check + public static bool CheckUsername(string username) + { + return Username.IsMatch(username); + } + + /// + /// Checks if it is a valid ssn + /// Should be 9 chars long, can only be numbers + /// + /// the ssn + /// the result of the check + public static bool CheckSSN(string ssn) + { + return SSN.IsMatch(ssn); + } + + /// + /// Check if scope is valid + /// + /// The scope to be validated + /// A bool indicating if the scope is well formatted + public static bool IsValidMaskinportenScope(string scope) + { + return MaskinportenScopes.IsMatch(scope); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Altinn.AccessManagement.Integration.csproj b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Altinn.AccessManagement.Integration.csproj new file mode 100644 index 00000000..93148506 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Altinn.AccessManagement.Integration.csproj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AccessListAuthorizationClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AccessListAuthorizationClient.cs new file mode 100644 index 00000000..bc650299 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AccessListAuthorizationClient.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Extensions; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models.AccessList; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.Authorization.ProblemDetails; +using Altinn.Common.AccessTokenClient.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients +{ + /// + /// A client for access list authorization actions. + /// + [ExcludeFromCodeCoverage] + public class AccessListAuthorizationClient : IAccessListsAuthorizationClient + { + private readonly ILogger _logger; + private readonly HttpClient _client; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly PlatformSettings _platformSettings; + private readonly IAccessTokenGenerator _accessTokenGenerator; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter() } }; + + /// + /// Initializes a new instance of the class. + /// + /// HttpClient from default httpclientfactory + /// the logger + /// handler for http context + /// the platform setttings + /// An instance of the AccessTokenGenerator service. + public AccessListAuthorizationClient( + IOptions platformSettings, + IHttpContextAccessor httpContextAccessor, + ILogger logger, + HttpClient httpClient, + IAccessTokenGenerator accessTokenGenerator) + { + _logger = logger; + _platformSettings = platformSettings.Value; + httpClient.BaseAddress = new Uri(platformSettings.Value.ApiAuthorizationEndpoint); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _client = httpClient; + _httpContextAccessor = httpContextAccessor; + _accessTokenGenerator = accessTokenGenerator; + } + + /// + public async Task AuthorizePartyForAccessList(AccessListAuthorizationRequest request, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = "accesslist/accessmanagement/authorization"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _client.PostAsync(token, endpointUrl, requestBody, accessToken, cancellationToken); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + return await response.Content.ReadFromJsonAsync(cancellationToken); + } + else + { + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + _logger.LogError("AccessManagement // AccessListAuthorizationClient // AuthorizePartyForAccessList // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return new() { Result = AccessListAuthorizationResult.NotAuthorized }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AccessListAuthorizationClient // AuthorizePartyForAccessList // Exception"); + throw; + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/Altinn2RightsClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/Altinn2RightsClient.cs new file mode 100644 index 00000000..982819f0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/Altinn2RightsClient.cs @@ -0,0 +1,120 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.AccessManagement.Integration.Services.Interfaces; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients; + +/// +/// Client for getting Altinn roles from AltinnII SBL Bridge +/// +[ExcludeFromCodeCoverage] +public class Altinn2RightsClient : IAltinn2RightsClient +{ + private readonly SblBridgeSettings _sblBridgeSettings; + private readonly HttpClient _client; + private readonly ILogger _logger; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + private readonly IPlatformAuthorizationTokenProvider _sblTokenProvider; + + /// + /// Initializes a new instance of the class + /// + /// HttpClient from default httpclientfactory + /// the sbl bridge settings + /// the logger + /// instance of authorization platform token provider + public Altinn2RightsClient(HttpClient httpClient, IOptions sblBridgeSettings, ILogger logger, IPlatformAuthorizationTokenProvider sblTokenProvider) + { + _sblBridgeSettings = sblBridgeSettings.Value; + _logger = logger; + _client = httpClient; + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _serializerOptions.Converters.Add(new JsonStringEnumConverter()); + _sblTokenProvider = sblTokenProvider; + } + + /// + public async Task PostDelegationCheck(int authenticatedUserId, int reporteePartyId, string serviceCode, string serviceEditionCode) + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/rights/delegation/userdelegationcheck?userId={authenticatedUserId}&partyId={reporteePartyId}&serviceCode={serviceCode}&serviceEditionCode={serviceEditionCode}"); + + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri); + string responseContent = await response.Content.ReadAsStringAsync(); + + DelegationCheckResponse delegationCheckResponse = new DelegationCheckResponse(); + + if (response.StatusCode == HttpStatusCode.OK) + { + delegationCheckResponse.RightDelegationCheckResults = JsonSerializer.Deserialize>(responseContent, _serializerOptions); + return delegationCheckResponse; + } + + _logger.LogError("AccessManagement // Altinn2RightsClient // PostDelegationCheck // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + if (response.StatusCode == HttpStatusCode.BadRequest) + { + SblValidationProblemResponse validationError = JsonSerializer.Deserialize(responseContent, _serializerOptions); + foreach (KeyValuePair> modelState in validationError.ModelState) + { + delegationCheckResponse.Errors.Add(modelState.Key, string.Join(" | ", modelState.Value)); + } + + return delegationCheckResponse; + } + + delegationCheckResponse.Errors.Add("SBLBridge", $"Unable to reach Altinn 2 for delegation check of Altinn 2 service. HttpStatusCode: {response.StatusCode}"); + return delegationCheckResponse; + } + + /// + public async Task PostDelegation(int authenticatedUserId, int reporteePartyId, SblRightDelegationRequest delegationRequest) + { + DelegationActionResult delegationResult = new DelegationActionResult(); + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/rights/delegation/userdelegation?authenticatedUserId={authenticatedUserId}&partyId={reporteePartyId}"); + + string token = await _sblTokenProvider.GetAccessToken(); + + StringContent requestBody = new StringContent(JsonSerializer.Serialize(delegationRequest), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _client.PostAsync(token, uriBuilder.Uri.ToString(), requestBody); + string responseContent = await response.Content.ReadAsStringAsync(); + + if (response.StatusCode == HttpStatusCode.OK) + { + delegationResult.Rights = JsonSerializer.Deserialize>(responseContent, _serializerOptions); + return delegationResult; + } + + _logger.LogError("AccessManagement // Altinn2RightsClient // PostDelegation // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + if (response.StatusCode == HttpStatusCode.BadRequest) + { + SblValidationProblemResponse validationError = JsonSerializer.Deserialize(responseContent, _serializerOptions); + foreach (KeyValuePair> modelState in validationError.ModelState) + { + delegationResult.Errors.Add(modelState.Key, string.Join(" | ", modelState.Value)); + } + + return delegationResult; + } + + delegationResult.Errors.Add("SBLBridge", $"Unable to reach Altinn 2 for delegation of Altinn 2 service. HttpStatusCode: {response.StatusCode}"); + return delegationResult; + } + + /// + public async Task ClearReporteeRights(int fromPartyId, int toPartyId, int toUserId = 0, CancellationToken cancellationToken = default) + { + UriBuilder endpoint = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}cache/api/clearreporteerights?reporteePartyId={fromPartyId}&coveredByPartyId={toPartyId}&coveredByUserId={toUserId}"); + return await _client.PutAsync(endpoint.Uri.ToString(), null, cancellationToken); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AltinnRolesClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AltinnRolesClient.cs new file mode 100644 index 00000000..cf21e04e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AltinnRolesClient.cs @@ -0,0 +1,111 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Integration.Configuration; +using Authorization.Platform.Authorization.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients; + +/// +/// Client for getting Altinn roles from AltinnII SBL Bridge +/// +[ExcludeFromCodeCoverage] +public class AltinnRolesClient : IAltinnRolesClient +{ + private readonly SblBridgeSettings _sblBridgeSettings; + private readonly HttpClient _client; + private readonly ILogger _logger; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + /// HttpClient from default httpclientfactory + /// the sbl bridge settings + /// the logger + public AltinnRolesClient(HttpClient httpClient, IOptions sblBridgeSettings, ILogger logger) + { + _sblBridgeSettings = sblBridgeSettings.Value; + _logger = logger; + _client = httpClient; + } + + /// + public async Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + try + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/roles?coveredByUserId={coveredByUserId}&offeredByPartyId={offeredByPartyId}"); + + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri, cancellationToken); + string roleList = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + return JsonSerializer.Deserialize>(roleList, _serializerOptions); + } + + _logger.LogError("AccessManagement // AltinnRolesClient // GetDecisionPointRolesForUser // Unexpected HttpStatusCode: {StatusCode}", response.StatusCode); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AltinnRolesClient // GetDecisionPointRolesForUser // Exception"); + throw; + } + } + + /// + public async Task> GetRolesForDelegation(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + try + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/delegatableroles?coveredByUserId={coveredByUserId}&offeredByPartyId={offeredByPartyId}"); + + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri, cancellationToken); + string roleList = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + return JsonSerializer.Deserialize>(roleList, _serializerOptions); + } + + _logger.LogError("AccessManagement // AltinnRolesClient // GetRolesForDelegation // Unexpected HttpStatusCode: {StatusCode}", response.StatusCode); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AltinnRolesClient // GetRolesForDelegation // Exception"); + throw; + } + } + + /// + public async Task> GetAuthorizedPartiesWithRoles(int userId, CancellationToken cancellationToken = default) + { + try + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/parties?userid={userId}"); + + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri, cancellationToken); + string content = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + List sblAuthorizedParties = JsonSerializer.Deserialize>(content, _serializerOptions); + return sblAuthorizedParties.Select(sblAuthorizedParty => new AuthorizedParty(sblAuthorizedParty)).ToList(); + } + + _logger.LogError("AccessManagement // AltinnRolesClient // GetAuthorizedPartiesWithRoles // Unexpected HttpStatusCode: {StatusCode} Response: {Content}", response.StatusCode, content); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AltinnRolesClient // GetAuthorizedPartiesWithRoles // Exception"); + throw; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AuthenticationClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AuthenticationClient.cs new file mode 100644 index 00000000..afae3706 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/AuthenticationClient.cs @@ -0,0 +1,162 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Platform.Register.Models; +using AltinnCore.Authentication.Utils; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Npgsql.Internal; +using DefaultRight = Altinn.AccessManagement.Core.Models.Authentication.DefaultRight; + +namespace Altinn.AccessManagement.Integration.Clients +{ + /// + /// A client for authentication actions in Altinn Platform. + /// + [ExcludeFromCodeCoverage] + public class AuthenticationClient : IAuthenticationClient + { + private readonly ILogger _logger; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly HttpClient _client; + private readonly PlatformSettings _platformSettings; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter() } }; + + /// + /// Initializes a new instance of the class + /// + /// The current platform settings. + /// the logger + /// The http context accessor + /// A HttpClient provided by the HttpClientFactory. + public AuthenticationClient( + IOptions platformSettings, + ILogger logger, + IHttpContextAccessor httpContextAccessor, + HttpClient httpClient) + { + _logger = logger; + _httpContextAccessor = httpContextAccessor; + _platformSettings = platformSettings.Value; + httpClient.BaseAddress = new Uri(platformSettings.Value.ApiAuthenticationEndpoint); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _client = httpClient; + } + + /// + public async Task RefreshToken(CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"refresh"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + HttpResponseMessage response = await _client.GetAsync(endpointUrl, cancellationToken); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + string refreshedToken = await response.Content.ReadAsStringAsync(cancellationToken); + refreshedToken = refreshedToken.Replace('"', ' ').Trim(); + return refreshedToken; + } + else + { + _logger.LogError("Refreshing JwtToken failed with status code"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AuthenticationClient // Refresh // Exception"); + throw; + } + + return null; + } + + /// + public async Task GetSystemUser(int partyId, string systemUserId, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"systemuser/{partyId}/{systemUserId}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + HttpResponseMessage response = await _client.GetAsync(endpointUrl, cancellationToken); + + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + SystemUser systemUser = JsonSerializer.Deserialize(responseContent, _serializerOptions); + + // The endpoint is not using the partyId input so added a check here to ensure the partyId is correct. + if (int.TryParse(systemUser?.PartyId, out int ownerParsed) && ownerParsed != partyId) + { + return null; + } + else + { + return systemUser; + } + } + else + { + HttpStatusCode statusCode = response.StatusCode; + _logger.LogError("Fetching system user failed with status code: {statusCode}, details: {responseContent}", statusCode, responseContent); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AuthenticationClient // GetSystemUser // Exception"); + throw; + } + + return null; + } + + /// + public async Task> GetDefaultRightsForRegisteredSystem(string systemId, CancellationToken cancellationToken = default) + { + List result = new List(); + + try + { + string endpointUrl = $"systemregister/{systemId}/rights"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + HttpResponseMessage response = await _client.GetAsync(endpointUrl, cancellationToken); + + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + result = JsonSerializer.Deserialize>(responseContent, _serializerOptions); + return result; + } + else + { + HttpStatusCode statusCode = response.StatusCode; + _logger.LogError("Fetching system user default rights failed with status code: {statusCode}, details: {responseContent}", statusCode, responseContent); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // AuthenticationClient // GetSystemUser // Exception"); + throw; + } + + return result; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/PartiesClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/PartiesClient.cs new file mode 100644 index 00000000..18664fa4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/PartiesClient.cs @@ -0,0 +1,254 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Extensions; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Platform.Register.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients; + +/// +/// Proxy implementation for parties +/// +[ExcludeFromCodeCoverage] +public class PartiesClient : IPartiesClient +{ + private readonly SblBridgeSettings _sblBridgeSettings; + private readonly ILogger _logger; + private readonly HttpClient _client; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly PlatformSettings _platformSettings; + private readonly IAccessTokenGenerator _accessTokenGenerator; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + /// HttpClient from default httpclientfactory + /// the sbl bridge settings + /// the logger + /// handler for http context + /// the platform setttings + /// An instance of the AccessTokenGenerator service. + public PartiesClient( + HttpClient httpClient, + IOptions sblBridgeSettings, + ILogger logger, + IHttpContextAccessor httpContextAccessor, + IOptions platformSettings, + IAccessTokenGenerator accessTokenGenerator) + { + _sblBridgeSettings = sblBridgeSettings.Value; + _logger = logger; + httpClient.BaseAddress = new Uri(platformSettings.Value.ApiRegisterEndpoint); + httpClient.DefaultRequestHeaders.Add(platformSettings.Value.SubscriptionKeyHeaderName, platformSettings.Value.SubscriptionKey); + _client = httpClient; + _httpContextAccessor = httpContextAccessor; + _platformSettings = platformSettings.Value; + _accessTokenGenerator = accessTokenGenerator; + _serializerOptions.Converters.Add(new JsonStringEnumConverter()); + } + + /// + public async Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"parties/{partyId}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + + HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, accessToken, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + return JsonSerializer.Deserialize(responseContent, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetPartyAsync // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return null; + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetPartyAsync // Exception"); + throw; + } + } + + /// + public async Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"parties/partylist?fetchSubUnits={includeSubunits}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(partyIds), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _client.PostAsync(token, endpointUrl, requestBody, accessToken, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + return JsonSerializer.Deserialize>(responseContent, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetPartiesAsync // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetPartiesAsync // Exception"); + throw; + } + } + + /// + public async Task> GetPartiesAsync(List partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"parties/partylistbyuuid?fetchSubUnits={includeSubunits}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(partyUuids), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _client.PostAsync(token, endpointUrl, requestBody, accessToken, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + return JsonSerializer.Deserialize>(responseContent, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetPartiesAsync // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetPartiesAsync // Exception"); + throw; + } + } + + /// + public async Task> GetPartiesForUserAsync(int userId, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"{_platformSettings.ApiAuthorizationEndpoint}parties?userId={userId}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + + HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, accessToken, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + return JsonSerializer.Deserialize>(responseContent, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetPartiesForUserAsync // Unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetPartiesForUserAsync // Exception"); + throw; + } + } + + /// + public async Task> GetKeyRoleParties(int userId, CancellationToken cancellationToken = default) + { + try + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/partieswithkeyroleaccess?userid={userId}"); + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri, cancellationToken); + string responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.IsSuccessStatusCode) + { + return JsonSerializer.Deserialize>(responseBody, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetKeyRoleParties // Failed // Unexpected HttpStatusCode: {StatusCode}\n {responseBody}", response.StatusCode, responseBody); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetKeyRoleParties // Failed // Unexpected Exception"); + throw; + } + } + + /// + public async Task> GetMainUnits(MainUnitQuery subunitPartyIds, CancellationToken cancellationToken = default) + { + try + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/partyparents"); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(subunitPartyIds), Encoding.UTF8, "application/json"); + HttpRequestMessage request = new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = uriBuilder.Uri, + Content = requestBody + }; + + HttpResponseMessage response = await _client.SendAsync(request, cancellationToken); + var responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.IsSuccessStatusCode) + { + return JsonSerializer.Deserialize>(responseBody, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // GetMainUnits // Failed // Unexpected HttpStatusCode: {StatusCode}\n {responseBody}", response.StatusCode, responseBody); + return new(); + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // GetMainUnits // Failed // Unexpected Exception"); + throw; + } + } + + /// + public async Task LookupPartyBySSNOrOrgNo(PartyLookup partyLookup, CancellationToken cancellationToken = default) + { + try + { + string endpointUrl = $"parties/lookup"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + var accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "access-management"); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(partyLookup, _serializerOptions), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _client.PostAsync(token, endpointUrl, requestBody, accessToken, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.StatusCode == HttpStatusCode.OK) + { + return JsonSerializer.Deserialize(responseContent, _serializerOptions); + } + + _logger.LogError("AccessManagement // PartiesClient // LookupPartyBySSNOrOrgNo // Unexpected HttpStatusCode: {StatusCode}\n {responseBody}", response.StatusCode, responseContent); + return null; + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // PartiesClient // LookupPartyBySSNOrOrgNo // Exception"); + throw; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ProfileClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ProfileClient.cs new file mode 100644 index 00000000..ca0b4cbf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ProfileClient.cs @@ -0,0 +1,64 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.Platform.Profile.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients +{ + /// + /// A client for retrieving profiles from Altinn Platform. + /// + [ExcludeFromCodeCoverage] + public class ProfileClient : IProfileClient + { + private readonly ILogger _logger; + private readonly PlatformSettings _settings; + private readonly HttpClient _client; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + /// the platform settings + /// the logger + /// A HttpClient provided by the HttpClientFactory. + public ProfileClient( + IOptions platformSettings, + ILogger logger, + HttpClient httpClient) + { + _logger = logger; + _settings = platformSettings.Value; + _client = httpClient; + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _serializerOptions.Converters.Add(new JsonStringEnumConverter()); + } + + /// + public async Task GetUser(UserProfileLookup userProfileLookup, CancellationToken cancellationToken = default) + { + UriBuilder endpoint = new UriBuilder($"{_settings.ApiProfileEndpoint}internal/user/"); + + StringContent requestBody = new StringContent(JsonSerializer.Serialize(userProfileLookup), Encoding.UTF8, "application/json"); + HttpResponseMessage response = await _client.PostAsync(endpoint.Uri, requestBody, cancellationToken); + string responseContent = await response.Content.ReadAsStringAsync(cancellationToken); + + if (!response.IsSuccessStatusCode) + { + _logger.LogError("Getting user profile failed with unexpected HttpStatusCode: {StatusCode}\n {responseContent}", response.StatusCode, responseContent); + return null; + } + + UserProfile userProfile = JsonSerializer.Deserialize(responseContent, _serializerOptions); + + return userProfile; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ResourceRegistryClient.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ResourceRegistryClient.cs new file mode 100644 index 00000000..1a1d9805 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Clients/ResourceRegistryClient.cs @@ -0,0 +1,130 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Integration.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Integration.Clients +{ + /// + /// Client implementation for integration with the Resource Registry + /// + [ExcludeFromCodeCoverage] + public class ResourceRegistryClient : IResourceRegistryClient + { + private readonly HttpClient _httpClient = new(); + private readonly ILogger _logger; + private readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + /// The resource registry config settings + /// Logger instance for this ResourceRegistryClient + public ResourceRegistryClient(IOptions settings, ILogger logger) + { + PlatformSettings platformSettings = settings.Value; + _httpClient.BaseAddress = new Uri(platformSettings.ApiResourceRegistryEndpoint); + _httpClient.Timeout = new TimeSpan(0, 0, 30); + _httpClient.DefaultRequestHeaders.Clear(); + _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _logger = logger; + } + + /// + public async Task GetResource(string resourceId, CancellationToken cancellationToken = default) + { + string endpointUrl = $"resource/{resourceId}"; + + HttpResponseMessage response = await _httpClient.GetAsync(endpointUrl, cancellationToken); + if (response.StatusCode == HttpStatusCode.OK) + { + string content = await response.Content.ReadAsStringAsync(cancellationToken); + return JsonSerializer.Deserialize(content, options); + } + + return null; + } + + /// + public async Task> GetResources(CancellationToken cancellationToken = default) + { + List resources = new(); + + try + { + string endpointUrl = $"resource/search"; + + HttpResponseMessage response = await _httpClient.GetAsync(endpointUrl, cancellationToken); + if (response.StatusCode == HttpStatusCode.OK) + { + string content = await response.Content.ReadAsStringAsync(cancellationToken); + resources = JsonSerializer.Deserialize>(content, options); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // ResourceRegistryClient // SearchResources // Exception"); + throw; + } + + return resources; + } + + /// + public async Task> GetResourceList(CancellationToken cancellationToken = default) + { + List resources = new(); + + try + { + string endpointUrl = $"resource/resourcelist"; + + HttpResponseMessage response = await _httpClient.GetAsync(endpointUrl, cancellationToken); + if (response.StatusCode == HttpStatusCode.OK) + { + string content = await response.Content.ReadAsStringAsync(cancellationToken); + resources = JsonSerializer.Deserialize>(content, options); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "AccessManagement // ResourceRegistryClient // GetResourceList // Exception"); + throw; + } + + return resources; + } + + /// + public async Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default) + { + string endpointUrl = $"resource/bysubjects"; + Dictionary> subjectResources = new Dictionary>(); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(subjects), Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await _httpClient.PostAsync(endpointUrl, requestBody, cancellationToken); + if (response.StatusCode == HttpStatusCode.OK) + { + string content = await response.Content.ReadAsStringAsync(cancellationToken); + PaginatedResult result = JsonSerializer.Deserialize>(content, options); + + if (result != null && result.Items != null) + { + foreach (SubjectResources resultItem in result.Items) + { + subjectResources.Add(resultItem.Subject.Urn, resultItem.Resources); + } + } + } + + return subjectResources; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/PlatformSettings.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/PlatformSettings.cs new file mode 100644 index 00000000..8d70fa29 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/PlatformSettings.cs @@ -0,0 +1,54 @@ +namespace Altinn.AccessManagement.Integration.Configuration +{ +#nullable enable + /// + /// General configuration settings + /// + public class PlatformSettings + { + /// + /// Open Id Connect Well known endpoint + /// + public string? OpenIdWellKnownEndpoint { get; set; } + + /// + /// Name of the cookie for where JWT is stored + /// + public string? JwtCookieName { get; set; } + + /// + /// Gets or sets the profile api endpoint. + /// + public string? ApiProfileEndpoint { get; set; } + + /// + /// Gets or sets the register api endpoint. + /// + public string? ApiRegisterEndpoint { get; set; } + + /// + /// Gets or sets the resource registry api endpoint. + /// + public string? ApiResourceRegistryEndpoint { get; set; } + + /// + /// Gets or sets the subscriptionkey. + /// + public string? SubscriptionKey { get; set; } + + /// + /// Gets or sets the SubscriptionKeyHeaderName + /// + public string? SubscriptionKeyHeaderName { get; set; } + + /// + /// Endpoint for authentication + /// + public string? ApiAuthenticationEndpoint { get; set; } + + /// + /// Altinn Authorization base url + /// + public string? ApiAuthorizationEndpoint { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/SblBridgeSettings.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/SblBridgeSettings.cs new file mode 100644 index 00000000..22095d68 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Configuration/SblBridgeSettings.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Integration.Configuration +{ + /// + /// Configuration settings for integration with the SBL Bridge + /// + public class SblBridgeSettings + { + /// + /// Gets or sets the base api url for the SBL Bridge + /// + public string BaseApiUrl { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/DelegationRequestProxy.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/DelegationRequestProxy.cs new file mode 100644 index 00000000..8f0cc34d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/DelegationRequestProxy.cs @@ -0,0 +1,81 @@ +using System.Text.Json; +using System.Web; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Integration.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Services +{ + /// + /// Proxy implementation for delegation requests + /// + public class DelegationRequestProxy : IDelegationRequestsWrapper + { + private readonly SblBridgeSettings _sblBridgeSettings; + private readonly ILogger _logger; + private readonly HttpClient _client; + + /// + /// Initializes a new instance of the class + /// + /// HttpClient from default httpclientfactory + /// the sbl bridge settings + /// the logger + public DelegationRequestProxy(HttpClient httpClient, IOptions sblBridgeSettings, ILogger logger) + { + _sblBridgeSettings = sblBridgeSettings.Value; + _logger = logger; + _client = httpClient; + } + + /// + public async Task GetDelegationRequestsAsync(string who, string serviceCode, int? serviceEditionCode, RestAuthorizationRequestDirection direction, List status, string continuation) + { + UriBuilder uriBuilder = new UriBuilder($"{_sblBridgeSettings.BaseApiUrl}authorization/api/DelegationRequests"); + var query = HttpUtility.ParseQueryString(uriBuilder.Query); + query["who"] = who; + if (!string.IsNullOrEmpty(serviceCode)) + { + query["serviceCode"] = serviceCode; + } + + if (serviceEditionCode != null) + { + query["serviceEditionCode"] = serviceEditionCode.ToString(); + } + + query["direction"] = direction.ToString(); + + if (status != null) + { + foreach (var statusItem in status) + { + query.Add("status", statusItem.ToString()); + } + } + + if (!string.IsNullOrEmpty(continuation)) + { + query["continuation"] = continuation; + } + + uriBuilder.Query = query.ToString(); + + HttpResponseMessage response = await _client.GetAsync(uriBuilder.Uri); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + return await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + } + else + { + _logger.LogError("Getting delegationg requsts from bridge failed with {StatusCode}", response.StatusCode); + } + + return null; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/EventMapperService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/EventMapperService.cs new file mode 100644 index 00000000..b393bf31 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/EventMapperService.cs @@ -0,0 +1,31 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Integration.Services +{ + /// + public class EventMapperService : IEventMapperService + { + /// + public DelegationChangeEventList MapToDelegationChangeEventList(List delegationChanges) + { + return new DelegationChangeEventList + { + DelegationChangeEvents = delegationChanges.Select(delegationChange => new DelegationChangeEvent + { + EventType = (DelegationChangeEventType)delegationChange.DelegationChangeType, + DelegationChange = new SimpleDelegationChange + { + DelegationChangeId = delegationChange.DelegationChangeId, + AltinnAppId = delegationChange.ResourceId, + OfferedByPartyId = delegationChange.OfferedByPartyId, + CoveredByPartyId = delegationChange.CoveredByPartyId, + CoveredByUserId = delegationChange.CoveredByUserId, + PerformedByUserId = delegationChange.PerformedByUserId, + Created = delegationChange.Created.Value + } + }).ToList() + }; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Extensions/IntegrationDependencyInjectionExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Extensions/IntegrationDependencyInjectionExtensions.cs new file mode 100644 index 00000000..91032560 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Extensions/IntegrationDependencyInjectionExtensions.cs @@ -0,0 +1,39 @@ +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Integration.Clients; +using Altinn.AccessManagement.Integration.Services; +using Altinn.AccessManagement.Integration.Services.Interfaces; +using Altinn.AccessManagement.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +namespace Altinn.AccessManagement.Integration.Extensions; + +/// +/// Extension methods for adding access management services to the dependency injection container. +/// +public static class IntegrationDependencyInjectionExtensions +{ + /// + /// Registers access management integration services with the dependency injection container. + /// + /// The . + /// for further chaining. + public static WebApplicationBuilder AddAccessManagementIntegration(this WebApplicationBuilder builder) + { + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddHttpClient(); + builder.Services.AddSingleton(); + + builder.Services.AddHttpClient(); + builder.Services.AddHttpClient(); + builder.Services.AddHttpClient(); + builder.Services.AddHttpClient(); + builder.Services.AddHttpClient(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + return builder; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IKeyVaultService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IKeyVaultService.cs new file mode 100644 index 00000000..d06764f9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IKeyVaultService.cs @@ -0,0 +1,15 @@ +namespace Altinn.AccessManagement.Integration.Services.Interfaces; + +/// +/// Interface for interacting with key vault +/// +public interface IKeyVaultService +{ + /// + /// Gets the value of a secret from the given key vault. + /// + /// The URI of the key vault to ask for secret. + /// The id of the secret. + /// The secret value. + Task GetCertificateAsync(string vaultUri, string secretId); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IPlatformAuthorizationTokenProvider.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IPlatformAuthorizationTokenProvider.cs new file mode 100644 index 00000000..00066c13 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/Interfaces/IPlatformAuthorizationTokenProvider.cs @@ -0,0 +1,13 @@ +namespace Altinn.AccessManagement.Integration.Services.Interfaces; + +/// +/// Provides a platform authorization access token that can be used by HTTP clients for authorization for SBL Bridge +/// +public interface IPlatformAuthorizationTokenProvider +{ + /// + /// Gets the platform authorization token. + /// + /// An platform authorization token as a printable string + public Task GetAccessToken(); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/KeyVaultService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/KeyVaultService.cs new file mode 100644 index 00000000..e24091d0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/KeyVaultService.cs @@ -0,0 +1,36 @@ +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Integration.Services.Interfaces; +using Azure; +using Azure.Identity; +using Azure.Security.KeyVault.Certificates; +using Azure.Security.KeyVault.Secrets; + +namespace Altinn.AccessManagement.Integration.Services; + +/// +/// Wrapper implementation for a KeyVaultClient. The wrapped client is created with a principal obtained through configuration. +/// +/// This class is excluded from code coverage because it has no logic to be tested. +[ExcludeFromCodeCoverage] +public class KeyVaultService : IKeyVaultService +{ + /// + public async Task GetCertificateAsync(string vaultUri, string secretId) + { + CertificateClient certificateClient = new CertificateClient(new Uri(vaultUri), new DefaultAzureCredential()); + AsyncPageable certificatePropertiesPage = certificateClient.GetPropertiesOfCertificateVersionsAsync(secretId); + await foreach (CertificateProperties certificateProperties in certificatePropertiesPage) + { + if (certificateProperties.Enabled == true && + (certificateProperties.ExpiresOn == null || certificateProperties.ExpiresOn >= DateTime.UtcNow)) + { + SecretClient secretClient = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential()); + + KeyVaultSecret secret = await secretClient.GetSecretAsync(certificateProperties.Name, certificateProperties.Version); + return secret.Value; + } + } + + return null; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/PlatformAuthorizationTokenProvider.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/PlatformAuthorizationTokenProvider.cs new file mode 100644 index 00000000..e37919d3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Integration/Services/PlatformAuthorizationTokenProvider.cs @@ -0,0 +1,70 @@ +using System.Security.Cryptography.X509Certificates; +using Altinn.AccessManagement.Integration.Services.Interfaces; +using Altinn.Common.AccessToken.Configuration; +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Common.Authentication.Configuration; +using Microsoft.Extensions.Options; +using AccessTokenSettings = Altinn.Common.AccessTokenClient.Configuration.AccessTokenSettings; + +namespace Altinn.AccessManagement.Integration.Services; + +/// +public class PlatformAuthorizationTokenProvider : IPlatformAuthorizationTokenProvider +{ + private readonly IKeyVaultService _keyVaultService; + private readonly IAccessTokenGenerator _accessTokenGenerator; + private readonly OidcProviderSettings _oidcProviderSettings; + private readonly AccessTokenSettings _accessTokenSettings; + private readonly KeyVaultSettings _keyVaultSettings; + private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); + private DateTime _cacheTokenUntil = DateTime.MinValue; + private string _accessToken; + + /// + /// Initializes a new instance of the class. + /// + /// The key vault service. + /// The access token generator. + /// The access token settings. + /// The key vault settings. + /// The oidc provider settings. + public PlatformAuthorizationTokenProvider( + IKeyVaultService keyVaultService, + IAccessTokenGenerator accessTokenGenerator, + IOptions accessTokenSettings, + IOptions keyVaultSettings, + IOptions oidcProviderSettings) + { + _keyVaultService = keyVaultService; + _accessTokenGenerator = accessTokenGenerator; + _accessTokenSettings = accessTokenSettings.Value; + _keyVaultSettings = keyVaultSettings.Value; + _oidcProviderSettings = oidcProviderSettings.Value; + } + + /// + public async Task GetAccessToken() + { + await Semaphore.WaitAsync(); + + try + { + if (_accessToken == null || _cacheTokenUntil < DateTime.UtcNow) + { + string certBase64 = await _keyVaultService.GetCertificateAsync(_keyVaultSettings.SecretUri, "JWTCertificate"); + _accessToken = _accessTokenGenerator.GenerateAccessToken( + _oidcProviderSettings["altinn"].Issuer, + "platform.authorization", + new X509Certificate2(Convert.FromBase64String(certBase64), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable)); + + _cacheTokenUntil = DateTime.UtcNow.AddSeconds(_accessTokenSettings.TokenLifetimeInSeconds - 2); // Add some slack to avoid tokens expiring in transit + } + + return _accessToken; + } + finally + { + Semaphore.Release(); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Altinn.AccessManagement.Persistence.csproj b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Altinn.AccessManagement.Persistence.csproj new file mode 100644 index 00000000..35c42179 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Altinn.AccessManagement.Persistence.csproj @@ -0,0 +1,26 @@ + + + + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/AzureStorageConfiguration.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/AzureStorageConfiguration.cs new file mode 100644 index 00000000..d9cf5341 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/AzureStorageConfiguration.cs @@ -0,0 +1,88 @@ +namespace Altinn.AccessManagement.Persistence.Configuration +{ + /// + /// Settings for Azure storage + /// + public class AzureStorageConfiguration + { + /// + /// The storage account name for Metadata + /// + public string MetadataAccountName { get; set; } + + /// + /// The storage account key for Metadata + /// + public string MetadataAccountKey { get; set; } + + /// + /// The name of the storage container in the Metadata storage account + /// + public string MetadataContainer { get; set; } + + /// + /// The url for the blob end point for Metadata + /// + public string MetadataBlobEndpoint { get; set; } + + /// + /// The storage account name for Delegations + /// + public string DelegationsAccountName { get; set; } + + /// + /// The storage account key for Delegations + /// + public string DelegationsAccountKey { get; set; } + + /// + /// The name of the storage container in the Delegations storage account + /// + public string DelegationsContainer { get; set; } + + /// + /// The url for the blob end point for Delegations + /// + public string DelegationsBlobEndpoint { get; set; } + + /// + /// The storage account name for the resource registry + /// + public string ResourceRegistryAccountName { get; set; } + + /// + /// The storage account key for the resource registry + /// + public string ResourceRegistryAccountKey { get; set; } + + /// + /// The name of the storage container in the resource registry storage account + /// + public string ResourceRegistryContainer { get; set; } + + /// + /// The url for the blob end point for the resource registry + /// + public string ResourceRegistryBlobEndpoint { get; set; } + + /// + /// The blob lease timeout value in seconds + /// + public int BlobLeaseTimeout { get; set; } + + /// + /// The endpoint url for the storage account for delegation event queue + /// + public string DelegationEventQueueEndpoint { get; set; } + + /// + /// The storage account name for delegation event queue + /// + public string DelegationEventQueueAccountName { get; set; } + + /// + /// The account key for the storage account for delegation event queue + /// + public string DelegationEventQueueAccountKey { get; set; } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/PostgreSQLSettings.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/PostgreSQLSettings.cs new file mode 100644 index 00000000..f6296188 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/PostgreSQLSettings.cs @@ -0,0 +1,18 @@ +namespace Altinn.AccessManagement.Persistence.Configuration +{ + /// + /// Settings for Postgres database + /// + public class PostgreSQLSettings + { + /// + /// Connection string for the postgres db + /// + public string ConnectionString { get; set; } + + /// + /// Password for app user for the postgres db + /// + public string AuthorizationDbPwd { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/TelemetryConfig.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/TelemetryConfig.cs new file mode 100644 index 00000000..053cfd92 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Configuration/TelemetryConfig.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace Altinn.AccessManagement.Persistence.Configuration +{ + /// + /// Config to be used for Telemetry in Altinn.AccessManagement.Persistence + /// + [ExcludeFromCodeCoverage] + public static class TelemetryConfig + { + /// + /// Used as source for the current project + /// + public static readonly ActivitySource ActivitySource = new("Altinn.AccessManagement.Persistence"); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationChangeEventQueue.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationChangeEventQueue.cs new file mode 100644 index 00000000..c2e39600 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationChangeEventQueue.cs @@ -0,0 +1,57 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Persistence.Configuration; +using Azure.Storage; +using Azure.Storage.Queues; +using Azure.Storage.Queues.Models; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Persistence +{ + /// + [ExcludeFromCodeCoverage] + public class DelegationChangeEventQueue : IDelegationChangeEventQueue + { + private readonly AzureStorageConfiguration _storageConfig; + private readonly IEventMapperService _eventMapperService; + private QueueClient _queueClient; + + /// + /// Initializes a new instance of the class. + /// + /// Mapper service responsible for mapping models + /// Azure storage queue config + public DelegationChangeEventQueue(IEventMapperService eventMapperService, IOptions storageConfig) + { + _eventMapperService = eventMapperService; + _storageConfig = storageConfig.Value; + } + + /// + /// Converts the delegation change to a delegation change event and pushes it to the event queue. + /// Throws exception if something fails + /// + /// The delegation change stored in postgresql + public async Task Push(DelegationChange delegationChange) + { + DelegationChangeEventList dceList = _eventMapperService.MapToDelegationChangeEventList(new List { delegationChange }); + QueueClient queueClient = await GetQueueClient(); + return await queueClient.SendMessageAsync(JsonSerializer.Serialize(dceList)); + } + + private async Task GetQueueClient() + { + if (_queueClient == null) + { + StorageSharedKeyCredential queueCredentials = new StorageSharedKeyCredential(_storageConfig.DelegationEventQueueAccountName, _storageConfig.DelegationEventQueueAccountKey); + _queueClient = new QueueClient(new Uri($"{_storageConfig.DelegationEventQueueEndpoint}/delegationevents"), queueCredentials, new QueueClientOptions { MessageEncoding = QueueMessageEncoding.Base64 }); + await _queueClient.CreateIfNotExistsAsync(); + } + + return _queueClient; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepo.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepo.cs new file mode 100644 index 00000000..c983b0d5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepo.cs @@ -0,0 +1,1602 @@ +using System.Data; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Npgsql; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Persistence +{ + /// + /// Repository implementation for PostgreSQL operations on delegations. + /// + [ExcludeFromCodeCoverage] + public class DelegationMetadataRepo : IDelegationMetadataRepository + { + private readonly NpgsqlDataSource _conn; + private readonly string defaultAppColumns = "delegationChangeId, delegationChangeType, altinnAppId, offeredByPartyId, fromUuid, fromType, coveredByUserId, coveredByPartyId, toUuid, toType, performedByUserId, performedByUuid, performedByType, blobStoragePolicyPath, blobStorageVersionId, created"; + private const string FromUuid = "fromUuid"; + private const string FromType = "fromType"; + private const string ToUuid = "toUuid"; + private const string ToType = "toType"; + private const string InstanceId = "instanceId"; + private const string ResourceId = "resourceId"; + private const string DelegationChangeType = "delegationChangeType"; + + /// + /// Initializes a new instance of the class + /// + /// PostgreSQL datasource connection + public DelegationMetadataRepo(NpgsqlDataSource conn) + { + _conn = conn; + } + + /// + public async Task> GetAllAppDelegationChanges(string altinnAppId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (coveredByUserId == null && coveredByPartyId == null) + { + activity?.StopWithError(new ArgumentException($"Both params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)} cannot be null.")); + throw new ArgumentException($"Both params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)} cannot be null."); + } + + string query = string.Empty; + if (coveredByPartyId != null) + { + query = /*strpsql*/@$" + SELECT {defaultAppColumns} + FROM delegation.delegationChanges + WHERE altinnAppId = @altinnAppId + AND offeredByPartyId = @offeredByPartyId + AND coveredByPartyId = @coveredByPartyId + "; + } + + if (coveredByUserId != null) + { + query = /*strpsql*/@$" + SELECT {defaultAppColumns} + FROM delegation.delegationChanges + WHERE altinnAppId = @altinnAppId + AND offeredByPartyId = @offeredByPartyId + AND coveredByUserId = @coveredByUserId + "; + } + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("altinnAppId", NpgsqlDbType.Text, altinnAppId); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, offeredByPartyId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, coveredByPartyId); + cmd.Parameters.AddWithNullableValue("coveredByUserId", NpgsqlDbType.Integer, coveredByUserId); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetAppDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllCurrentAppDelegationChanges(List offeredByPartyIds, List altinnAppIds, List coveredByPartyIds = null, List coveredByUserIds = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + if (offeredByPartyIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(offeredByPartyIds))); + throw new ArgumentNullException(nameof(offeredByPartyIds)); + } + + if (altinnAppIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(altinnAppIds))); + throw new ArgumentNullException(nameof(altinnAppIds)); + } + + if (coveredByPartyIds == null && coveredByUserIds == null) + { + activity?.StopWithError(new ArgumentException($"Both params: {nameof(coveredByUserIds)}, {nameof(coveredByPartyIds)} cannot be null.")); + throw new ArgumentException($"Both params: {nameof(coveredByUserIds)}, {nameof(coveredByPartyIds)} cannot be null."); + } + + string query = string.Empty; + if (coveredByPartyIds?.Count > 0) + { + query = /*strpsql*/@$" + WITH latestChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE (offeredByPartyId = ANY (@offeredByPartyIds)) + AND (altinnAppId = ANY (@altinnAppIds)) + AND (coveredByPartyId = ANY (@coveredByPartyIds)) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) + SELECT {defaultAppColumns} + FROM delegation.delegationchanges + INNER JOIN latestChanges ON delegationchangeid = latestChanges.latestId + "; + } + else if (coveredByUserIds?.Count > 0) + { + query = /*strpsql*/@$" + WITH latestChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE (offeredByPartyId = ANY (@offeredByPartyIds)) + AND (altinnAppId = ANY (@altinnAppIds)) + AND (coveredByUserId = ANY (@coveredByUserIds)) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) + SELECT {defaultAppColumns} + FROM delegation.delegationchanges + INNER JOIN latestChanges ON delegationchangeid = latestChanges.latestId + "; + } + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + cmd.Parameters.AddWithValue("altinnAppIds", NpgsqlDbType.Array | NpgsqlDbType.Text, altinnAppIds); + cmd.Parameters.AddWithNullableValue("coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + cmd.Parameters.AddWithNullableValue("coveredByUserIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByUserIds); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetAppDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllCurrentAppDelegationChanges(List altinnAppIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + if (altinnAppIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(altinnAppIds))); + throw new ArgumentNullException(nameof(altinnAppIds)); + } + + if (fromPartyIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(fromPartyIds))); + throw new ArgumentNullException(nameof(fromPartyIds)); + } + + if (toUuidType == UuidType.NotSpecified) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(toUuidType)} must be specified.")); + throw new ArgumentException($"Param: {nameof(toUuidType)} must be specified."); + } + + if (toUuid == Guid.Empty) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(toUuid)} must be specified.")); + throw new ArgumentException($"Param: {nameof(toUuid)} must be specified."); + } + + string query = /*strpsql*/@$" + WITH latestChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE offeredByPartyId = ANY (@offeredByPartyIds) + AND altinnAppId = ANY (@altinnAppIds) + AND toType = @toType + AND toUuid = @toUuid + GROUP BY altinnAppId, offeredByPartyId, offeredByPartyId, toType, toUuid + ) + SELECT {defaultAppColumns} + FROM delegation.delegationchanges + INNER JOIN latestChanges ON delegationchangeid = latestChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("altinnAppIds", NpgsqlDbType.Array | NpgsqlDbType.Text, altinnAppIds); + cmd.Parameters.AddWithValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, fromPartyIds); + cmd.Parameters.AddWithValue(ToType, toUuidType); + cmd.Parameters.AddWithValue(ToUuid, NpgsqlDbType.Uuid, toUuid); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetAppDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task GetCurrentDelegationChange(ResourceAttributeMatchType resourceMatchType, string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default) + { + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + return await GetCurrentAppDelegation(resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, toUuid, toUuidType, cancellationToken); + } + + return await GetCurrentResourceRegistryDelegation(resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, toUuid, toUuidType, cancellationToken); + } + + private async Task GetCurrentAppDelegation(string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (string.IsNullOrWhiteSpace(resourceId)) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(resourceId)} cannot be null or whitespace.")); + throw new ArgumentException($"Param: {nameof(resourceId)} cannot be null or whitespace."); + } + + if (offeredByPartyId == 0) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(offeredByPartyId)} cannot be zero.")); + throw new ArgumentException($"Param: {nameof(offeredByPartyId)} cannot be zero."); + } + + if (coveredByPartyId == null && coveredByUserId == null && toUuidType != UuidType.SystemUser) + { + activity?.StopWithError(new ArgumentException($"All params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)}, {nameof(toUuid)} cannot be null.")); + throw new ArgumentException($"All params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)}, {nameof(toUuid)} cannot be null."); + } + + string query = string.Empty; + if (coveredByPartyId != null) + { + query = /*strpsql*/@$" + SELECT {defaultAppColumns} + FROM delegation.delegationChanges + WHERE altinnAppId = @altinnAppId AND offeredByPartyId = @offeredByPartyId + AND coveredByPartyId = @coveredByPartyId + ORDER BY delegationChangeId DESC LIMIT 1 + "; + } + + if (coveredByUserId != null) + { + query = /*strpsql*/@$" + SELECT {defaultAppColumns} + FROM delegation.delegationChanges + WHERE altinnAppId = @altinnAppId AND offeredByPartyId = @offeredByPartyId + AND coveredByUserId = @coveredByUserId + ORDER BY delegationChangeId DESC LIMIT 1 + "; + } + + if (toUuidType == UuidType.SystemUser) + { + query = /*strpsql*/@$" + SELECT {defaultAppColumns} + FROM delegation.delegationChanges + WHERE + altinnAppId = @altinnAppId + AND offeredByPartyId = @offeredByPartyId + AND toUuid = @toUuid + AND toType = @toType + ORDER BY delegationChangeId DESC LIMIT 1 + "; + } + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, offeredByPartyId); + cmd.Parameters.AddWithValue("altinnAppId", NpgsqlDbType.Text, resourceId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, coveredByPartyId); + cmd.Parameters.AddWithNullableValue("coveredByUserId", NpgsqlDbType.Integer, coveredByUserId); + cmd.Parameters.AddWithNullableValue(ToUuid, NpgsqlDbType.Uuid, toUuid); + cmd.Parameters.AddWithValue(ToType, toUuidType); + + await using var reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetAppDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task InsertDelegation(ResourceAttributeMatchType resourceMatchType, DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + return await InsertAppDelegation(delegationChange, cancellationToken); + } + + return await InsertResourceRegistryDelegation(delegationChange, cancellationToken); + } + + /// + /// Fetches all instance delegated to given param + /// + /// list of parties that has received an instance delegation + /// cancellation token + /// + public async Task> GetAllCurrentReceivedInstanceDelegations(List toUuid, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + var query = /* strpsql */ @" + WITH latestChanges AS ( + SELECT + MAX(instancedelegationchangeid) as latestId + FROM + delegation.instancedelegationchanges + WHERE + touuid = ANY(@toUuid) + GROUP BY + touuid, + fromuuid, + resourceid, + instanceid + ) + SELECT + instancedelegationchangeid, + delegationchangetype, + instanceDelegationMode, + resourceid, + instanceid, + fromuuid, + fromtype, + touuid, + totype, + performedby, + performedbytype, + blobstoragepolicypath, + blobstorageversionid, + created + FROM + delegation.instancedelegationchanges + INNER JOIN latestChanges + ON instancedelegationchangeid = latestChanges.latestId + WHERE + delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("toUuid", NpgsqlDbType.Array | NpgsqlDbType.Uuid, toUuid); + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetInstanceDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task GetLastInstanceDelegationChange(InstanceDelegationChangeRequest request, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + SELECT + instancedelegationchangeid + ,delegationchangetype + ,instanceDelegationMode + ,resourceId + ,instanceId + ,fromUuid + ,fromType + ,toUuid + ,toType + ,performedBy + ,performedByType + ,blobStoragePolicyPath + ,blobStorageVersionId + ,created + FROM + delegation.instancedelegationchanges + WHERE + resourceId = @resourceId + AND instanceId = @instanceId + AND instanceDelegationMode = @instanceDelegationMode + AND fromUuid = @fromUuid + AND fromType = @fromType + AND toUuid = @toUuid + AND toType = @toType + ORDER BY + instancedelegationchangeid DESC LIMIT 1; + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue(ResourceId, NpgsqlDbType.Text, request.Resource); + cmd.Parameters.AddWithValue(InstanceId, NpgsqlDbType.Text, request.Instance); + cmd.Parameters.Add(new NpgsqlParameter("instancedelegationmode", request.InstanceDelegationMode)); + cmd.Parameters.AddWithValue(FromUuid, NpgsqlDbType.Uuid, request.FromUuid); + cmd.Parameters.Add(new NpgsqlParameter(FromType, request.FromType)); + cmd.Parameters.AddWithValue(ToUuid, NpgsqlDbType.Uuid, request.ToUuid); + cmd.Parameters.Add(new NpgsqlParameter(ToType, request.ToType)); + + await using var reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetInstanceDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task InsertInstanceDelegation(InstanceDelegationChange instanceDelegationChange, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + INSERT INTO delegation.instancedelegationchanges( + delegationchangetype + ,instanceDelegationMode + ,resourceId + ,instanceid + ,fromUuid + ,fromType + ,toUuid + ,toType + ,performedBy + ,performedByType + ,blobStoragePolicyPath + ,blobStorageVersionId) + VALUES ( + @delegationchangetype + ,@instanceDelegationMode + ,@resourceId + ,@instanceid + ,@fromUuid + ,@fromType + ,@toUuid + ,@toType + ,@performedBy + ,@performedByType + ,@blobStoragePolicyPath + ,@blobStorageVersionId) + RETURNING *; + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.Add(new NpgsqlParameter(DelegationChangeType, instanceDelegationChange.DelegationChangeType)); + cmd.Parameters.Add(new NpgsqlParameter("instancedelegationmode", instanceDelegationChange.InstanceDelegationMode)); + cmd.Parameters.AddWithValue(ResourceId, NpgsqlDbType.Text, instanceDelegationChange.ResourceId); + cmd.Parameters.AddWithValue(InstanceId, NpgsqlDbType.Text, instanceDelegationChange.InstanceId); + cmd.Parameters.AddWithValue(FromUuid, NpgsqlDbType.Uuid, instanceDelegationChange.FromUuid); + cmd.Parameters.Add(new NpgsqlParameter(FromType, instanceDelegationChange.FromUuidType != UuidType.NotSpecified ? instanceDelegationChange.FromUuidType : null)); + cmd.Parameters.AddWithValue(ToUuid, NpgsqlDbType.Uuid, instanceDelegationChange.ToUuid); + cmd.Parameters.Add(new NpgsqlParameter(ToType, instanceDelegationChange.ToUuidType != UuidType.NotSpecified ? instanceDelegationChange.ToUuidType : null)); + cmd.Parameters.AddWithValue("performedBy", NpgsqlDbType.Text, instanceDelegationChange.PerformedBy); + cmd.Parameters.Add(new NpgsqlParameter("performedByType", instanceDelegationChange.PerformedByType != UuidType.NotSpecified ? instanceDelegationChange.PerformedByType : null)); + cmd.Parameters.AddWithValue("blobStoragePolicyPath", NpgsqlDbType.Text, instanceDelegationChange.BlobStoragePolicyPath); + cmd.Parameters.AddWithValue("blobStorageVersionId", NpgsqlDbType.Text, instanceDelegationChange.BlobStorageVersionId); + + using NpgsqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetInstanceDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task InsertMultipleInstanceDelegations(List policyWriteOutputs, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + NpgsqlConnection connection = null; + + try + { + connection = await _conn.OpenConnectionAsync(cancellationToken); + + using (var writer = await connection.BeginBinaryImportAsync("copy delegation.instancedelegationchanges (delegationchangetype, instancedelegationmode, resourceid, instanceid, fromuuid, fromtype, touuid, totype, performedby, performedbytype, blobstoragepolicypath, blobstorageversionid, instancedelegationsource) from STDIN (FORMAT BINARY)", cancellationToken)) + { + foreach (var record in policyWriteOutputs) + { + await writer.StartRowAsync(cancellationToken); + await writer.WriteAsync(record.ChangeType, cancellationToken); + await writer.WriteAsync(record.Rules.InstanceDelegationMode, cancellationToken); + await writer.WriteAsync(record.Rules.ResourceId, NpgsqlDbType.Text, cancellationToken); + await writer.WriteAsync(record.Rules.InstanceId, NpgsqlDbType.Text, cancellationToken); + await writer.WriteAsync(record.Rules.FromUuid, NpgsqlDbType.Uuid, cancellationToken); + await writer.WriteAsync(record.Rules.FromType, cancellationToken); + await writer.WriteAsync(record.Rules.ToUuid, NpgsqlDbType.Uuid, cancellationToken); + await writer.WriteAsync(record.Rules.ToType, cancellationToken); + await writer.WriteAsync(record.Rules.PerformedBy, NpgsqlDbType.Text, cancellationToken); + await writer.WriteAsync(record.Rules.PerformedByType, cancellationToken); + await writer.WriteAsync(record.PolicyPath, NpgsqlDbType.Text, cancellationToken); + await writer.WriteAsync(record.VersionId, NpgsqlDbType.Text, cancellationToken); + await writer.WriteAsync(record.Rules.InstanceDelegationSource, cancellationToken); + } + + await writer.CompleteAsync(cancellationToken); + } + + return true; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return false; + } + finally + { + if (connection != null) + { + await connection.CloseAsync(); + } + } + } + + /// + public async Task> GetAllLatestInstanceDelegationChanges(InstanceDelegationSource source, string resourceID, string instanceID, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + WITH LatestChanges AS( + SELECT + MAX(instancedelegationchangeid) instancedelegationchangeid + FROM + delegation.instancedelegationchanges + WHERE + instancedelegationsource = @source + AND resourceid = @resourceId + AND instanceid = @instanceId + GROUP BY + instancedelegationmode + ,resourceid + ,instanceid + ,fromuuid + ,fromtype + ,touuid + ,totype) + SELECT + dc.instancedelegationchangeid + ,delegationchangetype + ,instancedelegationmode + ,resourceid + ,instanceid + ,fromuuid + ,fromtype + ,touuid + ,totype + ,performedby + ,performedbytype + ,blobstoragepolicypath + ,blobstorageversionid + ,created + FROM + LatestChanges lc + JOIN delegation.instancedelegationchanges dc ON lc.instancedelegationchangeid = dc.instancedelegationchangeid + WHERE + delegationchangetype != 'revoke_last';"; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.Add(new NpgsqlParameter("source", source)); + cmd.Parameters.AddWithValue(ResourceId, NpgsqlDbType.Text, resourceID); + cmd.Parameters.AddWithValue(InstanceId, NpgsqlDbType.Text, instanceID); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetInstanceDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetActiveInstanceDelegations(List resourceIds, Guid from, List to, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + WITH LatestChanges AS( + SELECT + MAX(instancedelegationchangeid) instancedelegationchangeid + FROM + delegation.instancedelegationchanges + WHERE + resourceid = ANY(@resourceIds) + AND fromuuid = @fromUuid + AND touuid = ANY(@toUuids) + GROUP BY + instancedelegationmode + ,resourceid + ,instanceid + ,fromuuid + ,fromtype + ,touuid + ,totype) + SELECT + dc.instancedelegationchangeid + ,delegationchangetype + ,instancedelegationmode + ,resourceid + ,instanceid + ,fromuuid + ,fromtype + ,touuid + ,totype + ,performedby + ,performedbytype + ,blobstoragepolicypath + ,blobstorageversionid + ,created + FROM + LatestChanges lc + JOIN delegation.instancedelegationchanges dc ON lc.instancedelegationchangeid = dc.instancedelegationchangeid + WHERE delegationchangetype != 'revoke_last';"; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("resourceIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceIds); + cmd.Parameters.AddWithValue("fromUuid", NpgsqlDbType.Uuid, from); + cmd.Parameters.AddWithValue("toUuids", NpgsqlDbType.Array | NpgsqlDbType.Uuid, to); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetInstanceDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private static async ValueTask GetInstanceDelegationChange(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + InstanceDelegationChange result = new() + { + InstanceDelegationChangeId = await reader.GetFieldValueAsync("instancedelegationchangeid"), + DelegationChangeType = await reader.GetFieldValueAsync(DelegationChangeType), + InstanceDelegationMode = await reader.GetFieldValueAsync("instancedelegationmode"), + ResourceId = await reader.GetFieldValueAsync(ResourceId), + InstanceId = await reader.GetFieldValueAsync(InstanceId), + FromUuid = await reader.GetFieldValueAsync(FromUuid), + FromUuidType = await reader.GetFieldValueAsync(FromType) ?? UuidType.NotSpecified, + ToUuid = await reader.GetFieldValueAsync(ToUuid), + ToUuidType = await reader.GetFieldValueAsync(ToType) ?? UuidType.NotSpecified, + PerformedBy = await reader.GetFieldValueAsync("performedBy"), + PerformedByType = await reader.GetFieldValueAsync("performedByType") ?? UuidType.NotSpecified, + BlobStoragePolicyPath = await reader.GetFieldValueAsync("blobstoragepolicypath"), + BlobStorageVersionId = await reader.GetFieldValueAsync("blobstorageversionid"), + Created = await reader.GetFieldValueAsync("created") + }; + + return result; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + + private async Task InsertAppDelegation(DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + INSERT INTO delegation.delegationChanges(delegationChangeType, altinnAppId, offeredByPartyId, fromUuid, fromType, coveredByUserId, coveredByPartyId, toUuid, toType, performedByUserId, blobStoragePolicyPath, blobStorageVersionId) + VALUES (@delegationChangeType, @altinnAppId, @offeredByPartyId, @fromUuid, @fromType, @coveredByUserId, @coveredByPartyId, @toUuid, @toType, @performedByUserId, @blobStoragePolicyPath, @blobStorageVersionId) + RETURNING *; + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue(DelegationChangeType, delegationChange.DelegationChangeType); + cmd.Parameters.AddWithValue("altinnAppId", NpgsqlDbType.Text, delegationChange.ResourceId); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, delegationChange.OfferedByPartyId); + cmd.Parameters.AddWithNullableValue(FromUuid, NpgsqlDbType.Uuid, delegationChange.FromUuid); + cmd.Parameters.Add(new NpgsqlParameter(FromType, delegationChange.FromUuidType != UuidType.NotSpecified ? delegationChange.FromUuidType : null)); + cmd.Parameters.AddWithNullableValue("coveredByUserId", NpgsqlDbType.Integer, delegationChange.CoveredByUserId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, delegationChange.CoveredByPartyId); + cmd.Parameters.AddWithNullableValue(ToUuid, NpgsqlDbType.Uuid, delegationChange.ToUuid); + cmd.Parameters.Add(new NpgsqlParameter(ToType, delegationChange.ToUuidType != UuidType.NotSpecified ? delegationChange.ToUuidType : null)); + cmd.Parameters.AddWithValue("performedByUserId", NpgsqlDbType.Integer, delegationChange.PerformedByUserId); + cmd.Parameters.AddWithValue("blobStoragePolicyPath", NpgsqlDbType.Text, delegationChange.BlobStoragePolicyPath); + cmd.Parameters.AddWithValue("blobStorageVersionId", NpgsqlDbType.Text, delegationChange.BlobStorageVersionId); + + using NpgsqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetAppDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task InsertResourceRegistryDelegation(DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + WITH insertRow AS ( + SELECT + @delegationChangeType AS delegationChangeType, + R.resourceId, + R.resourceType, + @offeredByPartyId AS offeredByPartyId, + @fromUuid AS fromUuid, + @fromType AS fromType, + @coveredByUserId AS coveredByUserId, + @coveredByPartyId AS coveredByPartyId, + @toUuid AS toUuid, + @toType AS toType, + @performedByUserId AS performedByUserId, + @performedByPartyId AS performedByPartyId, + @blobStoragePolicyPath AS blobStoragePolicyPath, + @blobStorageVersionId AS blobStorageVersionId, + @delegatedTime AS delegatedTime + FROM accessmanagement.Resource AS R + WHERE resourceRegistryId = @resourceregistryid + ), insertAction AS ( + INSERT INTO delegation.ResourceRegistryDelegationChanges + (delegationChangeType, resourceId_fk, offeredByPartyId, fromUuid, fromType, coveredByUserId, coveredByPartyId, toUuid, toType, performedByUserId, performedByPartyId, blobStoragePolicyPath, blobStorageVersionId, created) + SELECT delegationChangeType, resourceId, offeredByPartyId, fromUuid, fromType, coveredByUserId, coveredByPartyId, toUuid, toType, performedByUserId, performedByPartyId, blobStoragePolicyPath, blobStorageVersionId, delegatedTime + FROM insertRow + RETURNING * + ) + SELECT + ins.resourceRegistryDelegationChangeId, + ins.delegationChangeType, + @resourceregistryid AS resourceregistryid, + insertRow.resourceType, + ins.offeredByPartyId, + ins.fromUuid, + ins.fromType, + ins.coveredByUserId, + ins.coveredByPartyId, + ins.toUuid, + ins.toType, + ins.performedByUserId, + ins.performedByPartyId, + ins.blobStoragePolicyPath, + ins.blobStorageVersionId, + ins.created + FROM insertAction AS ins + JOIN insertRow ON ins.resourceId_fk = insertRow.resourceid; + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue(DelegationChangeType, delegationChange.DelegationChangeType); + cmd.Parameters.AddWithValue("resourceregistryid", delegationChange.ResourceId); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, delegationChange.OfferedByPartyId); + cmd.Parameters.AddWithNullableValue(FromUuid, NpgsqlDbType.Uuid, delegationChange.FromUuid); + cmd.Parameters.Add(new NpgsqlParameter(FromType, delegationChange.FromUuidType != UuidType.NotSpecified ? delegationChange.FromUuidType : null)); + cmd.Parameters.AddWithNullableValue("coveredByUserId", NpgsqlDbType.Integer, delegationChange.CoveredByUserId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, delegationChange.CoveredByPartyId); + cmd.Parameters.AddWithNullableValue(ToUuid, NpgsqlDbType.Uuid, delegationChange.ToUuid); + cmd.Parameters.Add(new NpgsqlParameter(ToType, delegationChange.ToUuidType != UuidType.NotSpecified ? delegationChange.ToUuidType : null)); + cmd.Parameters.AddWithNullableValue("performedByUserId", NpgsqlDbType.Integer, delegationChange.PerformedByUserId); + cmd.Parameters.AddWithNullableValue("performedByPartyId", NpgsqlDbType.Integer, delegationChange.PerformedByPartyId); + cmd.Parameters.AddWithValue("blobStoragePolicyPath", NpgsqlDbType.Text, delegationChange.BlobStoragePolicyPath); + cmd.Parameters.AddWithValue("blobStorageVersionId", NpgsqlDbType.Text, delegationChange.BlobStorageVersionId); + cmd.Parameters.AddWithValue("delegatedTime", delegationChange.Created.HasValue ? delegationChange.Created.Value : DateTime.UtcNow); + + using NpgsqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetResourceRegistryDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task GetCurrentResourceRegistryDelegation(string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (string.IsNullOrWhiteSpace(resourceId)) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(resourceId)} cannot be null or whitespace.")); + throw new ArgumentException($"Param: {nameof(resourceId)} cannot be null or whitespace."); + } + + if (offeredByPartyId == 0) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(offeredByPartyId)} cannot be zero.")); + throw new ArgumentException($"Param: {nameof(offeredByPartyId)} cannot be zero."); + } + + if (coveredByPartyId == null && coveredByUserId == null && toUuidType != UuidType.SystemUser) + { + activity?.StopWithError(new ArgumentException($"All params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)}, {nameof(toUuid)} cannot be null.")); + throw new ArgumentException($"All params: {nameof(coveredByUserId)}, {nameof(coveredByPartyId)}, {nameof(toUuid)} cannot be null."); + } + + string query = string.Empty; + if (coveredByUserId.HasValue) + { + query = /*strpsql*/@" + SELECT rr.resourceRegistryDelegationChangeId, rr.delegationChangeType, res.resourceRegistryId as resourceregistryid, res.resourceType, rr.offeredByPartyId, rr.fromUuid, rr.fromType, rr.coveredByUserId, rr.coveredByPartyId, rr.toUuid, rr.toType, rr.performedByUserId, rr.performedByPartyId, rr.blobStoragePolicyPath, rr.blobStorageVersionId, rr.created + FROM delegation.ResourceRegistryDelegationChanges AS rr + JOIN accessmanagement.Resource AS res ON rr.resourceId_fk = res.resourceid + WHERE res.resourceRegistryId = @resourceRegistryId AND offeredByPartyId = @offeredByPartyId + AND coveredByUserId = @coveredByUserId + ORDER BY resourceRegistryDelegationChangeId DESC LIMIT 1 + "; + } + + if (coveredByPartyId.HasValue) + { + query = /*strpsql*/@" + SELECT rr.resourceRegistryDelegationChangeId, rr.delegationChangeType, res.resourceRegistryId as resourceregistryid, res.resourceType, rr.offeredByPartyId, rr.fromUuid, rr.fromType, rr.coveredByUserId, rr.coveredByPartyId, rr.toUuid, rr.toType, rr.performedByUserId, rr.performedByPartyId, rr.blobStoragePolicyPath, rr.blobStorageVersionId, rr.created + FROM delegation.ResourceRegistryDelegationChanges AS rr + JOIN accessmanagement.Resource AS res ON rr.resourceId_fk = res.resourceid + WHERE res.resourceRegistryId = @resourceRegistryId AND offeredByPartyId = @offeredByPartyId + AND coveredByPartyId = @coveredByPartyId + ORDER BY resourceRegistryDelegationChangeId DESC LIMIT 1 + "; + } + + if (toUuidType == UuidType.SystemUser) + { + query = /*strpsql*/@" + SELECT rr.resourceRegistryDelegationChangeId, rr.delegationChangeType, res.resourceRegistryId as resourceregistryid, res.resourceType, rr.offeredByPartyId, rr.fromUuid, rr.fromType, rr.coveredByUserId, rr.coveredByPartyId, rr.toUuid, rr.toType, rr.performedByUserId, rr.performedByPartyId, rr.blobStoragePolicyPath, rr.blobStorageVersionId, rr.created + FROM + delegation.ResourceRegistryDelegationChanges AS rr + JOIN accessmanagement.Resource AS res ON rr.resourceId_fk = res.resourceid + WHERE + res.resourceRegistryId = @resourceRegistryId + AND offeredByPartyId = @offeredByPartyId + AND toUuid = @toUuid + AND toType = @toType + ORDER BY resourceRegistryDelegationChangeId DESC LIMIT 1 + "; + } + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, offeredByPartyId); + cmd.Parameters.AddWithValue("resourceRegistryId", NpgsqlDbType.Text, resourceId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, coveredByPartyId); + cmd.Parameters.AddWithNullableValue("coveredByUserId", NpgsqlDbType.Integer, coveredByUserId); + cmd.Parameters.AddWithNullableValue(ToUuid, NpgsqlDbType.Uuid, toUuid); + cmd.Parameters.AddWithValue(ToType, toUuidType); + + await using var reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetResourceRegistryDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllCurrentResourceRegistryDelegationChanges(List offeredByPartyIds, List resourceRegistryIds, List coveredByPartyIds = null, int? coveredByUserId = null, CancellationToken cancellationToken = default) + { + if (offeredByPartyIds?.Count == 0) + { + throw new ArgumentNullException(nameof(offeredByPartyIds)); + } + + List delegationChanges = new List(); + + if (coveredByPartyIds?.Count > 0) + { + delegationChanges.AddRange(await GetReceivedResourceRegistryDelegationsForCoveredByPartys(coveredByPartyIds, offeredByPartyIds, resourceRegistryIds, cancellationToken: cancellationToken)); + } + + if (coveredByUserId.HasValue) + { + delegationChanges.AddRange(await GetReceivedResourceRegistryDelegationsForCoveredByUser(coveredByUserId.Value, offeredByPartyIds, resourceRegistryIds, cancellationToken: cancellationToken)); + } + + return delegationChanges; + } + + /// + public async Task> GetAllCurrentResourceRegistryDelegationChanges(List resourceRegistryIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + if (resourceRegistryIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(resourceRegistryIds))); + throw new ArgumentNullException(nameof(resourceRegistryIds)); + } + + if (fromPartyIds?.Count < 1) + { + activity?.StopWithError(new ArgumentNullException(nameof(fromPartyIds))); + throw new ArgumentNullException(nameof(fromPartyIds)); + } + + if (toUuidType == UuidType.NotSpecified) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(toUuidType)} must be specified.")); + throw new ArgumentException($"Param: {nameof(toUuidType)} must be specified."); + } + + if (toUuid == Guid.Empty) + { + activity?.StopWithError(new ArgumentException($"Param: {nameof(toUuid)} must be specified.")); + throw new ArgumentException($"Param: {nameof(toUuid)} must be specified."); + } + + string query = /*strpsql*/@" + WITH resources AS ( + SELECT resourceId, resourceRegistryId, resourceType + FROM accessmanagement.Resource + WHERE resourceType != 'maskinportenschema' + AND resourceRegistryId = ANY (@resourceRegistryIds) + ), + latestResourceChanges AS ( + SELECT MAX(resourceRegistryDelegationChangeId) AS latestId + FROM delegation.ResourceRegistryDelegationChanges + WHERE offeredbypartyid = ANY (@offeredByPartyIds) + AND toType = @toType + AND toUuid = @toUuid + GROUP BY resourceId_fk, offeredByPartyId, toType, toUuid + ) + SELECT + resourceRegistryDelegationChangeId, + null AS delegationChangeId, + delegationChangeType, + resources.resourceRegistryId, + resources.resourceType, + null AS altinnAppId, + offeredByPartyId, + fromuuid, + fromtype, + coveredByUserId, + coveredByPartyId, + touuid, + totype, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.ResourceRegistryDelegationChanges + INNER JOIN resources ON resourceId_fk = resources.resourceid + INNER JOIN latestResourceChanges ON resourceRegistryDelegationChangeId = latestResourceChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceRegistryIds); + cmd.Parameters.AddWithValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, fromPartyIds); + cmd.Parameters.AddWithValue(ToType, toUuidType); + cmd.Parameters.AddWithValue(ToUuid, NpgsqlDbType.Uuid, toUuid); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetResourceRegistryDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetOfferedResourceRegistryDelegations(int offeredByPartyId, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + WITH lastChange AS ( + SELECT MAX(DC.resourceRegistryDelegationChangeId) AS changeId, R.resourceId, R.resourceRegistryId, R.resourceType + FROM accessmanagement.Resource AS R + INNER JOIN delegation.ResourceRegistryDelegationChanges AS DC ON R.resourceid = DC.resourceid_fk + WHERE DC.offeredByPartyId = @offeredByPartyId + "; + + if (resourceRegistryIds != null && resourceRegistryIds.Count > 0) + { + query += /*strpsql*/@" + AND resourceRegistryId = ANY (@resourceRegistryIds)"; + } + + if (resourceTypes != null && resourceTypes.Count > 0) + { + query += /*strpsql*/@" + AND resourceType = ANY (@resourceTypes)"; + } + + query += /*strpsql*/@" + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId, R.resourceId, R.resourceRegistryId, R.resourceType + ) + SELECT + change.resourceRegistryDelegationChangeId, + change.delegationChangeType, + lastChange.resourceRegistryId AS resourceRegistryId, + lastChange.resourceType, + change.offeredByPartyId, + change.fromUuid, + change.fromType, + change.coveredByUserId, + change.coveredByPartyId, + change.toUuid, + change.toType, + change.performedByUserId, + change.performedByPartyId, + change.blobStoragePolicyPath, + change.blobStorageVersionId, + change.created + FROM delegation.ResourceRegistryDelegationChanges AS change + INNER JOIN lastChange ON change.resourceId_fk = lastChange.resourceid AND change.resourceRegistryDelegationChangeId = lastChange.changeId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("offeredByPartyId", NpgsqlDbType.Integer, offeredByPartyId); + cmd.Parameters.AddWithNullableValue("resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceRegistryIds); + cmd.Parameters.AddWithNullableValue("resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceTypes != null ? resourceTypes.Select(t => t.ToString().ToLower()).ToList() : null); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetResourceRegistryDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetReceivedResourceRegistryDelegationsForCoveredByPartys(List coveredByPartyIds, List offeredByPartyIds = null, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + WITH res AS ( + SELECT resourceId, resourceRegistryId, resourceType + FROM accessmanagement.Resource + WHERE 1=1 + "; + + if (resourceRegistryIds != null && resourceRegistryIds.Count > 0) + { + query += /*strpsql*/@" + AND resourceRegistryId = ANY (@resourceRegistryIds)"; + } + + if (resourceTypes != null && resourceTypes.Count > 0) + { + query += /*strpsql*/@" + AND resourceType = ANY (@resourceTypes)"; + } + + query += /*strpsql*/@" + ), + active AS ( + SELECT MAX(resourceRegistryDelegationChangeId) AS changeId + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE coveredByPartyId = ANY (@coveredByPartyIds) + "; + + if (offeredByPartyIds != null && offeredByPartyIds.Count > 0) + { + query += /*strpsql*/@" + AND offeredByPartyId = ANY (@offeredByPartyIds)"; + } + + query += /*strpsql*/@" + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) + SELECT rr.resourceRegistryDelegationChangeId, rr.delegationChangeType, res.resourceRegistryId as resourceRegistryId, res.resourceType, rr.offeredByPartyId, rr.fromUuid, rr.fromType, rr.coveredByUserId, rr.coveredByPartyId, rr.ToUuid, rr.toType, rr.performedByUserId, rr.performedByPartyId, rr.blobStoragePolicyPath, rr.blobStorageVersionId, rr.created + FROM delegation.ResourceRegistryDelegationChanges AS rr + INNER JOIN res ON rr.resourceId_fk = res.resourceid + INNER JOIN active ON rr.resourceRegistryDelegationChangeId = active.changeId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + cmd.Parameters.AddWithNullableValue("resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceRegistryIds); + cmd.Parameters.AddWithNullableValue("resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceTypes != null ? resourceTypes.Select(t => t.ToString().ToLower()).ToList() : null); + cmd.Parameters.AddWithNullableValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetResourceRegistryDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetReceivedResourceRegistryDelegationsForCoveredByUser(int coveredByUserId, List offeredByPartyIds, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (coveredByUserId < 1) + { + throw new ArgumentException("CoveredByUserId is required"); + } + + string query = /*strpsql*/@" + WITH res AS ( + SELECT resourceId, resourceRegistryId, resourceType + FROM accessmanagement.Resource + WHERE 1=1 + "; + + if (resourceRegistryIds != null && resourceRegistryIds.Count > 0) + { + query += /*strpsql*/@" + AND resourceRegistryId = ANY (@resourceRegistryIds)"; + } + + if (resourceTypes != null && resourceTypes.Count > 0) + { + query += /*strpsql*/@" + AND resourceType = ANY (@resourceTypes)"; + } + + query += /*strpsql*/@" + ), + active AS ( + SELECT MAX(resourceRegistryDelegationChangeId) AS changeId + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE coveredByUserId = @coveredByUserId + "; + + if (offeredByPartyIds != null && offeredByPartyIds.Count > 0) + { + query += /*strpsql*/" AND offeredByPartyId = ANY (@offeredByPartyIds)"; + } + + query += /*strpsql*/@" + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) + SELECT rr.resourceRegistryDelegationChangeId, rr.delegationChangeType, res.resourceRegistryId as resourceRegistryId, res.resourceType, rr.offeredByPartyId, rr.fromUuid, rr.fromType, rr.coveredByUserId, rr.coveredByPartyId, rr.toUuid, rr.toType, rr.performedByUserId, rr.performedByPartyId, rr.blobStoragePolicyPath, rr.blobStorageVersionId, rr.created + FROM delegation.ResourceRegistryDelegationChanges AS rr + INNER JOIN res ON rr.resourceId_fk = res.resourceid + INNER JOIN active ON rr.resourceRegistryDelegationChangeId = active.changeId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("coveredByUserId", NpgsqlDbType.Integer, coveredByUserId); + cmd.Parameters.AddWithNullableValue("resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceRegistryIds); + cmd.Parameters.AddWithNullableValue("resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceTypes != null ? resourceTypes.Select(t => t.ToString().ToLower()).ToList() : null); + cmd.Parameters.AddWithNullableValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetResourceRegistryDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetResourceRegistryDelegationChanges(List resourceIds, int offeredByPartyId, int coveredByPartyId, ResourceType resourceType, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + if (resourceIds.Count < 1) + { + throw new ArgumentException("ResourceIds is required"); + } + + string query = /*strpsql*/@" + WITH lastChange AS ( + SELECT + MAX(resourceRegistryDelegationChangeId) AS changeId + ,R.resourceId + ,R.resourceRegistryId + ,R.resourceType + FROM + accessmanagement.Resource AS R + INNER JOIN delegation.ResourceRegistryDelegationChanges AS DC ON DC.resourceId_fk = R.resourceid + WHERE + R.resourceType = @resourceType + AND R.resourceRegistryId = ANY (@resourceRegistryIds) + "; + + if (offeredByPartyId > 0) + { + query += /*strpsql*/@" + AND offeredByPartyId = @offeredByPartyId"; + } + + if (coveredByPartyId > 0) + { + query += /*strpsql*/@" + AND coveredByPartyId = @coveredByPartyId"; + } + + query += /*strpsql*/@" + GROUP BY + DC.resourceId_fk + ,DC.offeredByPartyId + ,DC.coveredByPartyId + ,DC.coveredByUserId + ,R.resourceId + ,R.resourceRegistryId + ,R.resourceType + ) + SELECT + change.resourceRegistryDelegationChangeId + ,change.delegationChangeType + ,lastChange.resourceRegistryId + ,lastChange.resourceType + ,change.offeredByPartyId + ,change.fromUuid + ,change.fromType + ,change.coveredByUserId + ,change.coveredByPartyId + ,change.toUuid + ,change.toType + ,change.performedByUserId + ,change.performedByPartyId + ,change.blobStoragePolicyPath + ,change.blobStorageVersionId + ,change.created + FROM + delegation.ResourceRegistryDelegationChanges AS change + INNER JOIN lastChange ON change.resourceRegistryDelegationChangeId = lastChange.changeid + WHERE + delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceIds); + cmd.Parameters.AddWithValue("resourceType", NpgsqlDbType.Text, resourceType.ToString().ToLower()); + cmd.Parameters.AddWithNullableValue("offeredByPartyId", NpgsqlDbType.Integer, offeredByPartyId); + cmd.Parameters.AddWithNullableValue("coveredByPartyId", NpgsqlDbType.Integer, coveredByPartyId); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetResourceRegistryDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetOfferedDelegations(List offeredByPartyIds, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + const string query = /*strpsql*/@" + WITH resources AS ( + SELECT resourceId, resourceRegistryId, resourceType + FROM accessmanagement.Resource + WHERE resourceType != 'maskinportenschema' + ), + latestResourceChanges AS ( + SELECT MAX(resourceRegistryDelegationChangeId) as latestId + FROM delegation.ResourceRegistryDelegationChanges + WHERE offeredbypartyid = ANY (@offeredByPartyIds) + GROUP BY resourceId_fk, offeredByPartyId, coveredByUserId, coveredByPartyId + ), + latestAppChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE offeredbypartyid = ANY (@offeredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId, coveredByPartyId + ) + SELECT + resourceRegistryDelegationChangeId, + null AS delegationChangeId, + delegationChangeType, + resources.resourceRegistryId, + resources.resourceType, + null AS altinnAppId, + offeredByPartyId, + fromuuid, + fromtype, + coveredByUserId, + coveredByPartyId, + touuid, + totype, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.ResourceRegistryDelegationChanges + INNER JOIN resources ON resourceId_fk = resources.resourceid + INNER JOIN latestResourceChanges ON resourceRegistryDelegationChangeId = latestResourceChanges.latestId + WHERE delegationchangetype != 'revoke_last' + UNION ALL + SELECT + null AS resourceRegistryDelegationChangeId, + delegationChangeId, + delegationChangeType, + null AS resourceRegistryId, + null AS resourceType, + altinnAppId, + offeredByPartyId, + fromuuid, + fromtype, + coveredByUserId, + coveredByPartyId, + touuid, + totype, + performedByUserId, + null AS performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationchanges + INNER JOIN latestAppChanges ON delegationchangeid = latestAppChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllDelegationChangesForAuthorizedParties(List coveredByUserIds, List coveredByPartyIds, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (coveredByUserIds == null && coveredByPartyIds == null) + { + return []; + } + + const string query = /*strpsql*/@" + WITH resources AS ( + SELECT resourceId, resourceRegistryId, resourceType + FROM accessmanagement.Resource + WHERE resourceType != 'maskinportenschema' + ), + latestResourceChanges AS ( + SELECT MAX(resourceRegistryDelegationChangeId) as latestId + FROM delegation.ResourceRegistryDelegationChanges + WHERE coveredByUserId = ANY (@coveredbyuserids) OR coveredByPartyId = ANY (@coveredByPartyIds) + GROUP BY resourceId_fk, offeredByPartyId, coveredByUserId, coveredByPartyId + ), + latestAppChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE coveredByUserId = ANY (@coveredByUserIds) OR coveredByPartyId = ANY (@coveredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId, coveredByPartyId + ) + SELECT + resourceRegistryDelegationChangeId, + null AS delegationChangeId, + delegationChangeType, + resources.resourceRegistryId, + resources.resourceType, + null AS altinnAppId, + offeredByPartyId, + fromUuid, + fromType, + coveredByUserId, + coveredByPartyId, + toUuid, + toType, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.ResourceRegistryDelegationChanges + INNER JOIN resources ON resourceId_fk = resources.resourceid + INNER JOIN latestResourceChanges ON resourceRegistryDelegationChangeId = latestResourceChanges.latestId + WHERE delegationchangetype != 'revoke_last' + UNION ALL + SELECT + null AS resourceRegistryDelegationChangeId, + delegationChangeId, + delegationChangeType, + null AS resourceRegistryId, + null AS resourceType, + altinnAppId, + offeredByPartyId, + fromUuid, + fromType, + coveredByUserId, + coveredByPartyId, + toUuid, + toType, + performedByUserId, + null AS performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationchanges + INNER JOIN latestAppChanges ON delegationchangeid = latestAppChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithNullableValue("coveredByUserIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByUserIds); + cmd.Parameters.AddWithNullableValue("coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + + return await cmd.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private static async ValueTask GetDelegationChange(NpgsqlDataReader reader) + { + return await reader.GetFieldValueAsync("resourceregistrydelegationchangeid") > 0 + ? await GetResourceRegistryDelegationChange(reader) + : await GetAppDelegationChange(reader); + } + + private static async ValueTask GetAppDelegationChange(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + return new DelegationChange + { + DelegationChangeId = await reader.GetFieldValueAsync("delegationchangeid"), + DelegationChangeType = await reader.GetFieldValueAsync(DelegationChangeType), + ResourceId = await reader.GetFieldValueAsync("altinnappid"), + ResourceType = ResourceAttributeMatchType.AltinnAppId.ToString(), + OfferedByPartyId = await reader.GetFieldValueAsync("offeredbypartyid"), + FromUuid = await reader.GetFieldValueAsync(FromUuid), + FromUuidType = await reader.GetFieldValueAsync(FromType) ?? UuidType.NotSpecified, + CoveredByPartyId = await reader.GetFieldValueAsync("coveredbypartyid"), + CoveredByUserId = await reader.GetFieldValueAsync("coveredbyuserid"), + ToUuid = await reader.GetFieldValueAsync(ToUuid), + ToUuidType = await reader.GetFieldValueAsync(ToType) ?? UuidType.NotSpecified, + PerformedByUserId = await reader.GetFieldValueAsync("performedbyuserid"), + BlobStoragePolicyPath = await reader.GetFieldValueAsync("blobstoragepolicypath"), + BlobStorageVersionId = await reader.GetFieldValueAsync("blobstorageversionid"), + Created = await reader.GetFieldValueAsync("created") + }; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + + private static async ValueTask GetResourceRegistryDelegationChange(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + return new DelegationChange + { + ResourceRegistryDelegationChangeId = await reader.GetFieldValueAsync("resourceregistrydelegationchangeid"), + DelegationChangeType = await reader.GetFieldValueAsync(DelegationChangeType), + ResourceId = await reader.GetFieldValueAsync("resourceregistryid"), + ResourceType = await reader.GetFieldValueAsync("resourcetype"), + OfferedByPartyId = await reader.GetFieldValueAsync("offeredbypartyid"), + FromUuid = await reader.GetFieldValueAsync(FromUuid), + FromUuidType = await reader.GetFieldValueAsync(FromType) ?? UuidType.NotSpecified, + CoveredByPartyId = await reader.GetFieldValueAsync("coveredbypartyid"), + CoveredByUserId = await reader.GetFieldValueAsync("coveredbyuserid"), + ToUuid = await reader.GetFieldValueAsync(ToUuid), + ToUuidType = await reader.GetFieldValueAsync(ToType) ?? UuidType.NotSpecified, + PerformedByUserId = await reader.GetFieldValueAsync("performedbyuserid"), + PerformedByPartyId = await reader.GetFieldValueAsync("performedbypartyid"), + BlobStoragePolicyPath = await reader.GetFieldValueAsync("blobstoragepolicypath"), + BlobStorageVersionId = await reader.GetFieldValueAsync("blobstorageversionid"), + Created = await reader.GetFieldValueAsync("created") + }; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepository.cs new file mode 100644 index 00000000..6c5d776d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataRepository.cs @@ -0,0 +1,777 @@ +using System.Data; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Npgsql; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Persistence; + +/// +/// Repository implementation for PostgreSQL operations on delegations. +/// +[ExcludeFromCodeCoverage] +public class DelegationMetadataRepository : IDelegationMetadataRepository +{ + private readonly NpgsqlDataSource _conn; + + // App DelegationChange functions: + private readonly string insertAppDelegationChange = "select * from delegation.insert_delegationchange(@_delegationChangeType, @_altinnAppId, @_offeredByPartyId, @_coveredByUserId, @_coveredByPartyId, @_performedByUserId, @_blobStoragePolicyPath, @_blobStorageVersionId)"; + private readonly string getCurrentAppDelegationChange = "select * from delegation.get_current_change(@_altinnAppId, @_offeredByPartyId, @_coveredByUserId, @_coveredByPartyId)"; + private readonly string getAllAppDelegationChanges = "select * from delegation.get_all_changes(@_altinnAppId, @_offeredByPartyId, @_coveredByUserId, @_coveredByPartyId)"; + private readonly string getAppDelegationChangesForCoveredByPartyIds = "select * from delegation.get_all_current_changes_coveredbypartyids(@_altinnAppIds, @_offeredByPartyIds, @_coveredByPartyIds)"; + private readonly string getAppDelegationChangesForCoveredByUserIds = "select * from delegation.get_all_current_changes_coveredbyuserids(@_altinnAppIds, @_offeredByPartyIds, @_coveredByUserIds)"; + private readonly string getAppDelegationChangesOfferedByPartyIds = "select * from delegation.get_all_current_changes_offeredbypartyid_only(@_altinnAppIds, @_offeredByPartyIds)"; + + // Resource Registry DelegationChange functions: + private readonly string insertResourceRegistryDelegationChange = "select * from delegation.insert_resourceregistrydelegationchange(@_delegationChangeType, @_resourceregistryid, @_offeredByPartyId, @_coveredByUserId, @_coveredByPartyId, @_performedByUserId, @_performedbypartyid, @_blobStoragePolicyPath, @_blobStorageVersionId, @_delegatedTime)"; + private readonly string getCurrentResourceRegistryDelegationChange = "select * from delegation.select_current_resourceregistrydelegationchange(@_resourceRegistryId, @_offeredByPartyId, @_coveredByUserId, @_coveredByPartyId)"; + private readonly string getResourceRegistryDelegationChangesForCoveredByPartyIds = "select * from delegation.select_active_resourceregistrydelegationchanges_coveredbypartys(@_coveredByPartyIds, @_offeredByPartyIds, @_resourceRegistryIds, @_resourceTypes)"; + private readonly string getResourceRegistryDelegationChanges = "select * from delegation.select_active_resourceregistrydelegationchanges(@_coveredByPartyIds, @_offeredByPartyIds, @_resourceRegistryIds, @_resourceTypes)"; + private readonly string getResourceRegistryDelegationChangesForCoveredByUserId = "select * from delegation.select_active_resourceregistrydelegationchanges_coveredbyuser(@_coveredByUserId, @_offeredByPartyIds, @_resourceRegistryIds, @_resourceTypes)"; + private readonly string getResourceRegistryDelegationChangesOfferedByPartyId = "select * from delegation.select_active_resourceregistrydelegationchanges_offeredby(@_offeredByPartyId, @_resourceRegistryIds, @_resourceTypes)"; + + /// + /// Initializes a new instance of the class + /// + /// The database connection + public DelegationMetadataRepository(NpgsqlDataSource conn) + { + _conn = conn; + } + + /// + public async Task InsertDelegation(ResourceAttributeMatchType resourceMatchType, DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + return await InsertAppDelegation(delegationChange, cancellationToken); + } + + return await InsertResourceRegistryDelegation(delegationChange, cancellationToken); + } + + /// + public Task GetLastInstanceDelegationChange(InstanceDelegationChangeRequest request, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task InsertInstanceDelegation(InstanceDelegationChange instanceDelegationChange, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public async Task GetCurrentDelegationChange(ResourceAttributeMatchType resourceMatchType, string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default) + { + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + return await GetCurrentAppDelegation(resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, cancellationToken); + } + + return await GetCurrentResourceRegistryDelegation(resourceId, offeredByPartyId, coveredByPartyId, coveredByUserId, cancellationToken); + } + + /// + public async Task> GetAllAppDelegationChanges(string altinnAppId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + try + { + await using var pgcom = _conn.CreateCommand(getAllAppDelegationChanges); + + pgcom.Parameters.AddWithValue("_altinnAppId", altinnAppId); + pgcom.Parameters.AddWithValue("_offeredByPartyId", offeredByPartyId); + pgcom.Parameters.AddWithValue("_coveredByUserId", coveredByUserId.HasValue ? coveredByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_coveredByPartyId", coveredByPartyId.HasValue ? coveredByPartyId.Value : DBNull.Value); + + List delegationChanges = new List(); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + delegationChanges.Add(await GetAppDelegationChange(reader)); + } + + activity?.StopOk(resultSize: delegationChanges.Count); + return delegationChanges; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllCurrentAppDelegationChanges(List offeredByPartyIds, List altinnAppIds = null, List coveredByPartyIds = null, List coveredByUserIds = null, CancellationToken cancellationToken = default) + { + List delegationChanges = new List(); + CheckIfOfferedbyPartyIdsHasValue(offeredByPartyIds); + + if (coveredByPartyIds == null && coveredByUserIds == null) + { + delegationChanges.AddRange(await GetAllCurrentAppDelegationChangesOfferedByPartyIdOnly(altinnAppIds, offeredByPartyIds, cancellationToken)); + } + else + { + if (coveredByPartyIds?.Count > 0) + { + delegationChanges.AddRange(await GetAllCurrentAppDelegationChangesCoveredByPartyIds(altinnAppIds, offeredByPartyIds, coveredByPartyIds, cancellationToken)); + } + + if (coveredByUserIds?.Count > 0) + { + delegationChanges.AddRange(await GetAllCurrentAppDelegationChangesCoveredByUserIds(altinnAppIds, offeredByPartyIds, coveredByUserIds, cancellationToken)); + } + } + + return delegationChanges; + } + + /// + public Task> GetAllCurrentAppDelegationChanges(List altinnAppIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + // Only implemented as query the new DelegationMetadataRepo + throw new NotImplementedException(); + } + + /// + public async Task> GetAllCurrentResourceRegistryDelegationChanges(List offeredByPartyIds, List resourceRegistryIds, List coveredByPartyIds = null, int? coveredByUserId = null, CancellationToken cancellationToken = default) + { + List delegationChanges = new List(); + CheckIfOfferedbyPartyIdsHasValue(offeredByPartyIds); + + if (coveredByPartyIds?.Count > 0) + { + delegationChanges.AddRange(await GetReceivedResourceRegistryDelegationsForCoveredByPartys(coveredByPartyIds, offeredByPartyIds, resourceRegistryIds, cancellationToken: cancellationToken)); + } + + if (coveredByUserId.HasValue) + { + delegationChanges.AddRange(await GetReceivedResourceRegistryDelegationsForCoveredByUser(coveredByUserId.Value, offeredByPartyIds, resourceRegistryIds, cancellationToken: cancellationToken)); + } + + return delegationChanges; + } + + /// + public Task> GetAllCurrentResourceRegistryDelegationChanges(List resourceRegistryIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + // Only implemented as query the new DelegationMetadataRepo + throw new NotImplementedException(); + } + + /// + public async Task> GetOfferedResourceRegistryDelegations(int offeredByPartyId, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getResourceRegistryDelegationChangesOfferedByPartyId); + + pgcom.Parameters.AddWithValue("_offeredByPartyId", offeredByPartyId); + pgcom.Parameters.AddWithValue("_resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceRegistryIds == null || !resourceRegistryIds.Any()) ? DBNull.Value : resourceRegistryIds); + pgcom.Parameters.AddWithValue("_resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceTypes == null || !resourceTypes.Any()) ? DBNull.Value : resourceTypes.Select(rt => rt.ToString().ToLower()).ToList()); + + List delegatedResources = new List(); + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + delegatedResources.Add(await GetResourceRegistryDelegationChange(reader)); + } + + activity?.StopOk(resultSize: delegatedResources.Count); + return delegatedResources; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetReceivedResourceRegistryDelegationsForCoveredByPartys(List coveredByPartyIds, List offeredByPartyIds = null, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getResourceRegistryDelegationChangesForCoveredByPartyIds); + + pgcom.Parameters.AddWithValue("_coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, (offeredByPartyIds == null || !offeredByPartyIds.Any()) ? DBNull.Value : offeredByPartyIds); + pgcom.Parameters.AddWithValue("_resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceRegistryIds == null || !resourceRegistryIds.Any()) ? DBNull.Value : resourceRegistryIds); + pgcom.Parameters.AddWithValue("_resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceTypes == null || !resourceTypes.Any()) ? DBNull.Value : resourceTypes.Select(rt => rt.ToString().ToLower()).ToList()); + + List receivedDelegations = new List(); + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + receivedDelegations.Add(await GetResourceRegistryDelegationChange(reader)); + } + + activity?.StopOk(resultSize: receivedDelegations.Count); + return receivedDelegations; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetReceivedResourceRegistryDelegationsForCoveredByUser(int coveredByUserId, List offeredByPartyIds, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getResourceRegistryDelegationChangesForCoveredByUserId); + + pgcom.Parameters.AddWithValue("_coveredByUserId", coveredByUserId); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, (offeredByPartyIds == null || !offeredByPartyIds.Any()) ? DBNull.Value : offeredByPartyIds); + pgcom.Parameters.AddWithValue("_resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceRegistryIds == null || !resourceRegistryIds.Any()) ? DBNull.Value : resourceRegistryIds); + pgcom.Parameters.AddWithValue("_resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, (resourceTypes == null || !resourceTypes.Any()) ? DBNull.Value : resourceTypes.Select(rt => rt.ToString().ToLower()).ToList()); + + List receivedDelegations = new List(); + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + receivedDelegations.Add(await GetResourceRegistryDelegationChange(reader)); + } + + activity?.StopOk(resultSize: receivedDelegations.Count); + return receivedDelegations; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetOfferedDelegations(List offeredByPartyIds, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + const string QUERY = /*strpsql*/@" + WITH resources AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE resourceType != 'maskinportenschema' + ), + latestResourceChanges AS ( + SELECT MAX(resourceRegistryDelegationChangeId) as latestId + FROM delegation.ResourceRegistryDelegationChanges + WHERE offeredbypartyid = ANY (@offeredByPartyIds) + GROUP BY resourceId_fk, offeredByPartyId, coveredByUserId, coveredByPartyId + ), + latestAppChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE offeredbypartyid = ANY (@offeredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId, coveredByPartyId + ) + + SELECT + resourceRegistryDelegationChangeId, + null AS delegationChangeId, + delegationChangeType, + resources.resourceRegistryId, + resources.resourceType, + null AS altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.ResourceRegistryDelegationChanges + INNER JOIN resources ON resourceId_fk = resources.resourceid + INNER JOIN latestResourceChanges ON resourceRegistryDelegationChangeId = latestResourceChanges.latestId + WHERE delegationchangetype != 'revoke_last' + + UNION ALL + + SELECT + null AS resourceRegistryDelegationChangeId, + delegationChangeId, + delegationChangeType, + null AS resourceRegistryId, + null AS resourceType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + null AS performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationchanges + INNER JOIN latestAppChanges ON delegationchangeid = latestAppChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var pgcom = _conn.CreateCommand(QUERY); + pgcom.Parameters.AddWithNullableValue("offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + + return await pgcom.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetAllDelegationChangesForAuthorizedParties(List coveredByUserIds, List coveredByPartyIds, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + if (coveredByUserIds == null && coveredByPartyIds == null) + { + return await Task.FromResult(new List()); + } + + const string QUERY = /*strpsql*/@" + WITH resources AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE resourceType != 'maskinportenschema' + ), + latestResourceChanges AS ( + SELECT MAX(resourceRegistryDelegationChangeId) as latestId + FROM delegation.ResourceRegistryDelegationChanges + WHERE + coveredByUserId = ANY (@coveredbyuserids) + OR coveredByPartyId = ANY (@coveredByPartyIds) + GROUP BY resourceId_fk, offeredByPartyId, coveredByUserId, coveredByPartyId + ), + latestAppChanges AS ( + SELECT MAX(delegationChangeId) as latestId + FROM delegation.delegationchanges + WHERE + coveredByUserId = ANY (@coveredByUserIds) + OR coveredByPartyId = ANY (@coveredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId, coveredByPartyId + ) + + SELECT + resourceRegistryDelegationChangeId, + null AS delegationChangeId, + delegationChangeType, + resources.resourceRegistryId, + resources.resourceType, + null AS altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.ResourceRegistryDelegationChanges + INNER JOIN resources ON resourceId_fk = resources.resourceid + INNER JOIN latestResourceChanges ON resourceRegistryDelegationChangeId = latestResourceChanges.latestId + WHERE delegationchangetype != 'revoke_last' + + UNION ALL + + SELECT + null AS resourceRegistryDelegationChangeId, + delegationChangeId, + delegationChangeType, + null AS resourceRegistryId, + null AS resourceType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + null AS performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationchanges + INNER JOIN latestAppChanges ON delegationchangeid = latestAppChanges.latestId + WHERE delegationchangetype != 'revoke_last' + "; + + try + { + await using var pgcom = _conn.CreateCommand(QUERY); + pgcom.Parameters.AddWithNullableValue("coveredByUserIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByUserIds); + pgcom.Parameters.AddWithNullableValue("coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + + return await pgcom.ExecuteEnumerableAsync(cancellationToken) + .SelectAwait(GetDelegationChange) + .ToListAsync(cancellationToken); + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task InsertAppDelegation(DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(insertAppDelegationChange); + + pgcom.Parameters.AddWithValue("_delegationChangeType", delegationChange.DelegationChangeType); + pgcom.Parameters.AddWithValue("_altinnAppId", delegationChange.ResourceId); + pgcom.Parameters.AddWithValue("_offeredByPartyId", delegationChange.OfferedByPartyId); + pgcom.Parameters.AddWithValue("_coveredByUserId", delegationChange.CoveredByUserId.HasValue ? delegationChange.CoveredByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_coveredByPartyId", delegationChange.CoveredByPartyId.HasValue ? delegationChange.CoveredByPartyId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_performedByUserId", delegationChange.PerformedByUserId.HasValue ? delegationChange.PerformedByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_blobStoragePolicyPath", delegationChange.BlobStoragePolicyPath); + pgcom.Parameters.AddWithValue("_blobStorageVersionId", delegationChange.BlobStorageVersionId); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + if (reader.Read()) + { + return await GetAppDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task InsertResourceRegistryDelegation(DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(insertResourceRegistryDelegationChange); + + pgcom.Parameters.AddWithValue("_delegationChangeType", delegationChange.DelegationChangeType); + pgcom.Parameters.AddWithValue("_resourceRegistryId", delegationChange.ResourceId); + pgcom.Parameters.AddWithValue("_offeredByPartyId", delegationChange.OfferedByPartyId); + pgcom.Parameters.AddWithValue("_coveredByUserId", delegationChange.CoveredByUserId.HasValue ? delegationChange.CoveredByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_coveredByPartyId", delegationChange.CoveredByPartyId.HasValue ? delegationChange.CoveredByPartyId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_performedByUserId", delegationChange.PerformedByUserId.HasValue ? delegationChange.PerformedByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_performedByPartyId", delegationChange.PerformedByPartyId.HasValue ? delegationChange.PerformedByPartyId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_blobStoragePolicyPath", delegationChange.BlobStoragePolicyPath); + pgcom.Parameters.AddWithValue("_blobStorageVersionId", delegationChange.BlobStorageVersionId); + pgcom.Parameters.AddWithValue("_delegatedTime", delegationChange.Created.HasValue ? delegationChange.Created.Value : DateTime.UtcNow); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + if (reader.Read()) + { + return await GetResourceRegistryDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task GetCurrentAppDelegation(string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + try + { + await using var pgcom = _conn.CreateCommand(getCurrentAppDelegationChange); + + pgcom.Parameters.AddWithValue("_altinnAppId", resourceId); + pgcom.Parameters.AddWithValue("_offeredByPartyId", offeredByPartyId); + pgcom.Parameters.AddWithValue("_coveredByUserId", coveredByUserId.HasValue ? coveredByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_coveredByPartyId", coveredByPartyId.HasValue ? coveredByPartyId.Value : DBNull.Value); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + if (reader.Read()) + { + return await GetAppDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task GetCurrentResourceRegistryDelegation(string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getCurrentResourceRegistryDelegationChange); + + pgcom.Parameters.AddWithValue("_resourceRegistryId", resourceId); + pgcom.Parameters.AddWithValue("_offeredByPartyId", offeredByPartyId); + pgcom.Parameters.AddWithValue("_coveredByUserId", coveredByUserId.HasValue ? coveredByUserId.Value : DBNull.Value); + pgcom.Parameters.AddWithValue("_coveredByPartyId", coveredByPartyId.HasValue ? coveredByPartyId.Value : DBNull.Value); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + if (reader.Read()) + { + return await GetResourceRegistryDelegationChange(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public async Task> GetResourceRegistryDelegationChanges(List resourceIds, int offeredByPartyId, int coveredByPartyId, ResourceType resourceType, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getResourceRegistryDelegationChanges); + + pgcom.Parameters.AddWithValue("_coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyId == 0 ? DBNull.Value : new List { coveredByPartyId }); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyId == 0 ? DBNull.Value : new List { offeredByPartyId }); + pgcom.Parameters.AddWithValue("_resourceRegistryIds", NpgsqlDbType.Array | NpgsqlDbType.Text, resourceIds); + pgcom.Parameters.AddWithValue("_resourceTypes", NpgsqlDbType.Array | NpgsqlDbType.Text, new List { resourceType.ToString().ToLower() }); + + List receivedDelegations = new List(); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + receivedDelegations.Add(await GetResourceRegistryDelegationChange(reader)); + } + + activity?.StopOk(resultSize: receivedDelegations.Count); + return receivedDelegations; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private static void CheckIfOfferedbyPartyIdsHasValue(List offeredByPartyIds) + { + if (offeredByPartyIds == null) + { + throw new ArgumentNullException(nameof(offeredByPartyIds)); + } + else if (offeredByPartyIds.Count == 0) + { + throw new ArgumentOutOfRangeException(nameof(offeredByPartyIds)); + } + } + + private static async ValueTask GetDelegationChange(NpgsqlDataReader reader) + { + return await reader.GetFieldValueAsync("resourceregistrydelegationchangeid") > 0 + ? await GetResourceRegistryDelegationChange(reader) + : await GetAppDelegationChange(reader); + } + + private static async ValueTask GetAppDelegationChange(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + return new DelegationChange + { + DelegationChangeId = await reader.GetFieldValueAsync("delegationchangeid"), + DelegationChangeType = await reader.GetFieldValueAsync("delegationchangetype"), + ResourceId = await reader.GetFieldValueAsync("altinnappid"), + ResourceType = ResourceAttributeMatchType.AltinnAppId.ToString(), + OfferedByPartyId = await reader.GetFieldValueAsync("offeredbypartyid"), + CoveredByPartyId = await reader.GetFieldValueAsync("coveredbypartyid"), + CoveredByUserId = await reader.GetFieldValueAsync("coveredbyuserid"), + PerformedByUserId = await reader.GetFieldValueAsync("performedbyuserid"), + BlobStoragePolicyPath = await reader.GetFieldValueAsync("blobstoragepolicypath"), + BlobStorageVersionId = await reader.GetFieldValueAsync("blobstorageversionid"), + Created = await reader.GetFieldValueAsync("created") + }; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + + private static async ValueTask GetResourceRegistryDelegationChange(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + return new DelegationChange + { + ResourceRegistryDelegationChangeId = await reader.GetFieldValueAsync("resourceregistrydelegationchangeid"), + DelegationChangeType = await reader.GetFieldValueAsync("delegationchangetype"), + ResourceId = await reader.GetFieldValueAsync("resourceregistryid"), + ResourceType = await reader.GetFieldValueAsync("resourcetype"), + OfferedByPartyId = await reader.GetFieldValueAsync("offeredbypartyid"), + CoveredByPartyId = await reader.GetFieldValueAsync("coveredbypartyid"), + CoveredByUserId = await reader.GetFieldValueAsync("coveredbyuserid"), + PerformedByUserId = await reader.GetFieldValueAsync("performedbyuserid"), + PerformedByPartyId = await reader.GetFieldValueAsync("performedbypartyid"), + BlobStoragePolicyPath = await reader.GetFieldValueAsync("blobstoragepolicypath"), + BlobStorageVersionId = await reader.GetFieldValueAsync("blobstorageversionid"), + Created = await reader.GetFieldValueAsync("created") + }; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + + private async Task> GetAllCurrentAppDelegationChangesCoveredByPartyIds(List altinnAppIds = null, List offeredByPartyIds = null, List coveredByPartyIds = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getAppDelegationChangesForCoveredByPartyIds); + + pgcom.Parameters.AddWithValue("_altinnAppIds", NpgsqlDbType.Array | NpgsqlDbType.Text, altinnAppIds?.Count > 0 ? altinnAppIds : DBNull.Value); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + pgcom.Parameters.AddWithValue("_coveredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByPartyIds); + + List delegationChanges = new List(); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + delegationChanges.Add(await GetAppDelegationChange(reader)); + } + + activity?.StopOk(resultSize: delegationChanges.Count); + return delegationChanges; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task> GetAllCurrentAppDelegationChangesCoveredByUserIds(List altinnAppIds = null, List offeredByPartyIds = null, List coveredByUserIds = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getAppDelegationChangesForCoveredByUserIds); + + pgcom.Parameters.AddWithValue("_altinnAppIds", NpgsqlDbType.Array | NpgsqlDbType.Text, altinnAppIds?.Count > 0 ? altinnAppIds : DBNull.Value); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + pgcom.Parameters.AddWithValue("_coveredByUserIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, coveredByUserIds); + + List delegationChanges = new List(); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + delegationChanges.Add(await GetAppDelegationChange(reader)); + } + + activity?.StopOk(resultSize: delegationChanges.Count); + return delegationChanges; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private async Task> GetAllCurrentAppDelegationChangesOfferedByPartyIdOnly(List altinnAppIds = null, List offeredByPartyIds = null, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using var pgcom = _conn.CreateCommand(getAppDelegationChangesOfferedByPartyIds); + + pgcom.Parameters.AddWithValue("_altinnAppIds", NpgsqlDbType.Array | NpgsqlDbType.Text, altinnAppIds?.Count > 0 ? altinnAppIds : DBNull.Value); + pgcom.Parameters.AddWithValue("_offeredByPartyIds", NpgsqlDbType.Array | NpgsqlDbType.Integer, offeredByPartyIds); + + List delegationChanges = new List(); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + while (reader.Read()) + { + delegationChanges.Add(await GetAppDelegationChange(reader)); + } + + activity?.StopOk(resultSize: delegationChanges.Count); + return delegationChanges; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + /// + public Task> GetAllLatestInstanceDelegationChanges(InstanceDelegationSource source, string resourceID, string instanceID, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task> GetActiveInstanceDelegations(List resourceIds, Guid from, List to, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task> GetAllCurrentReceivedInstanceDelegations(List toUuid, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task InsertMultipleInstanceDelegations(List policyWriteOutputs, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/ActivityExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/ActivityExtensions.cs new file mode 100644 index 00000000..dec1bb72 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/ActivityExtensions.cs @@ -0,0 +1,72 @@ +using System.Collections; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Npgsql; +using OpenTelemetry.Trace; + +namespace Altinn.AccessManagement.Persistence.Extensions; +#nullable enable +/// +/// Extension for Activity used in Altinn.AccessManagement +/// +[ExcludeFromCodeCoverage] +public static class ActivityExtensions +{ + /// + /// Sets status and records exception + /// + /// Current activity + /// Exception to record + /// Optional description/message for error + public static void StopWithError(this Activity? activity, Exception ex, string? statusDescription = null) + { + if (activity?.Recorded ?? false) + { + activity.RecordException(ex); + activity.SetStatus(ActivityStatusCode.Error, statusDescription); + } + } + + /// + /// Sets status and records event + /// + /// Current activity + /// ActivityEvent to record + /// Information to record + /// Optional status description (Default: event.Name) + public static void StopWithError(this Activity? activity, ActivityEvent evnt, Dictionary? tags = null, string? statusDescription = null) + { + if (activity?.Recorded ?? false) + { + if (tags != null) + { + foreach (var tag in tags) + { + activity.AddTag(tag.Key, tag.Value); + } + } + + activity.AddEvent(evnt); + activity.SetStatus(ActivityStatusCode.Error, statusDescription ?? evnt.Name); + } + } + + /// + /// Sets status and records exception + /// + /// Current activity + /// Optional description/message for error + /// Optional metric of resultsize + public static void StopOk(this Activity? activity, string? statusDescription = null, int? resultSize = null) + { + if (activity?.Recorded ?? false) + { + if (resultSize != null) + { + activity.SetTag("ResultSize", resultSize.Value); + } + + activity.SetStatus(ActivityStatusCode.Ok, statusDescription); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/NpgsqlExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/NpgsqlExtensions.cs new file mode 100644 index 00000000..6e6b0a15 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/NpgsqlExtensions.cs @@ -0,0 +1,204 @@ +#nullable enable + +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using Npgsql; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Persistence.Extensions; + +/// +/// Helper extensions for Npgsql. +/// +[ExcludeFromCodeCoverage] +internal static class NpgsqlExtensions +{ + /// + /// Create a with the command text set. + /// + /// The . + /// The command text as a string. + /// A . + public static NpgsqlCommand CreateCommand(this NpgsqlConnection conn, string sql) + { + var cmd = conn.CreateCommand(); + cmd.CommandText = sql; + return cmd; + } + + /// + /// Executes a command against the database, returning a + /// that can be easily mapped over. + /// + /// The . + /// The . + /// + public static async IAsyncEnumerable ExecuteEnumerableAsync( + this NpgsqlCommand cmd, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + await using var reader = await cmd.ExecuteReaderAsync(cancellationToken); + + while (await reader.ReadAsync(cancellationToken)) + { + yield return reader; + } + } + + /// + /// Adds a to the given the parameter name and the data type + /// and value. + /// + /// The to add the parameter to. + /// The name of the parameter. + /// One of the values. + /// The parameter value. If this is , is used instead. + /// The index of the new object. + public static NpgsqlParameter AddWithNullableValue( + this NpgsqlParameterCollection parameters, + string parameterName, + NpgsqlDbType parameterType, + object? value) + => parameters.Add(parameterName, parameterType).SetNullableValue(value); + + /// + /// Sets the value of the to the given value. + /// + /// The + /// The new value + /// + public static NpgsqlParameter SetValue( + this NpgsqlParameter parameter, + object value) + { + parameter.Value = value; + + return parameter; + } + + /// + /// Sets the value of the to the given value, converting + /// to . + /// + /// The + /// The new value + /// + public static NpgsqlParameter SetNullableValue( + this NpgsqlParameter parameter, + object? value) + { + if (value is not null) + { + parameter.Value = value; + } + else + { + parameter.Value = DBNull.Value; + } + + return parameter; + } + + /// + /// Sets the value of the to the given value, converting + /// to . + /// + /// The array item type + /// The + /// The new value + /// + public static NpgsqlParameter SetOptionalImmutableArrayValue( + this NpgsqlParameter> parameter, + ImmutableArray value) + { + if (!value.IsDefault) + { + parameter.TypedValue = value; + } + else + { + parameter.TypedValue = null; + } + + return parameter; + } + + /// + /// Gets the value of the specified column as an instance of or + /// if the value is . + /// + /// The + /// The column ordinal + /// + public static string? GetStringOrNull( + this NpgsqlDataReader reader, + int ordinal) + => reader.IsDBNull(ordinal) ? null : reader.GetString(ordinal); + + /// + /// Gets the value of the specified column as an instance of or + /// if the value is . + /// + /// The + /// The column name + /// The value of the specified column. + public static string? GetStringOrNull( + this NpgsqlDataReader reader, + string name) + => reader.GetStringOrNull(reader.GetOrdinal(name)); + + /// + /// Adds a to the given the specified parameter name and + /// data type. + /// + /// The to add the parameter to. + /// The name of the . + /// One of the NpgsqlDbType values. + /// The parameter that was added. + public static NpgsqlParameter Add( + this NpgsqlParameterCollection parameters, + string parameterName, + NpgsqlDbType parameterType) + { + var parameter = new NpgsqlParameter(parameterName, parameterType); + parameters.Add(parameter); + return parameter; + } + + /// + /// Reads a column as a immutable array of values. + /// + /// The element type. + /// The reader. + /// The column index. + /// The async cancellation token. + /// The column data + public static async ValueTask> GetFieldValueArrayAsync( + this NpgsqlDataReader reader, + int ordinal, + CancellationToken cancellationToken) + { + if (await reader.IsDBNullAsync(ordinal, cancellationToken)) + { + return default; + } + + var list = await reader.GetFieldValueAsync>(ordinal, cancellationToken); + return list.ToImmutableArray(); + } + + /// + /// Reads a column as a immutable array of values. + /// + /// The element type. + /// The reader. + /// The column name. + /// The async cancellation token. + /// The column data + public static async ValueTask> GetFieldValueArrayAsync( + this NpgsqlDataReader reader, + string name, + CancellationToken cancellationToken) + => await reader.GetFieldValueArrayAsync(reader.GetOrdinal(name), cancellationToken); +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/PersistenceDependencyInjectionExtensions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/PersistenceDependencyInjectionExtensions.cs new file mode 100644 index 00000000..2c48f04f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Extensions/PersistenceDependencyInjectionExtensions.cs @@ -0,0 +1,151 @@ +using System.Reflection; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Policy; +using Altinn.Authorization.ServiceDefaults.Npgsql.Yuniql; +using Azure.Core; +using Azure.Storage; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Npgsql; + +namespace Altinn.AccessManagement.Persistence.Extensions; + +/// +/// Extension methods for adding access management services to the dependency injection container. +/// +public static class PersistenceDependencyInjectionExtensions +{ + /// + /// Registers access management persistence services with the dependency injection container. + /// + /// The . + /// for further chaining. + public static WebApplicationBuilder AddAccessManagementPersistence(this WebApplicationBuilder builder) + { + if (builder.Services.Any(s => s.ServiceType == typeof(Marker))) + { + return builder; + } + + builder.Services.AddSingleton(); + + builder.Services.AddSingleton(); + + if (builder.Configuration.GetSection("FeatureManagement").GetValue("UseNewQueryRepo")) + { + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + } + else + { + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + } + + builder.AddDatabase(); + builder.Services.AddDelegationPolicyRepository(builder.Configuration); + + return builder; + } + + /// + /// Registers a with the dependency injection container. + /// + /// The . + /// The . + private static IServiceCollection AddDelegationPolicyRepository(this IServiceCollection services, IConfiguration configuration) + { + var config = new AzureStorageConfiguration(); + + configuration + .GetRequiredSection(nameof(AzureStorageConfiguration)) + .Bind(config); + + services.AddDelegationPolicyRepository(options => + { + options.AddRange([ + new(PolicyAccountType.Delegations, config.DelegationsAccountName, config.DelegationsContainer, config.DelegationsBlobEndpoint, config.DelegationsAccountKey, config.BlobLeaseTimeout), + new(PolicyAccountType.Metadata, config.MetadataAccountName, config.MetadataContainer, config.MetadataBlobEndpoint, config.MetadataAccountKey, config.BlobLeaseTimeout), + new(PolicyAccountType.ResourceRegister, config.ResourceRegistryAccountName, config.ResourceRegistryContainer, config.ResourceRegistryBlobEndpoint, config.ResourceRegistryAccountKey, config.BlobLeaseTimeout), + ]); + }); + + return services; + } + + /// + /// Registers a with the dependency injection container. + /// + /// The . + /// options for configuring blob service + /// for further chaining. + private static IServiceCollection AddDelegationPolicyRepository(this IServiceCollection services, Action> configureOptions) + { + var options = new List(); + configureOptions(options); + services.AddAzureClients(builder => + { + foreach (var config in options) + { + services.AddOptions(config.Account.ToString()) + .Configure(policy => + { + policy.Account = config.Account; + policy.AccountName = config.AccountName; + policy.Container = config.Container; + policy.Key = config.Key; + policy.Uri = config.Uri; + policy.LeaseAcquireTimeout = config.LeaseAcquireTimeout; + }) + .Validate(policy => !string.IsNullOrEmpty(policy.AccountName), $"{nameof(PolicyOptions.AccountName)} cannot be null or empty for account type {config.Account}") + .Validate(policy => !string.IsNullOrEmpty(policy.Container), $"{nameof(PolicyOptions.Container)} cannot be null for account type {config.Account}") + .Validate(policy => !string.IsNullOrEmpty(policy.Key), $"{nameof(PolicyOptions.Key)} cannot be null or empty for account type {config.Account} ") + .Validate(policy => Uri.IsWellFormedUriString(policy.Uri, UriKind.Absolute), $"{nameof(PolicyOptions.Uri)} cannot be null for account type {config.Account}"); + + builder.AddBlobServiceClient(new Uri(config.Uri), new StorageSharedKeyCredential(config.AccountName, config.Key)) + .WithName(config.Account.ToString()) + .ConfigureOptions(options => + { + options.Retry.Mode = RetryMode.Exponential; + options.Retry.MaxRetries = 5; + options.Retry.MaxDelay = TimeSpan.FromSeconds(3); + }); + } + }); + + services.TryAddSingleton(); + + return services; + } + + private static IHostApplicationBuilder AddDatabase(this IHostApplicationBuilder builder) + { + var fs = new ManifestEmbeddedFileProvider(typeof(PersistenceDependencyInjectionExtensions).Assembly, "Migration"); + + builder.AddAltinnPostgresDataSource() + .MapEnum("delegation.delegationchangetype") + .MapEnum("delegation.uuidtype") + .MapEnum("delegation.instancedelegationmode") + .MapEnum("delegation.instancedelegationsource") + .AddYuniqlMigrations(cfg => + { + cfg.Workspace = "/"; + cfg.WorkspaceFileProvider = fs; + }); + + return builder; + } + + private sealed record Marker; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_draft/README.md b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_draft/README.md new file mode 100644 index 00000000..e2c724fb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_draft/README.md @@ -0,0 +1,2 @@ +# The `_draft` directory +Scripts in progress. Scripts that you are currently working and have not moved to specific version directory yet. Executed every time after the latest version. \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_erase/README.md b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_erase/README.md new file mode 100644 index 00000000..9a2a5b3f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_erase/README.md @@ -0,0 +1,2 @@ +# The `_erase` directory +Database cleanup scripts. Executed once only when you do `yuniql erase`. \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_init/README.md b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_init/README.md new file mode 100644 index 00000000..567e2f84 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_init/README.md @@ -0,0 +1,2 @@ +# The `_init` directory +Initialization scripts. Executed once. This is called the first time you do `yuniql run`. \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_post/README.md b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_post/README.md new file mode 100644 index 00000000..30285746 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_post/README.md @@ -0,0 +1,2 @@ +# The `_post` directory +Post migration scripts. Executed every time and always the last batch to run. \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_pre/README.md b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_pre/README.md new file mode 100644 index 00000000..c35c1c4b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/_pre/README.md @@ -0,0 +1,2 @@ +# The `_pre` directory +Pre migration scripts. Executed every time before any version. diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/01-setup-schemas.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/01-setup-schemas.sql new file mode 100644 index 00000000..fdec6044 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/01-setup-schemas.sql @@ -0,0 +1,2 @@ +-- Schema: delegation +CREATE SCHEMA IF NOT EXISTS delegation; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/02-setup-tables.sql new file mode 100644 index 00000000..488e3fcf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/02-setup-tables.sql @@ -0,0 +1,39 @@ +-- Table: delegation.delegationChanges +CREATE TABLE IF NOT EXISTS delegation.delegationchanges +( + delegationChangeId bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + altinnAppId character varying COLLATE pg_catalog."default" NOT NULL, + offeredByPartyId integer NOT NULL, + coveredByPartyId integer, + coveredByUserId integer, + performedByUserId integer NOT NULL, + blobStoragePolicyPath character varying COLLATE pg_catalog."default" NOT NULL, + blobStorageVersionId character varying COLLATE pg_catalog."default", + isDeleted bool default False, + created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +) +TABLESPACE pg_default; + +-- Index: idx_altinnappid +CREATE INDEX IF NOT EXISTS idx_altinnappid + ON delegation.delegationChanges USING btree + (altinnappid COLLATE pg_catalog."default" ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_offeredby +CREATE INDEX IF NOT EXISTS idx_offeredby + ON delegation.delegationChanges USING btree + (offeredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_coveredbyuser +CREATE INDEX IF NOT EXISTS idx_coveredbyuser + ON delegation.delegationChanges USING btree + (coveredbyuserid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_coveredbyparty +CREATE INDEX IF NOT EXISTS idx_coveredbyparty + ON delegation.delegationChanges USING btree + (coveredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/03-setup-grants.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/03-setup-grants.sql new file mode 100644 index 00000000..0a911641 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/03-setup-grants.sql @@ -0,0 +1,3 @@ +GRANT USAGE ON SCHEMA delegation TO platform_authorization; +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA delegation TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA delegation TO platform_authorization; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/04-setup-procedures.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/04-setup-procedures.sql new file mode 100644 index 00000000..a0d3bbf0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.00/04-setup-procedures.sql @@ -0,0 +1,98 @@ +-- Procecure: insert_change +CREATE OR REPLACE PROCEDURE delegation.insert_change( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer, + _performedByUserId integer, + _blobStoragePolicyPath character varying, + _blobStorageVersionId character varying, + _isDeleted bool, + inout _delegationChangeId bigint) +LANGUAGE 'plpgsql' +AS $BODY$ +BEGIN +INSERT INTO delegation.delegationChanges ( + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + isDeleted +) +VALUES ( + _altinnAppId, + _offeredByPartyId, + _coveredByUserId, + _coveredByPartyId, + _performedByUserId, + _blobStoragePolicyPath, + _blobStorageVersionId, + _isDeleted +) RETURNING delegationChangeId INTO _delegationChangeId; + +END; +$BODY$; + + +-- Function: get_current_change +CREATE OR REPLACE FUNCTION delegation.get_current_change( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer +) +RETURNS SETOF delegation.delegationChanges AS +$BODY$ + SELECT + delegationChangeId, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + isDeleted, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) + ORDER BY delegationChangeId DESC LIMIT 1 +$BODY$ +LANGUAGE sql; + + +-- Function: get_all_changes +CREATE OR REPLACE FUNCTION delegation.get_all_changes( + IN _altinnAppId character varying, + IN _offeredByPartyId integer, + IN _coveredByUserId integer, + IN _coveredByPartyId integer +) +RETURNS SETOF delegation.delegationChanges AS +$BODY$ + SELECT + delegationChangeId, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + isDeleted, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) +$BODY$ +LANGUAGE sql; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.01/02-setup-procedures.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.01/02-setup-procedures.sql new file mode 100644 index 00000000..5d1426ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.01/02-setup-procedures.sql @@ -0,0 +1,34 @@ +-- Function: get_all_current_changes +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbypartyids integer[], + _coveredbyuserids integer[]) + RETURNS SETOF delegation.delegationchanges + LANGUAGE 'sql' +AS $BODY$ +SELECT +delegationchangeid, +altinnappid, +offeredbypartyid, +coveredbypartyid, +coveredbyuserid, +performedbyuserid, +blobstoragepolicypath, +blobstorageversionid, +isdeleted, +created +FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (_offeredbypartyids IS NULL OR offeredByPartyId = ANY (_offeredByPartyIds)) + AND (_coveredbypartyids IS NULL OR (coveredByPartyId IS NULL OR coveredByPartyId = ANY (_coveredByPartyIds))) + AND (_coveredbyuserids IS NULL OR (coveredByUserId IS NULL OR coveredByUserId = ANY (_coveredByUserIds))) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.02/01-configure-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.02/01-configure-functions.sql new file mode 100644 index 00000000..0f5783a8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.02/01-configure-functions.sql @@ -0,0 +1,9 @@ +ALTER FUNCTION delegation.get_all_current_changes + STABLE PARALLEL SAFE; + +ALTER FUNCTION delegation.get_all_changes + STABLE PARALLEL SAFE; + +ALTER FUNCTION delegation.get_current_change + STABLE PARALLEL SAFE + ROWS 1; -- This function always return a single row, so hint this to the optimizer diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.03/02-setup-procedures.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.03/02-setup-procedures.sql new file mode 100644 index 00000000..9f4acdf1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.03/02-setup-procedures.sql @@ -0,0 +1,105 @@ +-- Function: delegation.get_all_current_changes + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_offeredbypartyid_only( + _altinnappids character varying[], + _offeredbypartyids integer[]) + RETURNS SETOF delegation.delegationchanges + LANGUAGE 'sql' + STABLE PARALLEL SAFE + +AS $BODY$ +SELECT +delegationchangeid, +altinnappid, +offeredbypartyid, +coveredbypartyid, +coveredbyuserid, +performedbyuserid, +blobstoragepolicypath, +blobstorageversionid, +isdeleted, +created +FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + +-- Function: delegation.get_all_current_changes_coveredbypartyids + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbypartyids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbypartyids integer[]) + RETURNS SETOF delegation.delegationchanges + LANGUAGE 'sql' + STABLE PARALLEL SAFE + +AS $BODY$ +SELECT +delegationchangeid, +altinnappid, +offeredbypartyid, +coveredbypartyid, +coveredbyuserid, +performedbyuserid, +blobstoragepolicypath, +blobstorageversionid, +isdeleted, +created +FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByPartyId = ANY (_coveredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + +-- Function: delegation.get_all_current_changes_coveredbyuserids + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbyuserids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbyuserids integer[]) + RETURNS SETOF delegation.delegationchanges + LANGUAGE 'sql' + STABLE PARALLEL SAFE + +AS $BODY$ +SELECT +delegationchangeid, +altinnappid, +offeredbypartyid, +coveredbypartyid, +coveredbyuserid, +performedbyuserid, +blobstoragepolicypath, +blobstorageversionid, +isdeleted, +created +FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByUserId = ANY (_coveredByUserIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/01-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/01-setup-tables.sql new file mode 100644 index 00000000..f4c46899 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/01-setup-tables.sql @@ -0,0 +1,50 @@ +-- Enum: delegation.delegationChangeType +DO $$ BEGIN + CREATE TYPE delegation.delegationChangeType AS ENUM ('grant', 'revoke', 'revokelast'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- Table: drop/create delegation.delegationChanges table both to drop old content and change from isDeleted to delegationChangeType +DROP TABLE IF EXISTS delegation.delegationChanges CASCADE; +CREATE TABLE IF NOT EXISTS delegation.delegationChanges +( + delegationChangeId bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + delegationChangeType delegation.delegationChangeType NOT NULL, + altinnAppId character varying COLLATE pg_catalog."default" NOT NULL, + offeredByPartyId integer NOT NULL, + coveredByPartyId integer, + coveredByUserId integer, + performedByUserId integer NOT NULL, + blobStoragePolicyPath character varying COLLATE pg_catalog."default" NOT NULL, + blobStorageVersionId character varying COLLATE pg_catalog."default", + created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +) +TABLESPACE pg_default; + +-- Set start value of delegationChangeId to 100K to allow some room for manual debugging without collision +ALTER SEQUENCE delegation.delegationchanges_delegationchangeid_seq RESTART WITH 100000 INCREMENT BY 1; + +-- Index: idx_altinnappid +CREATE INDEX IF NOT EXISTS idx_altinnappid + ON delegation.delegationChanges USING btree + (altinnappid COLLATE pg_catalog."default" ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_offeredby +CREATE INDEX IF NOT EXISTS idx_offeredby + ON delegation.delegationChanges USING btree + (offeredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_coveredbyuser +CREATE INDEX IF NOT EXISTS idx_coveredbyuser + ON delegation.delegationChanges USING btree + (coveredbyuserid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_coveredbyparty +CREATE INDEX IF NOT EXISTS idx_coveredbyparty + ON delegation.delegationChanges USING btree + (coveredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/02-setup-procedures.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/02-setup-procedures.sql new file mode 100644 index 00000000..f8589f70 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/02-setup-procedures.sql @@ -0,0 +1,217 @@ +-- Function: new insert function delegation.insert_delegationchange to replace old stored proc delegation.insert_change +DROP ROUTINE IF EXISTS delegation.insert_change( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer, + _performedByUserId integer, + _blobStoragePolicyPath character varying, + _blobStorageVersionId character varying, + _isDeleted bool, + inout _delegationChangeId bigint); + +CREATE OR REPLACE FUNCTION delegation.insert_delegationchange( + _delegationChangeType delegation.delegationChangeType, + _altinnappid character varying, + _offeredbypartyid integer, + _coveredbyuserid integer, + _coveredbypartyid integer, + _performedbyuserid integer, + _blobstoragepolicypath character varying, + _blobstorageversionid character varying +) +RETURNS SETOF delegation.delegationchanges +LANGUAGE 'sql' +VOLATILE +ROWS 1 +AS $BODY$ + INSERT INTO delegation.delegationChanges( + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId + ) + VALUES ( + _delegationChangeType, + _altinnAppId, + _offeredByPartyId, + _coveredByUserId, + _coveredByPartyId, + _performedByUserId, + _blobStoragePolicyPath, + _blobStorageVersionId + ) RETURNING *; +$BODY$; + + +-- Function: update get_current_change from including isDeleted to return delegationChangeType +CREATE OR REPLACE FUNCTION delegation.get_current_change( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer +) +RETURNS SETOF delegation.delegationChanges +LANGUAGE 'sql' +STABLE PARALLEL SAFE +ROWS 1 +AS $BODY$ + SELECT + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) + ORDER BY delegationChangeId DESC LIMIT 1 +$BODY$; + + +-- Function: get_all_changes from including isDeleted to return delegationChangeType +CREATE OR REPLACE FUNCTION delegation.get_all_changes( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer +) +RETURNS SETOF delegation.delegationChanges +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) +$BODY$; + + +-- Function: delegation.get_all_current_changes from including isDeleted to return delegationChangeType +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_offeredbypartyid_only( + _altinnappids character varying[], + _offeredbypartyids integer[] +) +RETURNS SETOF delegation.delegationchanges +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + + +-- Function: delegation.get_all_current_changes_coveredbypartyids from including isDeleted to return delegationChangeType +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbypartyids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbypartyids integer[] +) +RETURNS SETOF delegation.delegationchanges +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByPartyId = ANY (_coveredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + +-- Function: delegation.get_all_current_changes_coveredbyuserids from including isDeleted to return delegationChangeType +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbyuserids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbyuserids integer[] +) +RETURNS SETOF delegation.delegationchanges +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByUserId = ANY (_coveredByUserIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/03-setup-grants.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/03-setup-grants.sql new file mode 100644 index 00000000..f35ddc9d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.04/03-setup-grants.sql @@ -0,0 +1,3 @@ +-- Grants for authorization_accessmanagement must be executed again for new sequence (Enum) and since delegationChanges table has been drop/created +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA delegation TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA delegation TO platform_authorization; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.05/01-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.05/01-setup-tables.sql new file mode 100644 index 00000000..fc038476 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.05/01-setup-tables.sql @@ -0,0 +1,2 @@ +-- Enum: update delegation.delegationChangeType rename revokelast -> revoke_last +ALTER TYPE delegation.delegationchangetype RENAME VALUE 'revokelast' TO 'revoke_last' diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.06/03-setup-grants.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.06/03-setup-grants.sql new file mode 100644 index 00000000..0a911641 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.06/03-setup-grants.sql @@ -0,0 +1,3 @@ +GRANT USAGE ON SCHEMA delegation TO platform_authorization; +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA delegation TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA delegation TO platform_authorization; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/01-setup-schemas.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/01-setup-schemas.sql new file mode 100644 index 00000000..2654718c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/01-setup-schemas.sql @@ -0,0 +1,2 @@ +-- Schema: accessmanagement +CREATE SCHEMA IF NOT EXISTS accessmanagement; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/02-setup-tables.sql new file mode 100644 index 00000000..efab61b5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/02-setup-tables.sql @@ -0,0 +1,61 @@ +-- Table: accessmanagement.resource +CREATE TABLE IF NOT EXISTS accessmanagement.Resource +( + resourceId bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + resourceRegistryId text NOT NULL, + resourceType text NOT NULL, + created timestamp with time zone NOT NULL, + modified timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +) +TABLESPACE pg_default; + +-- Index: idx_resource_resourcereferenceid +CREATE INDEX IF NOT EXISTS idx_resource_resourcereferenceid + ON accessmanagement.resource USING btree + (resourceRegistryId COLLATE pg_catalog."default" ASC NULLS LAST) + INCLUDE(resourceType) + TABLESPACE pg_default; + +-- Table: delegation.ResourceRegistryDelegationChanges +CREATE TABLE IF NOT EXISTS delegation.ResourceRegistryDelegationChanges +( + resourceRegistryDelegationChangeId bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + delegationChangeType delegation.delegationChangeType NOT NULL, + resourceId_fk integer NOT NULL, + offeredByPartyId integer NOT NULL, + coveredByPartyId integer, + coveredByUserId integer, + performedByUserId integer, + performedByPartyId integer, + blobStoragePolicyPath text COLLATE pg_catalog."default" NOT NULL, + blobStorageVersionId text COLLATE pg_catalog."default" NOT NULL, + created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +) +TABLESPACE pg_default; + +-- Set start value of resourceRegistryDelegationChangeId to 100K to allow some room for manual debugging without collision +ALTER SEQUENCE delegation.resourceregistrydelegationcha_resourceregistrydelegationcha_seq RESTART WITH 100000 INCREMENT BY 1; + +-- Foreign Key: delegation.resourceregistrydelegationchanges.resourceId_fk +ALTER TABLE delegation.ResourceRegistryDelegationChanges +ADD CONSTRAINT resourceregistrydelegationchanges_resourceid_fk +FOREIGN KEY (resourceId_fk) +REFERENCES accessmanagement.resource(resourceId); + +-- Index: idx_rrdelegation_offeredby +CREATE INDEX IF NOT EXISTS idx_rrdelegation_offeredby + ON delegation.ResourceRegistryDelegationChanges USING btree + (offeredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_rrdelegation_coveredbyuser +CREATE INDEX IF NOT EXISTS idx_rrdelegation_coveredbyuser + ON delegation.ResourceRegistryDelegationChanges USING btree + (coveredbyuserid ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_rrdelegation_coveredbyparty +CREATE INDEX IF NOT EXISTS idx_rrdelegation_coveredbyparty + ON delegation.ResourceRegistryDelegationChanges USING btree + (coveredbypartyid ASC NULLS LAST) + TABLESPACE pg_default; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/03-setup-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/03-setup-functions.sql new file mode 100644 index 00000000..68e25993 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/03-setup-functions.sql @@ -0,0 +1,322 @@ +-- Function: CREATE new delegation.insert_resourceregistrydelegationchange +CREATE OR REPLACE FUNCTION delegation.insert_resourceregistrydelegationchange( + _delegationchangetype delegation.delegationchangetype, + _resourceregistryid text, + _offeredbypartyid int, + _coveredbyuserid int, + _coveredbypartyid int, + _performedbyuserid int, + _performedbypartyid int, + _blobstoragepolicypath text, + _blobstorageversionid text, + _delegatedTime timestamp with time zone DEFAULT CURRENT_TIMESTAMP) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + VOLATILE PARALLEL UNSAFE + ROWS 1 +AS $BODY$ + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE resourceRegistryId = _resourceregistryid + ), + insertedDelegation AS ( + INSERT INTO delegation.ResourceRegistryDelegationChanges( + delegationChangeType, + resourceId_fk, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + ) + SELECT _delegationChangeType, + res.resourceId, + _offeredByPartyId, + _coveredByUserId, + _coveredByPartyId, + _performedByUserId, + _performedbypartyid, + _blobStoragePolicyPath, + _blobStorageVersionId, + _delegatedTime + FROM res + RETURNING + resourceRegistryDelegationChangeId, + delegationChangeType, + resourceId_fk, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + performedByPartyId, + blobStoragePolicyPath, + blobStorageVersionId, + created + ) + SELECT + ins.resourceRegistryDelegationChangeId, + ins.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + ins.offeredByPartyId, + ins.coveredByUserId, + ins.coveredByPartyId, + ins.performedByUserId, + ins.performedByPartyId, + ins.blobStoragePolicyPath, + ins.blobStorageVersionId, + ins.created + FROM insertedDelegation AS ins + JOIN res ON ins.resourceId_fk = res.resourceid; +$BODY$; + +-- Function: CREATE delegation.select_current_resourceregistrydelegationchange +CREATE OR REPLACE FUNCTION delegation.select_current_resourceregistrydelegationchange( + _resourceRegistryId text, + _offeredbypartyid int, + _coveredbyuserid int, + _coveredbypartyid int) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1 +AS $BODY$ + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + JOIN accessmanagement.Resource AS res ON rrDelegationChange.resourceId_fk = res.resourceid + WHERE + res.resourceRegistryId = _resourceRegistryId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) + ORDER BY resourceRegistryDelegationChangeId DESC LIMIT 1 +$BODY$; + +-- Function: CREATE delegation.select_active_resourceregistrydelegationchanges_offeredby +CREATE OR REPLACE FUNCTION delegation.select_active_resourceregistrydelegationchanges_offeredby( + _offeredByPartyId int, + _resourceRegistryIds text[] = null, + _resourceTypes text[] = null) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 +AS $BODY$ + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE (_resourceRegistryIds IS NULL OR resourceRegistryId = ANY (_resourceRegistryIds)) + AND (_resourceTypes IS NULL OR resourceType = ANY (_resourceTypes)) + ) + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + INNER JOIN res ON rrDelegationChange.resourceId_fk = res.resourceid + INNER JOIN + ( + SELECT MAX(resourceRegistryDelegationChangeId) AS maxChange + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE + offeredByPartyId = _offeredByPartyId + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON resourceRegistryDelegationChangeId = selectMaxChange.maxChange + WHERE delegationchangetype != 'revoke_last' +$BODY$; + +-- Function: CREATE delegation.select_active_resourceregistrydelegationchanges_coveredbyuser +CREATE OR REPLACE FUNCTION delegation.select_active_resourceregistrydelegationchanges_coveredbyuser( + _coveredByUserId int, + _offeredByPartyIds int[] = null, + _resourceRegistryIds text[] = null, + _resourceTypes text[] = null) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 +AS $BODY$ + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE (_resourceRegistryIds IS NULL OR resourceRegistryId = ANY (_resourceRegistryIds)) + AND (_resourceTypes IS NULL OR resourceType = ANY (_resourceTypes)) + ) + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + INNER JOIN res ON rrDelegationChange.resourceId_fk = res.resourceid + INNER JOIN + ( + SELECT MAX(resourceRegistryDelegationChangeId) AS maxChange + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE + coveredByUserId = _coveredbyuserid + AND (_offeredByPartyIds IS NULL OR offeredByPartyId = ANY (_offeredByPartyIds)) + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON resourceRegistryDelegationChangeId = selectMaxChange.maxChange + WHERE delegationchangetype != 'revoke_last' +$BODY$; + +-- Function: CREATE delegation.select_active_resourceregistrydelegationchanges_coveredbypartys +CREATE OR REPLACE FUNCTION delegation.select_active_resourceregistrydelegationchanges_coveredbypartys( + _coveredByPartyIds int[], + _offeredByPartyIds int[], + _resourceRegistryIds text[] = null, + _resourceTypes text[] = null) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 +AS $BODY$ + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE (_resourceRegistryIds IS NULL OR resourceRegistryId = ANY (_resourceRegistryIds)) + AND (_resourceTypes IS NULL OR resourceType = ANY (_resourceTypes)) + ) + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + INNER JOIN res ON rrDelegationChange.resourceId_fk = res.resourceid + INNER JOIN + ( + SELECT MAX(resourceRegistryDelegationChangeId) AS maxChange + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE + offeredByPartyId = ANY (_offeredByPartyIds) + AND coveredByPartyId = ANY (_coveredbypartyids) + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON resourceRegistryDelegationChangeId = selectMaxChange.maxChange + WHERE delegationchangetype != 'revoke_last' +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/04-setup-grants.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/04-setup-grants.sql new file mode 100644 index 00000000..3762765e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.07-accessmanagement/04-setup-grants.sql @@ -0,0 +1,8 @@ +-- Grants for new accessmanagement schema for the runtime user +GRANT USAGE ON SCHEMA accessmanagement TO platform_authorization; +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA accessmanagement TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA accessmanagement TO platform_authorization; + +-- Grants for new table and sequence in delegation schema for the runtime user +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA delegation TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA delegation TO platform_authorization; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.08-accessmanagement/01-setup-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.08-accessmanagement/01-setup-functions.sql new file mode 100644 index 00000000..7f4f7a5b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.08-accessmanagement/01-setup-functions.sql @@ -0,0 +1,53 @@ +-- FUNCTION: CREATE new delegation.select_active_resourceregistrydelegationchanges +CREATE OR REPLACE FUNCTION delegation.select_active_resourceregistrydelegationchanges( + _coveredbypartyids integer[], + _offeredbypartyids integer[], + _resourceregistryids text[] DEFAULT NULL::text[], + _resourcetypes text[] DEFAULT NULL::text[]) + RETURNS TABLE(resourceregistrydelegationchangeid integer, delegationchangetype delegation.delegationchangetype, resourceregistryid text, resourcetype text, offeredbypartyid integer, coveredbyuserid integer, coveredbypartyid integer, performedbyuserid integer, performedbypartyid integer, blobstoragepolicypath text, blobstorageversionid text, created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 + +AS $BODY$ + + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE (_resourceRegistryIds IS NULL OR resourceRegistryId = ANY (_resourceRegistryIds)) + AND (_resourceTypes IS NULL OR resourceType = ANY (_resourceTypes)) + ) + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + INNER JOIN res ON rrDelegationChange.resourceId_fk = res.resourceid + INNER JOIN + ( + SELECT MAX(resourceRegistryDelegationChangeId) AS maxChange + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE + (_offeredByPartyIds IS NULL OR offeredByPartyId = ANY (_offeredByPartyIds)) + AND (_coveredbypartyids IS NULL OR coveredByPartyId = ANY (_coveredbypartyids)) + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON resourceRegistryDelegationChangeId = selectMaxChange.maxChange + WHERE delegationchangetype != 'revoke_last' +$BODY$; + + diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/02-setup-tables.sql new file mode 100644 index 00000000..f472b592 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/02-setup-tables.sql @@ -0,0 +1,17 @@ +-- Table: accessmanagement.resource +ALTER TABLE accessmanagement.resource +DROP COLUMN IF EXISTS resourcestatus; + +-- Index: dropping resourcestatus will automatically drop the index idx_resource_resourcereferenceid and must be recreated without the resourcestatus +CREATE INDEX IF NOT EXISTS idx_resource_resourcereferenceid + ON accessmanagement.resource USING btree + (resourceRegistryId COLLATE pg_catalog."default" ASC NULLS LAST) + INCLUDE(resourceType) + TABLESPACE pg_default; + +-- A drop create as there is no "add constraint if not exists" this is just for local dev where changes to yuniql db can be performed. +ALTER TABLE accessmanagement.resource +DROP CONSTRAINT IF EXISTS unique_resourceregisterid; + +ALTER TABLE accessmanagement.resource +ADD CONSTRAINT unique_resourceregisterid UNIQUE (resourceregistryid); \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/03-setup-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/03-setup-functions.sql new file mode 100644 index 00000000..89dbf025 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.09-accessmanagement/03-setup-functions.sql @@ -0,0 +1,34 @@ +CREATE OR REPLACE FUNCTION accessmanagement.upsert_resourceregistryresource( + _resourceregistryid text, + _resourcetype text) + RETURNS TABLE(resourceid bigint, resourceregistryid text, resourcetype text, created timestamp with time zone, modified timestamp with time zone) + LANGUAGE 'sql' + COST 100 + VOLATILE PARALLEL UNSAFE + ROWS 1 + +AS $BODY$ + + INSERT INTO + accessmanagement.resource (resourceregistryid, resourcetype, created, modified) + VALUES + (_resourceregistryid, _resourcetype, now(), now()) + ON CONFLICT (resourceregistryid) + DO + UPDATE SET resourcetype = _resourcetype, modified = now(); + + SELECT + r.resourceid, + r.resourceregistryid, + r.resourcetype, + r.created, + r.modified + FROM + accessmanagement.resource r + WHERE + r.resourceregistryid = _resourceregistryid + +$BODY$; + +ALTER FUNCTION accessmanagement.upsert_resourceregistryresource(text, text) + OWNER TO platform_authorization_admin; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.10-accessmanagement/03-setup-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.10-accessmanagement/03-setup-functions.sql new file mode 100644 index 00000000..3c75a974 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.10-accessmanagement/03-setup-functions.sql @@ -0,0 +1,61 @@ +-- Function: UPDATE delegation.select_active_resourceregistrydelegationchanges_coveredbypartys with optional OfferedBy filtering +CREATE OR REPLACE FUNCTION delegation.select_active_resourceregistrydelegationchanges_coveredbypartys( + _coveredByPartyIds int[], + _offeredByPartyIds int[] = null, + _resourceRegistryIds text[] = null, + _resourceTypes text[] = null) + RETURNS TABLE ( + resourceRegistryDelegationChangeId int, + delegationChangeType delegation.delegationchangetype, + resourceRegistryId text, + resourceType text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + performedByPartyId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 +AS $BODY$ + WITH res AS ( + SELECT + resourceId, + resourceRegistryId, + resourceType + FROM accessmanagement.Resource + WHERE (_resourceRegistryIds IS NULL OR resourceRegistryId = ANY (_resourceRegistryIds)) + AND (_resourceTypes IS NULL OR resourceType = ANY (_resourceTypes)) + ) + SELECT + rrDelegationChange.resourceRegistryDelegationChangeId, + rrDelegationChange.delegationChangeType, + res.resourceRegistryId, + res.resourceType, + rrDelegationChange.offeredByPartyId, + rrDelegationChange.coveredByUserId, + rrDelegationChange.coveredByPartyId, + rrDelegationChange.performedByUserId, + rrDelegationChange.performedByPartyId, + rrDelegationChange.blobStoragePolicyPath, + rrDelegationChange.blobStorageVersionId, + rrDelegationChange.created + FROM delegation.ResourceRegistryDelegationChanges AS rrDelegationChange + INNER JOIN res ON rrDelegationChange.resourceId_fk = res.resourceid + INNER JOIN + ( + SELECT MAX(resourceRegistryDelegationChangeId) AS maxChange + FROM delegation.ResourceRegistryDelegationChanges AS rrdc + INNER JOIN res ON rrdc.resourceId_fk = res.resourceid + WHERE + (_offeredByPartyIds IS NULL OR offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByPartyId = ANY (_coveredbypartyids) + GROUP BY resourceId_fk, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON resourceRegistryDelegationChangeId = selectMaxChange.maxChange + WHERE delegationchangetype != 'revoke_last' +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/02-setup-tables.sql new file mode 100644 index 00000000..3dad139b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/02-setup-tables.sql @@ -0,0 +1,48 @@ +-- Enum: delegation.delegationChangeType +DO $$ BEGIN + CREATE TYPE delegation.uuidType AS ENUM ('urn:altinn:person:uuid', 'urn:altinn:organization:uuid', 'urn:altinn:systemuser:uuid', 'urn:altinn:enterpriseuser:uuid'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- Table: delegation.delegationchanges +ALTER TABLE delegation.delegationchanges + ADD COLUMN fromUuid UUID, + ADD COLUMN fromType delegation.uuidType, + ADD COLUMN toUuid UUID, + ADD COLUMN toType delegation.uuidType, + ADD COLUMN performedByUuid UUID, + ADD COLUMN performedByType delegation.uuidType; + +-- Index: idx_delegation_from +CREATE INDEX IF NOT EXISTS idx_delegation_from + ON delegation.delegationChanges USING btree + (fromUuid, fromType ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_delegation_to +CREATE INDEX IF NOT EXISTS idx_delegation_to + ON delegation.delegationChanges USING btree + (toUuid, toType ASC NULLS LAST) + TABLESPACE pg_default; + +-- Table: delegation.resourceregistrydelegationchanges +ALTER TABLE delegation.resourceregistrydelegationchanges + ADD COLUMN fromUuid UUID, + ADD COLUMN fromType delegation.uuidType, + ADD COLUMN toUuid UUID, + ADD COLUMN toType delegation.uuidType, + ADD COLUMN performedByUuid UUID, + ADD COLUMN performedByType delegation.uuidType; + +-- Index: idx_rrdelegation_from +CREATE INDEX IF NOT EXISTS idx_rrdelegation_from + ON delegation.resourceregistryDelegationchanges USING btree + (fromUuid, fromType ASC NULLS LAST) + TABLESPACE pg_default; + +-- Index: idx_rrdelegation_to +CREATE INDEX IF NOT EXISTS idx_rrdelegation_to + ON delegation.resourceregistryDelegationChanges USING btree + (toUuid, toType ASC NULLS LAST) + TABLESPACE pg_default; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/03-setup-functions.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/03-setup-functions.sql new file mode 100644 index 00000000..00842f36 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/03-setup-functions.sql @@ -0,0 +1,326 @@ +-- Function: new insert function delegation.insert_delegationchange to replace old stored proc delegation.insert_change +DROP FUNCTION IF EXISTS delegation.insert_delegationchange(delegation.delegationchangetype, character varying, integer, integer, integer, integer, character varying, character varying); + +CREATE OR REPLACE FUNCTION delegation.insert_delegationchange( + _delegationChangeType delegation.delegationChangeType, + _altinnappid character varying, + _offeredbypartyid integer, + _coveredbyuserid integer, + _coveredbypartyid integer, + _performedbyuserid integer, + _blobstoragepolicypath character varying, + _blobstorageversionid character varying +) +RETURNS TABLE ( + delegationChangeId int, + delegationChangeType delegation.delegationChangeType, + altinnAppId text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) +LANGUAGE 'sql' +VOLATILE +ROWS 1 +AS $BODY$ + INSERT INTO delegation.delegationChanges( + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId + ) + VALUES ( + _delegationChangeType, + _altinnAppId, + _offeredByPartyId, + _coveredByUserId, + _coveredByPartyId, + _performedByUserId, + _blobStoragePolicyPath, + _blobStorageVersionId + ) + RETURNING + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created +$BODY$; + +-- Function: get_all_changes from including isDeleted to return delegationChangeType +DROP FUNCTION IF EXISTS delegation.get_all_changes(character varying, integer, integer, integer); + +CREATE OR REPLACE FUNCTION delegation.get_all_changes( + _altinnAppId character varying, + _offeredByPartyId integer, + _coveredByUserId integer, + _coveredByPartyId integer +) +RETURNS TABLE ( + delegationChangeId int, + delegationChangeType delegation.delegationChangeType, + altinnAppId text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByUserId, + coveredByPartyId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) +$BODY$; + + +-- Function: delegation.get_all_current_changes from including isDeleted to return delegationChangeType +DROP FUNCTION IF EXISTS delegation.get_all_current_changes_offeredbypartyid_only(character varying[], integer[]); + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_offeredbypartyid_only( + _altinnappids character varying[], + _offeredbypartyids integer[] +) +RETURNS TABLE ( + delegationChangeId int, + delegationChangeType delegation.delegationChangeType, + altinnAppId text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + + +-- Function: delegation.get_all_current_changes_coveredbypartyids from including isDeleted to return delegationChangeType +DROP FUNCTION IF EXISTS delegation.get_all_current_changes_coveredbypartyids(character varying[], integer[], integer[]); + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbypartyids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbypartyids integer[] +) +RETURNS TABLE ( + delegationChangeId int, + delegationChangeType delegation.delegationChangeType, + altinnAppId text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByPartyId = ANY (_coveredByPartyIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByPartyId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + +-- Function: delegation.get_all_current_changes_coveredbyuserids from including isDeleted to return delegationChangeType +DROP FUNCTION IF EXISTS delegation.get_all_current_changes_coveredbyuserids(character varying[], integer[], integer[]); + +CREATE OR REPLACE FUNCTION delegation.get_all_current_changes_coveredbyuserids( + _altinnappids character varying[], + _offeredbypartyids integer[], + _coveredbyuserids integer[] +) +RETURNS TABLE ( + delegationChangeId int, + delegationChangeType delegation.delegationChangeType, + altinnAppId text, + offeredByPartyId int, + coveredByUserId int, + coveredByPartyId int, + performedByUserId int, + blobStoragePolicyPath text, + blobStorageVersionId text, + created timestamp with time zone) +LANGUAGE 'sql' +STABLE PARALLEL SAFE +AS $BODY$ + SELECT + delegationchangeid, + delegationChangeType, + altinnappid, + offeredbypartyid, + coveredbypartyid, + coveredbyuserid, + performedbyuserid, + blobstoragepolicypath, + blobstorageversionid, + created + FROM delegation.delegationchanges + INNER JOIN + ( + SELECT MAX(delegationChangeId) AS maxChange + FROM delegation.delegationchanges + WHERE + (_altinnappids IS NULL OR altinnAppId = ANY (_altinnAppIds)) + AND (offeredByPartyId = ANY (_offeredByPartyIds)) + AND coveredByUserId = ANY (_coveredByUserIds) + GROUP BY altinnAppId, offeredByPartyId, coveredByUserId + ) AS selectMaxChange + ON delegationChangeId = selectMaxChange.maxChange +$BODY$; + +-- Function: select_delegationchanges_by_id_range +DROP FUNCTION IF EXISTS delegation.select_delegationchanges_by_id_range(bigint, bigint); + +CREATE OR REPLACE FUNCTION delegation.select_delegationchanges_by_id_range( + _startid bigint, + _endid bigint DEFAULT '9223372036854775807'::bigint) + RETURNS TABLE( + delegationchangeid integer, + delegationchangetype delegation.delegationchangetype, + altinnappid text, + offeredbypartyid integer, + coveredbypartyid integer, + coveredbyuserid integer, + performedbyuserid integer, + blobstoragepolicypath text, + blobstorageversionid text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1000 + +AS $BODY$ + + SELECT + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByPartyId, + coveredByUserId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationChanges + WHERE + delegationChangeId BETWEEN _startId AND _endId +$BODY$; + +-- Function: update delegation.get_current_change for correct select order coveredByPartyId before coveredByUserId to match delegation.delegationchanges column order +DROP FUNCTION IF EXISTS delegation.get_current_change(character varying, integer, integer, integer); +CREATE OR REPLACE FUNCTION delegation.get_current_change( + _altinnappid character varying, + _offeredbypartyid integer, + _coveredbyuserid integer, + _coveredbypartyid integer) + RETURNS TABLE( + delegationchangeid integer, + delegationchangetype delegation.delegationchangetype, + altinnappid text, + offeredbypartyid integer, + coveredbypartyid integer, + coveredbyuserid integer, + performedbyuserid integer, + blobstoragepolicypath text, + blobstorageversionid text, + created timestamp with time zone) + LANGUAGE 'sql' + COST 100 + STABLE PARALLEL SAFE + ROWS 1 +AS $BODY$ + SELECT + delegationChangeId, + delegationChangeType, + altinnAppId, + offeredByPartyId, + coveredByPartyId, + coveredByUserId, + performedByUserId, + blobStoragePolicyPath, + blobStorageVersionId, + created + FROM delegation.delegationChanges + WHERE + altinnAppId = _altinnAppId + AND offeredByPartyId = _offeredByPartyId + AND (_coveredByUserId IS NULL OR coveredByUserId = _coveredByUserId) + AND (_coveredByPartyId IS NULL OR coveredByPartyId = _coveredByPartyId) + ORDER BY delegationChangeId DESC LIMIT 1 +$BODY$; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/04-setup-grants.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/04-setup-grants.sql new file mode 100644 index 00000000..439954b1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.11-accessmanagement/04-setup-grants.sql @@ -0,0 +1,4 @@ +-- Setup grants again for delegation schema for the runtime user +GRANT USAGE ON SCHEMA delegation TO platform_authorization; +GRANT SELECT,INSERT,UPDATE,REFERENCES,DELETE,TRUNCATE,TRIGGER ON ALL TABLES IN SCHEMA delegation TO platform_authorization; +GRANT ALL ON ALL SEQUENCES IN SCHEMA delegation TO platform_authorization; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.12-accessmanagement/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.12-accessmanagement/02-setup-tables.sql new file mode 100644 index 00000000..2ce4153e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.12-accessmanagement/02-setup-tables.sql @@ -0,0 +1,61 @@ +-- Enum: delegation.instanceType +DO $$ BEGIN + CREATE TYPE delegation.instanceDelegationMode AS ENUM ('parallelsigning', 'normal'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +DO $$ BEGIN + CREATE TYPE delegation.uuidtype AS ENUM ('urn:altinn:person:uuid', 'urn:altinn:organization:uuid', 'urn:altinn:systemuser:uuid', 'urn:altinn:enterpriseuser:uuid', 'urn:altinn:resource'); +EXCEPTION + WHEN duplicate_object THEN + ALTER TYPE delegation.uuidtype ADD VALUE IF NOT EXISTS 'urn:altinn:resource'; +END $$; + +-- Table: delegation.instancedelegationchanges + +-- DROP TABLE IF EXISTS delegation.instancedelegationchanges; + +CREATE TABLE IF NOT EXISTS delegation.instancedelegationchanges +( + instancedelegationchangeid bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ), + delegationchangetype delegation.delegationchangetype NOT NULL, + instanceDelegationMode delegation.instanceDelegationMode NOT NULL, + resourceid text NOT NULL, + instanceid text NOT NULL, + fromuuid uuid NOT NULL, + fromtype delegation.uuidtype NOT NULL, + touuid uuid NOT NULL, + totype delegation.uuidtype NOT NULL, + performedby text, + performedbytype delegation.uuidtype, + blobstoragepolicypath text COLLATE pg_catalog."default" NOT NULL, + blobstorageversionid text COLLATE pg_catalog."default" NOT NULL, + created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +) + +TABLESPACE pg_default; + +ALTER TABLE IF EXISTS delegation.instancedelegationchanges + OWNER to platform_authorization_admin; + +GRANT ALL ON TABLE delegation.instancedelegationchanges TO platform_authorization; + +GRANT ALL ON TABLE delegation.instancedelegationchanges TO platform_authorization_admin; + +-- Index: idx_instancedelegation_from + +-- DROP INDEX IF EXISTS delegation.idx_instancedelegation_from; + +CREATE INDEX IF NOT EXISTS idx_instancedelegation_from + ON delegation.instancedelegationchanges USING btree + (fromuuid ASC NULLS LAST, fromtype ASC NULLS LAST) + TABLESPACE pg_default; +-- Index: idx_instancedelegation_to + +-- DROP INDEX IF EXISTS delegation.idx_instancedelegation_to; + +CREATE INDEX IF NOT EXISTS idx_instancedelegation_to + ON delegation.instancedelegationchanges USING btree + (touuid ASC NULLS LAST, totype ASC NULLS LAST) + TABLESPACE pg_default; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.13-accessmanagement/02-setup-tables.sql b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.13-accessmanagement/02-setup-tables.sql new file mode 100644 index 00000000..1be0d3f0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Migration/v0.13-accessmanagement/02-setup-tables.sql @@ -0,0 +1,13 @@ +-- Enum: delegation.instanceType +DO $$ BEGIN + CREATE TYPE delegation.instanceDelegationSource AS ENUM ('user', 'app'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- Table: delegation.instancedelegationchanges + +-- DROP TABLE IF EXISTS delegation.instancedelegationchanges; +ALTER TABLE IF EXISTS delegation.instancedelegationchanges ADD COLUMN IF NOT EXISTS instanceDelegationSource delegation.instanceDelegationSource NOT NULL DEFAULT 'app' + + diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyFactory.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyFactory.cs new file mode 100644 index 00000000..e2b4857d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyFactory.cs @@ -0,0 +1,41 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Azure.Storage.Blobs; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Persistence.Policy; + +/// +public class PolicyFactory : IPolicyFactory +{ + /// + /// Creates a new factory that handles blobs + /// + /// Azure client factory for creating blob clients + /// options for configuring azure blob clients + public PolicyFactory(IAzureClientFactory factory, IOptionsFactory options) + { + Factory = factory; + Options = options; + } + + private IAzureClientFactory Factory { get; } + + private IOptionsFactory Options { get; } + + /// + public IPolicyRepository Create(PolicyAccountType account, string filepath) + { + var options = Options.Create(account.ToString()); + return new PolicyRepository(Factory.CreateClient(account.ToString()).GetBlobContainerClient(options.Container).GetBlobClient(filepath), options); + } + + /// + public IPolicyRepository Create(string filepath) => filepath switch + { + var blob when blob.EndsWith("delegationpolicy.xml") => Create(PolicyAccountType.Delegations, filepath), + var blob when blob.EndsWith("resourcepolicy.xml") => Create(PolicyAccountType.ResourceRegister, filepath), + _ => Create(PolicyAccountType.Metadata, filepath), + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyOptions.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyOptions.cs new file mode 100644 index 00000000..412bad62 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyOptions.cs @@ -0,0 +1,60 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Enums; + +namespace Altinn.AccessManagement.Persistence.Policy; + +/// +/// Options for configuring storage account +/// +public class PolicyOptions +{ + /// + /// Initializes a new instance of the class. + /// + public PolicyOptions() + { + } + + /// + /// Initializes a new instance of the class. + /// + public PolicyOptions(PolicyAccountType account, string accountName, string container, string uri, string key, int leaseAcquireTimeoutInSec = 3) + { + Account = account; + AccountName = accountName; + Container = container; + Uri = uri; + Key = key; + LeaseAcquireTimeout = TimeSpan.FromSeconds(leaseAcquireTimeoutInSec); + } + + /// + /// Specifies Storage Account. Mostly used as a symbol for consumer for making it simpler to targeting storage account + /// + public PolicyAccountType Account { get; set; } + + /// + /// AzureRM account name + /// + public string AccountName { get; set; } + + /// + /// Container name + /// + public string Container { get; set; } + + /// + /// Blob URI + /// + public string Uri { get; set; } + + /// + /// SAS key for authentication + /// + public string Key { get; set; } + + /// + /// Timeout for some specific operations. Defaults to 3 seconds + /// + public TimeSpan LeaseAcquireTimeout { get; set; } = TimeSpan.FromSeconds(3); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyRepository.cs new file mode 100644 index 00000000..3f64d458 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/Policy/PolicyRepository.cs @@ -0,0 +1,106 @@ +using System.Diagnostics; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Azure; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Azure.Storage.Blobs.Specialized; + +namespace Altinn.AccessManagement.Persistence.Policy; + +/// +public class PolicyRepository(BlobClient client, PolicyOptions options) : IPolicyRepository +{ + /// + /// Azure Blob Storage client + /// + public BlobClient Client { get; } = client; + + /// + /// Policy Options + /// + public PolicyOptions Options { get; } = options; + + /// + public async Task DeletePolicyVersionAsync(string version, CancellationToken cancellationToken = default) + { + var result = await RoundTripper(async () => await Client.WithVersion(version).DeleteAsync(cancellationToken: cancellationToken)); + return result; + } + + /// + public async Task GetPolicyAsync(CancellationToken cancellationToken = default) => + await RoundTripper(async () => await DownloadStreamAsync(Client, cancellationToken: cancellationToken)); + + /// + public async Task GetPolicyVersionAsync(string version, CancellationToken cancellationToken = default) => + await RoundTripper(async () => await DownloadStreamAsync(Client.WithVersion(version), cancellationToken: cancellationToken)); + + /// + public async Task PolicyExistsAsync(CancellationToken cancellationToken = default) => + await RoundTripper(async () => await Client.ExistsAsync(cancellationToken: cancellationToken)); + + /// + public async void ReleaseBlobLease(string leaseId, CancellationToken cancellationToken = default) => + await RoundTripper(async () => await Client.GetBlobLeaseClient(leaseId).ReleaseAsync(cancellationToken: cancellationToken)); + + /// + public async Task TryAcquireBlobLease(CancellationToken cancellationToken = default) + { + var result = await RoundTripper(async () => await Client.GetBlobLeaseClient().AcquireAsync(Options.LeaseAcquireTimeout, cancellationToken: cancellationToken)); + return result.Value.LeaseId; + } + + /// + public async Task> WritePolicyAsync(Stream fileStream, CancellationToken cancellationToken = default) => + await RoundTripper(async () => await Client.UploadAsync(fileStream ?? new MemoryStream(), true, cancellationToken)); + + /// + public async Task> WritePolicyConditionallyAsync(Stream fileStream, string blobLeaseId, CancellationToken cancellationToken = default) + { + return await RoundTripper(async () => await Client.UploadAsync( + fileStream, + new BlobUploadOptions() + { + Conditions = new() + { + LeaseId = blobLeaseId, + } + }, + cancellationToken)); + } + + private static async Task RoundTripper(Func> func) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + return await func(); + } + catch (RequestFailedException ex) + { + activity.StopWithError(ex); + throw; + } + catch (Exception ex) + { + activity.StopWithError(ex); + throw; + } + } + + private static async Task DownloadStreamAsync(BlobClient client, CancellationToken cancellationToken = default) + { + Stream result = new MemoryStream(); + + if (await client.ExistsAsync(cancellationToken)) + { + await client.DownloadToAsync(result, cancellationToken); + result.Position = 0; + return result; + } + + return result; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepo.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepo.cs new file mode 100644 index 00000000..21b23c86 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepo.cs @@ -0,0 +1,85 @@ +using System.Data; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Npgsql; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Persistence +{ + /// + /// Storing Resource Rigistry metadata to Access management + /// + [ExcludeFromCodeCoverage] + public class ResourceMetadataRepo : IResourceMetadataRepository + { + private readonly NpgsqlDataSource _conn; + + /// + /// Initializes a new instance of the class + /// + /// PostgreSQL datasource connection + public ResourceMetadataRepo(NpgsqlDataSource conn) + { + _conn = conn; + } + + /// + public async Task InsertAccessManagementResource(AccessManagementResource resource, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + + string query = /*strpsql*/@" + INSERT INTO accessmanagement.resource (resourceregistryid, resourcetype, created, modified) + VALUES (@resourceregistryid, @resourcetype, now(), now()) + ON CONFLICT (resourceregistryid) DO UPDATE SET resourcetype = @resourcetype, modified = now() + RETURNING resourceid, resourceregistryid, resourcetype, created, modified; + "; + + try + { + await using var cmd = _conn.CreateCommand(query); + cmd.Parameters.AddWithValue("resourceregistryid", NpgsqlDbType.Text, resource.ResourceRegistryId); + cmd.Parameters.AddWithValue("resourcetype", NpgsqlDbType.Text, resource.ResourceType.ToString().ToLower()); + + using NpgsqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken); + if (await reader.ReadAsync(cancellationToken)) + { + return await GetAccessManagementResource(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private static async ValueTask GetAccessManagementResource(NpgsqlDataReader reader) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(); + try + { + return new AccessManagementResource + { + ResourceId = await reader.GetFieldValueAsync("resourceid"), + ResourceRegistryId = await reader.GetFieldValueAsync("resourceregistryid"), + ResourceType = Enum.TryParse(await reader.GetFieldValueAsync("resourcetype"), out ResourceType resourceType) ? resourceType : ResourceType.Default, + Created = await reader.GetFieldValueAsync("created"), + Modified = await reader.GetFieldValueAsync("modified") + }; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + return await new ValueTask(Task.FromException(ex)); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepository.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepository.cs new file mode 100644 index 00000000..ee8b8e78 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/ResourceMetadataRepository.cs @@ -0,0 +1,75 @@ +using System.Data; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Microsoft.Extensions.Options; +using Npgsql; + +namespace Altinn.AccessManagement.Persistence +{ + /// + /// Storing Resource Rigistry metadata to Access management + /// + [ExcludeFromCodeCoverage] + public class ResourceMetadataRepository : IResourceMetadataRepository + { + private readonly string _connectionString; + + private readonly string insertResorceAccessManagment = "select * from accessmanagement.upsert_resourceregistryresource(@_resourceregistryid, @_resourcetype)"; + + /// + /// Initializes a new instance of the class + /// + /// The postgreSQL configurations for AuthorizationDB + public ResourceMetadataRepository(IOptions config) + { + _connectionString = string.Format(config.Value.ConnectionString, config.Value.AuthorizationDbPwd); + } + + /// + public async Task InsertAccessManagementResource(AccessManagementResource resource, CancellationToken cancellationToken = default) + { + using var activity = TelemetryConfig.ActivitySource.StartActivity(ActivityKind.Client); + try + { + await using NpgsqlConnection conn = new NpgsqlConnection(_connectionString); + await conn.OpenAsync(); + + NpgsqlCommand pgcom = new NpgsqlCommand(insertResorceAccessManagment, conn); + pgcom.Parameters.AddWithValue("_resourceregistryid", resource.ResourceRegistryId); + pgcom.Parameters.AddWithValue("_resourcetype", NpgsqlTypes.NpgsqlDbType.Text, resource.ResourceType.ToString().ToLower()); + + using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync(cancellationToken); + if (reader.Read()) + { + return GetAccessManagementResource(reader); + } + + return null; + } + catch (Exception ex) + { + activity?.StopWithError(ex); + throw; + } + } + + private static AccessManagementResource GetAccessManagementResource(NpgsqlDataReader reader) + { + ResourceType resourceType; + return new AccessManagementResource + { + ResourceId = reader.GetFieldValue("resourceid"), + ResourceRegistryId = reader.GetFieldValue("resourceregistryid"), + ResourceType = Enum.TryParse(reader.GetFieldValue("resourcetype"), out resourceType) ? resourceType : ResourceType.Default, + Created = reader.GetFieldValue("created"), + Modified = reader.GetFieldValue("modified") + }; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/.dockerignore b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/.dockerignore new file mode 100644 index 00000000..3729ff0c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/AccessManagementHost.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/AccessManagementHost.cs new file mode 100644 index 00000000..e2c6835a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/AccessManagementHost.cs @@ -0,0 +1,204 @@ +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Extensions; +using Altinn.AccessManagement.Core.Services.Implementation; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Health; +using Altinn.AccessManagement.Integration.Configuration; +using Altinn.AccessManagement.Integration.Extensions; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Persistence.Extensions; +using Altinn.Authorization.ServiceDefaults; +using Altinn.Common.AccessToken; +using Altinn.Common.AccessToken.Configuration; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.Authentication.Configuration; +using Altinn.Common.Authentication.Models; +using Altinn.Common.PEP.Authorization; +using Altinn.Common.PEP.Clients; +using Altinn.Common.PEP.Implementation; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Authorization; +using Microsoft.FeatureManagement; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Npgsql; +using Swashbuckle.AspNetCore.Filters; + +namespace Altinn.AccessManagement; + +/// +/// Configures the register host. +/// +internal static class AccessManagementHost +{ + /// + /// Configures the register host. + /// + /// The command line arguments. + public static WebApplication Create(string[] args) + { + var builder = AltinnHost.CreateWebApplicationBuilder("access-management", args); + + builder.Services.AddAutoMapper(typeof(Program)); + builder.Services.AddControllers(); + builder.Services.AddFeatureManagement(); + builder.Services.AddHttpContextAccessor(); + builder.Services.AddHealthChecks() + .AddCheck("authorization_admin_health_check"); + + builder.ConfigureAppsettings(); + builder.ConfigurePostgreSqlConfiguration(); + builder.ConfigureAltinnPackages(); + builder.ConfigureInternals(); + builder.ConfigureOpenAPI(); + builder.ConfigureAuthorization(); + + return builder.Build(); + } + + private static WebApplicationBuilder ConfigureAltinnPackages(this WebApplicationBuilder builder) + { + builder.Services.AddTransient(); + builder.Services.AddSingleton(); + builder.Services.AddHttpClient(); + return builder; + } + + private static void ConfigureInternals(this WebApplicationBuilder builder) + { + builder.AddAccessManagementCore(); + builder.AddAccessManagementIntegration(); + builder.AddAccessManagementPersistence(); + } + + private static void ConfigureOpenAPI(this WebApplicationBuilder builder) + { + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(options => + { + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Description = "Standard Authorization header using the Bearer scheme. Example: \"bearer {token}\"", + In = ParameterLocation.Header, + Name = "Authorization", + Type = SecuritySchemeType.ApiKey + }); + options.OperationFilter(); + + var originalIdSelector = options.SchemaGeneratorOptions.SchemaIdSelector; + options.SchemaGeneratorOptions.SchemaIdSelector = (Type t) => + { + if (!t.IsNested) + { + return originalIdSelector(t); + } + + var chain = new List(); + do + { + chain.Add(originalIdSelector(t)); + t = t.DeclaringType; + } + while (t != null); + chain.Reverse(); + return string.Join(".", chain); + }; + }); + + builder.Services.AddUrnSwaggerSupport(); + } + + private static void ConfigureAppsettings(this WebApplicationBuilder builder) + { + var config = builder.Configuration; + + builder.Services.Configure(config.GetSection("GeneralSettings")); + builder.Services.Configure(config.GetSection("PlatformSettings")); + builder.Services.Configure(config.GetSection("PlatformSettings")); + builder.Services.Configure(config.GetSection("CacheConfig")); + builder.Services.Configure(config.GetSection("PostgreSQLSettings")); + builder.Services.Configure(config.GetSection("AzureStorageConfiguration")); + builder.Services.Configure(config.GetSection("SblBridgeSettings")); + builder.Services.Configure(config.GetSection("kvSetting")); + builder.Services.Configure(config.GetSection("OidcProviders")); + builder.Services.Configure(config.GetSection("UserProfileLookupSettings")); + } + + private static void ConfigureAuthorization(this WebApplicationBuilder builder) + { + PlatformSettings platformSettings = builder.Configuration.GetSection("PlatformSettings").Get(); + OidcProviderSettings oidcProviders = builder.Configuration.GetSection("OidcProviders").Get(); + + if (oidcProviders.TryGetValue("altinn", out OidcProvider altinnOidcProvder)) + { + builder.Services.AddAuthentication(JwtCookieDefaults.AuthenticationScheme) + .AddJwtCookie(JwtCookieDefaults.AuthenticationScheme, options => + { + options.JwtCookieName = platformSettings.JwtCookieName; + options.MetadataAddress = altinnOidcProvder.Issuer; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + ValidateIssuer = false, + ValidateAudience = false, + RequireExpirationTime = true, + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero + }; + + if (builder.Environment.IsDevelopment()) + { + options.RequireHttpsMetadata = false; + } + }); + } + + builder.Services.AddAuthorizationBuilder() + .AddPolicy(AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION, policy => policy.Requirements.Add(new AccessTokenRequirement())) + .AddPolicy(AuthzConstants.ALTINNII_AUTHORIZATION, policy => policy.Requirements.Add(new ClaimAccessRequirement("urn:altinn:app", "sbl.authorization"))) + .AddPolicy(AuthzConstants.INTERNAL_AUTHORIZATION, policy => policy.Requirements.Add(new ClaimAccessRequirement("urn:altinn:app", "internal.authorization"))) + .AddPolicy(AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_READ, policy => policy.Requirements.Add(new ResourceAccessRequirement("read", "altinn_maskinporten_scope_delegation"))) + .AddPolicy(AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_WRITE, policy => policy.Requirements.Add(new ResourceAccessRequirement("write", "altinn_maskinporten_scope_delegation"))) + .AddPolicy(AuthzConstants.POLICY_MASKINPORTEN_DELEGATIONS_PROXY, policy => policy.Requirements.Add(new ScopeAccessRequirement(["altinn:maskinporten/delegations", "altinn:maskinporten/delegations.admin"]))) + .AddPolicy(AuthzConstants.POLICY_ACCESS_MANAGEMENT_READ, policy => policy.Requirements.Add(new ResourceAccessRequirement("read", "altinn_access_management"))) + .AddPolicy(AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE, policy => policy.Requirements.Add(new ResourceAccessRequirement("write", "altinn_access_management"))) + .AddPolicy(AuthzConstants.POLICY_RESOURCEOWNER_AUTHORIZEDPARTIES, policy => policy.Requirements.Add(new ScopeAccessRequirement([AuthzConstants.SCOPE_AUTHORIZEDPARTIES_RESOURCEOWNER, AuthzConstants.SCOPE_AUTHORIZEDPARTIES_ADMIN]))); + + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + } + + private static void ConfigurePostgreSqlConfiguration(this WebApplicationBuilder builder) + { + var runMigrations = builder.Configuration.GetValue("PostgreSQLSettings:EnableDBConnection"); + var adminConnectionStringFmt = builder.Configuration.GetValue("PostgreSQLSettings:AdminConnectionString"); + var adminConnectionStringPwd = builder.Configuration.GetValue("PostgreSQLSettings:AuthorizationDbAdminPwd"); + var connectionStringFmt = builder.Configuration.GetValue("PostgreSQLSettings:ConnectionString"); + var connectionStringPwd = builder.Configuration.GetValue("PostgreSQLSettings:AuthorizationDbPwd"); + + var adminConnectionString = new NpgsqlConnectionStringBuilder(string.Format(adminConnectionStringFmt, adminConnectionStringPwd)); + var connectionString = new NpgsqlConnectionStringBuilder(string.Format(connectionStringFmt, connectionStringPwd)) + { + MaxAutoPrepare = 50, + AutoPrepareMinUsages = 2, + }; + + var serviceDescriptor = builder.Services.GetAltinnServiceDescriptor(); + var existing = builder.Configuration.GetValue($"ConnectionStrings:{serviceDescriptor.Name}_db"); + + if (!string.IsNullOrEmpty(existing)) + { + return; + } + + builder.Configuration.AddInMemoryCollection([ + KeyValuePair.Create($"ConnectionStrings:{serviceDescriptor.Name}_db", connectionString.ToString()), + KeyValuePair.Create($"ConnectionStrings:{serviceDescriptor.Name}_db_migrate", adminConnectionString.ToString()), + KeyValuePair.Create($"Altinn:Npgsql:{serviceDescriptor.Name}:Migrate:Enabled", runMigrations ? "true" : "false"), + ]); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Altinn.AccessManagement.csproj b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Altinn.AccessManagement.csproj new file mode 100644 index 00000000..3f1fa502 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Altinn.AccessManagement.csproj @@ -0,0 +1,44 @@ + + + + true + altinn-authorization-deployapi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/ConsoleTraceService.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/ConsoleTraceService.cs new file mode 100644 index 00000000..b2ea7ea9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/ConsoleTraceService.cs @@ -0,0 +1,65 @@ +using System.Diagnostics.CodeAnalysis; +using Yuniql.Extensibility; + +namespace Altinn.AccessManagement.Configuration +{ + /// + /// Copied from sample project. + /// + [ExcludeFromCodeCoverage] + public class ConsoleTraceService : ITraceService + { + /// + public bool IsDebugEnabled { get; set; } = false; + + /// + public bool IsTraceSensitiveData { get; set; } = false; + + /// + public bool IsTraceToFile { get; set; } = false; + + /// + public bool IsTraceToDirectory { get; set; } = false; + + /// + public string TraceDirectory { get; set; } + + /// + public void Info(string message, object payload = null) + { + var traceMessage = $"INF {DateTime.UtcNow.ToString("o")} {message}{Environment.NewLine}"; + Console.Write(traceMessage); + } + + /// + public void Error(string message, object payload = null) + { + var traceMessage = $"ERR {DateTime.UtcNow.ToString("o")} {message}{Environment.NewLine}"; + Console.Write(traceMessage); + } + + /// + public void Debug(string message, object payload = null) + { + if (IsDebugEnabled) + { + var traceMessage = $"DBG {DateTime.UtcNow.ToString("o")} {message}{Environment.NewLine}"; + Console.Write(traceMessage); + } + } + + /// + public void Success(string message, object payload = null) + { + var traceMessage = $"INF {DateTime.UtcNow.ToString("u")} {message}{Environment.NewLine}"; + Console.Write(traceMessage); + } + + /// + public void Warn(string message, object payload = null) + { + var traceMessage = $"WRN {DateTime.UtcNow.ToString("o")} {message}{Environment.NewLine}"; + Console.Write(traceMessage); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/CustomTelemetryInitializer.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/CustomTelemetryInitializer.cs new file mode 100644 index 00000000..804ad940 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Configuration/CustomTelemetryInitializer.cs @@ -0,0 +1,22 @@ +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.Extensibility; + +namespace Altinn.AccessManagement.Configuration +{ + /// + /// Set up custom telemetry for Application Insights + /// + public class CustomTelemetryInitializer : ITelemetryInitializer + { + /// + /// Custom TelemetryInitializer that sets some specific values for the component + /// + public void Initialize(ITelemetry telemetry) + { + if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName)) + { + telemetry.Context.Cloud.RoleName = "access-management"; + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/AuthorizedPartiesController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/AuthorizedPartiesController.cs new file mode 100644 index 00000000..e886fbb2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/AuthorizedPartiesController.cs @@ -0,0 +1,180 @@ +using System.Net.Mime; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.FeatureManagement.Mvc; + +namespace Altinn.AccessManagement.Controllers; + +/// +/// Controller responsible for all operations for retrieving AuthorizedParties list for a user / organization / system +/// +[ApiController] +[Route("accessmanagement/api/v1/")] +public class AuthorizedPartiesController : ControllerBase +{ + private readonly ILogger _logger; + private readonly IMapper _mapper; + private readonly IAuthorizedPartiesService _authorizedPartiesService; + private readonly IContextRetrievalService _contextRetrievalService; + + /// + /// Initializes a new instance of the class. + /// + /// logger service + /// mapper service + /// service implementation for authorized parties + /// service implementation for getting information regaring users, party etc. + public AuthorizedPartiesController( + ILogger logger, + IMapper mapper, + IAuthorizedPartiesService authorizedPartiesService, + IContextRetrievalService contextRetrievalService) + { + _logger = logger; + _mapper = mapper; + _authorizedPartiesService = authorizedPartiesService; + _contextRetrievalService = contextRetrievalService; + } + + /// + /// Endpoint for retrieving all authorized parties (with option to include Authorized Parties, aka Reportees, from Altinn 2) for the authenticated user + /// + /// Optional (Default: False): Whether Authorized Parties from Altinn 2 should be included in the result set, and if access to Altinn 3 resources through having Altinn 2 roles should be included. + /// The + /// Ok + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpGet] + [Authorize] + [Route("authorizedparties")] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task>> GetAuthorizedParties(bool includeAltinn2 = false, CancellationToken cancellationToken = default) + { + try + { + int userId = AuthenticationHelper.GetUserId(HttpContext); + if (userId == 0) + { + return Unauthorized(); + } + + List authorizedParties = await _authorizedPartiesService.GetAuthorizedPartiesForUser(userId, includeAltinn2, includeAuthorizedResourcesThroughRoles: false, cancellationToken); + + return _mapper.Map>(authorizedParties); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Unexpected internal exception occurred during GetAuthorizedParties"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for retrieving a given authorized party if it exists (with option to include Authorized Parties, aka Reportees from Altinn 2, when getting the underlying list of authorized parties) in the authenticated user's list of authorized parties + /// + /// The partyId to get if exists in the authenticated user's list of authorized parties + /// Optional (Default: False): Whether Authorized Parties from Altinn 2 should be included in the underlying result set, and if access to Altinn 3 resources through having Altinn 2 roles should be included. + /// The + /// Ok + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpGet] + [Authorize] + [Route("authorizedparty/{partyId}")] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task> GetAuthorizedParty([FromRoute] int partyId, bool includeAltinn2 = false, CancellationToken cancellationToken = default) + { + try + { + int userId = AuthenticationHelper.GetUserId(HttpContext); + if (userId == 0) + { + return Unauthorized(); + } + + List authorizedParties = await _authorizedPartiesService.GetAuthorizedPartiesForUser(userId, includeAltinn2, includeAuthorizedResourcesThroughRoles: false, cancellationToken); + AuthorizedParty authorizedParty = authorizedParties.Find(ap => ap.PartyId == partyId && !ap.OnlyHierarchyElementWithNoAccess) + ?? authorizedParties.SelectMany(ap => ap.Subunits).FirstOrDefault(subunit => subunit.PartyId == partyId); + + if (authorizedParty == null) + { + ModelState.AddModelError("InvalidParty", "The party id is either invalid or is not an authorized party for the authenticated user"); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return _mapper.Map(authorizedParty); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Unexpected internal exception occurred during GetAuthorizedParties"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for retrieving all authorized parties (with option to include Authorized Parties, aka Reportees, from Altinn 2) for the authenticated user + /// + /// The party to retrieve the list of authorized parties for + /// Optional (Default: False): Whether Authorized Parties from Altinn 2 should be included in the result set, and if access to Altinn 3 resources through having Altinn 2 roles should be included. + /// The + /// Ok + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpGet] + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_READ)] + [Route("{party}/authorizedparties")] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task>> GetAuthorizedPartiesAsAccessManager([FromRoute] int party, bool includeAltinn2 = false, CancellationToken cancellationToken = default) + { + try + { + int authenticatedUserPartyId = AuthenticationHelper.GetPartyId(HttpContext); + + Party subject = await _contextRetrievalService.GetPartyAsync(party, cancellationToken); + if (subject.PartyTypeName == PartyType.Person && subject.PartyId != authenticatedUserPartyId) + { + return Forbid(); + } + + List authorizedParties = await _authorizedPartiesService.GetAuthorizedPartiesForParty(subject.PartyId, includeAltinn2, includeAuthorizedResourcesThroughRoles: false, cancellationToken); + + return _mapper.Map>(authorizedParties); + } + catch (ArgumentException ex) + { + ModelState.AddModelError("Argument exception", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Unexpected internal exception occurred during GetAuthorizedParties"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationRequestsController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationRequestsController.cs new file mode 100644 index 00000000..fb025da6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationRequestsController.cs @@ -0,0 +1,66 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Resolvers; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations for managing delegation requests + /// + [Route("api")] + [ApiController] + public class DelegationRequestsController : ControllerBase + { + private readonly IDelegationRequests _delegationRequests; + + /// + /// Initializes a new instance of the class. + /// + /// The service implementation for + public DelegationRequestsController(IDelegationRequests delegationRequsts) + { + _delegationRequests = delegationRequsts; + } + + /// + /// Gets a list of delegation requests for the reportee if the user is authorized + /// + /// The reportee to get delegation requests for + /// Optional filter parameter for serviceCode + /// Optional filter parameter for serviceEditionCode + /// Optional filter parameter for directions (incoming, outgoing). If no direction is specified, both incoming and outgoing requests will be returned + /// Optional filter parameter for status. (created, unopened, approved, rejected, deleted) + /// Optional filter parameter for continuationToken + /// List of delegation requests + [HttpGet("accessmanagement/api/v1/delegationrequests/")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ApiExplorerSettings(IgnoreApi = true)] + public async Task Get(string who, [FromQuery] string serviceCode = "", [FromQuery] int? serviceEditionCode = null, [FromQuery] RestAuthorizationRequestDirection direction = RestAuthorizationRequestDirection.Both, [FromQuery] List status = null, [FromQuery] string continuation = "") + { + return await _delegationRequests.GetDelegationRequestsAsync(who, serviceCode, serviceEditionCode, direction, status, continuation); + } + + /// + /// Gets a single Delegation Requests by its id, if the id exists and the user is authorized + /// + /// The delegation request id + /// The delegation request + [HttpGet("accessmanagement/api/v1/delegationrequests/{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ApiExplorerSettings(IgnoreApi = true)] + public Task> Get(string id) + { + DelegationRequest delegationRequest = new() + { + RequestResources = + [ + new AuthorizationRequestResource() { ServiceCode = "asdf", ServiceEditionCode = 435 }, + ] + }; + + return Task.FromResult>(delegationRequest); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationsController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationsController.cs new file mode 100644 index 00000000..4f512e5f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/DelegationsController.cs @@ -0,0 +1,217 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations for managing delegations of Altinn Apps + /// + [ApiController] + public class DelegationsController : ControllerBase + { + private readonly ILogger _logger; + private readonly IPolicyInformationPoint _pip; + private readonly IPolicyAdministrationPoint _pap; + + /// + /// Initializes a new instance of the class. + /// + /// the logger. + /// The policy information point + /// The policy administration point + public DelegationsController( + ILogger logger, + IPolicyInformationPoint policyInformationPoint, + IPolicyAdministrationPoint policyAdministrationPoint) + { + _logger = logger; + _pap = policyAdministrationPoint; + _pip = policyInformationPoint; + } + + /// + /// Endpoint for adding one or more rules for the given app/offeredby/coveredby. This updates or creates a new delegated policy of type "DirectlyDelegated". DelegatedByUserId is included to store history information in 3.0. + /// + /// All rules to be delegated + /// CancellationToken + /// Created + /// Partial Content + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("accessmanagement/api/v1/delegations/addrules")] + public async Task Post([FromBody] List rules, CancellationToken cancellationToken) + { + if (rules == null || rules.Count < 1) + { + return BadRequest("Missing rules in body"); + } + + if (!ModelState.IsValid) + { + return BadRequest("Invalid model"); + } + + List delegationResults = await _pap.TryWriteDelegationPolicyRules(rules, cancellationToken); + + if (delegationResults.All(r => r.CreatedSuccessfully)) + { + return Created("Created", delegationResults); + } + + if (delegationResults.Any(r => r.CreatedSuccessfully)) + { + return StatusCode(206, delegationResults); + } + + string rulesJson = JsonSerializer.Serialize(rules); + _logger.LogInformation("Delegation could not be completed. None of the rules could be processed, indicating invalid or incomplete input:\n{rulesJson}", rulesJson); + return BadRequest("Delegation could not be completed"); + } + + /// + /// Endpoint for retrieving delegated rules between parties + /// + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("accessmanagement/api/v1/delegations/getrules")] + public async Task>> GetRules([FromBody] RuleQuery ruleQuery, CancellationToken cancellationToken, [FromQuery] bool onlyDirectDelegations = false) + { + List coveredByPartyIds = new List(); + List coveredByUserIds = new List(); + List offeredByPartyIds = new List(); + List resourceIds = new List(); + + if (ruleQuery.KeyRolePartyIds.Any(id => id != 0)) + { + coveredByPartyIds.AddRange(ruleQuery.KeyRolePartyIds); + } + + if (ruleQuery.ParentPartyId != 0) + { + offeredByPartyIds.Add(ruleQuery.ParentPartyId); + } + + foreach (List resource in ruleQuery.Resources) + { + if (DelegationHelper.TryGetResourceFromAttributeMatch(resource, out ResourceAttributeMatchType resourceMatchType, out string resourceId, out _, out _, out _, out _)) + { + resourceIds.Add(resourceId); + } + } + + if (DelegationHelper.TryGetPartyIdFromAttributeMatch(ruleQuery.CoveredBy, out int partyId)) + { + coveredByPartyIds.Add(partyId); + } + else if (DelegationHelper.TryGetUserIdFromAttributeMatch(ruleQuery.CoveredBy, out int userId)) + { + coveredByUserIds.Add(userId); + } + + if (ruleQuery.OfferedByPartyId != 0) + { + offeredByPartyIds.Add(ruleQuery.OfferedByPartyId); + } + + if (offeredByPartyIds.Count == 0) + { + return StatusCode(400, $"Unable to get the rules: Missing offeredbyPartyId value."); + } + + if (coveredByPartyIds.Count == 0 && coveredByUserIds.Count == 0) + { + return StatusCode(400, $"Unable to get the rules: Missing offeredby and coveredby values."); + } + + List rulesList = await _pip.GetRulesAsync(resourceIds, offeredByPartyIds, coveredByPartyIds, coveredByUserIds, cancellationToken); + DelegationHelper.SetRuleType(rulesList, ruleQuery.OfferedByPartyId, ruleQuery.KeyRolePartyIds, ruleQuery.CoveredBy, ruleQuery.ParentPartyId); + return Ok(rulesList); + } + + /// + /// Endpoint for deleting delegated rules between parties + /// + /// Deleted + /// Partial Content + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("accessmanagement/api/v1/delegations/deleterules")] + public async Task DeleteRule([FromBody] RequestToDeleteRuleList rulesToDelete, CancellationToken cancellationToken) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + List deletionResults = await _pap.TryDeleteDelegationPolicyRules(rulesToDelete, cancellationToken); + int ruleCountToDelete = DelegationHelper.GetRulesCountToDeleteFromRequestToDelete(rulesToDelete); + int deletionResultsCount = deletionResults.Count; + + if (deletionResultsCount == ruleCountToDelete) + { + return StatusCode(200, deletionResults); + } + + string rulesToDeleteSerialized = JsonSerializer.Serialize(rulesToDelete); + if (deletionResultsCount > 0) + { + string deletionResultsSerialized = JsonSerializer.Serialize(deletionResults); + _logger.LogInformation("Partial deletion completed deleted {deletionResultsCount} of {ruleCountToDelete}.\n{rulesToDeleteSerialized}\n{deletionResultsSerialized}", deletionResultsCount, ruleCountToDelete, rulesToDeleteSerialized, deletionResultsSerialized); + return StatusCode(206, deletionResults); + } + + _logger.LogInformation("Deletion could not be completed. None of the rules could be processed, indicating invalid or incomplete input:\n{rulesToDeleteSerialized}", rulesToDeleteSerialized); + return StatusCode(400, $"Unable to complete deletion"); + } + + /// + /// Endpoint for deleting an entire delegated policy between parties + /// + /// Deleted + /// Partial Content + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("accessmanagement/api/v1/delegations/deletepolicy")] + public async Task DeletePolicy([FromBody] RequestToDeletePolicyList policiesToDelete, CancellationToken cancellationToken) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + List deletionResults = await _pap.TryDeleteDelegationPolicies(policiesToDelete, cancellationToken); + int countPolicies = DelegationHelper.GetPolicyCount(deletionResults); + int policiesToDeleteCount = policiesToDelete.Count; + + if (countPolicies == policiesToDeleteCount) + { + return StatusCode(200, deletionResults); + } + + string policiesToDeleteSerialized = JsonSerializer.Serialize(policiesToDelete); + if (countPolicies > 0) + { + string deletionResultsSerialized = JsonSerializer.Serialize(deletionResults); + _logger.LogInformation("Partial deletion completed deleted {countPolicies} of {policiesToDeleteCount}.\n{deletionResultsSerialized}", countPolicies, policiesToDeleteCount, deletionResultsSerialized); + return StatusCode(206, deletionResults); + } + + _logger.LogInformation("Deletion could not be completed. None of the rules could be processed, indicating invalid or incomplete input:\n{policiesToDeleteSerialized}", policiesToDeleteSerialized); + return StatusCode(400, $"Unable to complete deletion"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ErrorController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ErrorController.cs new file mode 100644 index 00000000..35aa1e65 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ErrorController.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Handles the presentation of unhandled exceptions during the execution of a request. + /// + [ApiController] + [ApiExplorerSettings(IgnoreApi = true)] + [AllowAnonymous] + [Route("accessmanagement/api/v1")] + public class ErrorController : ControllerBase + { + /// + /// Create a response with a new instance with limited information. + /// + /// + /// This method cannot be called directly. It is used by the API framework as a way to output ProblemDetails + /// if there has been an unhandled exception. + /// + /// A new instance. + [Route("error")] + public IActionResult Error() => Problem(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/LookupController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/LookupController.cs new file mode 100644 index 00000000..aa77a1e2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/LookupController.cs @@ -0,0 +1,74 @@ +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Utilities; +using Altinn.Platform.Register.Models; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations for lookup + /// + [ApiController] + public class LookupController : ControllerBase + { + private readonly ILogger _logger; + private readonly IMapper _mapper; + private readonly IContextRetrievalService _contextRetrieval; + + /// + /// Initializes a new instance of the class. + /// + /// the logger. + /// mapper handler + /// handler for context retrieval + public LookupController( + ILogger logger, + IMapper mapper, + IContextRetrievalService contextRetrieval) + { + _logger = logger; + _mapper = mapper; + _contextRetrieval = contextRetrieval; + } + + /// + /// Endpoint for retrieving party if party exists in the authenticated users reporteelist + /// + /// The partyId for the reportee to look up + /// Reportee if party is in authenticated users reporteelist + [HttpGet] + [Authorize] + [Route("accessmanagement/api/v1/lookup/reportee/{partyId}")] + public async Task> GetPartyFromReporteeListIfExists(int partyId) + { + try + { + int userId = AuthenticationHelper.GetUserId(HttpContext); + Party party = await _contextRetrieval.GetPartyForUser(userId, partyId); + + if (party != null) + { + if (party.PartyTypeName == Platform.Register.Enums.PartyType.Person) + { + party.SSN = IdentifierUtil.MaskSSN(party.SSN); + } + + return _mapper.Map(party); + } + else + { + return StatusCode(404); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "GetReportee failed to fetch reportee information"); + return StatusCode(500); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/MaskinportenSchemaController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/MaskinportenSchemaController.cs new file mode 100644 index 00000000..cb721eb6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/MaskinportenSchemaController.cs @@ -0,0 +1,376 @@ +#nullable enable +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Utilities; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.FeatureManagement.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations regarding Maskinporten Schema + /// + [ApiController] + [Route("accessmanagement/api/v1/")] + public class MaskinportenSchemaController : ControllerBase + { + private readonly ILogger _logger; + private readonly IMaskinportenSchemaService _delegation; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + /// logger instance + /// Handler for the delegation service + /// mapper handler + public MaskinportenSchemaController( + ILogger logger, + IMaskinportenSchemaService delegationsService, + IMapper mapper) + { + _logger = logger; + _delegation = delegationsService; + _mapper = mapper; + } + + /// + /// Endpoint for API owners and integration with Maskinporten for retrieval of information from Altinn 3 Access Management regarding active delegations of maskinporten schemas between organizations, giving access to one or more scopes in maskinporten. + /// + /// Bad Request + /// Internal Server Error + [HttpGet] + [Route("admin/delegations/maskinportenschema")]// Old path to be removed later (after maskinporten no longer use A2 proxy or A2 updated with new endpoint) + [Route("maskinporten/delegations/")] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATIONS_PROXY)] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(403)] + [ProducesResponseType(500)] + public async Task>> GetMaskinportenDelegations([FromQuery] string? supplierOrg, [FromQuery] string? consumerOrg, [FromQuery] string scope, CancellationToken cancellationToken) + { + if (!MaskinportenSchemaAuthorizer.IsAuthorizedDelegationLookupAccess(scope, HttpContext.User)) + { + ProblemDetails result = new() { Title = $"Not authorized for lookup of delegations for the scope: {scope}", Status = StatusCodes.Status403Forbidden, Type = "https://tools.ietf.org/html/rfc7231#section-6.5.3" }; + return StatusCode(StatusCodes.Status403Forbidden, result); + } + + if (!string.IsNullOrEmpty(supplierOrg) && !IdentifierUtil.IsValidOrganizationNumber(supplierOrg)) + { + ModelState.AddModelError(nameof(supplierOrg), "Supplierorg is not an valid organization number"); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + if (!string.IsNullOrEmpty(consumerOrg) && !IdentifierUtil.IsValidOrganizationNumber(consumerOrg)) + { + ModelState.AddModelError(nameof(consumerOrg), "Consumerorg is not an valid organization number"); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + try + { + List delegations = await _delegation.GetMaskinportenDelegations(supplierOrg, consumerOrg, scope, cancellationToken); + List delegationsExternal = _mapper.Map>(delegations); + + return delegationsExternal; + } + catch (ArgumentException ex) + { + ModelState.AddModelError(ex.ParamName ?? "Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(ex, "GetMaskinportenDelegation failed to fetch delegations"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + + /// + /// Endpoint for performing a query of what rights a user can delegate to others on behalf of a specified reportee and maskinporten schema. + /// + /// The reportee party + /// Request model for user rights delegation check + /// CancellationToken + /// Ok + /// Bad Request + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_WRITE)] + [Route("{party}/maskinportenschema/delegationcheck")] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + [ProducesResponseType(500)] + public async Task>> DelegationCheck([FromRoute] string party, [FromBody] RightsDelegationCheckRequestExternal rightsDelegationCheckRequest, CancellationToken cancellationToken) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + int authenticationLevel = AuthenticationHelper.GetUserAuthenticationLevel(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + + RightsDelegationCheckRequest rightDelegationStatusRequestInternal = _mapper.Map(rightsDelegationCheckRequest); + rightDelegationStatusRequestInternal.From = reportee.SingleToList(); + + DelegationCheckResponse delegationCheckResultInternal = await _delegation.DelegationCheck(authenticatedUserId, authenticationLevel, rightDelegationStatusRequestInternal, cancellationToken); + if (!delegationCheckResultInternal.IsValid) + { + foreach (var error in delegationCheckResultInternal.Errors) + { + ModelState.AddModelError(error.Key, error.Value); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return _mapper.Map>(delegationCheckResultInternal.RightDelegationCheckResults); + } + catch (ValidationException valEx) + { + ModelState.AddModelError("Validation Error", valEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Internal exception occurred during DelegationCheck"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for delegating maskinporten scheme resources between two parties + /// + /// Created + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_WRITE)] + [Route("{party}/maskinportenschema/offered")] + [Consumes("application/json")] + [Produces("application/json")] + [ProducesResponseType(201)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task> MaskinportenScopeDelegation([FromRoute] string party, [FromBody] RightsDelegationRequestExternal delegation, CancellationToken cancellationToken) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + int authenticationLevel = AuthenticationHelper.GetUserAuthenticationLevel(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + DelegationLookup internalDelegation = _mapper.Map(delegation); + internalDelegation.From = reportee.SingleToList(); + DelegationActionResult response = await _delegation.DelegateMaskinportenSchema(authenticatedUserId, authenticationLevel, internalDelegation, cancellationToken); + + if (!response.IsValid) + { + foreach (string errorKey in response.Errors.Keys) + { + ModelState.AddModelError(errorKey, response.Errors[errorKey]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + RightsDelegationResponseExternal delegationResponse = _mapper.Map(response); + + return StatusCode(201, delegationResponse); + } + catch (Exception ex) + { + if (ex is ValidationException || ex is ArgumentException) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + _logger.LogError(ex, "Internal exception occurred during maskinportenschema delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + + /// + /// Endpoint for retrieving delegated Maskinporten resources offered by the reportee party to others + /// + /// Bad Request + /// Internal Server Error + [HttpGet] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_READ)] + [Route("{party}/maskinportenschema/offered")] + [Consumes("application/json")] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task>> GetOfferedMaskinportenSchemaDelegations([FromRoute] string party, CancellationToken cancellationToken) + { + try + { + AttributeMatch partyMatch = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + List delegations = await _delegation.GetOfferedMaskinportenSchemaDelegations(partyMatch, cancellationToken); + return _mapper.Map>(delegations); + } + catch (ArgumentException argEx) + { + ModelState.AddModelError("Validation Error", argEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + string errorMessage = ex.Message; + _logger.LogError(ex, "Failed to fetch offered delegations, See the error message for more details {errorMessage}", errorMessage); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + + /// + /// Endpoint for revoking a maskinporten scope delegation on behalf of the party having offered the delegation + /// + /// No Content + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_WRITE)] + [Route("{party}/maskinportenschema/offered/revoke")] + [Consumes("application/json")] + [Produces("application/json")] + [ProducesResponseType(204)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task RevokeOfferedMaskinportenScopeDelegation([FromRoute] string party, [FromBody] RevokeOfferedDelegationExternal delegation, CancellationToken cancellationToken) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + DelegationLookup internalDelegation = _mapper.Map(delegation); + internalDelegation.From = reportee.SingleToList(); + DelegationActionResult response = await _delegation.RevokeMaskinportenSchemaDelegation(authenticatedUserId, internalDelegation, cancellationToken); + + if (!response.IsValid) + { + foreach (string errorKey in response.Errors.Keys) + { + ModelState.AddModelError(errorKey, response.Errors[errorKey]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return NoContent(); + } + catch (Exception ex) + { + if (ex is ValidationException || ex is ArgumentException) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + _logger.LogError(ex, "Internal exception occurred during deletion of maskinportenschema delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + + /// + /// Endpoint for retrieving received Maskinporten resource delegation to the reportee party from others + /// + /// Bad Request + /// Internal Server Error + [HttpGet] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_READ)] + [Route("{party}/maskinportenschema/received")] + [Consumes("application/json")] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task>> GetReceivedMaskinportenSchemaDelegations([FromRoute] string party, CancellationToken cancellationToken) + { + try + { + AttributeMatch partyMatch = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + List delegations = await _delegation.GetReceivedMaskinportenSchemaDelegations(partyMatch, cancellationToken); + return _mapper.Map>(delegations); + } + catch (ArgumentException argEx) + { + ModelState.AddModelError("Validation Error", argEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + string errorMessage = ex.Message; + _logger.LogError(ex, "Failed to fetch received delegations, See the error message for more details {errorMessage}", errorMessage); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + + /// + /// Endpoint for revoking a maskinporten scope delegation on behalf of the party having received the delegation + /// + /// No Content + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_MASKINPORTEN_DELEGATION_WRITE)] + [Route("{party}/maskinportenschema/received/revoke")] + [Consumes("application/json")] + [Produces("application/json")] + [ProducesResponseType(204)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task RevokeReceivedMaskinportenScopeDelegation([FromRoute] string party, [FromBody] RevokeReceivedDelegationExternal delegation, CancellationToken cancellationToken) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + DelegationLookup internalDelegation = _mapper.Map(delegation); + internalDelegation.To = reportee.SingleToList(); + DelegationActionResult response = await _delegation.RevokeMaskinportenSchemaDelegation(authenticatedUserId, internalDelegation, cancellationToken); + + if (!response.IsValid) + { + foreach (string errorKey in response.Errors.Keys) + { + ModelState.AddModelError(errorKey, response.Errors[errorKey]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return NoContent(); + } + catch (Exception ex) + { + if (ex is ValidationException || ex is ArgumentException) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + _logger.LogError(ex, "Internal exception occurred during deletion of maskinportenschema delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/PolicyInformationPointController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/PolicyInformationPointController.cs new file mode 100644 index 00000000..1bce23e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/PolicyInformationPointController.cs @@ -0,0 +1,56 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using AutoMapper; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations for managing delegations of Altinn Apps + /// + [Route("accessmanagement/api/v1/policyinformation")] + [ApiController] + public class PolicyInformationPointController : ControllerBase + { + private readonly IPolicyInformationPoint _pip; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The policy information point + /// The mapper + public PolicyInformationPointController(IPolicyInformationPoint pip, IMapper mapper) + { + _pip = pip; + _mapper = mapper; + } + + /// + /// Endpoint to find all delegation changes for a given user, reportee and app/resource context + /// + /// The input model that contains id info about user, reportee, resource and resourceMatchType + /// CancellationToken + /// A list of delegation changes that's stored in the database + [ApiExplorerSettings(IgnoreApi = true)] + [HttpPost] + [Route("getdelegationchanges")] + public async Task>> GetAllDelegationChanges([FromBody] DelegationChangeInput request, CancellationToken cancellationToken) + { + DelegationChangeList response = await _pip.GetAllDelegations(request, includeInstanceDelegations: true, cancellationToken); + + if (!response.IsValid) + { + foreach (string errorKey in response.Errors.Keys) + { + ModelState.AddModelError(errorKey, response.Errors[errorKey]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return _mapper.Map>(response.DelegationChanges); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceController.cs new file mode 100644 index 00000000..6a5726a2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceController.cs @@ -0,0 +1,65 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller to update AccessManagement with resources existing i ResourceRegister. + /// + [ApiController] + public class ResourceController : ControllerBase + { + private readonly ILogger _logger; + private readonly IResourceAdministrationPoint _rap; + + /// + /// Initializes a new instance of the class. + /// + /// the logger. + /// The resource administration point + public ResourceController( + ILogger logger, + IResourceAdministrationPoint resourceAdministrationPoint) + { + _logger = logger; + _rap = resourceAdministrationPoint; + } + + /// + /// Updates or creates a Resource placeholder in AccessManagement to be used for describing which resource a given delegation is connected with + /// + /// List of new Resources to add or update + /// + [HttpPost] + [HttpPut] + [Route("accessmanagement/api/v1/internal/resources")] + [Authorize(Policy = "PlatformAccess")] + [ApiExplorerSettings(IgnoreApi = true)] + public async Task Post([FromBody] List resources) + { + if (resources.Count < 1) + { + return BadRequest("Missing resources in body"); + } + + List addResourceResult = await _rap.TryWriteResourceFromResourceRegister(resources); + + if (addResourceResult.Count == resources.Count) + { + return Created("Created", addResourceResult); + } + + if (addResourceResult.Count > 0) + { + return StatusCode(206, addResourceResult); + } + + string resourcesJson = JsonSerializer.Serialize(resources); + _logger.LogInformation("Delegation could not be completed. None of the rules could be processed, indicating invalid or incomplete input:\n{resourcesJson}", resourcesJson); + return BadRequest("Delegation could not be completed"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/AppsInstanceDelegationController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/AppsInstanceDelegationController.cs new file mode 100644 index 00000000..dc124997 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/AppsInstanceDelegationController.cs @@ -0,0 +1,308 @@ +#nullable enable + +using System.IdentityModel.Tokens.Jwt; +using System.Net.Mime; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.Authorization.ProblemDetails; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Controllers; + +/// +/// Controller responsible for all instance delegation operations from Apps +/// +[ApiController] +[Route("accessmanagement/api")] +public class AppsInstanceDelegationController : ControllerBase +{ + private readonly IMapper _mapper; + private readonly IAppsInstanceDelegationService _appInstanceDelegationService; + + /// + /// Initializes a new instance of the class. + /// + /// mapper service + /// app instance delegation handler + public AppsInstanceDelegationController( + IMapper mapper, + IAppsInstanceDelegationService appInstanceDelegationService) + { + _mapper = mapper; + _appInstanceDelegationService = appInstanceDelegationService; + } + + /// + /// Finds all rights the authenticated app can delegate for a given app instance + /// + /// The resource id + /// The instance id + /// platform token needed to define fetch wich app is calling this method + /// Result + [HttpGet] + [Route("v1/app/delegationcheck/resource/{resourceId}/instance/{instanceId}")] + [Authorize(Policy = AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task DelegationCheck([FromRoute] string resourceId, [FromRoute] string instanceId, [FromHeader(Name = "PlatformAccessToken")] string token) + { + ResourceIdUrn.ResourceId? performer = GetOrgAppFromToken(token); + + if (performer == null) + { + return Forbid(); + } + + AppsInstanceDelegationRequest request = new() { ResourceId = resourceId, InstanceId = instanceId, PerformedBy = performer }; + + Result serviceResult = await _appInstanceDelegationService.DelegationCheck(request); + + if (serviceResult.IsProblem) + { + return serviceResult.Problem.ToActionResult(); + } + + PaginatedLinks? next = new PaginatedLinks(null); + IEnumerable data = _mapper.Map>(serviceResult.Value.ResourceRightDelegationCheckResults); + + Paginated result = new Paginated(next, data); + + return Ok(result); + } + + /// + /// Delegates access to an app instance + /// + /// The request model + /// The resource id + /// The instance id + /// platform token needed to define fetch wich app is calling this method + /// The + /// Result + [HttpPost] + [Route("v1/app/delegations/resource/{resourceId}/instance/{instanceId}")] + [Authorize(Policy = AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(AppsInstanceDelegationResponseDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(AppsInstanceDelegationResponseDto), StatusCodes.Status206PartialContent)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + public async Task Delegation([FromBody] AppsInstanceDelegationRequestDto appInstanceDelegationRequestDto, [FromRoute] string resourceId, [FromRoute] string instanceId, [FromHeader(Name = "PlatformAccessToken")] string token, CancellationToken cancellationToken = default) + { + ResourceIdUrn.ResourceId? performer = GetOrgAppFromToken(token); + + if (performer == null) + { + return Forbid(); + } + + AppsInstanceDelegationRequest request = _mapper.Map(appInstanceDelegationRequestDto); + + request.ResourceId = resourceId; + request.InstanceId = instanceId; + request.PerformedBy = performer; + request.InstanceDelegationSource = Core.Enums.InstanceDelegationSource.App; + request.InstanceDelegationMode = Core.Enums.InstanceDelegationMode.Normal; + + Result serviceResult = await _appInstanceDelegationService.Delegate(request, cancellationToken); + + if (serviceResult.IsProblem) + { + return serviceResult.Problem.ToActionResult(); + } + + // Check result + int totalDelegations = request.Rights.Count(); + int validDelegations = serviceResult.Value.Rights.Count(r => r.Status == Core.Enums.DelegationStatus.Delegated); + + if (validDelegations == totalDelegations) + { + return Ok(_mapper.Map(serviceResult.Value)); + } + + return StatusCode(StatusCodes.Status206PartialContent, _mapper.Map(serviceResult.Value)); + } + + /// + /// Gets app instance delegation + /// + /// The resoure to fetch instance delegations for + /// The instance to fetch instance delegations for + /// the platformToken to use for Authorization + /// The + /// Result + [HttpGet] + [Authorize(Policy = AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION)] + [Route("v1/app/delegations/resource/{resourceId}/instance/{instanceId}")] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(AppsInstanceDelegationResponseDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + public async Task Get([FromRoute] string resourceId, [FromRoute] string instanceId, [FromHeader(Name = "PlatformAccessToken")] string token, CancellationToken cancellationToken = default) + { + ResourceIdUrn.ResourceId? performer = GetOrgAppFromToken(token); + + if (performer == null) + { + return Forbid(); + } + + AppsInstanceGetRequest request = new() + { + InstanceDelegationSource = Core.Enums.InstanceDelegationSource.App, + PerformingResourceId = performer, + ResourceId = resourceId, + InstanceId = instanceId, + }; + + Result> serviceResult = await _appInstanceDelegationService.Get(request, cancellationToken); + + if (serviceResult.IsProblem) + { + return serviceResult.Problem.ToActionResult(); + } + + List list = _mapper.Map>(serviceResult.Value); + PaginatedLinks links = new PaginatedLinks(null); + Paginated result = new Paginated(links, list); + + return Ok(result); + } + + /// + /// Revokes access to an app instance + /// + /// The request model + /// The resource identifier + /// The instance identifier + /// the platformToken to use for Authorization + /// The + /// Result + [HttpPost] + [Authorize(Policy = AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION)] + [Route("v1/app/delegationrevoke/resource/{resourceId}/instance/{instanceId}")] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(AppsInstanceDelegationResponseDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Revoke([FromBody] AppsInstanceDelegationRequestDto appInstanceDelegationRequestDto, [FromRoute] string resourceId, [FromRoute] string instanceId, [FromHeader(Name = "PlatformAccessToken")] string token, CancellationToken cancellationToken = default) + { + AppsInstanceDelegationRequest request = _mapper.Map(appInstanceDelegationRequestDto); + + ResourceIdUrn.ResourceId? performer = GetOrgAppFromToken(token); + + if (performer == null) + { + return Forbid(); + } + + request.ResourceId = resourceId; + request.InstanceId = instanceId; + request.InstanceDelegationSource = Core.Enums.InstanceDelegationSource.App; + request.PerformedBy = performer; + + Result serviceResult = await _appInstanceDelegationService.Revoke(request, cancellationToken); + + if (serviceResult.IsProblem) + { + return serviceResult.Problem?.ToActionResult(); + } + + // Check result + int totalDelegations = request.Rights.Count(); + int validDelegations = serviceResult.Value.Rights.Count(r => r.Status == Core.Enums.RevokeStatus.Revoked); + + if (validDelegations == totalDelegations) + { + return Ok(_mapper.Map(serviceResult.Value)); + } + + return StatusCode(StatusCodes.Status206PartialContent, _mapper.Map(serviceResult.Value)); + } + + /// + /// Revokes all access to an app instance + /// + /// The resource identifier + /// The instance identifier + /// the platformToken to use for Authorization + /// The + /// Result + [HttpDelete] + [Authorize(Policy = AuthzConstants.PLATFORM_ACCESS_AUTHORIZATION)] + [Route("v1/app/delegationrevoke/resource/{resourceId}/instance/{instanceId}")] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(AppsInstanceDelegationResponseDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task RevokeAll([FromRoute] string resourceId, [FromRoute] string instanceId, [FromHeader(Name = "PlatformAccessToken")] string token, CancellationToken cancellationToken = default) + { + ResourceIdUrn.ResourceId? performer = GetOrgAppFromToken(token); + + if (performer == null) + { + return Forbid(); + } + + AppsInstanceGetRequest request = new AppsInstanceGetRequest + { + ResourceId = resourceId, + InstanceId = instanceId, + PerformingResourceId = performer, + InstanceDelegationSource = Core.Enums.InstanceDelegationSource.App + }; + + Result> serviceResult = await _appInstanceDelegationService.RevokeAll(request, cancellationToken); + + if (serviceResult.IsProblem) + { + return serviceResult.Problem?.ToActionResult(); + } + + List items = _mapper.Map>(serviceResult.Value); + PaginatedLinks links = new PaginatedLinks(null); + + Paginated result = new(links, items); + + return Ok(result); + } + + /// + /// delegating app from the platform token + /// + private static ResourceIdUrn.ResourceId? GetOrgAppFromToken(string token) + { + if (!string.IsNullOrEmpty(token)) + { + var handler = new JwtSecurityTokenHandler(); + var jwtSecurityToken = handler.ReadJwtToken(token); + var appidentifier = jwtSecurityToken.Claims.FirstOrDefault(c => c.Type == AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute); + if (appidentifier != null) + { + return ResourceIdUrn.ResourceId.Create(ResourceIdentifier.CreateUnchecked($"app_{jwtSecurityToken.Issuer}_{appidentifier.Value}")); + } + } + + return null; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesController.cs new file mode 100644 index 00000000..2678e4c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesController.cs @@ -0,0 +1,82 @@ +using System.Net.Mime; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.FeatureManagement.Mvc; + +namespace Altinn.AccessManagement.Controllers; + +/// +/// Controller responsible for all operations for retrieving AuthorizedParties list for a user / organization / system +/// +[ApiController] +[Route("accessmanagement/api/v1/resourceowner")] +public class ResourceOwnerAuthorizedPartiesController : ControllerBase +{ + private readonly ILogger _logger; + private readonly IMapper _mapper; + private readonly IAuthorizedPartiesService _authorizedPartiesService; + + /// + /// Initializes a new instance of the class. + /// + /// logger service + /// mapper service + /// service implementation for authorized parties + public ResourceOwnerAuthorizedPartiesController( + ILogger logger, + IMapper mapper, + IAuthorizedPartiesService authorizedPartiesService) + { + _logger = logger; + _mapper = mapper; + _authorizedPartiesService = authorizedPartiesService; + } + + /// + /// Endpoint for retrieving all authorized parties (with option to include Authorized Parties, aka Reportees, from Altinn 2) for a given user or organization + /// + /// Subject input model identifying the user or organization to retrieve the list of authorized parties for + /// Optional (Default: False): Whether Authorized Parties from Altinn 2 should be included in the result set, and if access to Altinn 3 resources through having Altinn 2 roles should be included. + /// Optional (Default: False): Whether Authorized Resources per party should be enriched with resources the user has access to through AuthorizedRoles + /// The + /// Ok + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_RESOURCEOWNER_AUTHORIZEDPARTIES)] + [Route("authorizedparties")] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task>> GetAuthorizedPartiesAsServiceOwner(BaseAttributeExternal subject, bool includeAltinn2 = false, bool includeAuthorizedResourcesThroughRoles = false, CancellationToken cancellationToken = default) + { + try + { + BaseAttribute subjectAttribute = _mapper.Map(subject); + List authorizedParties = await _authorizedPartiesService.GetAuthorizedParties(subjectAttribute, includeAltinn2, includeAuthorizedResourcesThroughRoles, cancellationToken); + + return _mapper.Map>(authorizedParties); + } + catch (ArgumentException ex) + { + ModelState.AddModelError("Argument exception", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Unexpected internal exception occurred during ServiceOwnerGetAuthorizedParties"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/RightsInternalController.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/RightsInternalController.cs new file mode 100644 index 00000000..e8e8fbfc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Controllers/RightsInternalController.cs @@ -0,0 +1,423 @@ +using System.ComponentModel.DataAnnotations; +using System.Net; +using System.Net.Mime; +using Altinn.AccessManagement.Core; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Utilities; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.FeatureManagement.Mvc; + +namespace Altinn.AccessManagement.Controllers +{ + /// + /// Controller responsible for all operations regarding rights retrieval + /// + [ApiController] + [Route("accessmanagement/api/v1/")] + public class RightsInternalController : ControllerBase + { + private readonly ILogger _logger; + private readonly IMapper _mapper; + private readonly IPolicyInformationPoint _pip; + private readonly ISingleRightsService _rights; + private readonly IAltinn2RightsService _rightsForAltinn2; + + /// + /// Initializes a new instance of the class. + /// + /// the logger + /// handler for mapping between internal and external models + /// The policy information point + /// Service implementation for providing rights operations for BFF and external integrations + /// Service implementation for providing rights operations for Altinn 2 integrations + public RightsInternalController(ILogger logger, IMapper mapper, IPolicyInformationPoint policyInformationPoint, ISingleRightsService singleRightsService, IAltinn2RightsService rightsForAltinn2) + { + _logger = logger; + _mapper = mapper; + _pip = policyInformationPoint; + _rights = singleRightsService; + _rightsForAltinn2 = rightsForAltinn2; + } + + /// + /// Endpoint for performing a query of rights between two parties for a specific resource + /// + /// Query model for rights lookup + /// CancellationToken + /// Whether the response should return all possible rights for the resource, not just the rights the user have access to + /// Ok + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("internal/query/rights/")] + [ApiExplorerSettings(IgnoreApi = true)] + public async Task>> RightsQuery([FromBody] RightsQueryExternal rightsQuery, CancellationToken cancellationToken, [FromQuery] bool returnAllPolicyRights = false) + { + try + { + RightsQuery rightsQueryInternal = rightsQuery.ToRightsQueryInternal(_mapper); + List rightsInternal = await _pip.GetRights(rightsQueryInternal, returnAllPolicyRights, cancellationToken: cancellationToken); + return _mapper.Map>(rightsInternal); + } + catch (ValidationException valEx) + { + ModelState.AddModelError("Validation Error", valEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Internal exception occurred during RightsQuery"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for performing a query of rights a user can delegate to others a specified reportee and resource. + /// IMPORTANT: The delegable rights lookup does itself not check that the user has access to the necessary RolesAdministration/MainAdmin or MaskinportenSchema delegation system resources needed to be allowed to perform delegation. + /// + /// Query model for rights lookup + /// CancellationToken + /// Whether the response should return all possible rights for the resource, not just the rights the user is allowed to delegate + /// Ok + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.ALTINNII_AUTHORIZATION)] + [Route("internal/query/delegablerights")] + [ApiExplorerSettings(IgnoreApi = true)] + public async Task>> DelegableRightsQuery([FromBody] RightsQueryExternal rightsQuery, CancellationToken cancellationToken, [FromQuery] bool returnAllPolicyRights = false) + { + try + { + RightsQuery rightsQueryInternal = rightsQuery.ToRightsQueryInternal(_mapper); + + List rightsInternal = await _pip.GetRights(rightsQueryInternal, returnAllPolicyRights, getDelegableRights: true, cancellationToken); + return _mapper.Map>(rightsInternal); + } + catch (ValidationException valEx) + { + ModelState.AddModelError("Validation Error", valEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Internal exception occurred during DelegableRightsQuery"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for performing a query of what rights a user can delegate to others on behalf of a specified reportee and resource. + /// + /// The reportee party + /// Request model for user rights delegation check + /// Ok + /// Bad Request + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE)] + [Route("internal/{party}/rights/delegation/delegationcheck")] + [Route("{party}/rights/delegation/delegationcheck")] + [ApiExplorerSettings(IgnoreApi = false)] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + [ProducesResponseType(500)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task>> DelegationCheck([FromRoute] string party, [FromBody] RightsDelegationCheckRequestExternal rightsDelegationCheckRequest) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + int authenticationLevel = AuthenticationHelper.GetUserAuthenticationLevel(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + + RightsDelegationCheckRequest rightDelegationStatusRequestInternal = _mapper.Map(rightsDelegationCheckRequest); + rightDelegationStatusRequestInternal.From = reportee.SingleToList(); + + DelegationCheckResponse delegationCheckResultInternal = await _rights.RightsDelegationCheck(authenticatedUserId, authenticationLevel, rightDelegationStatusRequestInternal); + if (!delegationCheckResultInternal.IsValid) + { + foreach (var error in delegationCheckResultInternal.Errors) + { + ModelState.AddModelError(error.Key, error.Value); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return _mapper.Map>(delegationCheckResultInternal.RightDelegationCheckResults); + } + catch (ValidationException valEx) + { + ModelState.AddModelError("Validation Error", valEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Internal exception occurred during DelegationCheck"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Endpoint for performing a delegation of rights on behalf of a specified reportee and resource, to a recipient. + /// + /// The reportee party + /// Request model for rights delegation + /// CancellationToken + /// Ok + /// Bad Request + /// Unauthorized + /// Forbidden + /// Internal Server Error + [HttpPost] + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE)] + [Route("internal/{party}/rights/delegation/offered")] + [ApiExplorerSettings(IgnoreApi = false)] + [Produces("application/json")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + [ProducesResponseType(500)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task> Delegation([FromRoute] string party, [FromBody] RightsDelegationRequestExternal rightsDelegationRequest, CancellationToken cancellationToken) + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + int authenticationLevel = AuthenticationHelper.GetUserAuthenticationLevel(HttpContext); + + try + { + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(party, HttpContext); + + DelegationLookup rightsDelegationRequestInternal = _mapper.Map(rightsDelegationRequest); + rightsDelegationRequestInternal.From = reportee.SingleToList(); + + DelegationActionResult delegationResultInternal = await _rights.DelegateRights(authenticatedUserId, authenticationLevel, rightsDelegationRequestInternal, cancellationToken); + if (!delegationResultInternal.IsValid) + { + foreach (var error in delegationResultInternal.Errors) + { + ModelState.AddModelError(error.Key, error.Value); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return _mapper.Map(delegationResultInternal); + } + catch (ValidationException valEx) + { + ModelState.AddModelError("Validation Error", valEx.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (TooManyFailedLookupsException tooManyEx) + { + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.TooManyRequests, detail: tooManyEx.Message)); + } + catch (Exception ex) + { + _logger.LogError(500, ex, "Internal exception occurred during Rights Delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Gets a list of all recipients having received right delegations from the reportee party including the resource/app/service info, but not specific rights + /// + /// reportee acting on behalf of + /// Cancellation token used for cancelling the inbound HTTP + /// A representing the result of the asynchronous operation. + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_READ)] + [HttpGet("internal/{party}/rights/delegation/offered")] + [Produces(MediaTypeNames.Application.Json, Type = typeof(IEnumerable))] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task GetOfferedRights([FromRoute] int party, CancellationToken cancellationToken) + { + var delegations = await _rightsForAltinn2.GetOfferedRights(party, cancellationToken); + var response = _mapper.Map>(delegations); + return Ok(response); + } + + /// + /// Gets a list of all recipients having received right delegations from the reportee party including the resource/app/service info, but not specific rights + /// + /// reportee acting on behalf of + /// Cancellation token used for cancelling the inbound HTTP + /// A representing the result of the asynchronous operation. + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_READ)] + [HttpGet("internal/{party}/rights/delegation/received")] + [Produces(MediaTypeNames.Application.Json, Type = typeof(IEnumerable))] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task GetReceivedRights([FromRoute] int party, CancellationToken cancellationToken) + { + var delegations = await _rightsForAltinn2.GetReceivedRights(party, cancellationToken); + var response = _mapper.Map>(delegations); + return Ok(response); + } + + /// + /// Gets a list of all recipients having received right delegations from the reportee party including the resource/app/service info, but not specific rights + /// + /// Used to specify the reportee party the authenticated user is acting on behalf of. Can either be the PartyId, or the placeholder values: 'person' or 'organization' in combination with providing the social security number or the organization number using the header values. + /// The specific delegation to be revoked + /// Cancellation token used for cancelling the inbound HTTP + /// A representing the result of the asynchronous operation. + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE)] + [ActionName(nameof(RevokeReceivedDelegation))] + [HttpPost("internal/{party}/rights/delegation/received/revoke")] + [Produces(MediaTypeNames.Application.Json, Type = typeof(void))] + [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task RevokeReceivedDelegation([FromRoute, FromHeader] AuthorizedPartyInput input, [FromBody] RevokeReceivedDelegationExternal body, CancellationToken cancellationToken) + { + try + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(input.Party, HttpContext); + var delegation = _mapper.Map(body); + + delegation.To = reportee.SingleToList(); + + var result = await _rights.RevokeRightsDelegation(authenticatedUserId, delegation, cancellationToken); + if (result != null) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError(error.Key, error.Value[0]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return NoContent(); + } + catch (FormatException ex) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (ValidationException ex) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(StatusCodes.Status500InternalServerError, ex, "Internal exception occurred during Rights Delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Gets a list of all recipients having received right delegations from the reportee party including the resource/app/service info, but not specific rights + /// + /// Used to specify the reportee party the authenticated user is acting on behalf of. Can either be the PartyId, or the placeholder values: 'person' or 'organization' in combination with providing the social security number or the organization number using the header values. + /// payload + /// Cancellation token used for cancelling the inbound HTTP + /// A representing the result of the asynchronous operation. + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE)] + [ActionName(nameof(RevokeOfferedDelegation))] + [HttpPost("internal/{party}/rights/delegation/offered/revoke")] + [Produces(MediaTypeNames.Application.Json, Type = typeof(void))] + [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task RevokeOfferedDelegation([FromRoute, FromHeader] AuthorizedPartyInput input, [FromBody] RevokeOfferedDelegationExternal body, CancellationToken cancellationToken) + { + try + { + int authenticatedUserId = AuthenticationHelper.GetUserId(HttpContext); + AttributeMatch reportee = IdentifierUtil.GetIdentifierAsAttributeMatch(input.Party, HttpContext); + var delegation = _mapper.Map(body); + + delegation.From = reportee.SingleToList(); + var result = await _rights.RevokeRightsDelegation(authenticatedUserId, delegation, cancellationToken); + if (result != null) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError(error.Key, error.Value[0]); + } + + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + + return NoContent(); + } + catch (FormatException ex) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (ValidationException ex) + { + ModelState.AddModelError("Validation Error", ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState)); + } + catch (Exception ex) + { + _logger.LogError(StatusCodes.Status500InternalServerError, ex, "Internal exception occurred during Rights Delegation"); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, detail: "Internal Server Error")); + } + } + + /// + /// Clears access chaching for a given recipient having received right delegations from the reportee party, in order for the rights to take effect as imidiately as possible in the distributed authorization system between Altinn 2 and Altinn 3. + /// + /// Used to specify the reportee party id the authenticated user is acting on behalf of. + /// Attribute specification of the uuid of the recipient to clear access caching for + /// Cancellation token used for cancelling the inbound HTTP + [Authorize(Policy = AuthzConstants.POLICY_ACCESS_MANAGEMENT_WRITE)] + [ActionName(nameof(ClearAccessCache))] + [HttpPut("internal/{party}/accesscache/clear")] + [Produces(MediaTypeNames.Application.Json, Type = typeof(void))] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [FeatureGate(FeatureFlags.RightsDelegationApi)] + public async Task ClearAccessCache([FromRoute] int party, [FromBody] BaseAttributeExternal to, CancellationToken cancellationToken) + { + BaseAttribute toAttribute = _mapper.Map(to); + HttpResponseMessage response = await _rightsForAltinn2.ClearReporteeRights(party, toAttribute, cancellationToken); + if (!response.IsSuccessStatusCode) + { + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)response.StatusCode, detail: $"Could not complete the request. Reason: {response.ReasonPhrase}")); + } + + return Ok(); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/AuthorizedPartyTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/AuthorizedPartyTypeExternal.cs new file mode 100644 index 00000000..789449f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/AuthorizedPartyTypeExternal.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum for different types of Authorized Party +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum AuthorizedPartyTypeExternal +{ + /// + /// Unknown or unspecified + /// + None = 0, + + /// + /// Party Type is a Person + /// + Person = 1, + + /// + /// Party Type is an Organization + /// + Organization = 2, + + /// + /// Party Type is a Self Identified user + /// + SelfIdentified = 3 +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegableStatusExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegableStatusExternal.cs new file mode 100644 index 00000000..c09b39b9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegableStatusExternal.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum for different right delegation status responses +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum DelegableStatusExternal +{ + /// + /// User is not able to delegate the right + /// + [EnumMember(Value = "NotDelegable")] + NotDelegable = 0, + + /// + /// User is able to delegate the right + /// + [EnumMember(Value = "Delegable")] + Delegable = 1 +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegationStatusExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegationStatusExternal.cs new file mode 100644 index 00000000..2388f81e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DelegationStatusExternal.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum for different right delegation status responses +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum DelegationStatusExternal +{ + /// + /// Right was not delegated + /// + NotDelegated = 0, + + /// + /// Right was delegated + /// + Delegated = 1 +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DetailCodeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DetailCodeExternal.cs new file mode 100644 index 00000000..bafe6ef8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/DetailCodeExternal.cs @@ -0,0 +1,66 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Enums +{ + /// + /// Fixed values for DetailCodes + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum DetailCodeExternal + { + /// + /// Unknown reason should not be used + /// + Unknown = 0, + + /// + /// Has access by a delegated role in ER or Altinn + /// + RoleAccess = 1, + + /// + /// Has access by direct delegation + /// + DelegationAccess = 2, + + /// + /// The service requires explicit access in SRR and the reportee has this + /// + SrrRightAccess = 3, + + /// + /// Has not access by a delegation of role in ER or Altinn + /// + MissingRoleAccess = 4, + + /// + /// Has not access by direct delegation + /// + MissingDelegationAccess = 5, + + /// + /// The service requires explicit access in SRR and the reportee is missing this + /// + MissingSrrRightAccess = 6, + + /// + /// The service requires explicit authentication level and the reportee is missing this + /// + InsufficientAuthenticationLevel = 7, + + /// + /// The receiver already has the right + /// + AlreadyDelegated = 8, + + /// + /// The receiver has the right based on Access List delegation + /// + AccessListValidationPass = 9, + + /// + /// The receiver does not have the right based on Access List delegation + /// + AccessListValidationFail = 10, + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/InstanceDelegationModeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/InstanceDelegationModeExternal.cs new file mode 100644 index 00000000..a91d32c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/InstanceDelegationModeExternal.cs @@ -0,0 +1,19 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum defining the delegation mode for instance delegation Normal or PArallelSigning +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum InstanceDelegationModeExternal +{ + /// + /// Identifies a unit could also be identified with a Organization number + /// + [EnumMember(Value = "normal")] + [PgName("normal")] + Normal, +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceSourceExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceSourceExternal.cs new file mode 100644 index 00000000..fa69d7a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceSourceExternal.cs @@ -0,0 +1,25 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Enums.ResourceRegistry +{ + /// + /// Enum for the different reference sources for resources in the resource registry + /// + public enum ReferenceSourceExternal : int + { + [EnumMember(Value = "Default")] + Default = 0, + + [EnumMember(Value = "Altinn1")] + Altinn1 = 1, + + [EnumMember(Value = "Altinn2")] + Altinn2 = 2, + + [EnumMember(Value = "Altinn3")] + Altinn3 = 3, + + [EnumMember(Value = "ExternalPlatform")] + ExternalPlatform = 4 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceTypeExternal.cs new file mode 100644 index 00000000..8b3e81d6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ReferenceTypeExternal.cs @@ -0,0 +1,28 @@ +using System.Runtime.Serialization; + +namespace Altinn.AccessManagement.Enums.ResourceRegistry +{ + /// + /// Enum for reference types of resources in the resource registry + /// + public enum ReferenceTypeExternal : int + { + [EnumMember(Value = "Default")] + Default = 0, + + [EnumMember(Value = "Uri")] + Uri = 1, + + [EnumMember(Value = "DelegationSchemeId")] + DelegationSchemeId = 2, + + [EnumMember(Value = "MaskinportenScope")] + MaskinportenScope = 3, + + [EnumMember(Value = "ServiceCode")] + ServiceCode = 4, + + [EnumMember(Value = "ServiceEditionCode")] + ServiceEditionCode = 5, + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ResourceTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ResourceTypeExternal.cs new file mode 100644 index 00000000..1d0664bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/ResourceRegistry/ResourceTypeExternal.cs @@ -0,0 +1,29 @@ +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Enums.ResourceRegistry +{ + /// + /// Enum representation of the different types of resources supported by the resource registry + /// + [Flags] + public enum ResourceTypeExternal + { + [PgName("default")] + Default = 0, + + [PgName("systemresource")] + Systemresource = 1, + + [PgName("maskinportenschema")] + MaskinportenSchema = 2, + + [PgName("altinn2service")] + Altinn2Service = 4, + + [PgName("altinnapp")] + AltinnApp = 8, + + [PgName("genericaccessresource")] + GenericAccessResource = 16 + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RevokeStatusExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RevokeStatusExternal.cs new file mode 100644 index 00000000..fd51fd55 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RevokeStatusExternal.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum for different right revoke status responses +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum RevokeStatusExternal +{ + /// + /// Right was not revoked + /// + NotRevoked = 0, + + /// + /// Right was revoked + /// + Revoked = 1 +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RightSourceTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RightSourceTypeExternal.cs new file mode 100644 index 00000000..557416a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/RightSourceTypeExternal.cs @@ -0,0 +1,28 @@ +namespace Altinn.AccessManagement.Enums +{ + /// + /// Enum for different the source types exist for a right in Altinn Authorization + /// + public enum RightSourceTypeExternal + { + /// + /// Default value + /// + Unknown = 0, + + /// + /// XACML policy for an Altinn app + /// + AppPolicy = 1, + + /// + /// XACML policy for a resource from the resource registry + /// + ResourceRegistryPolicy = 2, + + /// + /// Altinn delegation policy + /// + DelegationPolicy = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/UuidTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/UuidTypeExternal.cs new file mode 100644 index 00000000..ac2543d9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Enums/UuidTypeExternal.cs @@ -0,0 +1,44 @@ +using System.Runtime.Serialization; +using NpgsqlTypes; + +namespace Altinn.AccessManagement.Enums; + +/// +/// Enum defining the different uuids used for defining parts in a delegation +/// +public enum UuidTypeExternal +{ + /// + /// Placeholder when type is not specified should only happen when there is no Uuid to match it with + /// + [EnumMember] + NotSpecified, + + /// + /// Defining a person this could also be identified with "Fødselsnummer"/"Dnummer" + /// + [EnumMember(Value = "urn:altinn:person:uuid")] + [PgName("urn:altinn:person:uuid")] + Person, + + /// + /// Identifies a unit could also be identified with a Organization number + /// + [EnumMember(Value = "urn:altinn:organization:uuid")] + [PgName("urn:altinn:organization:uuid")] + Organization, + + /// + /// Identifies a systemuser this is a identifier for machine integration it could also be identified with a unique name + /// + [EnumMember(Value = "urn:altinn:systemuser:uuid")] + [PgName("urn:altinn:systemuser:uuid")] + SystemUser, + + /// + /// Identifies a enterpriseuser this is marked as obsolete and is used for existing integration is also identified with an unique username + /// + [EnumMember(Value = "urn:altinn:enterpriseuser:uuid")] + [PgName("urn:altinn:enterpriseuser:uuid")] + EnterpriseUser +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Filters/IdentityTelemetryFilter.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Filters/IdentityTelemetryFilter.cs new file mode 100644 index 00000000..c01c6a0f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Filters/IdentityTelemetryFilter.cs @@ -0,0 +1,121 @@ +using System.Diagnostics.CodeAnalysis; +using System.Security.Claims; + +using AltinnCore.Authentication.Constants; + +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.DataContracts; +using Microsoft.ApplicationInsights.Extensibility; + +namespace Altinn.AccessManagement.Filters +{ + /// + /// Filter to enrich request telemetry with identity information + /// + [ExcludeFromCodeCoverage] + public class IdentityTelemetryFilter : ITelemetryProcessor + { + private ITelemetryProcessor Next { get; set; } + + private readonly IHttpContextAccessor _httpContextAccessor; + + /// + /// Initializes a new instance of the class. + /// + public IdentityTelemetryFilter(ITelemetryProcessor next, IHttpContextAccessor httpContextAccessor) + { + Next = next; + _httpContextAccessor = httpContextAccessor; + } + + /// + public void Process(ITelemetry item) + { + RequestTelemetry request = item as RequestTelemetry; + + if (request != null && request.Url.ToString().Contains("accessmanagement/api/")) + { + HttpContext ctx = _httpContextAccessor.HttpContext; + + if (ctx?.User != null) + { + int? orgNumber = GetOrgNumber(ctx.User); + int? userId = GetUserIdAsInt(ctx.User); + int? partyId = GetPartyIdAsInt(ctx.User); + int authLevel = GetAuthenticationLevel(ctx.User); + + request.Properties.Add("partyId", partyId.ToString()); + request.Properties.Add("authLevel", authLevel.ToString()); + + if (userId != null) + { + request.Properties.Add("userId", userId.ToString()); + } + + if (orgNumber != null) + { + request.Properties.Add("orgNumber", orgNumber.ToString()); + } + } + } + + Next.Process(item); + } + + private static int GetAuthenticationLevel(ClaimsPrincipal user) + { + if (user.HasClaim(c => c.Type == AltinnCoreClaimTypes.AuthenticationLevel)) + { + Claim userIdClaim = user.FindFirst(c => c.Type == AltinnCoreClaimTypes.AuthenticationLevel); + if (userIdClaim != null && int.TryParse(userIdClaim.Value, out int authenticationLevel)) + { + return authenticationLevel; + } + } + + return 0; + } + + private static int? GetPartyIdAsInt(ClaimsPrincipal user) + { + if (user.HasClaim(c => c.Type == AltinnCoreClaimTypes.UserId)) + { + Claim partyIdClaim = user.FindFirst(c => c.Type == AltinnCoreClaimTypes.PartyID); + if (partyIdClaim != null && int.TryParse(partyIdClaim.Value, out int partyId)) + { + return partyId; + } + } + + return null; + } + + private static int? GetOrgNumber(ClaimsPrincipal user) + { + if (user.HasClaim(c => c.Type == AltinnCoreClaimTypes.OrgNumber)) + { + Claim orgClaim = user.FindFirst(c => c.Type == AltinnCoreClaimTypes.OrgNumber); + if (orgClaim != null && int.TryParse(orgClaim.Value, out int orgNumber)) + { + return orgNumber; + } + } + + return null; + } + + private static int? GetUserIdAsInt(ClaimsPrincipal user) + { + if (user.HasClaim(c => c.Type == AltinnCoreClaimTypes.UserId)) + { + Claim userIdClaim = user.FindFirst(c => c.Type == AltinnCoreClaimTypes.UserId); + if (userIdClaim != null && int.TryParse(userIdClaim.Value, out int userId)) + { + return userId; + } + } + + return null; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthCheck.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthCheck.cs new file mode 100644 index 00000000..b30855e8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthCheck.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Altinn.AccessManagement.Health; + +/// +/// Health check service configured in startup. See https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks +/// Listen to +/// +public class HealthCheck : IHealthCheck +{ + /// + /// Verifies the health status + /// + /// The healtcheck context + /// The cancellationtoken + /// The health check result + public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + return Task.FromResult(HealthCheckResult.Healthy("A healthy result.")); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthTelemetryFilter.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthTelemetryFilter.cs new file mode 100644 index 00000000..ac982619 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Health/HealthTelemetryFilter.cs @@ -0,0 +1,47 @@ +using System.Diagnostics.CodeAnalysis; +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.DataContracts; +using Microsoft.ApplicationInsights.Extensibility; + +namespace Altinn.AccessManagement.Health +{ + /// + /// Filter to exclude health check request from Application Insights + /// + [ExcludeFromCodeCoverage] + public class HealthTelemetryFilter : ITelemetryProcessor + { + private ITelemetryProcessor Next { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public HealthTelemetryFilter(ITelemetryProcessor next) + { + Next = next; + } + + /// + public void Process(ITelemetry item) + { + if (ExcludeItemTelemetry(item)) + { + return; + } + + Next.Process(item); + } + + private bool ExcludeItemTelemetry(ITelemetry item) + { + RequestTelemetry request = item as RequestTelemetry; + + if (request != null && request.Url.ToString().EndsWith("/health/")) + { + return true; + } + + return false; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementConfiguration.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementConfiguration.cs new file mode 100644 index 00000000..0d7c62d5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementConfiguration.cs @@ -0,0 +1,18 @@ +using AutoMapper; + +namespace Altinn.AccessManagement.Mappers +{ + /// + /// Configuration for automapper for access management + /// + public class AccessManagementConfiguration : MapperConfigurationExpression + { + /// + /// access management mapping configuration + /// + public AccessManagementConfiguration() + { + this.AllowNullCollections = true; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementMapper.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementMapper.cs new file mode 100644 index 00000000..21234be8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Mappers/AccessManagementMapper.cs @@ -0,0 +1,98 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Models; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Platform.Register.Models; +using Altinn.Urn; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Mappers +{ + /// + /// A class that holds the access management mapper configuration + /// + public class AccessManagementMapper : AutoMapper.Profile + { + /// + /// Configuration for accessmanagement mapper + /// + public AccessManagementMapper() + { + AllowNullCollections = true; + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.SupplierOrg, act => act.MapFrom(src => src.CoveredByOrganizationNumber)) + .ForMember(dest => dest.ConsumerOrg, act => act.MapFrom(src => src.OfferedByOrganizationNumber)) + .ForMember(dest => dest.DelegationSchemeId, act => act.MapFrom(src => src.ResourceReferences.Find(rf => rf.ReferenceType == ReferenceType.DelegationSchemeId).Reference)) + .ForMember(dest => dest.Scopes, act => act.MapFrom(src => src.ResourceReferences.Where(rf => string.Equals(rf.ReferenceType, ReferenceType.MaskinportenScope)).Select(rf => rf.Reference).ToList())) + .ForMember(dest => dest.Created, act => act.MapFrom(src => src.Created)) + .ForMember(dest => dest.ResourceId, act => act.MapFrom(src => src.ResourceId)); + CreateMap() + .ForMember(dest => dest.Orgcode, act => act.MapFrom(src => src.Orgcode)) + .ForMember(dest => dest.Organization, act => act.MapFrom(src => src.Organization)) + .ForMember(dest => dest.Name, act => act.MapFrom(src => src.Name)); + CreateMap() + .ForMember(dest => dest.ReferenceType, act => act.MapFrom(src => src.ReferenceType)) + .ForMember(dest => dest.ReferenceSource, act => act.MapFrom(src => src.ReferenceSource)) + .ForMember(dest => dest.Reference, act => act.MapFrom(src => src.Reference)); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + // Rights + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.Action, act => act.MapFrom(src => src.Action.Value)); + CreateMap(); + CreateMap() + .ForMember(dest => dest.Action, act => act.MapFrom(src => src.Action.Value)); + CreateMap() + .ForMember(dest => dest.Action, opt => opt.MapFrom(src => + new AttributeMatch + { + Id = XacmlConstants.MatchAttributeIdentifiers.ActionId, + Value = src.Action + })); + CreateMap() + .ForMember(dest => dest.Action, act => act.MapFrom(src => src.Action.Value)); + CreateMap(); + + // Delegation + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.RightDelegationResults, act => act.MapFrom(src => src.Rights)); + CreateMap() + .ForMember(dest => dest.Action, act => act.MapFrom(src => src.Action.Value)); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.From, act => act.MapFrom(src => src.From.Value)) + .ForMember(dest => dest.To, act => act.MapFrom(src => src.To.Value)); + CreateMap() + .ForMember(dest => dest.Action, act => act.MapFrom(src => src.Action.Value)); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AttributeMatchExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AttributeMatchExternal.cs new file mode 100644 index 00000000..a38ac08a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AttributeMatchExternal.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a pair of AttributeId and AttributeValue for use in matching in XACML policies, for instance a resource, a user, a party or an action. + /// + public class AttributeMatchExternal + { + /// + /// Gets or sets the attribute id for the match + /// + [Required] + [JsonPropertyName("id")] + public string Id { get; set; } + + /// + /// Gets or sets the attribute value for the match + /// + [Required] + [JsonPropertyName("value")] + public string Value { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AuthorizedPartyExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AuthorizedPartyExternal.cs new file mode 100644 index 00000000..c7a7eca6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/AuthorizedPartyExternal.cs @@ -0,0 +1,91 @@ +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Core.Models; + +/// +/// Model representing an authorized party, meaning a party for which the subject which has been authorized, has received one or more rights (either directly or through role(s), rightspackages). +/// Used in new implementation of what has previously been named ReporteeList in Altinn 2. +/// +public class AuthorizedPartyExternal +{ + /// + /// Gets or sets the universally unique identifier of the party + /// + public Guid PartyUuid { get; set; } + + /// + /// Gets or sets the name of the party + /// + public string Name { get; set; } + + /// + /// Gets the organization number if the party is an organization + /// + public string OrganizationNumber { get; set; } + + /// + /// Gets the national identity number if the party is a person + /// + public string PersonId { get; set; } + + /// + /// Gets or sets the party id + /// + public int PartyId { get; set; } + + /// + /// Gets or sets the type of party + /// + public AuthorizedPartyTypeExternal Type { get; set; } + + /// + /// Gets or sets the unit type if the party is an organization + /// + public string UnitType { get; set; } + + /// + /// Gets or sets whether this party is marked as deleted in the Central Coordinating Register for Legal Entities + /// + public bool IsDeleted { get; set; } + + /// + /// Gets or sets a value indicating whether the party is only included as a hierarchy element without any access. Meaning a main unit where the authorized subject only have access to one or more of the subunits. + /// + public bool OnlyHierarchyElementWithNoAccess { get; set; } + + /// + /// Gets or sets a collection of all resource identifier the authorized subject has some access to on behalf of this party + /// + public List AuthorizedResources { get; set; } = []; + + /// + /// Gets or sets a collection of all rolecodes for roles from either Enhetsregisteret or Altinn 2 which the authorized subject has been authorized for on behalf of this party + /// + public List AuthorizedRoles { get; set; } = []; + + /// + /// Gets or sets a collection of all Authorized Instances + /// + public List AuthorizedInstances { get; set; } = []; + + /// + /// Gets or sets a set of subunits of this party, which the authorized subject also has some access to. + /// + public List Subunits { get; set; } = []; + + /// + /// Composite Key instances + /// + public class AuthorizedResource + { + /// + /// Resource ID + /// + public string ResourceId { get; set; } + + /// + /// Instance ID + /// + public string InstanceId { get; set; } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/BaseAttributeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/BaseAttributeExternal.cs new file mode 100644 index 00000000..b68dc764 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/BaseAttributeExternal.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models; + +/// +/// This model describes a an Attribute consisting of an Attribute Type and Attribute Value which can also be represented as a Urn by combining the properties as '{type}:{value}' +/// It's used both for external API input/output but also internally for working with attributes and matching to XACML-attributes used in policies, indentifying for instance a resource, a user, a party or an action. +/// +public class BaseAttributeExternal +{ + /// + /// Gets or sets the attribute id for the match + /// + [Required] + [JsonPropertyName("type")] + public string Type { get; set; } + + /// + /// Gets or sets the attribute value for the match + /// + [Required] + [JsonPropertyName("value")] + public string Value { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/CompetentAuthorityExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/CompetentAuthorityExternal.cs new file mode 100644 index 00000000..74bf7edd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/CompetentAuthorityExternal.cs @@ -0,0 +1,23 @@ +namespace Altinn.AccessManagement.Models +{ + /// + /// Model representation of Competent Authority part of the ServiceResource model + /// + public class CompetentAuthorityExternal + { + /// + /// The organization number + /// + public string Organization { get; set; } + + /// + /// The organization code + /// + public string Orgcode { get; set; } + + /// + /// The organization name. If not set it will be retrived from register based on Organization number + /// + public Dictionary Name { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeExternal.cs new file mode 100644 index 00000000..757065e2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeExternal.cs @@ -0,0 +1,132 @@ +#nullable enable + +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Models; + +/// +/// This is an external model that describes a delegation change as stored in the Authorization postgre DelegationChanges table. +/// +public class DelegationChangeExternal +{ + /// + /// Gets or sets the delegation change id + /// + [JsonPropertyName("delegationchangeid")] + public int DelegationChangeId { get; set; } + + /// + /// Gets or sets the resource registry delegation change id + /// + [JsonPropertyName("resourceregistrydelegationchangeid")] + public int ResourceRegistryDelegationChangeId { get; set; } + + /// + /// Gets or sets the delegation change type + /// + [JsonPropertyName("delegationchangetype")] + public DelegationChangeTypeExternal DelegationChangeType { get; set; } + + /// + /// Gets or sets the resource id. + /// + [JsonPropertyName("resourceid")] + public string ResourceId { get; set; } = string.Empty; + + /// + /// Gets or sets the resourcetype. + /// + [JsonPropertyName("resourcetype")] + public string ResourceType { get; set; } = string.Empty; + + /// + /// Gets or sets the resource instance id. + /// + [JsonPropertyName("instanceid")] + public string? InstanceId { get; set; } + + /// + /// Gets or sets the offeredbypartyid, refering to the party id of the user or organization offering the delegation. + /// + [JsonPropertyName("offeredbypartyid")] + public int OfferedByPartyId { get; set; } + + /// + /// The uuid of the party the right is on behalf of + /// + [JsonPropertyName("fromuuid")] + public Guid? FromUuid { get; set; } + + /// + /// The type of party the right is on behalf of (Person, Organization, SystemUser) + /// + [JsonPropertyName("fromuuidtype")] + public UuidTypeExternal FromUuidType { get; set; } + + /// + /// Gets or sets the coveredbypartyid, refering to the party id of the organization having received the delegation. Otherwise Null if the recipient is a user. + /// + [JsonPropertyName("coveredbypartyid")] + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the coveredbyuserid, refering to the user id of the user having received the delegation. Otherwise Null if the recipient is an organization. + /// + [JsonPropertyName("coveredbyuserid")] + public int? CoveredByUserId { get; set; } + + /// + /// The uuid of the party holding the right + /// + [JsonPropertyName("touuid")] + public Guid? ToUuid { get; set; } + + /// + /// The type of party holding the right + /// + [JsonPropertyName("touuidtype")] + public UuidTypeExternal ToUuidType { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("performedbyuserid")] + public int? PerformedByUserId { get; set; } + + /// + /// Gets or sets the party id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + [JsonPropertyName("performedbypartyid")] + public int? PerformedByPartyId { get; set; } + + /// + /// The uuid of the party that performed the delegation + /// + [JsonPropertyName("performedbyuuid")] + public string? PerformedByUuid { get; set; } + + /// + /// The type of the party that performed the delegation + /// + [JsonPropertyName("performedbyuuidtype")] + public UuidTypeExternal PerformedByUuidType { get; set; } + + /// + /// Gets or sets blobstoragepolicypath. + /// + [JsonPropertyName("blobstoragepolicypath")] + public string BlobStoragePolicyPath { get; set; } = string.Empty; + + /// + /// Gets or sets the blobstorage versionid + /// + [JsonPropertyName("blobstorageversionid")] + public string BlobStorageVersionId { get; set; } = string.Empty; + + /// + /// Gets or sets the created date and timestamp for the delegation change + /// + [JsonPropertyName("created")] + public DateTime? Created { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeTypeExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeTypeExternal.cs new file mode 100644 index 00000000..8f59204e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationChangeTypeExternal.cs @@ -0,0 +1,29 @@ +namespace Altinn.AccessManagement.Models +{ + /// + /// The type of delegation change + /// + public enum DelegationChangeTypeExternal + { + /// + /// Undefined default value + /// + // ReSharper disable UnusedMember.Global + Undefined = 0, + + /// + /// Grant event + /// + Grant = 1, + + /// + /// Revoke event + /// + Revoke = 2, + + /// + /// Revoke last right event + /// + RevokeLast = 3 + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationExternal.cs new file mode 100644 index 00000000..052369dd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DelegationExternal.cs @@ -0,0 +1,69 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums.ResourceRegistry; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a delegation. A delegation is an action that says if a resource is delegated to you or you have delegated a resource to another person/org + /// + [ExcludeFromCodeCoverage] + public class DelegationExternal + { + /// + /// Gets or sets the name of the delegation receiver + /// + public string CoveredByName { get; set; } + + /// + /// Gets or sets the name of the delegator + /// + public string OfferedByName { get; set; } + + /// + /// Gets or sets the userid id for the delegation + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets the reportee that received the delegation + /// + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation change (either added or removed rules to the policy, or deleted it entirely). + /// + public int PerformedByUserId { get; set; } + + /// + /// Gets or sets the userid that performed the delegation + /// + public DateTime Created { get; set; } + + /// + /// Gets or sets the organization number that offered the delegation + /// + public int OfferedByOrganizationNumber { get; set; } + + /// + /// Gets or sets the organization number that received the delegation + /// + public int CoveredByOrganizationNumber { get; set; } + + /// + /// Gets or sets the organization number that received the delegation + /// + public string ResourceId { get; set; } + + /// + /// The title of resource + /// + public Dictionary ResourceTitle { get; set; } + + /// + /// Gets or sets the resource type of the delegation + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResourceTypeExternal ResourceType { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DetailExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DetailExternal.cs new file mode 100644 index 00000000..1a5a5da0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/DetailExternal.cs @@ -0,0 +1,26 @@ +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a detail while providing a specific code for identifying a specific recurring detail and parameters needed for context and understanding. + /// Can be extended for specific detailing/metadata/informational purposes. + /// + public class DetailExternal + { + /// + /// Gets or sets the detail identifier code + /// + public DetailCodeExternal Code { get; set; } + + /// + /// Gets or sets a human readable (english) description of the detail + /// + public string Description { get; set; } + + /// + /// Gets or sets a dictionary of parameters which is related to the detail code and description + /// + public Dictionary> Parameters { get; set; } = new Dictionary>(); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationLookupRequestDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationLookupRequestDto.cs new file mode 100644 index 00000000..e742835d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationLookupRequestDto.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Enums; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Request model for performing delegation of access to an app instance from Apps +/// +public class AppsInstanceDelegationLookupRequestDto +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public UrnJsonTypeValue From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public UrnJsonTypeValue To { get; set; } + + /// + /// Gets or sets the urn identifying the resource of the instance + /// + [Required] + public UrnJsonTypeValue Resource { get; set; } + + /// + /// Gets or sets the urn identifying the instance id + /// + [Required] + public UrnJsonTypeValue Instance { get; set; } + + /// + /// Gets or sets the type of delegation to distinguish between parallel signing and other instance delegations + /// + [Required] + public InstanceDelegationModeExternal InstanceDelegationMode { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationRequestDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationRequestDto.cs new file mode 100644 index 00000000..81916657 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationRequestDto.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Request model for performing delegation of access to an app instance from Apps +/// +public class AppsInstanceDelegationRequestDto +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public required UrnJsonTypeValue From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public required UrnJsonTypeValue To { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public required IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationResponseDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationResponseDto.cs new file mode 100644 index 00000000..75079278 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceDelegationResponseDto.cs @@ -0,0 +1,41 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Request model for performing delegation of access to an app instance from Apps +/// +public class AppsInstanceDelegationResponseDto +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public UrnJsonTypeValue From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public UrnJsonTypeValue To { get; set; } + + /// + /// Gets or sets a value identifying the resource of the instance + /// + [Required] + public string ResourceId { get; set; } + + /// + /// Gets or sets a value identifying the instance id + /// + [Required] + public string InstanceId { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceRevokeResponseDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceRevokeResponseDto.cs new file mode 100644 index 00000000..10005162 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/InstanceDelegation/AppsInstanceRevokeResponseDto.cs @@ -0,0 +1,41 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Request model for performing revoke of access to a resource from Apps +/// +public class AppsInstanceRevokeResponseDto +{ + /// + /// Gets or sets the urn identifying the party to delegate from + /// + [Required] + public UrnJsonTypeValue From { get; set; } + + /// + /// Gets or sets the urn identifying the party to be delegated to + /// + [Required] + public UrnJsonTypeValue To { get; set; } + + /// + /// Gets or sets a value identifying the resource of the instance + /// + [Required] + public string ResourceId { get; set; } + + /// + /// Gets or sets a value identifying the instance id + /// + [Required] + public string InstanceId { get; set; } + + /// + /// Gets or sets the rights to delegate + /// + [Required] + public IEnumerable Rights { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ListObject.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ListObject.cs new file mode 100644 index 00000000..76bb567f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ListObject.cs @@ -0,0 +1,52 @@ +#nullable enable + +using System.Text.Json.Serialization; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Altinn.AccessManagement.Models; + +/// +/// A list object is a wrapper around a list of items to allow for the API to be +/// extended in the future without breaking backwards compatibility. +/// +[SwaggerSchemaFilter(typeof(SchemaFilter))] +public abstract record ListObject +{ + /// + /// Creates a new from a list of items. + /// + /// The list type. + /// The list of items. + /// A . + public static ListObject Create(IEnumerable items) + => new(items); + + /// + /// Default schema filter for . + /// + protected class SchemaFilter : ISchemaFilter + { + /// + public void Apply(OpenApiSchema schema, SchemaFilterContext context) + { + foreach (var prop in schema.Properties) + { + schema.Required.Add(prop.Key); + } + + schema.Properties["data"].Nullable = false; + } + } +} + +/// +/// A concrete list object. +/// +/// The item type. +/// The items. +public record ListObject( + [property: JsonPropertyName("data")] + IEnumerable Items) + : ListObject; diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MPDelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MPDelegationExternal.cs new file mode 100644 index 00000000..bbb7a14b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MPDelegationExternal.cs @@ -0,0 +1,49 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a delegation. A delegation is an action that says which resource is delegated by supplier to consumer org + /// + [ExcludeFromCodeCoverage] + public class MPDelegationExternal + { + /// + /// Gets or sets the organization number of the consumer that gives the delegation + /// + [JsonPropertyName("consumer_org")] + public string ConsumerOrg { get; set; } + + /// + /// Gets or sets the organization number of the supplier that received the delegation + /// + [JsonPropertyName("supplier_org")] + public string SupplierOrg { get; set; } + + /// + /// Gets or sets the id of the DelegationScheme that is delegated + /// + /// The id of the delegation scheme. + [JsonPropertyName("delegation_scheme_Id")] + public Guid? DelegationSchemeId { get; set; } + + /// + /// Gets or sets a list of scopes in the DelegationScheme + /// + [JsonPropertyName("scopes")] + public HashSet Scopes { get; set; } + + /// + /// Gets or sets the time for when the delegation was preformed + /// + [JsonPropertyName("created")] + public DateTime? Created { get; set; } + + /// + /// Gets or sets the id of the resource + /// + [JsonPropertyName("resourceid")] + public string ResourceId { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MaskinportenSchemaDelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MaskinportenSchemaDelegationExternal.cs new file mode 100644 index 00000000..4a63ee20 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/MaskinportenSchemaDelegationExternal.cs @@ -0,0 +1,53 @@ +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a delegation of a Maskinporten Schema from a client/consumer organization to a supplier organization, giving the supplier access to the scopes covered by the schema. + /// + public class MaskinportenSchemaDelegationExternal + { + /// + /// Gets or sets the PartyId of the client/consumer organization having delegated the maskinporten schema + /// + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets the name of the client/consumer organization having delegated the maskinporten schema + /// + public string OfferedByName { get; set; } + + /// + /// Gets or sets the organization number of the client/consumer organization having delegated the maskinporten schema + /// + public string OfferedByOrganizationNumber { get; set; } + + /// + /// Gets or sets the PartyId of the supplier organization having received the delegated maskinporten schema + /// + public int? CoveredByPartyId { get; set; } + + /// + /// Gets or sets the name of the supplier organization having received the delegated maskinporten schema + /// + public string CoveredByName { get; set; } + + /// + /// Gets or sets the organization number of the supplier organization having received the delegated maskinporten schema + /// + public string CoveredByOrganizationNumber { get; set; } + + /// + /// Gets or sets the user id of the user that performed the delegation + /// + public int PerformedByUserId { get; set; } + + /// + /// Gets or sets the date and timestamp when the delegation was performed + /// + public DateTime Created { get; set; } + + /// + /// Gets or sets the identifier of the maskinporten schema resource registered in the resource registry + /// + public string ResourceId { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Paginated.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Paginated.cs new file mode 100644 index 00000000..0a33fb28 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Paginated.cs @@ -0,0 +1,60 @@ +#nullable enable + +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Altinn.AccessManagement.Models; + +/// +/// A paginated . +/// +public static class Paginated +{ + /// + /// Create a new . + /// + /// The type of items + /// The items + /// The optional next-link + /// A new . + public static Paginated Create( + IEnumerable items, + string? next) + => new(new(next), items); +} + +/// +/// A paginated . +/// +/// The item type. +/// Pagination links. +/// The items. +public record Paginated( + PaginatedLinks Links, + IEnumerable Items) + : ListObject(Items); + +/// +/// Pagination links. +/// +/// Link to the next page of items (if any). +[SwaggerSchemaFilter(typeof(SchemaFilter))] +public record PaginatedLinks( + string? Next) +{ + private sealed class SchemaFilter : ISchemaFilter + { + /// + public void Apply(OpenApiSchema schema, SchemaFilterContext context) + { + schema.Required.Add("next"); + + var nextSchema = schema.Properties["next"]; + nextSchema.Nullable = true; + nextSchema.Format = "uri-reference"; + nextSchema.Example = new OpenApiString("/foo/bar/bat?page=2"); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PartyExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PartyExternal.cs new file mode 100644 index 00000000..c7fa699c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PartyExternal.cs @@ -0,0 +1,69 @@ +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.Enums; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a party. A party can be a person/organisation/enterprise user/selfidentified user + /// + [ExcludeFromCodeCoverage] + public class PartyExternal + { + /// + /// Gets or sets the ID of the party + /// + public int PartyId { get; set; } + + /// + /// Gets or sets the type of party + /// + public PartyType PartyTypeName { get; set; } + + /// + /// Gets the parties org number + /// + public string OrgNumber { get; set; } + + /// + /// Gets the parties ssn + /// + public string SSN { get; set; } + + /// + /// Gets or sets the UnitType + /// + public string UnitType { get; set; } + + /// + /// Gets or sets the Name + /// + public string Name { get; set; } + + /// + /// Gets or sets the IsDeleted + /// + public bool IsDeleted { get; set; } + + /// + /// Gets or sets a value indicating whether if the reportee in the list is only there for showing the hierarchy (a parent unit with no access) + /// + public bool OnlyHierarchyElementWithNoAccess { get; set; } + + /// + /// Gets or sets the person details for this party (will only be set if the party type is Person) + /// + public Person Person { get; set; } + + /// + /// Gets or sets the organization details for this party (will only be set if the party type is Organization) + /// + public Organization Organization { get; set; } + + /// + /// Gets or sets the value of ChildParties + /// + public List ChildParties { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PolicyAttributeMatchExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PolicyAttributeMatchExternal.cs new file mode 100644 index 00000000..9e129628 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/PolicyAttributeMatchExternal.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model extends the AttributeMatch model with a boolean value indicating whether the ABAC found a match for the attribute + /// + public class PolicyAttributeMatchExternal : AttributeMatchExternal + { + /// + /// Gets or sets a value indicating whether the ABAC found a match for the attribute + /// + [Required] + public bool? MatchFound { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckRequestDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckRequestDto.cs new file mode 100644 index 00000000..bfcf6360 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckRequestDto.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Request model for a list of all delegable rights for a specific resource. +/// +public class ResourceDelegationCheckRequestDto +{ + /// + /// Gets or sets the urn for identifying the resource of the rights to be checked + /// + [Required] + public UrnJsonTypeValue ResourceId { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckResponseDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckResponseDto.cs new file mode 100644 index 00000000..d425510d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceDelegationCheckResponseDto.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Response model for the result of a delegation status check, for which rights a user is able to delegate between two parties. +/// +public class ResourceDelegationCheckResponseDto +{ + /// + /// Gets or sets the urn identifying the party the rights can be delegated from + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public required UrnJsonTypeValue From { get; set; } + + /// + /// Gets or sets a list of right delegation status models + /// + public IEnumerable ResourceRightDelegationCheckResults { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceReferenceExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceReferenceExternal.cs new file mode 100644 index 00000000..ac76430c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceReferenceExternal.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums.ResourceRegistry; + +namespace Altinn.AccessManagement.Core.Models.ResourceRegistry +{ + /// + /// Model representation of the resource reference part of the ServiceResource model + /// + public class ResourceReferenceExternal + { + /// + /// The source the reference identifier points to + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ReferenceSourceExternal? ReferenceSource { get; set; } + + /// + /// The reference identifier + /// + public string Reference { get; set; } + + /// + /// The reference type + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public ReferenceTypeExternal? ReferenceType { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceRightDelegationCheckResultDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceRightDelegationCheckResultDto.cs new file mode 100644 index 00000000..6fcf0f76 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/ResourceRightDelegationCheckResultDto.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Enums; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// Response model describing the delegation status for a given single right, whether the authenticated user is able to delegate the right or not on behalf of the from part. +/// +public class ResourceRightDelegationCheckResultDto +{ + /// + /// Gets or sets the right key + /// + [Required] + public string RightKey { get; set; } + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + [Required] + public IEnumerable Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + [Required] + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right is delegable or not + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public DelegableStatusExternal Status { get; set; } + + /// + /// Gets or sets a list of details describing why or why not the right is valid in the current user and reportee party context + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public IEnumerable Details { get; set; } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeOfferedDelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeOfferedDelegationExternal.cs new file mode 100644 index 00000000..0183dc99 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeOfferedDelegationExternal.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Model for revoking a delegation of one or more rights a reportee has offered to another party. + /// + public class RevokeOfferedDelegationExternal + { + /// + /// Gets or sets a set of Attribute Id and Attribute Value identifying the party the delegated rights to be revoked, have been offered to. + /// + [Required] + public List To { get; set; } + + /// + /// Gets or sets a list of rights identifying what is to be revoked + /// NOTE: + /// If the right only specifies the top-level resource identifier or org/app without an action specification, + /// the operation will find and revoke all the rights the recipient party have received for the given resource. + /// + [Required] + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeReceivedDelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeReceivedDelegationExternal.cs new file mode 100644 index 00000000..80bd53ae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/RevokeReceivedDelegationExternal.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Model for revoking a delegation of one or more rights a reportee has received from another party. + /// + public class RevokeReceivedDelegationExternal + { + /// + /// Gets or sets a set of Attribute Id and Attribute Value identifying the party the delegated rights to be revoked, have been received from. + /// + [Required] + public List From { get; set; } + + /// + /// Gets or sets a list of rights identifying what is to be revoked + /// NOTE: + /// If the right only specifies the top-level resource identifier or org/app without an action specification, + /// the operation will find and revoke all the rights received from the delegating party. + /// + [Required] + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/AuthorizedPartyInput.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/AuthorizedPartyInput.cs new file mode 100644 index 00000000..9fe7006f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/AuthorizedPartyInput.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Utilities; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Models; + +/// +/// Input model +/// +public record AuthorizedPartyInput +{ + /// + /// Used to provide the organization number of the party, in combination with 'organization' as placeholder value for the {party} path parameter + /// + [FromHeader(Name = IdentifierUtil.OrganizationNumberHeader)] + public string OrganizationNumber { get; set; } + + /// + /// Used to provide the social security number of the party, in combination with 'person' as placeholder value for the {party} path parameter + /// + [FromHeader(Name = IdentifierUtil.PersonHeader)] + public string PartySSN { get; set; } + + /// + /// Used to specify the reportee party the authenticated user is acting on behalf of. Can either be the PartyId, or the placeholder values: 'person' or 'organization' in combination with providing the social security number or the organization number using the header values. + /// + [FromRoute(Name = "party")] + public string Party { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/BaseRightExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/BaseRightExternal.cs new file mode 100644 index 00000000..626db9e8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/BaseRightExternal.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a single right + /// + public class BaseRightExternal + { + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public string Action { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationCheckResultExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationCheckResultExternal.cs new file mode 100644 index 00000000..863329ed --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationCheckResultExternal.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Response model describing the delegation status for a given single right, whether the authenticated user is able to delegate the right or not on behalf of the from part. + /// + public class RightDelegationCheckResultExternal + { + /// + /// Gets or sets the right key + /// + [Required] + public string RightKey { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource the rights + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + [Required] + public string Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right is delegable or not + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public DelegableStatusExternal Status { get; set; } + + /// + /// Gets or sets a list of details describing why or why not the right is valid in the current user and reportee party context + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List Details { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationExternal.cs new file mode 100644 index 00000000..1b2e798e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationExternal.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models; + +/// +/// Describes the delegation result for a given single right. +/// +public class RightDelegationExternal +{ + /// + /// Specifies who have delegated permissions + /// + [JsonPropertyName("from")] + public List From { get; set; } = []; + + /// + /// Receiver of the permissions + /// + [JsonPropertyName("to")] + public List To { get; set; } = []; + + /// + /// Specifies the permissions + /// + [JsonPropertyName("resource")] + public List Resource { get; set; } = []; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultDto.cs new file mode 100644 index 00000000..75339152 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultDto.cs @@ -0,0 +1,62 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Enums; +using Altinn.Swashbuckle.Examples; +using Altinn.Swashbuckle.Filters; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// This model describes a single right +/// +[SwaggerExampleFromExampleProvider] +public class RightDelegationResultDto : IExampleDataProvider +{ + private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web); + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public IEnumerable Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully delegated or not + /// + public DelegationStatusExternal Status { get; set; } + + /// + /// Example data provider for RightV2 + /// + /// Options + /// + public static IEnumerable GetExamples(ExampleDataOptions options) + { + var json = """ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_apps-test" + }, + { + "type": "urn:altinn:resource:task", + "value": "task_1" + } + ], + "action": + { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegated" + } + """; + yield return JsonSerializer.Deserialize(json, SerializerOptions); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultExternal.cs new file mode 100644 index 00000000..a520a25f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDelegationResultExternal.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Response model describing the delegation result for a given single right, whether the authenticated user was able to delegate the right or not on behalf of the from part. + /// + public class RightDelegationResultExternal + { + /// + /// Gets or sets the right key + /// + [Required] + public string RightKey { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource which the right provides access to + /// + [Required] + public List Resource { get; set; } + + /// + /// Gets or sets the action the right gives access to perform on the resource + /// + [Required] + public string Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully delegated or not + /// + [Required] + [JsonConverter(typeof(JsonStringEnumConverter))] + public DelegationStatusExternal Status { get; set; } + + /// + /// Gets or sets a list of details describing the reason(s) behind the status (if any can be provided) + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List Details { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDto.cs new file mode 100644 index 00000000..d68bbd27 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightDto.cs @@ -0,0 +1,59 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.Swashbuckle.Examples; +using Altinn.Swashbuckle.Filters; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// This model describes a single right +/// +[SwaggerExampleFromExampleProvider] +public class RightDto : IExampleDataProvider +{ + private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web); + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public IEnumerable Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Example data provider for RightV2 + /// + /// Options + /// + public static IEnumerable GetExamples(ExampleDataOptions options) + { + var json = """ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_apps-test" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "0191579e-72bc-7977-af5d-f9e92af4393b" + }, + { + "type": "urn:altinn:resource:task", + "value": "task_1" + } + ], + "action": + { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + """; + yield return JsonSerializer.Deserialize(json, SerializerOptions); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightExternal.cs new file mode 100644 index 00000000..fa3d94bd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightExternal.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a single right including specification of right source information and whether the user have access or delegation access for the right + /// + public class RightExternal : BaseRightExternal + { + /// + /// Gets or sets the right key + /// + public string RightKey { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party has the right + /// + public bool HasPermit { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party is permitted to delegate the right to others + /// + public bool CanDelegate { get; set; } + + /// + /// Gets or sets the set of identified sources providing the right + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List RightSources { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightRevokeResultDto.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightRevokeResultDto.cs new file mode 100644 index 00000000..c2d8c02b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightRevokeResultDto.cs @@ -0,0 +1,62 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Enums; +using Altinn.Swashbuckle.Examples; +using Altinn.Swashbuckle.Filters; +using Altinn.Urn.Json; + +namespace Altinn.AccessManagement.Models; + +/// +/// This model describes a single right +/// +[SwaggerExampleFromExampleProvider] +public class RightRevokeResultDto : IExampleDataProvider +{ + private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web); + + /// + /// Gets or sets the list of resource matches which uniquely identifies the resource this right applies to. + /// + public IEnumerable Resource { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right applies to + /// + public UrnJsonTypeValue Action { get; set; } + + /// + /// Gets or sets a value indicating whether the right was successfully delegated or not + /// + public RevokeStatusExternal Status { get; set; } + + /// + /// Example data provider for RightV2 + /// + /// Options + /// + public static IEnumerable GetExamples(ExampleDataOptions options) + { + var json = """ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_apps-test" + }, + { + "type": "urn:altinn:resource:task", + "value": "task_1" + } + ], + "action": + { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + """; + yield return JsonSerializer.Deserialize(json, SerializerOptions); + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightSourceExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightSourceExternal.cs new file mode 100644 index 00000000..6307f912 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightSourceExternal.cs @@ -0,0 +1,67 @@ +using System.Text.Json.Serialization; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Models +{ + /// + /// This model describes a source from where a right exist for a user or party + /// + public class RightSourceExternal + { + /// + /// Gets or sets the set of type of source this right originated from (Role, AccessGroup, AppDelegation, ResourceRegistryDelegation etc.) + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public RightSourceTypeExternal RightSourceType { get; set; } + + /// + /// Gets or sets the unique identifier for the specific policy the right originates (Output only). + /// + public string PolicyId { get; set; } + + /// + /// Gets or sets the version of the policy which the right originates (Output only). + /// + public string PolicyVersion { get; set; } + + /// + /// Gets or sets the unique identifier for the specific rule within the policy the right originates (Output only). + /// + public string RuleId { get; set; } + + /// + /// Gets or sets the party offering the rights to the receiving (CoveredBy) entity. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public int OfferedByPartyId { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party has the right + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public bool? HasPermit { get; set; } + + /// + /// Gets or sets a value indicating whether the user or party is permitted to delegate the right to others + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public bool? CanDelegate { get; set; } + + /// + /// Gets or sets a value specifying the minimum required authentication level + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public int MinimumAuthenticationLevel { get; set; } + + /// + /// Gets or sets the list of subject matches the user has. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List UserSubjects { get; set; } + + /// + /// Gets or sets the list of subject matches which provides access to this right in the resource policy + /// + public List> PolicySubjects { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationCheckRequestExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationCheckRequestExternal.cs new file mode 100644 index 00000000..d32de9ff --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationCheckRequestExternal.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Request model for a list of all rights for a specific resource, that a user can delegate from a given reportee to a given recipient. + /// + public class RightsDelegationCheckRequestExternal + { + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource of the rights to be checked + /// + [Required] + public List Resource { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationRequestExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationRequestExternal.cs new file mode 100644 index 00000000..00f58f58 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationRequestExternal.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Model for performing a delegation of one or more rights to a recipient. + /// + public class RightsDelegationRequestExternal + { + /// + /// Gets or sets a set of Attribute Id and Attribute Value identfying the single person or entity receiving the delegation + /// + [Required] + public List To { get; set; } + + /// + /// Gets or sets a list of rights which is to be delegated to the recipient. + /// + [Required] + public List Rights { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationResponseExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationResponseExternal.cs new file mode 100644 index 00000000..088183eb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsDelegationResponseExternal.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Response model for the result of a delegation of one or more rights to a recipient. + /// + public class RightsDelegationResponseExternal + { + /// + /// Gets or sets a set of Attribute Id and Attribute Value identfying the single person or entity receiving the delegation + /// + [Required] + public List To { get; set; } + + /// + /// Gets or sets a list of rights delegation results with status wheter the delegation was successfully delegated to the recipient. + /// + [Required] + public List RightDelegationResults { get; set; } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsQueryExternal.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsQueryExternal.cs new file mode 100644 index 00000000..c2aa4aac --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Models/Rights/RightsQueryExternal.cs @@ -0,0 +1,61 @@ +using System.ComponentModel.DataAnnotations; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using AutoMapper; + +namespace Altinn.AccessManagement.Models +{ + /// + /// Queries for a list of all rights between two parties for a specific resource. + /// If coveredby user has any key roles, those party ids should be included in the query to have the 3.0 PIP lookup rights inheirited through those as well. + /// If offeredby is a sub unit, parenty party id should be supplied to include inheirited rights received through the main unit. + /// + public class RightsQueryExternal + { + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the entity having offered rights + /// + [Required] + public List From { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for the entity having received rights + /// + [Required] + public List To { get; set; } + + /// + /// Gets or sets the set of Attribute Id and Attribute Value for identifying the resource the rights + /// + [Required] + public List Resource { get; set; } + + /// + /// Method to convert the external rights query to internal rights query + /// + /// mapper to use for subtypes + /// RightsQuery + public RightsQuery ToRightsQueryInternal(IMapper mapper) + { + return new RightsQuery + { + Type = RightsQueryType.User, + From = mapper.Map>(From), + To = mapper.Map>(To), + Resource = new ServiceResource + { + Identifier = GetResourceIdentifier(Resource), + AuthorizationReference = mapper.Map>(Resource) + } + }; + } + + private static string GetResourceIdentifier(List resource) + { + return resource.Find(r => r.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute)?.Value ?? + $"app_{resource.Find(r => r.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute)?.Value}_{resource.Find(r => r.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute)?.Value}"; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Program.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Program.cs new file mode 100644 index 00000000..300d9dd7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Program.cs @@ -0,0 +1,33 @@ +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement; +using Microsoft.IdentityModel.Logging; + +WebApplication app = AccessManagementHost.Create(args); + +app.AddDefaultAltinnMiddleware(errorHandlingPath: "/accessmanagement/api/v1/error"); + +if (app.Environment.IsDevelopment()) +{ + // Enable higher level of detail in exceptions related to JWT validation + IdentityModelEventSource.ShowPII = true; + + // Enable Swagger + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapControllers(); +app.MapDefaultAltinnEndpoints(); + +await app.RunAsync(); + +/// +/// Startup class. +/// +[ExcludeFromCodeCoverage] +public sealed partial class Program +{ +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Properties/launchSettings.json b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Properties/launchSettings.json new file mode 100644 index 00000000..51da79b9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Properties/launchSettings.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5117", + "sslPort": 0 + } + }, + "profiles": { + "Altinn.AccessManagement": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5117", + "dotnetRunMessages": true + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "publishAllPorts": true + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/HashUtil.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/HashUtil.cs new file mode 100644 index 00000000..a9d2be38 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/HashUtil.cs @@ -0,0 +1,26 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Utilities; + +/// +/// Hash utility class +/// +public static class HashUtil +{ + /// + /// Get a hash code for a list of objects that is order independent + /// + /// The list of objects + /// Hash code for the list + public static int GetOrderIndependentHashCode(IEnumerable source) + { + int hash = 0; + foreach (T element in source) + { + hash = unchecked(hash + EqualityComparer.Default.GetHashCode(element)); + } + + return hash; + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/IdentifierUtil.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/IdentifierUtil.cs new file mode 100644 index 00000000..a040a8f5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/IdentifierUtil.cs @@ -0,0 +1,195 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Utilities +{ + /// + /// Utility class for working with internal and external identifiers + /// + public static class IdentifierUtil + { + private const string PersonHeaderTrigger = "person"; + private const string OrganizationHeaderTrigger = "organization"; + + /// + /// Default HTTP header for SSN input + /// + public const string PersonHeader = "Altinn-Party-SocialSecurityNumber"; + + /// + /// Default HTTP header for Organization number input + /// + public const string OrganizationNumberHeader = "Altinn-Party-OrganizationNumber"; + + /// + /// Validates that a given organization number is valid. + /// + /// + /// Organization number to validate + /// + /// + /// true if valid, false otherwise. + /// + /// + /// Validates length, numeric and modulus 11. + /// + public static bool IsValidOrganizationNumber(string orgNo) + { + int[] weight = { 3, 2, 7, 6, 5, 4, 3, 2 }; + + // Validation only done for 8 and 9 digit numbers + if (orgNo.Length == 9) + { + try + { + int currentDigit = 0; + int sum = 0; + for (int i = 0; i < orgNo.Length - 1; i++) + { + currentDigit = int.Parse(orgNo.Substring(i, 1)); + sum += currentDigit * weight[i]; + } + + int ctrlDigit = 11 - (sum % 11); + if (ctrlDigit == 11) + { + ctrlDigit = 0; + } + + return int.Parse(orgNo.Substring(orgNo.Length - 1)) == ctrlDigit; + } + catch (Exception) + { + return false; + } + } + else + { + return false; + } + } + + /// + /// Validates that a given social security number is valid. + /// + /// + /// Social security number to validate + /// + /// + /// true if valid, false otherwise. + /// + /// + /// Validates length, numeric and modulus 11. + /// + public static bool IsValidSSN(string ssnNo) + { + int[] weightDigit10 = { 3, 7, 6, 1, 8, 9, 4, 5, 2 }; + int[] weightDigit11 = { 5, 4, 3, 2, 7, 6, 5, 4, 3, 2 }; + + // Validation only done for 11 digit numbers + if (ssnNo.Length == 11) + { + try + { + int currentDigit = 0; + int sumCtrlDigit10 = 0; + int sumCtrlDigit11 = 0; + int ctrlDigit10 = -1; + int ctrlDigit11 = -1; + + // Calculate control digits + for (int i = 0; i < 9; i++) + { + currentDigit = int.Parse(ssnNo.Substring(i, 1)); + sumCtrlDigit10 += currentDigit * weightDigit10[i]; + sumCtrlDigit11 += currentDigit * weightDigit11[i]; + } + + ctrlDigit10 = 11 - (sumCtrlDigit10 % 11); + if (ctrlDigit10 == 11) + { + ctrlDigit10 = 0; + } + + sumCtrlDigit11 += ctrlDigit10 * weightDigit11[9]; + ctrlDigit11 = 11 - (sumCtrlDigit11 % 11); + if (ctrlDigit11 == 11) + { + ctrlDigit11 = 0; + } + + // Validate control digits in ssn + bool digit10Valid = ctrlDigit10 == int.Parse(ssnNo.Substring(9, 1)); + bool digit11Valid = ctrlDigit11 == int.Parse(ssnNo.Substring(10, 1)); + return digit10Valid && digit11Valid; + } + catch + { + return false; + } + } + + return false; + } + + /// + /// Masks an incoming SSN. + /// + /// SSN that should be masked + /// Masked SSN + public static string MaskSSN(string input) + { + return string.Concat(input.AsSpan(0, 6), "*****"); + } + + /// + /// Route allowes for specifying the reportee party in the path. + /// This value must either be a PartyId, or the placeholder values: "organization" or "person" + /// if the placeholder value is used the organization number or social security number must be specified in a corresponding header value: "Altinn-Party-OrganizationNumber" or "Altinn-Party-SocialSecurityNumber" + /// + /// The party value from route + /// The httpcontext for getting header values + /// AttributeMatch model representation of the identifier + public static AttributeMatch GetIdentifierAsAttributeMatch(string party, HttpContext context) + { + if (party.Equals(OrganizationHeaderTrigger)) + { + if (!context.Request.Headers.ContainsKey(OrganizationNumberHeader)) + { + throw new ArgumentException($"When using the '{OrganizationHeaderTrigger}' path parameter the organization number must be provided as a request header value: '{OrganizationNumberHeader}'"); + } + + if (!IsValidOrganizationNumber(context.Request.Headers[OrganizationNumberHeader])) + { + throw new ArgumentException($"The request header '{OrganizationNumberHeader}' does not provide a well-formed organization number value: '{context.Request.Headers[OrganizationNumberHeader]}'"); + } + + return new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationNumberAttribute, Value = context.Request.Headers[OrganizationNumberHeader] }; + } + + if (party.Equals(PersonHeaderTrigger)) + { + if (!context.Request.Headers.ContainsKey(PersonHeader)) + { + throw new ArgumentException($"When using the '{PersonHeaderTrigger}' path parameter the national identity number must be provided as a request header value: '{PersonHeader}'"); + } + + if (!IsValidSSN(context.Request.Headers[PersonHeader])) + { + throw new ArgumentException($"The request header '{PersonHeader}' does not provide a well-formed national identity number value: '{context.Request.Headers[PersonHeader]}'"); + } + + return new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.SocialSecurityNumberAttribute, Value = context.Request.Headers[PersonHeader] }; + } + + if (int.TryParse(party, out int partyId) && partyId != 0) + { + return new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = partyId.ToString() }; + } + else + { + throw new ArgumentException($"The party path parameter is not a well-formed party id: '{party}'"); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/MaskinportenSchemaAuthorizer.cs b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/MaskinportenSchemaAuthorizer.cs new file mode 100644 index 00000000..f5f2a190 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/Utilities/MaskinportenSchemaAuthorizer.cs @@ -0,0 +1,51 @@ +using System.Security.Claims; +using Altinn.AccessManagement.Core.Constants; + +namespace Altinn.AccessManagement.Utilities +{ + /// + /// Authorization helper for custom authorization for maskinporten schema API operations + /// + public static class MaskinportenSchemaAuthorizer + { + /// + /// Authorization of whether the provided claims is authorized for lookup of delegations of the given scope + /// + /// The scope to authorize for delegation lookup + /// The claims principal of the authenticated organization + /// bool + public static bool IsAuthorizedDelegationLookupAccess(string scope, ClaimsPrincipal claims) + { + if (HasDelegationsAdminScope(claims)) + { + return true; + } + + return HasAuthorizedScopePrefixClaim(new[] { scope }, claims); + } + + private static bool HasDelegationsAdminScope(ClaimsPrincipal claims) + { + return HasScope(claims, AuthzConstants.SCOPE_MASKINPORTEN_DELEGATIONS_ADMIN); + } + + private static bool HasScope(ClaimsPrincipal claims, string scope) + { + Claim c = claims.Claims.FirstOrDefault(x => x.Type == AuthzConstants.CLAIM_MASKINPORTEN_SCOPE); + if (c == null) + { + return false; + } + + string[] scopes = c.Value.Split(' '); + + return scopes.Contains(scope); + } + + private static bool HasAuthorizedScopePrefixClaim(IEnumerable scopesToAuthorize, ClaimsPrincipal claims) + { + List prefixes = claims.Claims.Where(x => x.Type == AuthzConstants.CLAIM_MASKINPORTEN_CONSUMER_PREFIX).Select(v => v.Value).ToList(); + return scopesToAuthorize.All(scopes => prefixes.Any(prefix => scopes.StartsWith(prefix + ':'))); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.Development.json b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.Development.json new file mode 100644 index 00000000..025f017d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.Development.json @@ -0,0 +1,35 @@ +{ + "PostgreSQLSettings": { + "WorkspacePath": "Altinn.AccessManagement.Persistence/Migration" + }, + "AzureStorageConfiguration": { + "BlobLeaseTimeout": 60 + }, + "SblBridgeSettings": { + "BaseApiUrl": "https://at22.altinn.cloud/sblbridge/" + }, + "PlatformSettings": { + "ApiResourceRegistryEndpoint": "http://localhost:5100/resourceregistry/api/v1/", + "ApiRegisterEndpoint": "http://localhost:5020/register/api/v1/", + "ApiProfileEndpoint": "http://localhost:5030/profile/api/v1/", + "ApiAuthorizationEndpoint": "http://localhost:49723/authorization/api/v1/" + }, + "OidcProviders": { + "altinn": { + "Issuer": "https://platform.at22.altinn.cloud/authentication/api/v1/openid/", + "WellKnownConfigEndpoint": "https://platform.at22.altinn.cloud/authentication/api/v1/openid/.well-known/openid-configuration" + }, + "maskinporten-ver2": { + "Issuer": "https://ver2.maskinporten.no/", + "WellKnownConfigEndpoint": "https://ver2.maskinporten.no/.well-known/oauth-authorization-server" + }, + "maskinporten-test": { + "Issuer": "https://test.maskinporten.no/", + "WellKnownConfigEndpoint": "https://test.maskinporten.no/.well-known/oauth-authorization-server" + } + }, + "FeatureManagement": { + "RightsDelegationApi": true, + "UseNewQueryRepo": true + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.json b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.json new file mode 100644 index 00000000..17165cb7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement/appsettings.json @@ -0,0 +1,69 @@ +{ + "CacheConfig": { + "AltinnRoleCacheTimeout": 5, + "MainUnitCacheTimeout": 5, + "KeyrolePartyIdsCacheTimeout": 5, + "PartyCacheTimeout": 10, + "PolicyCacheTimeout": 10, + "ResourceRegistryResourceCacheTimeout": 10, + "ResourceRegistrySubjectResourcesCacheTimeout": 60, + "RightsCacheTimeout": 5 + }, + "PlatformSettings": { + "ApiAuthenticationEndpoint": "http://localhost:5101/authentication/api/v1/", + "ApiAuthorizationEndpoint": "http://localhost:5101/authorization/api/v1/", + "ApiProfileEndpoint": "http://localhost:5101/profile/api/v1/", + "ApiRegisterEndpoint": "http://localhost:5101/register/api/v1/", + "ApiResourceRegistryEndpoint": "http://localhost:5101/resourceregistry/api/v1/", + "JwtCookieName": "AltinnStudioRuntime", + "SubscriptionKeyHeaderName": "Ocp-Apim-Subscription-Key" + }, + "PostgreSQLSettings": { + "EnableDBConnection": "true", + "WorkspacePath": "Migration", + "AdminConnectionString": "Host=localhost;Port=5432;Username=platform_authorization_admin;Password={0};Database=authorizationdb", + "ConnectionString": "Host=localhost;Port=5432;Username=platform_authorization;Password={0};Database=authorizationdb", + "AuthorizationDbAdminPwd": "Password", + "AuthorizationDbPwd": "Password" + }, + "AzureStorageConfiguration": { + "MetadataAccountName": "devstoreaccount1", + "MetadataAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "MetadataContainer": "metadata", + "MetadataBlobEndpoint": "http://127.0.0.1:10000/devstoreaccount1/", + "DelegationsAccountName": "devstoreaccount1", + "DelegationsAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "DelegationsContainer": "delegationpolicies", + "DelegationsBlobEndpoint": "http://127.0.0.1:10000/devstoreaccount1/", + "ResourceRegistryAccountName": "devstoreaccount1", + "ResourceRegistryAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "ResourceRegistryContainer": "resourceregistry", + "ResourceRegistryBlobEndpoint": "http://127.0.0.1:10000/devstoreaccount1/", + "BlobLeaseTimeout": 15, + "DelegationEventQueueAccountName": "devstoreaccount1", + "DelegationEventQueueAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "DelegationEventQueueEndpoint": "http://127.0.0.1:10000/devstoreaccount1/" + }, + "SblBridgeSettings": { + "BaseApiUrl": "http://localhost:88/sblbridge/" + }, + "GeneralSettings": { + "Hostname": "localhost", + "DisableCsrfCheck": false + }, + "OidcProviders": { + "altinn": { + "Issuer": "http://localhost:5101/authentication/api/v1/openid/", + "WellKnownConfigEndpoint": "http://localhost:5101/authentication/api/v1/openid/.well-known/openid-configuration" + } + }, + "UserProfileLookupSettings": { + "MaximumFailedAttempts": 2, + "FailedAttemptsCacheLifetimeSeconds": 3600 + }, + "FeatureManagement": { + "RightsDelegationApi": false, + "OpenTelementry": false, + "UseNewQueryRepo": true + } +} diff --git a/src/apps/Altinn.AccessManagement/src/Directory.Build.props b/src/apps/Altinn.AccessManagement/src/Directory.Build.props new file mode 100644 index 00000000..7f79d6f5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/src/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + true + true + CS1591 + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/AcceptanceCriteriaComposer.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/AcceptanceCriteriaComposer.cs new file mode 100644 index 00000000..02985ebd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/AcceptanceCriteriaComposer.cs @@ -0,0 +1,174 @@ +using System.Net; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Microsoft.Extensions.DependencyInjection; + +namespace Altinn.AccessManagement.Tests; + +/// +/// Sets up tests and teardown tests for controller tests +/// +public abstract class AcceptanceCriteriaComposer +{ + /// + /// ctor + /// + /// acceptance criteria + /// list of functional object mutators provided to parent class + /// list of functional object mutators provided from parent class + public AcceptanceCriteriaComposer(string acceptanceCriteria, Action[] parent, params Action[] actions) + { + AcceptanceCriteria = acceptanceCriteria; + foreach (var action in actions.Concat(parent)) + { + action(this); + } + } + + /// + /// List of Scenarios + /// + public List Scenarios { get; set; } = []; + + /// + /// List of Assertions for HTTP assertions + /// + public List> ResponseAssertions { get; set; } = []; + + /// + /// List of API assertions for mock context and DB + /// + public List> ApiAssertions { get; set; } = []; + + /// + /// Http request to be sent to the controller action + /// + public HttpRequestMessage Request { get; set; } = new(); + + /// + /// Acceptance criteria for the test + /// + protected string AcceptanceCriteria { get; } + + /// + /// Sets Request URI + /// + public string RequestUri { get; set; } + + /// + /// Asserts response given from API + /// + public async Task AssertResponse(HttpResponseMessage message) + { + foreach (var assertion in ResponseAssertions) + { + await assertion(message); + } + } + + /// + /// Asserts mock call and DB + /// + /// Web application fixture + public async Task AssertApi(Host host) + { + foreach (var assertion in ApiAssertions) + { + await assertion(host); + } + } + + /// + /// Asserts that response has given status code. + /// + /// HTTP status code + /// + public static Action WithAssertResponseStatusCode(HttpStatusCode code) => test => + { + test.ResponseAssertions.Add(response => + { + Assert.Equal(code, response.StatusCode); + return Task.CompletedTask; + }); + }; + + /// + /// Asserts that response given from API is a successful status code. + /// + public static void WithAssertResponseStatusCodeSuccessful(AcceptanceCriteriaComposer test) + { + test.ResponseAssertions.Add(response => + { + Assert.True(response.IsSuccessStatusCode, $"expected successful status code, got status code {(int)response.StatusCode}: {response.StatusCode}"); + return Task.CompletedTask; + }); + } + + /// + /// Seeds the DB and creates the mock context for the integrations. + /// + /// list of scenarions + /// + public static Action WithScenarios(params Scenario[] scenarios) => test => + { + test.Scenarios.AddRange(scenarios); + }; + + /// + /// Http request route + /// + /// list of URL segments + public static Action WithRequestRoute(params object[] segments) => test => + { + test.RequestUri = string.Join("/", segments.Select(segment => segment.ToString().Trim('/'))); + }; + + /// + /// Sets the HTTP request method + /// + public static Action WithRequestVerb(HttpMethod method) => test => + { + test.Request.Method = method; + }; + + /// + /// Deserialize the paylaod and sends the content as JSON and adds the + /// content type header 'application/json' + /// + /// object to deserialize + public static Action WithHttpRequestBodyJson(T body) + where T : class => test => + { + var content = JsonSerializer.Serialize(body); + test.Request.Content = new StringContent(content, Encoding.UTF8, MediaTypeNames.Application.Json); + }; + + /// + /// Runs tests + /// + /// web application fixture + public async Task Test(WebApplicationFixture fixture) + { + var host = fixture.ConfigureHostBuilderWithScenarios([.. Scenarios]); + Request.RequestUri = new Uri(host.Client.BaseAddress, RequestUri); + + foreach (var seed in host.Mock.DbSeeds) + { + await seed(host.Api.Services.GetRequiredService()); + } + + await AssertResponse(await host.Client.SendAsync(Request)); + await AssertApi(host); + } + + /// + /// Return Acceptance Criteria + /// + public new string ToString() + { + return AcceptanceCriteria; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Altinn.AccessManagement.Tests.csproj b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Altinn.AccessManagement.Tests.csproj new file mode 100644 index 00000000..14379975 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Altinn.AccessManagement.Tests.csproj @@ -0,0 +1,52 @@ + + + + false + CS1591;SA1600;SA1649 + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AsserterTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AsserterTests.cs new file mode 100644 index 00000000..cbc0f65e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AsserterTests.cs @@ -0,0 +1,16 @@ +using Altinn.AccessManagement.Core.Asserters; + +namespace Altinn.AccessManagement.Tests.Asserters; + +/// +/// summary +/// +public class AsserterTests +{ + /// + /// summary + /// + /// + /// + public static IAssert Asserter() => new Asserter(); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AttributeMatchAsserterTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AttributeMatchAsserterTests.cs new file mode 100644 index 00000000..f64a8190 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Asserters/AttributeMatchAsserterTests.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using Altinn.AccessManagement.Core.Asserters; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Resolvers; +using Microsoft.AspNetCore.Mvc; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Asserters; + +/// +/// summary +/// +public class AttributeMatchAsserterTests +{ + /// + /// summary + /// + [Theory] + [MemberData(nameof(DefaultToCases), MemberType = typeof(AttributeMatchAsserterTests))] + public void DefaultTo(IEnumerable values, Action assert) + { + var asserter = AsserterTests.Asserter(); + + var result = asserter.Evaluate(values, asserter.DefaultTo); + + assert(result); + } + + /// + /// summary + /// + public static TheoryData, Action> DefaultToCases => + new() + { + { + [new(BaseUrn.Altinn.Person.IdentifierNo, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Person.UserId, "123")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.IdentifierNo, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.PartyId, "321")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.PartyId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Resource.ResourceRegistryId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Organization.IdentifierNo, ""), new(BaseUrn.Altinn.Resource.AppId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Person.IdentifierNo, string.Empty)], + Assert.NotNull + } + }; + + /// + /// summary + /// + [Theory] + [MemberData(nameof(DefaultFromCases), MemberType = typeof(AttributeMatchAsserterTests))] + public void DefaultFrom(IEnumerable values, Action assert) + { + var asserter = AsserterTests.Asserter(); + + var result = asserter.Evaluate(values, asserter.DefaultTo); + + assert(result); + } + + /// + /// summary + /// + public static TheoryData, Action> DefaultFromCases => + new() + { + { + [new(BaseUrn.Altinn.Person.IdentifierNo, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Person.UserId, "123")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.IdentifierNo, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.PartyId, "321")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Organization.PartyId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Resource.ResourceRegistryId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Organization.IdentifierNo, ""), new(BaseUrn.Altinn.Resource.AppId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Person.IdentifierNo, string.Empty)], + Assert.NotNull + } + }; + + /// + /// summary + /// + [Theory] + [MemberData(nameof(DefaultResourceCases), MemberType = typeof(AttributeMatchAsserterTests))] + public void DefaultResource(IEnumerable values, Action assert) + { + var asserter = AsserterTests.Asserter(); + + var result = asserter.Evaluate(values, asserter.DefaultResource); + + assert(result); + } + + /// + /// summary + /// + public static TheoryData, Action> DefaultResourceCases => + new() + { + { + [new(BaseUrn.Altinn.Resource.AppOwner, ""), new(BaseUrn.Altinn.Resource.AppId, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Resource.ResourceRegistryId, "")], + Assert.Null + }, + { + [new(BaseUrn.Altinn.Resource.ResourceRegistryId, ""), new(BaseUrn.Altinn.Organization.IdentifierNo, ""), new(BaseUrn.Altinn.Resource.AppId, "")], + Assert.NotNull + }, + { + [new(BaseUrn.Altinn.Resource.ResourceRegistryId, string.Empty)], + Assert.NotNull + } + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/MockContext.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/MockContext.cs new file mode 100644 index 00000000..96f9361e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/MockContext.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Contexts; + +/// +/// A wrapper class used by mock implementation for getting data +/// +public class MockContext +{ + /// + /// ctor + /// + public MockContext(params Action[] values) + { + foreach (var value in values) + { + value(this); + } + } + + /// + /// List of mock resources + /// + public List Resources { get; set; } = []; + + /// + /// Dictionary of mock subject resources + /// + public IDictionary> SubjectResources { get; set; } = new Dictionary>(); + + /// + /// List of mock parties + /// + public List Parties { get; set; } = []; + + /// + /// List of mock user profiles + /// + public List UserProfiles { get; set; } = []; + + /// + /// Dictionary of mainunits. Where key is partyid of the subunit and values are the main units. + /// + public Dictionary MainUnits { get; set; } = []; + + /// + /// Dictionary of keyroles where the key is userid and value a list of party ids. + /// + /// + public Dictionary> KeyRoles { get; set; } = []; + + /// + /// JWT token. + /// + public IDictionary HttpHeaders { get; set; } = new Dictionary(); + + /// + /// A list of Db seed functation that are executed after database has been migrated. + /// + public List> DbSeeds { get; } = []; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/PartiesClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/PartiesClientMock.cs new file mode 100644 index 00000000..74f3a3c8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/PartiesClientMock.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Contexts; + +/// +public class PartiesClientMock(MockContext context) : IPartiesClient +{ + private MockContext Context { get; } = context; + + /// + public Task> GetKeyRoleParties(int userId, CancellationToken cancellationToken = default) + { + Context.KeyRoles.TryGetValue(userId, out var result); + return Task.FromResult(result); + } + + /// + public Task> GetMainUnits(MainUnitQuery subunitPartyIds, CancellationToken cancellationToken = default) => + Task.FromResult(subunitPartyIds.PartyIds + .Where(Context.MainUnits.ContainsKey) + .Select(party => Context.MainUnits[party]) + .ToList()); + + /// + public Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default) => + Task.FromResult(Context.Parties.Where(party => partyIds.Contains(party.PartyId)).ToList()); + + /// + public Task> GetPartiesAsync(List partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default) => + Task.FromResult(Context.Parties.Where(party => partyUuids.Contains(party.PartyUuid ?? Guid.Empty)).ToList()); + + /// + public Task> GetPartiesForUserAsync(int userId, CancellationToken cancellationToken = default) => + Task.FromResult(Context.UserProfiles.Where(user => user.UserId == userId).Select(user => user.Party).ToList()); + + /// + public Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default) => + Task.FromResult(Context.Parties.FirstOrDefault(party => party.PartyId == partyId)); + + /// + public Task LookupPartyBySSNOrOrgNo(PartyLookup partyLookup, CancellationToken cancellationToken = default) => + Task.FromResult(Context.Parties.FirstOrDefault(party => party.SSN == partyLookup.Ssn || party.OrgNumber == partyLookup.OrgNo)); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ProfileClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ProfileClientMock.cs new file mode 100644 index 00000000..1f3b972d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ProfileClientMock.cs @@ -0,0 +1,22 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Tests.Contexts; + +/// +public class ProfileClientMock(MockContext context) : IProfileClient +{ + private MockContext Context { get; } = context; + + /// + public Task GetUser(UserProfileLookup userProfileLookup, CancellationToken cancellationToken = default) => + Task.FromResult(Context.UserProfiles.FirstOrDefault(profile => + profile.UserId == userProfileLookup.UserId || + profile.UserName == userProfileLookup.Username || + profile.Party.SSN == userProfileLookup.Ssn || + profile.UserUuid == userProfileLookup.UserUuid)); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ResourceRegistryMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ResourceRegistryMock.cs new file mode 100644 index 00000000..f670fc2c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Contexts/ResourceRegistryMock.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Tests.Contexts; + +/// +/// ResourceRegistryMock +/// +public class ResourceRegistryMock(MockContext context) : IResourceRegistryClient +{ + private MockContext Context { get; } = context; + + /// + public Task GetResource(string resourceId, CancellationToken cancellationToken = default) => + Task.FromResult(Context.Resources.FirstOrDefault(resource => resource.Identifier == resourceId)); + + /// + public Task> GetResourceList(CancellationToken cancellationToken = default) => + Task.FromResult(Context.Resources); + + /// + public Task> GetResources(CancellationToken cancellationToken = default) => + Task.FromResult(Context.Resources); + + /// + public Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default) => + Task.FromResult(Context.SubjectResources); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/Altinn2RightsControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/Altinn2RightsControllerTest.cs new file mode 100644 index 00000000..30ed0c4e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/Altinn2RightsControllerTest.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Utilities; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// Controller test for +/// +public class Altinn2RightsControllerTest : IClassFixture> +{ + private readonly CustomWebApplicationFactory _factory; + + private readonly string sblInternalToken = PrincipalUtil.GetAccessToken("sbl.authorization"); + + private readonly JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public Altinn2RightsControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + } + + /// + /// Tests + /// + [Theory] + [MemberData(nameof(GetGivenDelegations_ReturnOk_Input))] + public async Task GetGivenDelegations_ReturnOk(string header, string value, Action assert) + { + var client = NewDefaultClient(WithHeader(header, value)); + + var response = await client.GetAsync($"internal/{GetUrlParameter(header, value)}/rights/delegation/offered"); + + assert(response); + } + + /// + /// Case 1. List delegations from an organization to person using their orgnumber + /// Case 2. List delegations from an organization to person using their partyid + /// Case 3. List delegations from a person to org with no keyroles using their ssn + /// Case 4. List delegations from a person to org with keyroles using their ssn + /// Case 5. List delegations from a person to org with no keyroles using their partyid + /// + public static TheoryData> GetGivenDelegations_ReturnOk_Input() => new() + { + { + string.Empty, "50005545", response => Assertions( + AssertFromContains(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "50005545"), + AssertToContains(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "20000095"), + AssertStatusCode(HttpStatusCode.OK)) + }, + { + string.Empty, "50002203", Assertions( + AssertFromContains(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "50002203"), + AssertToContains(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "50005545"), + AssertStatusCode(HttpStatusCode.OK)) + } + }; + + /// + /// Tests + /// + [Theory] + [MemberData(nameof(GetReceviedDelegations_ReturnOk_Input))] + public async Task GetReceviedDelegations_ReturnOk(string header, string value, Action assert) + { + var client = NewDefaultClient(WithHeader(header, value)); + + var response = await client.GetAsync($"internal/{GetUrlParameter(header, value)}/rights/delegation/received"); + + assert(response); + } + + /// + /// Case 1. List all delegations to an organization using orgnumber "" + /// Case 2. List all delegations to an organization using party "" + /// Case 3. List all delegations to a person "" with no keyroles using ssn + /// Case 4. List all delegations to a person "" with keyroles using ssn + /// Case 5. List all delegations to a person with no keyroles using partyid + /// + public static TheoryData> GetReceviedDelegations_ReturnOk_Input() => new() + { + { + string.Empty, "50005545", Assertions( + AssertFromContains(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "50002203"), + AssertToContains(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "50005545"), + AssertStatusCode(HttpStatusCode.OK)) + }, + }; + + /// + /// Tests + /// + [Theory] + [MemberData(nameof(ClearAccessCache_ReturnOk_input))] + public async Task ClearAccessCache_ReturnOk(string authnUserToken, int party, BaseAttributeExternal toAttribute, Action assert) + { + var client = NewClient(NewServiceCollection(WithServiceMoq), WithClientRoute("accessmanagement/api/v1/")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authnUserToken); + + HttpResponseMessage response = await client.PutAsync($"internal/{party}/accesscache/clear", new StringContent(JsonSerializer.Serialize(toAttribute), Encoding.UTF8, MediaTypeNames.Application.Json)); + + assert(response); + } + + /// + /// Test case: PUT internal/{party}/accesscache/clear + /// with the authenticated user being an authorized Administrator for the {party} + /// Expected: - Should return 200 OK + /// Reason: Authenticated users which authorized as Administrator/Main Administrator for the {party} should be allowed to clear access cache for recipient + /// + public static TheoryData> ClearAccessCache_ReturnOk_input() => new() + { + { + PrincipalUtil.GetToken(20000490, 50002598, 3), // Kasper B�rstad + 50002598, // From Kasper + new BaseAttributeExternal { Type = BaseUrn.Altinn.Person.Uuid, Value = "00000000-0000-0000-0005-000000003899" }, // To �rjan Ravn�s + AssertStatusCode(HttpStatusCode.OK) + }, + { + PrincipalUtil.GetToken(20000490, 50002598, 3), // Kasper B�rstad + 50002598, // From Kasper + new BaseAttributeExternal { Type = BaseUrn.Altinn.Organization.Uuid, Value = "00000000-0000-0000-0005-000000004222" }, // To KARLSTAD OG ULOYBUKT + AssertStatusCode(HttpStatusCode.OK) + }, + { + PrincipalUtil.GetToken(20000490, 50002598, 3), // Kasper B�rstad + 50005545, // From �rsta + new BaseAttributeExternal { Type = BaseUrn.Altinn.EnterpriseUser.Uuid, Value = "00000000-0000-0000-0002-000000010727" }, // To OrstaECUser + AssertStatusCode(HttpStatusCode.OK) + } + }; + + /// + /// Tests + /// + [Theory] + [MemberData(nameof(ClearAccessCache_ReturnBadRequest_input))] + public async Task ClearAccessCache_ReturnBadRequest(string authnUserToken, int party, BaseAttributeExternal toAttribute, Action assert) + { + var client = NewClient(NewServiceCollection(WithServiceMoq), WithClientRoute("accessmanagement/api/v1/")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authnUserToken); + + HttpResponseMessage response = await client.PutAsync($"internal/{party}/accesscache/clear", new StringContent(JsonSerializer.Serialize(toAttribute), Encoding.UTF8, MediaTypeNames.Application.Json)); + + assert(response); + } + + /// + /// Test case: PUT internal/{party}/accesscache/clear + /// with the authenticated user being an Administrator for the {party} + /// where input attribute does not contain a well-formatted uuid + /// Expected: - Should return 400 BadRequest + /// + public static TheoryData> ClearAccessCache_ReturnBadRequest_input() => new() + { + { + PrincipalUtil.GetToken(20000490, 50002598, 3), // Kasper B�rstad + 50002598, // From Kasper + new BaseAttributeExternal { Type = BaseUrn.Altinn.Person.Uuid, Value = "asdf" }, // To not a well-formated uuid + AssertStatusCode(HttpStatusCode.BadRequest) + }, + { + PrincipalUtil.GetToken(20000490, 50002598, 3), // Kasper B�rstad + 50005545, // From �rsta + new BaseAttributeExternal { Type = BaseUrn.Altinn.Organization.Uuid, Value = "123" }, // To not a well-formated uuid + AssertStatusCode(HttpStatusCode.BadRequest) + } + }; + + private static Action Assertions(params Action[] assertions) => response => + { + foreach (var assertion in assertions) + { + assertion(response); + } + }; + + private static Action AssertStatusCode(HttpStatusCode expected) => response => + { + Assert.Equal(expected, response.StatusCode); + }; + + private static Action AssertToContains(string type, string value) => response => + { + var content = response.Content.ReadAsStringAsync().Result; + var models = JsonSerializer.Deserialize>(content); + + foreach (var model in models) + { + foreach (var attribute in model.To) + { + if (attribute.Id.Equals(type, StringComparison.InvariantCultureIgnoreCase) && attribute.Value.Equals(value)) + { + return; + } + } + } + + Assert.Fail($"Failed to find any attributes in the field 'To' with type '{type}' and value '{value}'"); + }; + + private static Action AssertFromContains(string type, string value) => response => + { + var content = response.Content.ReadAsStringAsync().Result; + var models = JsonSerializer.Deserialize>(content); + + foreach (var model in models) + { + foreach (var attribute in model.From) + { + if (attribute.Id.Equals(type, StringComparison.InvariantCultureIgnoreCase) && attribute.Value.Equals(value)) + { + return; + } + } + } + + Assert.Fail($"Failed to find any attributes in the field 'From' with type '{type}' and value '{value}'"); + }; + + private WebApplicationFactory NewServiceCollection(params Action[] actions) + { + return _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + foreach (var action in actions) + { + action(services); + } + }); + }); + } + + private HttpClient NewDefaultClient(params Action[] actions) => + NewClient(NewServiceCollection(WithServiceMoq), [WithClientToken(), WithClientRoute("accessmanagement/api/v1/"), .. actions]); + + private static HttpClient NewClient(WebApplicationFactory factory, params Action[] actions) + { + var client = factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + foreach (var action in actions) + { + action(client); + } + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + return client; + } + + private static void WithServiceMoq(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(new DelegationChangeEventQueueMock()); + } + + private static string GetUrlParameter(string header, object value) => header switch + { + IdentifierUtil.OrganizationNumberHeader => "organization", + IdentifierUtil.PersonHeader => "person", + _ => value.ToString(), + }; + + private static Action WithHeader(string header, object value) => client => + { + if (!string.IsNullOrEmpty(header)) + { + client.DefaultRequestHeaders.Add(header, value.ToString()); + } + }; + + private static Action WithClientRoute(string route) => client => + { + client.BaseAddress = new Uri(client.BaseAddress, route); + }; + + private static void WithClientAcceptContentTypeJson(HttpClient client) => + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); + + private static Action WithClientToken(int userId = 20001337, int partyId = 50002203, int authenticationLevel = 3) => client => + { + var token = PrincipalUtil.GetToken(userId, partyId, authenticationLevel); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/AuthorizedPartiesControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/AuthorizedPartiesControllerTest.cs new file mode 100644 index 00000000..4f1a832f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/AuthorizedPartiesControllerTest.cs @@ -0,0 +1,234 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Text.Json; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Tests.Data; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// Test class for +/// +[Collection("AuthorizedPartiesController Tests")] +public class AuthorizedPartiesControllerTest : IClassFixture> +{ + private readonly CustomWebApplicationFactory _factory; + private readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public AuthorizedPartiesControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + } + + /// + /// Test case: GET /authorizedparties?includeAltinn2={includeAltinn2} + /// for an unauthenticated user + /// Expected: - Should return 401 Unauthorized + /// Reason: Operation requires valid user authentication + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.UnauthenticatedNoValidToken), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.UnauthenticatedValidTokenMissingUserContext), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParties_UnauthenticatedUser_Unauthorized(string userToken) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/authorizedparties?includeAltinn2={true}"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GET /authorizedparty/{partyId}?includeAltinn2={includeAltinn2} + /// for an unauthenticated user + /// Expected: - Should return 401 Unauthorized + /// Reason: Operation requires valid user authentication + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.UnauthenticatedNoValidToken), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.UnauthenticatedValidTokenMissingUserContext), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParty_UnauthenticatedUser_Unauthorized(string userToken) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/authorizedparty/{123}?includeAltinn2={true}"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GET /authorizedparties?includeAltinn2={includeAltinn2} + /// with an authenticated user + /// Expected: - Should return 200 OK + /// - Should return the expected list of authorized party models + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.PersonToPerson), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.PersonToPersonInclA2), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.PersonToOrg), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.PersonToOrgInclA2), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.MainUnitAndSubUnitToPerson), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.MainUnitAndSubUnitToPersonInclA2), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.MainUnitAndSubUnitToOrg), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.MainUnitAndSubUnitToOrgInclA2), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.SubUnitToPerson), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParties_AuthenticatedUser_Ok(string userToken, bool includeAltinn2, List expected) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/authorizedparties?includeAltinn2={includeAltinn2}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertCollections(expected, actual, TestDataAuthorizedParties.AssertAuthorizedPartyExternalEqual); + } + + /// + /// Test case: GET /authorizedparty/{partyId}?includeAltinn2={includeAltinn2} + /// with an authenticated user + /// Expected: - Should return 200 OK + /// - Should return the expected authorized party model + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.PersonGettingSelfInclA2_Success), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.PersonGettingA3Delegator_Success), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.PersonGettingA3DelegatorInclA2_Success), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParty_AuthenticatedUser_Ok(string userToken, int partyId, bool includeAltinn2, AuthorizedPartyExternal expected) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/authorizedparty/{partyId}?includeAltinn2={includeAltinn2}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + AuthorizedPartyExternal actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + TestDataAuthorizedParties.AssertAuthorizedPartyExternalEqual(expected, actual); + } + + /// + /// Test case: GET /authorizedparty/{partyId}?includeAltinn2={includeAltinn2} + /// with an authenticated user + /// Expected: - Should return 400 BadRequest + /// - Should return the expected ValidationProblemDetails response + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.PersonGettingSelf_BadRequest), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParty_AuthenticatedUser_BadRequest(string userToken, int partyId, bool includeAltinn2, ValidationProblemDetails expected) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/authorizedparty/{partyId}?includeAltinn2={includeAltinn2}"); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertValidationProblemDetailsEqual(expected, actual); + } + + /// + /// Test case: GET {party}/authorizedparties?includeAltinn2={includeAltinn2} + /// with an authenticated and authorized Access Manager for the {party} + /// Expected: - Should return 200 OK + /// - Should return the expected list of authorized party models + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.PersonGettingOwnList_Success), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.AccessManagerGettingOrgList_Success), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParties_AsAccessManager_Ok(string userToken, int partyId, bool includeAltinn2, List expected) + { + var client = GetTestClient(userToken, WithPDPMock); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/{partyId}/authorizedparties?includeAltinn2={includeAltinn2}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertCollections(expected, actual, TestDataAuthorizedParties.AssertAuthorizedPartyExternalEqual); + } + + /// + /// Test case: GET {party}/authorizedparties?includeAltinn2={includeAltinn2} + /// with an authenticated and authorized Access Manager for the {party} which is a person + /// Expected: - Should return 403 Forbidden + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.AccessManagerGettingPersonList_Forbidden), MemberType = typeof(TestDataAuthorizedParties))] + public async Task GetAuthorizedParties_AsAccessManager_Forbidden(string userToken, int partyId, bool includeAltinn2) + { + var client = GetTestClient(userToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/{partyId}/authorizedparties?includeAltinn2={includeAltinn2}"); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + private static void WithPDPMock(IServiceCollection services) => services.AddSingleton(new PepWithPDPAuthorizationMock()); + + private HttpClient GetTestClient(string token, params Action[] actions) + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + foreach (var action in actions) + { + action(services); + } + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + return client; + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/DelegationsControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/DelegationsControllerTest.cs new file mode 100644 index 00000000..3e353bae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/DelegationsControllerTest.cs @@ -0,0 +1,1633 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers +{ + /// + /// Test class for + /// + [Collection("DelegationController Tests")] + public class DelegationsControllerTest : IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + private HttpClient _client; + + private readonly JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public DelegationsControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _client = GetTestClient(); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + string token = PrincipalUtil.GetAccessToken("sbl.authorization"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a valid deletion of org1/app3 + /// Expected: DeleteRules returns status code 201 and list of rules created match expected + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to perform a valid deletion + /// Input: + /// List of two one rule in one policy for deletion of the app org1/app3 between for a single offeredby/coveredby combination resulting in a single policyfile beeing updated. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// DeleteRules returns status code 201 and list of rules deleted to match expected + /// + [Fact] + public async Task Post_DeleteRules_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a valid deletion of resourceRegistryId + /// Expected: DeleteRules returns status code 201 and list of rules created match expected + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to perform a valid deletion + /// Input: + /// List of two one rule in one policy for deletion of the resource between for a single offeredby/coveredby combination resulting in a single policyfile beeing updated. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// DeleteRules returns status code 201 and list of rules deleted to match expected + /// + [Fact] + public async Task Post_DeleteResourceRegistryRules_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadResource2_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", null, null, createdSuccessfully: true, resourceRegistryId: "resource2"), + }; + + string expectedRuleId = "99e5cced-3bcb-42b6-9089-63c834f89e77"; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(actual[0].RuleId, expectedRuleId); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a valid deletion of org1/app3 + /// Expected: DeleteRules returns status code 206 and list of rules created match expected one of the rules does not exist + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to perform a valid deletion and one not existing + /// Input: + /// List of two one rule in one policy for deletion of the app org1/app3 between for a single offeredby/coveredby combination resulting in a single policyfile beeing updated. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule id deleted + /// Success Criteria: + /// DeleteRules returns status code 206 and list of rules deleted to match expected (one rule) + /// + [Fact] + public async Task Post_DeleteRulesNotExistingRuleId_PartialSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337RuleIdDoesNotExist.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a valid deletion of org1/app3 without a valid bearertoken + /// Expected: DeleteRules returns status code 401 + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to perform a valid deletion + /// Input: + /// List of two one rule in one policy for deletion of the app org1/app3 between for a single offeredby/coveredby combination resulting in a single policyfile beeing updated. + /// Expected Result: + /// Responce declined as it is not Authorized + /// Success Criteria: + /// DeleteRules returns status code 401 + /// + [Fact] + public async Task Post_DeleteRules_WithoutAuthorization() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "ThisIsNotAValidToken"); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a valid deletion of org1/app3 org1/app4 org1/app8 + /// Expected: DeleteRules returns status code 206 and list of rules created match expected + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to perform a valid deletion but one of the policy files was not found and some rules was therfore not deleted + /// Input: + /// List of four rules for deletion spread accross 3 policy files of the app org1/app3 org1/app4 and org1/app8 between for a single offeredby/coveredby combination resulting in two policyfile beeing updated. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule ids but not all rules is retuned + /// Success Criteria: + /// DeleteRules returns status code 206 and list of rules dleted to match expected + /// + [Fact] + public async Task Post_DeleteRules_OnePolicyMissing_PartialSucess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3App4App8_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app4", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app4", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a deletion of org1/app4 and org1/app3 without rules defined + /// Expected: DeleteRules returns status code 500 and no list of rules as one of the policies had no ruleids defined + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to delete rules without giving a RuleId + /// Input: + /// List of three rules for delegation of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting in no policy file beeing updated. + /// Expected Result: + /// No Rules are deleted and no rules are returned + /// Success Criteria: + /// DeleteRules returns status code 500 and no deletion is performed + /// + [Fact] + public async Task Post_DeleteRules_InvalidInput_BadRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoRule.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + List actual = null; + try + { + actual = (List)JsonSerializer.Deserialize(responseContent, typeof(List)); + } + catch + { + // do nothing this is expected + } + + Assert.Null(actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a deletion of org1/app4 and org1/app3 where the user performing the task is not defined + /// Expected: DeleteRules returns status code 500 and no list of rules as one of the policies had no DeletedByUser set (0) + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to delete rules without giving a DeletedByUserId + /// Input: + /// List of three rules for delegation of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting in no policy file beeing updated. + /// Expected Result: + /// No Rules are deleted and no rules are returned + /// Success Criteria: + /// DeleteRules returns status code 500 and no deletion is performed + /// + [Fact] + public async Task Post_DeleteRules_InvalidUserPerformingDeleteRule_BadRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string errormessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal("Not all RequestToDelete has a value for the user performing the delete", errormessage); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a deletion of org1/app4 and org1/app3 where the user performing the task is not defined + /// Expected: DeleteRules returns status code 500 and no list of rules as one of the policies had no DeletedByUser set (0) + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to delete rules without giving a DeletedByUserId + /// Input: + /// List of three rules for delegation of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting in no policy file beeing updated. + /// Expected Result: + /// No Rules are deleted and no rules are returned + /// Success Criteria: + /// DeleteRules returns status code 500 and no deletion is performed + /// + [Fact] + public async Task Post_DeletePolicies_InvalidUserPerformingDeleteRule_BadRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string errorMessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal("Not all RequestToDelete has a value for the user performing the delete", errorMessage); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a deletion of org1/app4 and org1/app3 without rules defined + /// Expected: DeleteRules returns status code 500 and no list of rules as one of the policies had no ruleids defined + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to delete rules without giving a RuleId + /// Input: + /// List of three rules for delegation of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting in no policy file beeing updated. + /// Expected Result: + /// No Rules are deleted and no rules are returned + /// Success Criteria: + /// DeleteRules returns status code 500 and no deletion is performed + /// + [Fact] + public async Task Post_DeleteRules_ValidInputAllFails_BadRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + List actual = null; + try + { + actual = (List)JsonSerializer.Deserialize(responseContent, typeof(List)); + } + catch + { + // do nothing this is expected + } + + Assert.Null(actual); + } + + /// + /// Test case: Calling the POST operation for DeleteRules to perform a deletion of org1/app3 with difrent rules on same policy declared in two requests + /// Expected: DeleteRules returns status code 500 and no list of rules as the same policy was tried to delete from twice + /// + /// Scenario: + /// Calling the POST operation for DeleteRules to delete rules giving the dame policy twice + /// Input: + /// List of two rules for deletion of the app org1/app3 for a single offeredby/coveredby combination resulting in no policy file beeing updated. + /// Expected Result: + /// No Rules are deleted and no rules are returned + /// Success Criteria: + /// DeleteRules returns status code 500 and no deletion is performed + /// + [Fact] + public async Task Post_DeleteRules_DuplicatePolicy_BadRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337_DuplicatePolicy.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeleteRules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string errorMessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal("Input should not contain any duplicate policies", errorMessage); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a valid deletion of org1/app3 org1/app4 + /// Expected: DeletePolicy returns status code 201 and list of rules created match expected + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of 2 policy files of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting in all rules in two policyfile beeing removed. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule ids but not all rules is retuned + /// Success Criteria: + /// DeleteRules returns status code 201 and list of rules deleted to match expected + /// + [Fact] + public async Task Post_DeletePolicies_Sucess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app4", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app4", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a valid deletion of resource 1 and resource2 + /// Expected: DeletePolicy returns status code 201 and list of rules created match expected + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of 2 policy files of resource1 and resource2 between for a single offeredby/coveredby combination resulting in all rules in two policyfile beeing removed. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule ids but not all rules is retuned + /// Success Criteria: + /// DeleteRules returns status code 201 and list of rules deleted to match expected + /// + [Fact] + public async Task Post_DeletePoliciesWithResourceRegistryId_Sucess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadResource1Resource2_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, null, createdSuccessfully: true, resourceRegistryId: "resource2"), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", null, null, createdSuccessfully: true, resourceRegistryId: "resource2"), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform an invalid deletion of a non-existing resource. + /// Expected: DeletePolicy returns status code 400 and the error message "Unable to complete deletion". + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform an invalid deletion + /// Input: + /// Resource with a non existing resource registry id. + /// Expected Result: + /// Response contains error message. + /// Success Criteria: + /// DeleteRules returns status code 400 + /// + [Fact] + public async Task Post_DeletePoliciesWithNotExistingResourceRegistryId_Fail() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadNotExistingResourceRegistryId.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + string expectedErrorMessage = "\"Unable to complete deletion\""; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(responseContent, expectedErrorMessage); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a valid deletion of org1/app3 with invalid Authorization token + /// Expected: DeletePolicy returns status code 401 + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion withot valid bearertoken + /// Input: + /// List of 2 policy files of the app org1/app3 and org1/app4 between for a single offeredby/coveredby combination resulting Http Unauthorized + /// Expected Result: + /// Nothing is performed and responce has UnAuthorized responcecode + /// Success Criteria: + /// DeleteRules returns status code 401 + /// + [Fact] + public async Task Post_DeletePolicies_InvalidBearerToken_Unauthorized() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "ThisIsNotAValidToken"); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a valid deletion of org1/app3 org1/app4 and one who does not exixt org1/app8 + /// Expected: DeletePolicy returns status code 206 and list of rules deleted match expected + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of 3 policy files of the app org1/app3 and org1/app4 and org1/app8 between for a single offeredby/coveredby combination resulting in two policyfile beeing updated. + /// Expected Result: + /// Rules are deleted and returned with the CreatedSuccessfully flag set and rule in defoned policy files but not all policyfiles was touched so only rules from updated policyfiles is returned + /// Success Criteria: + /// DeletePolicy returns status code 206 and list of rules deleted to match expected + /// + [Fact] + public async Task Post_DeletePolicies_OneMissingPolicyFile_PartialSucess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App3App4App8_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app4", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app4", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a valid deletion of org1/app8 error/postgrewritechangefail + /// Expected: DeletePolicy returns status code 500 + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of four rules for deletion spread accross 2 policy files of the app org1/app8 and error/postgrewritechangefail between for a single offeredby/coveredby combination. + /// Expected Result: + /// Nothing are deleted and 500 status code is returned + /// Success Criteria: + /// postgrewritechangefail returns status code 500 + /// + [Fact] + public async Task Post_DeletePolicies_AllPoliciesFail_Fail() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal("\"Unable to complete deletion\"", responseContent); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a invalid deletion of org1/app3 with the same policy defined twice + /// Expected: DeletePolicy returns status code 500 + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of four rules for deletion spread accross 2 policy files of the app org1/app8 and error/postgrewritechangefail between for a single offeredby/coveredby combination. + /// Expected Result: + /// Nothing are deleted and 500 status code is returned + /// Success Criteria: + /// returns status code 500 + /// + [Fact] + public async Task Post_DeletePolicies_DuplicatePoliciesDefinedInput() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/ReadOrg1App3-DuplicatePolicyInRequest_50001337_20001337_NoUpdates.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string errorMessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal("Input should not contain any duplicate policies", errorMessage); + } + + /// + /// Test case: Calling the POST operation for DeletePolicy to perform a invalid deletion of org1/app3 with the same policy defined twice + /// Expected: DeletePolicy returns status code 500 + /// + /// Scenario: + /// Calling the POST operation for DeletePolicy to perform a valid deletion + /// Input: + /// List of four rules for deletion spread accross 2 policy files of the app org1/app8 and error/postgrewritechangefail between for a single offeredby/coveredby combination. + /// Expected Result: + /// Nothing are deleted and 500 status code is returned + /// Success Criteria: + /// returns status code 500 + /// + [Fact] + public async Task Post_DeletePolicies_EmptyInput() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/DeletePolicies/EmptyInput.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/DeletePolicy", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string errorMessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal("A non-empty request body is required.", errorMessage); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to without AccessToken + /// Expected Result: + /// Call should return Unauthorized + /// Success Criteria: + /// AddRules returns status code 401 Unauthorized + /// + [Fact] + public async Task Post_AddRules_Unauthorized() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ReadWriteOrg1App1_50001337_20001336.json"); + StreamContent content = new StreamContent(dataStream); + _client.DefaultRequestHeaders.Remove("Authorization"); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to without any rules specified in the body + /// Expected Result: + /// Call should return Badrequest + /// Success Criteria: + /// AddRules returns status code 400 Badrequest + /// + [Fact] + public async Task Post_AddRules_Badrequest_NoRules() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/EmptyRuleModel.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to with invalid rule model + /// Expected Result: + /// Call should return Badrequest + /// Success Criteria: + /// AddRules returns status code 400 Badrequest + /// + [Fact] + public async Task Post_AddRules_Badrequest_InvalidModel() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/InvalidRuleModel.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of two rules for delegation of the app org1/app1 between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ReadWriteOrg1App1_50001337_20001336.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + foreach (Rule rule in actual) + { + Assert.True(Guid.TryParse(rule.RuleId, out _)); + } + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of one rule for delegation of the resourceregistry resource2 between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_DelegatedByParty_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ScopeaccessResourceRegistryId_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(50001337, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "scopeaccess", null, null, createdSuccessfully: true, resourceRegistryId: "resource2", delegatedByParty: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + foreach (Rule rule in actual) + { + Assert.True(Guid.TryParse(rule.RuleId, out _)); + } + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of two rules for delegation of the resource between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_With_ResourceRegistryId_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001336.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"), + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + foreach (Rule rule in actual) + { + Assert.True(Guid.TryParse(rule.RuleId, out _)); + } + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of two rules for delegation of the app org1/app3 between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids but since the delegation is already existing the RuleId is known before delegating as they are already existing in the Xacml file + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_DuplicateSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ReadWriteOrg1App3_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + Rule rule1 = TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app3", createdSuccessfully: true); + rule1.RuleId = "0d0c8570-64fb-49f9-9f7d-45c057fddf94"; + rule1.Type = RuleType.DirectlyDelegated; + Rule rule2 = TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app3", createdSuccessfully: true); + rule2.RuleId = "6f11dd0b-5e5d-4bd1-85f0-9796300dfded"; + rule2.Type = RuleType.DirectlyDelegated; + + List expected = new List { rule1, rule2 }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual, true); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of two rules for delegation of the resource for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids but since the delegation is already existing the RuleId is known before delegating as they are already existing in the Xacml file + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_With_RegistryResource_DuplicateSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001337.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + Rule rule1 = TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"); + rule1.RuleId = "57b3ee85-f932-42c6-9ab0-941eb6c96eb0"; + rule1.Type = RuleType.DirectlyDelegated; + Rule rule2 = TestDataUtil.GetRuleModel(20001336, 50001337, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", null, null, createdSuccessfully: true, resourceRegistryId: "resource1"); + rule2.RuleId = "99e5cced-3bcb-42b6-9089-63c834f89e77"; + rule2.Type = RuleType.DirectlyDelegated; + + List expected = new List { rule1, rule2 }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual, true); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation + /// Input: + /// List of 4 rules for delegation of from 4 different offeredBys to 4 different coveredBys for 4 different apps. Resulting in 4 different delegation policy files + /// Expected Result: + /// Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// Success Criteria: + /// AddRules returns status code 201 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_MultipleAppsOfferedBysAndCoveredBys_Success() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/MultipleAppsOfferedBysAndCoveredBys.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001337, 50001337, "50001336", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", "org1", "app2", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001336, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001336, "50001337", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", "org2", "app2", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a partially valid delegation + /// Input: + /// List of 4 rules for delegation of from 4 different offeredBys to 4 different coveredBys for 4 different apps. Resulting in 4 different delegation policy files. 1 of the rules are for an app which does not exist + /// Expected Result: + /// 3 Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// 1 Rule is not created and returned with the CreatedSuccessfully flag set to false and no rule id + /// Success Criteria: + /// AddRules returns status code 206 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_OneInvalidApp_PartialSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/OneOutOfFourInvalidApp.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001337, 50001337, "50001336", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", "org1", "INVALIDAPPNAME", createdSuccessfully: false), + TestDataUtil.GetRuleModel(20001336, 50001336, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001336, "50001337", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", "org2", "app2", createdSuccessfully: true), + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertionUtil.AssertEqual(expected[i], actual[i]); + } + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a partially valid delegation + /// Input: + /// List of 4 rules for delegation of from 4 different offeredBys to 4 different coveredBys for 4 different apps. Resulting in 4 different delegation policy files. 1 of the rules are incomplete (missing org/app resource specification) + /// Expected Result: + /// 3 Rules are created and returned with the CreatedSuccessfully flag set and rule ids + /// 1 Rule is not created and returned with the CreatedSuccessfully flag set to false and no rule id + /// Success Criteria: + /// AddRules returns status code 206 and list of rules created match expected + /// + [Fact] + public async Task Post_AddRules_OneIncompleteInput_MissingOrgApp_PartialSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/OneOutOfFourIncompleteApp.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + Rule invalidRule = TestDataUtil.GetRuleModel(20001337, 50001337, "50001336", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", null, null, createdSuccessfully: false); + invalidRule.Resource = new List(); + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001336, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(20001336, 50001336, "50001337", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "write", "org2", "app2", createdSuccessfully: true), + invalidRule, + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertionUtil.AssertEqual(expected[i], actual[i]); + } + } + + /// + /// Scenario: + /// Calling the POST operation for AddRules to perform a valid delegation, but pushing the delegation event to the queue fails. + /// Input: + /// List with a rule for delegation of the app error/delegationeventfail between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Internal exception cause pushing delegation event to fail, after delegation has been stored. + /// Success Criteria: + /// AddRules returns status code Created, but a Critical Error has been logged + /// + [Fact] + public async Task Post_AddRules_DelegationEventQueue_Push_Exception() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/AddRules/DelegationEventError.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + List expected = new List + { + TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "error", "delegationeventfail", createdSuccessfully: true) + }; + + // Act + HttpResponseMessage response = await _client.PostAsync("accessmanagement/api/v1/delegations/addrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + Assert.True(actual.TrueForAll(a => a.CreatedSuccessfully)); + Assert.True(actual.TrueForAll(a => !string.IsNullOrEmpty(a.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + foreach (Rule rule in actual) + { + Assert.True(Guid.TryParse(rule.RuleId, out _)); + } + } + + /// + /// Test case: GetRules returns a list of rules offeredby has given coveredby + /// Expected: GetRules returns a list of rules offeredby has given coveredby + /// + [Fact] + public async Task GetRules_RuleType_Is_DirectlyDelegated() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_SuccessRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = GetExpectedRulesForUser(); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetRules returns a list of rules that have been inherited by the recipient via keyrole + /// Expected: GetRules returns a list of rules offeredby's main unit has given to the recipient via keyrole + /// + [Fact] + public async Task GetRules_RuleType_Is_InheritedViaKeyRole() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_RuleTypeInheritedViaKeyRoleRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = new List(); + expectedRules.Add(TestDataUtil.GetRuleModel(20001337, 50001337, "50001338", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "sign", "skd", "taxreport", ruleType: RuleType.InheritedViaKeyRole)); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetRules returns a list of rules that have been inherited by the subunit recipient via keyrole + /// Expected: GetRules returns a list of rules offeredby's main unit has given to the subunit recipient via keyrole + /// + [Fact] + public async Task GetRules_RuleType_Is_InheritedAsSubunitViaKeyrole() + { + // Arrange + Assert.True(File.Exists("Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitViaKeyroleRequest.json")); + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitViaKeyroleRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = new List(); + expectedRules.Add(TestDataUtil.GetRuleModel(20001339, 50001335, "50001337", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "read", "skd", "taxreport", ruleType: RuleType.InheritedAsSubunitViaKeyrole)); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetRules returns rule that is inherited by a subunit from the main unit + /// Expected: GetRules returns a list of rules the subunit has received from the main unit + /// + [Fact] + public async Task GetRules_RuleType_Is_InheritedAsSubunit() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = new List(); + expectedRules.Add(TestDataUtil.GetRuleModel(20001339, 50001338, "50001336", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "sign", "skd", "taxreport", ruleType: RuleType.InheritedAsSubunit)); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetRules with missing values in the request + /// Expected: GetRules returns a BadRequest response + /// + [Fact] + public async Task GetRules_MissingValuesInRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_MissingValuesInRequestRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + /// + /// Test case: GetRules with missing values in the request + /// Expected: GetRules returns a BadRequest response + /// + [Fact] + public async Task GetRules_MissingOfferedByInRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_MissingOfferedByInRequestRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + /// + /// Test case: GetRules for a coveredby that does not have any rules + /// Expected: GetRules returns an empty list + /// + [Fact] + public async Task GetRules_NoRulesRequest() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_NoRulesRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = new List(); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetRules returns a list of rules offeredby has given two coveredbys (a userid and partyid) + /// Expected: GetRules returns a list of rules offeredby has given coveredby + /// + [Fact] + public async Task GetRules_WithKeyRolePartyIdsSuccess() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/GetRules/GetRules_UsingkeyRolePartyIdsRequest.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + List expectedRules = GetExpectedRulesForUser(); + expectedRules.AddRange(GetExpectedRulesForParty()); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/delegations/getrules", content); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRules = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRules, actualRules, AssertionUtil.AssertRuleEqual); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations returns a list of delegations between supplier and consumer for a given scope. + /// Token is authorized for admin scope and and can lookup delegations even when scope is not in the consumers owned scope-prefixes (consumer_prefix) + /// Expected: GetMaskinportenSchemaDelegations returns a list of delegations offered by supplier to consumer for a given scope + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_Valid() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List resourceIds = new List + { + "nav_aa_distribution", + "appid-123" + }; + List expectedDelegations = GetExpectedMaskinportenSchemaDelegations("810418672", "810418192", resourceIds); + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualDelegations = JsonSerializer.Deserialize>(responseContent); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertDelegationEqual); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations returns a list of delegations between supplier and consumer for a given scope. + /// Token is authorized for admin scope and and can lookup delegations even when scope is not in the consumers owned scope-prefixes (consumer_prefix) + /// Expected: GetMaskinportenSchemaDelegations returns a list of delegations offered by supplier to consumer for a given scope + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_ServiceOwnerLookup_Valid() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List resourceIds = new List + { + "nav_aa_distribution", + "appid-123" + }; + List expectedDelegations = GetExpectedMaskinportenSchemaDelegations("810418672", "810418192", resourceIds); + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualDelegations = JsonSerializer.Deserialize>(responseContent); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertDelegationEqual); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations with a scope with altinn prefix, which the serviceowner skd is not authorized for + /// Expected: GetMaskinportenSchemaDelegations returns forbidden + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_ServiceOwnerLookup_UnauthorizedScope() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("SKD", "974761076", "altinn:maskinporten/delegations", new[] { "skd" }); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Not authorized for lookup of delegations for the scope: altinn:instances.read"; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + string scope = "altinn:instances.read"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + Assert.Equal(expected, errorResponse.Title); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations for orgnummer that does not have any delegations + /// Expected: GetMaskinportenSchemaDelegations returns ok, no delegations found + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_Valid_DelegationsEmpty() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "[]"; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains(expected, responseContent); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations without sending scopes + /// Expected: GetMaskinportenSchemaDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_MissingScope() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "The scope field is required."; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope="); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["scope"][0]); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations for invalid supplier orgnummer + /// Expected: GetMaskinportenSchemaDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_InvalidSupplier() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Supplierorg is not an valid organization number"; + + // Act + string supplierOrg = "12345"; + string consumerOrg = "810418532"; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["supplierOrg"][0]); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations for invalid consumer orgnummer + /// Expected: GetMaskinportenSchemaDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_InvalidConsumer() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Consumerorg is not an valid organization number"; + + // Act + string supplierOrg = "810418362"; + string consumerOrg = "12345"; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["consumerOrg"][0]); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations for a scope which is not a registered reference on any resources + /// Expected: GetMaskinportenSchemaDelegations returns ok, no delegations found + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_ScopesNotRegisteredOnResource() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "[]"; + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/test"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(expected, responseContent.Replace('"', ' ').Trim()); + } + + /// + /// Test case: GetMaskinportenSchemaDelegations for an invalid scope format + /// Expected: GetMaskinportenSchemaDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenSchemaDelegations_Admin_InvalidScopeFormat() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Is not well formatted: test invalid scope (Parameter 'scope')"; + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "test invalid scope"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/admin/delegations/maskinportenschema/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["scope"][0]); + } + + private static List GetExpectedRulesForUser() + { + List list = new List(); + list.Add(TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "skd", "taxreport", ruleType: RuleType.DirectlyDelegated)); + list.Add(TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "skd", "taxreport", ruleType: RuleType.DirectlyDelegated)); + return list; + } + + private static List GetExpectedRulesForParty() + { + List list = new List(); + list.Add(TestDataUtil.GetRuleModel(20001337, 50001337, "50001336", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "sign", "skd", "taxreport", ruleType: RuleType.InheritedViaKeyRole)); + return list; + } + + private static List GetExpectedMaskinportenSchemaDelegations(string supplierOrg, string consumerOrg, List resourceIds) + { + List delegations = new List(); + delegations = TestDataUtil.GetAdminDelegations(supplierOrg, consumerOrg, resourceIds); + return delegations; + } + + private HttpClient GetTestClient(IPDP pdpMock = null, IHttpContextAccessor httpContextAccessor = null, IDelegationMetadataRepository delegationMetadataRepositoryMock = null) + { + pdpMock ??= new PepWithPDPAuthorizationMock(); + httpContextAccessor ??= new HttpContextAccessor(); + delegationMetadataRepositoryMock ??= new DelegationMetadataRepositoryMock(); + + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(delegationMetadataRepositoryMock); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(pdpMock); + services.AddSingleton(httpContextAccessor); + services.AddSingleton(); + services.AddSingleton(); + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + return client; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/LookupControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/LookupControllerTest.cs new file mode 100644 index 00000000..5c79000e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/LookupControllerTest.cs @@ -0,0 +1,178 @@ +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.AccessManagement.Utilities; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers +{ + /// + /// Test class for + /// + [Collection("LookupController Tests")] + public class LookupControllerTest : IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + private readonly HttpClient _client; + + private readonly JsonSerializerOptions serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public LookupControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _client = GetTestClient(); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + string token = PrincipalUtil.GetAccessToken("sbl.authorization"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + /// + /// Test case: GetParty for partyId that corresponds to a party in partylist for authenticated user. + /// Expected: GetParty returns list with party. + /// + /// + [Fact] + public async Task GetParty_Valid_PartyId_is_person() + { + // Arrange + PartyExternal expectedParty = GetExpectedParty(50002182); + expectedParty.SSN = IdentifierUtil.MaskSSN(expectedParty.SSN); + int userId = 50002182; + string token = PrincipalUtil.GetToken(userId, 50002182, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/lookup/reportee/{expectedParty.PartyId}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + PartyExternal actualParty = JsonSerializer.Deserialize(responseContent, serializerOptions); + AssertionUtil.AssertPartyEqual(expectedParty, actualParty); + } + + /// + /// Test case: GetParty for partyId that corresponds to a party in partylist for authenticated user. + /// Expected: GetParty returns list with party. + /// + /// + [Fact] + public async Task GetParty_Valid_PartyId_is_Org() + { + // Arrange + PartyExternal expectedParty = GetExpectedParty(50004226); + int userId = 50004226; + string token = PrincipalUtil.GetToken(userId, 50004226, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/lookup/reportee/{expectedParty.PartyId}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + PartyExternal actualParty = JsonSerializer.Deserialize(responseContent, serializerOptions); + AssertionUtil.AssertPartyEqual(expectedParty, actualParty); + } + + /// + /// Test case: GetParty for partyId that corresponds to a party in partylist for authenticated user. + /// Expected: GetParty returns list with party. + /// + /// + [Fact] + public async Task GetParty_Valid_PartyId_is_Subunit() + { + // Arrange + PartyExternal expectedParty = GetExpectedParty(50004646, true); + + int userId = 50004646; + string token = PrincipalUtil.GetToken(userId, 50004646, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/lookup/reportee/{expectedParty.PartyId}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + PartyExternal actualParty = JsonSerializer.Deserialize(responseContent, serializerOptions); + AssertionUtil.AssertPartyEqual(expectedParty, actualParty); + } + + /// + /// Test case: GetParty for partyId that does not correspond to a party in partylist for authenticated user. + /// Expected: GetParty returns 404 not found. + /// + /// 404 not found + [Fact] + public async Task GetParty_Invalid_partyId() + { + // Arrange + int userId = 1234; + string token = PrincipalUtil.GetToken(userId, 50002182, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/lookup/reportee/{54321}"); + + // Assert + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + private HttpClient GetTestClient() + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + return client; + } + + private static PartyExternal GetExpectedOrganisation(string orgNummer) + { + PartyExternal party = TestDataUtil.GetOrganisation(orgNummer); + return party; + } + + private static PartyExternal GetExpectedParty(int partyId, bool isSubUnit = false) + { + if (isSubUnit) + { + return TestDataUtil.GetTestPartyWithSubUnit(partyId); + } + + return TestDataUtil.GetTestParty(partyId); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/MaskinportenSchemaControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/MaskinportenSchemaControllerTest.cs new file mode 100644 index 00000000..af7343eb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/MaskinportenSchemaControllerTest.cs @@ -0,0 +1,1809 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using Altinn.Platform.Register.Models; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers +{ + /// + /// Test class for + /// + [Collection("MaskinportenSchemaController Tests")] + public class MaskinportenSchemaControllerTest : IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + private HttpClient _client; + + private readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public MaskinportenSchemaControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _client = GetTestClient(); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + string token = PrincipalUtil.GetAccessToken("sbl.authorization"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns a list of delegations offeredby has given coveredby + /// Expected: GetOfferedMaskinportenSchemaDelegations returns a list of delegations offeredby has given coveredby + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_Valid_OfferedByParty() + { + // Arrange + List expectedDelegations = TestDataUtil.GetOfferedMaskinportenSchemaDelegations(50004223); + var token = PrincipalUtil.GetToken(4321, 87654321, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004223/maskinportenschema/offered"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns a list of delegations offeredby has given coveredby + /// Expected: GetOfferedMaskinportenSchemaDelegations returns a list of delegations offeredby has given coveredby + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_Valid_OfferedByOrg() + { + // Arrange + List expectedDelegations = TestDataUtil.GetOfferedMaskinportenSchemaDelegations(50004223); + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "50004223"); + _client = GetTestClient(httpContextAccessor: httpContextAccessorMock); + var token = PrincipalUtil.GetToken(4321, 87654321, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418982"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/offered"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns notfound when the query parameter is missing + /// Expected: GetOfferedMaskinportenSchemaDelegations returns notfound + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_Notfound_MissingOfferedBy() + { + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1//maskinportenschema/offered"); + + // Assert + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns Forbidden when the query parameter is invalid + /// Expected: GetOfferedMaskinportenSchemaDelegations returns Forbidden + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_Forbidden_InvalidOfferedBy() + { + // Arrange + _client = GetTestClient(new PepWithPDPAuthorizationMock()); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/123/maskinportenschema/offered"); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns 200 with response message empty array when there are no delegations for the reportee + /// Expected: GetOfferedMaskinportenSchemaDelegations returns 200 with response message empty array when there are no delegations for the reportee + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_OfferedBy_NoDelegations() + { + // Arrange + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + string expected = "[]"; + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004225/maskinportenschema/offered"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains(expected, responseContent); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns list of resources that were delegated. The resource metadata is set to not available if the resource in a delegation for some reason is not found in resource registry + /// Expected: GetOfferedMaskinportenSchemaDelegations returns list of resources that were delegated. The resource metadata is set to not available if the resource in a delegation for some reason is not found in resource registry + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_ResourceMetadataNotFound() + { + // Arrange + List expectedDelegations = TestDataUtil.GetOfferedMaskinportenSchemaDelegations(50004226); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004226/maskinportenschema/offered"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not set + /// Expected: GetOfferedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not set + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_MissingBearerToken() + { + _client.DefaultRequestHeaders.Remove("Authorization"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004223/maskinportenschema/offered"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not valid + /// Expected: GetOfferedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not valid + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_InvalidBearerToken() + { + // Arrange + _client.DefaultRequestHeaders.Remove("Authorization"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "This is an invalid token"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004223/maskinportenschema/offered"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns a list of delegations received by coveredby + /// Expected: GetReceivedMaskinportenSchemaDelegations returns a list of delegations received by coveredby + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_Valid_CoveredBy() + { + // Arrange + List expectedDelegations = TestDataUtil.GetReceivedMaskinportenSchemaDelegations(50004219); + + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004219/maskinportenschema/received"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns a list of delegations received by coveredby when the coveredby is an organisation number + /// Expected: GetReceivedMaskinportenSchemaDelegations returns a list of delegations received by coveredby + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_Valid_CoveredByOrg() + { + // Arrange + List expectedDelegations = TestDataUtil.GetReceivedMaskinportenSchemaDelegations(50004219); + + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "50004219"); + _client = GetTestClient(new PepWithPDPAuthorizationMock(), httpContextAccessorMock); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418192"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/received"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns notfound when the query parameter is missing + /// Expected: GetReceivedMaskinportenSchemaDelegations returns notfound when the query parameter is missing + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_Missing_CoveredBy() + { + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1//maskinportenschema/received"); + + // Assert + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns Forbidden when the query parameter is invalid + /// Expected: GetReceivedMaskinportenSchemaDelegations returns Forbidden + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_Invalid_CoveredBy() + { + // Arrange + _client = GetTestClient(new PepWithPDPAuthorizationMock()); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/1234/maskinportenschema/received"); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns 200 with empty array when there are no delegations received for the reportee + /// Expected: GetReceivedMaskinportenSchemaDelegations returns 200 with rempty array when there are no delegations received for the reportee + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_CoveredBy_NoDelegations() + { + // Arrange + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + string expected = "[]"; + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004225/maskinportenschema/received"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains(expected, responseContent); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns list of resources that were delegated. The resource metadata is set to not available if the resource in a delegation for some reason is not found in resource registry + /// Expected: GetReceivedMaskinportenSchemaDelegations returns list of resources that were delegated. The resource metadata is set to not available if the resource in a delegation for some reason is not found in resource registry + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_ResourceMetadataNotFound() + { + // Arrange + List expectedDelegations = TestDataUtil.GetReceivedMaskinportenSchemaDelegations(50004216); + + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004216/maskinportenschema/received"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualDelegations = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertMaskinportenSchemaDelegationExternalEqual); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not set + /// Expected: GetReceivedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not set + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_MissingBearerToken() + { + _client.DefaultRequestHeaders.Remove("Authorization"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004223/maskinportenschema/received"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not valid + /// Expected: GetReceivedMaskinportenSchemaDelegations returns unauthorized when the bearer token is not valid + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_InvalidBearerToken() + { + _client.DefaultRequestHeaders.Remove("Authorization"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "This is an invalid token"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/50004223/maskinportenschema/received"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: GetMaskinportenDelegations returns a list of delegations between supplier and consumer for a given scope. + /// Token is authorized for admin scope and and can lookup delegations even when scope is not in the consumers owned scope-prefixes (consumer_prefix) + /// Expected: GetMaskinportenDelegations returns a list of delegations offered by supplier to consumer for a given scope + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_Valid() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List resourceIds = new List + { + "nav_aa_distribution", + "appid-123" + }; + List expectedDelegations = GetExpectedMaskinportenSchemaDelegations("810418672", "810418192", resourceIds); + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualDelegations = JsonSerializer.Deserialize>(responseContent); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertDelegationEqual); + } + + /// + /// Test case: GetMaskinportenDelegations returns a list of delegations between supplier and consumer for a given scope. + /// Token is authorized for admin scope and and can lookup delegations even when scope is not in the consumers owned scope-prefixes (consumer_prefix) + /// Expected: GetMaskinportenDelegations returns a list of delegations offered by supplier to consumer for a given scope + /// + [Fact] + public async Task GetMaskinportenDelegations_ServiceOwnerLookup_Valid() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List resourceIds = new List + { + "nav_aa_distribution", + "appid-123" + }; + List expectedDelegations = GetExpectedMaskinportenSchemaDelegations("810418672", "810418192", resourceIds); + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualDelegations = JsonSerializer.Deserialize>(responseContent); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertDelegationEqual); + } + + /// + /// Test case: GetMaskinportenDelegations returns a list of delegations for a given scope. + /// Token is authorized for admin scope and and can lookup delegations even when scope is not in the consumers owned scope-prefixes (consumer_prefix) + /// Expected: GetMaskinportenDelegations returns a list of delegations for a given scope + /// + [Fact] + public async Task GetMaskinportenDelegations_ServiceOwnerLookup_NoSupplerConsumer_Valid() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List resourceIds = new List + { + "nav_aa_distribution", + "appid-123" + }; + List expectedDelegations = GetExpectedMaskinportenSchemaDelegations(null, null, resourceIds); + + // Act + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualDelegations = JsonSerializer.Deserialize>(responseContent); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedDelegations, actualDelegations, AssertionUtil.AssertDelegationEqual); + } + + /// + /// Test case: GetMaskinportenDelegations with a scope with altinn prefix, which the serviceowner skd is not authorized for + /// Expected: GetMaskinportenDelegations returns forbidden + /// + [Fact] + public async Task GetMaskinportenDelegations_ServiceOwnerLookup_UnauthorizedScope() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("SKD", "974761076", "altinn:maskinporten/delegations", new[] { "skd" }); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Not authorized for lookup of delegations for the scope: altinn:instances.read"; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + string scope = "altinn:instances.read"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + Assert.Equal(expected, errorResponse.Title); + } + + /// + /// Test case: GetMaskinportenDelegations for orgnummer that does not have any delegations + /// Expected: GetMaskinportenDelegations returns ok, no delegations found + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_Valid_DelegationsEmpty() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "[]"; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains(expected, responseContent); + } + + /// + /// Test case: GetMaskinportenDelegations without sending scopes + /// Expected: GetMaskinportenDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_MissingScope() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "The scope field is required."; + + // Act + int supplierOrg = 810418362; + int consumerOrg = 810418532; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope="); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["scope"][0]); + } + + /// + /// Test case: GetMaskinportenDelegations for invalid supplier orgnummer + /// Expected: GetMaskinportenDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_InvalidSupplier() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Supplierorg is not an valid organization number"; + + // Act + string supplierOrg = "12345"; + string consumerOrg = "810418532"; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["supplierOrg"][0]); + } + + /// + /// Test case: GetMaskinportenDelegations for invalid consumer orgnummer + /// Expected: GetMaskinportenDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_InvalidConsumer() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Consumerorg is not an valid organization number"; + + // Act + string supplierOrg = "810418362"; + string consumerOrg = "12345"; + string scope = "altinn:test/theworld.write"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["consumerOrg"][0]); + } + + /// + /// Test case: GetMaskinportenDelegations for a scope which is not a registered reference on any resources + /// Expected: GetMaskinportenDelegations returns ok, no delegations found + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_ScopesNotRegisteredOnResource() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "[]"; + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "altinn:test/test"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(expected, responseContent.Replace('"', ' ').Trim()); + } + + /// + /// Test case: GetMaskinportenDelegations for an invalid scope format + /// Expected: GetMaskinportenDelegations returns badrequest + /// + [Fact] + public async Task GetMaskinportenDelegations_Admin_InvalidScopeFormat() + { + // Arrange + string token = PrincipalUtil.GetOrgToken("DIGDIR", "991825827", "altinn:maskinporten/delegations.admin"); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + string expected = "Is not well formatted: test invalid scope (Parameter 'scope')"; + + // Act + int supplierOrg = 810418672; + int consumerOrg = 810418192; + string scope = "test invalid scope"; + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/maskinporten/delegations/?supplierorg={supplierOrg}&consumerorg={consumerOrg}&scope={scope}"); + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails errorResponse = JsonSerializer.Deserialize(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, errorResponse.Errors["scope"][0]); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations, user with necessary rights + /// Expected: User is authorized + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_UserComplyingToPolicy() + { + // Arrange + const HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "50004219"); + _client = GetTestClient(new PepWithPDPAuthorizationMock(), httpContextAccessorMock); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418192"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/offered"); + + // Assert + Assert.Equal(expectedStatusCode, response.StatusCode); + } + + /// + /// Test case: GetOfferedMaskinportenSchemaDelegations, user without necessary rights + /// Expected: Authorization is denied + /// Testing if user without necessary rights is denied access to + /// + [Fact] + public async Task GetOfferedMaskinportenSchemaDelegations_UserNotComplyingToPolicy() + { + // Arrange + const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden; + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "12345678"); + _client = GetTestClient(new PepWithPDPAuthorizationMock(), httpContextAccessorMock); + var token = PrincipalUtil.GetToken(1234, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418192"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/offered"); + + // Assert + Assert.Equal(expectedStatusCode, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations, user with necessary rights + /// Expected: User is authorized + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_UserComplyingToPolicy() + { + // Arrange + const HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "50004219"); + _client = GetTestClient(new PepWithPDPAuthorizationMock(), httpContextAccessorMock); + var token = PrincipalUtil.GetToken(1234, 12344321, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418192"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/received"); + + // Assert + Assert.Equal(expectedStatusCode, response.StatusCode); + } + + /// + /// Test case: GetReceivedMaskinportenSchemaDelegations, user without necessary rights + /// Expected: Authorization is denied + /// Testing if user without necessary rights is denied access to + /// + [Fact] + public async Task GetReceivedMaskinportenSchemaDelegations_UserNotComplyingToPolicy() + { + // Arrange + const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden; + var httpContextAccessorMock = GetHttpContextAccessorMock("party", "50004219"); + _client = GetTestClient(new PepWithPDPAuthorizationMock(), httpContextAccessorMock); + var token = PrincipalUtil.GetToken(4321, 12345678, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418192"); + + // Act + HttpResponseMessage response = await _client.GetAsync($"accessmanagement/api/v1/organization/maskinportenschema/received"); + + // Assert + Assert.Equal(expectedStatusCode, response.StatusCode); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, to the organization 50004222 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: MaskinportenDelegation returns 201 Created with response body containing the expected delegated rights + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_DAGL_Success() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + RightsDelegationResponseExternal expectedResponse = GetExpectedResponse("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004222"); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004222"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 for the reportee organization 910459880 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, to the organization 50004222 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 910459880 + /// Expected: MaskinportenDelegation returns 201 Created with response body containing the expected delegated rights + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_DAGL_ExternalIdentifier_OrgNoReportee_Success() + { + // Arrange + string fromParty = "50005545"; + _client = GetTestClient(httpContextAccessor: GetHttpContextAccessorMock("party", fromParty)); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "910459880"); + + RightsDelegationResponseExternal expectedResponse = GetExpectedResponse("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004222"); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004222"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/organization/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, to the organization 810418672 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The request 'To' property is using the urn:altinn:organizationnumber attribute in order to use the externally available organizationnumber to specify the recipient of the delegation + /// Expected: MaskinportenDelegation returns 201 Created with response body containing the expected delegated rights + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_DAGL_ExternalIdentifier_OrgNoRecipient_Success() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + RightsDelegationResponseExternal expectedResponse = GetExpectedResponse("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "810418672"); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "810418672"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed without a user token + /// Expected: 401 Unauthorized + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_MissingToken_Unauthorized() + { + // Arrange + string fromParty = "50005545"; + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004222"); + + // Act + HttpResponseMessage response = await GetTestClient().PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20001337 with authentication level 2, + /// for the reportee party 1 to the recipient party 2 + /// In this case: + /// - The request contains multiple rights + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_SingleRightOnly() + { + // Arrange + _client = GetTestClient(new PdpPermitMock(), GetHttpContextAccessorMock("party", "1")); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "Input_SingleRightOnly"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "ExpectedOutput_SingleRightOnly"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/1/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20001337 with authentication level 2, + /// for the reportee party 1 to the recipient party 2 + /// In this case: + /// - The request contains a resource specification using Org/App identifier + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_OrgAppResource() + { + // Arrange + _client = GetTestClient(new PdpPermitMock(), GetHttpContextAccessorMock("party", "1")); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "Input_OrgAppResource"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "ExpectedOutput_OrgAppResource"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/1/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20001337 with authentication level 2, + /// for the reportee party 1 to the recipient party 2 + /// In this case: + /// - The resource registry id does not exist + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidResourceRegistryId() + { + // Arrange + _client = GetTestClient(new PdpPermitMock(), GetHttpContextAccessorMock("party", "1")); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "Input_InvalidResourceRegistryId"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "ExpectedOutput_InvalidResourceRegistryId"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/1/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20001337 with authentication level 2, + /// for the reportee party 1 to the recipient party 2 + /// In this case: + /// - The resource registry id is not for a MaskinportenSchema + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidResourceType() + { + // Arrange + _client = GetTestClient(new PdpPermitMock(), GetHttpContextAccessorMock("party", "1")); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "Input_InvalidResourceType"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p1", "p2", "ExpectedOutput_InvalidResourceType"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/1/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, + /// for the reportee party 50002598 to the recipient party 2 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The recipient (To) in the request is not a valid party id + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidTo() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2", "Input_Default"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2", "ExpectedOutput_InvalidTo"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, + /// for the reportee party 50002598 to the recipient userid 20001337 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The recipient (To) in the request is a userid which delegation of maskinporten schema to should not be possible + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidTo_UserId() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "u20001337", "Input_InvalidTo_UserId"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "u20001337", "ExpectedOutput_InvalidTo_UserId"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, + /// for the reportee party 50002598 to a recipient social security number + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The recipient (To) in the request is a social security number which delegation of maskinporten schema to should not be possible + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidTo_Ssn() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "u20001337", "Input_InvalidTo_Ssn"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "u20001337", "ExpectedOutput_InvalidTo_Ssn"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, on behalf of himself. + /// In this case: + /// - The user 20000490 tries to perform maskinporten delegation from himself + /// - This shouldn't really happen as long as the authorization requirement is done through roles tied to ER-roles, + /// but this case mocks permit from PDP to test internal service validation + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_InvalidFrom_Ssn() + { + // Arrange + string fromParty = "50002598"; + _client = GetTestClient(new PdpPermitMock(), GetHttpContextAccessorMock("party", "50002598")); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + _client.DefaultRequestHeaders.Add("Altinn-Party-SocialSecurityNumber", "07124912037"); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2", "Input_Default"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2", "ExpectedOutput_InvalidFrom_Ssn"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/person/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, + /// for the reportee party 50005545 of the non_delegable_maskinportenschema maskinporten schema resource from the resource registry to the organization 50004222 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The non_delegable_maskinportenschema resource has a role requirement (NOPE), which does not exist meaning the user will not have any delegable rights for the resource + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_NonDelegableResource() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "non_delegable_maskinportenschema", $"p{fromParty}", "p50004222"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "non_delegable_maskinportenschema", $"p{fromParty}", "p50004222"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 with authentication level 2, + /// for the reportee party 50005545 of the digdirs_company_car maskinporten schema resource from the resource registry to the organization 50004222 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The required minimum authentication level for digdirs_company_car + /// Expected: MaskinportenDelegation returns 400 Bad Request with a problem details respons body describing the error + /// + [Fact] + public async Task PostMaskinportenSchemaDelegation_ValidationProblemDetails_TooLowAuthenticationLevelForResource() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "digdirs_company_car", $"p{fromParty}", "p50004222"); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "digdirs_company_car", $"p{fromParty}", "p50004222"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: RevokeOfferedMaskinportenScopeDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// delegated to the organization 50004221 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: RevokeOfferedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeOfferedMaskinportenScopeDelegation_DAGL_Success() + { + // Arrange + int fromParty = 50005545; + DelegationMetadataRepositoryMock delegationMetadataRepositoryMock = new DelegationMetadataRepositoryMock { MetadataChanges = new Dictionary>() }; + HttpClient client = GetTestClient(delegationMetadataRepositoryMock: delegationMetadataRepositoryMock); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "resourceregistry/jks_audi_etron_gt/50005545/p50004221", new List { TestDataUtil.GetResourceRegistryDelegationChange("jks_audi_etron_gt", ResourceType.MaskinportenSchema, fromParty, Convert.ToDateTime("2022-09-27T13:02:23.786072Z"), coveredByPartyId: 50004221, performedByUserId: 20000490, changeType: DelegationChangeType.RevokeLast) } } + }; + + StreamContent requestContent = GetRequestContent("RevokeOfferedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004221"); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + AssertionUtil.AssertEqual(expectedDbUpdates, delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Test case: RevokeOfferedMaskinportenScopeDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// delegated to the organization 50004221 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: RevokeOfferedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeOfferedMaskinportenScopeDelegation_DAGL_ToOrgNo_Success() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("RevokeOfferedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "810418532"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: RevokeOfferedMaskinportenScopeDelegation performed by authenticated user 20000490 for the reportee organization 910459880 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// delegated to the organization 50004221 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 910459880 + /// Expected: RevokeOfferedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeOfferedMaskinportenScopeDelegation_DAGL_FromOrgNo_Success() + { + // Arrange + string fromParty = "50005545"; + _client = GetTestClient(httpContextAccessor: GetHttpContextAccessorMock("party", fromParty)); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "910459880"); + + StreamContent requestContent = GetRequestContent("RevokeOfferedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "810418532"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: RevokeOfferedMaskinportenScopeDelegation performed by authenticated user 20000095 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// delegated to the organization 50004221 + /// In this case: + /// - The user 20000095 is ADMAI (Tilgangsstyrer) for the From unit 50005545 + /// Expected: RevokeOfferedMaskinportenScopeDelegation returns 403 Forbidden + /// + [Fact] + public async Task RevokeOfferedMaskinportenScopeDelegation_ADMAI_Forbidden() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000095, 50002203)); + + StreamContent requestContent = GetRequestContent("RevokeOfferedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50004221"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: RevokeOfferedMaskinportenScopeDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// delegated to party 2 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The To party does not exist + /// Expected: RevokeOfferedMaskinportenScopeDelegation returns 400 Bad Request with ValidationProblemDetails body + /// + [Fact] + public async Task RevokeOfferedMaskinportenScopeDelegation_ValidationProblemDetails_InvalidTo() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + StreamContent requestContent = GetRequestContent("RevokeOfferedMaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("RevokeOfferedMaskinportenScopeDelegation", "mp_validation_problem_details", $"p{fromParty}", "p2", "ExpectedOutput_InvalidTo"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: RevokeReceivedMaskinportenScopeDelegation performed by authenticated user 20001337 for the reportee party 50004221 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// which have received delegation from the party 50005545 + /// In this case: + /// - The user 20001337 is DAGL for the To unit 50004221 + /// Expected: RevokeReceivedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeReceivedMaskinportenScopeDelegation_DAGL_Success() + { + // Arrange + string toParty = "50004221"; + DelegationMetadataRepositoryMock delegationMetadataRepositoryMock = new DelegationMetadataRepositoryMock { MetadataChanges = new Dictionary>() }; + HttpClient client = GetTestClient(delegationMetadataRepositoryMock: delegationMetadataRepositoryMock); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "resourceregistry/jks_audi_etron_gt/50005545/p50004221", new List { TestDataUtil.GetResourceRegistryDelegationChange("jks_audi_etron_gt", ResourceType.MaskinportenSchema, 50005545, created: null, coveredByPartyId: 50004221, performedByUserId: 20001337, changeType: DelegationChangeType.RevokeLast) } } + }; + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p50005545", $"p{toParty}"); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/{toParty}/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + AssertionUtil.AssertEqual(expectedDbUpdates, delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Test case: RevokeActiveMaskinportenScopeDelegation performed by authenticated user 20001337 for the reportee party 50004221 of the non-delegable altinn_access_management maskinporten schema resource from the resource registry, + /// which have received delegation from the party 50005545 + /// In this case: + /// - The user 20001337 is DAGL for the To unit 50004221 + /// Expected: RevokeActiveMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeActiveMaskinportenScopeDelegation_ResourceDelegableFalse_Success() + { + // Arrange + string toParty = "50004221"; + DelegationMetadataRepositoryMock delegationMetadataRepositoryMock = new DelegationMetadataRepositoryMock { MetadataChanges = new Dictionary>() }; + HttpClient client = GetTestClient(delegationMetadataRepositoryMock: delegationMetadataRepositoryMock); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "jks_undelegable", $"p50005545", $"p{toParty}"); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/{toParty}/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: RevokeReceivedMaskinportenScopeDelegation performed by authenticated user 20001337 for the reportee organization 810418532 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// which have received delegation from the party 50005545 + /// In this case: + /// - The user 20001337 is DAGL for the To unit 810418532 + /// Expected: RevokeReceivedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeReceivedMaskinportenScopeDelegation_DAGL_ToOrgNo_Success() + { + // Arrange + string toParty = "50004221"; + _client = GetTestClient(httpContextAccessor: GetHttpContextAccessorMock("party", toParty)); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418532"); + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p50005545", $"p{toParty}"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/organization/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: RevokeReceivedMaskinportenScopeDelegation performed by authenticated user 20001337 for the reportee organization 910459880 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// which have received delegation from the party 50005545 + /// In this case: + /// - The user 20000490 is DAGL for the From unit 910459880 + /// Expected: RevokeReceivedMaskinportenScopeDelegation returns 204 No Content + /// + [Fact] + public async Task RevokeReceivedMaskinportenScopeDelegation_DAGL_FromOrgNo_Success() + { + // Arrange + string toParty = "50004221"; + _client = GetTestClient(httpContextAccessor: GetHttpContextAccessorMock("party", toParty)); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + _client.DefaultRequestHeaders.Add("Altinn-Party-OrganizationNumber", "810418532"); + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"910459880", $"810418532"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/organization/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: RevokeReceivedMaskinportenScopeDelegation performed by authenticated user 20000095 for the reportee party 50004221 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// which have received delegation from the party 50005545 + /// In this case: + /// - The user 20000095 is ADMAI (Tilgangsstyrer) for the To party 50004221 + /// Expected: RevokeReceivedMaskinportenScopeDelegation returns 403 Forbidden + /// + [Fact] + public async Task RevokeReceivedMaskinportenScopeDelegation_ADMAI_Forbidden() + { + // Arrange + string toParty = "50004221"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000095, 50002203)); + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "jks_audi_etron_gt", $"p50005545", $"p{toParty}"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{toParty}/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: RevokeReceivedMaskinportenScopeDelegation performed by authenticated user 20001337 for the reportee party 50004221 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, + /// which have received delegation from the party 2 + /// In this case: + /// - The user 20001337 is DAGL for the To unit 50004221 + /// - The From party 2 is not a valid party + /// Expected: RevokeReceivedMaskinportenScopeDelegation returns 400 Bad Request with ValidationProblemDetails body + /// + [Fact] + public async Task RevokeReceivedMaskinportenScopeDelegation_ValidationProblemDetails_InvalidFrom() + { + // Arrange + string toParty = "50004221"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20001337, 50001337)); + + StreamContent requestContent = GetRequestContent("RevokeReceivedMaskinportenScopeDelegation", "mp_validation_problem_details", $"p2", $"p{toParty}"); + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("RevokeReceivedMaskinportenScopeDelegation", "mp_validation_problem_details", $"p2", $"p{toParty}", "ExpectedOutput_InvalidFrom"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{toParty}/maskinportenschema/received/revoke", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, to the organization with partyId 50005545 (orgNr 910459880) + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: MaskinportenDelegation returns 400 BadRequest with response body containing ValidationProblemDetails with error message that CoveredBy can not be the same as OfferedBy + /// + [Fact] + public async Task MaskinportenDelegation_DAGL_FromAndToIdenticalPartyId() + { + // Arrange + string fromParty = "50005545"; + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50005545"); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", "p50005545"); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: MaskinportenDelegation performed by authenticated user 20000490 for the reportee party 50005545 of the jks_audi_etron_gt maskinporten schema resource from the resource registry, to the organization with orgNr 910459880 (partyId: 50005545) + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: MaskinportenDelegation returns 400 BadRequest with response body containing ValidationProblemDetails with error message that CoveredBy can not be the same as OfferedBy + /// + [Fact] + public async Task MaskinportenDelegation_DAGL_FromAndToIdenticalOrgNr() + { + // Arrange + string fromParty = "50005545"; + string toOrg = "910459880"; + + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(20000490, 50002598)); + + ValidationProblemDetails expectedResponse = GetExpectedValidationProblemDetails("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", toOrg); + StreamContent requestContent = GetRequestContent("MaskinportenScopeDelegation", "jks_audi_etron_gt", $"p{fromParty}", toOrg); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{fromParty}/maskinportenschema/offered", requestContent); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + string responseContent = await response.Content.ReadAsStringAsync(); + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20000490 is authorized to delegate the maskinportenchema on behalf of the reportee party 50005545. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The only right for the maskinportenschema scope-access-schema is delegable through having DAGL: + /// - scope-access-schema:ScopeAccess + /// Expected: DelegationCheck returns a list of RightDelegationStatus matching expected + /// + [Fact] + public async Task DelegationCheck_DAGL_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005545; + string resourceId = "scope-access-schema"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List expectedResponse = GetExpectedDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20001337 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// - The only right for the maskinportenschema scope-access-schema is delegable through having DAGL (and HADM inherits the same rights as DAGL): + /// - scope-access-schema:ScopeAccess + /// Expected: DelegationCheck returns a list of RightDelegationStatus matching expected + /// + [Fact] + public async Task DelegationCheck_HADM_HasDelegableRights() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50005545; + string resourceId = "scope-access-schema"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List expectedResponse = GetExpectedDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck bars use by private persons + /// In this case: + /// - The user 20000490 has PRIV role for itself (party 50002598) + /// - Only Organizations can delegate and get delegated maskinpostenschema + /// Expected: DelegationCheck returns a 403 Forbidden + /// + [Fact] + public async Task DelegationCheck_PRIV_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50002598; + string resourceId = "scope-access-schema"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: DelegationCheck is only made to be used for MaskinportenServices, not A3 apps + /// In this case: + /// - Since the resource is an AltinnApp, a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task DelegationCheck_AppRight_BadRequest() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50005545; + string resourceId = "org1_app1"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + ValidationProblemDetails expectedResponse = GetExpectedValidationError($"DelegationCheck", $"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: DelegationCheck when the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the invalid resource non_existing_id + /// In this case: + /// - Since the resource is invalid a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task DelegationCheck_InvalidResource_BadRequest() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50005545; + string resourceId = "non_existing_id"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + ValidationProblemDetails expectedResponse = GetExpectedValidationError("DelegationCheck", $"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: DelegationCheck is only made to be used for MaskinportenServices, not resource registry resources + /// In this case: + /// - Since the resource is an AltinnApp, a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task DelegationCheck_RRResource_BadRequest() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50005545; + string resourceId = "generic-access-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + ValidationProblemDetails expectedResponse = GetExpectedValidationError("DelegationCheck", $"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: DelegationCheck checks that minimum required access level is fulfilled + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545, meaning the resource scope-access-schema is delegable for the user + /// - The user is currently authorized with a level 2 while the resource requires a minum level of 3 + /// Expected: DelegationCheck returns a responce error matching expected + /// + [Fact] + public async Task DelegationCheck_InsufficientAccessLevel() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005545; + string resourceId = "scope-access-schema"; + + var token = PrincipalUtil.GetToken(userId, 0, 2); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + List expectedResponse = GetExpectedDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId, 2); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/{reporteePartyId}/maskinportenschema/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + private static IHttpContextAccessor GetHttpContextAccessorMock(string partytype, string id) + { + HttpContext httpContext = new DefaultHttpContext(); + httpContext.Request.RouteValues.Add(partytype, id); + + var httpContextAccessorMock = new Mock(); + httpContextAccessorMock.Setup(h => h.HttpContext).Returns(httpContext); + return httpContextAccessorMock.Object; + } + + private static List GetExpectedMaskinportenSchemaDelegations(string supplierOrg, string consumerOrg, List resourceIds) + { + List delegations = new List(); + delegations = TestDataUtil.GetAdminDelegations(supplierOrg, consumerOrg, resourceIds); + return delegations; + } + + private static StreamContent GetRequestContent(string operation, string resourceId, string from, string to, string inputFileName = "Input_Default") + { + Stream dataStream = File.OpenRead($"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/to_{to}/{inputFileName}.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + + private static RightsDelegationResponseExternal GetExpectedResponse(string operation, string resourceId, string from, string to, string responseFileName = "ExpectedOutput_Default") + { + string responsePath = $"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/to_{to}/{responseFileName}.json"; + string content = File.ReadAllText(responsePath); + return (RightsDelegationResponseExternal)JsonSerializer.Deserialize(content, typeof(RightsDelegationResponseExternal), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static ValidationProblemDetails GetExpectedValidationProblemDetails(string operation, string resourceId, string from, string to, string responseFileName = "ExpectedOutput_Default") + { + string responsePath = $"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/to_{to}/{responseFileName}.json"; + string content = File.ReadAllText(responsePath); + return (ValidationProblemDetails)JsonSerializer.Deserialize(content, typeof(ValidationProblemDetails), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static ValidationProblemDetails GetExpectedProblemDetails(string operation, string resourceId, string from, string to, string responseFileName = "ExpectedOutput_Default") + { + string responsePath = $"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/to_{to}/{responseFileName}.json"; + string content = File.ReadAllText(responsePath); + return (ValidationProblemDetails)JsonSerializer.Deserialize(content, typeof(ValidationProblemDetails), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static List GetExpectedDelegationStatus(string user, string from, string resourceId, int? authLevel = null) + { + string content; + if (authLevel == null) + { + content = File.ReadAllText($"Data/Json/MaskinportenSchema/DelegationCheck/{resourceId}/from_{from}/authn_{user}.json"); + } + else + { + content = File.ReadAllText($"Data/Json/MaskinportenSchema/DelegationCheck/{resourceId}/from_{from}/authn_{user}_authLevel{authLevel}.json"); + } + + return (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static ValidationProblemDetails GetExpectedValidationError(string operation, string user, string from, string resourceId, int? authLevel = null) + { + string content; + if (authLevel == null) + { + content = File.ReadAllText($"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/authn_{user}.json"); + } + else + { + content = File.ReadAllText($"Data/Json/MaskinportenSchema/{operation}/{resourceId}/from_{from}/authn_{user}_authLevel{authLevel}.json"); + } + + return (ValidationProblemDetails)JsonSerializer.Deserialize(content, typeof(ValidationProblemDetails), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static StreamContent GetDelegationCheckContent(string resourceId) + { + Stream dataStream = File.OpenRead($"Data/Json/MaskinportenSchema/DelegationCheck/{resourceId}/request.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + + private HttpClient GetTestClient(IPDP pdpMock = null, IHttpContextAccessor httpContextAccessor = null, IDelegationMetadataRepository delegationMetadataRepositoryMock = null) + { + pdpMock ??= new PepWithPDPAuthorizationMock(); + httpContextAccessor ??= new HttpContextAccessor(); + delegationMetadataRepositoryMock ??= new DelegationMetadataRepositoryMock(); + + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(delegationMetadataRepositoryMock); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(pdpMock); + services.AddSingleton(httpContextAccessor); + services.AddSingleton(); + services.AddSingleton(); + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + return client; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/PolicyInformationPointControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/PolicyInformationPointControllerTest.cs new file mode 100644 index 00000000..5b900ea4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/PolicyInformationPointControllerTest.cs @@ -0,0 +1,102 @@ +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// Test class for +/// +public class PolicyInformationPointControllerTest : IClassFixture> +{ + private HttpClient _client; + private readonly CustomWebApplicationFactory _factory; + private readonly JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + /// + /// Initializes a new instance of the class. + /// + /// CustomWebApplicationFactory + public PolicyInformationPointControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _client = GetTestClient(); + } + + private HttpClient GetTestClient(IDelegationMetadataRepository delegationMetadataRepositoryMock = null) + { + delegationMetadataRepositoryMock ??= new DelegationMetadataRepositoryMock(); + + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(delegationMetadataRepositoryMock); + services.AddSingleton(); + services.AddSingleton(); + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + return client; + } + + /// + /// Sets up test scenarios for + /// + public static TheoryData Scenarios() => new() + { + { "app_toPerson" }, + { "resource_toPerson" }, + { "app_toSystemUser" }, + { "resource_toSystemUser" } + }; + + /// + /// Test case: Tests if you can get all delegation changes for a resource + /// Expected: Returns delegation changes for a resource + /// + [Theory] + [MemberData(nameof(Scenarios))] + public async Task GetDelegationChanges_ValidResponse(string scenario) + { + // Act + HttpResponseMessage actualResponse = await _client.PostAsync($"accessmanagement/api/v1/policyinformation/getdelegationchanges", GetRequest(scenario)); + + // Assert + Assert.Equal(HttpStatusCode.OK, actualResponse.StatusCode); + + List actualDelegationChanges = JsonSerializer.Deserialize>(await actualResponse.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertEqual(GetExpected(scenario), actualDelegationChanges); + } + + private static StreamContent GetRequest(string scenario) + { + Stream dataStream = File.OpenRead($"Data/PolicyInformationPoint/Requests/{scenario}.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + + private List GetExpected(string scenario) + { + string expectedContent = File.ReadAllText($"Data/PolicyInformationPoint/Expected/{scenario}.json"); + return (List)JsonSerializer.Deserialize(expectedContent, typeof(List), options); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceControllerTest.cs new file mode 100644 index 00000000..d21b0e7b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceControllerTest.cs @@ -0,0 +1,272 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Enums.ResourceRegistry; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers +{ + /// + /// Tests for AccessManagmet Resource metadata + /// + [Collection("ResourceController Tests")] + public class ResourceControllerTest : IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + private readonly HttpClient _client; + + private readonly JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public ResourceControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _client = GetTestClient(); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + } + + /// + /// Test calling InsertAccessManagementResource with valid data + /// + /// + [Fact] + public async Task InsertAccessManagementResource_ResourceStored() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input1.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + string dataElement1 = await File.OpenText("Data/Json/InsertAccessManagementResource/InsertData_string.json").ReadToEndAsync(); + string dataElement2 = await File.OpenText("Data/Json/InsertAccessManagementResource/InsertData_string2.json").ReadToEndAsync(); + string expectedText = $"[{dataElement1},{dataElement2}]"; + List expected = JsonSerializer.Deserialize>(expectedText, options); + + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("platform", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + AssertionUtil.ListAccessManagementResourceAreEqual(expected, actual); + } + + /// + /// Test calling InsertAccessManagementResource with missing token + /// + /// + [Fact] + public async Task InsertAccessManagementResource_MissingBearerToken() + { + // Arrange + _client.DefaultRequestHeaders.Remove("Authorization"); + + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input1.json"); + StreamContent content = new StreamContent(dataStream); + + // Act + HttpResponseMessage response = await _client.PostAsync($"accessmanagement/api/v1/internal/resources", content); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test calling InsertAccessManagementResource with invalid token + /// + /// + [Fact] + public async Task InsertAccessManagementResource_InvalidBearerToken() + { + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input1.json"); + StreamContent content = new StreamContent(dataStream); + + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("UnitTest", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test calling InsertAccessManagementResource with empty body + /// + /// + [Fact] + public async Task InsertAccessManagementResource_NoInput() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input2.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + string expected = @"""Missing resources in body"""; + + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("platform", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + string actual = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, actual); + } + + /// + /// Test calling InsertAccessManagementResource with empty body + /// + /// + [Fact] + public async Task InsertAccessManagementResource_InvalidModel() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input3.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + string expectedErrorMessage = "The ResourceRegistryId field is required."; + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("platform", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actual = JsonSerializer.Deserialize(responseContent, options); + string actualErrorMessage = actual.Errors.Values.FirstOrDefault()[0]; + Assert.Equal(expectedErrorMessage, actualErrorMessage); + } + + /// + /// Test calling InsertAccessManagementResource with valid data one filing in write + /// + /// + [Fact] + public async Task InsertAccessManagementResource_ResourcePartialStored() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input4.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + string dataElement1 = await File.OpenText("Data/Json/InsertAccessManagementResource/InsertData_string.json").ReadToEndAsync(); + string dataElement2 = await File.OpenText("Data/Json/InsertAccessManagementResource/InsertData_string2.json").ReadToEndAsync(); + string expectedText = $"[{dataElement1},{dataElement2}]"; + List expected = JsonSerializer.Deserialize>(expectedText, options); + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("platform", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + string responseContent = await response.Content.ReadAsStringAsync(); + List actual = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + AssertionUtil.ListAccessManagementResourceAreEqual(expected, actual); + } + + /// + /// Test calling InsertAccessManagementResource with valid data one filing in write + /// + /// + [Fact] + public async Task InsertAccessManagementResource_AllFailed() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Json/InsertAccessManagementResource/input5.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + string expected = @"""Delegation could not be completed"""; + + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"accessmanagement/api/v1/internal/resources") + { + Content = content + }; + + httpRequestMessage.Headers.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken("platform", "resourceregistry")); + + // Act + HttpResponseMessage response = await _client.SendAsync(httpRequestMessage); + string actual = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(expected, actual); + } + + private HttpClient GetTestClient() + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + return client; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/AppsInstanceDelegationControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/AppsInstanceDelegationControllerTest.cs new file mode 100644 index 00000000..81aa68b0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/AppsInstanceDelegationControllerTest.cs @@ -0,0 +1,237 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Data; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Authorization.ProblemDetails; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Tests.Controllers; + +public class AppsInstanceDelegationControllerTest : IClassFixture> +{ + private readonly CustomWebApplicationFactory _factory; + private readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public AppsInstanceDelegationControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + } + + /// + /// Test case: GET apps/instancedelegation/{resourceId}/{instanceId}/delegationcheck + /// with a valid PlatformAccessToken for an app having xacml rules specifying rights available for delegation + /// Expected: - Should return 200 OK + /// Reason: See testdata cases for details + /// + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegationCheck_Ok), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task DelegationCheck_ValidToken_OK(string platformToken, string resourceId, string instanceId, Paginated expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/app/delegationcheck/resource/{resourceId}/instance/{instanceId}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + Paginated actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + + AssertionUtil.AssertPagination(expected, actual, AssertionUtil.AssertResourceRightDelegationCheckResultDto); + } + + /// + /// Test case: POST apps/instancedelegation/{resourceId}/{instanceId} + /// with a valid delegation + /// Expected: - Should return 200 OK + /// Reason: See testdat cases for details + /// + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateParallelReadForAppNoExistingPolicy), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateParallelSignForAppExistingPolicy), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateNormalReadForAppNoExistingPolicy), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateNormalSignForAppExistingPolicy), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateNormalReadForAppNoExistingPolicyOrganizatonNumber), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_Delegate_OK(string platformToken, AppsInstanceDelegationRequestDto request, string resourceId, string instanceId, AppsInstanceDelegationResponseDto expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/app/delegations/resource/{resourceId}/instance/{instanceId}", new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, MediaTypeNames.Application.Json)); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + AppsInstanceDelegationResponseDto actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertAppsInstanceDelegationResponseDto(expected, actual); + } + + /// + /// Test case: POST apps/instancedelegation/{resourceId}/{instanceId} + /// with a valid delegation + /// Expected: - Should return 200 OK + /// Reason: See testdat cases for details + /// + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.RevokeReadForAppOnlyExistingPolicyRevokeLast), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.RevokeReadForAppMultipleExistingPolicyRevoke), MemberType = typeof(TestDataAppsInstanceDelegation))] + [MemberData(nameof(TestDataAppsInstanceDelegation.RevokeReadForAppNoExistingPolicyRevokeLast), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_Revoke_OK(string platformToken, AppsInstanceDelegationRequestDto request, string resourceId, string instanceId, AppsInstanceRevokeResponseDto expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/app/delegationrevoke/resource/{resourceId}/instance/{instanceId}", new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, MediaTypeNames.Application.Json)); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + AppsInstanceRevokeResponseDto actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertAppsInstanceRevokeResponseDto(expected, actual); + } + + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.RevokeAll), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_RevokeAll_OK(string platformToken, string resourceId, string instanceId, Paginated expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.DeleteAsync($"accessmanagement/api/v1/app/delegationrevoke/resource/{resourceId}/instance/{instanceId}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + Paginated actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertPagination(expected, actual, AssertionUtil.AssertAppsInstanceRevokeResponseDto); + } + + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.RevokeAllUnathorized), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_NoToken_RevokeAll_Unauthorized(string resourceId, string instanceId) + { + var client = GetTestClient(null); + + // Act + HttpResponseMessage response = await client.DeleteAsync($"accessmanagement/api/v1/app/delegationrevoke/resource/{resourceId}/instance/{instanceId}"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: POST apps/instancedelegation/{resourceId}/{instanceId} + /// with a valid delegation + /// Expected: - Should return 200 OK + /// Reason: See testdat cases for details + /// + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateReadForAppNoExistingPolicyNoResponceDBWrite), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_Delegate_DBWriteFails(string platformToken, AppsInstanceDelegationRequestDto request, string resourceId, string instanceId, AppsInstanceDelegationResponseDto expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/app/delegations/resource/{resourceId}/instance/{instanceId}", new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, MediaTypeNames.Application.Json)); + + // Assert + Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode); + + AppsInstanceDelegationResponseDto actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertAppsInstanceDelegationResponseDto(expected, actual); + } + + /// + /// Test case: POST apps/instancedelegation/{resourceId}/{instanceId} + /// with a valid delegation + /// Expected: - Should return 200 OK + /// Reason: See testdat cases for details + /// + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.DelegateToPartyNotExisting), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_Delegate_InvalidParty(string platformToken, AppsInstanceDelegationRequestDto request, string resourceId, string instanceId, AltinnProblemDetails expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/app/delegations/resource/{resourceId}/instance/{instanceId}", new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, MediaTypeNames.Application.Json)); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + AltinnProblemDetails actual = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), options); + TestDataAppsInstanceDelegation.AssertAltinnProblemDetailsEqual(expected, actual); + } + + [Theory] + [MemberData(nameof(TestDataAppsInstanceDelegation.GetAllAppDelegatedInstances), MemberType = typeof(TestDataAppsInstanceDelegation))] + public async Task AppsInstanceDelegationController_ValidToken_Get_OK(string platformToken, string resourceId, string instanceId, Paginated expected) + { + var client = GetTestClient(platformToken); + + // Act + HttpResponseMessage response = await client.GetAsync($"accessmanagement/api/v1/app/delegations/resource/{resourceId}/instance/{instanceId}"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + Paginated actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertPagination(expected, actual, AssertionUtil.AssertAppsInstanceDelegationResponseDto); + } + + private static void WithPDPMock(IServiceCollection services) => services.AddSingleton(new PepWithPDPAuthorizationMock()); + + private HttpClient GetTestClient(string token, params Action[] actions) + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + foreach (var action in actions) + { + action(services); + } + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + if (token != null) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + client.DefaultRequestHeaders.Add("PlatformAccessToken", token); + return client; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesControllerTest.cs new file mode 100644 index 00000000..40202185 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/ResourceOwnerAPI/ResourceOwnerAuthorizedPartiesControllerTest.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Data; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// Test class for +/// +[Collection("ResourceOwnerAuthorizedPartiesController Tests")] +public class ResourceOwnerAuthorizedPartiesControllerTest : IClassFixture> +{ + private readonly CustomWebApplicationFactory _factory; + private readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public ResourceOwnerAuthorizedPartiesControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + } + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// without valid token + /// Expected: - Should return 401 Unauthorized + /// Reason: Operation requires valid token + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.UnauthenticatedNoValidToken), MemberType = typeof(TestDataAuthorizedParties))] + public async Task PostResourceOwnerAuthorizedParties_InvalidToken_Unauthorized(string resourceOwnerToken) + { + var client = GetTestClient(resourceOwnerToken); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2={true}", null); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid token but missing required scope + /// Expected: - Should return 403 Forbidden + /// Reason: Operation requires valid token with authorized scope + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.ValidResourceOwnerTokenMissingScope), MemberType = typeof(TestDataAuthorizedParties))] + public async Task PostResourceOwnerAuthorizedParties_ValidToken_MissingAuthorizationScope_Forbidden(string resourceOwnerToken) + { + var client = GetTestClient(resourceOwnerToken, WithPDPMock); + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2={true}", null); + + // Assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid token including authorized scope + /// Expected: - Should return 200 OK + /// - Should return the expected Authorized Party list for the requested party + /// Reason: See individual test case description in + /// + [Theory] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetPersonList_ByPersonId), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetPersonList_ByPersonUuid), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetPersonList_ByPartyId), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetPersonList_ByUserId), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetPersonList_ByPersonId_InclResourcesThroughRoles), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetOrgList_ByOrganizationNumber), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetOrgList_ByOrganizationUuid), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetOrgList_ByPartyId), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetOrgList_ByOrganizationNumber_InclResourcesThroughRoles), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUsername), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUuid), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetEnterpriseUserList_ByUserId), MemberType = typeof(TestDataAuthorizedParties))] + [MemberData(nameof(TestDataAuthorizedParties.ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUsername_InclResourcesThroughRoles), MemberType = typeof(TestDataAuthorizedParties))] + public async Task PostResourceOwnerAuthorizedParties_Ok(string resourceOwnerToken, BaseAttributeExternal attributeExt, bool inclA2, bool inclRoleResources, List expected) + { + var client = GetTestClient(resourceOwnerToken); + + // Act + HttpResponseMessage response = await client.PostAsync( + $"accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2={inclA2}&includeAuthorizedResourcesThroughRoles={inclRoleResources}", + new StringContent(JsonSerializer.Serialize(attributeExt), Encoding.UTF8, MediaTypeNames.Application.Json)); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actual = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync(), options); + AssertionUtil.AssertCollections(expected, actual, TestDataAuthorizedParties.AssertAuthorizedPartyExternalEqual); + } + + private static void WithPDPMock(IServiceCollection services) => services.AddSingleton(new PepWithPDPAuthorizationMock()); + + private HttpClient GetTestClient(string token, params Action[] actions) + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + foreach (var action in actions) + { + action(services); + } + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + return client; + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/RightsInternalControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/RightsInternalControllerTest.cs new file mode 100644 index 00000000..c44b40fc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/RightsInternalControllerTest.cs @@ -0,0 +1,1711 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Mime; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers +{ + /// + /// Test class for + /// + [Collection("RightsInternalController Tests")] + public class RightsInternalControllerTest : IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + + private readonly string sblInternalToken = PrincipalUtil.GetAccessToken("sbl.authorization"); + + private readonly JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public RightsInternalControllerTest(CustomWebApplicationFactory factory) + { + _factory = factory; + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000095 have for the From party 50005545 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50005545) has delegated the "Park" action directly to the user. + /// - The From unit (50005545) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_UserDelegation_KeyRoleUnitDelegation_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50005545", "u20000095", false); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50005545", "u20000095"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000095 have for the From party 50005545 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50005545) has delegated the "Park" action directly to the user. + /// - The From unit (50005545) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_UserDelegation_KeyRoleUnitDelegation_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50005545", "u20000095", true); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50005545", "u20000095"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50005545 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_DAGL_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50005545", "u20000490", false); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50005545", "u20000490"); + + // Act + var client = GetTestClient(sblInternalToken); + + var response = await client.PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50005545 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_DAGL_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50005545", "u20000490", true); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50005545", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20001337 have for the From party 50005545 for the digdirs_company_car resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_HADM_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("digdirs_company_car", "p50005545", "u20001337", false); + StreamContent requestContent = GetRightsQueryRequestContent("digdirs_company_car", "p50005545", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20001337 have for the From party 50005545 for the digdirs_company_car resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_HADM_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("digdirs_company_car", "p50005545", "u20001337", true); + StreamContent requestContent = GetRightsQueryRequestContent("digdirs_company_car", "p50005545", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50004221 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "Race" action directly to the user. + /// - The main unit (50004222) has delegated the "Park" action to the user. + /// - The main unit (50004222) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_UserDelegation_MainUnitToUserDelegation_MainUnitToKeyRoleDelegation_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50004221", "u20000490", false); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50004221", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50004221 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "Race" action directly to the user. + /// - The main unit (50004222) has delegated the "Park" action to the user. + /// - The main unit (50004222) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_ResourceRight_UserDelegation_MainUnitToUserDelegation_MainUnitToKeyRoleDelegation_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("jks_audi_etron_gt", "p50004221", "u20000490", true); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50004221", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20001337 have for the From party 50001337 for the Altinn App org1/app1. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_AppRight_UserDelegation_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("org1_app1", "p50001337", "u20001337", false); + StreamContent requestContent = GetRightsQueryRequestContent("org1_app1", "p50001337", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20001337 have for the From party 50001337 for the Altinn App org1/app1. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_AppRight_UserDelegation_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("org1_app1", "p50001337", "u20001337", true); + StreamContent requestContent = GetRightsQueryRequestContent("org1_app1", "p50001337", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50005545 for the Altinn App ttd/rf-0002. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_AppRight_DAGL_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedRights("ttd_rf-0002", "p50005545", "u20000490", false); + StreamContent requestContent = GetRightsQueryRequestContent("ttd_rf-0002", "p50005545", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: RightsQuery returns a list of rights the To userid 20000490 have for the From party 50005545 for the Altinn App ttd/rf-0002. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user has Permit for the rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task RightsQuery_AppRight_DAGL_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedRights("ttd_rf-0002", "p50005545", "u20000490", true); + StreamContent requestContent = GetRightsQueryRequestContent("ttd_rf-0002", "p50005545", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/rights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20000490 is able to delegate to others, for the From party 50005545 for the Altinn App ttd/rf-0002. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// Expected: GetDelegableRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_AppRight_DAGL_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("ttd_rf-0002", "p50005545", "u20000490", false); + StreamContent requestContent = GetRightsQueryRequestContent("ttd_rf-0002", "p50005545", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20000490 is able to delegate to others, for the From party 50005545 for the Altinn App ttd/rf-0002. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user can delegate the right (which is indicated by the CanDelegate bool). + /// Expected: GetDelegableRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_AppRight_DAGL_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("ttd_rf-0002", "p50005545", "u20000490", true); + StreamContent requestContent = GetRightsQueryRequestContent("ttd_rf-0002", "p50005545", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20000490 is able to delegate to others, for the From party 50004221 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "Race" action directly to the user. + /// - The main unit (50004222) has delegated the "Park" action to the user. + /// - The main unit (50004222) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_ResourceRight_UserDelegation_MainUnitToUserDelegation_MainUnitToKeyRoleDelegation_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("jks_audi_etron_gt", "p50004221", "u20000490", false); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50004221", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20000490 is able to delegate to others, for the From party 50004221 for the jks_audi_etron_gt resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "Race" action directly to the user. + /// - The main unit (50004222) has delegated the "Park" action to the user. + /// - The main unit (50004222) has delegated the "Drive" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user can delegate the right (which is indicated by the CanDelegate bool). + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_ResourceRight_UserDelegation_MainUnitToUserDelegation_MainUnitToKeyRoleDelegation_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("jks_audi_etron_gt", "p50004221", "u20000490", true); + StreamContent requestContent = GetRightsQueryRequestContent("jks_audi_etron_gt", "p50004221", "u20000490"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20001337 is able to delegate to others, for the From party 50005545 for the digdirs_company_car resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_ResourceRight_HADM_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("digdirs_company_car", "p50005545", "u20001337", false); + StreamContent requestContent = GetRightsQueryRequestContent("digdirs_company_car", "p50005545", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20001337 is able to delegate to others, for the From party 50005545 for the digdirs_company_car resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user can delegate the right (which is indicated by the CanDelegate bool). + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_ResourceRight_HADM_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("digdirs_company_car", "p50005545", "u20001337", true); + StreamContent requestContent = GetRightsQueryRequestContent("digdirs_company_car", "p50005545", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20001337 is able to delegate to others, for the From party 50001337 for the Altinn App org1/app1. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_AppRight_UserDelegation_ReturnAllPolicyRights_False() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("org1_app1", "p50001337", "u20001337", false); + StreamContent requestContent = GetRightsQueryRequestContent("org1_app1", "p50001337", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegableRightsQuery returns a list of rights the To userid 20001337 is able to delegate to others, for the From party 50001337 for the Altinn App org1/app1. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// - The returnAllPolicyRights query param is set to True and operation should return all rights found in the resource registry XACML policy whether or not the user can delegate the right (which is indicated by the CanDelegate bool). + /// Expected: GetRights returns a list of right matching expected + /// + [Fact] + public async Task DelegableRightsQuery_AppRight_UserDelegation_ReturnAllPolicyRights_True() + { + // Arrange + List expectedRights = GetExpectedDelegableRights("org1_app1", "p50001337", "u20001337", true); + StreamContent requestContent = GetRightsQueryRequestContent("org1_app1", "p50001337", "u20001337"); + + // Act + HttpResponseMessage response = await GetTestClient(sblInternalToken).PostAsync($"accessmanagement/api/v1/internal/query/delegablerights/?returnAllPolicyRights=true", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + List actualRights = JsonSerializer.Deserialize>(responseContent, options); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + AssertionUtil.AssertCollections(expectedRights, actualRights, AssertionUtil.AssertRightExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - 6 out of 9 of the rights for the resource: generic-access-resource is delegable through having DAGL: + /// - generic-access-resource:read + /// - generic-access-resource:admai-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_DAGL_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005545; + string resourceId = "generic-access-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + // Delegable, AccessLists fail + [Fact] + public async Task DelegationCheck_GenericAccessListsResource_DAGL_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005545; + string resourceId = "generic-accesslist-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + // Tilgangsstyrer som ikke er dagl + [Fact] + public async Task DelegationCheck_GenericAccessListsResource_ADMAI_HasNotDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50004221; + string resourceId = "generic-accesslist-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + // On behalf of a privatperson ikke org sÃ¥ fail pÃ¥ helperfunction + [Fact] + public async Task DelegationCheck_GenericAccessListsResource_PRIV_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50002598; + string resourceId = "generic-accesslist-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the app ttd/apps-test. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - 8 out of 10 of the rights for the app: ttd/apps-test is delegable through having DAGL: + /// - apps-test,ttd:instantiate + /// - apps-test,ttd:read + /// - apps-test,ttd,Task_1:read + /// - apps-test,ttd,Task_1:write + /// - apps-test,EndEvent_1,ttd:read + /// - apps-test,EndEvent_1,ttd:write + /// - apps-test,ttd:delete + /// - apps-test,events,ttd:read + /// - 2 out of the 10 rights is only available to the service owner and is removed entirly from the result as it is not available for any end users + /// - apps-test,EndEvent_1,ttd:complete + /// - apps-test,ttd:write + /// - Also some of the rules is also available to the service owner in those cases only the detail for this access is removed from the result this is for + /// - apps-test,ttd:instantiate + /// - apps-test,ttd:read + /// + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected: 8 Delegable with roles returned Delegable as role is correct, 2 Not connected to any roles filtered away. All Rule details for Service Owner is Filtered away + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_DAGL_HasTheDelegableRightsExistingForEndUsers() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005545; + string resourceId = "ttd_apps-test"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005546 for the app ttd/apps-test. + /// In this case: + /// - The user 20000490 has no rights for the From unit 50005546 + /// - 8 out of 10 of the rights for the app: ttd/apps-test is delegable through having Roles (DAGL, REGNA, ADMAI): + /// - apps-test,ttd:instantiate + /// - apps-test,ttd:read + /// - apps-test,ttd,Task_1:read + /// - apps-test,ttd,Task_1:write + /// - apps-test,EndEvent_1,ttd:read + /// - apps-test,EndEvent_1,ttd:write + /// - apps-test,ttd:delete + /// - apps-test,events,ttd:read + /// - 2 out of the 10 rights is only available to the service owner and is removed entirly from the result as it is not available for any end users + /// - apps-test,EndEvent_1,ttd:complete + /// - apps-test,ttd:write + /// - Also some of the rules is also available to the service owner in those cases only the detail for this access is removed from the result this is for + /// - apps-test,ttd:instantiate + /// - apps-test,ttd:read + /// + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected: 8 Delegable with roles returned but not delegable as role is missing, 2 Not connected to any roles filtered away. All Rule details for Service Owner is Filtered away + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_NoRoleOrRights_AllRightsNotDelegableServiceOwnerRightsFilteredAway() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50005546; + string resourceId = "ttd_apps-test"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of itself (partyId 50002598) for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 has PRIV role for itself (party 50002598) + /// - 5 out of 9 of the rights for the resource: generic-access-resource is delegable through having PRIV: + /// - generic-access-resource:read + /// - generic-access-resource:write + /// - generic-access-resource:admai-delegated-action + /// - generic-access-resource,priv-delegation-subtask:delegated-action-to-user + /// - generic-access-resource,priv-delegation-subtask:delegated-action-to-keyroleunit + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_PRIV_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50002598; + string resourceId = "generic-access-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated userid 20001337 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// - 6 out of 9 of the rights for the resource: generic-access-resource is delegable through having HADM (which inheirits same rights for delegation as DAGL): + /// - generic-access-resource:read + /// - generic-access-resource:admai-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_HADM_HasDelegableRights() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50005545; + string resourceId = "generic-access-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated 20000490 is authorized to delegate on behalf of the reportee party 50004221 for the generic-access-resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "subunit-delegated-action" action directly to the user. + /// - The From unit (50004221) has delegated the "subunit-delegated-action-to-keyunit" action directly to the user. + /// - The main unit (50004222) has delegated the "mainunit-delegated-action" action to the user. + /// - The main unit (50004222) has delegated the "mainunit-delegated-action-to-keyunit" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// - 4 out of 8 rights are thus delegable and should contain the information of the actual recipient of the delegation + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected + /// + [Fact] + public async Task DelegationCheck_GenericAccessResource_SubUnitToUserDelegation_SubUnitToKeyRoleUnitDelegation_MainUnitToUserDelegation_MainUnitToKeyRoleUnitDelegation_HasDelegableRights() + { + // Arrange + int userId = 20000490; + int reporteePartyId = 50004221; + string resourceId = "generic-access-resource"; + + var token = PrincipalUtil.GetToken(userId, 0, 3); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the org1_app1 Altinn App. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// Expected: DelegationCheck returns a list of RightDelegationCheckResult matching expected + /// + [Fact] + public async Task DelegationCheck_AppRight_UserDelegation_HasDelegableRights() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50001337; + string resourceId = "org1_app1"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the 1337_1338 Altinn 2 service. + /// In this case: + /// - The test scenario is setup using existing test data for 1337/1338, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "1338,1337,task1:sign" and "rightKey": "1338,1337,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// Expected: DelegationCheck returns a list of RightDelegationStatus matching expected + /// + [Fact] + public async Task DelegationCheck_ServiceRight_UserDelegation_HasDelegableRights() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50001337; + string resourceId = "se_1337_1338"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + + List expectedResponse = GetExpectedRightDelegationStatus($"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + List actualResponse = JsonSerializer.Deserialize>(responseContent, options); + AssertionUtil.AssertCollections(expectedResponse, actualResponse, AssertionUtil.AssertRightDelegationCheckExternalEqual); + } + + /// + /// Test case: DelegationCheck returns a list of rights the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the invalid resource non_existing_id + /// In this case: + /// - Since the resource is invalid a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task DelegationCheck_InvalidResource_BadRequest() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50001337; + string resourceId = "non_existing_id"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + + ValidationProblemDetails expectedResponse = GetExpectedValidationError("DelegationCheck", $"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: DelegationCheck when the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the MaskinportenSchema resource jks_audi_etron_gt + /// In this case: + /// - Since the resource is a MaskinportenSchema a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task DelegationCheck_MaskinportenSchema_BadRequest() + { + // Arrange + int userId = 20001337; + int reporteePartyId = 50001337; + string resourceId = "jks_audi_etron_gt"; + + var token = PrincipalUtil.GetToken(userId, 0, 4); + + ValidationProblemDetails expectedResponse = GetExpectedValidationError("DelegationCheck", $"u{userId}", $"p{reporteePartyId}", resourceId); + StreamContent requestContent = GetDelegationCheckContent(resourceId); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{reporteePartyId}/rights/delegation/delegationcheck", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The user is delegating: + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToPerson_ByDagl_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, "27099450067", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The user is delegating: + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToSystemUser_ByDagl_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, string.Empty, "16C1F2F6-9E00-4922-B16D-74C46D948E61", 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The user is delegating: + /// - generic-access-resource2,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource2,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource2,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource2,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource2_FromOrg_ToSystemUser_ByDagl_ResourceNotAllowed() + { + // Arrange + string resourceId = "generic-access-resource2"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, string.Empty, "16C1F2F6-9E00-4922-B16D-74C46D948E61", 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "failure"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + ValidationProblemDetails expectedResponse = GetExpectedRightsDelegationError(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the app: ttd/apps-test from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The user is delegating: + /// - ttd,apps-test:read + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_App_FromOrg_ToSystemUser_ByDagl_Success() + { + // Arrange + string resourceId = "app_ttd_apps-test"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, string.Empty, "9D569A55-D5CE-4914-BBF8-CA3474458604", 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 is DAGL for the From unit 50005545 + /// - The user is delegating: + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - The recipient is a person identified through user UUID + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToUserUuid_ByDagl_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid) from = ("910459880", string.Empty, 50005545, string.Empty); + (string OrgNo, string Ssn, string Uuid) to = (string.Empty, string.Empty, "00000000-0000-0000-0005-000000003899"); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty); + string scenario = "success"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns validation problem details when trying to delegate to SSN without specifying last name of recipient + /// Expected: Delegation returns validation problem details + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToPerson_ByDagl_MissingToLastName() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, "27099450067", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "missing-to-lastname"; + + string token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + ValidationProblemDetails expectedResponse = GetExpectedRightsDelegationError(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of itself (partyId 50002598) for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 has PRIV role for itself (party 50002598) + /// - The user delegates: + /// - generic-access-resource:read + /// - generic-access-resource:write + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromPerson_ToPerson_ByPriv_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = (string.Empty, "07124912037", 50002598, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, "27099450067", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.Ssn, to.Ssn, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.Ssn, to.Ssn, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000490 is authorized to delegate on behalf of itself (partyId 50002598) for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 has PRIV role for itself (party 50002598) + /// - The user delegates: + /// - generic-access-resource:read + /// - generic-access-resource:write + /// - The To organization is identified by it's organization uuid: 00000000-0000-0000-0001-000000000004 + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromPerson_ToOrganizationUuid_ByPriv_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid) from = (string.Empty, "07124912037", 50002598, string.Empty); + (string OrgNo, string Ssn, string Uuid) to = (string.Empty, string.Empty, "00000000-0000-0000-0001-000000000004"); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.Ssn, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.Ssn, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20001337 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20001337 is HADM for the From unit 50005545 + /// - The user is using HADM privilege to self delegate rights + /// - 5 out of 8 of the rights for the resource: generic-access-resource is delegable through having HADM (which inheirits same rights for delegation as DAGL): + /// - generic-access-resource:read + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action + /// - generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToPerson_ByHadm_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, "27099450067", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20001337, 0, string.Empty, "27099450067", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated 20000490 is authorized to delegate on behalf of the reportee party 50004221 for the generic-access-resource from the resource registry. + /// In this case: + /// - The From unit (50004221) is a subunit of 500042222. + /// - The From unit (50004221) has delegated the "subunit-delegated-action" action directly to the user. + /// - The From unit (50004221) has delegated the "subunit-delegated-action-to-keyunit" action directly to the user. + /// - The main unit (50004222) has delegated the "mainunit-delegated-action" action to the user. + /// - The main unit (50004222) has delegated the "mainunit-delegated-action-to-keyunit" action to the party 50005545 where the user is DAGL and have keyrole privileges. + /// - 4 out of 8 rights are thus delegable and should contain the information of the actual recipient of the delegation + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromSubunit_ToOrg_ByDelegation_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("810418532", string.Empty, 50004221, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = ("810418672", string.Empty, string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000095 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 has the roles ADMAI and UTINN for the From unit 50005545 + /// - The UTINN gives the user access to delegate: + /// - generic-access-resource:admai-delegated-action + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToEcUser_ByAdmai_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Username, string Uuid, int UuidType) to = (string.Empty, string.Empty, "OrstaECUser", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000095, 0, string.Empty, "02056260016", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Username, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Username, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated userid 20000095 is authorized to delegate on behalf of the reportee party 50005545 for the generic-access-resource from the resource registry. + /// In this case: + /// - The user 20000490 has the roles ADMAI and UTINN for the From unit 50005545 + /// - The UTINN gives the user access to delegate: + /// - generic-access-resource:admai-delegated-action + /// - The Enterprise user is identified in To attribute by it's user Uuid: 00000000-0000-0000-0002-000000010727 + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_GenericAccessResource_FromOrg_ToEcUserUuid_ByAdmai_Success() + { + // Arrange + string resourceId = "generic-access-resource"; + (string OrgNo, string Ssn, int PartyId, string Uuid) from = ("910459880", string.Empty, 50005545, string.Empty); + (string OrgNo, string Ssn, string Username, string Uuid) to = (string.Empty, string.Empty, string.Empty, "00000000-0000-0000-0002-000000010727"); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid) by = (20000095, 0, string.Empty, "02056260016", string.Empty, string.Empty); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Uuid, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the org1_app1 Altinn App. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// - The user is trying to delegate: + /// - app1,org1:read + /// - app1,org1:write + /// - The user only have delegable rights for app1,org1:read + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_AppRight_PartialSuccess() + { + // Arrange + string resourceId = "app_org1_app1"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910001337", string.Empty, 50001337, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = ("810418672", string.Empty, string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20001337, 0, string.Empty, "27099450067", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation returns a list of rights the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the org1_app1 Altinn App. + /// In this case: + /// - The test scenario is setup using existing test data for Org1/App1, offeredBy 50001337 and coveredbyuser 20001337, where the delegation policy contains rules for resources not in the App policy: + /// ("rightKey": "app1,org1,task1:sign" and "rightKey": "app1,org1,task1:write"). This should normally not happen but can become an real scenario where delegations have been made and then the resource/app policy is changed to remove some rights. + /// - The user is trying to delegate: + /// - app1,org1:read + /// - app1,org1:write + /// - The user only have delegable rights for app1,org1:read + /// Expected: Delegation returns a RightsDelegationResponse matching expected + /// + [Fact] + public async Task Delegation_Altinn2Service_Success() + { + // Arrange + string resourceId = "se_2802_2203"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910459880", string.Empty, 50005545, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = (string.Empty, "27099450067", string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20000490, 0, string.Empty, "07124912037", string.Empty, string.Empty, 0); + string scenario = "success"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + RightsDelegationResponseExternal expectedResponse = GetExpectedRightsDelegationResponse(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.Ssn, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + RightsDelegationResponseExternal actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertRightsDelegationResponseExternalEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation when the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the invalid resource non_existing_id + /// In this case: + /// - Since the resource is invalid a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task Delegation_InvalidResource_BadRequest() + { + // Arrange + string resourceId = "non_existing_id"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910001337", string.Empty, 50001337, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = ("810418672", string.Empty, string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20001337, 0, string.Empty, "27099450067", string.Empty, string.Empty, 0); + string scenario = "invalid-resource"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + ValidationProblemDetails expectedResponse = GetExpectedRightsDelegationError(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Delegation when the authenticated 20001337 is authorized to delegate on behalf of the reportee party 50001337 for the MaskinportenSchema resource jks_audi_etron_gt + /// In this case: + /// - Since the resource is a MaskinportenSchema a BadRequest response with a ValidationProblemDetails model response should be returned + /// Expected: Responce error model is matching expected + /// + [Fact] + public async Task Delegation_MaskinportenSchema_BadRequest() + { + // Arrange + string resourceId = "jks_audi_etron_gt"; + (string OrgNo, string Ssn, int PartyId, string Uuid, int UuidType) from = ("910001337", string.Empty, 50001337, string.Empty, 0); + (string OrgNo, string Ssn, string Uuid, int UuidType) to = ("810418672", string.Empty, string.Empty, 0); + (int UserId, int PartyId, string OrgNo, string Ssn, string Username, string Uuid, int UuidType) by = (20001337, 0, string.Empty, "27099450067", string.Empty, string.Empty, 0); + string scenario = "invalid-resource-maskinportenschema"; + + var token = PrincipalUtil.GetToken(by.UserId, 0, 3); + + ValidationProblemDetails expectedResponse = GetExpectedRightsDelegationError(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + StreamContent requestContent = GetRightsDelegationContent(resourceId, from.OrgNo, to.OrgNo, by.Ssn, scenario); + + // Act + HttpResponseMessage response = await GetTestClient(token).PostAsync($"accessmanagement/api/v1/internal/{from.PartyId}/rights/delegation/offered", requestContent); + string responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + + ValidationProblemDetails actualResponse = JsonSerializer.Deserialize(responseContent, options); + AssertionUtil.AssertValidationProblemDetailsEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: Revoke given delegation + /// Expected: - Should return 201 + /// + /// + [Theory] + [MemberData(nameof(TestDataRevokeOfferedDelegationExternal.FromPersonToPerson), MemberType = typeof(TestDataRevokeOfferedDelegationExternal))] + [MemberData(nameof(TestDataRevokeOfferedDelegationExternal.FromPersonToOrganization), MemberType = typeof(TestDataRevokeOfferedDelegationExternal))] + [MemberData(nameof(TestDataRevokeOfferedDelegationExternal.FromOrganizationToOrganization), MemberType = typeof(TestDataRevokeOfferedDelegationExternal))] + [MemberData(nameof(TestDataRevokeOfferedDelegationExternal.FromOrganizationToPerson), MemberType = typeof(TestDataRevokeOfferedDelegationExternal))] + public async Task RevokeRightsOfferedDelegations_ReturnNoContent(string userToken, RevokeOfferedDelegationExternal input, string partyRouteValue, string headerKey = null, string headerValue = null) + { + var client = GetTestClient(userToken, WithPDPMock); + if (headerKey != null && headerValue != null) + { + client.DefaultRequestHeaders.Add(headerKey, headerValue); + } + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/internal/{partyRouteValue}/rights/delegation/offered/revoke", new StringContent(JsonSerializer.Serialize(input), new MediaTypeHeaderValue(MediaTypeNames.Application.Json))); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + /// + /// Test case: Revoke given delegation + /// Expected: - Should return 201 + /// + /// + // [MemberData(nameof(TestDataRevokeReceivedDelegationExternal.FromOrganizationToEnterpriseuser), MemberType = typeof(TestDataRevokeReceivedDelegationExternal))] + [Theory] + [MemberData(nameof(TestDataRevokeReceivedDelegationExternal.FromPersonToPerson), MemberType = typeof(TestDataRevokeReceivedDelegationExternal))] + [MemberData(nameof(TestDataRevokeReceivedDelegationExternal.FromPersonToOrganization), MemberType = typeof(TestDataRevokeReceivedDelegationExternal))] + [MemberData(nameof(TestDataRevokeReceivedDelegationExternal.FromOrganizationToOrganization), MemberType = typeof(TestDataRevokeReceivedDelegationExternal))] + [MemberData(nameof(TestDataRevokeReceivedDelegationExternal.FromOrganizationToPerson), MemberType = typeof(TestDataRevokeReceivedDelegationExternal))] + public async Task RevokeRightsReceivedDelegations_ReturnNoContent(string userToken, RevokeReceivedDelegationExternal input, string partyRouteValue, string headerKey = null, string headerValue = null) + { + var client = GetTestClient(userToken, WithPDPMock); + if (headerKey != null && headerValue != null) + { + client.DefaultRequestHeaders.Add(headerKey, headerValue); + } + + // Act + HttpResponseMessage response = await client.PostAsync($"accessmanagement/api/v1/internal/{partyRouteValue}/rights/delegation/received/revoke", new StringContent(JsonSerializer.Serialize(input), new MediaTypeHeaderValue(MediaTypeNames.Application.Json))); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + private static Action WithHttpContextAccessorMock(string partytype, string id) + { + return services => + { + HttpContext httpContext = new DefaultHttpContext(); + httpContext.Request.RouteValues.Add(partytype, id); + + var mock = new Mock(); + mock.Setup(h => h.HttpContext).Returns(httpContext); + services.AddSingleton(mock.Object); + }; + } + + private void WithPDPMock(IServiceCollection services) => services.AddSingleton(new PepWithPDPAuthorizationMock()); + + private HttpClient GetTestClient(string token, params Action[] actions) + { + HttpClient client = _factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(new DelegationChangeEventQueueMock()); + services.AddSingleton(new AuthenticationMock()); + services.AddSingleton(new AccessListsAuthorizationClientMock()); + + foreach (var action in actions) + { + action(services); + } + }); + }).CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + return client; + } + + private static List GetExpectedRights(string resourceId, string from, string to, bool returnAllPolicyRights) + { + string rightsPath = $"Data/Json/RightsQuery/{resourceId}/from_{from}/to_{to}/expected_rights_returnall_{returnAllPolicyRights.ToString().ToLower()}.json"; + string content = File.ReadAllText(rightsPath); + return (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static List GetExpectedDelegableRights(string resourceId, string from, string to, bool returnAllPolicyRights) + { + string rightsPath = $"Data/Json/DelegableRightsQuery/{resourceId}/from_{from}/to_{to}/expected_rights_returnall_{returnAllPolicyRights.ToString().ToLower()}.json"; + string content = File.ReadAllText(rightsPath); + return (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static List GetExpectedRightDelegationStatus(string user, string from, string resourceId) + { + string content = File.ReadAllText($"Data/Json/DelegationCheck/{resourceId}/from_{from}/authn_{user}.json"); + return (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static ValidationProblemDetails GetExpectedValidationError(string operation, string user, string from, string resourceId) + { + string content = File.ReadAllText($"Data/Json/{operation}/{resourceId}/from_{from}/authn_{user}.json"); + return (ValidationProblemDetails)JsonSerializer.Deserialize(content, typeof(ValidationProblemDetails), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static ValidationProblemDetails GetExpectedRightsDelegationError(string resourceId, string from, string to, string by, string scenario) + { + string content = File.ReadAllText($"Data/Json/RightsDelegation/{resourceId}/from_{from}/to_{to}/by_{by}/{scenario}_response.json"); + return (ValidationProblemDetails)JsonSerializer.Deserialize(content, typeof(ValidationProblemDetails), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static RightsDelegationResponseExternal GetExpectedRightsDelegationResponse(string resourceId, string from, string to, string by, string scenario) + { + string content = File.ReadAllText($"Data/Json/RightsDelegation/{resourceId}/from_{from}/to_{to}/by_{by}/{scenario}_response.json"); + return (RightsDelegationResponseExternal)JsonSerializer.Deserialize(content, typeof(RightsDelegationResponseExternal), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + private static StreamContent GetRightsQueryRequestContent(string resourceId, string from, string to) + { + Stream dataStream = File.OpenRead($"Data/Json/RightsQuery/{resourceId}/from_{from}/to_{to}/RightsQuery.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + + private static StreamContent GetDelegationCheckContent(string resourceId) + { + Stream dataStream = File.OpenRead($"Data/Json/DelegationCheck/{resourceId}/request.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + + private static StreamContent GetRightsDelegationContent(string resourceId, string from, string to, string by, string scenario) + { + Stream dataStream = File.OpenRead($"Data/Json/RightsDelegation/{resourceId}/from_{from}/to_{to}/by_{by}/{scenario}_request.json"); + StreamContent content = new StreamContent(dataStream); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + return content; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2AuthorizedPartiesControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2AuthorizedPartiesControllerTest.cs new file mode 100644 index 00000000..b7113fab --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2AuthorizedPartiesControllerTest.cs @@ -0,0 +1,324 @@ +using System.Net.Http.Json; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Altinn.AccessManagement.Tests.Seeds; +using Microsoft.VisualBasic; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// +/// +public class V2AuthorizedPartiesControllerTest(WebApplicationFixture fixture) : IClassFixture +{ + private WebApplicationFixture Fixture { get; } = fixture; + + private static Action WithAssertDbContainsDelegations(IParty from, IAccessManagementResource resource) => test => + { + test.ApiAssertions.Add(async host => + { + var delegations = await host.Repository.DelegationMetadataRepository.GetAllCurrentAppDelegationChanges(from.Party.PartyId.SingleToList(), resource.DbResource.ResourceRegistryId.SingleToList()); + Assert.True( + delegations.Count > 0, + $"Couldn't find any delegations from {from.Party.PartyId} to app {resource.DbResource.ResourceRegistryId}"); + }); + }; + + private static Action WithAssertSuccessfulResponse(params Func, string>[] asserts) => test => + { + test.ResponseAssertions.Add(async response => + { + if (response.IsSuccessStatusCode) + { + var authorizedParties = await response.Content.ReadFromJsonAsync>(); + var result = new List(); + foreach (var assert in asserts) + { + if (assert(authorizedParties) is var msg && !string.IsNullOrEmpty(msg)) + { + result.Add(msg); + } + } + + Assert.True(result.Count == 0, string.Join("\n", result)); + } + }); + }; + + private static Func, string> WithAssertResponseContainsPartyWithInstance(string resourceId, string instanceId) => response => + { + var result = response.Exists(authorizedParty => authorizedParty.AuthorizedInstances.Exists(instance => instance.ResourceId == resourceId && instance.InstanceId == instanceId)); + if (result) + { + return null; + } + + return $"Response don't contain authorized party with instance delegations with resource Id {resourceId} and instance id {instanceId}"; + }; + + private static Func, string> WithAssertResponseContainsSubUnitWithInstance(string resourceId, string instanceId) => response => + { + var result = response.Exists(authorizedParty => authorizedParty.Subunits.Exists(authorizedSubUnit => authorizedSubUnit.AuthorizedInstances.Exists(instance => instance.ResourceId == resourceId && instance.InstanceId == instanceId))); + if (result) + { + return null; + } + + return $"Response don't contain authorized party with subunit having instance delegations with resource Id {resourceId} and instance id {instanceId}"; + }; + + private static Func, string> WithAssertResponseContainsParty(IParty party) => response => + { + var result = response.Exists(authorizedParty => authorizedParty.PartyId == party.Party.PartyId); + if (result) + { + return null; + } + + return $"Response don't contain any reportees with party ID {party.Party.PartyId} ({party.Party.Name})"; + }; + + private static Func, string> WithAssertResponseContainsNotParty(IParty party) => response => + { + var result = response.Exists(authorizedParty => authorizedParty.PartyId == party.Party.PartyId); + if (result) + { + return $"Response should not contain reportees with party ID {party.Party.PartyId} ({party.Party.Name})"; + } + + return null; + }; + + private static Func, string> WithAssertResponseContainsNotInstance(string resourceId, string instanceId) => response => + { + var result = response.Exists(authorizedParty => authorizedParty.AuthorizedInstances.Any(instance => instance.ResourceId == resourceId && instance.InstanceId == instanceId)); + if (result) + { + return $"Response should not contain any instance delegations with resource Id {resourceId} and instance id {instanceId}"; + } + + return null; + }; + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// modifiers for + public class GetAuthorizedParties(string acceptanceCriteria, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + WithRequestRoute("accessmanagement", "api", "v1", "authorizedparties"), + WithRequestVerb(HttpMethod.Get)) + { + /// + /// Seeds + /// + public static TheoryData Seeds() => [ + new( + /* Acceptance Critieria: User Receiving Instance Access from an Individual */ @" + GIVEN a user who has received instance delegation directly from an individual + WHEN the user's list of authorized parties is retrieved + THEN the access list should contain the individual who delegated the instance access + AND the individual's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation", + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Kasper.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "chalk"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, PersonSeeds.Kasper.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Olav.Defaults, PersonSeeds.Kasper.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + TokenScenario.PersonToken(PersonSeeds.Paula.Defaults) + ), + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsNotParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "chalk"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2"), + WithAssertResponseContainsParty(PersonSeeds.Kasper.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Olav.Defaults), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1") + ) + ), + new( + /* Acceptance Critieria: User Receiving Instance Access from a Primary Unit */ @" + GIVEN a user who has received instance delegation from a primary unit + WHEN the user's list of authorized parties is retrieved + THEN the access list should contain the primary unit from which the instance access is delegated + AND the primary unit's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation + AND if the user has no other permissions for the primary unit or its subunits, no other subunits should be present in the list of authorized parties", + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.WhereUnitHasMainUnit(OrganizationSeeds.VossAccounting.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "sponge"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Olav.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_3"), + TokenScenario.PersonToken(PersonSeeds.Paula.Defaults) + ), + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsParty(OrganizationSeeds.VossConsulting.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Olav.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "sponge"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_3") + ) + ), + new( + /* Acceptance Critieria: User Receiving Instance Access from a Subunit */ @" + GIVEN a user who has received instance delegation from a subunit + WHEN the user's list of authorized parties is retrieved + THEN the list of authorized parties should include the subunit from which the instance access is delegated + AND the subunit's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation + AND the list of authorized parties should also include the primary unit of the subunit + AND with no additional authorized roles/resources/instances and the flag 'onlyHierarchyElementWithNoAccess': true", + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.WhereUnitHasMainUnit(OrganizationSeeds.VossAccounting.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "water"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Olav.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_3"), + TokenScenario.PersonToken(PersonSeeds.Paula.Defaults) + ), + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsParty(OrganizationSeeds.VossConsulting.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Olav.Defaults), + WithAssertResponseContainsSubUnitWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "water"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_3") + ) + ), + ]; + } + + /// + /// + /// + /// acceptance test + [Theory] + [MemberData(nameof(GetAuthorizedParties.Seeds), MemberType = typeof(GetAuthorizedParties))] + public async Task GET_AuthorizedParties(GetAuthorizedParties acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// partyId + /// modifiers for + public class GetAuthorizedPartiesAsAccessManager(string acceptanceCriteria, int partyId, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + WithRequestRoute("accessmanagement", "api", "v1", partyId, "authorizedparties"), + WithRequestVerb(HttpMethod.Get)) + { + /// + /// Seeds + /// + public static TheoryData Seeds() => [ + new( + /* Acceptance Critieria: Organization Receiving Instance Access from an Individual */ @" + GIVEN a user holding a key role (e.g., DAGL/ECKeyRole) for an organization that has received instance delegation from an individual + WHEN the user's list of authorized parties is retrieved + THEN the list of authorized parties should include the individual from whom the instance access is delegated + AND the individual's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation", + OrganizationSeeds.VossConsulting.PartyId, + WithScenarios( + DelegationScenarios.Defaults, + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults), + DelegationScenarios.WherePersonHasKeyRole(PersonSeeds.Olav.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "frame_1"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Kasper.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "frame_2"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Olav.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsParty(PersonSeeds.Kasper.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "frame_1"), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "frame_2"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2") + ) + ), + new( + /* Acceptance Critieria: User Receiving Instance Access from a Subunit */ @" + GIVEN an organization that has received instance delegation from an individual + WHEN the organization's list of authorized parties is retrieved + THEN the list of authorized parties should contain the individual from whom the instance access is delegated + AND the individual's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation", + OrganizationSeeds.VossConsulting.PartyId, + WithScenarios( + DelegationScenarios.Defaults, + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults), + DelegationScenarios.WherePersonHasKeyRole(PersonSeeds.Olav.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "frame_1"), + DelegationScenarios.WithInstanceDelegation(PersonSeeds.Kasper.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "frame_2"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Olav.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsParty(PersonSeeds.Kasper.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsNotParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "frame_1"), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "frame_2"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2") + ) + ), + new( + /* Acceptance Critieria: Organization Receiving Instance Access from a Primary Unit */ @" + GIVEN an organization that has received instance delegation from a primary unit + WHEN the organization's list of authorized parties is retrieved + THEN the list of authorized parties should contain the primary unit from which the instance access is delegated + AND the primary unit's AuthorizedInstances should include an identifier specifying the resourceId and instanceId for the instance delegation + AND if the organization has no other permissions for the primary unit or its subunits, no other subunits should be present in the list of authorized parties", + OrganizationSeeds.VossConsulting.PartyId, + WithScenarios( + DelegationScenarios.Defaults, + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults), + DelegationScenarios.WherePersonHasKeyRole(PersonSeeds.Olav.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.WhereUnitHasMainUnit(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossAccounting.Defaults, OrganizationSeeds.VossConsulting.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "color_1"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_1"), + DelegationScenarios.WithInstanceDelegation(OrganizationSeeds.VossConsulting.Defaults, PersonSeeds.Olav.Defaults, ResourceSeeds.ChalkboardResource.Defaults, "should_not_be_in_result_list_2"), + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertSuccessfulResponse( + WithAssertResponseContainsParty(OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Paula.Defaults), + WithAssertResponseContainsNotParty(PersonSeeds.Olav.Defaults), + WithAssertResponseContainsPartyWithInstance(ResourceSeeds.ChalkboardResource.Identifier, "color_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_1"), + WithAssertResponseContainsNotInstance(ResourceSeeds.ChalkboardResource.Identifier, "should_not_be_in_result_list_2") + ) + ) + ]; + } + + /// + /// + /// + /// acceptance test + [Theory] + [MemberData(nameof(GetAuthorizedPartiesAsAccessManager.Seeds), MemberType = typeof(GetAuthorizedPartiesAsAccessManager))] + public async Task GET_AuthorizedPartiesAsAccessManager(GetAuthorizedPartiesAsAccessManager acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2MaskinportenSchemaControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2MaskinportenSchemaControllerTest.cs new file mode 100644 index 00000000..a8cd0e0e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2MaskinportenSchemaControllerTest.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Altinn.AccessManagement.Tests.Seeds; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// +/// +public class V2MaskinportenSchemaControllerTest(WebApplicationFixture fixture) : IClassFixture +{ + private WebApplicationFixture Fixture { get; } = fixture; + + /// + /// Verifies that a delegation from and to party exists in database + /// + public static Action WithAssertDbContainsDelegationsToParty(int from, int to, string resource) => test => + { + test.ApiAssertions.Add(async host => + { + var actual = await host.Repository.DelegationMetadataRepository.GetAllCurrentResourceRegistryDelegationChanges(from.SingleToList(), resource.SingleToList(), to.SingleToList()); + Assert.NotEmpty(actual); + }); + }; + + /// + /// Assert response + /// + /// delegated from + /// delegation to + /// + public static Action WithAssertResponseContainsDelegations(IParty from, IParty to) => test => + { + test.ResponseAssertions.Add(async response => + { + var body = await response.Content.ReadFromJsonAsync>(); + + Assert.True( + body.Any(delegation => delegation.OfferedByPartyId == from.Party.PartyId && delegation.CoveredByPartyId == to.Party.PartyId), + $"Body did not contain a delegation from party with id {from.Party.PartyId} to party with id {to.Party.PartyId}"); + }); + }; + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// party id + /// modifiers for + public class SeedGetOfferedMaskinportenSchemaDelegations(string acceptanceCriteria, int partyId, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + + WithRequestRoute("accessmanagement", "api", "v1", partyId, "maskinportenschema", "offered"), + WithRequestVerb(HttpMethod.Get)) + { + /// + /// Seeds + /// + public static TheoryData Seeds() => + [ + new( + /* Acceptance Criteria */ @" + GIVEN that organization Voss consulting has delegated a MaskinportenSchema resource to Voss Accounting + WHEN DAGL Olav for voss consulting requests delegations that Voss consulting has offered + THEN Voss accounting should be in the list of offered delegations", + OrganizationSeeds.VossConsulting.PartyId, + + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.FromOrganizationToOrganization(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.MaskinportenSchema.Defaults)), + + WithAssertDbContainsDelegationsToParty(OrganizationSeeds.VossConsulting.PartyId, OrganizationSeeds.VossAccounting.PartyId, ResourceSeeds.MaskinportenSchema.Identifier), + WithAssertResponseContainsDelegations(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults), + WithAssertResponseStatusCodeSuccessful) + ]; + } + + /// + /// + /// + /// acceptance criteria + [Theory] + [MemberData(nameof(SeedGetOfferedMaskinportenSchemaDelegations.Seeds), MemberType = typeof(SeedGetOfferedMaskinportenSchemaDelegations))] + public async Task GET_GetOfferedMaskinportenSchemaDelegations(SeedGetOfferedMaskinportenSchemaDelegations acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2ResourceControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2ResourceControllerTest.cs new file mode 100644 index 00000000..f622a705 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2ResourceControllerTest.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// +/// +public class V2ResourceControllerTest(WebApplicationFixture fixture) : IClassFixture +{ + private WebApplicationFixture Fixture { get; } = fixture; + + /// + /// Asserts that resource exists in DB + /// + /// excpected resource to exsist + /// + public static Action WithAssertResourceExistsInDb(AccessManagementResource expected) => test => + { + test.ApiAssertions.Add(async host => + { + await Task.CompletedTask; + }); + }; + + /// + /// Test input + /// + private static readonly AccessManagementResource TestAltinnApp = new() + { + Created = DateTime.Today, + Modified = DateTime.Today, + ResourceId = 1, + ResourceRegistryId = "test_id123", + ResourceType = ResourceType.AltinnApp + }; + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// modifiers for + public class SeedPostUpsertResource(string acceptanceCriteria, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + WithRequestRoute("accessmanagement", "api", "v1", "internal", "resources"), + WithRequestVerb(HttpMethod.Post)) + { + /// + /// Seeds + /// + public static TheoryData Seeds() => + [ + new( + /* Acceptance Criteria */ @" + GIVEN a resource is upserted in resource registry + WHEN resource registry forwards the resource + THEN the resource should be stored", + + WithHttpRequestBodyJson>([TestAltinnApp]), + + WithScenarios(TokenScenario.PlatformToken("platform", "resourceregistry")), + + WithAssertResponseStatusCodeSuccessful, + WithAssertResourceExistsInDb(TestAltinnApp)) + ]; + } + + /// + /// + /// + /// acceptance criteria + [Theory(DisplayName = "POST_UpsertResource")] + [MemberData(nameof(SeedPostUpsertResource.Seeds), MemberType = typeof(SeedPostUpsertResource))] + public async Task POST_UpsertResource(SeedPostUpsertResource acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2RightsInternalControllerTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2RightsInternalControllerTest.cs new file mode 100644 index 00000000..6baf54d6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Controllers/V2RightsInternalControllerTest.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Altinn.AccessManagement.Tests.Seeds; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Controllers; + +/// +/// +/// +public class V2RightsInternalControllerTest(WebApplicationFixture fixture) : IClassFixture +{ + private WebApplicationFixture Fixture { get; } = fixture; + + private static Action WithAssertDbContainsDelegations(IParty from, IAccessManagementResource resource) => test => + { + test.ApiAssertions.Add(async host => + { + var delegations = await host.Repository.DelegationMetadataRepository.GetAllCurrentAppDelegationChanges(from.Party.PartyId.SingleToList(), resource.DbResource.ResourceRegistryId.SingleToList()); + Assert.True( + delegations.Count > 0, + $"Couldn't find any delegations from {from.Party.PartyId} to app {resource.DbResource.ResourceRegistryId}"); + }); + }; + + private static Action WithAssertResponseContainsDelegationToUserProfile(IParty from, IUserProfile to) => test => + { + test.ResponseAssertions.Add(async response => + { + var delegations = await response.Content.ReadFromJsonAsync>(); + var result = delegations + .Where(delegation => delegation.To.Any(attribute => attribute.Value == to.UserProfile.UserId.ToString())) + .Where(delegation => delegation.From.Any(attribute => attribute.Value == from.Party.PartyId.ToString())); + + Assert.True(result.Any(), $"Response don't contain any delegations from '{from.Party.Name}' with party ID '{from.Party.PartyId}' to user profile '{to.UserProfile.Party.Name}' with user ID '{to.UserProfile.UserId}'"); + }); + }; + + private static Action WithAssertResponseContainsDelegationToParty(IParty from, IParty to) => test => + { + test.ResponseAssertions.Add(async response => + { + var delegations = await response.Content.ReadFromJsonAsync>(); + var result = delegations + .Where(delegation => delegation.To.Any(attribute => attribute.Value == to.Party.PartyId.ToString())) + .Where(delegation => delegation.From.Any(attribute => attribute.Value == from.Party.PartyId.ToString())); + + Assert.True(result.Any(), $"Response don't contain any delegations from '{from.Party.Name}' with party ID '{from.Party.PartyId}' to party '{to.Party.Name}' with party ID '{to.Party.PartyId}'"); + }); + }; + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// partyId in URL + /// modifiers for + public class SeedGetRightsDelegationsOffered(string acceptanceCriteria, int partyId, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + WithRequestRoute("accessmanagement", "api", "v1", "internal", partyId, "rights", "delegation", "offered"), + WithRequestVerb(HttpMethod.Get)) + { + /// + /// Seeds + /// + public static TheoryData Seeds() => [ + new( + /* Acceptance Critieria */ @" + GIVEN that organization Voss Accounting has an active delegation to employee Paula + WHEN DAGL Olav for Orstad Accounting requests offered delegations from Orstad Accounting + THEN Paula should be included in the list of offered delegations", + OrganizationSeeds.VossAccounting.PartyId, + + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.FromOrganizationToPerson(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults), + DelegationScenarios.WherePersonHasKeyRole(PersonSeeds.Olav.Defaults, OrganizationSeeds.VossAccounting.Defaults), + TokenScenario.PersonToken(PersonSeeds.Olav.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertResponseContainsDelegationToUserProfile(OrganizationSeeds.VossAccounting.Defaults, PersonSeeds.Paula.Defaults)), + + new( + /* Acceptance Critieria */ @" + GIVEN that organization Voss Consulting has delegations to organization Voss Accounting + WHEN DAGL Paula for Voss Consulting requests offered delegations from Voss Consulting + THEN Voss Accounting should be included in the list of offered delegations", + OrganizationSeeds.VossConsulting.PartyId, + + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.WherePersonHasKeyRole(PersonSeeds.Paula.Defaults, OrganizationSeeds.VossConsulting.Defaults), + DelegationScenarios.FromOrganizationToOrganization(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.AltinnApp.Defaults), + TokenScenario.PersonToken(PersonSeeds.Paula.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertResponseContainsDelegationToParty(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults)), + new( + /* Acceptance Critieria */ @" + GIVEN that organization Voss Consulting has active app delegations to organization Voss Accounting + AND app is deleted + WHEN DAGL Paula for Voss Consulting requests offered delegations from Voss Consulting + THEN Voss Accounting should be included in the list of offered delegations + AND organization name and partyid of deleted app should be included in the list of offered delegations", + OrganizationSeeds.VossConsulting.PartyId, + + WithScenarios( + DelegationScenarios.Defaults, + DelegationScenarios.FromOrganizationToOrganization(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.AltinnApp.Defaults), + DelegationScenarios.WithoutResource(ResourceSeeds.AltinnApp.Defaults)), + + WithAssertResponseStatusCodeSuccessful, + WithAssertResponseContainsDelegationToParty(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults)), + ]; + } + + /// + /// + /// + /// acceptance test + [Theory] + [MemberData(nameof(SeedGetRightsDelegationsOffered.Seeds), MemberType = typeof(SeedGetRightsDelegationsOffered))] + public async Task GET_RightsDelegationsOffered(SeedGetRightsDelegationsOffered acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/CustomWebApplicationFactory.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/CustomWebApplicationFactory.cs new file mode 100644 index 00000000..261e0273 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/CustomWebApplicationFactory.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.Configuration; + +namespace Altinn.AccessManagement.Tests +{ + /// + /// CustomWebApplicationFactory for integration tests + /// + /// Entrypoint + public class CustomWebApplicationFactory : WebApplicationFactory + where TStartup : class + { + /// + /// ConfigureWebHost for setup of configuration and test services + /// + /// IWebHostBuilder + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + var appsettings = new ConfigurationBuilder() + .AddJsonFile("appsettings.test.json") + .AddInMemoryCollection(new Dictionary + { + ["Logging:LogLevel:*"] = "Warning", + }); + + builder.UseConfiguration(appsettings.Build()); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100002.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100002.json new file mode 100644 index 00000000..1cd827e4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100002.json @@ -0,0 +1,32 @@ +[ + { + "PartyTypeName": 1, + "SSN": "01017270071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100002, + "PartyUUID": "00000000-0000-0000-0001-000000000002", + "UnitType": null, + "Name": "PERSON TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null, + "AuthorizedRoles": [ "PRIV" ] + }, + { + "PartyTypeName": 1, + "SSN": "01017170071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100001, + "PartyUUID": "00000000-0000-0000-0001-000000000001", + "UnitType": null, + "Name": "PERSON TO PERSON DELEGATOR", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null, + "AuthorizedRoles": [ "UTINN" ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100005.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100005.json new file mode 100644 index 00000000..015b7c42 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100005.json @@ -0,0 +1,32 @@ +[ + { + "PartyTypeName": 1, + "SSN": "01017570071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100005, + "PartyUUID": "00000000-0000-0000-0001-000000000005", + "UnitType": null, + "Name": "PERSON TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null, + "AuthorizedRoles": [ "PRIV" ] + }, + { + "PartyTypeName": 1, + "SSN": "01017370071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100003, + "PartyUUID": "00000000-0000-0000-0001-000000000003", + "UnitType": null, + "Name": "PERSON TO ORG DELEGATOR", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null, + "AuthorizedRoles": [ "UTINN" ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100009.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100009.json new file mode 100644 index 00000000..2af03d24 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100009.json @@ -0,0 +1,63 @@ +[ + { + "PartyTypeName": 1, + "SSN": "01017970071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100009, + "PartyUUID": "00000000-0000-0000-0001-000000000009", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null, + "AuthorizedRoles": [ "PRIV" ] + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000006", + "Person": null, + "Organization": null, + "PartyId": 50100006, + "PartyUUID": "00000000-0000-0000-0001-000000000006", + "UnitType": "AS", + "Name": "AUTHORIZEDPARTIES MAINUNIT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "REGNA" ], + "ChildParties": [ + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000007", + "Person": null, + "Organization": null, + "PartyId": 50100007, + "PartyUUID": "00000000-0000-0000-0001-000000000007", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "REGNA", "SISKD" ], + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000008", + "Person": null, + "Organization": null, + "PartyId": 50100008, + "PartyUUID": "00000000-0000-0000-0001-000000000008", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "REGNA" ], + "ChildParties": null + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100010.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100010.json new file mode 100644 index 00000000..5fc9faeb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100010.json @@ -0,0 +1,18 @@ +[ + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000010", + "PartyId": 50100010, + "PartyUuid": "00000000-0000-0000-0001-000000000010", + "UnitType": "AS", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "ECKEYROLE" + ], + "ChildParties": null + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100011.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100011.json new file mode 100644 index 00000000..5d3aa33f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/SBLBridge/authorizedparties_u20100011.json @@ -0,0 +1,63 @@ +[ + { + "PartyTypeName": 1, + "SSN": "01018170071", + "OrgNumber": "", + "Person": null, + "Organization": null, + "PartyId": 50100011, + "PartyUUID": "00000000-0000-0000-0001-000000000011", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "PRIV" ], + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000006", + "Person": null, + "Organization": null, + "PartyId": 50100006, + "PartyUUID": "00000000-0000-0000-0001-000000000006", + "UnitType": "AS", + "Name": "AUTHORIZEDPARTIES MAINUNIT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "UTINN" ], + "ChildParties": [ + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000007", + "Person": null, + "Organization": null, + "PartyId": 50100007, + "PartyUUID": "00000000-0000-0000-0001-000000000007", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "UTINN", "APIADM" ], + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000008", + "Person": null, + "Organization": null, + "PartyId": 50100008, + "PartyUUID": "00000000-0000-0000-0001-000000000008", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "AuthorizedRoles": [ "UTINN" ], + "ChildParties": null + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAppsInstanceDelegation.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAppsInstanceDelegation.cs new file mode 100644 index 00000000..43e5132c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAppsInstanceDelegation.cs @@ -0,0 +1,336 @@ +using System.Text.Json; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Authorization.ProblemDetails; +using Dapper; + +namespace Altinn.AccessManagement.Tests.Data; + +public static class TestDataAppsInstanceDelegation +{ + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + private static readonly string AppId = "app_ttd_am-devtest-instancedelegation"; + + private static readonly string InstanceIdParallelNewPolicy = "0191579e-72bc-7977-af5d-f9e92af4393b"; + + private static readonly string InstanceIdParallelExistingPolicy = "00000000-0000-0000-0000-000000000001"; + + private static readonly string InstanceIdNewPolicyNoResponceOnWrite = "00000000-0000-0000-0000-000000000002"; + + private static readonly string InstanceIdNormalNewPolicy = "00000000-0000-0000-0000-000000000003"; + + private static readonly string InstanceIdNormalExistingPolicy = "00000000-0000-0000-0000-000000000005"; + + private static readonly string InstanceIdInvalidParty = "00000000-0000-0000-0000-000000000006"; + + private static readonly string InstanceIdNormalNewPolicyOrgNumber = "00000000-0000-0000-0000-000000000007"; + + private static readonly string ListOfDelegationsForAnInstance = "00000000-0000-0000-0000-000000000008"; + + private static readonly string RevokeOneOfExistingDelegations = "00000000-0000-0000-0000-000000000009"; + + private static readonly string RevokeAllInstance = "00000000-0000-0000-0000-000000000010"; + + /// + /// Test case: GET v1/apps/instancedelegation/{resourceId}/{instanceId}/delegationcheck + /// with: + /// - a valid app authenticated as the delegater, authenticated with PlatformAccessToken + /// - valid resource for instance delegation + /// - xacml policy file for resource to be delegated configured with rights available for delegation by the authenticated app + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData> DelegationCheck_Ok() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + AppId, + InstanceIdParallelNewPolicy, + GetExpectedResponse>("DelegationCheck", AppId, InstanceIdParallelNewPolicy) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to ParallelSigning + /// - no policy file with existing rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateParallelReadForAppNoExistingPolicy() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdParallelNewPolicy), + AppId, + InstanceIdParallelNewPolicy, + GetExpectedResponse("Delegation", AppId, InstanceIdParallelNewPolicy) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to ParallelSigning + /// - existing policy existing with rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateParallelSignForAppExistingPolicy() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdParallelExistingPolicy), + AppId, + InstanceIdParallelExistingPolicy, + GetExpectedResponse("Delegation", AppId, InstanceIdParallelExistingPolicy) + } + }; + + public static TheoryData RevokeReadForAppOnlyExistingPolicyRevokeLast() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Revoke", AppId, InstanceIdParallelExistingPolicy), + AppId, + InstanceIdParallelExistingPolicy, + GetExpectedResponse("Revoke", AppId, InstanceIdParallelExistingPolicy) + } + }; + + public static TheoryData RevokeReadForAppMultipleExistingPolicyRevoke() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Revoke", AppId, RevokeOneOfExistingDelegations), + AppId, + RevokeOneOfExistingDelegations, + GetExpectedResponse("Revoke", AppId, RevokeOneOfExistingDelegations) + } + }; + + public static TheoryData> RevokeAll() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + AppId, + RevokeAllInstance, + GetExpectedResponse>("Revoke", AppId, RevokeAllInstance) + } + }; + + public static TheoryData RevokeAllUnathorized() => new() + { + { + AppId, + RevokeAllInstance + } + }; + + public static TheoryData RevokeReadForAppNoExistingPolicyRevokeLast() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Revoke", AppId, InstanceIdNewPolicyNoResponceOnWrite), + AppId, + InstanceIdNewPolicyNoResponceOnWrite, + GetExpectedResponse("Revoke", AppId, InstanceIdNewPolicyNoResponceOnWrite) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to Normal + /// - no policy file with existing rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateReadForAppNoExistingPolicyNoResponceDBWrite() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdNewPolicyNoResponceOnWrite), + AppId, + InstanceIdNewPolicyNoResponceOnWrite, + GetExpectedResponse("Delegation", AppId, InstanceIdNewPolicyNoResponceOnWrite) + } + }; + + public static TheoryData DelegateToPartyNotExisting() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdInvalidParty), + AppId, + InstanceIdInvalidParty, + GetExpectedResponse("Delegation", AppId, InstanceIdInvalidParty) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to ParallelSigning + /// - no policy file with existing rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateNormalReadForAppNoExistingPolicy() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdNormalNewPolicy), + AppId, + InstanceIdNormalNewPolicy, + GetExpectedResponse("Delegation", AppId, InstanceIdNormalNewPolicy) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to ParallelSigning + /// - no policy file with existing rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateNormalReadForAppNoExistingPolicyOrganizatonNumber() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdNormalNewPolicyOrgNumber), + AppId, + InstanceIdNormalNewPolicyOrgNumber, + GetExpectedResponse("Delegation", AppId, InstanceIdNormalNewPolicyOrgNumber) + } + }; + + /// + /// Test case: POST v1/apps/instancedelegation/{resourceId}/{instanceId} + /// with: + /// - a valid app as the delegater + /// - valid resource for instance delegation + /// - Instancedelegation mode set to ParallelSigning + /// - existing policy existing with rights delegated + /// Expected: - Should return 200 OK + /// - Should include the delegated rights + /// Reason: Apps defined in the policy file should be able to delegate the defined rights + /// + public static TheoryData DelegateNormalSignForAppExistingPolicy() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + GetRequest("Delegation", AppId, InstanceIdNormalExistingPolicy), + AppId, + InstanceIdNormalExistingPolicy, + GetExpectedResponse("Delegation", AppId, InstanceIdNormalExistingPolicy) + } + }; + + public static TheoryData> GetAllAppDelegatedInstances() => new() + { + { + PrincipalUtil.GetAccessToken("ttd", "am-devtest-instancedelegation"), + AppId, + ListOfDelegationsForAnInstance, + GetExpectedResponse>("Get", AppId, ListOfDelegationsForAnInstance) + } + }; + + public static void AssertAltinnProblemDetailsEqual(AltinnProblemDetails expected, AltinnProblemDetails actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Instance, actual.Instance); + Assert.Equal(expected.Detail, actual.Detail); + Assert.Equal(expected.Type, actual.Type); + Assert.Equal(expected.Title, actual.Title); + Assert.Equal(expected.ErrorCode, actual.ErrorCode); + AssertionUtil.AssertCollections(expected.Extensions.ToDictionary(), actual.Extensions.ToDictionary(), AssertProblemDetailsExtensionEqual); + } + + public static void AssertProblemDetailsExtensionEqual(KeyValuePair expected, KeyValuePair actual) + { + Assert.Equal(expected.Key, actual.Key); + JsonElement? actualJson = actual.Value as JsonElement?; + JsonElement? expectedJson = expected.Value as JsonElement?; + + if (actualJson == null) + { + Assert.Null(expectedJson); + return; + } + + Assert.NotNull(actualJson); + Assert.NotNull(expectedJson); + + var actualExtensionList = actualJson.Value.EnumerateArray().AsList(); + var expectedExtensionList = expectedJson.Value.EnumerateArray().AsList(); + Assert.Equal(expectedExtensionList.Count, actualExtensionList.Count); + + for (int i = 0; i < actualExtensionList.Count; i++) + { + ErrorDetails expectedDetail = JsonSerializer.Deserialize(expectedExtensionList[i].GetRawText(), JsonOptions); + ErrorDetails actualDetail = JsonSerializer.Deserialize(actualExtensionList[i].GetRawText(), JsonOptions); + Assert.Equal(expectedDetail.Code, actualDetail.Code); + Assert.Equal(expectedDetail.Detail, actualDetail.Detail); + + if (expectedDetail.Paths == null) + { + Assert.Null(expectedDetail.Paths); + return; + } + + Assert.NotNull(actualDetail.Paths); + Assert.NotNull(expectedDetail.Paths); + + Assert.Equal(expectedDetail.Paths.Count, actualDetail.Paths.Count); + for (int j = 0; j < expectedDetail.Paths.Count; j++) + { + Assert.Equal(expectedDetail.Paths[j], actualDetail.Paths[j]); + } + } + } + + internal class ErrorDetails + { + public string Code { get; set; } + + public string Detail { get; set; } + + public List Paths { get; set; } + } + + private static T GetExpectedResponse(string operation, string appId, string instanceId) + { + string content = File.ReadAllText($"Data/Json/AppsInstanceDelegation/{operation}/{appId}/{instanceId}/response.json"); + return (T)JsonSerializer.Deserialize(content, typeof(T), JsonOptions); + } + + private static T GetRequest(string operation, string appId, string instanceId) + { + string content = File.ReadAllText($"Data/Json/AppsInstanceDelegation/{operation}/{appId}/{instanceId}/request.json"); + return (T)JsonSerializer.Deserialize(content, typeof(T), JsonOptions); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAuthorizedParties.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAuthorizedParties.cs new file mode 100644 index 00000000..38715380 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/AuthorizedParties/TestDataAuthorizedParties.cs @@ -0,0 +1,675 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Util; +using Altinn.AccessManagement.Tests.Utils; +using Microsoft.AspNetCore.Mvc; +using Xunit; +using static System.Collections.Specialized.BitVector32; + +namespace Altinn.AccessManagement.Tests.Data; + +/// +/// Test data builder for testing AuthorizedParties +/// +public static class TestDataAuthorizedParties +{ +#pragma warning disable SA1600 // Elements should be documented + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + private static string OnlyAltinn3 => "OnlyAltinn3"; + + private static string BothAltinn3AndAltinn2 => "BothAltinn3AndAltinn2"; + + private static string InclResourcesThroughRoles => "InclResourcesThroughRoles"; + + public static int PersonToPerson_FromUserId => 20100001; + + public static int PersonToPerson_FromPartyId => 50100001; + + public static int PersonToPerson_ToUserId => 20100002; + + public static int PersonToPerson_ToPartyId => 50100002; + + public static int PersonToOrg_FromUserId => 20100003; + + public static int PersonToOrg_FromPartyId => 50100003; + + public static int PersonToOrg_ToOrgPartyId => 50100004; + + public static int PersonToOrg_ToOrgDaglUserId => 20100005; + + public static int PersonToOrg_ToOrgDaglPartyId => 50100005; + + public static int MainUnit_PartyId => 50100006; + + public static int SubUnit_PartyId => 50100007; + + public static int SubUnitTwo_PartyId => 50100008; + + public static int MainUnitAndSubUnitToPerson_ToUserId => 20100009; + + public static int MainUnitAndSubUnitToPerson_ToPartyId => 50100009; + + public static string MainUnitAndSubUnitToOrg_ToOrgOrganizationNumber => "901000010"; + + public static string MainUnitAndSubUnitToOrg_ToOrgOrganizationUuid => "00000000-0000-0000-0001-000000000010"; + + public static int MainUnitAndSubUnitToOrg_ToOrgPartyId => 50100010; + + public static string MainUnitAndSubUnitToOrg_ToOrgDaglPersonId => "01018170071"; + + public static string MainUnitAndSubUnitToOrg_ToOrgDaglPersonUuid => "00000000-0000-0000-0001-000000000011"; + + public static int MainUnitAndSubUnitToOrg_ToOrgDaglUserId => 20100011; + + public static int MainUnitAndSubUnitToOrg_ToOrgDaglPartyId => 50100011; + + public static string MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUsername => "MainUnit_And_SubUnit_ToOrg_EcKeyRole_User"; + + public static string MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUserUuid => "00000000-0000-0000-0002-000000000010"; + + public static int MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUserId => 20100010; + + public static int SubUnitToPerson_ToUserId => 20100012; + + public static int SubUnitToPerson_ToPartyId => 50100012; + +#pragma warning restore SA1600 // Elements should be documented + + /// + /// Sets up a request without a valid token + /// + public static TheoryData UnauthenticatedNoValidToken() => new() + { + { + string.Empty + } + }; + + /// + /// Sets up a request with a valid token but missing a valid urn:altinn:userid claim + /// + public static TheoryData UnauthenticatedValidTokenMissingUserContext() => new() + { + { + PrincipalUtil.GetToken(0, 0, 0) + } + }; + + /// + /// Sets up a request with a valid token but missing a valid authorization scope for authorized party list API + /// + public static TheoryData ValidResourceOwnerTokenMissingScope() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:serviceowner") + } + }; + + /// + /// Sets up the authenticated user, + /// getting authorized parties from only Altinn 3 + /// where the user has received delegations from a person, + /// of both an Altinn App and a Resource + /// + public static TheoryData> PersonToPerson() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + false, + GetExpectedResponse>("PersonToPerson", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user, + /// getting authorized parties from both Altinn 3 and Altinn 2 + /// where the user has received delegations from a person, + /// of both an Altinn App, a Resource and a Role from Altinn 2 + /// + public static TheoryData> PersonToPersonInclA2() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + true, + GetExpectedResponse>("PersonToPerson", BothAltinn3AndAltinn2) + } + }; + + /// + /// Sets up the authenticated user as DAGL of an organization, + /// getting authorized parties from only Altinn 3 + /// where the user's organization has received delegations from a person, + /// of both an Altinn App and a Resource + /// + public static TheoryData> PersonToOrg() => new() + { + { + PrincipalUtil.GetToken(PersonToOrg_ToOrgDaglUserId, PersonToOrg_ToOrgDaglPartyId, 3), + false, + GetExpectedResponse>("PersonToOrg", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user as DAGL of an organization, + /// getting authorized parties from both Altinn 3 and Altinn 2 + /// where the user's organization has received delegations from a person, + /// of both an Altinn App, a Resource and a Role from Altinn 2 + /// + public static TheoryData> PersonToOrgInclA2() => new() + { + { + PrincipalUtil.GetToken(PersonToOrg_ToOrgDaglUserId, PersonToOrg_ToOrgDaglPartyId, 3), + true, + GetExpectedResponse>("PersonToOrg", BothAltinn3AndAltinn2) + } + }; + + /// + /// Sets up the authenticated user, + /// getting authorized parties from only Altinn 3 + /// where the user has received the following delegations: + /// from mainunit: + /// the resource: devtest_gar_authparties-main-to-person + /// from subunit: + /// the altinn app: ttd/am-devtest-sub-to-person + /// + public static TheoryData> MainUnitAndSubUnitToPerson() => new() + { + { + PrincipalUtil.GetToken(MainUnitAndSubUnitToPerson_ToUserId, MainUnitAndSubUnitToPerson_ToPartyId, 3), + false, + GetExpectedResponse>("MainUnitAndSubUnitToPerson", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user, + /// getting authorized parties from only Altinn 3 + /// where the user has received the following delegations: + /// from mainunit: + /// the resource: devtest_gar_authparties-main-to-person + /// the role: REGNA + /// from subunit: + /// the altinn app: ttd/am-devtest-sub-to-person + /// the role: SISKD + /// + public static TheoryData> MainUnitAndSubUnitToPersonInclA2() => new() + { + { + PrincipalUtil.GetToken(MainUnitAndSubUnitToPerson_ToUserId, MainUnitAndSubUnitToPerson_ToPartyId, 3), + true, + GetExpectedResponse>("MainUnitAndSubUnitToPerson", BothAltinn3AndAltinn2) + } + }; + + /// + /// Sets up the authenticated user as DAGL of an organization, + /// getting authorized parties from only Altinn 3 + /// where the user's organization has received the following delegations: + /// from mainunit: + /// the resource: devtest_gar_authparties-main-to-org + /// from subunit: + /// the altinn app: ttd/am-devtest-sub-to-org + /// + public static TheoryData> MainUnitAndSubUnitToOrg() => new() + { + { + PrincipalUtil.GetToken(MainUnitAndSubUnitToOrg_ToOrgDaglUserId, MainUnitAndSubUnitToOrg_ToOrgDaglPartyId, 3), + false, + GetExpectedResponse>("MainUnitAndSubUnitToOrg", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user as DAGL of an organization, + /// getting authorized parties from only Altinn 3 + /// where the user's organization has received the following delegations: + /// from mainunit: + /// the resource: devtest_gar_authparties-main-to-org + /// the role: UTINN + /// from subunit: + /// the altinn app: ttd/am-devtest-sub-to-org + /// the role: APIADM + /// + public static TheoryData> MainUnitAndSubUnitToOrgInclA2() => new() + { + { + PrincipalUtil.GetToken(MainUnitAndSubUnitToOrg_ToOrgDaglUserId, MainUnitAndSubUnitToOrg_ToOrgDaglPartyId, 3), + true, + GetExpectedResponse>("MainUnitAndSubUnitToOrg", BothAltinn3AndAltinn2) + } + }; + + /// + /// Sets up the authenticated user, + /// getting authorized parties from only Altinn 3 + /// where the user has received the following delegations: + /// from subunit: + /// the altinn app: ttd/am-devtest-sub-to-person + /// the resource: devtest_gar_authparties-sub-to-person + /// + public static TheoryData> SubUnitToPerson() => new() + { + { + PrincipalUtil.GetToken(SubUnitToPerson_ToUserId, SubUnitToPerson_ToPartyId, 3), + false, + GetExpectedResponse>("SubUnitToPerson", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user, + /// getting it's own authorized party + /// without including Altinn 2 authorized parties + /// + /// Expected result: empty response since Altinn 2 is required in order to get self through PRIV role + /// + public static TheoryData PersonGettingSelf_BadRequest() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_ToPartyId, + false, + GetExpectedResponse("PersonGettingSelf", OnlyAltinn3) + } + }; + + /// + /// Sets up the authenticated user, + /// getting it's own authorized party + /// including Altinn 2 authorized parties + /// + /// Expected result: success, own authorized party is found including the PRIV authorized role + /// + public static TheoryData PersonGettingSelfInclA2_Success() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_ToPartyId, + true, + GetExpectedResponse("PersonGettingSelf", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: GET AuthorizedParty/{A3DelegatorPartyId} for authenticated user, without including Altinn 2 authorized parties + /// Expected: - Should return 200 OK + /// - Should include expected authorized party model of the authenticated user + /// Reason: Since Altinn 3 delegation exists A2 authorized parties is not needed to find Authorized Party with an authorized resource connection + /// + public static TheoryData PersonGettingA3Delegator_Success() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_ToPartyId, + true, + GetExpectedResponse("PersonGettingSelf", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: GET AuthorizedParty/{A3DelegatorPartyId} for authenticated user, including Altinn 2 authorized parties + /// Expected: - Should return 200 OK + /// - Should include expected authorized party model of the authenticated user + /// Reason: Since Altinn 3 delegation exists Altinn 2 authorized parties is not needed to find Authorized Party with an authorized resource connection, + /// but will enrich the Authorized Party with any authorized roles from Altinn 2 + /// + public static TheoryData PersonGettingA3DelegatorInclA2_Success() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_ToPartyId, + true, + GetExpectedResponse("PersonGettingSelf", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: GET {party}/authorizedparties?includeAltinn2={includeAltinn2} + /// with the authenticated user and getting the authorized party list for it's own {party} + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the authenticated user + /// Reason: Authenticated users are authorized for getting own authorized party list + /// + public static TheoryData> PersonGettingOwnList_Success() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_ToPartyId, + true, + GetExpectedResponse>("PersonGettingOwnList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: GET {party}/authorizedparties?includeAltinn2={includeAltinn2} + /// with the authenticated user being an authorized Access Manager for the {party} organization + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the organization + /// Reason: Authenticated users who are authorized as Access Manager for organizations should be allowed to get the organizations authorized party list + /// + public static TheoryData> AccessManagerGettingOrgList_Success() => new() + { + { + PrincipalUtil.GetToken(MainUnitAndSubUnitToOrg_ToOrgDaglUserId, MainUnitAndSubUnitToOrg_ToOrgDaglPartyId, 3), + MainUnitAndSubUnitToOrg_ToOrgPartyId, + true, + GetExpectedResponse>("AccessManagerGettingOrgList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: GET {party}/authorizedparties?includeAltinn2={includeAltinn2} + /// with the authenticated user being an authorized Access Manager for the {party} person + /// Expected: - Should return 403 Forbidden + /// - Should include expected authorized party list of the organization + /// Reason: Authenticated users who are authorized as Access Manager for organizations should be allowed to get the organizations authorized party list + /// + public static TheoryData AccessManagerGettingPersonList_Forbidden() => new() + { + { + PrincipalUtil.GetToken(PersonToPerson_ToUserId, PersonToPerson_ToPartyId, 3), + PersonToPerson_FromPartyId, + true + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for a person identified by urn:altinn:person:identifier-no + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetPersonList_ByPersonId() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId, Value = MainUnitAndSubUnitToOrg_ToOrgDaglPersonId }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetPersonList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for a person identified by urn:altinn:person:identifier-no + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// - Should include authorized resources the user has access to through roles for each authorized party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetPersonList_ByPersonId_InclResourcesThroughRoles() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId, Value = MainUnitAndSubUnitToOrg_ToOrgDaglPersonId }, + false, + true, + GetExpectedResponse>("ResourceOwner_GetPersonList", InclResourcesThroughRoles) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for a person identified by urn:altinn:person:uuid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetPersonList_ByPersonUuid() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid, Value = MainUnitAndSubUnitToOrg_ToOrgDaglPersonUuid }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetPersonList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for a person identified by urn:altinn:partyid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetPersonList_ByPartyId() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = MainUnitAndSubUnitToOrg_ToOrgDaglPartyId.ToString() }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetPersonList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for a person identified by urn:altinn:userid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetPersonList_ByUserId() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, Value = MainUnitAndSubUnitToOrg_ToOrgDaglUserId.ToString() }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetPersonList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:organization:identifier-no + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetOrgList_ByOrganizationNumber() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationId, Value = MainUnitAndSubUnitToOrg_ToOrgOrganizationNumber }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetOrgList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:organization:identifier-no + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// - Should include authorized resources the user has access to through roles for each authorized party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetOrgList_ByOrganizationNumber_InclResourcesThroughRoles() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationId, Value = MainUnitAndSubUnitToOrg_ToOrgOrganizationNumber }, + false, + true, + GetExpectedResponse>("ResourceOwner_GetOrgList", InclResourcesThroughRoles) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:organization:uuid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetOrgList_ByOrganizationUuid() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid, Value = MainUnitAndSubUnitToOrg_ToOrgOrganizationUuid }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetOrgList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:partyid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetOrgList_ByPartyId() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, Value = MainUnitAndSubUnitToOrg_ToOrgPartyId.ToString() }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetOrgList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:enterpriseuser:username + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUsername() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserName, Value = MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUsername }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetEnterpriseUserList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:enterpriseuser:username + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// - Should include authorized resources the user has access to through roles for each authorized party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUsername_InclResourcesThroughRoles() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserName, Value = MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUsername }, + false, + true, + GetExpectedResponse>("ResourceOwner_GetEnterpriseUserList", InclResourcesThroughRoles) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:enterpriseuser:uuid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetEnterpriseUserList_ByEnterpriseUserUuid() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid, Value = MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUserUuid }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetEnterpriseUserList", BothAltinn3AndAltinn2) + } + }; + + /// + /// Test case: POST resourceowner/authorizedparties?includeAltinn2={includeAltinn2} + /// with a valid resource owner token with the scope: altinn:accessmanagement/authorizedparties.resourceowner + /// getting authorized party list for an organization identified by urn:altinn:userid + /// Expected: - Should return 200 OK + /// - Should include expected authorized party list of the requested party + /// Reason: Authenticated resource owner organizations authorized with scope: altinn:accessmanagement/authorizedparties.resourceowner + /// are authorized to get authorized party list of any person, user or organization in Altinn + /// + public static TheoryData> ResourceOwner_GetEnterpriseUserList_ByUserId() => new() + { + { + PrincipalUtil.GetOrgToken("digdir", "991825827", "altinn:accessmanagement/authorizedparties.resourceowner"), + new BaseAttributeExternal { Type = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, Value = MainUnitAndSubUnitToOrg_ToOrgEcKeyRoleUserId.ToString() }, + true, + false, + GetExpectedResponse>("ResourceOwner_GetEnterpriseUserList", BothAltinn3AndAltinn2) + } + }; + + private static T GetExpectedResponse(string delegationType, string retrievalType) + { + string content = File.ReadAllText($"Data/Json/AuthorizedParties/{delegationType}/{retrievalType}.json"); + return (T)JsonSerializer.Deserialize(content, typeof(T), JsonOptions); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertAuthorizedPartyExternalEqual(AuthorizedPartyExternal expected, AuthorizedPartyExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.PartyId, actual.PartyId); + Assert.Equal(expected.PartyUuid, actual.PartyUuid); + Assert.Equal(expected.Type, actual.Type); + Assert.Equal(expected.OrganizationNumber, actual.OrganizationNumber); + Assert.Equal(expected.PersonId, actual.PersonId); + Assert.Equal(expected.UnitType, actual.UnitType); + Assert.Equal(expected.Name, actual.Name); + Assert.Equal(expected.IsDeleted, actual.IsDeleted); + Assert.Equal(expected.OnlyHierarchyElementWithNoAccess, actual.OnlyHierarchyElementWithNoAccess); + Assert.Equal(expected.AuthorizedResources, actual.AuthorizedResources); + Assert.Equal(expected.AuthorizedRoles, actual.AuthorizedRoles); + AssertionUtil.AssertCollections(expected.Subunits, actual.Subunits, AssertAuthorizedPartyExternalEqual); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/DelegationRequests/coveredby_UID1337_offeredby_PID12345.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/DelegationRequests/coveredby_UID1337_offeredby_PID12345.json new file mode 100644 index 00000000..fe0050c5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/DelegationRequests/coveredby_UID1337_offeredby_PID12345.json @@ -0,0 +1,19 @@ +{ + "coveredBy": "01038712345", + "coveredByName": "Sophie Salt", + "offeredBy": "123342345", + "offeredByName": "Oslos Vakreste Borettslag", + "created": "2019-07-31T09:57:23.4729995Z", + "lastChanged": "2019-07-31T09:57:23.4729995Z", + "requestMessage": "Please give me the right", + "guid": "26133fb5-a9f2-45d4-90b1-f6d93ad40713", + "requestStatus": 6, + "requestResources": [ + { + "serviceCode": "MVA", + "serviceEditionCode": 1337, + "operations": [ "item1", "adsf" ], + "metadata": {"fake": "nofake"} + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/read.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/read.json new file mode 100644 index 00000000..19136f9a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/read.json @@ -0,0 +1,15 @@ +{ + "subject": { + "type": "urn:altinn:organization:identifier-no", + "value": "910459880" + }, + "resource": { + "type": "urn:altinn:resource", + "value": "generic-accesslist-resource" + }, + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "result": "Authorized" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/write.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/write.json new file mode 100644 index 00000000..1a9e6315 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AccessListResponses/generic-accesslist-resource/910459880/write.json @@ -0,0 +1,15 @@ +{ + "subject": { + "type": "urn:altinn:organization:identifier-no", + "value": "910459880" + }, + "resource": { + "type": "urn:altinn:resource", + "value": "generic-accesslist-resource" + }, + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + }, + "result": "NotAuthorized" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/BlobStorageError.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/BlobStorageError.json new file mode 100644 index 00000000..bcc114bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/BlobStorageError.json @@ -0,0 +1,26 @@ +[ + { + "delegatedByUserId": 1, + "offeredByPartyId": 1, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "1" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "error" + }, + { + "id": "urn:altinn:app", + "value": "blobstorage" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "error" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/DelegationEventError.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/DelegationEventError.json new file mode 100644 index 00000000..c5beb692 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/DelegationEventError.json @@ -0,0 +1,26 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "error" + }, + { + "id": "urn:altinn:app", + "value": "delegationeventfail" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/EmptyRuleModel.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/EmptyRuleModel.json new file mode 100644 index 00000000..0d4f101c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/EmptyRuleModel.json @@ -0,0 +1,2 @@ +[ +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/InvalidRuleModel.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/InvalidRuleModel.json new file mode 100644 index 00000000..bfd2464e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/InvalidRuleModel.json @@ -0,0 +1,26 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": null, //Invalid as it is required + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/MultipleAppsOfferedBysAndCoveredBys.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/MultipleAppsOfferedBysAndCoveredBys.json new file mode 100644 index 00000000..8008f1f6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/MultipleAppsOfferedBysAndCoveredBys.json @@ -0,0 +1,98 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app2" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app2" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourIncompleteApp.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourIncompleteApp.json new file mode 100644 index 00000000..9d6e4c5c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourIncompleteApp.json @@ -0,0 +1,90 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001336" + } + ], + "resource": [ + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app2" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourInvalidApp.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourInvalidApp.json new file mode 100644 index 00000000..df927153 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/OneOutOfFourInvalidApp.json @@ -0,0 +1,98 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "INVALIDAPPNAME" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001336, + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org2" + }, + { + "id": "urn:altinn:app", + "value": "app2" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/PostgreError.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/PostgreError.json new file mode 100644 index 00000000..09dab426 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/PostgreError.json @@ -0,0 +1,26 @@ +[ + { + "delegatedByUserId": 0, + "offeredByPartyId": 0, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "0" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "error" + }, + { + "id": "urn:altinn:app", + "value": "postgre" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "error" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App1_50001337_20001336.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App1_50001337_20001336.json new file mode 100644 index 00000000..14d711ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App1_50001337_20001336.json @@ -0,0 +1,50 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App3_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App3_50001337_20001337.json new file mode 100644 index 00000000..f0b18da7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteOrg1App3_50001337_20001337.json @@ -0,0 +1,50 @@ +[ + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001336.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001336.json new file mode 100644 index 00000000..f2093f6e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001336.json @@ -0,0 +1,42 @@ +[ + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001337.json new file mode 100644 index 00000000..09c803a8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ReadWriteResourceregistryId_50001337_20001337.json @@ -0,0 +1,42 @@ +[ + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "delegatedByUserId": 20001336, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource1" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ScopeaccessResourceRegistryId_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ScopeaccessResourceRegistryId_50001337_20001337.json new file mode 100644 index 00000000..098d9c8b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AddRules/ScopeaccessResourceRegistryId_50001337_20001337.json @@ -0,0 +1,22 @@ +[ + { + "delegatedByPartyId": 50001337, + "offeredByPartyId": 50001337, + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource2" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "scopeaccess" + } + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json new file mode 100644 index 00000000..87cda70e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json new file mode 100644 index 00000000..0eee85d7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000001", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json new file mode 100644 index 00000000..07f188ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json new file mode 100644 index 00000000..454e8dfb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000002", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "NotDelegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json new file mode 100644 index 00000000..87cda70e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json new file mode 100644 index 00000000..19dac613 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000003", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json new file mode 100644 index 00000000..87cda70e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json new file mode 100644 index 00000000..dab07c7b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000005", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json new file mode 100644 index 00000000..e7100db7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "DFC6D814-B657-4BA6-A678-6A76C12C9DDF" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "594D195C-09C7-4EE0-8E83-BD4439EC27B1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json new file mode 100644 index 00000000..8eeccbbb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json @@ -0,0 +1,23 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "Bad Request", + "status": 400, + "detail": "One or more validation errors occurred.", + "code": "STD-00000", + "validationErrors": [ + { + "code": "AM.VLD-00001", + "detail": "Invalid party URN.", + "paths": [ + "From" + ] + }, + { + "code": "AM.VLD-00001", + "detail": "Invalid party URN.", + "paths": [ + "To" + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json new file mode 100644 index 00000000..11d25e9a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:organization:identifier-no", + "value": "810419342" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json new file mode 100644 index 00000000..18d3e2f5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:organization:identifier-no", + "value": "810419342" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000007", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json new file mode 100644 index 00000000..07f188ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json new file mode 100644 index 00000000..e1cc79b4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Delegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "0191579e-72bc-7977-af5d-f9e92af4393b", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/DelegationCheck/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/DelegationCheck/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json new file mode 100644 index 00000000..f3423704 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/DelegationCheck/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json @@ -0,0 +1,43 @@ +{ + "links": { + "next": null + }, + "data": [ + { + "rightKey": "app_ttd_am-devtest-instancedelegation,task_1:read", + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegable" + }, + { + "rightKey": "app_ttd_am-devtest-instancedelegation,task_1:sign", + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegable" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Get/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000008/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Get/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000008/response.json new file mode 100644 index 00000000..f0893fd5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Get/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000008/response.json @@ -0,0 +1,86 @@ +{ + "links": { + "next": null + }, + "data": [ + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "ce4ba72b-d111-404f-95b5-313fb3847fa1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000008", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegated" + } + ] + }, + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "0268b99a-5817-4bbf-9b62-d90b16d527ea" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000008", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegated" + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] + } + ] +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json new file mode 100644 index 00000000..07f188ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json new file mode 100644 index 00000000..15d1db1f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000001", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json new file mode 100644 index 00000000..07f188ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json new file mode 100644 index 00000000..c4033761 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000002", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/request.json new file mode 100644 index 00000000..07f188ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/request.json @@ -0,0 +1,28 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/response.json new file mode 100644 index 00000000..78ff9c06 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000009/response.json @@ -0,0 +1,31 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000009", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000010/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000010/response.json new file mode 100644 index 00000000..88841bfc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/Revoke/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000010/response.json @@ -0,0 +1,165 @@ +{ + "links": { + "next": null + }, + "data": [ + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "ce4ba72b-d111-404f-95b5-313fb3847fa1" + }, + "resourceId": "app_ttd_am-devtest-instancedelegation", + "instanceId": "00000000-0000-0000-0000-000000000010", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + ] + }, + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "0268b99a-5817-4bbf-9b62-d90b16d527ea" + }, + "resourceId": "app_ttd_am-devtest-instancedelegation", + "instanceId": "00000000-0000-0000-0000-000000000010", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Revoked" + } + ] + }, + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "00000000-0000-0000-0001-000000000012" + }, + "resourceId": "app_ttd_am-devtest-instancedelegation", + "instanceId": "00000000-0000-0000-0000-000000000010", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Revoked" + } + ] + }, + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "b537c953-03c4-4822-b028-c15182adc356" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "00000000-0000-0000-0001-000000000010" + }, + "resourceId": "app_ttd_am-devtest-instancedelegation", + "instanceId": "00000000-0000-0000-0000-000000000010", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Revoked" + } + ] + } + ] +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json new file mode 100644 index 00000000..4bb20bb8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "ParallelSigning", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json new file mode 100644 index 00000000..0b2f3757 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000001", + "instanceDelegationMode": "ParallelSigning", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "00000000-0000-0000-0000-000000000001" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json new file mode 100644 index 00000000..c9fecf88 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json new file mode 100644 index 00000000..95f22b1c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000002/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000002", + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "00000000-0000-0000-0000-000000000002" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "NotDelegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json new file mode 100644 index 00000000..89354bde --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json new file mode 100644 index 00000000..4a161ce7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000003/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000003", + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "00000000-0000-0000-0000-000000000003" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json new file mode 100644 index 00000000..89354bde --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json new file mode 100644 index 00000000..52aa91fd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000005/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000005", + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "00000000-0000-0000-0000-000000000005" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json new file mode 100644 index 00000000..c0bb278a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "DFC6D814-B657-4BA6-A678-6A76C12C9DDF" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "594D195C-09C7-4EE0-8E83-BD4439EC27B1" + }, + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json new file mode 100644 index 00000000..8eeccbbb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000006/response.json @@ -0,0 +1,23 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "Bad Request", + "status": 400, + "detail": "One or more validation errors occurred.", + "code": "STD-00000", + "validationErrors": [ + { + "code": "AM.VLD-00001", + "detail": "Invalid party URN.", + "paths": [ + "From" + ] + }, + { + "code": "AM.VLD-00001", + "detail": "Invalid party URN.", + "paths": [ + "To" + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json new file mode 100644 index 00000000..6f283160 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:organization:identifier-no", + "value": "810419342" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json new file mode 100644 index 00000000..65678583 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000007/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:organization:identifier-no", + "value": "810419342" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "00000000-0000-0000-0000-000000000007", + "instanceDelegationMode": "Normal", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "00000000-0000-0000-0000-000000000007" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json new file mode 100644 index 00000000..790e9fee --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/request.json @@ -0,0 +1,33 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "instanceDelegationMode": "ParallelSigning", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json new file mode 100644 index 00000000..7fa5e331 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AppsInstanceDelegation/app_ttd_am-devtest-instancedelegation/0191579e-72bc-7977-af5d-f9e92af4393b/response.json @@ -0,0 +1,40 @@ +{ + "from": { + "type": "urn:altinn:party:uuid", + "value": "0268B99A-5817-4BBF-9B62-D90B16D527EA" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "CE4BA72B-D111-404F-95B5-313FB3847FA1" + }, + "resourceid": "app_ttd_am-devtest-instancedelegation", + "instanceid": "0191579e-72bc-7977-af5d-f9e92af4393b", + "instanceDelegationMode": "ParallelSigning", + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:org", + "value": "ttd" + }, + { + "type": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + }, + { + "type": "urn:altinn:resource:instance-id", + "value": "0191579e-72bc-7977-af5d-f9e92af4393b" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/AccessManagerGettingOrgList/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/AccessManagerGettingOrgList/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..0e28b565 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/AccessManagerGettingOrgList/BothAltinn3AndAltinn2.json @@ -0,0 +1,53 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..3a3e4dee --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/BothAltinn3AndAltinn2.json @@ -0,0 +1,76 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000011", + "name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "organizationNumber": null, + "personId": "01018170071", + "partyId": 50100011, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [ + "UTINN", + "APIADM" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/OnlyAltinn3.json new file mode 100644 index 00000000..0e28b565 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToOrg/OnlyAltinn3.json @@ -0,0 +1,53 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..7362fa94 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/BothAltinn3AndAltinn2.json @@ -0,0 +1,75 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000009", + "name": "MAINUNIT AND SUBUNIT TO PERSON RECIPIENT", + "organizationNumber": null, + "personId": "01017970071", + "partyId": 50100009, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person" + ], + "authorizedRoles": [ + "REGNA" + ], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person", + "app_ttd_am-devtest-sub-to-person" + ], + "authorizedRoles": [ + "REGNA", + "SISKD" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person" + ], + "authorizedRoles": [ + "REGNA" + ], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/OnlyAltinn3.json new file mode 100644 index 00000000..a966708b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/MainUnitAndSubUnitToPerson/OnlyAltinn3.json @@ -0,0 +1,52 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person", + "app_ttd_am-devtest-sub-to-person" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-person" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..a49e8067 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/BothAltinn3AndAltinn2.json @@ -0,0 +1,19 @@ +{ + "partyUuid": "00000000-0000-0000-0001-000000000001", + "name": "PERSON TO PERSON DELEGATOR", + "organizationNumber": null, + "personId": "01017170071", + "partyId": 50100001, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-person", + "app_ttd_am-devtest-person-to-person" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/OnlyAltinn3.json new file mode 100644 index 00000000..e27a9511 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingA3Delegator/OnlyAltinn3.json @@ -0,0 +1,17 @@ +{ + "partyUuid": "00000000-0000-0000-0001-000000000001", + "name": "PERSON TO PERSON DELEGATOR", + "organizationNumber": null, + "personId": "01017170071", + "partyId": 50100001, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-person", + "app_ttd_am-devtest-person-to-person" + ], + "authorizedRoles": [], + "subunits": [] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingOwnList/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingOwnList/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..777f2014 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingOwnList/BothAltinn3AndAltinn2.json @@ -0,0 +1,37 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000002", + "name": "PERSON TO PERSON RECIPIENT", + "organizationNumber": null, + "personId": "01017270071", + "partyId": 50100002, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000001", + "name": "PERSON TO PERSON DELEGATOR", + "organizationNumber": null, + "personId": "01017170071", + "partyId": 50100001, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-person", + "app_ttd_am-devtest-person-to-person" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..52eae0a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/BothAltinn3AndAltinn2.json @@ -0,0 +1,16 @@ +{ + "partyUuid": "00000000-0000-0000-0001-000000000002", + "name": "PERSON TO PERSON RECIPIENT", + "organizationNumber": null, + "personId": "01017270071", + "partyId": 50100002, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/OnlyAltinn3.json new file mode 100644 index 00000000..cbec0368 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonGettingSelf/OnlyAltinn3.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "InvalidParty": [ + "The party id is either invalid or is not an authorized party for the authenticated user" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..8bbddf24 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/BothAltinn3AndAltinn2.json @@ -0,0 +1,37 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000005", + "name": "PERSON TO ORG DAGL", + "organizationNumber": null, + "personId": "01017570071", + "partyId": 50100005, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000003", + "name": "PERSON TO ORG DELEGATOR", + "organizationNumber": null, + "personId": "01017370071", + "partyId": 50100003, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-org", + "app_ttd_am-devtest-person-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/OnlyAltinn3.json new file mode 100644 index 00000000..e6caf68b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToOrg/OnlyAltinn3.json @@ -0,0 +1,19 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000003", + "name": "PERSON TO ORG DELEGATOR", + "organizationNumber": null, + "personId": "01017370071", + "partyId": 50100003, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-org", + "app_ttd_am-devtest-person-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..777f2014 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/BothAltinn3AndAltinn2.json @@ -0,0 +1,37 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000002", + "name": "PERSON TO PERSON RECIPIENT", + "organizationNumber": null, + "personId": "01017270071", + "partyId": 50100002, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000001", + "name": "PERSON TO PERSON DELEGATOR", + "organizationNumber": null, + "personId": "01017170071", + "partyId": 50100001, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-person", + "app_ttd_am-devtest-person-to-person" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/OnlyAltinn3.json new file mode 100644 index 00000000..ed6501ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/PersonToPerson/OnlyAltinn3.json @@ -0,0 +1,19 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000001", + "name": "PERSON TO PERSON DELEGATOR", + "organizationNumber": null, + "personId": "01017170071", + "partyId": 50100001, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-person-to-person", + "app_ttd_am-devtest-person-to-person" + ], + "authorizedRoles": [], + "subunits": [] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..5fbe7114 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/BothAltinn3AndAltinn2.json @@ -0,0 +1,69 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000010", + "name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "organizationNumber": "901000010", + "personId": null, + "partyId": 50100010, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "ECKEYROLE" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/InclResourcesThroughRoles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/InclResourcesThroughRoles.json new file mode 100644 index 00000000..5fbe7114 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetEnterpriseUserList/InclResourcesThroughRoles.json @@ -0,0 +1,69 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000010", + "name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "organizationNumber": "901000010", + "personId": null, + "partyId": 50100010, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "ECKEYROLE" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..0e28b565 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/BothAltinn3AndAltinn2.json @@ -0,0 +1,53 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/InclResourcesThroughRoles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/InclResourcesThroughRoles.json new file mode 100644 index 00000000..0e28b565 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetOrgList/InclResourcesThroughRoles.json @@ -0,0 +1,53 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/BothAltinn3AndAltinn2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/BothAltinn3AndAltinn2.json new file mode 100644 index 00000000..3a3e4dee --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/BothAltinn3AndAltinn2.json @@ -0,0 +1,76 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000011", + "name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "organizationNumber": null, + "personId": "01018170071", + "partyId": 50100011, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [ + "UTINN", + "APIADM" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/InclResourcesThroughRoles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/InclResourcesThroughRoles.json new file mode 100644 index 00000000..57ed1439 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/ResourceOwner_GetPersonList/InclResourcesThroughRoles.json @@ -0,0 +1,84 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000011", + "name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "organizationNumber": null, + "personId": "01018170071", + "partyId": 50100011, + "type": "Person", + "unitType": null, + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "generic-access-resource" + ], + "authorizedRoles": [ + "PRIV" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "jks_audi_etron_gt", + "generic-access-resource", + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "jks_audi_etron_gt", + "generic-access-resource", + "app_ttd_am-devtest-sub-to-org", + "devtest_gar_authparties-main-to-org", + "devtest_gar_authparties-sub-to-org" + ], + "authorizedRoles": [ + "UTINN", + "APIADM" + ], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "jks_audi_etron_gt", + "generic-access-resource", + "devtest_gar_authparties-main-to-org" + ], + "authorizedRoles": [ + "UTINN" + ], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/SubUnitToPerson/OnlyAltinn3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/SubUnitToPerson/OnlyAltinn3.json new file mode 100644 index 00000000..583f8266 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/AuthorizedParties/SubUnitToPerson/OnlyAltinn3.json @@ -0,0 +1,50 @@ +[ + { + "partyUuid": "00000000-0000-0000-0001-000000000006", + "name": "AUTHORIZEDPARTIES MAINUNIT", + "organizationNumber": "901000006", + "personId": null, + "partyId": 50100006, + "type": "Organization", + "unitType": "AS", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": true, + "authorizedResources": [], + "authorizedRoles": [], + "subunits": [ + { + "partyUuid": "00000000-0000-0000-0001-000000000007", + "name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "organizationNumber": "901000007", + "personId": null, + "partyId": 50100007, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "app_ttd_am-devtest-sub-to-person", + "devtest_gar_authparties-sub-to-person" + ], + "authorizedRoles": [], + "subunits": [] + }, + { + "partyUuid": "00000000-0000-0000-0001-000000000008", + "name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "organizationNumber": "901000008", + "personId": null, + "partyId": 50100008, + "type": "Organization", + "unitType": "BEDR", + "isDeleted": false, + "onlyHierarchyElementWithNoAccess": false, + "authorizedResources": [ + "devtest_gar_authparties-sub2-to-person" + ], + "authorizedRoles": [], + "subunits": [] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json new file mode 100644 index 00000000..10f75fb3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json new file mode 100644 index 00000000..5ba9f997 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json @@ -0,0 +1,133 @@ +[ + { + "rightKey": "digdirs_company_car:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ], + "action": "drive", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "EKTJ" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0286" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json new file mode 100644 index 00000000..5ba9f997 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json @@ -0,0 +1,133 @@ +[ + { + "rightKey": "digdirs_company_car:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ], + "action": "drive", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "EKTJ" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0286" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..e87466a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50004221" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..f5bc0c64 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,110 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:5", + "policyVersion": "1.0", + "ruleId": "e7a89266-9457-45c9-86c4-53155c6f0230", + "offeredByPartyId": 50004221, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..1743a367 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,295 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:5", + "policyVersion": "1.0", + "ruleId": "e7a89266-9457-45c9-86c4-53155c6f0230", + "offeredByPartyId": 50004221, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt,mechanic_work:change_tires", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + }, + { + "id": "urn:altinn:task", + "value": "mechanic_work" + } + ], + "action": "change_tires", + "canDelegate": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json new file mode 100644 index 00000000..e669eefc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json @@ -0,0 +1,24 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50001337" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json new file mode 100644 index 00000000..4da4d127 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json @@ -0,0 +1,42 @@ +[ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "57b3ee85-f932-42c6-9ab0-941eb6c96eb0", + "offeredByPartyId": 50001337, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json new file mode 100644 index 00000000..d582c42c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json @@ -0,0 +1,169 @@ +[ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "regna" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "57b3ee85-f932-42c6-9ab0-941eb6c96eb0", + "offeredByPartyId": 50001337, + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "write", + "canDelegate": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "regna" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1,task1:sign", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:task", + "value": "task1" + } + ], + "action": "sign", + "canDelegate": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..4c4d0631 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json @@ -0,0 +1,24 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..477d321a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,999 @@ +[ + { + "rightKey": "rf-0002,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "instantiate", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "delete", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..fc6dc613 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegableRightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,1264 @@ +[ + { + "rightKey": "rf-0002,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "instantiate", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "delete", + "canDelegate": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "canDelegate": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "write", + "canDelegate": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:4", + "canDelegate": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:complete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "complete", + "canDelegate": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:5", + "canDelegate": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50002598/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50002598/authn_u20000490.json new file mode 100644 index 00000000..db9823be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50002598/authn_u20000490.json @@ -0,0 +1,271 @@ +[ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:PRIV. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "Parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:PRIV. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-user", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-user", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:PRIV. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:PRIV. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:UTINN. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50004221/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50004221/authn_u20000490.json new file mode 100644 index 00000000..fec4b90e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50004221/authn_u20000490.json @@ -0,0 +1,280 @@ +[ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-user", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-user", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-keyroleunit", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "DelegationAccess", + "description": "The user have access through delegation(s) of the right to the following recipient(s): urn:altinn:userid:20000490", + "parameters": { + "DelegationRecipients": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "DelegationAccess", + "description": "The user have access through delegation(s) of the right to the following recipient(s): urn:altinn:userid:20000490", + "parameters": { + "DelegationRecipients": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "DelegationAccess", + "description": "The user have access through delegation(s) of the right to the following recipient(s): urn:altinn:partyid:50005545", + "parameters": { + "DelegationRecipients": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "DelegationAccess", + "description": "The user have access through delegation(s) of the right to the following recipient(s): urn:altinn:partyid:50005545", + "parameters": { + "DelegationRecipients": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:UTINN), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20000490.json new file mode 100644 index 00000000..9e00c507 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20000490.json @@ -0,0 +1,266 @@ +[ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-user", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-user", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-keyroleunit", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:UTINN. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json new file mode 100644 index 00000000..9e00c507 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json @@ -0,0 +1,266 @@ +[ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-user", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-user", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,priv-delegation-subtask:delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "priv-delegation-subtask" + } + ], + "action": "delegated-action-to-keyroleunit", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:PRIV), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "PRIV" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:UTINN. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/request.json new file mode 100644 index 00000000..e531d483 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-access-resource/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50002598/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50002598/authn_u20000490.json new file mode 100644 index 00000000..af0de266 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50002598/authn_u20000490.json @@ -0,0 +1,62 @@ +[ + { + "rightKey": "generic-accesslist-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-accesslist-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50004221/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50004221/authn_u20000490.json new file mode 100644 index 00000000..af0de266 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50004221/authn_u20000490.json @@ -0,0 +1,62 @@ +[ + { + "rightKey": "generic-accesslist-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "generic-accesslist-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50005545/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50005545/authn_u20000490.json new file mode 100644 index 00000000..eea0f1b5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/from_p50005545/authn_u20000490.json @@ -0,0 +1,60 @@ +[ + { + "rightKey": "generic-accesslist-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "AccessListValidationPass", + "description": "The fromParty has the right based on Access List delegation" + } + ] + }, + { + "rightKey": "generic-accesslist-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "AccessListValidationFail", + "description": "The fromParty does not have the right based on Access List delegation" + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/request.json new file mode 100644 index 00000000..fb41821b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/generic-accesslist-resource/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json new file mode 100644 index 00000000..e44de6ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "This operation does not support MaskinportenSchema resources. Please use the MaskinportenSchema DelegationCheck API. Invalid resource: jks_audi_etron_gt. Invalid resource type: MaskinportenSchema" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/request.json new file mode 100644 index 00000000..248a9246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/jks_audi_etron_gt/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/from_p50001337/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/from_p50001337/authn_u20001337.json new file mode 100644 index 00000000..de6bb2f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/from_p50001337/authn_u20001337.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "The resource does not exist or is not available for delegation" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/request.json new file mode 100644 index 00000000..44336e37 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/non_existing_id/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_existing_id" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/from_p50001337/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/from_p50001337/authn_u20001337.json new file mode 100644 index 00000000..19c5dab3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/from_p50001337/authn_u20001337.json @@ -0,0 +1,115 @@ +[ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "DelegationAccess", + "description": "The user have access through delegation(s) of the right to the following recipient(s): urn:altinn:userid:20001337", + "parameters": { + "DelegationRecipients": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } + ] + }, + { + "rightKey": "app1,org1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:regna, urn:altinn:rolecode:dagl, urn:altinn:rolecode:priv), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "regna" + }, + { + "id": "urn:altinn:rolecode", + "value": "dagl" + }, + { + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "app1,org1,task1:sign", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:task", + "value": "task1" + } + ], + "action": "sign", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:dagl, urn:altinn:rolecode:priv), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "dagl" + }, + { + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/request.json new file mode 100644 index 00000000..eb10114d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/org1_app1/request.json @@ -0,0 +1,12 @@ +{ + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337.json new file mode 100644 index 00000000..687cbafe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337.json @@ -0,0 +1,151 @@ +[ + { + "RightKey": "1337:1338:read", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "action": "read", + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:write", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "action": "write", + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + }, + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:archiveread", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "action": "archiveread", + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:archivedelete", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "action": "archivedelete", + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:sign", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "action": "sign", + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337_from_sbl_bridge.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337_from_sbl_bridge.json new file mode 100644 index 00000000..6aba5c9e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337_from_sbl_bridge.json @@ -0,0 +1,166 @@ +[ + { + "RightKey": "1337:1338:read", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "Action": { + "Id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "Value": "read" + }, + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:write", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "Action": { + "Id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "Value": "write" + }, + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + }, + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:archiveread", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "Action": { + "Id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "Value": "archiveread" + }, + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:archivedelete", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "Action": { + "Id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "Value": "archivedelete" + }, + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + }, + { + "RightKey": "1337:1338:sign", + "Resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "1337" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "1338" + } + ], + "Action": { + "Id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "Value": "sign" + }, + "Status": "Delegable", + "Details": [ + { + "Code": "RoleAccess", + "Description": "User has a role giving right to delegate this right", + "Parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "UTINN" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/request.json new file mode 100644 index 00000000..4c543e4f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/se_1337_1338/request.json @@ -0,0 +1,12 @@ +{ + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "1337" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "1338" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005545/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005545/authn_u20000490.json new file mode 100644 index 00000000..26cd9bd8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005545/authn_u20000490.json @@ -0,0 +1,282 @@ +[ + { + "rightKey": "apps-test,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "instantiate", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "delete", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:ADMAI. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + } + ] + } + } + ] + }, + { + "rightKey": "apps-test,events,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:appresource", + "value": "events" + } + ], + "action": "read", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005546/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005546/authn_u20000490.json new file mode 100644 index 00000000..6e432854 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/from_p50005546/authn_u20000490.json @@ -0,0 +1,322 @@ +[ + { + "rightKey": "apps-test,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "instantiate", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "delete", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:ADMAI), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + }, + { + "rightKey": "apps-test,events,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + }, + { + "id": "urn:altinn:appresource", + "value": "events" + } + ], + "action": "read", + "status": "NotDelegable", + "details": [ + { + "code": "MissingRoleAccess", + "description": "Delegator does not have any required role(s) for the reportee party: (urn:altinn:rolecode:REGNA, urn:altinn:rolecode:DAGL), which would give access to delegate the right.", + "parameters": { + "RequiredRoles": [ + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + } + }, + { + "code": "MissingDelegationAccess", + "description": "The user does not have access through delegation(s) of the right", + "parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/request.json new file mode 100644 index 00000000..9f3c9c2f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DelegationCheck/ttd_apps-test/request.json @@ -0,0 +1,12 @@ +{ + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/EmptyInput.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/EmptyInput.json new file mode 100644 index 00000000..e69de29b diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadNotExistingResourceRegistryId.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadNotExistingResourceRegistryId.json new file mode 100644 index 00000000..5329cb7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadNotExistingResourceRegistryId.json @@ -0,0 +1,20 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "notexistingresource" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3-DuplicatePolicyInRequest_50001337_20001337_NoUpdates.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3-DuplicatePolicyInRequest_50001337_20001337_NoUpdates.json new file mode 100644 index 00000000..fe3ca756 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3-DuplicatePolicyInRequest_50001337_20001337_NoUpdates.json @@ -0,0 +1,46 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4App8_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4App8_50001337_20001337.json new file mode 100644 index 00000000..d6614c96 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4App8_50001337_20001337.json @@ -0,0 +1,71 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "urn:altinn:ruleid:0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app8" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337.json new file mode 100644 index 00000000..3dae948e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337.json @@ -0,0 +1,46 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json new file mode 100644 index 00000000..fa70523d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json @@ -0,0 +1,45 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json new file mode 100644 index 00000000..5f233c49 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json @@ -0,0 +1,46 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app8" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "error" + }, + { + "id": "urn:altinn:app", + "value": "postgrewritechangefail" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadResource1Resource2_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadResource1Resource2_50001337_20001337.json new file mode 100644 index 00000000..58764eb1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeletePolicies/ReadResource1Resource2_50001337_20001337.json @@ -0,0 +1,38 @@ +[ + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource1" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource2" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4App8_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4App8_50001337_20001337.json new file mode 100644 index 00000000..c9fb821c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4App8_50001337_20001337.json @@ -0,0 +1,78 @@ +[ + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "adfa64fa-5859-46e5-8d0d-62762082f3b9", + "7d015074-e91a-464a-a5f6-e4d4f58c3511" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app8" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json new file mode 100644 index 00000000..c22eab16 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoDeletedBy.json @@ -0,0 +1,52 @@ +[ + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "adfa64fa-5859-46e5-8d0d-62762082f3b9", + "7d015074-e91a-464a-a5f6-e4d4f58c3511" + ], + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoRule.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoRule.json new file mode 100644 index 00000000..4a4b77f8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3App4_50001337_20001337_NoRule.json @@ -0,0 +1,52 @@ +[ + { + "ruleIds": [ + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "adfa64fa-5859-46e5-8d0d-62762082f3b9", + "7d015074-e91a-464a-a5f6-e4d4f58c3511" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app4" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337.json new file mode 100644 index 00000000..f972aac7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337.json @@ -0,0 +1,27 @@ +[ + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337RuleIdDoesNotExist.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337RuleIdDoesNotExist.json new file mode 100644 index 00000000..63d45969 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337RuleIdDoesNotExist.json @@ -0,0 +1,28 @@ +[ + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94", + "0d0c8570-64fb-49f9-9f7d-45c057fddf95" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337_DuplicatePolicy.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337_DuplicatePolicy.json new file mode 100644 index 00000000..e9a4e3ce --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App3_50001337_20001337_DuplicatePolicy.json @@ -0,0 +1,52 @@ +[ + { + "ruleIds": [ + "0d0c8570-64fb-49f9-9f7d-45c057fddf94" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app3" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json new file mode 100644 index 00000000..ce443e5e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadOrg1App8-Errorpostgrewritechangefail_50001337_20001337_NoUpdates.json @@ -0,0 +1,52 @@ +[ + { + "ruleIds": [ + "adfa64fa-5859-46e5-8d0d-62762082f3b9" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app8" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + }, + { + "ruleIds": [ + "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:org", + "value": "error" + }, + { + "id": "urn:altinn:app", + "value": "postgrewritechangefail" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadResource2_50001337_20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadResource2_50001337_20001337.json new file mode 100644 index 00000000..774a2136 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/DeleteRules/ReadResource2_50001337_20001337.json @@ -0,0 +1,23 @@ +[ + { + "ruleIds": [ + "99e5cced-3bcb-42b6-9089-63c834f89e77" + ], + "deletedByUserId": 20001336, + "policyMatch": { + "offeredByPartyId": 50001337, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "resource2" + } + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + } + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingOfferedByInRequestRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingOfferedByInRequestRequest.json new file mode 100644 index 00000000..a2fd81e5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingOfferedByInRequestRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 0, + "keyRolePartyIds": [ + 0 + ], + "offeredByPartyId": 0, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "SKD" + }, + { + "id": "urn:altinn:app", + "value": "TaxReport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingValuesInRequestRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingValuesInRequestRequest.json new file mode 100644 index 00000000..3f8b30e4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_MissingValuesInRequestRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 50001336, + "keyRolePartyIds": [ + + ], + "offeredByPartyId": 50001337, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "SKD" + }, + { + "id": "urn:altinn:app", + "value": "" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001341" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_NoRulesRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_NoRulesRequest.json new file mode 100644 index 00000000..7d26b5ac --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_NoRulesRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 0, + "keyRolePartyIds": [ + + ], + "offeredByPartyId": 50001337, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "SKD" + }, + { + "id": "urn:altinn:app", + "value": "TaxReport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001338" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitRequest.json new file mode 100644 index 00000000..e2cc2bd8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 50001338, + "keyRolePartyIds": [ + + ], + "offeredByPartyId": 50001399, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "skd" + }, + { + "id": "urn:altinn:app", + "value": "taxreport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:partyid", + "value": "50001336" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitViaKeyroleRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitViaKeyroleRequest.json new file mode 100644 index 00000000..10678b7d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedAsSubunitViaKeyroleRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 50001335, + "keyRolePartyIds": [ + 50001337 + ], + "offeredByPartyId": 50001339, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "skd" + }, + { + "id": "urn:altinn:app", + "value": "taxreport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedViaKeyRoleRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedViaKeyRoleRequest.json new file mode 100644 index 00000000..22d56547 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_RuleTypeInheritedViaKeyRoleRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 0, + "keyRolePartyIds": [ + 50001338 + ], + "offeredByPartyId": 50001337, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "skd" + }, + { + "id": "urn:altinn:app", + "value": "taxreport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001335" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_SuccessRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_SuccessRequest.json new file mode 100644 index 00000000..826816db --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_SuccessRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 0, + "keyRolePartyIds": [ + 0 + ], + "offeredByPartyId": 50001337, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "skd" + }, + { + "id": "urn:altinn:app", + "value": "taxreport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_UsingkeyRolePartyIdsRequest.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_UsingkeyRolePartyIdsRequest.json new file mode 100644 index 00000000..c2d6b012 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/GetRules/GetRules_UsingkeyRolePartyIdsRequest.json @@ -0,0 +1,25 @@ +{ + "parentPartyId": 0, + "keyRolePartyIds": [ + 50001336 + ], + "offeredByPartyId": 50001337, + "resources": [ + [ + { + "id": "urn:altinn:org", + "value": "skd" + }, + { + "id": "urn:altinn:app", + "value": "taxreport" + } + ] + ], + "coveredBy": [ + { + "id": "urn:altinn:userid", + "value": "20001336" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string.json new file mode 100644 index 00000000..d41e70bc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string.json @@ -0,0 +1,7 @@ +{ +"resourceId": 5, +"resourceRegistryId": "string", +"resourceType": "maskinportenschema", +"created": "2022-12-01T12:53:18.910549Z", +"modified": "2022-12-01T13:01:34.604744Z" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string2.json new file mode 100644 index 00000000..ad5a5ab5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/InsertData_string2.json @@ -0,0 +1,7 @@ +{ +"resourceId": 8, +"resourceRegistryId": "string2", +"resourceType": "MaskinportenSchema", +"created": "2022-12-01T13:01:34.633944Z", +"modified": "2022-12-01T13:01:34.633944Z" +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input1.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input1.json new file mode 100644 index 00000000..8ea4cc84 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input1.json @@ -0,0 +1,10 @@ +[ + { + "resourceregistryid": "string", + "resourcetype": "MaskinportenSchema" + }, + { + "resourceregistryid": "string2", + "resourcetype": "maskinportenschema" + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input2.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input2.json @@ -0,0 +1 @@ +[] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input3.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input3.json new file mode 100644 index 00000000..b1f7a207 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input3.json @@ -0,0 +1,6 @@ +[ + { + "resourceregistryid": "", + "resourcetype": "MaskinportenSchema" + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input4.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input4.json new file mode 100644 index 00000000..80172eb6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input4.json @@ -0,0 +1,14 @@ +[ + { + "resourceregistryid": "string", + "resourcetype": "MaskinportenSchema" + }, + { + "resourceregistryid": "string2", + "resourcetype": "MaskinportenSchema" + }, + { + "resourceregistryid": "string3", + "resourcetype": "maskinportenschema" + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input5.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input5.json new file mode 100644 index 00000000..a27e5321 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/InsertAccessManagementResource/input5.json @@ -0,0 +1,6 @@ +[ + { + "resourceregistryid": "string3", + "resourcetype": "MaskinportenSchema" + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json new file mode 100644 index 00000000..a72b86ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/from_p50005545/authn_u20001337.json @@ -0,0 +1,9 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-4ab72739dcb5cd3d84df7e4d46859e71-4ef2957ed15cf74d-00", + "errors": { + "right[0].Resource": [ "This operation only supports MaskinportenSchema resources. Please use the Single Rights DelegationCheck API. Invalid resource: generic-access-resource. Invalid resource type: GenericAccessResource" ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/request.json new file mode 100644 index 00000000..e531d483 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/generic-access-resource/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json new file mode 100644 index 00000000..e44de6ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/from_p50001337/authn_u20001337.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "This operation does not support MaskinportenSchema resources. Please use the MaskinportenSchema DelegationCheck API. Invalid resource: jks_audi_etron_gt. Invalid resource type: MaskinportenSchema" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/request.json new file mode 100644 index 00000000..248a9246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/jks_audi_etron_gt/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/from_p50005545/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/from_p50005545/authn_u20001337.json new file mode 100644 index 00000000..de6bb2f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/from_p50005545/authn_u20001337.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "The resource does not exist or is not available for delegation" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/request.json new file mode 100644 index 00000000..44336e37 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/non_existing_id/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_existing_id" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/from_p50005545/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/from_p50005545/authn_u20001337.json new file mode 100644 index 00000000..cef99f87 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/from_p50005545/authn_u20001337.json @@ -0,0 +1,9 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-00954cfe03029a84f48b6958264c3630-88574e5f628738d5-00", + "errors": { + "right[0].Resource": [ "This operation only supports MaskinportenSchema resources. Please use the Single Rights DelegationCheck API. Invalid resource: org1/app1. Invalid resource type: AltinnApp" ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/request.json new file mode 100644 index 00000000..eb10114d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/org1_app1/request.json @@ -0,0 +1,12 @@ +{ + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490.json new file mode 100644 index 00000000..0595b94c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490.json @@ -0,0 +1,27 @@ +[ + { + "rightKey": "scope-access-schema:ScopeAccess", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "scope-access-schema" + } + ], + "action": "ScopeAccess", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "DAGL" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490_authLevel2.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490_authLevel2.json new file mode 100644 index 00000000..39f012b8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20000490_authLevel2.json @@ -0,0 +1,27 @@ +[ + { + "rightKey": "scope-access-schema:ScopeAccess", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "scope-access-schema" + } + ], + "action": "ScopeAccess", + "status": "NotDelegable", + "details": [ + { + "code": "InsufficientAuthenticationLevel", + "description": "Authenticated user does not meet the required security level for resource. Minimum authentication level is 3", + "parameters": { + "MinimumAuthenticationLevel": [ + { + "Id": "urn:altinn:minimum-authenticationlevel", + "Value": "3" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20001337.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20001337.json new file mode 100644 index 00000000..0595b94c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/from_p50005545/authn_u20001337.json @@ -0,0 +1,27 @@ +[ + { + "rightKey": "scope-access-schema:ScopeAccess", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "scope-access-schema" + } + ], + "action": "ScopeAccess", + "status": "Delegable", + "details": [ + { + "code": "RoleAccess", + "description": "Delegator have access through having one of the following role(s) for the reportee party: urn:altinn:rolecode:DAGL. Note: if the user is a Main Administrator (HADM) the user might not have direct access to the role other than for delegation purposes.", + "parameters": { + "RoleRequirementsMatches": [ + { + "Id": "urn:altinn:rolecode", + "Value": "DAGL" + } + ] + } + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/request.json new file mode 100644 index 00000000..c626dbba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/DelegationCheck/scope-access-schema/request.json @@ -0,0 +1,8 @@ +{ + "resource": [ + { + "id": "urn:altinn:resource", + "value": "scope-access-schema" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/ExpectedOutput_Default.json new file mode 100644 index 00000000..3ea7fcd3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/ExpectedOutput_Default.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "right[0].Resource": [ + "Authenticated user does not meet the required security level requirement for resource: digdirs_company_car" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/Input_Default.json new file mode 100644 index 00000000..feb83a92 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/digdirs_company_car/from_p50005545/to_p50004222/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/ExpectedOutput_Default.json new file mode 100644 index 00000000..3c3f4155 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/ExpectedOutput_Default.json @@ -0,0 +1,43 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rightDelegationResults": [ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "status": "Delegated" + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "status": "Delegated" + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/Input_Default.json new file mode 100644 index 00000000..69c13ed7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418672/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/ExpectedOutput_Default.json new file mode 100644 index 00000000..42e58195 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/ExpectedOutput_Default.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-89a2524fd6cda819ee788e5ac4e24d4c-03bf71781cd3ed0c-00", + "errors": { + "To": [ + "Maskinporten schema delegation can not have the same party in the From and To Attributes: 910459880" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/Input_Default.json new file mode 100644 index 00000000..efbe42d6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_910459880/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "910459880" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/ExpectedOutput_Default.json new file mode 100644 index 00000000..99756a35 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/ExpectedOutput_Default.json @@ -0,0 +1,43 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "rightDelegationResults": [ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "status": "Delegated" + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "status": "Delegated" + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/Input_Default.json new file mode 100644 index 00000000..2af102c4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004222/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/ExpectedOutput_Default.json new file mode 100644 index 00000000..def765fc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/ExpectedOutput_Default.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-89a2524fd6cda819ee788e5ac4e24d4c-03bf71781cd3ed0c-00", + "errors": { + "To": [ + "Maskinporten schema delegation can not have the same party in the From and To Attributes: 50005545" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/Input_Default.json new file mode 100644 index 00000000..c748c7ce --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50005545/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceRegistryId.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceRegistryId.json new file mode 100644 index 00000000..55aadebb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceRegistryId.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "right[0].Resource": [ + "The resource: non_existing_id, does not exist or is not available for delegation" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceType.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceType.json new file mode 100644 index 00000000..f780c567 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_InvalidResourceType.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "right[0].Resource": [ + "This operation only support requests for Maskinporten schema resources. Invalid resource: Identifier: system_resource, ResourceType: Systemresource" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_OrgAppResource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_OrgAppResource.json new file mode 100644 index 00000000..03ec1a4d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_OrgAppResource.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "right[0].Resource": [ + "This operation only support requests for resources from the Altinn Resource Registry using the urn:altinn:resource attribute id" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_SingleRightOnly.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_SingleRightOnly.json new file mode 100644 index 00000000..6cca1b6d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/ExpectedOutput_SingleRightOnly.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "Rights": [ + "This operation only support requests specifying a single right identifying a Maskinporten schema resource registered in the Altinn Resource Registry" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_Default.json new file mode 100644 index 00000000..be061605 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceRegistryId.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceRegistryId.json new file mode 100644 index 00000000..c3596879 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceRegistryId.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_existing_id" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceType.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceType.json new file mode 100644 index 00000000..6dc987e4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_InvalidResourceType.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "system_resource" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_OrgAppResource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_OrgAppResource.json new file mode 100644 index 00000000..39f59e4f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_OrgAppResource.json @@ -0,0 +1,22 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_SingleRightOnly.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_SingleRightOnly.json new file mode 100644 index 00000000..d37d4b8c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p1/to_p2/Input_SingleRightOnly.json @@ -0,0 +1,26 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details1" + } + ] + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details2" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/ExpectedOutput_InvalidFrom_Ssn.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/ExpectedOutput_InvalidFrom_Ssn.json new file mode 100644 index 00000000..1a8f1130 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/ExpectedOutput_InvalidFrom_Ssn.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "From": [ + "Maskinporten schema delegation can only be delegated from a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 07124912037" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/Input_Default.json new file mode 100644 index 00000000..be061605 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50002598/to_p2/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json new file mode 100644 index 00000000..5f943211 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "To": [ + "Maskinporten schema delegation can only be delegated to a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 2" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json new file mode 100644 index 00000000..be061605 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_Ssn.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_Ssn.json new file mode 100644 index 00000000..042b3e62 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_Ssn.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "To": [ + "Maskinporten schema delegation can only be delegated to a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 02056260016" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_UserId.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_UserId.json new file mode 100644 index 00000000..332f81e9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/ExpectedOutput_InvalidTo_UserId.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "To": [ + "Maskinporten schema delegation can only be delegated to a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 20001337" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_Ssn.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_Ssn.json new file mode 100644 index 00000000..97b479ba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_Ssn.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:socialsecuritynumber", + "value": "02056260016" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_UserId.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_UserId.json new file mode 100644 index 00000000..e8cea724 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_u20001337/Input_InvalidTo_UserId.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/ExpectedOutput_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/ExpectedOutput_Default.json new file mode 100644 index 00000000..6881c54e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/ExpectedOutput_Default.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "right[0].Resource": [ + "Authenticated user does not have any delegable rights for the resource: non_delegable_maskinportenschema" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/Input_Default.json new file mode 100644 index 00000000..b64370f9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/MaskinportenScopeDelegation/non_delegable_maskinportenschema/from_p50005545/to_p50004222/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_delegable_maskinportenschema" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Offered.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Offered.json new file mode 100644 index 00000000..482c869e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Offered.json @@ -0,0 +1,134 @@ +[ + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004220, + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "coveredbyorganizationnumber": "810418362", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004221, + "coveredbyname": "LUNDAMO OG FLEINVAR", + "coveredbyorganizationnumber": "810418532", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004220, + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "coveredbyorganizationnumber": "810418362", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004223, + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbyorganizationNumber": "810418982", + "coveredbypartyid": 50004221, + "coveredbyname": "LUNDAMO OG FLEINVAR", + "coveredbyorganizationnumber": "810418532", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "nav1_aa_distribution" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004220, + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "coveredbyorganizationnumber": "810418362", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav1_aa_distribution" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004221, + "coveredbyname": "LUNDAMO OG FLEINVAR", + "coveredbyorganizationnumber": "810418532", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav1_aa_distribution" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004220, + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "coveredbyorganizationnumber": "810418362", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004221, + "coveredbyname": "LUNDAMO OG FLEINVAR", + "coveredbyorganizationnumber": "810418532", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Received.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Received.json new file mode 100644 index 00000000..14ff2117 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/Received.json @@ -0,0 +1,112 @@ +[ + { + "offeredbypartyid": 50004222, + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbyorganizationNumber": "810418672", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004222, + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbyorganizationNumber": "810418672", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004220, + "offeredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyorganizationNumber": "810418362", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004220, + "offeredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyorganizationNumber": "810418362", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004221, + "offeredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyorganizationNumber": "810418532", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004221, + "offeredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyorganizationNumber": "810418532", + "coveredbypartyid": 50004219, + "coveredbyname": "KOLSAAS OG FLAAM", + "coveredbyorganizationnumber": "810418192", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004222, + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbyorganizationNumber": "810418672", + "coveredbypartyid": 50004216, + "coveredbyname": "TYNSET OG OPPDAL", + "coveredbyorganizationnumber": "10008387", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "nav_aa_distribution" + }, + { + "offeredbypartyid": 50004222, + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbyorganizationNumber": "810418672", + "coveredbypartyid": 50004216, + "coveredbyname": "TYNSET OG OPPDAL", + "coveredbyorganizationnumber": "10008387", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004216, + "coveredbyname": "TYNSET OG OPPDAL", + "coveredbyorganizationnumber": "10008387", + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "resourceid": "nav1_aa_distribution" + }, + { + "offeredbypartyid": 50004226, + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbyorganizationNumber": "810419342", + "coveredbypartyid": 50004216, + "coveredbyname": "TYNSET OG OPPDAL", + "coveredbyorganizationnumber": "10008387", + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "resourceid": "skd_1" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json new file mode 100644 index 00000000..883bfab9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418532" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json new file mode 100644 index 00000000..b5d9629f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004221" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json new file mode 100644 index 00000000..883bfab9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418532" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json new file mode 100644 index 00000000..b5d9629f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "50004221" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json new file mode 100644 index 00000000..5f943211 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/ExpectedOutput_InvalidTo.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "To": [ + "Maskinporten schema delegation can only be delegated to a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 2" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json new file mode 100644 index 00000000..be061605 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeOfferedMaskinportenScopeDelegation/mp_validation_problem_details/from_p50005545/to_p2/Input_Default.json @@ -0,0 +1,18 @@ +{ + "to": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json new file mode 100644 index 00000000..299f3df2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_810418532/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:organizationnumber", + "value": "910459880" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json new file mode 100644 index 00000000..299f3df2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_910459880/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:organizationnumber", + "value": "910459880" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json new file mode 100644 index 00000000..528441e3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_810418532/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json new file mode 100644 index 00000000..528441e3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_audi_etron_gt/from_p50005545/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_undelegable/from_p50005545/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_undelegable/from_p50005545/to_p50004221/Input_Default.json new file mode 100644 index 00000000..045177cb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/jks_undelegable/from_p50005545/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_undelegable" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/ExpectedOutput_InvalidFrom.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/ExpectedOutput_InvalidFrom.json new file mode 100644 index 00000000..e6a95bea --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/ExpectedOutput_InvalidFrom.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-27cf2819f526d884b56a1c8fd44a09ad-5fe2af21a90ad213-00", + "errors": { + "From": [ + "Maskinporten schema delegation can only be delegated from a valid organization (identified by either urn:altinn:organizationnumber or urn:altinn:partyid attribute id). Invalid value: 2" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/Input_Default.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/Input_Default.json new file mode 100644 index 00000000..b7d5248c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/RevokeReceivedMaskinportenScopeDelegation/mp_validation_problem_details/from_p2/to_p50004221/Input_Default.json @@ -0,0 +1,18 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "2" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/admindelegations.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/admindelegations.json new file mode 100644 index 00000000..55506ecb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/admindelegations.json @@ -0,0 +1,24 @@ +[ + { + "consumer_org": "810418672", + "supplier_org": "810418192", + "delegation_scheme_Id": null, + "scopes": [ + "altinn:test/theworld.write", + "urn:altinn:maskinporten:nav_aa" + ], + "created": "2022-09-27T15:02:23.7860720+02:00", + "resourceid": "nav_aa_distribution" + }, + { + "consumer_org": "810418672", + "supplier_org": "810418192", + "delegation_scheme_Id": "3cb27d7b-9e2c-475c-ba91-e1fc359bc717", + "scopes": [ + "altinn:test/theworld.write", + "altinn:test/theworld.admin" + ], + "created": "2022-09-27T15:02:23.7860720+02:00", + "resourceid": "appid-123" + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/inbounddelegation.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/inbounddelegation.json new file mode 100644 index 00000000..6f06df22 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/inbounddelegation.json @@ -0,0 +1,122 @@ +[ + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418672, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810418672, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbypartyid": 50004220, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810418362, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbypartyid": 50004220, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810418362, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "LUNDAMO OG FLEINVAR", + "offeredbypartyid": 50004221, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418532, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "LUNDAMO OG FLEINVAR", + "offeredbypartyid": 50004221, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418532, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "TYNSET OG OPPDAL", + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50004216, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418672, + "CoveredByOrganizationNumber": 10008387, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "TYNSET OG OPPDAL", + "offeredbyname": "KARLSTAD OG ULOYBUKT", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50004216, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418672, + "CoveredByOrganizationNumber": 10008387, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "TYNSET OG OPPDAL", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004216, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 10008387, + "resourceid": "nav1_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "TYNSET OG OPPDAL", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004216, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 10008387, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/outbounddelegation.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/outbounddelegation.json new file mode 100644 index 00000000..a89afff3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/MaskinportenSchema/outbounddelegation.json @@ -0,0 +1,146 @@ +[ + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004220, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418362, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004221, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418532, + "resourceid": "nav_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004220, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418362, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyname": "HAMAR OG GJESVÆR", + "offeredbypartyid": 50004223, + "coveredbypartyid": 50004221, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810418982, + "CoveredByOrganizationNumber": 810418532, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "nav1_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004220, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418362, + "resourceid": "nav1_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004221, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418532, + "resourceid": "nav1_aa_distribution", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "KOLSAAS OG FLAAM", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004219, + "performedbyuserid": 20000002, + "created": "2022-10-17T11:37:58.053427Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418192, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "NORDRE FROGN OG MORTENHALS", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004220, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418362, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + }, + { + "coveredbyname": "LUNDAMO OG FLEINVAR", + "offeredbyname": "KOLBJORNSVIK OG ROAN", + "offeredbypartyid": 50004226, + "coveredbypartyid": 50004221, + "performedbyuserid": 20000002, + "created": "2022-09-24T22:00:00Z", + "offeredbyorganizationNumber": 810419342, + "CoveredByOrganizationNumber": 810418532, + "resourceid": "skd_1", + "resourcetype": "MaskinportenSchema" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_request.json new file mode 100644 index 00000000..89edddc0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_request.json @@ -0,0 +1,36 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "write" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_response.json new file mode 100644 index 00000000..3d28401d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_org1_app1/from_910001337/to_810418672/by_27099450067/success_response.json @@ -0,0 +1,40 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "RightDelegationResults": [ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "status": "Delegated" + }, + { + "rightKey": "app1,org1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "write", + "status": "NotDelegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_request.json new file mode 100644 index 00000000..240ab0ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_request.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "9D569A55-D5CE-4914-BBF8-CA3474458604" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "read" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_response.json new file mode 100644 index 00000000..bcd6e25f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/app_ttd_apps-test/from_910459880/to_9D569A55-D5CE-4914-BBF8-CA3474458604/by_07124912037/success_response.json @@ -0,0 +1,25 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "9D569A55-D5CE-4914-BBF8-CA3474458604" + } + ], + "RightDelegationResults": [ + { + "rightKey": "apps-test,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ], + "action": "read", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_request.json new file mode 100644 index 00000000..13c9f75f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_request.json @@ -0,0 +1,28 @@ +{ + "to": [ + { + "id": "urn:altinn:organization:uuid", + "value": "00000000-0000-0000-0001-000000000004" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_response.json new file mode 100644 index 00000000..152c6bb4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_00000000-0000-0000-0001-000000000004/by_07124912037/success_response.json @@ -0,0 +1,32 @@ +{ + "to": [ + { + "id": "urn:altinn:organization:uuid", + "value": "00000000-0000-0000-0001-000000000004" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_request.json new file mode 100644 index 00000000..6946cb4a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_request.json @@ -0,0 +1,32 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_response.json new file mode 100644 index 00000000..ef5d776c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_07124912037/to_27099450067/by_07124912037/success_response.json @@ -0,0 +1,36 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource:write", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "write", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_request.json new file mode 100644 index 00000000..d101e409 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_request.json @@ -0,0 +1,62 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_response.json new file mode 100644 index 00000000..56f56ceb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_810418532/to_810418672/by_07124912037/success_response.json @@ -0,0 +1,70 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_request.json new file mode 100644 index 00000000..48f20423 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_request.json @@ -0,0 +1,19 @@ +{ + "to": [ + { + "id": "urn:altinn:enterpriseuser:uuid", + "value": "00000000-0000-0000-0002-000000010727" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_response.json new file mode 100644 index 00000000..8cd68528 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0002-000000010727/by_02056260016/success_response.json @@ -0,0 +1,21 @@ +{ + "to": [ + { + "id": "urn:altinn:enterpriseuser:uuid", + "value": "00000000-0000-0000-0002-000000010727" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_request.json new file mode 100644 index 00000000..e730b89d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_request.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:person:uuid", + "value": "00000000-0000-0000-0005-000000003899" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_response.json new file mode 100644 index 00000000..6bcaf7a2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_00000000-0000-0000-0005-000000003899/by_07124912037/success_response.json @@ -0,0 +1,25 @@ +{ + "to": [ + { + "id": "urn:altinn:person:uuid", + "value": "00000000-0000-0000-0005-000000003899" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json new file mode 100644 index 00000000..b7964b56 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "16C1F2F6-9E00-4922-B16D-74C46D948E61" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json new file mode 100644 index 00000000..72a26e61 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json @@ -0,0 +1,25 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "16C1F2F6-9E00-4922-B16D-74C46D948E61" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_request.json new file mode 100644 index 00000000..b7964b56 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_request.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "16C1F2F6-9E00-4922-B16D-74C46D948E61" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_response.json new file mode 100644 index 00000000..72a26e61 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/success_response.json @@ -0,0 +1,25 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "16C1F2F6-9E00-4922-B16D-74C46D948E61" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_request.json new file mode 100644 index 00000000..c96efdf3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_request.json @@ -0,0 +1,62 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "02056260016" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_response.json new file mode 100644 index 00000000..29d01200 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/missing-to-lastname_response.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "To": [ + "A distinct recipient party for the delegation, could not be identified by the supplied attributes. A recipient can be identified by either a single urn:altinn:organizationnumber or urn:altinn:enterpriseuser:username attribute, or a combination of urn:altinn:person:identifier-no and urn:altinn:person:lastname attributes, urn:altinn:person:username and urn:altinn:person:lastname attributes or urn:altinn:systemuser:uuid attribute." + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_request.json new file mode 100644 index 00000000..904de00d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_request.json @@ -0,0 +1,66 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_response.json new file mode 100644 index 00000000..ba62e564 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_07124912037/success_response.json @@ -0,0 +1,74 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_request.json new file mode 100644 index 00000000..fc37b5cf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_request.json @@ -0,0 +1,75 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_response.json new file mode 100644 index 00000000..6e56e77f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_27099450067/by_27099450067/success_response.json @@ -0,0 +1,85 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource:read", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "read", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:subunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "subunit-delegated-action-to-keyroleunit", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action", + "status": "Delegated" + }, + { + "rightKey": "generic-access-resource,org-delegation-subtask:mainunit-delegated-action-to-keyroleunit", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action-to-keyroleunit", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_request.json new file mode 100644 index 00000000..fc830428 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_request.json @@ -0,0 +1,19 @@ +{ + "to": [ + { + "id": "urn:altinn:enterpriseuser:username", + "value": "OrstaECUser" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_response.json new file mode 100644 index 00000000..0ecc39d4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/not-yet-supported_response.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "To": [ + "Enterpriseuser delegation is not yet supported." + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_request.json new file mode 100644 index 00000000..fc830428 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_request.json @@ -0,0 +1,19 @@ +{ + "to": [ + { + "id": "urn:altinn:enterpriseuser:username", + "value": "OrstaECUser" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_response.json new file mode 100644 index 00000000..e4983172 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource/from_910459880/to_OrstaECUser/by_02056260016/success_response.json @@ -0,0 +1,21 @@ +{ + "to": [ + { + "id": "urn:altinn:enterpriseuser:username", + "value": "OrstaECUser" + } + ], + "RightDelegationResults": [ + { + "rightKey": "generic-access-resource:admai-delegated-action", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ], + "action": "admai-delegated-action", + "status": "Delegated" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json new file mode 100644 index 00000000..60be36ae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_request.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "16C1F2F6-9E00-4922-B16D-74C46D948E61" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource2" + }, + { + "id": "urn:altinn:task", + "value": "org-delegation-subtask" + } + ], + "action": "mainunit-delegated-action" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json new file mode 100644 index 00000000..42d0e010 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/generic-access-resource2/from_910459880/to_16C1F2F6-9E00-4922-B16D-74C46D948E61/by_07124912037/failure_response.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "errors": { + "right[0].Resource": [ + "The resource does not exist or is not available for delegation" + ] + }, + "traceId": "0HN529OQ63R5R" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_request.json new file mode 100644 index 00000000..2446160e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_request.json @@ -0,0 +1,19 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_existing_id" + } + ], + "action": "read" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_response.json new file mode 100644 index 00000000..de6bb2f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/jks_audi_etron_gt/from_910001337/to_810418672/by_27099450067/invalid-resource-maskinportenschema_response.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "The resource does not exist or is not available for delegation" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_request.json new file mode 100644 index 00000000..2446160e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_request.json @@ -0,0 +1,19 @@ +{ + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "810418672" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "non_existing_id" + } + ], + "action": "read" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_response.json new file mode 100644 index 00000000..de6bb2f7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/non_existing_id/from_910001337/to_810418672/by_27099450067/invalid-resource_response.json @@ -0,0 +1,11 @@ +{ + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-28b6bcd340952ec6500b24cdc8498b6a-60b6ed58b49f5af6-00", + "errors": { + "right[0].Resource": [ + "The resource does not exist or is not available for delegation" + ] + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_50005545/to_20001337/by_20000490/sbl_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_50005545/to_20001337/by_20000490/sbl_response.json new file mode 100644 index 00000000..e8fe5604 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_50005545/to_20001337/by_20000490/sbl_response.json @@ -0,0 +1,52 @@ +[ + { + "RightKey": "2802,2203:read", + "Resource": [ + { + "id": "urn:altinn:servicecode", + "value": "2802" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "2203" + } + ], + "Action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + }, + "Status": "Delegated", + "Details": [ + { + "Code": "DelegationAccess", + "Description": null, + "Parameters": {} + } + ] + }, + { + "RightKey": "2802,2203:write", + "Resource": [ + { + "id": "urn:altinn:servicecode", + "value": "2802" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "2203" + } + ], + "Action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "write" + }, + "Status": "Delegated", + "Details": [ + { + "Code": "DelegationAccess", + "Description": null, + "Parameters": {} + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_request.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_request.json new file mode 100644 index 00000000..5583989e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_request.json @@ -0,0 +1,40 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "rights": [ + { + "resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "2802" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "2203" + } + ], + "action": "read" + }, + { + "resource": [ + { + "Id": "urn:altinn:servicecode", + "Value": "2802" + }, + { + "Id": "urn:altinn:serviceeditioncode", + "Value": "2203" + } + ], + "action": "write" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_response.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_response.json new file mode 100644 index 00000000..9201bf5a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsDelegation/se_2802_2203/from_910459880/to_27099450067/by_07124912037/success_response.json @@ -0,0 +1,58 @@ +{ + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "27099450067" + }, + { + "id": "urn:altinn:person:lastname", + "value": "RAVNÃ…S" + } + ], + "RightDelegationResults": [ + { + "RightKey": "2802,2203:read", + "Resource": [ + { + "id": "urn:altinn:servicecode", + "value": "2802" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "2203" + } + ], + "Action": "read", + "Status": "Delegated", + "Details": [ + { + "Code": "DelegationAccess", + "Description": null, + "Parameters": {} + } + ] + }, + { + "RightKey": "2802,2203:write", + "Resource": [ + { + "id": "urn:altinn:servicecode", + "value": "2802" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "2203" + } + ], + "Action": "write", + "Status": "Delegated", + "Details": [ + { + "Code": "DelegationAccess", + "Description": null, + "Parameters": {} + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json new file mode 100644 index 00000000..10f75fb3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json new file mode 100644 index 00000000..32960f8c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_false.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json new file mode 100644 index 00000000..0f5319fb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/digdirs_company_car/from_p50005545/to_u20001337/expected_rights_returnall_true.json @@ -0,0 +1,37 @@ +[ + { + "rightKey": "digdirs_company_car:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ], + "action": "drive", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..e87466a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50004221" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..a2d4f281 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,110 @@ +[ + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:5", + "policyVersion": "1.0", + "ruleId": "e7a89266-9457-45c9-86c4-53155c6f0230", + "offeredByPartyId": 50004221, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..58b57e03 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004221/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,295 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:5", + "policyVersion": "1.0", + "ruleId": "e7a89266-9457-45c9-86c4-53155c6f0230", + "offeredByPartyId": 50004221, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt,mechanic_work:change_tires", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + }, + { + "id": "urn:altinn:task", + "value": "mechanic_work" + } + ], + "action": "change_tires", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..a2b3d7e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..31e297d8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,80 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "drive" + }, + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "park" + }, + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..ff13cc08 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50004222/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,284 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "drive" + }, + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:4", + "policyVersion": "1.0", + "ruleId": "45453412-efea-4238-8887-6256d8d1727f", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50005545" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "park" + }, + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:3", + "policyVersion": "1.0", + "ruleId": "16f91ee0-2c15-474c-a9df-712371289b15", + "offeredByPartyId": 50004222, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000490" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "race" + }, + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt,mechanic_work:change_tires", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + }, + { + "id": "urn:altinn:task", + "value": "mechanic_work" + } + ], + "action": { + "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "change_tires" + }, + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/RightsQuery.json new file mode 100644 index 00000000..cc81791f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000095" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_false.json new file mode 100644 index 00000000..9545260c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_false.json @@ -0,0 +1,74 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:2", + "policyVersion": "1.0", + "ruleId": "7d4ea875-c62e-4a45-acfd-32c9c5b1b122", + "offeredByPartyId": 50005545, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50004222" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "4ab005d9-1770-4c9b-9dc0-9e06eb31c5b4", + "offeredByPartyId": 50005545, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000095" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000095" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_true.json new file mode 100644 index 00000000..72d308af --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000095/expected_rights_returnall_true.json @@ -0,0 +1,320 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:2", + "policyVersion": "1.0", + "ruleId": "7d4ea875-c62e-4a45-acfd-32c9c5b1b122", + "offeredByPartyId": 50005545, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:partyid", + "value": "50004222" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:partyid", + "value": "50004222" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "4ab005d9-1770-4c9b-9dc0-9e06eb31c5b4", + "offeredByPartyId": 50005545, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20000095" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20000095" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt,mechanic_work:change_tires", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + }, + { + "id": "urn:altinn:task", + "value": "mechanic_work" + } + ], + "action": "change_tires", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..368492bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/RightsQuery.json @@ -0,0 +1,20 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..f6f2eb1d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,416 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..db2e6605 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/jks_audi_etron_gt/from_p50005545/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,826 @@ +[ + { + "rightKey": "jks_audi_etron_gt:drive", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "drive", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:park", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "park", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + }, + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "driveway" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt:race", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ], + "action": "race", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "INNH" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + } + ] + ] + } + ] + }, + { + "rightKey": "jks_audi_etron_gt,mechanic_work:change_tires", + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + }, + { + "id": "urn:altinn:task", + "value": "mechanic_work" + } + ], + "action": "change_tires", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "ResourceRegistryPolicy", + "policyId": "urn:altinn:example:delegationscheme:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "matchFound": null, + "id": "urn:altinn:location", + "value": "garage" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json new file mode 100644 index 00000000..e669eefc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/RightsQuery.json @@ -0,0 +1,24 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50001337" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json new file mode 100644 index 00000000..69236ff9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_false.json @@ -0,0 +1,130 @@ +[ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "57b3ee85-f932-42c6-9ab0-941eb6c96eb0", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1,task1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:task", + "value": "task1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "78e5cced-3bcb-42b6-9089-63c834f89e73", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,event1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:appresource", + "value": "event1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "31776194-9921-4383-994d-dfd42a2aa91b", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json new file mode 100644 index 00000000..c8d0e06a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/org1_app1/from_p50001337/to_u20001337/expected_rights_returnall_true.json @@ -0,0 +1,257 @@ +[ + { + "rightKey": "app1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "regna" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + }, + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "57b3ee85-f932-42c6-9ab0-941eb6c96eb0", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ], + "action": "write", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "regna" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1,task1:sign", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:task", + "value": "task1" + } + ], + "action": "sign", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": false, + "userSubjects": [ + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "dagl" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "priv" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,org1,task1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:task", + "value": "task1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "78e5cced-3bcb-42b6-9089-63c834f89e73", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + }, + { + "rightKey": "app1,event1,org1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + }, + { + "id": "urn:altinn:appresource", + "value": "event1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "DelegationPolicy", + "policyId": "urn:altinn:policyid:1", + "policyVersion": "1.0", + "ruleId": "31776194-9921-4383-994d-dfd42a2aa91b", + "offeredByPartyId": 50001337, + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:userid", + "value": "20001337" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:userid", + "value": "20001337" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json new file mode 100644 index 00000000..4c4d0631 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/RightsQuery.json @@ -0,0 +1,24 @@ +{ + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:userid", + "value": "20000490" + } + ], + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json new file mode 100644 index 00000000..f154a933 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_false.json @@ -0,0 +1,1026 @@ +[ + { + "rightKey": "rf-0002,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "instantiate", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action":"read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "delete", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json new file mode 100644 index 00000000..6e0d7882 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Json/RightsQuery/ttd_rf-0002/from_p50005545/to_u20000490/expected_rights_returnall_true.json @@ -0,0 +1,1300 @@ +[ + { + "rightKey": "rf-0002,ttd:instantiate", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "instantiate", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:1", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd,Task_1:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:task", + "value": "Task_1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:read", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "read", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "write", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:2", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:delete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "delete", + "hasPermit": true, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:3", + "hasPermit": true, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "REGNA" + } + ], + [ + { + "matchFound": null, + "id": "urn:altinn:rolecode", + "value": "DAGL" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,ttd:write", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + } + ], + "action": "write", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:4", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + }, + { + "rightKey": "rf-0002,EndEvent_1,ttd:complete", + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "rf-0002" + }, + { + "id": "urn:altinn:end-event", + "value": "EndEvent_1" + } + ], + "action": "complete", + "hasPermit": false, + "rightSources": [ + { + "rightSourceType": "AppPolicy", + "policyId": "urn:altinn:example:policyid:1", + "policyVersion": "1.0", + "ruleId": "urn:altinn:example:ruleid:5", + "hasPermit": false, + "userSubjects": [ + { + "id": "urn:altinn:rolecode", + "value": "LOPER" + }, + { + "id": "urn:altinn:rolecode", + "value": "ADMAI" + }, + { + "id": "urn:altinn:rolecode", + "value": "REGNA" + }, + { + "id": "urn:altinn:rolecode", + "value": "SISKD" + }, + { + "id": "urn:altinn:rolecode", + "value": "UILUF" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTINN" + }, + { + "id": "urn:altinn:rolecode", + "value": "UTOMR" + }, + { + "id": "urn:altinn:rolecode", + "value": "KLADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "ATTST" + }, + { + "id": "urn:altinn:rolecode", + "value": "HVASK" + }, + { + "id": "urn:altinn:rolecode", + "value": "PAVAD" + }, + { + "id": "urn:altinn:rolecode", + "value": "SIGNE" + }, + { + "id": "urn:altinn:rolecode", + "value": "UIHTL" + }, + { + "id": "urn:altinn:rolecode", + "value": "KOMAB" + }, + { + "id": "urn:altinn:rolecode", + "value": "LEDE" + }, + { + "id": "urn:altinn:rolecode", + "value": "DAGL" + }, + { + "id": "urn:altinn:rolecode", + "value": "ECKEYROLE" + }, + { + "id": "urn:altinn:rolecode", + "value": "HADM" + }, + { + "id": "urn:altinn:rolecode", + "value": "PASIG" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0278" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0236" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0212" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0293" + }, + { + "id": "urn:altinn:rolecode", + "value": "A0294" + }, + { + "id": "urn:altinn:rolecode", + "value": "APIADM" + } + ], + "policySubjects": [ + [ + { + "matchFound": null, + "id": "urn:altinn:org", + "value": "ttd" + } + ] + ] + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000095/keyroleunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000095/keyroleunits.json new file mode 100644 index 00000000..68272d5f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000095/keyroleunits.json @@ -0,0 +1,4 @@ +[ + 50004222, + 50004221 +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000490/keyroleunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000490/keyroleunits.json new file mode 100644 index 00000000..161c2e78 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20000490/keyroleunits.json @@ -0,0 +1,3 @@ +[ + 50005545 +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100005/keyroleunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100005/keyroleunits.json new file mode 100644 index 00000000..58c62034 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100005/keyroleunits.json @@ -0,0 +1,3 @@ +[ + 50100004 +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100010/keyroleunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100010/keyroleunits.json new file mode 100644 index 00000000..8bbf5ba2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100010/keyroleunits.json @@ -0,0 +1,3 @@ +[ + 50100010 +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100011/keyroleunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100011/keyroleunits.json new file mode 100644 index 00000000..8bbf5ba2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/KeyRoleUnits/20100011/keyroleunits.json @@ -0,0 +1,3 @@ +[ + 50100010 +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50004221/mainunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50004221/mainunits.json new file mode 100644 index 00000000..ca685818 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50004221/mainunits.json @@ -0,0 +1,8 @@ +[ + { + "PartyId": 50004221, + "ParentPartyId": 50004222, + "ParentOrganizationNumber": "810418672", + "ParentOrganizationName": "KARLSTAD OG ULØYBUKT REGNSKAP" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50005545/mainunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50005545/mainunits.json new file mode 100644 index 00000000..143e542a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50005545/mainunits.json @@ -0,0 +1,8 @@ +[ + { + "PartyId": 50005545, + "ParentPartyId": null, + "ParentOrganizationNumber": null, + "ParentOrganizationName": null + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100006/mainunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100006/mainunits.json new file mode 100644 index 00000000..f56df977 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100006/mainunits.json @@ -0,0 +1,8 @@ +[ + { + "PartyId": 50100006, + "ParentPartyId": null, + "ParentOrganizationNumber": null, + "ParentOrganizationName": null + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100007/mainunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100007/mainunits.json new file mode 100644 index 00000000..79ad9deb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100007/mainunits.json @@ -0,0 +1,8 @@ +[ + { + "PartyId": 50100007, + "ParentPartyId": 50100006, + "ParentOrganizationNumber": "901000006", + "ParentOrganizationName": "AUTHORIZEDPARTIES MAINUNIT" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100008/mainunits.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100008/mainunits.json new file mode 100644 index 00000000..35e94753 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/MainUnits/50100008/mainunits.json @@ -0,0 +1,8 @@ +[ + { + "PartyId": 50100008, + "ParentPartyId": 50100006, + "ParentOrganizationNumber": "901000006", + "ParentOrganizationName": "AUTHORIZEDPARTIES MAINUNIT" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Parties/parties.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Parties/parties.json new file mode 100644 index 00000000..b1826d22 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Parties/parties.json @@ -0,0 +1,1124 @@ +[ + { + "PartyTypeName": 2, + "SSN": "null", + "OrgNumber": "910493353", + "Person": null, + "Organization": { + "OrgNumber": "910493353", + "Name": "LEPSØY OG TONSTAD", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50006078, + "PartyUuid": "00000000-0000-0000-0005-000000006078", + "UnitType": "AS", + "Name": "LEPSØY OG TONSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": [ + { + "PartyTypeName": 2, + "SSN": "null", + "OrgNumber": "910422154", + "Person": null, + "Organization": { + "OrgNumber": "910422154", + "Name": "ROGNE OG HERØY", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004646, + "PartyUuid": "00000000-0000-0000-0005-000000004646", + "UnitType": "AS", + "Name": "ROGNE OG HERØY", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + } + ] + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "10008387", + "Person": null, + "Organization": { + "OrgNumber": "10008387", + "Name": "TYNSET OG OPPDAL", + "UnitType": "ANS", + "TelephoneNumber": "22077000", + "MobileNumber": "99000000", + "FaxNumber": "22077108", + "EMailAddress": null, + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": "", + "MailingPostalCity": "", + "BusinessAddress": null, + "BusinessPostalCode": "", + "BusinessPostalCity": "" + }, + "PartyId": 50004216, + "PartyUuid": "00000000-0000-0000-0005-000000004216", + "UnitType": "ANS", + "Name": "TYNSET OG OPPDAL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810418192", + "Person": null, + "Organization": { + "OrgNumber": "810418192", + "Name": "KOLSAAS OG FLAAM", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004219, + "PartyUuid": "00000000-0000-0000-0005-000000004219", + "UnitType": "AS", + "Name": "KOLSAAS OG FLAAM", + "IsDeleted": true, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810418362", + "Person": null, + "Organization": { + "OrgNumber": "810418362", + "Name": "NORDRE FROGN OG MORTENHALS", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004220, + "PartyUuid": "00000000-0000-0000-0005-000000004220", + "UnitType": "AS", + "Name": "NORDRE FROGN OG MORTENHALS", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810418532", + "Person": null, + "Organization": { + "OrgNumber": "810418532", + "Name": "LUNDAMO OG FLEINVAR", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004221, + "PartyUuid": "00000000-0000-0000-0005-000000004221", + "UnitType": "AS", + "Name": "LUNDAMO OG FLEINVAR", + "IsDeleted": true, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810418672", + "Person": null, + "Organization": { + "OrgNumber": "810418672", + "Name": "KARLSTAD OG ULOYBUKT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004222, + "PartyUuid": "00000000-0000-0000-0005-000000004222", + "UnitType": "AS", + "Name": "KARLSTAD OG ULOYBUKT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810418982", + "Person": null, + "Organization": { + "OrgNumber": "810418982", + "Name": "HAMAR OG GJESVÆR", + "UnitType": "AS", + "TelephoneNumber": "12345678", + "MobileNumber": "99999999", + "FaxNumber": "12345679", + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": "", + "MailingPostalCity": "", + "BusinessAddress": null, + "BusinessPostalCode": "", + "BusinessPostalCity": "" + }, + "PartyId": 50004223, + "PartyUuid": "00000000-0000-0000-0005-000000004223", + "UnitType": "AS", + "Name": "HAMAR OG GJESVÆR", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810419172", + "Person": null, + "Organization": { + "OrgNumber": "810419172", + "Name": "STJORDAL OG HOMBORSUND", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004224, + "PartyUuid": "00000000-0000-0000-0005-000000004224", + "UnitType": "AS", + "Name": "STJORDAL OG HOMBORSUND", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810419202", + "Person": null, + "Organization": { + "OrgNumber": "810419202", + "Name": "ROSSFJORDSTRAUMEN OG EIKEFJORD", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004225, + "PartyUuid": "00000000-0000-0000-0005-000000004225", + "UnitType": "AS", + "Name": "ROSSFJORDSTRAUMEN OG EIKEFJORD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810419342", + "Person": null, + "Organization": { + "OrgNumber": "810419342", + "Name": "KOLBJORNSVIK OG ROAN", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004226, + "PartyUuid": "00000000-0000-0000-0005-000000004226", + "UnitType": "AS", + "Name": "KOLBJORNSVIK OG ROAN", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "01124621077", + "OrgNumber": "", + "Person": null, + "Organization": { + "OrgNumber": "", + "Name": "KARI GUNNERUD", + "UnitType": "", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50002182, + "PartyUuid": "00000000-0000-0000-0005-000000002182", + "UnitType": null, + "Name": "KARI GUNNERUD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "910459880", + "Person": null, + "Organization": { + "OrgNumber": "910459880", + "Name": "ØRSTA OG HEGGEDAL REGNSKAP", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50005545, + "PartyUuid": "00000000-0000-0000-0005-000000005545", + "UnitType": "AS", + "Name": "ØRSTA OG HEGGEDAL REGNSKAP", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810419482", + "Person": null, + "Organization": { + "OrgNumber": "810419482", + "Name": "ØRSTA OG HEGGEDAL REVISJON", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50005546, + "PartyUuid": "00000000-0000-0000-0005-000000005546", + "UnitType": "AS", + "Name": "ØRSTA OG HEGGEDAL REVISJON", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "910001337", + "Person": null, + "Organization": { + "OrgNumber": "910001337", + "Name": "1337", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50001337, + "PartyUuid": "00000000-0000-0000-0005-000000001337", + "UnitType": "AS", + "Name": "1337", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "927144913", + "Person": null, + "Organization": { + "OrgNumber": "927144913", + "Name": "JOHNNY KJETIL BLIKKENSLAGER AS", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 20001337, + "UnitType": "AS", + "Name": "JOHNNY KJETIL BLIKKENSLAGER AS", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "21033041133", + "OrgNumber": "", + "Person": { + "SSN": "21033041133", + "Name": "JOHNNY KJETILSEN", + "FirstName": "JOHNNY", + "MiddleName": "ANDRE", + "LastName": "KJETILSEN", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": "Tarr'a en dramveien 20 1628 FREDRIKSTAD", + "MailingPostalCode": "1628", + "MailingPostalCity": "FREDRIKSTAD", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "1628", + "AddressCity": "FREDRIKSTAD", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 20001337, + "UnitType": null, + "Name": "JOHNNY KJETILSEN", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "07124912037", + "OrgNumber": "", + "Person": { + "SSN": "07124912037", + "Name": "KASPER BØRSTAD", + "FirstName": "KASPER", + "MiddleName": "", + "LastName": "BØRSTAD", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " SkÃ¥levikstølen 7 5178 LODDEFJORD", + "MailingPostalCode": "5178", + "MailingPostalCity": "LODDEFJORD", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "5178", + "AddressCity": "LODDEFJORD", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002598, + "PartyUuid": "00000000-0000-0000-0005-000000002598", + "UnitType": null, + "Name": "KASPER BØRSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "02056260016", + "OrgNumber": "", + "Person": { + "SSN": "02056260016", + "Name": "PAULA RIMSTAD", + "FirstName": "PAULA", + "MiddleName": null, + "LastName": "RIMSTAD", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002203, + "PartyUuid": "00000000-0000-0000-0005-000000002203", + "UnitType": null, + "Name": "PAULA RIMSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "27099450067", + "OrgNumber": "", + "Person": { + "SSN": "27099450067", + "Name": "ØRJAN RAVNÃ…S", + "FirstName": "ØRJAN", + "MiddleName": null, + "LastName": "RAVNÃ…S", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50003899, + "PartyUuid": "00000000-0000-0000-0005-000000003899", + "UnitType": null, + "Name": "ØRJAN RAVNÃ…S", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01017170071", + "OrgNumber": "", + "Person": { + "SSN": "01017170071", + "Name": "PERSON TO PERSON DELEGATOR", + "FirstName": "PERSON TO PERSON", + "MiddleName": null, + "LastName": "DELEGATOR", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100001, + "PartyUuid": "00000000-0000-0000-0001-000000000001", + "UnitType": null, + "Name": "PERSON TO PERSON DELEGATOR", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01017270071", + "OrgNumber": "", + "Person": { + "SSN": "01017270071", + "Name": "PERSON TO PERSON RECIPIENT", + "FirstName": "PERSON TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100002, + "PartyUuid": "00000000-0000-0000-0001-000000000002", + "UnitType": null, + "Name": "PERSON TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01017370071", + "OrgNumber": "", + "Person": { + "SSN": "01017370071", + "Name": "PERSON TO ORG DELEGATOR", + "FirstName": "PERSON TO ORG", + "MiddleName": null, + "LastName": "DELEGATOR", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100003, + "PartyUuid": "00000000-0000-0000-0001-000000000003", + "UnitType": null, + "Name": "PERSON TO ORG DELEGATOR", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000004", + "Person": null, + "Organization": { + "OrgNumber": "901000004", + "Name": "PERSON TO ORG RECIPIENT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100004, + "PartyUuid": "00000000-0000-0000-0001-000000000004", + "UnitType": "AS", + "Name": "PERSON TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01017570071", + "OrgNumber": "", + "Person": { + "SSN": "01017570071", + "Name": "PERSON TO ORG DAGL", + "FirstName": "PERSON TO ORG", + "MiddleName": null, + "LastName": "DAGL", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100005, + "PartyUuid": "00000000-0000-0000-0001-000000000005", + "UnitType": null, + "Name": "PERSON TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000006", + "Person": null, + "Organization": { + "OrgNumber": "901000006", + "Name": "AUTHORIZEDPARTIES MAINUNIT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100006, + "PartyUuid": "00000000-0000-0000-0001-000000000006", + "UnitType": "AS", + "Name": "AUTHORIZEDPARTIES MAINUNIT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": [ + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000007", + "Person": null, + "Organization": { + "OrgNumber": "901000007", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "UnitType": "BEDR", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100007, + "PartyUuid": "00000000-0000-0000-0001-000000000007", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000008", + "Person": null, + "Organization": { + "OrgNumber": "901000008", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "UnitType": "BEDR", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100008, + "PartyUuid": "00000000-0000-0000-0001-000000000008", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + } + ] + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000007", + "Person": null, + "Organization": { + "OrgNumber": "901000007", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "UnitType": "BEDR", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100007, + "PartyUuid": "00000000-0000-0000-0001-000000000007", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT ONE", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": null, + "OrgNumber": "901000008", + "Person": null, + "Organization": { + "OrgNumber": "901000008", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "UnitType": "BEDR", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100008, + "PartyUuid": "00000000-0000-0000-0001-000000000008", + "UnitType": "BEDR", + "Name": "AUTHORIZEDPARTIES SUBUNIT TWO", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01017970071", + "OrgNumber": "", + "Person": { + "SSN": "01017970071", + "Name": "MAINUNIT AND SUBUNIT TO PERSON RECIPIENT", + "FirstName": "MAINUNIT AND SUBUNIT TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100009, + "PartyUuid": "00000000-0000-0000-0001-000000000009", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000010", + "Person": null, + "Organization": { + "OrgNumber": "901000010", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100010, + "PartyUuid": "00000000-0000-0000-0001-000000000010", + "UnitType": "AS", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01018170071", + "OrgNumber": "", + "Person": { + "SSN": "01018170071", + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "FirstName": "MAINUNIT AND SUBUNIT TO ORG", + "MiddleName": null, + "LastName": "DAGL", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100011, + "PartyUuid": "00000000-0000-0000-0001-000000000011", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyTypeName": 1, + "SSN": "01018270071", + "OrgNumber": "", + "Person": { + "SSN": "01018270071", + "Name": "SUBUNIT TO PERSON RECIPIENT", + "FirstName": "SUBUNIT TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100012, + "PartyUuid": "00000000-0000-0000-0001-000000000012", + "UnitType": null, + "Name": "SUBUNIT TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + { + "PartyId": 50004226, + "PartyUuid": "0268b99a-5817-4bbf-9b62-d90b16d527ea", + "PartyTypeName": 2, + "OrgNumber": "810419342", + "SSN": "", + "UnitType": "AS", + "Name": "KOLBJØRNSVIK OG ROAN", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "Person": null, + "Organization": { + "OrgNumber": "810419342", + "Name": "KOLBJØRNSVIK OG ROAN", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null, + "UnitStatus": "N" + }, + "ChildParties": null + }, + { + "PartyId": 50002115, + "PartyUuid": "ce4ba72b-d111-404f-95b5-313fb3847fa1", + "PartyTypeName": 1, + "OrgNumber": "", + "SSN": "01025181049", + "UnitType": null, + "Name": "MARGRETHE THORUD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "Person": { + "SSN": "01025181049", + "Name": "MARGRETHE THORUD", + "FirstName": "MARGRETHE", + "MiddleName": null, + "LastName": "THORUD", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "ChildParties": null + }, + { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "810419512", + "Person": null, + "Organization": { + "OrgNumber": "810419512", + "Name": "NØSS OG GRAVBERGET REGNSKAP", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50004230, + "PartyUuid": "B537C953-03C4-4822-B028-C15182ADC356", + "UnitType": "AS", + "Name": "NØSS OG GRAVBERGET REGNSKAP", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + } +] diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Policies/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Policies/policy.xml new file mode 100644 index 00000000..2e4ff72c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Policies/policy.xml @@ -0,0 +1,234 @@ + + + + + Eksempel pÃ¥ samleregel som spesifiserer at bÃ¥de REGNA og DAGL m/sikkerhetsnivÃ¥; 2, for ressursen; SKD/TaxReport fÃ¥r tilgang til operasjonene; Read, Write og Instantiate for Event; Tasks; FormFilling og Signing + + + + + regna + + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + + + skd + + + + taxreport + + + + formfilling + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + read + + + + + + write + + + + + + instantiate + + + + + + + + Eksempel pÃ¥ tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivÃ¥; 3, for ressursen; SKD/TaxReport fÃ¥r tilgang til operasjonen; Sign bÃ¥de for Event; SluttEvent_1b + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + sign + + + + + + + + Example rule that gives org nav and skd read right to the app inn all states + + + + + skd + + + + + + + + nav + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Example rule that gives org skd write right for app inn all states + + + + + skd + + + + + + + + skd + + + + taxreport + + + + + + + + write + + + + + + + + Rule that gives systems with a specific API scope access to do read + + + + + altinn:platform:skd:amelding + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toPerson.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toPerson.json new file mode 100644 index 00000000..f1c2dfa0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toPerson.json @@ -0,0 +1,17 @@ +[ + { + "delegationchangeid": 1337, + "resourceregistrydelegationchangeid": 0, + "delegationchangetype": 1, + "resourceid": "org1/app1", + "resourcetype": "AltinnAppId", + "offeredbypartyid": 50001337, + "coveredbypartyid": null, + "coveredbyuserid": 20001337, + "performedbyuserid": 20001336, + "performedbypartyid": null, + "blobstoragepolicypath": "org1/app1/50001337/u20001337/delegationpolicy.xml", + "blobstorageversionid": "CorrectLeaseId", + "created": "2022-11-29T10:19:45" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toSystemUser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toSystemUser.json new file mode 100644 index 00000000..16325ff7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/app_toSystemUser.json @@ -0,0 +1,23 @@ +[ + { + "delegationchangeid": 1337, + "resourceregistrydelegationchangeid": 0, + "delegationchangetype": 1, + "resourceid": "ttd/apps-test", + "resourcetype": "AltinnAppId", + "offeredbypartyid": 50005545, + "fromuuid": "00000000-0000-0000-0005-000000005545", + "fromuuidtype": 2, + "coveredbypartyid": null, + "coveredbyuserid": null, + "touuid": "a6355a68-86b8-4344-8a81-0248cb461468", + "touuidtype": 3, + "performedbyuserid": 20000490, + "performedbypartyid": null, + "performedbyuuid": null, + "performedbyuuidtype": 0, + "blobstoragepolicypath": "ttd/apps-test/50005545/SystemUsera6355a68-86b8-4344-8a81-0248cb461468/delegationpolicy.xml", + "blobstorageversionid": "2024-07-18T13:37:00.1337Z", + "created": "2024-07-18T13:37:00.1337Z" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toPerson.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toPerson.json new file mode 100644 index 00000000..3f9195be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toPerson.json @@ -0,0 +1,47 @@ +[ + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42210490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004221, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + }, + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42220490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + }, + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42225545, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50005545, + "coveredbyuserid": null, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toSystemUser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toSystemUser.json new file mode 100644 index 00000000..315e0d7d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Expected/resource_toSystemUser.json @@ -0,0 +1,23 @@ +[ + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 1337, + "delegationchangetype": 1, + "resourceid": "generic-access-resource", + "resourcetype": "genericaccessresource", + "offeredbypartyid": 50005545, + "fromuuid": "00000000-0000-0000-0005-000000005545", + "fromuuidtype": 2, + "coveredbypartyid": null, + "coveredbyuserid": null, + "touuid": "a6355a68-86b8-4344-8a81-0248cb461468", + "touuidtype": 3, + "performedbyuserid": 20000490, + "performedbypartyid": null, + "performedbyuuid": null, + "performedbyuuidtype": 0, + "blobstoragepolicypath": "resourceregistry/generic-access-resource/50005545/SystemUsera6355a68-86b8-4344-8a81-0248cb461468/delegationpolicy.xml", + "blobstorageversionid": "2024-07-18T13:37:00.1337Z", + "created": "2024-07-18T13:37:00.1337Z" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toPerson.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toPerson.json new file mode 100644 index 00000000..c50d46be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toPerson.json @@ -0,0 +1,20 @@ +{ + "subject": { + "id": "urn:altinn:userid", + "value": "20001337" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50001337" + }, + "resource": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toSystemUser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toSystemUser.json new file mode 100644 index 00000000..6d7db651 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/app_toSystemUser.json @@ -0,0 +1,20 @@ +{ + "subject": { + "id": "urn:altinn:systemuser:uuid", + "value": "a6355a68-86b8-4344-8a81-0248cb461468" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toPerson.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toPerson.json new file mode 100644 index 00000000..6ee0a76e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toPerson.json @@ -0,0 +1,16 @@ +{ + "subject": { + "id": "urn:altinn:userid", + "value": "20000490" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50004221" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toSystemUser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toSystemUser.json new file mode 100644 index 00000000..e56d1bad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/PolicyInformationPoint/Requests/resource_toSystemUser.json @@ -0,0 +1,16 @@ +{ + "subject": { + "id": "urn:altinn:systemuser:uuid", + "value": "a6355a68-86b8-4344-8a81-0248cb461468" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/app/app.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/app/app.json new file mode 100644 index 00000000..f1c2dfa0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/app/app.json @@ -0,0 +1,17 @@ +[ + { + "delegationchangeid": 1337, + "resourceregistrydelegationchangeid": 0, + "delegationchangetype": 1, + "resourceid": "org1/app1", + "resourcetype": "AltinnAppId", + "offeredbypartyid": 50001337, + "coveredbypartyid": null, + "coveredbyuserid": 20001337, + "performedbyuserid": 20001336, + "performedbypartyid": null, + "blobstoragepolicypath": "org1/app1/50001337/u20001337/delegationpolicy.xml", + "blobstorageversionid": "CorrectLeaseId", + "created": "2022-11-29T10:19:45" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/jks_audi_etron_gt/50004221/20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/jks_audi_etron_gt/50004221/20000490/delegationchange.json new file mode 100644 index 00000000..3f9195be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/ExpectedResponses/jks_audi_etron_gt/50004221/20000490/delegationchange.json @@ -0,0 +1,47 @@ +[ + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42210490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004221, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + }, + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42220490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + }, + { + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42225545, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50005545, + "coveredbyuserid": null, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/p50005545/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/p50005545/delegationchange.json new file mode 100644 index 00000000..fe9b4c44 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/p50005545/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42215545, + "delegationchangetype": 1, + "resourceid": "generic-access-resource", + "resourcetype": "GenericAccessResource", + "offeredbypartyid": 50004221, + "coveredbypartyid": 50005545, + "coveredbyuserid": null, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/generic-access-resource/50004221/p50005545/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/u20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/u20000490/delegationchange.json new file mode 100644 index 00000000..27ef44e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004221/u20000490/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42210490, + "delegationchangetype": 1, + "resourceid": "generic-access-resource", + "resourcetype": "GenericAccessResource", + "offeredbypartyid": 50004221, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/generic-access-resource/50004221/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/p50005545/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/p50005545/delegationchange.json new file mode 100644 index 00000000..c11d9a8f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/p50005545/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42225545, + "delegationchangetype": 1, + "resourceid": "generic-access-resource", + "resourcetype": "GenericAccessResource", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50005545, + "coveredbyuserid": null, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/generic-access-resource/50004222/p50005545/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/u20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/u20000490/delegationchange.json new file mode 100644 index 00000000..21873a0f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/generic-access-resource/50004222/u20000490/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42220490, + "delegationchangetype": 1, + "resourceid": "generic-access-resource", + "resourcetype": "GenericAccessResource", + "offeredbypartyid": 50004222, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/generic-access-resource/50004222/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/20000490/delegationchange.json new file mode 100644 index 00000000..a56b9873 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/20000490/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42210490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004221, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/u20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/u20000490/delegationchange.json new file mode 100644 index 00000000..a56b9873 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004221/u20000490/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42210490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004221, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/p50005545/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/p50005545/delegationchange.json new file mode 100644 index 00000000..2b09424b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/p50005545/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42225545, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": 50005545, + "coveredbyuserid": null, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/u20000490/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/u20000490/delegationchange.json new file mode 100644 index 00000000..66cf5675 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50004222/u20000490/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 42220490, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50004222, + "coveredbypartyid": null, + "coveredbyuserid": 20000490, + "performedbyuserid": 20000095, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/p50004222/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/p50004222/delegationchange.json new file mode 100644 index 00000000..35785efc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/p50004222/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 55454222, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50005545, + "coveredbypartyid": 50004222, + "coveredbyuserid": null, + "performedbyuserid": 20000490, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/u20000095/delegationchange.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/u20000095/delegationchange.json new file mode 100644 index 00000000..b4b40d5d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryDelegationChanges/jks_audi_etron_gt/50005545/u20000095/delegationchange.json @@ -0,0 +1,15 @@ +{ + "delegationchangeid": 0, + "resourceregistrydelegationchangeid": 55450095, + "delegationchangetype": 1, + "resourceid": "jks_audi_etron_gt", + "resourcetype": "MaskinportenSchema", + "offeredbypartyid": 50005545, + "coveredbypartyid": null, + "coveredbyuserid": 20000095, + "performedbyuserid": 20000490, + "performedbypartyid": null, + "blobstoragepolicypath": "resourceregistry/jks_audi_etron_gt/50005545/u20000095/delegationpolicy.xml", + "blobstorageversionid": "2022-11-29T09:19:52.1743413Z", + "created": "2022-11-29T10:19:45.336206+01" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/digdirs_company_car/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/digdirs_company_car/resource.json new file mode 100644 index 00000000..fe541433 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/digdirs_company_car/resource.json @@ -0,0 +1,53 @@ +{ + "identifier": "digdirs_company_car", + "title": { + "en": "DigDir's company car'", + "nb-no": "DigDir's company car", + "nn-no": "DigDir's company car" + }, + "description": { + "en": "Only the manager (DAGL) has access to drive the company car", + "nb-no": "Bare daglig leder (DAGL) har tilgang til � kj�re firmabilen", + "nn-no": "Berre dagleg leiar (DAGL) har h�ve til � kj�yre firmabilen" + }, + "rightDescription": { + "en": "Gives an employee permission to borrow the company car", + "nb-no": "Gir en ansatt lov til � l�ne firmabilen", + "nn-no": "Gjev ein tilsett l�yve til � ta ei r�nerunde ned i vik" + }, + "homepage": "https://www.jksfirmabiler.no/", + "status": "Active", + "validFrom": "2022-09-20T06:46:07.598Z", + "validTo": "2099-12-24T23:59:59", + "isPartOf": "jk_ressurser", + "isPublicService": true, + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "urn:altinn:resource:digdirs_company_car", + "referenceType": "Uri" + } + ], + "isComplete": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR" + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "sector": [ + "offentlig" + ], + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/generic-access-resource/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/generic-access-resource/resource.json new file mode 100644 index 00000000..c3407d1a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/generic-access-resource/resource.json @@ -0,0 +1,45 @@ +{ + "identifier": "generic-access-resource", + "title": { + "en": "Generic Access Resource", + "nb": "Generisk Tilgangsressurs", + "nn": "Generisk Tilgongsressurs" + }, + "description": { + "en": "Very nice generic access resource", + "nb": "Veldig fin generisk tilgangsressurs", + "nn": "Steikje fine generisk tilgongsressurs" + }, + "rightDescription": { + "en": "You'll give access to this nice generic access resource", + "nb": "Du gir tilgang til denne fine generiske tilgangsressursen", + "nn": "Du gir tilgong til dinne steikje fine generiske tilgongsressursen" + }, + "homepage": "https://www.altinn.no", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/jks_audi_etron_gt/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/jks_audi_etron_gt/resource.json new file mode 100644 index 00000000..e512c27b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/jks_audi_etron_gt/resource.json @@ -0,0 +1,53 @@ +{ + "identifier": "jks_audi_etron_gt", + "title": { + "en": "JK's Audi E-Tron GT", + "nb-no": "JK's Audi E-Tron GT", + "nn-no": "JK's Audi E-Tron GT" + }, + "description": { + "en": "Very nice car", + "nb-no": "Veldig fin bil", + "nn-no": "Steikje fine bil" + }, + "rightDescription": { + "en": "Permission to borrow the car", + "nb-no": "Gir mottaker lov til � l�ne bilen", + "nn-no": "L�yve til � ta ei r�nerunde ned i vik" + }, + "homepage": "https://www.jksaudi.no/", + "status": "Active", + "validFrom": "2022-09-20T06:46:07.598Z", + "validTo": "2099-12-24T23:59:59", + "isPartOf": "jk_ressurser", + "isPublicService": true, + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "urn:altinn:resource:jks_audi_etron_gt", + "referenceType": "Uri" + } + ], + "isComplete": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR" + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "sector": [ + "privat" + ], + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/mp_validation_problem_details/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/mp_validation_problem_details/resource.json new file mode 100644 index 00000000..be9b0ee2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/mp_validation_problem_details/resource.json @@ -0,0 +1,44 @@ +{ + "title": { + "en": "MaskinportenSchema for ValidationProblemDetails responses", + "nb-no": "MaskinportenSchema for ValidationProblemDetails responses", + "nn-no": "MaskinportenSchema for ValidationProblemDetails responses" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "mp_validation_problem_details", + "isComplete": true, + "description": { + "en": "A MaskinportenSchema to test ValidationProblemDetails responses", + "nb-no": "A MaskinportenSchema to test ValidationProblemDetails responses", + "nn-no": "A MaskinportenSchema to test ValidationProblemDetails responses" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Acces to this MaskinportenSchema", + "nb-no": "Acces to this MaskinportenSchema", + "nn-no": "Acces to this MaskinportenSchema" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/nav_aa_distribution/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/nav_aa_distribution/resource.json new file mode 100644 index 00000000..3355e791 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/nav_aa_distribution/resource.json @@ -0,0 +1,62 @@ +{ + "title": { + "en": "NAV aa distribution", + "nb-no": "NAV aa distribution", + "nn-no": "NAV aa distribution" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "nav_aa_distribution", + "isComplete": true, + "description": { + "en": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger", + "nb-no": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger", + "nn-no": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:nav_aa", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:nav_aa", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "NAV", + "organization": "991825827", + "name": { + "en": "The Norwegian Labour and Welfare Administration", + "nb-no": "Arbeids og velferdsetaten", + "nn-no": "Arbeids og velferdsetaten" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/non_delegable_maskinportenschema/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/non_delegable_maskinportenschema/resource.json new file mode 100644 index 00000000..2a645158 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/non_delegable_maskinportenschema/resource.json @@ -0,0 +1,50 @@ +{ + "title": { + "en": "MaskinportenSchema that cannot be delegated", + "nb-no": "MaskinportenSchema that cannot be delegated", + "nn-no": "MaskinportenSchema that cannot be delegated" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "non_delegable_maskinportenschema", + "isComplete": true, + "description": { + "en": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated", + "nb-no": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated", + "nn-no": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Not delegable", + "nb-no": "Not delegable", + "nn-no": "Not delegable" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + }, + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "non_delegable_maskinportenschema" + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource1/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource1/resource.json new file mode 100644 index 00000000..313b5246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource1/resource.json @@ -0,0 +1,62 @@ +{ + "title": { + "en": "resource 1", + "nb-no": "resource 1", + "nn-no": "resource 1" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "resource1", + "isComplete": true, + "description": { + "en": "resource 1", + "nb-no": "resource 1", + "nn-no": "resource 1" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:skd_1", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:skd_1", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076", + "name": { + "en": "The Norwegian Tax Administration", + "nb-no": "Skatteetaten", + "nn-no": "Skatteetaten" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource2/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource2/resource.json new file mode 100644 index 00000000..313b5246 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/resource2/resource.json @@ -0,0 +1,62 @@ +{ + "title": { + "en": "resource 1", + "nb-no": "resource 1", + "nn-no": "resource 1" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "resource1", + "isComplete": true, + "description": { + "en": "resource 1", + "nb-no": "resource 1", + "nn-no": "resource 1" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:skd_1", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:skd_1", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076", + "name": { + "en": "The Norwegian Tax Administration", + "nb-no": "Skatteetaten", + "nn-no": "Skatteetaten" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/skd_1/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/skd_1/resource.json new file mode 100644 index 00000000..2ffbfd7d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/skd_1/resource.json @@ -0,0 +1,62 @@ +{ + "title": { + "en": "SKD 1", + "nb-no": "SKD 1", + "nn-no": "SKD 1" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "skd_1", + "isComplete": true, + "description": { + "en": "Tax service", + "nb-no": "Skatt tjeneste", + "nn-no": "Skatt tjeneste" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:skd_1", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:skd_1", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076", + "name": { + "en": "The Norwegian Tax Administration", + "nb-no": "Skatteetaten", + "nn-no": "Skatteetaten" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/system_resource/resource.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/system_resource/resource.json new file mode 100644 index 00000000..eb3c2caf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/ResourceRegistryResources/system_resource/resource.json @@ -0,0 +1,44 @@ +{ + "title": { + "en": "A System Resource", + "nb-no": "A System Resource", + "nn-no": "A System Resource" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "system_resource", + "isComplete": true, + "description": { + "en": "Random System Resource", + "nb-no": "Random System Resource", + "nn-no": "Random System Resource" + }, + "resourceType": "SystemResource", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Acces to this random system resource", + "nb-no": "Acces to this random system resource", + "nn-no": "Acces to this random system resource" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resourceList.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resourceList.json new file mode 100644 index 00000000..4fb61627 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resourceList.json @@ -0,0 +1,1663 @@ +[ + { + "identifier": "altinn_maskinporten_scope_delegation", + "title": { + "en": "Maskinporten Scope Delegation", + "nb": "Maskinporten Scope Delegation", + "nn": "Maskinporten Scope Delegation" + }, + "description": { + "en": "Maskinporten Scope Delegation", + "nb": "Maskinporten Scope Delegation", + "nn": "Maskinporten Scope Delegation" + }, + "rightDescription": { + "en": "Access to Maskinporten Scope Delegation", + "nb": "Access to Maskinporten Scope Delegation", + "nn": "Access to Maskinporten Scope Delegation" + }, + "homepage": "https://www.digdir.no/", + "status": "Active", + "isPartOf": "Altinn", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb": "DIGITALISERINGSDIREKTORATET", + "nn": "DIGITALISERINGSDIREKTORATET" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "Systemresource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "altinn_maskinporten_scope_delegation" + } + ] + }, + { + "identifier": "altinn_access_management", + "title": { + "en": "Access Management", + "nb": "Tilgangsstyring", + "nn": "Tilgongsstyring" + }, + "description": { + "en": "System resource for authorization of users which should have access to access management user interfaces and access information in Altinn.", + "nb": "System ressurs for autorisasjon av brukere som skal ha tilgang til brukergrensesnitt og informasjon knytt til tilgangsstyring i Altinn.", + "nn": "System ressurs for autorisasjon av brukarar som skal ha tilgong til brukargrensesnitt og informasjon knytta til tilgongsstyring i Altinn." + }, + "rightDescription": { + "en": "User with who receives this resource will be able to access all access management user interfaces and access information on behalf of the delegating party. The user will also be able to perform delegation, of roles or rights the user themselves possess on behalf of the delegating party.", + "nb": "Bruker som mottar denne ressursen vil få tilgang til alle brukergrensesnitt for tilgangsstyring og behandle tilgangsinformasjon på vegne av delegerende part. Brukeren vil også kunne utføre delegering av roller og rettigheter, som brukeren selv har mottatt fra delegerende part.", + "nn": "Brukar som mottek ressursen vil få tilgong til alle brukargrensesnitt for tilgongsstyring og behandle tilgongsinformasjon på vegne av delegerande part. Brukaren vil også kunne utføre delegering av roller og rettigheiter, som brukaren sjølv har motteke fra delegerande part." + }, + "homepage": "https://altinn.no", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": false, + "visible": false, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb": "DIGITALISERINGSDIREKTORATET", + "nn": "DIGITALISERINGSDIREKTORATET" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "Systemresource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "altinn_access_management" + } + ] + }, + { + "identifier": "jks_audi_etron_gt", + "title": { + "en": "JK's Audi e-tron GT", + "nb": "JK's Audi e-tron GT", + "nn": "JK's Audi e-tron GT" + }, + "description": { + "en": "Very nice car", + "nb": "Veldig fin bil", + "nn": "Steikje fine bil" + }, + "rightDescription": { + "en": "Permission to borrow the car", + "nb": "Gir mottaker lov til å låne bilen", + "nn": "Løyve til å ta ei rånerunde ned i vik" + }, + "homepage": "https://www.jksaudi.no/", + "status": "Active", + "isPartOf": "jk_ressurser", + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "altinn:resourceregistry/jksaudietrongt.drive", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "Altinn3", + "reference": "altinn:resourceregistry/jksaudietrongt.park", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "Altinn3", + "reference": "altinn:resourceregistry/jksaudietrongt.race", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR" + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_etron_gt" + } + ] + }, + { + "identifier": "jks_audi_a3", + "title": { + "en": "JK's Audi A3", + "nb": "JK's Audi A3", + "nn": "JK's Audi A3" + }, + "description": { + "en": "Very nice car", + "nb": "Veldig fin bil", + "nn": "Steikje fine bil" + }, + "rightDescription": { + "en": "Permission to borrow the car", + "nb": "Gir mottaker lov til å låne bilen", + "nn": "Løyve til å ta ei rånerunde ned i vik" + }, + "homepage": "https://www.jksaudi.no/", + "status": "Active", + "isPartOf": "jk_ressurser", + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "urn:altinn:resourceregistry:jks_audi_a3", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb": "DIGITALISERINGSDIREKTORATET", + "nn": "DIGITALISERINGSDIREKTORATET" + } + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "jks_audi_a3" + } + ] + }, + { + "identifier": "jks_undelegable", + "title": { + "en": "JK's Undelegable Resource", + "nb": "JK's Undelegable Resource", + "nn": "JK's Undelegable Resource" + }, + "description": { + "en": "Nope", + "nb": "Nope", + "nn": "Nope" + }, + "rightDescription": { + "en": "Nope", + "nb": "Nope", + "nn": "Nope" + }, + "homepage": "https://www.nope.no/", + "status": "Active", + "isPartOf": "jk_ressurser", + "isPublicService": true, + "resourceReferences": [], + "delegable": false, + "visible": false, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb": "DIGITALISERINGSDIREKTORATET", + "nn": "DIGITALISERINGSDIREKTORATET" + } + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "jks_undelegable" + } + ] + }, + { + "identifier": "ttd-am-k6", + "title": { + "en": "Maskinporten Schema - AM - K6", + "nb": "Maskinporten Schema - AM - K6", + "nn": "Maskinporten Schema - AM - K6" + }, + "description": { + "en": "Maskinporten Schema test resource for automated tests", + "nb": "Maskinporten Schema test resource for automatiserte tester", + "nn": "Maskinporten Schema test resource for automatiserte testar" + }, + "rightDescription": { + "en": "Access to the test scopes", + "nb": "Tilgang til test scopene", + "nn": "Tilgong til test omfang" + }, + "homepage": "https://www.digdir.no/", + "status": "Active", + "isPartOf": "Altinn", + "resourceReferences": [ + { + "referenceSource": "ExternalPlatform", + "reference": "test:am/k6.read", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "ExternalPlatform", + "reference": "test:am/k6.write", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "TTD", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + }, + { + "identifier": "app_org1_app1", + "title": { + "nb": "test applikasjon 1", + "nn": "test applikasjon 1", + "en": "test application 1" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "org1/app1", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "org1", + "name": { + "en": "Organization 1", + "nb": "Organisasjon 1", + "nn": "Organisasjon 1" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "mainLanguage": "nb", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "org1" + }, + { + "id": "urn:altinn:app", + "value": "app1" + } + ] + }, + { + "identifier": "se_1337_1338", + "title": { + "en": "Altinn 2 delegation check", + "nb": "Altinn 2 delegation check", + "nn": "Altinn 2 delegation check" + }, + "description": { + "en": "Altinn 2 delegation check", + "nb": "Altinn 2 delegation check", + "nn": "Altinn 2 delegation check" + }, + "rightDescription": { + "en": "Altinn 2 delegation check", + "nb": "Altinn 2 delegation check", + "nn": "Altinn 2 delegation check" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "reference": "1337", + "referenceType": "ServiceCode" + }, + { + "reference": "1338", + "referenceType": "ServiceEditionCode" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ACC", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "Altinn2Service", + "mainLanguage": "nb", + "authorizationReference": [ + { + "id": "urn:altinn:servicecode", + "value": "1337" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "1338" + } + ] + }, + { + "identifier": "generic-access-resource", + "title": { + "en": "Generic Access Resource", + "nb": "Generisk Tilgangsressurs", + "nn": "Generisk Tilgongsressurs" + }, + "description": { + "en": "Very nice generic access resource", + "nb": "Veldig fin generisk tilgangsressurs", + "nn": "Steikje fine generisk tilgongsressurs" + }, + "rightDescription": { + "en": "You'll give access to this nice generic access resource", + "nb": "Du gir tilgang til denne fine generiske tilgangsressursen", + "nn": "Du gir tilgong til dinne steikje fine generiske tilgongsressursen" + }, + "homepage": "https://www.altinn.no", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] + }, + { + "identifier": "scope-access-schema", + "title": { + "en": "Generic Access Maskinportenschema", + "nb": "Generisk Maskinportenschema", + "nn": "Generisk Maskinportenschema" + }, + "description": { + "en": "Very nice generic maskinportenschema resource", + "nb": "Veldig fin generisk maskinportenschema-resurs", + "nn": "Steikje fine generisk maskinportenschema-resurs" + }, + "rightDescription": { + "en": "You'll give access to the scopes of this maskinportenschema", + "nb": "Du gir tilgang til scopesene til denne maskinportenschemet", + "nn": "Du gir tilgong til scopesene til denne maskinportenschemet" + }, + "homepage": "https://www.altinn.no", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "referenceSource": "Altinn2", + "reference": "3fc59d3e-1c45-4b37-9c2f-d804afb55f7s", + "referenceType": "DelegationSchemeId" + }, + { + "referenceSource": "Altinn2", + "reference": "great:things", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "Altinn2", + "reference": "AppId:49", + "referenceType": "ServiceCode" + }, + { + "referenceSource": "Altinn2", + "reference": "1", + "referenceType": "ServiceEditionCode" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "scope-access-schema" + } + ] + }, + { + "identifier": "se_2802_2203", + "title": { + "nb": "ACC Security level 2 MAG", + "en": "ACC Security level 2 MAG", + "nn": "ACC Security level 2 MAG" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn2", + "reference": "2802", + "referenceType": "ServiceCode" + }, + { + "referenceSource": "Altinn2", + "reference": "2203", + "referenceType": "ServiceEditionCode" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "orgcode": "acn" + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "Altinn2Service", + "authorizationReference": [ + { + "id": "urn:altinn:servicecode", + "value": "2802" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "2203" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-person-to-person", + "title": { + "en": "AM DevTest - Person to Person delegation", + "nb": "AM DevTest - Person til Person delegering", + "nn": "AM DevTest - Person til Person delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-person-to-person", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-person-to-person" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-person-to-org", + "title": { + "en": "AM DevTest - Person to Organization delegation", + "nb": "AM DevTest - Person til Organization delegering", + "nn": "AM DevTest - Person til Organization delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-person-to-org", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-person-to-org" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-main-to-person", + "title": { + "en": "AM DevTest - Main Unit to Person delegation", + "nb": "AM DevTest - Hovedenhet til Person delegering", + "nn": "AM DevTest - Hovudeining til Person delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-main-to-person", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-main-to-person" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-sub-to-person", + "title": { + "en": "AM DevTest - Subunit to Person delegation", + "nb": "AM DevTest - Underenhet til Person delegering", + "nn": "AM DevTest - Undereining til Person delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-sub-to-person", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-sub-to-person" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-sub-to-org", + "title": { + "en": "AM DevTest - Subunit to Organization delegation", + "nb": "AM DevTest - Underenhet til Organisasjon delegering", + "nn": "AM DevTest - Undereining til Organisasjon delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-sub-to-org", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-sub-to-org" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-main-to-org", + "title": { + "en": "AM DevTest - Main Unit to Organization delegation", + "nb": "AM DevTest - Hovedenhet til Organisasjon delegering", + "nn": "AM DevTest - Hovudeining til Organisasjon delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-main-to-org", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-main-to-org" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-main-to-ecuser", + "title": { + "en": "AM DevTest - Main Unit to Enterpriseuser delegation", + "nb": "AM DevTest - Hovedenhet til Virksomhetsbruker delegering", + "nn": "AM DevTest - Hovudeining til Verksemdbrukar delegering" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-main-to-ecuser", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-main-to-ecuser" + } + ] + }, + { + "identifier": "devtest_gar_authparties-main-to-person", + "title": { + "en": "AuthorizedParties: Mainunit to Person Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Mainunit to Person Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Mainunit to Person Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Mainunit to Person is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Mainunit to Person er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Person er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Mainunit to Person, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Mainunit to Person, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Mainunit to Person, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-main-to-person" + } + ] + }, + { + "identifier": "devtest_gar_authparties-sub-to-person", + "title": { + "en": "AuthorizedParties: Subunit to Person Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Subunit to Person Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Subunit to Person Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Subunit to Person is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Subunit to Person er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Subunit to Person er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Subunit to Person, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Subunit to Person, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Subunit to Person, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-sub-to-person" + } + ] + }, + { + "identifier": "devtest_gar_authparties-main-to-org", + "title": { + "en": "AuthorizedParties: Mainunit to Organization Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Mainunit to Organization Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Mainunit to Organization Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Mainunit to Organization is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Mainunit to Organization er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Organization er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Mainunit to Organization, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Mainunit to Organization, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Mainunit to Organization, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-main-to-org" + } + ] + }, + { + "identifier": "devtest_gar_authparties-sub-to-org", + "title": { + "en": "AuthorizedParties: Subunit to Organization Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Subunit to Organization Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Subunit to Organization Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Subunit to Organization is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Subunit to Organization er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Subunit to Organization er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Subunit to Organization, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Subunit to Organization, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Subunit to Organization, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-sub-to-org" + } + ] + }, + { + "identifier": "devtest_mps_authparties-main-to-person", + "title": { + "en": "AuthorizedParties: Mainunit to Person Maskinporten Schema for development testing", + "nb": "AuthorizedParties: Mainunit to Person Maskinporten Schema for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Person Maskinporten Schema for utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Mainunit to Person Maskinporten Schema test resource for development testing", + "nb": "AuthorizedParties: Mainunit to Person Maskinporten Schema test resource for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Person Maskinporten Schema test resource for utviklingstestar" + }, + "rightDescription": { + "en": "Access to the referenced maskinporten scopes", + "nb": "Tilgang til de refererte maskinporten scopene", + "nn": "Tilgong til dei refererte maskinporten scopa" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-main-to-person.read", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-main-to-person.write", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_mps_authparties-main-to-person" + } + ] + }, + { + "identifier": "devtest_mps_authparties-main-to-org", + "title": { + "en": "AuthorizedParties: Mainunit to Organization Maskinporten Schema for development testing", + "nb": "AuthorizedParties: Mainunit to Organization Maskinporten Schema for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Organization Maskinporten Schema for utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Mainunit to Organization Maskinporten Schema test resource for development testing", + "nb": "AuthorizedParties: Mainunit to Organization Maskinporten Schema test resource for utviklingstester", + "nn": "AuthorizedParties: Mainunit to Organization Maskinporten Schema test resource for utviklingstestar" + }, + "rightDescription": { + "en": "Access to the referenced maskinporten scopes", + "nb": "Tilgang til de refererte maskinporten scopene", + "nn": "Tilgong til dei refererte maskinporten scopa" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-main-to-org.read", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-main-to-org.write", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_mps_authparties-main-to-org" + } + ] + }, + { + "identifier": "devtest_mps_authparties-sub-to-person", + "title": { + "en": "AuthorizedParties: Subunit to Person Maskinporten Schema for development testing", + "nb": "AuthorizedParties: Subunit to Person Maskinporten Schema for utviklingstester", + "nn": "AuthorizedParties: Subunit to Person Maskinporten Schema for utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Subunit to Person Maskinporten Schema test resource for development testing", + "nb": "AuthorizedParties: Subunit to Person Maskinporten Schema test resource for utviklingstester", + "nn": "AuthorizedParties: Subunit to Person Maskinporten Schema test resource for utviklingstestar" + }, + "rightDescription": { + "en": "Access to the referenced maskinporten scopes", + "nb": "Tilgang til de refererte maskinporten scopene", + "nn": "Tilgong til dei refererte maskinporten scopa" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-sub-to-person.read", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-sub-to-person.write", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_mps_authparties-sub-to-person" + } + ] + }, + { + "identifier": "devtest_mps_authparties-sub-to-org", + "title": { + "en": "AuthorizedParties: Subunit to Organization Maskinporten Schema for development testing", + "nb": "AuthorizedParties: Subunit to Organization Maskinporten Schema for utviklingstester", + "nn": "AuthorizedParties: Subunit to Organization Maskinporten Schema for utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Subunit to Organization Maskinporten Schema test resource for development testing", + "nb": "AuthorizedParties: Subunit to Organization Maskinporten Schema test resource for utviklingstester", + "nn": "AuthorizedParties: Subunit to Organization Maskinporten Schema test resource for utviklingstestar" + }, + "rightDescription": { + "en": "Access to the referenced maskinporten scopes", + "nb": "Tilgang til de refererte maskinporten scopene", + "nn": "Tilgong til dei refererte maskinporten scopa" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [ + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-sub-to-org.read", + "referenceType": "MaskinportenScope" + }, + { + "referenceSource": "ExternalPlatform", + "reference": "ttd:mps/authparties-sub-to-org.write", + "referenceType": "MaskinportenScope" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_mps_authparties-sub-to-org" + } + ] + }, + { + "identifier": "devtest_gar_authparties-person-to-person", + "title": { + "en": "AuthorizedParties: Person to Person Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Person to Person Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Person to Person Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Person to Person is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Person to Person er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Person to Person er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Person to Person, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Person to Person, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Person to Person, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-person-to-person" + } + ] + }, + { + "identifier": "devtest_gar_authparties-person-to-org", + "title": { + "en": "AuthorizedParties: Person to Organization Generic Access Resource for Development Tests", + "nb": "AuthorizedParties: Person to Organization Generisk Tilgangsressurs for Utviklingstester", + "nn": "AuthorizedParties: Person to Organization Generisk Tilgongsressurs for Utviklingstestar" + }, + "description": { + "en": "AuthorizedParties: Person to Organization is a very nice generic access resource for development tests", + "nb": "AuthorizedParties: Person to Organization er en veldig fin generisk tilgangsressurs for utviklingstester", + "nn": "AuthorizedParties: Person to Organization er ein steikje fine generisk tilgongsressurs for utviklingstestar" + }, + "rightDescription": { + "en": "You'll give access to AuthorizedParties: Person to Organization, a generic access resource for development tests", + "nb": "Du gir tilgang til AuthorizedParties: Person to Organization, en generisk tilgangsressurs for utviklingstester", + "nn": "Du gir tilgong til AuthorizedParties: Person to Organization, ein generisk tilgongsressurs for utviklingstestar" + }, + "homepage": "", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": true, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-person-to-org" + } + ] + }, + { + "identifier": "app_ttd_apps-test", + "title": { + "en": "test application (simple)", + "nb": "test applikasjon (enkel)", + "nn": "test applikasjon (enkel)" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/apps-test", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "", + "orgcode": "ttd", + "name": { + "en": "Test Ministry", + "nb": "Testdepartementet", + "nn": "Testdepartementet" + } + }, + "limitedByRRR": false, + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] + }, + { + "identifier": "app_ttd_am-devtest-instancedelegation", + "title": { + "en": "AM DevTest - Instance delegation test app", + "nb": "AM DevTest - Instansdelegering test app", + "nn": "AM DevTest - Instansdelegering test app" + }, + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "ttd/am-devtest-instancedelegation", + "referenceType": "ApplicationId" + } + ], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "name": { + "en": "Test Ministry", + "nn": "Testdepartementet", + "nb": "Testdepartementet" + }, + "organization": "991825827", + "orgcode": "ttd" + }, + "accessListMode": "Disabled", + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "AltinnApp", + "authorizationReference": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "am-devtest-instancedelegation" + } + ] + }, + { + "title": { + "en": "MaskinportenSchema for ValidationProblemDetails responses", + "nb-no": "MaskinportenSchema for ValidationProblemDetails responses", + "nn-no": "MaskinportenSchema for ValidationProblemDetails responses" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "mp_validation_problem_details", + "isComplete": true, + "description": { + "en": "A MaskinportenSchema to test ValidationProblemDetails responses", + "nb-no": "A MaskinportenSchema to test ValidationProblemDetails responses", + "nn-no": "A MaskinportenSchema to test ValidationProblemDetails responses" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Acces to this MaskinportenSchema", + "nb-no": "Acces to this MaskinportenSchema", + "nn-no": "Acces to this MaskinportenSchema" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + }, + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "mp_validation_problem_details" + } + ] + }, + { + "identifier": "digdirs_company_car", + "title": { + "en": "DigDir's company car'", + "nb-no": "DigDir's company car", + "nn-no": "DigDir's company car" + }, + "description": { + "en": "Only the manager (DAGL) has access to drive the company car", + "nb-no": "Bare daglig leder (DAGL) har tilgang til � kj�re firmabilen", + "nn-no": "Berre dagleg leiar (DAGL) har h�ve til � kj�yre firmabilen" + }, + "rightDescription": { + "en": "Gives an employee permission to borrow the company car", + "nb-no": "Gir en ansatt lov til � l�ne firmabilen", + "nn-no": "Gjev ein tilsett l�yve til � ta ei r�nerunde ned i vik" + }, + "homepage": "https://www.jksfirmabiler.no/", + "status": "Active", + "validFrom": "2022-09-20T06:46:07.598Z", + "validTo": "2099-12-24T23:59:59", + "isPartOf": "jk_ressurser", + "isPublicService": true, + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "resourceReferences": [ + { + "referenceSource": "Altinn3", + "reference": "urn:altinn:resource:digdirs_company_car", + "referenceType": "Uri" + } + ], + "isComplete": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "DIGDIR" + }, + "keywords": [ + { + "word": "bil", + "language": "nb" + } + ], + "sector": [ + "offentlig" + ], + "resourceType": "MaskinportenSchema", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "digdirs_company_car" + } + ] + }, + { + "title": { + "en": "A System Resource", + "nb-no": "A System Resource", + "nn-no": "A System Resource" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "system_resource", + "isComplete": true, + "description": { + "en": "Random System Resource", + "nb-no": "Random System Resource", + "nn-no": "Random System Resource" + }, + "resourceType": "SystemResource", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Acces to this random system resource", + "nb-no": "Acces to this random system resource", + "nn-no": "Acces to this random system resource" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + }, + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "system_resource" + } + ] + }, + { + "title": { + "en": "MaskinportenSchema that cannot be delegated", + "nb-no": "MaskinportenSchema that cannot be delegated", + "nn-no": "MaskinportenSchema that cannot be delegated" + }, + "sector": [ + "private", + "public" + ], + "status": "Active", + "validTo": "2099-12-24T23:59:59", + "homepage": "https://www.digdir.no/", + "isPartOf": "Altinn", + "keywords": [ + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "non_delegable_maskinportenschema", + "isComplete": true, + "description": { + "en": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated", + "nb-no": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated", + "nn-no": "A MaskinportenSchema with a RoleRequirement (NOPE) to a role which does not exist and so cannot be delegated" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Not delegable", + "nb-no": "Not delegable", + "nn-no": "Not delegable" + }, + "resourceReferences": [ + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827", + "name": { + "en": "DIGITALISERINGSDIREKTORATET", + "nb-no": "DIGITALISERINGSDIREKTORATET", + "nn-no": "DIGITALISERINGSDIREKTORATET" + } + }, + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "non_delegable_maskinportenschema" + } + ] + }, + { + "identifier": "generic-accesslist-resource", + "title": { + "en": "Generic Accesslist Resource ", + "nb": "Generisk Tilgangslisteressurs", + "nn": "Generisk Tilgongslisteressurs" + }, + "description": { + "en": "Very nice generic accesslist resource", + "nb": "Veldig fin generisk tilgangslisteressurs", + "nn": "Steikje fine generisk tilgongslisteressurs" + }, + "rightDescription": { + "en": "You'll give access to this nice generic accesslist resource", + "nb": "Du gir tilgang til denne fine generiske tilgangslisteressursen", + "nn": "Du gir tilgong til dinne steikje fine generiske tilgongslisteressursen" + }, + "homepage": "https://www.altinn.no", + "status": "Active", + "contactPoints": [], + "isPartOf": "", + "resourceReferences": [], + "delegable": true, + "visible": true, + "hasCompetentAuthority": { + "organization": "991825827", + "orgcode": "ttd", + "name": { + "en": "Test departement", + "nb": "Testdepartement", + "nn": "Testdepartement" + } + }, + "keywords": [], + "accessListMode": "Enabled", + "selfIdentifiedUserEnabled": false, + "enterpriseUserEnabled": false, + "resourceType": "GenericAccessResource", + "authorizationReference": [ + { + "id": "urn:altinn:resource", + "value": "generic-accesslist-resource" + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resources.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resources.json new file mode 100644 index 00000000..90ca787c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/resources.json @@ -0,0 +1,3719 @@ +[ + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-04T18:04:27.27", + "identifier": "appid-119", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "8f08210a-d792-48f5-9e27-0f029e41111e", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:119", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-06T09:36:15.443", + "identifier": "appid-122", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "da7650a5-d893-404a-9bfe-28d0904fe896", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:122", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-06T09:41:15.817", + "identifier": "appid-123", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "3cb27d7b-9e2c-475c-ba91-e1fc359bc717", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:123", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-04T19:07:46.143", + "identifier": "appid-120", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "a6574ca8-5836-46b0-91f0-8ebb0ff214cf", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:120", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-25T15:17:18.487", + "identifier": "appid-124", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "fb1bc117-333d-4dea-9400-6bd3e1ce07dd", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:124", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-13T11:10:52.203", + "identifier": "appid-126", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "4f9b0f81-74a6-4b76-8ce5-0e1fe153c872", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:126", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-19T11:13:36.8", + "identifier": "appid-127", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "38da61a2-4cd8-4dac-9d6b-8205f91661c4", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:127", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-03-25T15:20:40.17", + "identifier": "appid-125", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "c8e7b227-3d62-4682-81a2-f2865f0eb91f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:125", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-19T11:18:52.84", + "identifier": "appid-128", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "74f5dcb3-eee0-4a3b-9499-93fc2148a513", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:128", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-20T11:49:19.26", + "identifier": "appid-129", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "d0fc231c-aaa3-4e6a-bece-4e283e6e2f6f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:129", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-20T12:32:41.78", + "identifier": "appid-130", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "3fc8a856-d5b1-4861-ace0-6b3fd5ffd916", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:130", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-28T23:38:06.337", + "identifier": "appid-132", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "923bdaaf-0a5e-4b63-908b-4a5ecf75e37b", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:132", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-28T23:39:09.01", + "identifier": "appid-133", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "f7670967-0428-4b90-86a2-2ac637d0ec2a", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:133", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-28T23:40:31.413", + "identifier": "appid-134", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "d812fd77-7a43-4332-a782-375b37aff1eb", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:134", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-05-29T09:50:19.333", + "identifier": "appid-136", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "911f9e93-1541-429d-a8c6-a06f9a52d827", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:136", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "MAT", + "organization": "985399077" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-06-05T14:05:14.83", + "identifier": "appid-137", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "938a1d17-5015-4a17-bd20-575bf5cd1102", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:137", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-06-17T12:46:18.437", + "identifier": "appid-138", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "b4c2ac55-fa7d-44d1-8c95-e64d47206a57", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:138", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SLK", + "organization": "960885406" + } + }, + { + "title": { + "en": "Test-API for a demo", + "nb": "Test-API for demo", + "nn": "Test-API for ein demo" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-08-27T08:15:12.673", + "identifier": "appid-139", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "This service grants full access to a test API", + "nb": "Denne tjenesten gir full tilgang til et test-API", + "nn": "Denne tenesta gir full tilgang til eit test-API" + }, + "resourceReferences": [ + { + "reference": "0f184d85-afa3-4dcf-916b-5a8f85a12c95", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:ettellerannetscope.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:ettellerannetscope.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:139", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-09-11T07:32:49.723", + "identifier": "appid-142", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "1f6952b3-84ef-4eec-b742-846d986691e3", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:142", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "JK's Security Level 3 Scheme", + "nb": "JK's Sikkerhetsnivå 3 Scheme", + "nn": "JK's Sikkringsnivå 3 Scheme" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-09-22T11:46:26.11", + "identifier": "appid-144", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Example of a DelegationScheme with security level 3 requirement", + "nb": "Eksempel på DelegationScheme med sikkerhetsnivå 3 krav", + "nn": "Eit døme på DelegationScheme med sikkringsnivå 3 krav" + }, + "resourceReferences": [ + { + "reference": "5f03a306-8a01-47b5-8219-8014843ce691", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/seclvl3.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/seclvl3.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:144", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "JK's Security Level 2 Scheme", + "nb": "JK's Sikkerhetsnivå 2 Scheme", + "nn": "JK's Sikkringsnivå 2 Scheme" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-09-22T11:54:03.32", + "identifier": "appid-145", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Example of a DelegationScheme with security level 2 requirement", + "nb": "Eksempel på DelegationScheme med sikkerhetsnivå 2 krav", + "nn": "Eit døme på DelegationScheme med sikkringsnivå 2 krav" + }, + "resourceReferences": [ + { + "reference": "6685c771-459a-43ac-acb0-27a46d8f32d1", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/seclvl2.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/seclvl2.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:145", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-09-29T12:32:40.68", + "identifier": "appid-147", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "08d6bac5-e581-4e34-b33e-1f3e2994159a", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:147", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-09-30T10:57:40.96", + "identifier": "appid-148", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "6d91d828-5554-48f9-8875-3a5cb1cf562e", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:148", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-11-23T08:36:19.6", + "identifier": "appid-150", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "77b6ba03-b0e0-4b38-8477-0928f4a2131c", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:150", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2020-12-16T11:19:44.693", + "identifier": "appid-153", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "4ee353be-b998-4e86-8366-99a9c8ece1bc", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:153", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-01-10T22:55:28.887", + "identifier": "appid-154", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "630031e8-8074-4e85-b39d-b5ec523354fa", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:154", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "NAV", + "organization": "889640782" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-01-12T20:47:54.047", + "identifier": "appid-155", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "7a44f919-f4a6-4ac1-8caf-0d364e8f355f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:155", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-01-15T09:06:22.017", + "identifier": "appid-164", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "5fec884c-c232-456f-8b2f-9e54c0d1efb3", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:164", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-01-28T18:05:06.683", + "identifier": "appid-168", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "30168308-9f93-460f-868a-0edbb921ea8f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:168", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-15T19:51:35.823", + "identifier": "appid-178", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "04e68c88-92f4-42a1-a464-a97f41d7a58f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:178", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-15T19:54:20.687", + "identifier": "appid-179", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "692cc835-60b0-49d7-b10d-2f9fa3c07eec", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:179", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-15T19:57:22.347", + "identifier": "appid-180", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "da9b46e2-479f-44c1-8423-01c3a0fab56c", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:180", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-15T19:57:28.673", + "identifier": "appid-181", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "73085841-e264-4257-bc0c-061c5707d54b", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:181", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Regression", + "nb": "Regression", + "nn": "Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-15T19:57:42.953", + "identifier": "appid-182", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes", + "nb": "Gir anledning til å teste maskinporten", + "nn": "Gjer høve til å teste maskinporten" + }, + "resourceReferences": [ + { + "reference": "c6086d53-6d60-41b3-9f67-32a6347222e2", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:maskinporten/delegationschemes.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:182", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-16T16:01:27.67", + "identifier": "appid-184", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "3210f4eb-2d76-4666-9574-664c0fd985f5", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:184", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-02-16T16:02:03.783", + "identifier": "appid-185", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "165a2af4-a9e3-4d94-a5f2-65ec749af10e", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:185", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-09T14:11:22.853", + "identifier": "appid-191", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "86a49da7-9d41-42ba-9ab8-0ded1f6b6b34", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:191", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SVV", + "organization": "971032081" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-09T14:11:34.503", + "identifier": "appid-192", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "cc8878d7-21d2-43af-ae4a-27ffcd0f06e4", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:192", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SVV", + "organization": "971032081" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-09T20:12:53.51", + "identifier": "appid-193", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "47a69357-3028-48bc-abdf-1fd4857446bb", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:193", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:35.29", + "identifier": "appid-196", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "b6bdc87c-e124-437b-9858-35f27171a24a", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:196", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:39.577", + "identifier": "appid-197", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "09ef4c47-0493-49ba-ba69-7028df31134c", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:197", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:43.623", + "identifier": "appid-198", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "98e7d274-3b64-4d10-b7d4-2b6e27026350", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:198", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:47.017", + "identifier": "appid-199", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "6ac1efeb-0ae7-4e3d-aafd-5bfe2184e348", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:199", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:49.973", + "identifier": "appid-200", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "0d552f1c-dc41-43a6-9f76-4650434ed5e1", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:200", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:54.017", + "identifier": "appid-201", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "45164e1d-147b-4c51-8446-19d9233a0c27", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:201", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T13:59:57.35", + "identifier": "appid-202", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "d60d98dd-830e-4554-b2d4-b9b76696f770", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:202", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T14:00:00.53", + "identifier": "appid-203", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "eb7a322c-98f5-4d91-8720-baf4b7a61dcc", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:203", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-03-19T14:00:04.45", + "identifier": "appid-204", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "18ab3b9a-a0c2-408c-b9fa-21838330c2fa", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:204", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-05-18T13:47:29.147", + "identifier": "appid-205", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "92e7f534-b126-415c-8a65-d7a8d8ff70a5", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:205", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SVV", + "organization": "971032081" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-10T09:46:01.027", + "identifier": "appid-206", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "72f5b1bd-3e0e-49d0-8133-236cb8b628e5", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:206", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-10T09:47:12.093", + "identifier": "appid-207", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "71cee800-9b2c-4326-b336-7921223f9ca3", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:207", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-10T09:47:54.12", + "identifier": "appid-208", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "fd9a3748-2c56-49dd-9860-64de0258ada3", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:208", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-10T09:48:49.723", + "identifier": "appid-209", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "f011cd46-d7f3-4037-975c-5bdcd166295e", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:209", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-10T10:01:35.137", + "identifier": "appid-210", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "55d73b7c-6040-41ff-b0dc-877692ba0ea6", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:210", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-12T13:27:33.327", + "identifier": "appid-211", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "43a73290-3193-49be-89f5-2b309e373442", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:211", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-08-18T14:22:38", + "identifier": "appid-212", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "5295d5bd-c4c4-43c4-a55e-7c15ecde1ce7", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:212", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "nb": "Bjørn 1" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-09-28T13:55:27.403", + "identifier": "appid-214", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "nb": "Bla bla bla bla bla" + }, + "resourceReferences": [ + { + "reference": "61aeb251-1e1c-4dcd-b33a-6e63e30b0e6f", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:214", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "nb": "Bjørn 1" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-09-03T12:30:33.887", + "identifier": "appid-213", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "nb": "Bla bla bla bla bla" + }, + "resourceReferences": [ + { + "reference": "8931d72d-0bab-4c9f-a260-ce37810d6f16", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:213", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": { + "nb": "Automation Test Delegation Scheme Requires Level 3" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-10-27T16:11:59.113", + "identifier": "appid-215", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "nb": "Bla bla bla bla bla" + }, + "resourceReferences": [ + { + "reference": "89058b75-8ddb-4c69-8e5c-158b87f7e6cc", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:215", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "NAV", + "organization": "889640782" + } + }, + { + "title": { + "nb": "Automation Test Delegation Scheme Requires Level 3" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-10-27T16:12:00.827", + "identifier": "appid-216", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "nb": "Bla bla bla bla bla" + }, + "resourceReferences": [ + { + "reference": "9fd1e158-2dad-4e56-bf7f-ab2e69b73a0a", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.read", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:bjorn/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:216", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "NAV", + "organization": "889640782" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-12-13T12:12:34.827", + "identifier": "appid-217", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "ea6e52be-b4d6-44d3-a272-f955b84b34e6", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:217", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "Automation Regression", + "nb": "Automation Regression", + "nn": "Automation Regression" + }, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2021-12-13T12:12:49.563", + "identifier": "appid-218", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": { + "en": "Allows you to test maskinporten changes as part of automation testing", + "nb": "Gir anledning til a teste maskinporten som en del av automatiserte tester", + "nn": "Gjer hove til a teste maskinporten som en del av automatiserte tester" + }, + "resourceReferences": [ + { + "reference": "ed752be2-e80b-4cc5-83e5-263dbc1cf60d", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "altinn:test/theworld.admin", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:218", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2022-03-01T13:28:17.143", + "identifier": "appid-219", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "5b16379f-f999-4805-9a67-2c32ce304ffa", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:219", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DFO", + "organization": "986252932" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2022-04-01T15:29:03.213", + "identifier": "appid-220", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "122cea91-6b64-4ea4-b460-3ab597ffe15d", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:220", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "NHN", + "organization": "994598759" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2022-04-20T13:31:33.433", + "identifier": "appid-221", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "fae69028-5497-432f-9a32-d7821b487fff", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:221", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "MAT", + "organization": "985399077" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2022-06-08T09:45:50.453", + "identifier": "appid-222", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "95c94595-c026-4b7b-880a-7c03d9736ceb", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:222", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076" + } + }, + { + "title": {}, + "sector": null, + "status": null, + "validTo": "9999-12-31T23:59:59.997", + "homepage": null, + "isPartOf": null, + "keywords": null, + "validFrom": "2022-06-13T13:41:02.943", + "identifier": "appid-223", + "isComplete": false, + "description": null, + "resourceType": "MaskinportenSchema", + "thematicArea": null, + "isPublicService": true, + "rightDescription": {}, + "resourceReferences": [ + { + "reference": "2d04277f-f4a9-498f-b317-8bfacb0d19e9", + "referenceType": "DelegationSchemeId", + "referenceSource": "Altinn2" + }, + { + "reference": "AppId:223", + "referenceType": "ServiceCode", + "referenceSource": "Altinn2" + }, + { + "reference": "1", + "referenceType": "ServiceEditionCode", + "referenceSource": "Altinn2" + } + ], + "hasCompetentAuthority": { + "orgcode": "DIGDIR", + "organization": "991825827" + } + }, + { + "title": { + "en": "NAV aa distribution", + "nb-no": "NAV aa distribution", + "nn-no": "NAV aa distribution" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "nav_aa_distribution", + "isComplete": true, + "description": { + "en": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger", + "nb-no": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger", + "nn-no": "NAVs brukerstøtte for Aa-registerets distribusjonsløsninger" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:nav_aa", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:nav_aa", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "NAV", + "organization": "991825827", + "name": { + "en": "The Norwegian Labour and Welfare Administration", + "nb-no": "Arbeids og velferdsetaten", + "nn-no": "Arbeids og velferdsetaten" + } + } + }, + { + "title": { + "en": "SKD 1", + "nb-no": "SKD 1", + "nn-no": "SKD 1" + }, + "sector": [ + "privat" + ], + "status": "Active", + "validTo": "2022-12-24T23:59:59", + "homepage": "https://www.nav.no/", + "isPartOf": "navportal", + "keywords": [ + { + "word": "delegation", + "language": "nb" + } + ], + "validFrom": "2022-09-20T06:46:07.598Z", + "identifier": "skd_1", + "isComplete": true, + "description": { + "en": "SKD 1", + "nb-no": "SKD 1", + "nn-no": "SKD 1" + }, + "resourceType": "MaskinportenSchema", + "thematicArea": "http://publications.europa.eu/resource/authority/eurovoc/2468", + "isPublicService": true, + "rightDescription": { + "en": "Gir mottaker lov til å bruke api", + "nb-no": "Gir mottaker lov til å bruke api", + "nn-no": "Gir mottaker lov til å bruke api" + }, + "resourceReferences": [ + { + "reference": "urn:altinn:resource:skd_1", + "referenceType": "Uri", + "referenceSource": "Altinn3" + }, + { + "reference": "urn:altinn:maskinporten:skd_1", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + }, + { + "reference": "altinn:test/theworld.write", + "referenceType": "MaskinportenScope", + "referenceSource": "Altinn3" + } + ], + "hasCompetentAuthority": { + "orgcode": "SKD", + "organization": "974761076", + "name": { + "en": "The Norwegian Tax Administration", + "nb-no": "Skatteetaten", + "nn-no": "Skatteetaten" + } + } + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/subjectResources.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/subjectResources.json new file mode 100644 index 00000000..72ed3fae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Resources/subjectResources.json @@ -0,0 +1,99 @@ +{ + "links": {}, + "data": [ + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "dagl", + "urn": "urn:altinn:rolecode:dagl" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_apps-test", + "urn": "urn:altinn:resource:app_ttd_apps-test" + }, + { + "type": "urn:altinn:resource", + "value": "generic-access-resource", + "urn": "urn:altinn:resource:generic-access-resource" + } + ] + }, + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "regna", + "urn": "urn:altinn:rolecode:regna" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "app_ttd_apps-test", + "urn": "urn:altinn:resource:app_ttd_apps-test" + } + ] + }, + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "innh", + "urn": "urn:altinn:rolecode:innh" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "jks_audi_etron_gt", + "urn": "urn:altinn:resource:jks_audi_etron_gt" + } + ] + }, + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "utinn", + "urn": "urn:altinn:rolecode:utinn" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "jks_audi_etron_gt", + "urn": "urn:altinn:resource:jks_audi_etron_gt" + }, + { + "type": "urn:altinn:resource", + "value": "generic-access-resource", + "urn": "urn:altinn:resource:generic-access-resource" + } + ] + }, + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "hadm", + "urn": "urn:altinn:rolecode:hadm" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "jks_audi_etron_gt", + "urn": "urn:altinn:resource:jks_audi_etron_gt" + } + ] + }, + { + "subject": { + "type": "urn:altinn:rolecode", + "value": "priv", + "urn": "urn:altinn:rolecode:priv" + }, + "resources": [ + { + "type": "urn:altinn:resource", + "value": "generic-access-resource", + "urn": "urn:altinn:resource:generic-access-resource" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004216/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004216/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004216/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004219/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004219/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004219/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004225/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004225/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004225/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004226/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004226/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_1234/party_50004226/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50004221/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50004221/roles.json new file mode 100644 index 00000000..d464a7a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50004221/roles.json @@ -0,0 +1,10 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50005545/roles.json new file mode 100644 index 00000000..d464a7a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000095/party_50005545/roles.json @@ -0,0 +1,10 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000490/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000490/party_50005545/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20000490/party_50005545/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50004221/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50004221/roles.json new file mode 100644 index 00000000..79a820ac --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50004221/roles.json @@ -0,0 +1,6 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50005545/roles.json new file mode 100644 index 00000000..bb62548c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20001337/party_50005545/roles.json @@ -0,0 +1,6 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100001/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100001/roles.json new file mode 100644 index 00000000..79b5a21a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100001/roles.json @@ -0,0 +1,6 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100002/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100002/roles.json new file mode 100644 index 00000000..c5dac5a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100002/party_50100002/roles.json @@ -0,0 +1,70 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIUT" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIV" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "BOADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "TUL02" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0282" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100010/party_50100010/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100010/party_50100010/roles.json new file mode 100644 index 00000000..145593cf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100010/party_50100010/roles.json @@ -0,0 +1,6 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100010/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100010/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100010/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100011/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100011/roles.json new file mode 100644 index 00000000..c5dac5a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_20100011/party_50100011/roles.json @@ -0,0 +1,70 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIUT" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIV" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "BOADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "TUL02" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0282" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_4321/party_50004223/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_4321/party_50004223/roles.json new file mode 100644 index 00000000..101390a5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Roles/user_4321/party_50004223/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "APIADM" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000095/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000095/party_50005545/roles.json new file mode 100644 index 00000000..d464a7a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000095/party_50005545/roles.json @@ -0,0 +1,10 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50002598/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50002598/roles.json new file mode 100644 index 00000000..c5dac5a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50002598/roles.json @@ -0,0 +1,70 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIUT" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PRIV" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "BOADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "TUL02" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0282" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50005545/roles.json new file mode 100644 index 00000000..ac9f2949 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20000490/party_50005545/roles.json @@ -0,0 +1,98 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LEDE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20001337/party_50005545/roles.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20001337/party_50005545/roles.json new file mode 100644 index 00000000..d1db368c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/RolesForDelegation/user_20001337/party_50005545/roles.json @@ -0,0 +1,102 @@ +[ + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "LOPER" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ADMAI" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "REGNA" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SISKD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UILUF" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTINN" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UTOMR" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KLADM" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ATTST" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "HVASK" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PAVAD" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "SIGNE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "UIHTL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "KOMAB" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "DAGL" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "ECKEYROLE" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "EKTJ" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "PASIG" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0278" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0236" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0212" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0286" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0293" + }, + { + "Type": "http://schemas.altinn.no/rest/2019/05/identity/claims/role", + "Value": "A0294" + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/System/ttd_demo_product/defaultrights.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/System/ttd_demo_product/defaultrights.json new file mode 100644 index 00000000..00b66584 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/System/ttd_demo_product/defaultrights.json @@ -0,0 +1,22 @@ +[ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] + }, + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] + } +] \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/16C1F2F6-9E00-4922-B16D-74C46D948E61/systemuser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/16C1F2F6-9E00-4922-B16D-74C46D948E61/systemuser.json new file mode 100644 index 00000000..f1c04282 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/16C1F2F6-9E00-4922-B16D-74C46D948E61/systemuser.json @@ -0,0 +1,13 @@ +{ + "id": "16C1F2F6-9E00-4922-B16D-74C46D948E61", + "integrationTitle": "MySystemUser", + "systemId": "ttd_demo_product", + "productName": "", + "systemInternalId": "6d728100-a29b-4b40-a115-590b796e9a79", + "partyId": "50005545", + "reporteeOrgNo": "910459880", + "created": "2024-07-09T09:56:25.593115Z", + "isDeleted": false, + "supplierName": "", + "supplierOrgno": "910419560" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/9D569A55-D5CE-4914-BBF8-CA3474458604/systemuser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/9D569A55-D5CE-4914-BBF8-CA3474458604/systemuser.json new file mode 100644 index 00000000..65c85be3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/SystemUser/9D569A55-D5CE-4914-BBF8-CA3474458604/systemuser.json @@ -0,0 +1,13 @@ +{ + "id": "9D569A55-D5CE-4914-BBF8-CA3474458604", + "integrationTitle": "MySystemUser2", + "systemId": "ttd_demo_product", + "productName": "", + "systemInternalId": "6d728100-a29b-4b40-a115-590b796e9a79", + "partyId": "50005545", + "reporteeOrgNo": "910459880", + "created": "2024-07-09T09:56:25.593115Z", + "isDeleted": false, + "supplierName": "", + "supplierOrgno": "910419560" +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeOfferedDelegationExternal.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeOfferedDelegationExternal.cs new file mode 100644 index 00000000..c35db724 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeOfferedDelegationExternal.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Util; + +/// +/// testdata +/// +public static class TestDataRevokeOfferedDelegationExternal +{ + private static string PersonPaulaSSN => "02056260016"; + + private static int PersonPaulaUserId => 20000095; + + private static int PersonPaulaPartyId => 50002203; + + private static string PersonOrjanSSN => "27099450067"; + + private static int PersonOrjanUserId => 20001337; + + private static int PersonOrjanPartyId => 50003899; + + private static string ResourceOrg => "org1"; + + private static string ResourceAppId => "app1"; + + private static string OrganizationOrstaAccounting => "910459880"; + + private static int OrganizationOrstaPartyId => 50005545; + + private static string PersonKasperSSN => "07124912037"; + + private static int PersonKasperUserId => 20000490; + + private static int PersonKasperPartyId => 50002598; + + private static string OrganizationKolbjorn => "810419342"; + + private static int OrganizationKolbjornPartyId => 50004226; + + private static string EnterpriseUsername => "OrstaECUser"; + + /// + /// An input model that specifies revoking an existing delegation for resource app_org1_app1 with action read from Orjan to Paula. + /// The delegation + /// + /// + public static IEnumerable FromPersonToPerson() => [[ + PrincipalUtil.GetToken(PersonOrjanUserId, PersonOrjanPartyId, 3), + NewRevokeOfferedModel( + WithRevokeOfferedTo(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, PersonPaulaUserId), + WithRevokeOfferedAction("read"), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + PersonOrjanPartyId + ]]; + + /// + /// An input model that specifies revoking an existing delegation from Paula to Orstad Accounting. The delegation should + /// + /// + public static IEnumerable FromPersonToOrganization() => [[ + PrincipalUtil.GetToken(PersonPaulaUserId, PersonPaulaPartyId, 3), + NewRevokeOfferedModel( + WithRevokeOfferedTo(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, OrganizationOrstaPartyId), + WithRevokeOfferedAction("read"), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + PersonPaulaPartyId + ]]; + + /// + /// a + /// + /// + public static IEnumerable FromOrganizationToOrganization() => [[ + PrincipalUtil.GetToken(PersonKasperUserId, PersonKasperPartyId, 3), + NewRevokeOfferedModel( + WithRevokeOfferedTo(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, OrganizationKolbjornPartyId), + WithRevokeOfferedAction("read"), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + OrganizationOrstaPartyId + ]]; + + /// + /// summary + /// + /// + public static IEnumerable FromOrganizationToPerson() => [[ + PrincipalUtil.GetToken(PersonKasperUserId, PersonKasperPartyId, 3), + NewRevokeOfferedModel( + WithRevokeOfferedTo(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, PersonPaulaUserId), + WithRevokeOfferedAction("read"), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + OrganizationOrstaPartyId + ]]; + + /// + /// summary + /// + /// + public static IEnumerable FromOrganizationToEnterpriseuser() => [[ + PrincipalUtil.GetToken(PersonKasperUserId, PersonKasperPartyId, 3), + NewRevokeOfferedModel( + WithRevokeOfferedTo(BaseUrn.Altinn.EnterpriseUser.Username, EnterpriseUsername), + WithRevokeOfferedAction("read"), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeOfferedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + OrganizationOrstaPartyId + ]]; + + private static RevokeOfferedDelegationExternal NewRevokeOfferedModel(params Action[] actions) + { + var model = new RevokeOfferedDelegationExternal(); + foreach (var action in actions) + { + action(model); + } + + return model; + } + + private static Action WithRevokeOfferedAction(string action) => model => + { + model.Rights ??= [new() { Action = action, Resource = [] }]; + model.Rights.First().Action = action; + }; + + private static Action WithRevokeOfferedResource(string id, object value) => model => + { + model.Rights ??= [new() { Resource = [] }]; + model.Rights.First().Resource ??= []; + model.Rights.First().Resource.Add(new() + { + Id = id, + Value = value.ToString(), + }); + }; + + private static Action WithRevokeOfferedTo(string id, object value) => model => + { + model.To ??= []; + model.To.Add(new() + { + Id = id, + Value = value.ToString(), + }); + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeReceivedDelegationExternal.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeReceivedDelegationExternal.cs new file mode 100644 index 00000000..1b747ac8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/TestDataRevokeReceivedDelegationExternal.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Util; + +/// +/// testdata +/// +public static class TestDataRevokeReceivedDelegationExternal +{ + private static string PersonPaulaSSN => "02056260016"; + + private static int PersonPaulaUserId => 20000095; + + private static int PersonPaulaPartyId => 50002203; + + private static string PersonOrjanSSN => "27099450067"; + + private static int PersonOrjanUserId => 20001337; + + private static int PersonOrjanPartyId => 50003899; + + private static string ResourceOrg => "org1"; + + private static string ResourceAppId => "app1"; + + private static string OrganizationOrstaAccounting => "910459880"; + + private static int OrganizationOrstaPartyId => 50005545; + + private static string PersonKasperSSN => "07124912037"; + + private static int PersonKasperUserId => 20000490; + + private static int PersonKasperPartyId => 50002598; + + private static string OrganizationKolbjorn => "810419342"; + + private static int OrganizationKolbjornPartyId => 50004226; + + private static string EnterpriseUsername => "OrstaECUser"; + + /// + /// An input model that specifies revoking an existing delegation from Orjan to Paula. + /// The delegation + /// + /// + public static IEnumerable FromPersonToPerson() => [[ + PrincipalUtil.GetToken(PersonOrjanUserId, PersonOrjanPartyId, 3), + NewRevokeReceivedModel( + WithRevokeReceivedFrom(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, PersonPaulaUserId), + WithRevokeReceivedAction("read"), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + PersonOrjanPartyId + ]]; + + /// + /// An input model that specifies an delegation from Paula + /// + /// + public static IEnumerable FromPersonToOrganization() => [[ + PrincipalUtil.GetToken(PersonOrjanUserId, PersonOrjanPartyId, 3), + NewRevokeReceivedModel( + WithRevokeReceivedFrom(AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, PersonPaulaUserId), + WithRevokeReceivedAction("read"), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + OrganizationOrstaPartyId + ]]; + + /// + /// a + /// + /// + public static IEnumerable FromOrganizationToOrganization() => [[ + PrincipalUtil.GetToken(PersonOrjanUserId, PersonOrjanPartyId, 3), + NewRevokeReceivedModel( + WithRevokeReceivedFrom(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, OrganizationOrstaPartyId), + WithRevokeReceivedAction("read"), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + OrganizationKolbjornPartyId + ]]; + + /// + /// summary + /// + /// + public static IEnumerable FromOrganizationToPerson() => [[ + PrincipalUtil.GetToken(PersonPaulaUserId, PersonPaulaPartyId, 3), + NewRevokeReceivedModel( + WithRevokeReceivedFrom(AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, OrganizationOrstaPartyId), + WithRevokeReceivedAction("read"), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppOwner, ResourceOrg), + WithRevokeReceivedResource(BaseUrn.Altinn.Resource.AppId, ResourceAppId)), + PersonPaulaPartyId + ]]; + + private static RevokeReceivedDelegationExternal NewRevokeReceivedModel(params Action[] actions) + { + var model = new RevokeReceivedDelegationExternal(); + foreach (var action in actions) + { + action(model); + } + + return model; + } + + private static Action WithRevokeReceivedAction(string action) => model => + { + model.Rights ??= [new() { Action = action }]; + model.Rights.First().Action = action; + }; + + private static Action WithRevokeReceivedResource(string id, object value) => model => + { + model.Rights ??= [new() { Resource = [] }]; + model.Rights.First().Resource ??= []; + model.Rights.First().Resource.Add(new() + { + Id = id, + Value = value.ToString(), + }); + }; + + private static Action WithRevokeReceivedFrom(string id, object value) => model => + { + model.From ??= []; + model.From.Add(new() + { + Id = id, + Value = value.ToString(), + }); + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0001-000000000011.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0001-000000000011.json new file mode 100644 index 00000000..9404bcd2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0001-000000000011.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100011, + "UserUuid": "00000000-0000-0000-0001-000000000011", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100011, + "Party": { + "PartyTypeName": 1, + "SSN": "01018170071", + "OrgNumber": "", + "Person": { + "SSN": "01018170071", + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "FirstName": "MAINUNIT AND SUBUNIT TO ORG", + "MiddleName": null, + "LastName": "DAGL", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100011, + "PartyUuid": "00000000-0000-0000-0001-000000000011", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000000010.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000000010.json new file mode 100644 index 00000000..36fe87e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000000010.json @@ -0,0 +1,44 @@ +{ + "UserId": 20100010, + "UserUuid": "00000000-0000-0000-0002-000000000010", + "UserType": 3, + "UserName": "MainUnit_And_SubUnit_ToOrg_EcKeyRole_User", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100010, + "Party": { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000010", + "Person": null, + "Organization": { + "OrgNumber": "901000010", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100010, + "PartyUuid": "00000000-0000-0000-0001-000000000010", + "UnitType": "AS", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000010727.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000010727.json new file mode 100644 index 00000000..a3705333 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0002-000000010727.json @@ -0,0 +1,44 @@ +{ + "UserId": 20010727, + "UserUuid": "00000000-0000-0000-0002-000000010727", + "UserType": 3, + "UserName": "OrstaECUser", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50005545, + "Party": { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "910459880", + "Person": null, + "Organization": { + "OrgNumber": "910459880", + "Name": "ØRSTA OG HEGGEDAL", + "UnitType": "AS", + "TelephoneNumber": "12345678", + "MobileNumber": "99999999", + "FaxNumber": "12345679", + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": "", + "MailingPostalCity": "", + "BusinessAddress": null, + "BusinessPostalCode": "", + "BusinessPostalCity": "", + "UnitStatus": "N" + }, + "PartyId": 50005545, + "UnitType": "AS", + "Name": "ØRSTA OG HEGGEDAL ", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0005-000000003899.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0005-000000003899.json new file mode 100644 index 00000000..e74c76de --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/00000000-0000-0000-0005-000000003899.json @@ -0,0 +1,47 @@ +{ + "UserId": 20001337, + "UserUuid": "00000000-0000-0000-0005-000000003899", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50003899, + "Party": { + "PartyTypeName": 1, + "SSN": "27099450067", + "OrgNumber": "", + "Person": { + "SSN": "27099450067", + "Name": "ØRJAN RAVNÅS", + "FirstName": "ØRJAN", + "MiddleName": "", + "LastName": "RAVNÅS", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Bjerkeveien 23 1726 SARPSBORG", + "MailingPostalCode": "1726", + "MailingPostalCity": "SARPSBORG", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "1726", + "AddressCity": "SARPSBORG", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50003899, + "UnitType": null, + "Name": "ØRJAN RAVNÅS", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01017270071.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01017270071.json new file mode 100644 index 00000000..3cf03bf5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01017270071.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100002, + "UserUuid": "00000000-0000-0000-0001-000000000002", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100002, + "Party": { + "PartyTypeName\": 1,": null, + "SSN": "01017270071", + "OrgNumber": "", + "Person": { + "SSN": "01017270071", + "Name": "PERSON TO PERSON RECIPIENT", + "FirstName": "PERSON TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100002, + "PartyUuid": "00000000-0000-0000-0001-000000000002", + "UnitType": null, + "Name": "PERSON TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01018170071.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01018170071.json new file mode 100644 index 00000000..9404bcd2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/01018170071.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100011, + "UserUuid": "00000000-0000-0000-0001-000000000011", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100011, + "Party": { + "PartyTypeName": 1, + "SSN": "01018170071", + "OrgNumber": "", + "Person": { + "SSN": "01018170071", + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "FirstName": "MAINUNIT AND SUBUNIT TO ORG", + "MiddleName": null, + "LastName": "DAGL", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100011, + "PartyUuid": "00000000-0000-0000-0001-000000000011", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/02056260016.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/02056260016.json new file mode 100644 index 00000000..bbfb7229 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/02056260016.json @@ -0,0 +1,47 @@ +{ + "UserId": 20000095, + "UserUuid": "00000000-0000-0000-0005-000000002203", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50002203, + "Party": { + "PartyTypeName": 1, + "SSN": "02056260016", + "OrgNumber": "", + "Person": { + "SSN": "02056260016", + "Name": "PAULA RIMSTAD", + "FirstName": "PAULA", + "MiddleName": "", + "LastName": "RIMSTAD", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Brannpostveien 15 3014 DRAMMEN", + "MailingPostalCode": "3014", + "MailingPostalCity": "DRAMMEN", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "3014", + "AddressCity": "DRAMMEN", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002203, + "UnitType": null, + "Name": "PAULA RIMSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/07124912037.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/07124912037.json new file mode 100644 index 00000000..0d16bb51 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/07124912037.json @@ -0,0 +1,47 @@ +{ + "UserId": 20000490, + "UserUuid": "00000000-0000-0000-0005-000000002598", + "UserType": 1, + "UserName": "kasper", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50002598, + "Party": { + "PartyTypeName": 1, + "SSN": "07124912037", + "OrgNumber": "", + "Person": { + "SSN": "07124912037", + "Name": "KASPER BØRSTAD", + "FirstName": "KASPER", + "MiddleName": "", + "LastName": "BØRSTAD", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Skålevikstølen 7 5178 LODDEFJORD", + "MailingPostalCode": "5178", + "MailingPostalCity": "LODDEFJORD", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "5178", + "AddressCity": "LODDEFJORD", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002598, + "UnitType": null, + "Name": "KASPER BØRSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000095.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000095.json new file mode 100644 index 00000000..98fd9696 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000095.json @@ -0,0 +1,48 @@ +{ + "UserId": 20000095, + "UserUuid": "00000000-0000-0000-0005-000000002203", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50002203, + "Party": { + "PartyTypeName": 1, + "SSN": "02056260016", + "OrgNumber": "", + "Person": { + "SSN": "02056260016", + "Name": "PAULA RIMSTAD", + "FirstName": "PAULA", + "MiddleName": "", + "LastName": "RIMSTAD", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Brannpostveien 15 3014 DRAMMEN", + "MailingPostalCode": "3014", + "MailingPostalCity": "DRAMMEN", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "3014", + "AddressCity": "DRAMMEN", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002203, + "PartyUuid": "00000000-0000-0000-0005-000000002203", + "UnitType": null, + "Name": "PAULA RIMSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000490.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000490.json new file mode 100644 index 00000000..046200e9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20000490.json @@ -0,0 +1,48 @@ +{ + "UserId": 20000490, + "UserUuid": "00000000-0000-0000-0005-000000002598", + "UserType": 1, + "UserName": "kasper", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50002598, + "Party": { + "PartyTypeName": 1, + "SSN": "07124912037", + "OrgNumber": "", + "Person": { + "SSN": "07124912037", + "Name": "KASPER BØRSTAD", + "FirstName": "KASPER", + "MiddleName": "", + "LastName": "BØRSTAD", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Skålevikstølen 7 5178 LODDEFJORD", + "MailingPostalCode": "5178", + "MailingPostalCity": "LODDEFJORD", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "5178", + "AddressCity": "LODDEFJORD", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50002598, + "PartyUuid": "00000000-0000-0000-0005-000000002598", + "UnitType": null, + "Name": "KASPER BØRSTAD", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100002.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100002.json new file mode 100644 index 00000000..3cf03bf5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100002.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100002, + "UserUuid": "00000000-0000-0000-0001-000000000002", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100002, + "Party": { + "PartyTypeName\": 1,": null, + "SSN": "01017270071", + "OrgNumber": "", + "Person": { + "SSN": "01017270071", + "Name": "PERSON TO PERSON RECIPIENT", + "FirstName": "PERSON TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100002, + "PartyUuid": "00000000-0000-0000-0001-000000000002", + "UnitType": null, + "Name": "PERSON TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100010.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100010.json new file mode 100644 index 00000000..36fe87e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100010.json @@ -0,0 +1,44 @@ +{ + "UserId": 20100010, + "UserUuid": "00000000-0000-0000-0002-000000000010", + "UserType": 3, + "UserName": "MainUnit_And_SubUnit_ToOrg_EcKeyRole_User", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100010, + "Party": { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000010", + "Person": null, + "Organization": { + "OrgNumber": "901000010", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100010, + "PartyUuid": "00000000-0000-0000-0001-000000000010", + "UnitType": "AS", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100011.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100011.json new file mode 100644 index 00000000..9404bcd2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100011.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100011, + "UserUuid": "00000000-0000-0000-0001-000000000011", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100011, + "Party": { + "PartyTypeName": 1, + "SSN": "01018170071", + "OrgNumber": "", + "Person": { + "SSN": "01018170071", + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "FirstName": "MAINUNIT AND SUBUNIT TO ORG", + "MiddleName": null, + "LastName": "DAGL", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100011, + "PartyUuid": "00000000-0000-0000-0001-000000000011", + "UnitType": null, + "Name": "MAINUNIT AND SUBUNIT TO ORG DAGL", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100012.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100012.json new file mode 100644 index 00000000..562802b8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/20100012.json @@ -0,0 +1,48 @@ +{ + "UserId": 20100012, + "UserUuid": "00000000-0000-0000-0001-000000000012", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100012, + "Party": { + "PartyTypeName": 1, + "SSN": "01018270071", + "OrgNumber": "", + "Person": { + "SSN": "01018270071", + "Name": "SUBUNIT TO PERSON RECIPIENT", + "FirstName": "SUBUNIT TO PERSON", + "MiddleName": null, + "LastName": "RECIPIENT", + "TelephoneNumber": null, + "MobileNumber": null, + "MailingAddress": "", + "MailingPostalCode": null, + "MailingPostalCity": null, + "AddressMunicipalNumber": null, + "AddressMunicipalName": null, + "AddressStreetName": null, + "AddressHouseNumber": null, + "AddressHouseLetter": null, + "AddressPostalCode": null, + "AddressCity": null, + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50100012, + "PartyUuid": "00000000-0000-0000-0001-000000000012", + "UnitType": null, + "Name": "SUBUNIT TO PERSON RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/27099450067.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/27099450067.json new file mode 100644 index 00000000..e74c76de --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/27099450067.json @@ -0,0 +1,47 @@ +{ + "UserId": 20001337, + "UserUuid": "00000000-0000-0000-0005-000000003899", + "UserType": 1, + "UserName": "", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50003899, + "Party": { + "PartyTypeName": 1, + "SSN": "27099450067", + "OrgNumber": "", + "Person": { + "SSN": "27099450067", + "Name": "ØRJAN RAVNÅS", + "FirstName": "ØRJAN", + "MiddleName": "", + "LastName": "RAVNÅS", + "TelephoneNumber": "", + "MobileNumber": "", + "MailingAddress": " Bjerkeveien 23 1726 SARPSBORG", + "MailingPostalCode": "1726", + "MailingPostalCity": "SARPSBORG", + "AddressMunicipalNumber": "", + "AddressMunicipalName": "", + "AddressStreetName": "", + "AddressHouseNumber": "", + "AddressHouseLetter": "", + "AddressPostalCode": "1726", + "AddressCity": "SARPSBORG", + "DateOfDeath": null + }, + "Organization": null, + "PartyId": 50003899, + "UnitType": null, + "Name": "ØRJAN RAVNÅS", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/MainUnit_And_SubUnit_ToOrg_EcKeyRole_User.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/MainUnit_And_SubUnit_ToOrg_EcKeyRole_User.json new file mode 100644 index 00000000..36fe87e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/MainUnit_And_SubUnit_ToOrg_EcKeyRole_User.json @@ -0,0 +1,44 @@ +{ + "UserId": 20100010, + "UserUuid": "00000000-0000-0000-0002-000000000010", + "UserType": 3, + "UserName": "MainUnit_And_SubUnit_ToOrg_EcKeyRole_User", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50100010, + "Party": { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "901000010", + "Person": null, + "Organization": { + "OrgNumber": "901000010", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "UnitType": "AS", + "TelephoneNumber": null, + "MobileNumber": null, + "FaxNumber": null, + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": null, + "MailingPostalCity": null, + "BusinessAddress": null, + "BusinessPostalCode": null, + "BusinessPostalCity": null + }, + "PartyId": 50100010, + "PartyUuid": "00000000-0000-0000-0001-000000000010", + "UnitType": "AS", + "Name": "MAINUNIT AND SUBUNIT TO ORG RECIPIENT", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/OrstaECUser.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/OrstaECUser.json new file mode 100644 index 00000000..a3705333 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/UserProfile/OrstaECUser.json @@ -0,0 +1,44 @@ +{ + "UserId": 20010727, + "UserUuid": "00000000-0000-0000-0002-000000010727", + "UserType": 3, + "UserName": "OrstaECUser", + "ExternalIdentity": "", + "PhoneNumber": null, + "Email": null, + "PartyId": 50005545, + "Party": { + "PartyTypeName": 2, + "SSN": "", + "OrgNumber": "910459880", + "Person": null, + "Organization": { + "OrgNumber": "910459880", + "Name": "ØRSTA OG HEGGEDAL", + "UnitType": "AS", + "TelephoneNumber": "12345678", + "MobileNumber": "99999999", + "FaxNumber": "12345679", + "EMailAddress": "test@test.test", + "InternetAddress": null, + "MailingAddress": null, + "MailingPostalCode": "", + "MailingPostalCity": "", + "BusinessAddress": null, + "BusinessPostalCode": "", + "BusinessPostalCity": "", + "UnitStatus": "N" + }, + "PartyId": 50005545, + "UnitType": "AS", + "Name": "ØRSTA OG HEGGEDAL ", + "IsDeleted": false, + "OnlyHierarchyElementWithNoAccess": false, + "ChildParties": null + }, + "ProfileSettingPreference": { + "Language": "nb", + "PreSelectedPartyId": 0, + "DoNotPromptForParty": false + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/error/delegationeventfail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/error/delegationeventfail/policy.xml new file mode 100644 index 00000000..24484e7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/error/delegationeventfail/policy.xml @@ -0,0 +1,56 @@ + + + + + Eksempel på samleregel som spesifiserer at både PRIV og DAGL m/sikkerhetsnivå; 2, for ressursen; error/delegationeventfail får tilgang til operasjonene; Read og Write + + + + + dagl + + + + + + priv + + + + + + + + error + + + + delegationeventfail + + + + + + + + read + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app1/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app1/policy.xml new file mode 100644 index 00000000..f9670934 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app1/policy.xml @@ -0,0 +1,110 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app2/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app2/policy.xml new file mode 100644 index 00000000..716eb23c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app2/policy.xml @@ -0,0 +1,93 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org1 + + + + app2 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org1 + + + + app2 + + + + task1 + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app3/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app3/policy.xml new file mode 100644 index 00000000..7e76229e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/app3/policy.xml @@ -0,0 +1,110 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app3 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app3 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app3 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app3 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/singlecomplexrule/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/singlecomplexrule/policy.xml new file mode 100644 index 00000000..778c004b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/singlecomplexrule/policy.xml @@ -0,0 +1,106 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + 20001337 + + + + + + org2 + + + + + + + + org1 + + + + singlecomplexrule + + + + task1 + + + + + + singlecomplexrule + + + + org1 + + + + task2 + + + + + + banana + + + + singlecomplexrule + + + + org1 + + + + + + + + read + + + + + + write + + + + + + eat + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/unorderedresources/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/unorderedresources/policy.xml new file mode 100644 index 00000000..9a7e6a6e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org1/unorderedresources/policy.xml @@ -0,0 +1,62 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + unorderedresources + + + + org1 + + + + + + + + read + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app1/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app1/policy.xml new file mode 100644 index 00000000..c28d1dae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app1/policy.xml @@ -0,0 +1,93 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org2 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org2 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app2/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app2/policy.xml new file mode 100644 index 00000000..80dbbf9e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/org2/app2/policy.xml @@ -0,0 +1,126 @@ + + + + + Eksempel på regel til Org subject, for egen action for eiere av appen + + + + + org2 + + + + + + + + org2 + + + + app2 + + + + + + + + appownerread + + + + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org2 + + + + app2 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org2 + + + + app2 + + + + task1 + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport/policy.xml new file mode 100644 index 00000000..c21f0f88 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport/policy.xml @@ -0,0 +1,277 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; SKD/TaxReport får tilgang til operasjonene; Read og Write Instantiate og Tasks; FormFilling og Signing + + + + + regna + + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + + + skd + + + + taxreport + + + + formfilling + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + read + + + + + + write + + + + + + instantiate + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 3, for ressursen; SKD/TaxReport får tilgang til operasjonen; Sign både for Event; SluttEvent_1b + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + sign + + + + + + + + Example rule that gives org nav and skd read right to the app inn all states + + + + + skd + + + + + + + + nav + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Example rule that gives org skd write right for app inn all states + + + + + skd + + + + + + + + skd + + + + taxreport + + + + + + + + write + + + + + + + + Rule that gives systems with a specific API scope access to do read + + + + + altinn:platform:skd:amelding + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; SKD/TaxReport hvor appresource = events + + + + + regna + + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + events + + + + + + + + read + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport2/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport2/policy.xml new file mode 100644 index 00000000..b40ebe08 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/taxreport2/policy.xml @@ -0,0 +1,174 @@ + + + Eksempel på en policy + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; skd/TaxReport får tilgang til operasjonene; Read og Write både for Event; Signing og Tasks; Instantiate og FormFilling + + + + + REGNA + + + + + + DAGL + + + + + + + + skd + + + + taxreport2 + + + + Instansiate + + + + + + skd + + + + taxreport2 + + + + FormFilling + + + + + + skd + + + + taxreport2 + + + + Signing + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 3, for ressursen; skd/TaxReport får tilgang til operasjonen; Sign både for Event; SluttEvent_1b + + + + + DAGL + + + + + + + + skd + + + + taxreport2 + + + + Signing + + + + + + + + sign + + + + + + + + + + + + PRIV + + + + + + PRIV2 + + + + + + DAGL + + + + + + + + skd + + + + taxreport2 + + + + Signing + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/undefined/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/undefined/policy.xml new file mode 100644 index 00000000..f9670934 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/skd/undefined/policy.xml @@ -0,0 +1,110 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/testorg/testapp/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/testorg/testapp/policy.xml new file mode 100644 index 00000000..237f0117 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/testorg/testapp/policy.xml @@ -0,0 +1,46 @@ + + + + Policy for GetRolesWithAccess_TC04. + + + + + A subject with a "bogus" attribute with a value of + "Physician" can read or write Bart Simpson's medical + record. + + + + + + Physician + + + + + + + + http://medico.com/record/patient/BartSimpson + + + + + + + + read + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/am-devtest-instancedelegation/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/am-devtest-instancedelegation/policy.xml new file mode 100644 index 00000000..f5f5d674 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/am-devtest-instancedelegation/policy.xml @@ -0,0 +1,124 @@ + + + + + A rule giving user with role Priv, Dagl and the app owner ttd all rights for the app ttd/am-devtest-instancedelegation + + + + + ttd + + + + + + priv + + + + + + dagl + + + + + + + + ttd + + + + am-devtest-instancedelegation + + + + + + + + instantiate + + + + + + read + + + + + + write + + + + + + delete + + + + + + complete + + + + + + + + A rule defining all instance delegation rights the App itself is allowed to perform for instances of the app ttd/am-devtest-instancedelegation. In this example the app can delegate the Read and Sign actions for Task_1 + + + + + app_ttd_am-devtest-instancedelegation + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + + + + + read + + + + + + sign + + + + + + + + + + 2 + + + + + 3 + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/apps-test/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/apps-test/policy.xml new file mode 100644 index 00000000..4dbc1d55 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/apps-test/policy.xml @@ -0,0 +1,306 @@ + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to instantiate a instance of a given app of ttd/apps-test + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + apps-test + + + + + + + + instantiate + + + + + + read + + + + + + + + Rule that defines that user with role REGNA or DAGL can read and write for ttd/apps-test when it is in Task_1 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + apps-test + + + + Task_1 + + + + + + ttd + + + + apps-test + + + + EndEvent_1 + + + + + + + + read + + + + + + write + + + + + + + + Rule that defines that user with role ADMAI can delete instances of ttd/apps-test + + + + + ADMAI + + + + + + + + ttd + + + + apps-test + + + + delete + + + + + + + + Rule that defines that org can complete an instance of ttd/apps-test which state is at the end event. + + + + + ttd + + + + + + + + ttd + + + + apps-test + + + + EndEvent_1 + + + + + + + + complete + + + + + + + + Rule that defines that org can delete an instance of tdd/endring-av-navn in any task or event. + + + + + ttd + + + + + + + + ttd + + + + apps-test + + + + + + + + delete + + + + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to read the appresource events of a given app of ttd/apps-test + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + apps-test + + + + events + + + + + + + + read + + + + + + + + Rule that defines that org can write to instances of ttd/apps-test for any states + + + + + ttd + + + + + + + + ttd + + + + apps-test + + + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/rf-0002/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/rf-0002/policy.xml new file mode 100644 index 00000000..31df7c2b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/AltinnApps/ttd/rf-0002/policy.xml @@ -0,0 +1,230 @@ + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to instantiate a instance of a given app of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + instantiate + + + + + + read + + + + + + + + Rule that defines that user with role REGNA or DAGL can read and write for ttd/rf-0002 when it is in Task_1 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + Task_1 + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + read + + + + + + write + + + + + + + + Rule that defines that user with role REGNA or DAGL can delete instances of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + delete + + + + + + + + Rule that defines that org can write to instances of ttd/rf-0002 for any states + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + write + + + + + + + + Rule that defines that org can complete an instance of ttd/rf-0002 which state is at the end event. + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + complete + + + + + + + + + + 1 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/Instance/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/Instance/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/delegationpolicy.xml new file mode 100644 index 00000000..fe51d365 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/Instance/app_ttd_am-devtest-instancedelegation/00000000-0000-0000-0000-000000000001/delegationpolicy.xml @@ -0,0 +1,46 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + ce4ba72b-d111-404f-95b5-313fb3847fa1 + + + + + + + + ttd + + + + am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000001 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/PolicyRepository/IIA003Policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/PolicyRepository/IIA003Policy.xml new file mode 100644 index 00000000..d0f24805 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/PolicyRepository/IIA003Policy.xml @@ -0,0 +1,46 @@ + + + + Policy for Conformance Test IIA003. + + + + + A subject with a "bogus" attribute with a value of + "Physician" can read or write Bart Simpson's medical + record. + + + + + + Physician + + + + + + + + http://medico.com/record/patient/BartSimpson + + + + + + + + read + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/altinn_maskinporten_scope_delegation/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/altinn_maskinporten_scope_delegation/policy.xml new file mode 100644 index 00000000..852307ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/altinn_maskinporten_scope_delegation/policy.xml @@ -0,0 +1,58 @@ + + + + + SystemResource policy for resource; altinn_maskinporten_scope_delegation for roles; APIADM, APIADMNUF and HADM to have access to actions; read and write + + + + + APIADM + + + + + + APIADMNUF + + + + + + HADM + + + + + + + + altinn_maskinporten_scope_delegation + + + + + + + + read + + + + + + write + + + + + + + + + + 2 + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/digdirs_company_car/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/digdirs_company_car/resourcepolicy.xml new file mode 100644 index 00000000..7d42f3b9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/digdirs_company_car/resourcepolicy.xml @@ -0,0 +1,40 @@ + + + + + Policy for DigDir's Company Car + + + + + DAGL + + + + + + + + digdirs_company_car + + + + + + + + drive + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-access-resource/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-access-resource/resourcepolicy.xml new file mode 100644 index 00000000..0881d778 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-access-resource/resourcepolicy.xml @@ -0,0 +1,190 @@ + + + Policy for a Generic Access Resource in Altinn 3 + + + + + + + PRIV + + + + + + + + generic-access-resource + + + + + + + + read + + + + + + write + + + + + + + + + + + + PRIV + + + + + + + + generic-access-resource + + + + priv-delegation-subtask + + + + + + + + delegated-action-to-user + + + + + + delegated-action-to-keyroleunit + + + + + + + + + + + + DAGL + + + + + + + + generic-access-resource + + + + + + + + read + + + + + + + + + + + + DAGL + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + subunit-delegated-action + + + + + + mainunit-delegated-action + + + + + + subunit-delegated-action-to-keyroleunit + + + + + + mainunit-delegated-action-to-keyroleunit + + + + + + + + + + + + UTINN + + + + + + + + generic-access-resource + + + + + + + + admai-delegated-action + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-accesslist-resource/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-accesslist-resource/resourcepolicy.xml new file mode 100644 index 00000000..2efded48 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/generic-accesslist-resource/resourcepolicy.xml @@ -0,0 +1,68 @@ + + + Policy for a Generic Accesslist Resource in Altinn 3 + + + + + + + DAGL + + + + + + + + generic-accesslist-resource + + + + + + + + read + + + + + + + + + + + + DAGL + + + + + + + + generic-accesslist-resource + + + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/jks_audi_etron_gt/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/jks_audi_etron_gt/resourcepolicy.xml new file mode 100644 index 00000000..9ee5bcc1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/jks_audi_etron_gt/resourcepolicy.xml @@ -0,0 +1,144 @@ + + + + + Policy for JK's Audi E-Tron GT + + + + + INNH + + + + + + HADM + + + + + + + + jks_audi_etron_gt + + + + + + + + drive + + + + + + park + + + + + + race + + + + + + + + Policy for JK's Audi E-Tron GT + + + + + HADM + + + + garage + + + + + + + + jks_audi_etron_gt + + + + mechanic_work + + + + + + + + change_tires + + + + + + + + Policy for JK's Audi E-Tron GT + + + + + UTINN + + + + garage + + + + + + UTINN + + + + driveway + + + + + + + + jks_audi_etron_gt + + + + + + + + drive + + + + + + park + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/mp_validation_problem_details/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/mp_validation_problem_details/resourcepolicy.xml new file mode 100644 index 00000000..78ab4a68 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/mp_validation_problem_details/resourcepolicy.xml @@ -0,0 +1,44 @@ + + + + + + + + + + DAGL + + + + + + + + mp_validation_problem_details + + + + + + + + read + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/non_delegable_maskinportenschema/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/non_delegable_maskinportenschema/resourcepolicy.xml new file mode 100644 index 00000000..1dfee0da --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/non_delegable_maskinportenschema/resourcepolicy.xml @@ -0,0 +1,44 @@ + + + + + + + + + + NOPE + + + + + + + + non_delegable_maskinportenschema + + + + + + + + read + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource1/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource1/resourcepolicy.xml new file mode 100644 index 00000000..d8d9c312 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource1/resourcepolicy.xml @@ -0,0 +1,104 @@ + + + + + Default policy template for Maskinporten DelegationSchemes + + + + + BEST + + + + + + BOBE + + + + + + BEST + + + + + + DAGL + + + + + + DTPR + + + + + + DTSO + + + + + + INNH + + + + + + KEMN + + + + + + KOMP + + + + + + LEDE + + + + + + REPR + + + + + + + + resource1 + + + + + + + + read + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource2/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource2/resourcepolicy.xml new file mode 100644 index 00000000..5aebe703 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/resource2/resourcepolicy.xml @@ -0,0 +1,100 @@ + + + + + Default policy template for Maskinporten DelegationSchemes + + + + + BEST + + + + + + BOBE + + + + + + BEST + + + + + + DAGL + + + + + + DTPR + + + + + + DTSO + + + + + + INNH + + + + + + KEMN + + + + + + KOMP + + + + + + LEDE + + + + + + REPR + + + + + + + + resource2 + + + + + + + + scopeaccess + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/scope-access-schema/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/scope-access-schema/resourcepolicy.xml new file mode 100644 index 00000000..df166cce --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/scope-access-schema/resourcepolicy.xml @@ -0,0 +1,40 @@ + + + Policy for a MaskinportenSchema in Altinn 3 + + + + + + + DAGL + + + + + + + + scope-access-schema + + + + + + + + ScopeAccess + + + + + + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/system_resource/resourcepolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/system_resource/resourcepolicy.xml new file mode 100644 index 00000000..9f35f37e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/Xacml/3.0/ResourceRegistry/system_resource/resourcepolicy.xml @@ -0,0 +1,44 @@ + + + + + + + + + + DAGL + + + + + + + + system_resource + + + + + + + + read + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000001/N/313FB3847FA1/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000001/N/313FB3847FA1/delegationpolicy.xml new file mode 100644 index 00000000..988c6d20 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000001/N/313FB3847FA1/delegationpolicy.xml @@ -0,0 +1,42 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + ce4ba72b-d111-404f-95b5-313fb3847fa1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000001 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000003/N/313FB3847FA1/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000003/N/313FB3847FA1/delegationpolicy.xml new file mode 100644 index 00000000..bd807f23 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000003/N/313FB3847FA1/delegationpolicy.xml @@ -0,0 +1,42 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + ce4ba72b-d111-404f-95b5-313fb3847fa1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000003 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/313FB3847FA1/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/313FB3847FA1/delegationpolicy.xml new file mode 100644 index 00000000..f141c4be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/313FB3847FA1/delegationpolicy.xml @@ -0,0 +1,42 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + CE4BA72B-D111-404F-95B5-313FB3847FA1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000008 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/D90B16D527EA/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/D90B16D527EA/delegationpolicy.xml new file mode 100644 index 00000000..33d5a5d4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000008/N/D90B16D527EA/delegationpolicy.xml @@ -0,0 +1,79 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000008 + + + + + + + + read + + + + + + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000008 + + + + + + + + sign + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000009/N/313FB3847FA1/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000009/N/313FB3847FA1/delegationpolicy.xml new file mode 100644 index 00000000..d3d613c7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000009/N/313FB3847FA1/delegationpolicy.xml @@ -0,0 +1,79 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + ce4ba72b-d111-404f-95b5-313fb3847fa1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000009 + + + + + + + + read + + + + + + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + ce4ba72b-d111-404f-95b5-313fb3847fa1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000009 + + + + + + + + sign + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000010/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000010/delegationpolicy.xml new file mode 100644 index 00000000..2a995db1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000010/delegationpolicy.xml @@ -0,0 +1,42 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + CE4BA72B-D111-404F-95B5-313FB3847FA1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000012/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000012/delegationpolicy.xml new file mode 100644 index 00000000..4b0ea5a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/000000000012/delegationpolicy.xml @@ -0,0 +1,79 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + read + + + + + + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + sign + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/313FB3847FA1/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/313FB3847FA1/delegationpolicy.xml new file mode 100644 index 00000000..2a995db1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/313FB3847FA1/delegationpolicy.xml @@ -0,0 +1,42 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + CE4BA72B-D111-404F-95B5-313FB3847FA1 + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/D90B16D527EA/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/D90B16D527EA/delegationpolicy.xml new file mode 100644 index 00000000..4b0ea5a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/Instance/app_ttd_am-devtest-instancedelegation/000000000010/N/D90B16D527EA/delegationpolicy.xml @@ -0,0 +1,79 @@ + + + Delegation policy containing all delegated rights/actions from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource; app_ttd_am-devtest-instancedelegation + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + read + + + + + + + + Delegation of a right/action from urn:altinn:organization:uuid:0268b99a-5817-4bbf-9b62-d90b16d527ea to urn:altinn:person:uuid:ce4ba72b-d111-404f-95b5-313fb3847fa1, for the resource: app_ttd_am-devtest-instancedelegation, by: urn:altinn:resource:app_ttd_am-devtest-instancedelegation + + + + + 0268B99A-5817-4BBF-9B62-D90B16D527EA + + + + + + + + app_ttd_am-devtest-instancedelegation + + + + task_1 + + + + 00000000-0000-0000-0000-000000000010 + + + + + + + + sign + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/20001337/p50006078/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/20001337/p50006078/delegationpolicy.xml new file mode 100644 index 00000000..31b93334 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/20001337/p50006078/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; generic-access-resource + + + Delegation of a right/action from 50004222 to 50005545, for the resource: generic-access-resource, by user; 20000095 + + + + + 50005545 + + + + + + + + org1 + + + + app1 + + + + + + + + mainunit-delegated-action-to-keyroleunit + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50002203/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50002203/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..9a592391 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50002203/p50005545/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50002203 to 50005545, for the resource app_org1_app1; + + + Delegation of a right/action from 50002203 to 20000095, for the resource: app_org1_app1, by user; 20000095 + + + + + 50002203 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50003899/p20000095/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50003899/p20000095/delegationpolicy.xml new file mode 100644 index 00000000..6e1445b1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50003899/p20000095/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50003899 to 20000095, for the resource app_org1_app1; + + + Delegation of a right/action from 50003899 to 20000095, for the resource: app_org1_app1, by user; 20000095 + + + + + 50003899 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p20010727/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p20010727/delegationpolicy.xml new file mode 100644 index 00000000..560eaf9d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p20010727/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 20010727, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 20010727, for the resource: app_org1_app1, by user; 20010727 + + + + + 50005545 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50002203/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50002203/delegationpolicy.xml new file mode 100644 index 00000000..e14b8a33 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50002203/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50002203, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 50002203, for the resource: app_org1_app1, by user; 50002203 + + + + + 50005545 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50004226/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50004226/delegationpolicy.xml new file mode 100644 index 00000000..0b41a978 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/app_org1_app1/50005545/p50004226/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50004226, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 50004226, for the resource: app_org1_app1, by user; 50004226 + + + + + 50005545 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..4d5a93e6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; error/postgrewritechangefail + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; error/postgrewritechangefail, by user; 20001336 + + + + + 20001337 + + + + + + + + error + + + + postgrewritechangefail + + + + + + + + error + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/policy.xml new file mode 100644 index 00000000..2ddae495 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstoragegetleaselockfail/policy.xml @@ -0,0 +1,44 @@ + + + + + Placeholder policy + + + + + dagl + + + + + + + + error + + + + blobstoragegetleaselockfail + + + + + + + + error + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..4d5a93e6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; error/postgrewritechangefail + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; error/postgrewritechangefail, by user; 20001336 + + + + + 20001337 + + + + + + + + error + + + + postgrewritechangefail + + + + + + + + error + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/policy.xml new file mode 100644 index 00000000..5b34e4f4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/blobstorageleaselockwritefail/policy.xml @@ -0,0 +1,44 @@ + + + + + Placeholder policy + + + + + dagl + + + + + + + + error + + + + blobstorageleaselockwritefail + + + + + + + + error + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..00ab0677 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml @@ -0,0 +1,69 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; error/delegationeventfail + + + + + + + 20001336 + + + + + + + + error + + + + delegationeventfail + + + + + + + + read + + + + + + + + + + + + 20001336 + + + + + + + + error + + + + delegationeventfail + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/policy.xml new file mode 100644 index 00000000..24484e7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/delegationeventfail/policy.xml @@ -0,0 +1,56 @@ + + + + + Eksempel på samleregel som spesifiserer at både PRIV og DAGL m/sikkerhetsnivå; 2, for ressursen; error/delegationeventfail får tilgang til operasjonene; Read og Write + + + + + dagl + + + + + + priv + + + + + + + + error + + + + delegationeventfail + + + + + + + + read + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgregetcurrentfail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgregetcurrentfail/policy.xml new file mode 100644 index 00000000..335bd2a0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgregetcurrentfail/policy.xml @@ -0,0 +1,44 @@ + + + + + Placeholder policy + + + + + dagl + + + + + + + + error + + + + postgregetcurrentfail + + + + + + + + error + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..4d5a93e6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; error/postgrewritechangefail + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; error/postgrewritechangefail, by user; 20001336 + + + + + 20001337 + + + + + + + + error + + + + postgrewritechangefail + + + + + + + + error + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/policy.xml new file mode 100644 index 00000000..9d7c977c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/error/postgrewritechangefail/policy.xml @@ -0,0 +1,44 @@ + + + + + Placeholder policy + + + + + dagl + + + + + + + + error + + + + postgrewritechangefail + + + + + + + + error + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..cde47972 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/p50001336/delegationpolicy.xml @@ -0,0 +1,112 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + write + + + + + + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + org1 + + + + app1 + + + + event1 + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..54ae9a5b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,112 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + write + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app1 + + + + event1 + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/policy.xml new file mode 100644 index 00000000..f9670934 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app1/policy.xml @@ -0,0 +1,110 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..f3437e29 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/p50001336/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app2 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app2, by user; 20001337 + + + + + 50001336 + + + + + + + + org1 + + + + app2 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..98d7c15f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app2 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app2, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app2 + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/policy.xml new file mode 100644 index 00000000..716eb23c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app2/policy.xml @@ -0,0 +1,93 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org1 + + + + app2 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org1 + + + + app2 + + + + task1 + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app3/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app3/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..02ffeaae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app3/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,71 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app3 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app3, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app3 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app3, by user; 20001336 + + + + + 20001337 + + + + + + + + org1 + + + + app3 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app4/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app4/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..d9b65c12 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app4/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,71 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 20001337 + + + + + 20001337 + + + + + + + + org1 + + + + app4 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 20001337 + + + + + 20001337 + + + + + + + + org1 + + + + app4 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app5/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app5/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..d65711dd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org1/app5/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,5 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app5 + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001336/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001336/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..9bb8d7bd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001336/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001336 to 20001337, for resources on the app; org2/app1 + + + Delegation of a right/action from 50001336 to 20001337, for a resource on the app; org2/app1, by user; 20001336 + + + + + 20001337 + + + + + + + + org2 + + + + app1 + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..1a66d846 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org2/app1 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org2/app1, by user; 20001336 + + + + + 20001337 + + + + + + + + org2 + + + + app1 + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/policy.xml new file mode 100644 index 00000000..c28d1dae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app1/policy.xml @@ -0,0 +1,93 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org2 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org2 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/50001336/p50001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/50001336/p50001337/delegationpolicy.xml new file mode 100644 index 00000000..8c08e110 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/50001336/p50001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50001336 to 50001337, for resources on the app; org2/app2 + + + Delegation of a right/action from 50001336 to 50001337, for a resource on the app; org2/app2, by user; 20001336 + + + + + 50001337 + + + + + + + + org2 + + + + app2 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/policy.xml new file mode 100644 index 00000000..2cd04746 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app2/policy.xml @@ -0,0 +1,126 @@ + + + + + Eksempel på regel til Org subject, for egen action for eiere av appen + + + + + org2 + + + + + + + + org2 + + + + app2 + + + + + + + + appownerread + + + + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + + + org2 + + + + app2 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + + + org2 + + + + app2 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app3/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app3/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..6e810d7b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/org2/app3/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,71 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 20001337 + + + + + 20001337 + + + + + + + + org2 + + + + app3 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 20001337 + + + + + 20001337 + + + + + + + + org2 + + + + app3 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..0a3e8503 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,63 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the resource; resource2 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 20001336 + + + + + 20001337 + + + + + + + + resource1 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 20001336 + + + + + 20001337 + + + + + + + + resource1 + + + + + + + + write + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource2/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource2/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..87a328e9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resource2/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,63 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on resource2 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 20001336 + + + + + 20001337 + + + + + + + + resource2 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 20001336 + + + + + 20001337 + + + + + + + + resource2 + + + + + + + + write + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml new file mode 100644 index 00000000..cbe18f85 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; generic-access-resource + + + Delegation of a right/action from 50004222 to 50005545, for the resource: generic-access-resource, by user; 20000095 + + + + + 50005545 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + mainunit-delegated-action-to-keyroleunit + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..41885d38 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50002203 to 50005545, for the resource app_org1_app1; + + + Delegation of a right/action from 50002203 to 20000095, for the resource: app_org1_app1, by user; 20000095 + + + + + 50002203 + + + + + + + + app_org1_app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml new file mode 100644 index 00000000..1dd53702 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50003899 to 20000095, for the resource app_org1_app1; + + + Delegation of a right/action from 50003899 to 20000095, for the resource: app_org1_app1, by user; 20000095 + + + + + 50003899 + + + + + + + + app_org1_app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml new file mode 100644 index 00000000..e7dd075e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 20010727, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 20010727, for the resource: app_org1_app1, by user; 20010727 + + + + + 50005545 + + + + + + + + app_org1_app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml new file mode 100644 index 00000000..9d3a03e5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50002203, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 50002203, for the resource: app_org1_app1, by user; 50002203 + + + + + 50005545 + + + + + + + + app_org1_app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml new file mode 100644 index 00000000..ac0cc6d2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50004226, for the resource app_org1_app1; + + + Delegation of a right/action from 50005545 to 50004226, for the resource: app_org1_app1, by user; 50004226 + + + + + 50005545 + + + + + + + + app_org1_app1 + + + + + + + + read + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..9a53fdec --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/p50005545/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004221 to 50005545, for the resource; generic-access-resource + + + Delegation of a right/action from 50004221 to 50005545, for the resource: generic-access-resource, by user; 20000095 + + + + + 50005545 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + subunit-delegated-action-to-keyroleunit + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/u20000490/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/u20000490/delegationpolicy.xml new file mode 100644 index 00000000..553d858e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004221/u20000490/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004221 to 20000490, for the resource; generic-access-resource + + + Delegation of a right/action from 50004221 to 20000490, for the resource: generic-access-resource, by user; 20000095 + + + + + 20000490 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + subunit-delegated-action + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..9ca86bcc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/p50005545/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; generic-access-resource + + + Delegation of a right/action from 50004222 to 50005545, for the resource: generic-access-resource, by user; 20000095 + + + + + 50005545 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + mainunit-delegated-action-to-keyroleunit + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/u20000490/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/u20000490/delegationpolicy.xml new file mode 100644 index 00000000..bc9497cc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/generic-access-resource/50004222/u20000490/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 20000490, for the resource; generic-access-resource + + + Delegation of a right/action from 50004222 to 20000490, for the resource: generic-access-resource, by user; 20000095 + + + + + 20000490 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + mainunit-delegated-action + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml new file mode 100644 index 00000000..e72386ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004221/u20000490/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50004221 to 20000490, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50004221 to 20000490, for the resource: jks_audi_etron_gt, by user; 20000095 + + + + + 20000490 + + + + + + + + jks_audi_etron_gt + + + + + + + + race + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..66cde461 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/p50005545/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50004222 to 50005545, for the resource: jks_audi_etron_gt, by user; 20000095 + + + + + 50005545 + + + + + + + + jks_audi_etron_gt + + + + + + + + drive + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml new file mode 100644 index 00000000..a29a6c58 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50004222/u20000490/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 20000490, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50004222 to 20000490, for the resource: jks_audi_etron_gt, by user; 20000095 + + + + + 20000490 + + + + + + + + jks_audi_etron_gt + + + + + + + + park + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml new file mode 100644 index 00000000..b373e402 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50004221, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50005545 to 50004221, for the resource: jks_audi_etron_gt, by user; 20000490 + + + + + 50004221 + + + + + + + + jks_audi_etron_gt + + + + + + + + drive + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml new file mode 100644 index 00000000..50f6764a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 50004222, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50005545 to 50004222, for the resource: jks_audi_etron_gt, by user; 20000490 + + + + + 50004222 + + + + + + + + jks_audi_etron_gt + + + + + + + + drive + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/u20000095/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/u20000095/delegationpolicy.xml new file mode 100644 index 00000000..65e9487b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/jks_audi_etron_gt/50005545/u20000095/delegationpolicy.xml @@ -0,0 +1,34 @@ + + + Delegation policy containing all delegated rights/actions from 50005545 to 20000095, for the resource; jks_audi_etron_gt + + + Delegation of a right/action from 50005545 to 20000095, for the resource: jks_audi_etron_gt, by user; 20000490 + + + + + 20000095 + + + + + + + + jks_audi_etron_gt + + + + + + + + park + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/p50006078/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/p50006078/delegationpolicy.xml new file mode 100644 index 00000000..cbe18f85 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/p50006078/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; generic-access-resource + + + Delegation of a right/action from 50004222 to 50005545, for the resource: generic-access-resource, by user; 20000095 + + + + + 50005545 + + + + + + + + generic-access-resource + + + + org-delegation-subtask + + + + + + + + mainunit-delegated-action-to-keyroleunit + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..61122984 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,63 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the resource; resource1 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 20001336 + + + + + 20001337 + + + + + + + + resource1 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 20001336 + + + + + 20001337 + + + + + + + + resource1 + + + + + + + + write + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..87a328e9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1,63 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on resource2 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 20001336 + + + + + 20001337 + + + + + + + + resource2 + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 20001336 + + + + + 20001337 + + + + + + + + resource2 + + + + + + + + write + + + + + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/1000/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/1000/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..79224e60 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/1000/u20001337/delegationpolicy.xml @@ -0,0 +1,38 @@ + + + Delegation policy containing all delegated rights/actions from 1000 to 20001337, for resources on the app; skd/taxreport + + + Delegation of a right/action from 1000 to 20001337, for a resource on the app; skd/taxreport, by user; 20001336 + + + + + 20001337 + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001335/p50001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001335/p50001337/delegationpolicy.xml new file mode 100644 index 00000000..be9dc9bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001335/p50001337/delegationpolicy.xml @@ -0,0 +1,50 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001337 + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001335/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001335/delegationpolicy.xml new file mode 100644 index 00000000..babb1d44 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001335/delegationpolicy.xml @@ -0,0 +1,50 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; SKD/TaxReport + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; SKD/TaxReport, by user; 20001336 + + + + + 50001338 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..59cbba7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001336/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001338/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001338/delegationpolicy.xml new file mode 100644 index 00000000..59cbba7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/p50001338/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..cc6948fc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001336/delegationpolicy.xml @@ -0,0 +1,83 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; skd/taxreport + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; skd/taxreport, by user; 20001336 + + + + + 20001336 + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; skd/taxreport, by user; 20001336 + + + + + 20001336 + + + + + + + + skd + + + + taxreport + + + + + + + + write + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..b24b03c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1readDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1task1writeDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1event1read43 diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..59cbba7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001336/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001339/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001339/delegationpolicy.xml new file mode 100644 index 00000000..28911701 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001339/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001339 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001340/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001340/delegationpolicy.xml new file mode 100644 index 00000000..28911701 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001338/p50001340/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001339 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p20001337/delegationpolicy.xml new file mode 100644 index 00000000..b24b03c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1readDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1task1writeDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1event1read43 diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..59cbba7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/p50001336/delegationpolicy.xml @@ -0,0 +1,51 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1 + + + Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 20001336 + + + + + 50001336 + + + + + + + + skd + + + + taxreport + + + + + + + + sign + + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..90b74dd8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001336/delegationpolicy.xml @@ -0,0 +1,83 @@ + + + Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; skd/taxreport + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; skd/taxreport, by user; 20001336 + + + + + 20001336 + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Delegation of a right/action from 50001337 to 20001336, for a resource on the app; skd/taxreport, by user; 20001336 + + + + + 20001336 + + + + + + + + skd + + + + taxreport + + + + + + + + write + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..b24b03c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/50001339/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1readDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1task1writeDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1event1read43 diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/policy.xml new file mode 100644 index 00000000..f9670934 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/skd/taxreport/policy.xml @@ -0,0 +1,110 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonene; Read og Write + + + + + regna + + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + + + + + read + + + + + + write + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 2, for ressursen; org1/app1 får tilgang til operasjonen; Sign for Task: task1 + + + + + dagl + + + + + + priv + + + + + + + + org1 + + + + app1 + + + + task1 + + + + + + + + sign + + + + + + + + + + 4 + + + + + 3 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/repository-test-app/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/repository-test-app/policy.xml new file mode 100644 index 00000000..31df7c2b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/repository-test-app/policy.xml @@ -0,0 +1,230 @@ + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to instantiate a instance of a given app of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + instantiate + + + + + + read + + + + + + + + Rule that defines that user with role REGNA or DAGL can read and write for ttd/rf-0002 when it is in Task_1 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + Task_1 + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + read + + + + + + write + + + + + + + + Rule that defines that user with role REGNA or DAGL can delete instances of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + delete + + + + + + + + Rule that defines that org can write to instances of ttd/rf-0002 for any states + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + write + + + + + + + + Rule that defines that org can complete an instance of ttd/rf-0002 which state is at the end event. + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + complete + + + + + + + + + + 1 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/rf-0002/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/rf-0002/policy.xml new file mode 100644 index 00000000..31df7c2b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/input/ttd/rf-0002/policy.xml @@ -0,0 +1,230 @@ + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to instantiate a instance of a given app of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + instantiate + + + + + + read + + + + + + + + Rule that defines that user with role REGNA or DAGL can read and write for ttd/rf-0002 when it is in Task_1 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + Task_1 + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + read + + + + + + write + + + + + + + + Rule that defines that user with role REGNA or DAGL can delete instances of ttd/rf-0002 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + rf-0002 + + + + delete + + + + + + + + Rule that defines that org can write to instances of ttd/rf-0002 for any states + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + + + + + write + + + + + + + + Rule that defines that org can complete an instance of ttd/rf-0002 which state is at the end event. + + + + + ttd + + + + + + + + ttd + + + + rf-0002 + + + + EndEvent_1 + + + + + + + + complete + + + + + + + + + + 1 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..377f1ac1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/delegationeventfail/50001337/u20001336/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; error/delegationeventfail20001336errordelegationeventfailread20001336errordelegationeventfailwrite \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/postgregetcurrentfail/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/postgregetcurrentfail/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..e69de29b diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..30322d26 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; error/postgrewritechangefaileId="ade3b138-7fa4-4c83-9306-8ec4a72c2daa" Effect="Permit">Delegation of a right/action from 50001337 to 20001337, for a resource on the app; error/postgrewritechangefail, by user; 2000133620001337errorpostgrewritechangefailerror \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org/app/policy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org/app/policy.xml new file mode 100644 index 00000000..2e4ff72c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org/app/policy.xml @@ -0,0 +1,234 @@ + + + + + Eksempel på samleregel som spesifiserer at både REGNA og DAGL m/sikkerhetsnivå; 2, for ressursen; SKD/TaxReport får tilgang til operasjonene; Read, Write og Instantiate for Event; Tasks; FormFilling og Signing + + + + + regna + + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + + + skd + + + + taxreport + + + + formfilling + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + read + + + + + + write + + + + + + instantiate + + + + + + + + Eksempel på tilleggsregel som spesifiserer at bare DAGL m/sikkerhetsnivå; 3, for ressursen; SKD/TaxReport får tilgang til operasjonen; Sign både for Event; SluttEvent_1b + + + + + dagl + + + + + + + + skd + + + + taxreport + + + + signing + + + + + + + + sign + + + + + + + + Example rule that gives org nav and skd read right to the app inn all states + + + + + skd + + + + + + + + nav + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + Example rule that gives org skd write right for app inn all states + + + + + skd + + + + + + + + skd + + + + taxreport + + + + + + + + write + + + + + + + + Rule that gives systems with a specific API scope access to do read + + + + + altinn:platform:skd:amelding + + + + + + + + skd + + + + taxreport + + + + + + + + read + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..25cc37af --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50001336/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 50001336, for a resource on the app; org1/app1, by user; 2000133650001336org1app1event1read \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50004222/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50004222/delegationpolicy.xml new file mode 100644 index 00000000..183dbe76 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/p50004222/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 50004222, for the resource; org1/app1Delegation of a right/action from 50001337 to 50004222, for the resource: org1/app1, by user; 2000133750004222org1app1read \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..83b30484 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001336/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for the resource; org1/app1Delegation of a right/action from 50001337 to 20001336, for the resource: org1/app1, by user; 2000133720001336org1app1readDelegation of a right/action from 50001337 to 20001336, for the resource: org1/app1, by user; 2000133720001336org1app1write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..a0ebf7e8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1readDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1task1writeDelegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app1, by user; 2000133620001337org1app1event1readDelegation of a right/action from 50001337 to 20001337, for the resource: org1/app1, by user; 2000133620001337org1app1task1sign \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/p50001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/p50001336/delegationpolicy.xml new file mode 100644 index 00000000..76b8b2c1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/p50001336/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 50001336, for the resource; org1/app2Delegation of a right/action from 50001337 to 50001336, for the resource: org1/app2, by user; 2000133750001336org1app2write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..7ec9fe87 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app2/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for the resource; org1/app2Delegation of a right/action from 50001337 to 20001337, for the resource: org1/app2, by user; 2000133620001337org1app2read \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app3/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app3/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..fd9b27bd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app3/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the app; org1/app3Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app3, by user; 2000133620001337org1app3writeId="6f11dd0b-5e5d-4bd1-85f0-9796300dfded" Effect="Permit">Delegation of a right/action from 50001337 to 20001337, for a resource on the app; org1/app3, by user; 2000133620001337org1app3write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app4/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app4/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..ed5632ac --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org1/app4/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; org1/app1eId="7d015074-e91a-464a-a5f6-e4d4f58c3511" Effect="Permit">Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 2000133720001337org1app4write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001336/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001336/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..3b67436f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001336/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001336 to 20001337, for the resource; org2/app1Delegation of a right/action from 50001336 to 20001337, for the resource: org2/app1, by user; 2000133620001337org2app1read \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..3bced091 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for the resource; org2/app1Delegation of a right/action from 50001337 to 20001337, for the resource: org2/app1, by user; 2000133620001337org2app1read \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app2/50001336/p50001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app2/50001336/p50001337/delegationpolicy.xml new file mode 100644 index 00000000..524c43d4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app2/50001336/p50001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001336 to 50001337, for the resource; org2/app2Delegation of a right/action from 50001336 to 50001337, for the resource: org2/app2, by user; 2000133650001337org2app2write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app3/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app3/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..f012af71 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/org2/app3/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for resources on the app; org1/app1Delegation of a right/action from 50001337 to 20001336, for a resource on the app; org1/app1, by user; 2000133720001337org2app3write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml new file mode 100644 index 00000000..3a338175 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/20001337/p50006078/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50004222 to 50005545, for the resource; generic-access-resource \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml new file mode 100644 index 00000000..1435754e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50002203/p50005545/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50002203 to 50005545, for the resource app_org1_app1; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml new file mode 100644 index 00000000..2d2c89d1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50003899/p20000095/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50003899 to 20000095, for the resource app_org1_app1; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml new file mode 100644 index 00000000..c422e42c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p20010727/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 20010727, for the resource app_org1_app1; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml new file mode 100644 index 00000000..76fd2bab --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50002203/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 50002203, for the resource app_org1_app1; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml new file mode 100644 index 00000000..8a4f6cc2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/app_org1_app1/50005545/p50004226/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 50004226, for the resource app_org1_app1; \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/p50100004/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/p50100004/delegationpolicy.xml new file mode 100644 index 00000000..6f5d770e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/p50100004/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50002598 to 50100004, for the resource; generic-access-resourceDelegation of a right/action from 50002598 to 50100004, for the resource: generic-access-resource, by user; 2000049050100004generic-access-resourcereadDelegation of a right/action from 50002598 to 50100004, for the resource: generic-access-resource, by user; 2000049050100004generic-access-resourcewrite \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..08a60602 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50002598/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50002598 to 20001337, for the resource; generic-access-resourceDelegation of a right/action from 50002598 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourcereadDelegation of a right/action from 50002598 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourcewrite \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50004221/p50004222/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50004221/p50004222/delegationpolicy.xml new file mode 100644 index 00000000..8ad23737 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50004221/p50004222/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50004221 to 50004222, for the resource; generic-access-resourceDelegation of a right/action from 50004221 to 50004222, for the resource: generic-access-resource, by user; 2000049050004222generic-access-resourceorg-delegation-subtasksubunit-delegated-actionDelegation of a right/action from 50004221 to 50004222, for the resource: generic-access-resource, by user; 2000049050004222generic-access-resourceorg-delegation-subtasksubunit-delegated-action-to-keyroleunitDelegation of a right/action from 50004221 to 50004222, for the resource: generic-access-resource, by user; 2000049050004222generic-access-resourceorg-delegation-subtaskmainunit-delegated-actionDelegation of a right/action from 50004221 to 50004222, for the resource: generic-access-resource, by user; 2000049050004222generic-access-resourceorg-delegation-subtaskmainunit-delegated-action-to-keyroleunit \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/SystemUser16c1f2f6-9e00-4922-b16d-74c46d948e61/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/SystemUser16c1f2f6-9e00-4922-b16d-74c46d948e61/delegationpolicy.xml new file mode 100644 index 00000000..1662ebfe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/SystemUser16c1f2f6-9e00-4922-b16d-74c46d948e61/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 16c1f2f6-9e00-4922-b16d-74c46d948e61, for the resource; generic-access-resourceDelegation of a right/action from 50005545 to 16c1f2f6-9e00-4922-b16d-74c46d948e61, for the resource: generic-access-resource, by user; 2000049016c1f2f6-9e00-4922-b16d-74c46d948e61generic-access-resourceorg-delegation-subtaskmainunit-delegated-action \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..4e21937a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 20001337, for the resource; generic-access-resourceDelegation of a right/action from 50005545 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourceorg-delegation-subtasksubunit-delegated-actionDelegation of a right/action from 50005545 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourceorg-delegation-subtasksubunit-delegated-action-to-keyroleunitDelegation of a right/action from 50005545 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourceorg-delegation-subtaskmainunit-delegated-actionDelegation of a right/action from 50005545 to 20001337, for the resource: generic-access-resource, by user; 2000049020001337generic-access-resourceorg-delegation-subtaskmainunit-delegated-action-to-keyroleunitributeDesignator AttributeId="urn:altinn:userid" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />generic-access-resourceorg-delegation-subtaskmainunit-delegated-action-to-keyroleunit \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20010727/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20010727/delegationpolicy.xml new file mode 100644 index 00000000..4a58d47a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/generic-access-resource/50005545/u20010727/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 20010727, for the resource; generic-access-resourceDelegation of a right/action from 50005545 to 20010727, for the resource: generic-access-resource, by user; 2000009520010727generic-access-resourceadmai-delegated-action \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml new file mode 100644 index 00000000..53f96bee --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004221/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 50004221, for the resource; jks_audi_etron_gt \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml new file mode 100644 index 00000000..f9cde840 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/jks_audi_etron_gt/50005545/p50004222/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 50004222, for the resource; jks_audi_etron_gtDelegation of a right/action from 50005545 to 50004222, for the resource: jks_audi_etron_gt, by user; 2000049050004222jks_audi_etron_gtdriveDelegation of a right/action from 50005545 to 50004222, for the resource: jks_audi_etron_gt, by user; 2000049050004222jks_audi_etron_gtparkDelegation of a right/action from 50005545 to 50004222, for the resource: jks_audi_etron_gt, by user; 2000049050004222jks_audi_etron_gtrace \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001336/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001336/delegationpolicy.xml new file mode 100644 index 00000000..d397ab52 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001336/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001336, for the resource; resource1Delegation of a right/action from 50001337 to 20001336, for the resource: resource1, by user; 2000133720001336resource1readDelegation of a right/action from 50001337 to 20001336, for the resource: resource1, by user; 2000133720001336resource1write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..80213227 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource1/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on the resource; resource1Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 2000133620001337resource1readDelegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource1, by user; 2000133620001337resource1write \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml new file mode 100644 index 00000000..8b805298 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/resourceregistry/resource2/50001337/u20001337/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50001337 to 20001337, for resources on resource2Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 2000133620001337resource2readeId="99e5cced-3bcb-42b6-9089-63c834f89e77" Effect="Permit">Delegation of a right/action from 50001337 to 20001337, for a resource on the resource; resource2, by user; 2000133620001337resource2writeDelegation of a right/action from 50001337 to 20001337, for the resource: resource2, by user; 20001337resource2scopeaccess \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/ttd/apps-test/50005545/SystemUser9d569a55-d5ce-4914-bbf8-ca3474458604/delegationpolicy.xml b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/ttd/apps-test/50005545/SystemUser9d569a55-d5ce-4914-bbf8-ca3474458604/delegationpolicy.xml new file mode 100644 index 00000000..26c5cc83 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Data/blobs/output/ttd/apps-test/50005545/SystemUser9d569a55-d5ce-4914-bbf8-ca3474458604/delegationpolicy.xml @@ -0,0 +1 @@ +Delegation policy containing all delegated rights/actions from 50005545 to 9d569a55-d5ce-4914-bbf8-ca3474458604, for the resource; ttd/apps-testDelegation of a right/action from 50005545 to 9d569a55-d5ce-4914-bbf8-ca3474458604, for the resource: ttd/apps-test, by user; 200004909d569a55-d5ce-4914-bbf8-ca3474458604ttdapps-testread \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/PostgresFixture.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/PostgresFixture.cs new file mode 100644 index 00000000..6d08072a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/PostgresFixture.cs @@ -0,0 +1,404 @@ +using System.Collections.Concurrent; +using System.Reflection; +using Altinn.AccessManagement.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Persistence; +using Altinn.AccessManagement.Persistence.Configuration; +using Altinn.AccessManagement.Tests.Seeds; +using Microsoft.Extensions.Options; +using Npgsql; +using Testcontainers.PostgreSql; +using Xunit.Sdk; +using Yuniql.Core; + +namespace Altinn.AccessManagement.Tests.Fixtures; + +/// +/// For running exclusively database tests. Before each tests, method must be called in order +/// to create a new database that runs isolated for that tests. This should be used as an +/// +public class PostgresFixture : IAsyncLifetime +{ + private ConsoleTraceService Tracer { get; } = new() + { + IsDebugEnabled = true + }; + + /// + /// Creates a new database and runs the migrations + /// + /// + public PostgresDatabase New() + { + var db = PostgresServer.NewDatabase(); + var configuration = new Yuniql.AspNetCore.Configuration + { + Platform = SUPPORTED_DATABASES.POSTGRESQL, + Workspace = Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Migration"), + ConnectionString = db.Admin.ToString(), + IsAutoCreateDatabase = false, + }; + + var dataService = new Yuniql.PostgreSql.PostgreSqlDataService(Tracer); + var bulkImportService = new Yuniql.PostgreSql.PostgreSqlBulkImportService(Tracer); + var migrationServiceFactory = new MigrationServiceFactory(Tracer); + var migrationService = migrationServiceFactory.Create(dataService, bulkImportService); + ConfigurationHelper.Initialize(configuration); + migrationService.Run(); + return db; + } + + /// + public Task DisposeAsync() + { + PostgresServer.StopUsing(this); + return Task.CompletedTask; + } + + /// + public Task InitializeAsync() + { + PostgresServer.StartUsing(this); + return Task.CompletedTask; + } +} + +/// +/// Postgres singleton that creates a npg sql server and creates a new database for each test +/// +public static class PostgresServer +{ + private static PostgreSqlContainer Server { get; } = new PostgreSqlBuilder() + .WithCleanUp(true) + .WithImage("docker.io/postgres:16.1-alpine") + .Build(); + + private static Mutex Mutex { get; } = new(); + + private static ConcurrentDictionary Consumers { get; } = new(); + + private static int DatabaseInstance { get; set; } = 0; + + /// + /// Database Password + /// + public static readonly string DbPassword = "Password"; + + /// + /// Database Username + /// + public static readonly string DbUserName = "platform_authorization"; + + /// + /// Database Admin + /// + public static readonly string DbAdminName = "platform_authorization_admin"; + + /// + /// Must be called before getting creating databases + /// + /// this + public static void StartUsing(object consumer) + { + Mutex.WaitOne(); + try + { + Consumers.AddOrUpdate(consumer, 1, (consumer, current) => + { + return ++current; + }); + + if (Consumers.Values.Sum() == 1) + { + Server.StartAsync().Wait(); + var result = Server.ExecScriptAsync($@" + DO + $$ + BEGIN + IF NOT EXISTS (SELECT * FROM pg_user WHERE usename IN ('{DbUserName}', '{DbAdminName}')) THEN + CREATE USER {DbUserName} WITH PASSWORD '{DbPassword}'; + CREATE USER {DbAdminName} WITH PASSWORD '{DbPassword}'; + ALTER ROLE {DbUserName} LOGIN INHERIT; + ALTER ROLE {DbAdminName} LOGIN SUPERUSER INHERIT; + END IF; + END + $$;").Result; + + if (result.ExitCode != 0 || !string.IsNullOrEmpty(result.Stderr)) + { + throw new XunitException($"Failed to create users. Exitcode {result.ExitCode}, Error Message ${result.Stderr}"); + } + } + } + finally + { + Mutex.ReleaseMutex(); + } + } + + /// + /// Should be called after tests are executed + /// + public static void StopUsing(object consumer) + { + Mutex.WaitOne(); + try + { + Consumers.AddOrUpdate(consumer, 1, (consumer, current) => + { + if (current > 0) + { + return --current; + } + + return 0; + }); + + if (Consumers.Values.Sum() == 0) + { + Server.StopAsync().Wait(); + } + } + finally + { + Mutex.ReleaseMutex(); + } + } + + /// + /// Creates a new database and connection string + /// + public static PostgresDatabase NewDatabase() + { + Mutex.WaitOne(); + try + { + var dbname = $"test_{DatabaseInstance++}"; + Server.ExecScriptAsync($"CREATE DATABASE {dbname};").Wait(); + return new(dbname, Server.GetConnectionString()); + } + finally + { + Mutex.ReleaseMutex(); + } + } +} + +/// +/// Container for persisting connections string and database name +/// +public class PostgresDatabase(string dbname, string connectionString) : IOptions +{ + /// + /// Database name + /// + public string Dbname { get; } = dbname; + + /// + /// Creates + /// + public IDelegationMetadataRepository DelegationMetadata => + new DelegationMetadataRepository(new NpgsqlDataSourceBuilder(User.ToString()).Build()); + + /// + /// Creates + /// + public IResourceMetadataRepository ResourceMetadata => new ResourceMetadataRepository(this); + + /// + /// Admin name + /// + public NpgsqlConnectionStringBuilder Admin { get; } = new NpgsqlConnectionStringBuilder(connectionString) + { + Timeout = 3, + Database = dbname, + Username = PostgresServer.DbAdminName, + Password = PostgresServer.DbPassword, + IncludeErrorDetail = true, + }; + + /// + /// User name + /// + public NpgsqlConnectionStringBuilder User { get; } = new NpgsqlConnectionStringBuilder(connectionString) + { + Timeout = 3, + Database = dbname, + Username = PostgresServer.DbUserName, + Password = PostgresServer.DbPassword, + IncludeErrorDetail = true, + }; + + /// + /// Implements + /// + public PostgreSQLSettings Value => new() + { + ConnectionString = User.ToString(), + AuthorizationDbPwd = User.Password + }; +} + +/// +/// RepositoryContainer +/// +public class RepositoryContainer(IDelegationMetadataRepository delegationMetadataRepository, IResourceMetadataRepository resourceMetadataRepository) +{ + /// + /// DelegationMetadataRepository + /// + public IDelegationMetadataRepository DelegationMetadataRepository { get; } = delegationMetadataRepository; + + /// + /// ResourceMetadataRepository + /// + public IResourceMetadataRepository ResourceMetadataRepository { get; } = resourceMetadataRepository; +} + +/// +/// Build a Delegation Change +/// +public static class DelegationChangeComposer +{ + /// + /// Creates a new delegation + /// + public static DelegationChange New(params Action[] actions) + { + var delegation = new DelegationChange() + { + DelegationChangeType = DelegationChangeType.Grant + }; + + foreach (var action in actions) + { + action(delegation); + } + + if (delegation.PerformedByUserId == null) + { + delegation.PerformedByUserId = delegation.CoveredByUserId == null ? 1 : PersonSeeds.Paula.PartyId; + } + + if (delegation.PerformedByPartyId == null && delegation.CoveredByPartyId != null) + { + delegation.PerformedByPartyId = delegation.CoveredByPartyId; + } + + if (string.IsNullOrEmpty(delegation.BlobStoragePolicyPath)) + { + delegation.BlobStoragePolicyPath = $"undefined"; + } + + if (string.IsNullOrEmpty(delegation.BlobStorageVersionId)) + { + delegation.BlobStorageVersionId = "v1"; + } + + return delegation; + } + + /// + /// sets the field to given delegation + /// + /// delegation + public static void WithDelegationChangeRevokeLast(DelegationChange delegation) + { + delegation.DelegationChangeType = DelegationChangeType.RevokeLast; + } + + /// + /// Sets the field to given "resource" + /// + /// resource + public static Action WithResource(IAccessManagementResource resource) => delegation => + { + if (resource.Resource.ResourceType == ResourceType.AltinnApp) + { + var org = resource.Resource.AuthorizationReference.FirstOrDefault(attr => attr.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute); + var app = resource.Resource.AuthorizationReference.FirstOrDefault(attr => attr.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute); + delegation.ResourceId = $"{org.Value}/{app.Value}"; + } + else + { + delegation.ResourceId = resource.Resource.Identifier; + } + + delegation.ResourceType = resource.Resource.ResourceType.ToString(); + }; + + /// + /// Sets the field to given "profile" + /// + /// user profile + /// + public static Action WithToUser(IUserProfile profile) => delegation => + { + delegation.CoveredByUserId = profile.UserProfile.UserId; + }; + + /// + /// Sets the field to given "profile" + /// + /// manual set user ID + /// + public static Action WithToUser(int userId) => delegation => + { + delegation.CoveredByUserId = userId; + }; + + /// + /// Sets the field to given party + /// + /// party + public static Action WithToParty(IParty party) => delegation => + { + delegation.CoveredByPartyId = party.Party.PartyId; + }; + + /// + /// Sets the field to given party + /// + /// manually sets Party ID + public static Action WithToParty(int partyId) => delegation => + { + delegation.CoveredByPartyId = partyId; + }; + + /// + /// Sets the field to given party + /// + public static Action WithFrom(IParty party) => delegation => + { + delegation.OfferedByPartyId = party.Party.PartyId; + }; + + /// + /// Sets the field to given party + /// + public static Action WithFrom(int partyId) => delegation => + { + delegation.OfferedByPartyId = partyId; + }; + + /// + /// Sets the field to given userId + /// + /// User profile + public static Action WithPerformedByUserProfile(IUserProfile profile) => delegation => + { + delegation.PerformedByUserId = profile.UserProfile.UserId; + }; + + /// + /// Sets the field to given party + /// + /// party + public static Action WithPerformedByParty(IParty party) => delegation => + { + delegation.PerformedByPartyId = party.Party.PartyId; + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/WebApplicationFixture.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/WebApplicationFixture.cs new file mode 100644 index 00000000..51ad5ea4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Fixtures/WebApplicationFixture.cs @@ -0,0 +1,143 @@ +using System.Reflection; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Tests.Contexts; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Scenarios; +using Altinn.Common.AccessToken.Services; +using Altinn.Common.PEP.Interfaces; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Tests.Fixtures; + +/// +/// Test server for Access management API +/// +public class WebApplicationFixture : WebApplicationFactory, IAsyncLifetime +{ + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + var db = PostgresServer.NewDatabase(); + + var appsettings = new ConfigurationBuilder() + .AddJsonFile("appsettings.test.json") + .AddInMemoryCollection(new Dictionary + { + ["PostgreSQLSettings:AdminConnectionString"] = db.Admin.ToString(), + ["PostgreSQLSettings:ConnectionString"] = db.User.ToString(), + ["PostgreSQLSettings:EnableDBConnection"] = "true", + ["Logging:LogLevel:*"] = "Error", + }); + + builder.UseConfiguration(appsettings.Build()); + } + + /// + /// Creates a specific mock context based on given scenarios. + /// + /// list of scenarios + public Host ConfigureHostBuilderWithScenarios(params Scenario[] scenarios) + { + var mock = new MockContext(); + var host = CreateHost(scenarios, mock); + var client = host.CreateClient(); + + foreach (var header in mock.HttpHeaders) + { + client.DefaultRequestHeaders.Add(header.Key, header.Value); + } + + return new Host(host, client, mock); + } + + private WebApplicationFactory CreateHost(Scenario[] scenarios, MockContext mock) + { + return WithWebHostBuilder(builder => + { + foreach (var scenario in scenarios) + { + scenario(mock); + } + + mock.Parties = mock.Parties.DistinctBy(party => party.PartyId).ToList(); + mock.UserProfiles = mock.UserProfiles.DistinctBy(userProfile => userProfile.UserId).ToList(); + mock.Resources = mock.Resources.DistinctBy(resource => resource.Identifier).ToList(); + + builder.ConfigureServices(services => + { + services.AddSingleton(); + }); + + builder.ConfigureTestServices(services => + { + services.AddSingleton(mock); + AddMockClients(services); + }); + }); + } + + private static void AddMockClients(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(new DelegationChangeEventQueueMock()); + } + + /// + /// Signalize usage of postgres server + /// + public Task InitializeAsync() + { + PostgresServer.StartUsing(this); + return Task.CompletedTask; + } + + /// + /// Removes itself as consumer of the postgres server + /// + public new Task DisposeAsync() + { + PostgresServer.StopUsing(this); + return Task.CompletedTask; + } +} + +/// +/// Container for the test server API and HTTP Client for sending requests +/// +public class Host(WebApplicationFactory api, HttpClient client, MockContext mock) +{ + public MockContext Mock { get; set; } = mock; + + /// + /// Test server + /// + public WebApplicationFactory Api { get; } = api; + + /// + /// Http Client with predefined base route to the API + /// + public HttpClient Client { get; } = client; + + /// + /// Repository Container that contains database implementation + /// + public RepositoryContainer Repository => Api.Services.GetRequiredService(); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/HealthCheckTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/HealthCheckTests.cs new file mode 100644 index 00000000..257e51a9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/HealthCheckTests.cs @@ -0,0 +1,47 @@ +using System.Net; +using Altinn.AccessManagement.Health; +using Altinn.AccessManagement.Tests.Fixtures; + +namespace Altinn.AccessManagement.Tests.Health +{ + /// + /// Health check + /// + /// + public class HealthCheckTests(WebApplicationFixture fixture) : IClassFixture + { + public WebApplicationFixture Fixture { get; } = fixture; + + /// + /// Verify that component responds on health check + /// + /// + [Fact] + public async Task VerifyHealthCheck_OK() + { + HttpClient client = Fixture.ConfigureHostBuilderWithScenarios().Client; + + var request = new HttpRequestMessage(HttpMethod.Get, "/health"); + + HttpResponseMessage response = await client.SendAsync(request); + Assert.Equal("Healthy", await response.Content.ReadAsStringAsync()); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + /// + /// Verify that component responds on health check + /// + /// + [Fact] + public async Task VerifyAliveCheck_OK() + { + HttpClient client = Fixture.ConfigureHostBuilderWithScenarios().Client; + + var request = new HttpRequestMessage(HttpMethod.Get, "/alive"); + + HttpResponseMessage response = await client.SendAsync(request); + await response.Content.ReadAsStringAsync(); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/DelegationHelperTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/DelegationHelperTest.cs new file mode 100644 index 00000000..1b08ae47 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/DelegationHelperTest.cs @@ -0,0 +1,502 @@ +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Authorization.ABAC.Xacml; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Moq; + +namespace Altinn.AccessManagement.Tests.Helpers +{ + /// + /// Test class for + /// + public class DelegationHelperTest + { + private PolicyRetrievalPointMock _prpMock = new PolicyRetrievalPointMock(new HttpContextAccessor(), new Mock>().Object); + + /// + /// Scenario: + /// Tests the SortRulesByDelegationPolicyPath function + /// Input: + /// List of un ordered rules for delegation of 3 different apps to/from the same set of OfferedBy/CoveredBy parties + /// Expected Result: + /// Dictionary with rules sorted by the path of the 3 delegation policy files + /// Success Criteria: + /// Dictionary with the expected keys (policy paths) and values (sorted rules for each file) + /// + [Fact] + public void SortRulesByDelegationPolicyPath_ThreeAppsSameOfferedByAndCoveredBy_Success() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "App2"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "write", "org1", "app1", "task1"), // Should be sorted together with the first rule + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", task: null, "event1") // Should be sorted together with the first rule + }; + + Dictionary> expected = new Dictionary>(); + expected.Add($"org1/app1/{offeredByPartyId}/u{coveredBy}/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "write", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", task: null, "event1") + }); + expected.Add($"org2/app1/{offeredByPartyId}/u{coveredBy}/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1") + }); + expected.Add($"org1/App2/{offeredByPartyId}/u{coveredBy}/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "App2") + }); + + // Act + Dictionary> actual = DelegationHelper.SortRulesByDelegationPolicyPath(unsortedRules, out List unsortables); + + // Assert + Assert.NotNull(actual); + Assert.Empty(unsortables); + + Assert.Equal(expected.Keys.Count, actual.Keys.Count); + foreach (string expectedPathKey in expected.Keys) + { + Assert.True(actual.ContainsKey(expectedPathKey)); + Assert.Equal(expected[expectedPathKey].Count, actual[expectedPathKey].Count); + AssertionUtil.AssertEqual(expected[expectedPathKey], actual[expectedPathKey]); + } + } + + /// + /// Scenario: + /// Tests the SortRulesByDelegationPolicyPath function + /// Input: + /// List of un ordered rules for delegation of the same apps from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// Expected Result: + /// Dictionary with rules sorted by the path of the 3 delegation policy files + /// Success Criteria: + /// Dictionary with the expected keys (policy paths) and values (sorted rules for each file) + /// + [Fact] + public void SortRulesByDelegationPolicyPath_OneAppSameOfferedBy_ThreeCoveredBy_Success() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001331", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", null, "event1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "50001333", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1") // Should be sorted together with the first rule + }; + + Dictionary> expected = new Dictionary>(); + expected.Add($"org1/app1/{offeredByPartyId}/u20001337/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1") + }); + expected.Add($"org1/app1/{offeredByPartyId}/u20001331/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001331", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", null, "event1"), + }); + expected.Add($"org1/app1/{offeredByPartyId}/p50001333/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "50001333", AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute, "read", "org1", "app1"), + }); + + // Act + Dictionary> actual = DelegationHelper.SortRulesByDelegationPolicyPath(unsortedRules, out List unsortables); + + // Assert + Assert.NotNull(actual); + Assert.Empty(unsortables); + + Assert.Equal(expected.Keys.Count, actual.Keys.Count); + foreach (string expectedPathKey in expected.Keys) + { + Assert.True(actual.ContainsKey(expectedPathKey)); + Assert.Equal(expected[expectedPathKey].Count, actual[expectedPathKey].Count); + AssertionUtil.AssertEqual(expected[expectedPathKey], actual[expectedPathKey]); + } + } + + /// + /// Scenario: + /// Tests the SortRulesByDelegationPolicyPath function + /// Input: + /// List of un ordered rules for delegation of the same apps from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// Expected Result: + /// Dictionary with rules sorted by the path of the 3 delegation policy files + /// Success Criteria: + /// Dictionary with the expected keys (policy paths) and values (sorted rules for each file) + /// + [Fact] + public void SortRulesByDelegationPolicyPath_Unsortables_Success() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1") + }; + + Dictionary> expected = new Dictionary>(); + expected.Add($"org1/app1/{offeredByPartyId}/u20001337/delegationpolicy.xml", new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1") + }); + + List expectedUnsortable = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, "20001337", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", null, "app1") + }; + + // Act + Dictionary> actual = DelegationHelper.SortRulesByDelegationPolicyPath(unsortedRules, out List unsortables); + + // Assert + Assert.NotNull(actual); + + Assert.Equal(expectedUnsortable.Count, unsortables.Count); + AssertionUtil.AssertEqual(expectedUnsortable, unsortables); + + Assert.Equal(expected.Keys.Count, actual.Keys.Count); + foreach (string expectedPathKey in expected.Keys) + { + Assert.True(actual.ContainsKey(expectedPathKey)); + Assert.Equal(expected[expectedPathKey].Count, actual[expectedPathKey].Count); + AssertionUtil.AssertEqual(expected[expectedPathKey], actual[expectedPathKey]); + } + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns true when it finds a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing read and write rules for org1/app1, and a API Rule model for write + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_True() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "write", "org1", "app1"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "app1"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.True(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns true when it finds a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing read and write rules for org1/app1, and a API Rule model for read + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_PolicyResourcesOutOfOrder_True() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org1", "unorderedresources"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "unorderedresources"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.True(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns true when it finds a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing a single rule for spanning multiple different resources and actions + /// A rule for one of the last combinations for action and resource (eat, banana) + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_SingleComplexRulePolicy_True() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "eat", "org1", "singlecomplexrule", appresource: "banana"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "singlecomplexrule"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.True(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns true when it finds a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing XacmlRule for sign on task1 for org1/app1, and a API Rule model representation for the same rule + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_SignForTask_True() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "sign", "org1", "app1", task: "task1"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "app1"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.True(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns false when it does not find a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing read and write rules for org1/app1, and a API Rule model for sign + /// Expected Result: + /// False + /// Success Criteria: + /// Rule is not found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_InvalidAction_False() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "sign", "org1", "app1"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "app1"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.False(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns false when it does not find a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing read and write rules for org1/app1, and a API Rule model for read but for org2/app1 + /// Expected Result: + /// False + /// Success Criteria: + /// Rule is not found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_InvalidOrg_False() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org2", "app1"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "app1"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.False(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns false when it does not find a given API rule model as a XacmlRule in a XacmlPolicy + /// Input: + /// A XacmlPolicy containing read and write rules for org1/app1, and a API Rule model for read but for org1/app2 + /// Expected Result: + /// False + /// Success Criteria: + /// Rule is not found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_InvalidApp_False() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "read", "org2", "app1"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "app1"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.False(actual); + } + + /// + /// Scenario: + /// Tests that the PolicyContainsMatchingRule function returns false when the App policy does not contain org/app level resource specification. + /// Input: + /// A XacmlPolicy containing no rules with resource specification on org/app level (all resources are more specific e.g incl task/appresource) + /// A rule which match action but not a complete resource match + /// Expected Result: + /// False + /// Success Criteria: + /// Rule is not found and expected result is returned + /// + [Fact] + public async Task PolicyContainsMatchingRule_PolicyContainsRule_PolicyWithoutAppLevelResource_False() + { + // Arrange + Rule rule = TestDataUtil.GetRuleModel(20001337, 50001337, "20001336", AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute, "eat", "org1", "singlecomplexrule"); + XacmlPolicy policy = await _prpMock.GetPolicyAsync("org1", "singlecomplexrule"); + + // Act + bool actual = DelegationHelper.PolicyContainsMatchingRule(policy, rule); + + // Assert + Assert.False(actual); + } + + /// + /// Scenario: + /// Given an AttributeMatch list parse out the type and Identificator from the list + /// Input: + /// Attribute match list containing a SystemUser urn. + /// Expected Result: + /// True and Type set to UuidType.SystemUser and Id set to correct Uuid + /// Success Criteria: + /// Rule is not found and expected result is returned + /// + [Fact] + public void ParseSystemUserTypeAndIdentifierFromUrn_Succsess() + { + string idString = "56224CB5-E8BF-4569-86EC-6CF104B63F74"; + List input = new List + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.SystemUserUuid, Value = idString } + }; + + bool result = DelegationHelper.TryGetPerformerFromAttributeMatches(input, out string id, out UuidType type); + Assert.True(result); + Assert.Equal(UuidType.SystemUser, type); + Assert.Equal(idString, id); + } + + /// + /// Scenario: + /// Given an AttributeMatch list parse out the type and Identificator from the list + /// Input: + /// Attribute match list containing a Organization urn. + /// Expected Result: + /// returns True and output Type set to UuidType.Organization and Id set to correct Uuid + /// + [Fact] + public void ParseOrganizationTypeAndIdentifierFromUrn_Succsess() + { + string idString = "9867756B-625E-4904-815E-889A5824C33C"; + List input = new List + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrganizationUuid, Value = idString } + }; + + bool result = DelegationHelper.TryGetPerformerFromAttributeMatches(input, out string id, out UuidType type); + Assert.True(result); + Assert.Equal(UuidType.Organization, type); + Assert.Equal(idString, id); + } + + /// + /// Scenario: + /// Given an AttributeMatch list parse out the type and Identificator from the list + /// Input: + /// Attribute match list containing a Person urn. + /// Expected Result: + /// returns True and output Type set to UuidType.Person and Id set to correct Uuid + /// + [Fact] + public void ParsePersonTypeAndIdentifierFromUrn_Succsess() + { + string idString = "7514B58F-ABBC-42F7-98EB-11BCE123E757"; + List input = new List + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonUuid, Value = idString } + }; + + bool result = DelegationHelper.TryGetPerformerFromAttributeMatches(input, out string id, out UuidType type); + Assert.True(result); + Assert.Equal(UuidType.Person, type); + Assert.Equal(idString, id); + } + + /// + /// Scenario: + /// Given an AttributeMatch list parse out the type and Identificator from the list + /// Input: + /// Attribute match list containing a EnterpriseUser urn. + /// Expected Result: + /// returns True and output Type set to UuidType.EnterpriseUser and Id set to correct Uuid + /// + [Fact] + public void ParseEnterpriseUserTypeAndIdentifierFromUrn_Succsess() + { + string idString = "1CF6DFC5-31BC-48F4-A5ED-48711DC0FF4B"; + List input = new List + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.EnterpriseUserUuid, Value = idString } + }; + + bool result = DelegationHelper.TryGetPerformerFromAttributeMatches(input, out string id, out UuidType type); + Assert.True(result); + Assert.Equal(UuidType.EnterpriseUser, type); + Assert.Equal(idString, id); + } + + /// + /// Scenario: + /// Given an AttributeMatch list parse out the type and Identificator from the list + /// Input: + /// Attribute match list containing a EnterpriseUser urn. + /// Expected Result: + /// returns False and output Type set to UuidType.NotSpecified and Id set to NULL + /// + [Fact] + public void ParseSsnTypeAndIdentifierFromUrn_Failure() + { + string idString = "01010149978"; + List input = new List + { + new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PersonId, Value = idString } + }; + + bool result = DelegationHelper.TryGetPerformerFromAttributeMatches(input, out string id, out UuidType type); + Assert.False(result); + Assert.Equal(UuidType.NotSpecified, type); + Assert.Null(id); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/Extensions/EnumExtensionTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/Extensions/EnumExtensionTest.cs new file mode 100644 index 00000000..2f8bd30b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/Extensions/EnumExtensionTest.cs @@ -0,0 +1,17 @@ +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Enums; + +namespace Altinn.AccessManagement.Tests.Helpers.Extensions +{ + public class EnumExtensionTest + { + [Fact] + public void ConvertEnumMemberValueStringToEnum() + { + string enumMemberValueString = "urn:altinn:person:uuid"; + bool result = EnumExtensions.EnumValue(enumMemberValueString, out UuidType enumValue); + Assert.True(result); + Assert.Equal(UuidType.Person, enumValue); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/PolicyHelperTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/PolicyHelperTest.cs new file mode 100644 index 00000000..6e05c651 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Helpers/PolicyHelperTest.cs @@ -0,0 +1,169 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Authorization.ABAC.Xacml; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Helpers +{ + /// + /// Test class for + /// + public class PolicyHelperTest + { + private readonly PolicyRetrievalPointMock _policyRetrievalPointMock; + + /// + /// Constructor setting up dependencies + /// + public PolicyHelperTest() + { + _policyRetrievalPointMock = new PolicyRetrievalPointMock(); + } + + /// + /// Scenario: + /// Tests that the GetAltinnAppsPolicyPath method returns a correct path based on the input parameters. + /// Input: + /// Org and app from the AltinnAppId. + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public void GetAltinnAppsPolicyPath() + { + // Arrange + string expected = $"org1/app1/policy.xml"; + + // Act + string actual = PolicyHelper.GetAltinnAppsPolicyPath("org1", "app1"); + + // Assert + Assert.Equal(expected, actual); + } + + /// + /// Scenario: + /// Tests that the GetAltinnAppsPolicyPath method returns a correct path based on the input parameters. + /// Input: + /// Org and app from the AltinnAppId. + /// Expected Result: + /// True + /// Success Criteria: + /// Rule is found and expected result is returned + /// + [Fact] + public async Task GetRolesWithAccess() + { + // Arrange + XacmlPolicy policy = await _policyRetrievalPointMock.GetPolicyAsync("resource1"); + + List expected = TestDataUtil.GetRolesWithAccess(); + + // Act + List actual = PolicyHelper.GetRolesWithAccess(policy); + + // Assert + Assert.Equal(actual, expected); + } + + /// + /// Scenario: + /// Tests that the GetDelegationPolicyPath method throws the expected argument exception when org does not have a value + /// Input: + /// ResourceId is null because this is a org/app scenario but only app has been provided as part of the resource + /// Expected Result: + /// Argument exception thrown + /// Success Criteria: + /// Argument exception has the expected error message + /// + [Fact] + public void GetDelegationPolicyPath_OrgEmpty() + { + // Arrange + string expectedArgumentException = "Org was not defined"; + + // Act + string actual = string.Empty; + try + { + PolicyHelper.GetDelegationPolicyPath(ResourceAttributeMatchType.AltinnAppId, null, null, "app", "50001337", 20001337, null, null, UuidType.NotSpecified); + } + catch (System.ArgumentException argEx) + { + actual = argEx.Message; + } + + // Assert + Assert.Equal(expectedArgumentException, actual); + } + + /// + /// Scenario: + /// Tests that the GetDelegationPolicyPath method throws the expected argument exception when app does not have a value + /// Input: + /// ResourceId is null because this is a org/app scenario but only org has been provided as part of the resource + /// Expected Result: + /// Argument exception thrown + /// Success Criteria: + /// Argument exception has the expected error message + /// + [Fact] + public void GetDelegationPolicyPath_AppEmpty() + { + // Arrange + string expectedArgumentException = "App was not defined"; + + // Act + string actual = string.Empty; + try + { + PolicyHelper.GetDelegationPolicyPath(ResourceAttributeMatchType.AltinnAppId, null, "org", string.Empty, "50001337", 20001337, null, null, UuidType.NotSpecified); + } + catch (System.ArgumentException argEx) + { + actual = argEx.Message; + } + + // Assert + Assert.Equal(expectedArgumentException, actual); + } + + /// + /// Scenario: + /// Tests that the GetDelegationPolicyPath method throws the expected argument exception when resourceId does not have a value + /// Input: + /// Org and App is null because this is a resourceId scenario but resourceId has been provided as an empty string in the delegation + /// Expected Result: + /// Argument exception thrown + /// Success Criteria: + /// Argument exception has the expected error message + /// + [Fact] + public void GetDelegationPolicyPath_ResourceIdEmpty() + { + // Arrange + string expectedArgumentException = "ResourceRegistryId was not defined"; + + // Act + string actual = string.Empty; + try + { + PolicyHelper.GetDelegationPolicyPath(ResourceAttributeMatchType.ResourceRegistry, string.Empty, null, null, "50001337", 20001337, null, null, UuidType.NotSpecified); + } + catch (System.ArgumentException argEx) + { + actual = argEx.Message; + } + + // Assert + Assert.Equal(expectedArgumentException, actual); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AccessListsAuthorizationClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AccessListsAuthorizationClientMock.cs new file mode 100644 index 00000000..5a685964 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AccessListsAuthorizationClientMock.cs @@ -0,0 +1,35 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.AccessList; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class AccessListsAuthorizationClientMock : IAccessListsAuthorizationClient + { + private readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; + + /// + public async Task AuthorizePartyForAccessList(AccessListAuthorizationRequest request, CancellationToken cancellationToken = default) + { + AccessListAuthorizationResponse response = null; + + string responsePath = GetResponsePath(request); + if (File.Exists(responsePath)) + { + string content = File.ReadAllText(responsePath); + response = JsonSerializer.Deserialize(content, _jsonSerializerOptions); + } + + return await Task.FromResult(response ?? new AccessListAuthorizationResponse { Result = AccessListAuthorizationResult.NotAuthorized }); + } + + private static string GetResponsePath(AccessListAuthorizationRequest request) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AccessListsAuthorizationClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "Json", "AccessListResponses", $"{request.Resource.Value.ValueSpan}", $"{request.Subject.Value.ValueSpan}", $"{request.Action.Value.ValueSpan}.json"); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/Altinn2RightsClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/Altinn2RightsClientMock.cs new file mode 100644 index 00000000..e2199bd1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/Altinn2RightsClientMock.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers; +using Altinn.AccessManagement.Core.Models; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class Altinn2RightsClientMock : IAltinn2RightsClient + { + /// + /// Initializes a new instance of the class + /// + public Altinn2RightsClientMock() + { + } + + /// + public Task PostDelegationCheck(int userId, int partyId, string serviceCode, string serviceEditionCode) + { + if (partyId == 50001337 && serviceCode == "1337" && serviceEditionCode == "1338") + { + string content = File.ReadAllText($"Data/Json/DelegationCheck/se_1337_1338/from_p50001337/authn_u20001337_from_sbl_bridge.json"); + List results = JsonSerializer.Deserialize>(content); + return Task.FromResult(new DelegationCheckResponse { From = new List { new AttributeMatch { Id = "thing", Value = partyId.ToString() } }, RightDelegationCheckResults = results }); + } + + throw new NotImplementedException(); + } + + /// + public Task PostDelegation(int authenticatedUserId, int reporteePartyId, SblRightDelegationRequest delegationRequest) + { + DelegationHelper.TryGetResourceFromAttributeMatch(delegationRequest.Rights.First().Resource, out ResourceAttributeMatchType _, out string _, out string _, out string _, out string serviceCode, out string serviceEditionCode); + + DelegationActionResult result = new DelegationActionResult(); + result.Rights = GetSblRightsDelegationResult($"se_{serviceCode}_{serviceEditionCode}", reporteePartyId.ToString(), delegationRequest.To.Value, authenticatedUserId.ToString()); + + return Task.FromResult(result); + } + + /// + public Task ClearReporteeRights(int fromPartyId, int toPartyId, int toUserId = 0, CancellationToken cancellationToken = default) + { + return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)); + } + + private static List GetSblRightsDelegationResult(string resourceId, string reporteePartyId, string to, string by) + { + JsonSerializerOptions serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + serializerOptions.Converters.Add(new JsonStringEnumConverter()); + + string content = File.ReadAllText($"Data/Json/RightsDelegation/{resourceId}/from_{reporteePartyId}/to_{to}/by_{by}/sbl_response.json"); + return (List)JsonSerializer.Deserialize(content, typeof(List), serializerOptions); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AltinnRolesClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AltinnRolesClientMock.cs new file mode 100644 index 00000000..54b5afe9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AltinnRolesClientMock.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Authorization.Platform.Authorization.Models; + +namespace Altinn.AccessManagement.Tests.Mocks; + +/// +/// Mock class for interface +/// +public class AltinnRolesClientMock : IAltinnRolesClient +{ + private readonly JsonSerializerOptions jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + public AltinnRolesClientMock() + { + } + + /// + public async Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + List roles = new List(); + string rolesPath = GetRolesPath(coveredByUserId, offeredByPartyId); + if (File.Exists(rolesPath)) + { + string content = await File.ReadAllTextAsync(rolesPath, cancellationToken); + roles = (List)JsonSerializer.Deserialize(content, typeof(List), jsonOptions); + } + + return roles; + } + + /// + public async Task> GetRolesForDelegation(int coveredByUserId, int offeredByPartyId, CancellationToken cancellationToken = default) + { + List roles = new List(); + string rolesPath = GetRolesForDelegationPath(coveredByUserId, offeredByPartyId); + if (File.Exists(rolesPath)) + { + string content = await File.ReadAllTextAsync(rolesPath, cancellationToken); + roles = (List)JsonSerializer.Deserialize(content, typeof(List), jsonOptions); + } + + return roles; + } + + /// + public async Task> GetAuthorizedPartiesWithRoles(int userId, CancellationToken cancellationToken = default) + { + string authorizedPartiesPath = GetAltinn2AuthorizedPartiesWithRolesPath(userId); + if (File.Exists(authorizedPartiesPath)) + { + string content = await File.ReadAllTextAsync(authorizedPartiesPath, cancellationToken); + List bridgeAuthParties = (List)JsonSerializer.Deserialize(content, typeof(List), jsonOptions); + return bridgeAuthParties.Select(sblAuthorizedParty => new AuthorizedParty(sblAuthorizedParty)).ToList(); + } + + return new(); + } + + private static string GetRolesPath(int coveredByUserId, int offeredByPartyId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AltinnRolesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Roles", $"user_{coveredByUserId}", $"party_{offeredByPartyId}", "roles.json"); + } + + private static string GetRolesForDelegationPath(int coveredByUserId, int offeredByPartyId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AltinnRolesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "RolesForDelegation", $"user_{coveredByUserId}", $"party_{offeredByPartyId}", "roles.json"); + } + + private static string GetAltinn2AuthorizedPartiesWithRolesPath(int userId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AltinnRolesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "AuthorizedParties", "SBLBridge", $"authorizedparties_u{userId}.json"); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationMock.cs new file mode 100644 index 00000000..5e14ac37 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationMock.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Authentication; +using Altinn.AccessManagement.Tests.Util; +using Altinn.Platform.Register.Models; +using static Microsoft.ApplicationInsights.MetricDimensionNames.TelemetryContext; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class AuthenticationMock : IAuthenticationClient + { + private readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; + + /// + public async Task RefreshToken(CancellationToken cancellationToken = default) => await Task.FromResult(PrincipalUtil.GetAccessToken("sbl-authorization")); + + /// + public async Task GetSystemUser(int partyId, string systemUserId, CancellationToken cancellationToken = default) + { + SystemUser systemUser = null; + + string systemUserPath = GetSystemUserPath(systemUserId); + if (File.Exists(systemUserPath)) + { + string content = File.ReadAllText(systemUserPath); + systemUser = (SystemUser)JsonSerializer.Deserialize(content, typeof(SystemUser), _jsonSerializerOptions); + } + + return await Task.FromResult(systemUser); + } + + /// + public async Task> GetDefaultRightsForRegisteredSystem(string productId, CancellationToken cancellationToken = default) + { + List defaultRights = new(); + + string systemUserPath = GetDefaultRightsForRegisteredSystemPath(productId); + if (File.Exists(systemUserPath)) + { + string content = File.ReadAllText(systemUserPath); + defaultRights = (List)JsonSerializer.Deserialize(content, typeof(List), _jsonSerializerOptions); + } + + return await Task.FromResult(defaultRights); + } + + private static string GetSystemUserPath(string systemUserId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AuthenticationMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "SystemUser", $"{systemUserId}", "systemuser.json"); + } + + private static string GetDefaultRightsForRegisteredSystemPath(string productId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(AuthenticationMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "System", $"{productId}", "defaultrights.json"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationNullRefreshMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationNullRefreshMock.cs new file mode 100644 index 00000000..c7ddef8b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/AuthenticationNullRefreshMock.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Authentication; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class AuthenticationNullRefreshMock : IAuthenticationClient + { + /// + public async Task RefreshToken(CancellationToken cancellationToken = default) => await Task.FromResult(string.Empty); + + /// + public async Task GetSystemUser(int partyId, string systemUserId, CancellationToken cancellationToken = default) => await Task.FromResult((SystemUser)null); + + /// + public async Task> GetDefaultRightsForRegisteredSystem(string productId, CancellationToken cancellationToken = default) => await Task.FromResult((List)null); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ConfigurationManagerStub.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ConfigurationManagerStub.cs new file mode 100644 index 00000000..e3248676 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ConfigurationManagerStub.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.Tokens; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Represents a stub of to be used in integration tests. + /// + public class ConfigurationManagerStub : IConfigurationManager + { + /// + public async Task GetConfigurationAsync(CancellationToken cancel) + { + ICollection signingKeys = await GetSigningKeys(); + + OpenIdConnectConfiguration configuration = new OpenIdConnectConfiguration(); + foreach (var securityKey in signingKeys) + { + configuration.SigningKeys.Add(securityKey); + } + + return configuration; + } + + /// + public void RequestRefresh() + { + } + + private async Task> GetSigningKeys() + { + List signingKeys = new List(); + + X509Certificate2 cert = new X509Certificate2("selfSignedTestCertificatePublic.cer"); + SecurityKey key = new X509SecurityKey(cert); + + signingKeys.Add(key); + + return await Task.FromResult(signingKeys); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationChangeEventQueueMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationChangeEventQueueMock.cs new file mode 100644 index 00000000..d1f4b9f6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationChangeEventQueueMock.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Azure.Storage.Queues.Models; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + public class DelegationChangeEventQueueMock : IDelegationChangeEventQueue + { + /// + /// Mocks pushing delegation changes to the event queue + /// + /// The delegation change stored in postgresql + public Task Push(DelegationChange delegationChange) + { + if (delegationChange.ResourceId == "error/delegationeventfail") + { + throw new Exception("DelegationChangeEventQueue || Push || Error"); + } + + return Task.FromResult((SendReceipt)null); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationMetadataRepositoryMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationMetadataRepositoryMock.cs new file mode 100644 index 00000000..831581ba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationMetadataRepositoryMock.cs @@ -0,0 +1,621 @@ +using System.Text; +using System.Text.Json; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Helpers.Extensions; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Enums; +using Altinn.AccessManagement.Tests.Data; +using Altinn.AccessManagement.Tests.Utils; + +namespace Altinn.AccessManagement.Tests.Mocks; + +/// +/// Mock class for interface +/// +public class DelegationMetadataRepositoryMock : IDelegationMetadataRepository +{ + /// + /// Property for storing delegation changes locally for verification later from the integration tests + /// + public Dictionary> MetadataChanges { get; set; } + + /// + /// Constructor setting up dependencies + /// + public DelegationMetadataRepositoryMock() + { + MetadataChanges = new Dictionary>(); + } + + /// + public Task InsertDelegation(ResourceAttributeMatchType resourceMatchType, DelegationChange delegationChange, CancellationToken cancellationToken = default) + { + List current; + string coveredBy = delegationChange.CoveredByPartyId != null ? $"p{delegationChange.CoveredByPartyId}" : $"u{delegationChange.CoveredByUserId}"; + string key = string.Empty; + + if (resourceMatchType == ResourceAttributeMatchType.AltinnAppId) + { + key = $"{delegationChange.ResourceId}/{delegationChange.OfferedByPartyId}/{coveredBy}"; + } + else + { + key = $"resourceregistry/{delegationChange.ResourceId}/{delegationChange.OfferedByPartyId}/{coveredBy}"; + } + + if (MetadataChanges.ContainsKey(key)) + { + current = MetadataChanges[key]; + } + else + { + current = new List(); + MetadataChanges[key] = current; + } + + DelegationChange currentDelegationChange = new DelegationChange + { + DelegationChangeId = 1337, + DelegationChangeType = delegationChange.DelegationChangeType, + ResourceId = delegationChange.ResourceId, + ResourceType = resourceMatchType == ResourceAttributeMatchType.AltinnAppId ? ResourceAttributeMatchType.AltinnAppId.ToString() : ResourceType.MaskinportenSchema.ToString(), + OfferedByPartyId = delegationChange.OfferedByPartyId, + CoveredByPartyId = delegationChange.CoveredByPartyId, + CoveredByUserId = delegationChange.CoveredByUserId, + PerformedByUserId = delegationChange.PerformedByUserId, + BlobStoragePolicyPath = delegationChange.BlobStoragePolicyPath, + BlobStorageVersionId = delegationChange.BlobStorageVersionId, + Created = DateTime.Now + }; + + current.Add(currentDelegationChange); + + if (delegationChange.ResourceId == "error/postgrewritechangefail") + { + currentDelegationChange.DelegationChangeId = 0; + return Task.FromResult(currentDelegationChange); + } + + return Task.FromResult(currentDelegationChange); + } + + public Task GetLastInstanceDelegationChange(InstanceDelegationChangeRequest request, CancellationToken cancellationToken = default) + { + Random random = new Random(); + switch (request.Instance) + { + case "00000000-0000-0000-0000-000000000001": + case "00000000-0000-0000-0000-000000000009": + case "00000000-0000-0000-0000-000000000010": + return Task.FromResult(new InstanceDelegationChange + { + FromUuidType = request.FromType, + FromUuid = request.FromUuid, + ToUuidType = request.ToType, + ToUuid = request.ToUuid, + PerformedBy = request.Resource, + PerformedByType = UuidType.Resource, + BlobStoragePolicyPath = BuildPolicyPath(request.ToUuid, request.InstanceDelegationMode, request.Resource, request.Instance), + BlobStorageVersionId = "2024-09-13T16:59:13.123Z", + Created = new DateTime(2024, 9, 13, 16, 59, 13, 347, DateTimeKind.Utc), + InstanceId = request.Instance, + DelegationChangeType = DelegationChangeType.Grant, + InstanceDelegationChangeId = random.Next(1, 1000), + InstanceDelegationMode = InstanceDelegationMode.ParallelSigning, + ResourceId = request.Resource + }); + default: + return Task.FromResult((InstanceDelegationChange)null); + } + } + + public Task InsertInstanceDelegation(InstanceDelegationChange instanceDelegationChange, CancellationToken cancellationToken = default) + { + Random random = new(); + string path = GetDelegationPolicyPathFromInstanceRule(instanceDelegationChange); + InstanceDelegationChange result = instanceDelegationChange.InstanceId switch + { + "00000000-0000-0000-0000-000000000002" => null, + _ => new InstanceDelegationChange + { + InstanceDelegationChangeId = random.Next(0, 1000), + DelegationChangeType = instanceDelegationChange.DelegationChangeType, + InstanceDelegationMode = instanceDelegationChange.InstanceDelegationMode, + ResourceId = instanceDelegationChange.ResourceId, + InstanceId = instanceDelegationChange.InstanceId, + FromUuid = instanceDelegationChange.FromUuid, + FromUuidType = instanceDelegationChange.FromUuidType, + ToUuid = instanceDelegationChange.ToUuid, + ToUuidType = instanceDelegationChange.ToUuidType, + PerformedBy = instanceDelegationChange.PerformedBy, + PerformedByType = instanceDelegationChange.PerformedByType, + BlobStoragePolicyPath = path, + BlobStorageVersionId = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), + Created = DateTime.Now + }, + }; + + return Task.FromResult(result); + } + + private static string GetDelegationPolicyPathFromInstanceRule(InstanceDelegationChange change) + { + StringBuilder sb = new StringBuilder(); + + sb.Append(change.ResourceId); + + sb.Append('/'); + + sb.Append(change.FromUuidType); + sb.Append('-'); + sb.Append(change.FromUuid); + sb.Append('/'); + + sb.Append(change.ToUuidType); + sb.Append('-'); + sb.Append(change.ToUuid); + sb.Append('/'); + + sb.Append(change.InstanceId.AsFileName(false)); + + sb.Append('/'); + sb.Append(change.InstanceDelegationMode); + + sb.Append("/delegationpolicy.xml"); + return sb.ToString(); + } + + /// + public Task GetCurrentDelegationChange(ResourceAttributeMatchType resourceMatchType, string resourceId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, Guid? toUuid, UuidType toUuidType, CancellationToken cancellationToken = default) + { + DelegationChange result = null; + DateTime created = Convert.ToDateTime("2022-09-27T13:02:23.786072Z"); + + switch (resourceId) + { + case "app_org1_app1": + case "org1/app1": + case "org1/app3": + case "org2/app3": + case "org1/app4": + case "error/blobstorageleaselockwritefail": + case "error/postgrewritechangefail": + result = TestDataUtil.GetAltinnAppDelegationChange(resourceId, offeredByPartyId, coveredByUserId, coveredByPartyId); + break; + case "org1/app5": + result = TestDataUtil.GetAltinnAppDelegationChange(resourceId, offeredByPartyId, coveredByUserId, coveredByPartyId, changeType: DelegationChangeType.RevokeLast); + break; + case "error/postgregetcurrentfail": + throw new Exception("Some exception happened"); + case "error/delegationeventfail": + result = TestDataUtil.GetAltinnAppDelegationChange(resourceId, offeredByPartyId, coveredByUserId, coveredByPartyId, changeType: DelegationChangeType.Grant); + break; + case "resource1": + result = TestDataUtil.GetResourceRegistryDelegationChange(resourceId, ResourceType.MaskinportenSchema, offeredByPartyId, created, coveredByUserId, coveredByPartyId); + break; + case "resource2": + result = TestDataUtil.GetResourceRegistryDelegationChange(resourceId, ResourceType.MaskinportenSchema, offeredByPartyId, created, coveredByUserId, coveredByPartyId); + break; + case "jks_audi_etron_gt": + result = TestDataUtil.GetResourceRegistryDelegationChange(resourceId, ResourceType.MaskinportenSchema, offeredByPartyId, created, coveredByUserId, coveredByPartyId); + break; + default: + result = null; + break; + } + + return Task.FromResult(result); + } + + /// + public Task> GetAllAppDelegationChanges(string altinnAppId, int offeredByPartyId, int? coveredByPartyId, int? coveredByUserId, CancellationToken cancellationToken = default) + { + return Task.FromResult(new List()); + } + + /// + public Task> GetAllCurrentAppDelegationChanges(List offeredByPartyIds, List altinnAppIds, List coveredByPartyIds, List coveredByUserIds, CancellationToken cancellationToken = default) + { + List result = new List(); + altinnAppIds ??= []; + if (altinnAppIds.Count == 0 && offeredByPartyIds.Contains(20001337)) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("org1/app1", 20001337, 20001336)); + } + + if (altinnAppIds.Any(appId => appId == "org1/app1") && offeredByPartyIds.Contains(50001337) && (coveredByUserIds != null && coveredByUserIds.Contains(20001337))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("org1/app1", 50001337, coveredByUserId: 20001337)); + } + + if (altinnAppIds.Any(appId => appId == "skd/taxreport") && offeredByPartyIds.Contains(1000) && (coveredByUserIds != null && coveredByUserIds.Contains(20001337))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 1000, coveredByUserId: 20001337)); + } + + if (altinnAppIds.Any(appId => appId == "org1/app1") && offeredByPartyIds.Contains(50001337) && (coveredByUserIds != null && coveredByUserIds.Contains(20001338))) + { + DelegationChange delegation = TestDataUtil.GetAltinnAppDelegationChange("org1/app1", 50001337, coveredByUserId: 20001338); + delegation.DelegationChangeType = DelegationChangeType.RevokeLast; + result.Add(delegation); + } + + if (altinnAppIds.Any(appId => appId == "org1/app1") && offeredByPartyIds.Contains(50001337) && (coveredByPartyIds != null && coveredByPartyIds.Contains(50001336))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("org1/app1", 50001337, coveredByPartyId: 50001336)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001337) && (coveredByUserIds != null && coveredByUserIds.Contains(20001336))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001337, coveredByUserId: 20001336, performedByUserId: 20001337, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001337) && (coveredByUserIds != null && coveredByUserIds.Contains(20001335))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001337, coveredByPartyId: 50001335, performedByUserId: 20001337, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001337) && (coveredByPartyIds != null && coveredByPartyIds.Contains(50001336))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001337, coveredByPartyId: 50001338, performedByUserId: 20001337, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001338) && (coveredByPartyIds != null && coveredByPartyIds.Contains(50001339))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001338, coveredByPartyId: 50001339, performedByUserId: 20001338, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001338) && (coveredByPartyIds != null && coveredByPartyIds.Contains(50001340))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001338, coveredByPartyId: 50001340, performedByUserId: 20001338, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001338) && (coveredByPartyIds != null && coveredByPartyIds.Contains(50001336))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001338, coveredByPartyId: 50001336, performedByUserId: 20001339, changeType: DelegationChangeType.Grant)); + } + + if (altinnAppIds.Contains("skd/taxreport") && offeredByPartyIds.Contains(50001339) && (coveredByPartyIds != null && coveredByUserIds.Contains(20001336))) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("skd/taxreport", 50001335, coveredByPartyId: 50001337, performedByUserId: 20001339, changeType: DelegationChangeType.Grant)); + } + + return Task.FromResult(result); + } + + /// + public Task> GetAllCurrentAppDelegationChanges(List altinnAppIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + List result = new List(); + if (altinnAppIds.Contains("ttd/apps-test") && fromPartyIds.Contains(50005545) && toUuid == new Guid("a6355a68-86b8-4344-8a81-0248cb461468")) + { + result.Add(new DelegationChange + { + DelegationChangeId = 1337, + DelegationChangeType = DelegationChangeType.Grant, + ResourceId = "ttd/apps-test", + ResourceType = ResourceAttributeMatchType.AltinnAppId.ToString(), + OfferedByPartyId = 50005545, + FromUuid = new Guid("00000000-0000-0000-0005-000000005545"), + FromUuidType = UuidType.Organization, + CoveredByPartyId = null, + CoveredByUserId = null, + ToUuid = new Guid("a6355a68-86b8-4344-8a81-0248cb461468"), + ToUuidType = UuidType.SystemUser, + PerformedByUserId = 20000490, + PerformedByUuid = null, + PerformedByUuidType = UuidType.NotSpecified, + BlobStoragePolicyPath = $"ttd/apps-test/50005545/SystemUsera6355a68-86b8-4344-8a81-0248cb461468/delegationpolicy.xml", + BlobStorageVersionId = "2024-07-18T13:37:00.1337Z", + Created = Convert.ToDateTime("2024-07-18T13:37:00.1337Z") + }); + } + + return Task.FromResult(result); + } + + /// + public Task> GetAllCurrentResourceRegistryDelegationChanges(List offeredByPartyIds, List resourceRegistryIds = null, List coveredByPartyIds = null, int? coveredByUserId = null, CancellationToken cancellationToken = default) + { + List result = new List(); + + foreach (string resourceRegistryId in resourceRegistryIds) + { + foreach (int offeredByPartyId in offeredByPartyIds) + { + if (coveredByPartyIds != null) + { + foreach (int coveredByPartyId in coveredByPartyIds) + { + string delegationChangePath = GetResourceRegistryDelegationPath_ForCoveredByPartyId(resourceRegistryId, offeredByPartyId, coveredByPartyId); + if (File.Exists(delegationChangePath)) + { + string content = File.ReadAllText(delegationChangePath); + DelegationChange delegationChange = (DelegationChange)JsonSerializer.Deserialize(content, typeof(DelegationChange), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + result.Add(delegationChange); + } + } + } + + if (coveredByUserId.HasValue) + { + string delegationChangePath = GetResourceRegistryDelegationPath_ForCoveredByUserId(resourceRegistryId, offeredByPartyId, coveredByUserId.Value); + if (File.Exists(delegationChangePath)) + { + string content = File.ReadAllText(delegationChangePath); + DelegationChange delegationChange = (DelegationChange)JsonSerializer.Deserialize(content, typeof(DelegationChange), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + result.Add(delegationChange); + } + } + } + } + + return Task.FromResult(result); + } + + /// + public Task> GetAllCurrentResourceRegistryDelegationChanges(List resourceRegistryIds, List fromPartyIds, UuidType toUuidType, Guid toUuid, CancellationToken cancellationToken = default) + { + List result = new List(); + if (resourceRegistryIds.Contains("generic-access-resource") && fromPartyIds.Contains(50005545) && toUuid == new Guid("a6355a68-86b8-4344-8a81-0248cb461468")) + { + result.Add(new DelegationChange + { + ResourceRegistryDelegationChangeId = 1337, + DelegationChangeType = DelegationChangeType.Grant, + ResourceId = "generic-access-resource", + ResourceType = ResourceType.GenericAccessResource.ToString().ToLower(), + OfferedByPartyId = 50005545, + FromUuid = new Guid("00000000-0000-0000-0005-000000005545"), + FromUuidType = UuidType.Organization, + CoveredByPartyId = null, + CoveredByUserId = null, + ToUuid = new Guid("a6355a68-86b8-4344-8a81-0248cb461468"), + ToUuidType = UuidType.SystemUser, + PerformedByUserId = 20000490, + PerformedByUuid = null, + PerformedByUuidType = UuidType.NotSpecified, + BlobStoragePolicyPath = $"resourceregistry/generic-access-resource/50005545/SystemUsera6355a68-86b8-4344-8a81-0248cb461468/delegationpolicy.xml", + BlobStorageVersionId = "2024-07-18T13:37:00.1337Z", + Created = Convert.ToDateTime("2024-07-18T13:37:00.1337Z") + }); + } + + return Task.FromResult(result); + } + + /// + public Task> GetOfferedResourceRegistryDelegations(int offeredByPartyId, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + List result = new List(); + DateTime created = Convert.ToDateTime("2022-09-27T13:02:23.786072Z"); + if (offeredByPartyId == 20001337) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("altinn_access_management", ResourceType.Systemresource, 20001337, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("app_org1_app1", ResourceType.AltinnApp, 20001337, created, null, 50004220, 20000002, DelegationChangeType.Grant, 1235)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("scope-access-schema", ResourceType.MaskinportenSchema, 20001337, created, null, 50004221, 20000002, DelegationChangeType.Grant, 1236)); + } + + if (offeredByPartyId == 50004223 && resourceTypes.Count == 1 && resourceTypes.First() == ResourceType.MaskinportenSchema) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004223, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004223, created, null, 50004220, 20000002, DelegationChangeType.Grant, 1235)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004223, created, null, 50004221, 20000002, DelegationChangeType.Grant, 1236)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004223, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004223, created, null, 50004220, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004223, created, null, 50004221, 20000002, DelegationChangeType.Grant, 1234)); + } + else if (offeredByPartyId == 50004226 && resourceTypes.Count == 1 && resourceTypes.First() == ResourceType.MaskinportenSchema) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav1_aa_distribution", ResourceType.MaskinportenSchema, 50004226, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav1_aa_distribution", ResourceType.MaskinportenSchema, 50004226, created, null, 50004220, 20000002, DelegationChangeType.Grant, 1235)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav1_aa_distribution", ResourceType.MaskinportenSchema, 50004226, created, null, 50004221, 20000002, DelegationChangeType.Grant, 1236)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004226, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004226, created, null, 50004220, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004226, created, null, 50004221, 20000002, DelegationChangeType.Grant, 1234)); + } + + return Task.FromResult(result); + } + + /// + public Task> GetReceivedResourceRegistryDelegationsForCoveredByPartys(List coveredByPartyIds, List offeredByPartyIds, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + List result = new List(); + DateTime created = DateTime.Parse("2022-09-27T13:02:23.786072Z"); + if (coveredByPartyIds.Count == 1 && coveredByPartyIds.First() == 50004219 && resourceTypes.Count == 1 && resourceTypes.First() == ResourceType.MaskinportenSchema) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004222, created, null, 50004219, 20000008, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004222, created, null, 50004219, 20000008, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004220, created, null, 50004219, 20000007, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004220, created, null, 50004219, 20000007, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004221, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004221, created, null, 50004219, 20000002, DelegationChangeType.Grant, 1234)); + } + else if (coveredByPartyIds.Count == 1 && coveredByPartyIds.First() == 50004216 && resourceTypes.Count == 1 && resourceTypes.First() == ResourceType.MaskinportenSchema) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", ResourceType.MaskinportenSchema, 50004222, created, null, 50004216, 20000008, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004222, created, null, 50004216, 20000008, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav1_aa_distribution", ResourceType.MaskinportenSchema, 50004226, created, null, 50004216, 20000002, DelegationChangeType.Grant, 1234)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("skd_1", ResourceType.MaskinportenSchema, 50004226, created, null, 50004216, 20000002, DelegationChangeType.Grant, 1234)); + } + + return Task.FromResult(result); + } + + /// + public Task> GetResourceRegistryDelegationChanges(List resourceIds, int offeredByPartyid, int coveredByPartyId, ResourceType resourceType, CancellationToken cancellationToken = default) + { + List result = new List(); + if (offeredByPartyid == 50004222 && coveredByPartyId == 50004219 && (resourceIds != null && resourceIds.Count > 0)) + { + DateTime created = Convert.ToDateTime("2022-09-27T13:02:23.786072Z"); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("nav_aa_distribution", resourceType, offeredByPartyid, created, null, coveredByPartyId, 20000008, DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("appid-123", resourceType, offeredByPartyid, created, null, coveredByPartyId, 20000008, DelegationChangeType.Grant)); + } + + return Task.FromResult(result); + } + + /// + public Task> GetReceivedResourceRegistryDelegationsForCoveredByUser(int coveredByUserId, List offeredByPartyIds, List resourceRegistryIds = null, List resourceTypes = null, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public Task> GetAllDelegationChangesForAuthorizedParties(List coveredByUserIds, List coveredByPartyIds, CancellationToken cancellationToken = default) + { + List result = new List(); + DateTime created = Convert.ToDateTime("2024-02-05T21:05:00.00Z"); + if (coveredByPartyIds != null && coveredByPartyIds.Contains(50005545)) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("altinn_access_management", ResourceType.Systemresource, 50002203, DateTime.Now, coveredByPartyId: 50005545)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("org1/app1", ResourceType.AltinnApp, 50002203, DateTime.Now, coveredByPartyId: 50005545)); + } + else if (coveredByUserIds != null && coveredByUserIds.Contains(20000095)) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("altinn_access_management", ResourceType.Systemresource, 50002203, DateTime.Now, coveredByUserId: 20000095)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("org1/app1", ResourceType.AltinnApp, 50002203, DateTime.Now, coveredByUserId: 20000095)); + } + else if (coveredByUserIds != null && coveredByUserIds.Contains(TestDataAuthorizedParties.PersonToPerson_ToUserId)) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-person-to-person", ResourceType.GenericAccessResource, TestDataAuthorizedParties.PersonToPerson_FromPartyId, created, coveredByUserId: TestDataAuthorizedParties.PersonToPerson_ToUserId, performedByUserId: TestDataAuthorizedParties.PersonToPerson_FromUserId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetAltinnAppDelegationChange("ttd/am-devtest-person-to-person", TestDataAuthorizedParties.PersonToPerson_FromPartyId, coveredByUserId: TestDataAuthorizedParties.PersonToPerson_ToUserId, performedByUserId: TestDataAuthorizedParties.PersonToPerson_FromUserId, changeType: DelegationChangeType.Grant)); + } + else if (coveredByPartyIds != null && coveredByPartyIds.Contains(TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId)) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-person-to-org", ResourceType.GenericAccessResource, TestDataAuthorizedParties.PersonToOrg_FromPartyId, created, coveredByPartyId: TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId, performedByUserId: TestDataAuthorizedParties.PersonToOrg_FromUserId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetAltinnAppDelegationChange("ttd/am-devtest-person-to-org", TestDataAuthorizedParties.PersonToOrg_FromPartyId, coveredByPartyId: TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId, performedByUserId: TestDataAuthorizedParties.PersonToOrg_FromUserId, changeType: DelegationChangeType.Grant)); + } + else if (coveredByUserIds != null && coveredByUserIds.Contains(TestDataAuthorizedParties.MainUnitAndSubUnitToPerson_ToUserId)) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-main-to-person", ResourceType.GenericAccessResource, TestDataAuthorizedParties.MainUnit_PartyId, created, coveredByUserId: TestDataAuthorizedParties.MainUnitAndSubUnitToPerson_ToUserId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetAltinnAppDelegationChange("ttd/am-devtest-sub-to-person", TestDataAuthorizedParties.SubUnit_PartyId, coveredByUserId: TestDataAuthorizedParties.MainUnitAndSubUnitToPerson_ToUserId, changeType: DelegationChangeType.Grant)); + } + else if (coveredByPartyIds != null && coveredByPartyIds.Contains(TestDataAuthorizedParties.MainUnitAndSubUnitToOrg_ToOrgPartyId)) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("ttd/am-devtest-sub-to-org", TestDataAuthorizedParties.SubUnit_PartyId, coveredByPartyId: TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-main-to-org", ResourceType.GenericAccessResource, TestDataAuthorizedParties.MainUnit_PartyId, created, coveredByPartyId: TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-sub-to-org", ResourceType.GenericAccessResource, TestDataAuthorizedParties.SubUnit_PartyId, created, coveredByPartyId: TestDataAuthorizedParties.PersonToOrg_ToOrgPartyId, changeType: DelegationChangeType.Grant)); + } + else if (coveredByUserIds != null && coveredByUserIds.Contains(TestDataAuthorizedParties.SubUnitToPerson_ToUserId)) + { + result.Add(TestDataUtil.GetAltinnAppDelegationChange("ttd/am-devtest-sub-to-person", TestDataAuthorizedParties.SubUnit_PartyId, coveredByUserId: TestDataAuthorizedParties.SubUnitToPerson_ToUserId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-sub-to-person", ResourceType.GenericAccessResource, TestDataAuthorizedParties.SubUnit_PartyId, created, coveredByUserId: TestDataAuthorizedParties.SubUnitToPerson_ToUserId, changeType: DelegationChangeType.Grant)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("devtest_gar_authparties-sub2-to-person", ResourceType.GenericAccessResource, TestDataAuthorizedParties.SubUnitTwo_PartyId, created, coveredByUserId: TestDataAuthorizedParties.SubUnitToPerson_ToUserId, changeType: DelegationChangeType.Grant)); + } + + return Task.FromResult(result); + } + + /// + public Task> GetOfferedDelegations(List offeredByPartyIds, CancellationToken cancellationToken = default) + { + var result = new List(); + foreach (var offeredBy in offeredByPartyIds) + { + if (offeredBy == 50002203) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("altinn_access_management", ResourceType.Systemresource, offeredBy, DateTime.Now, coveredByPartyId: 50005545)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("org1/app1", ResourceType.AltinnApp, offeredBy, DateTime.Now, coveredByPartyId: 50005545)); + } + + if (offeredBy == 50005545) + { + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("altinn_access_management", ResourceType.Systemresource, offeredBy, DateTime.Now, coveredByUserId: 20000095)); + result.Add(TestDataUtil.GetResourceRegistryDelegationChange("org1/app1", ResourceType.AltinnApp, offeredBy, DateTime.Now, coveredByUserId: 20000095)); + } + } + + return Task.FromResult(result); + } + + /// + public Task> GetActiveInstanceDelegations(List resourceIds, Guid from, List to, CancellationToken cancellationToken = default) + { + return Task.FromResult>(new List()); + } + + private static string GetResourceRegistryDelegationPath_ForCoveredByPartyId(string resourceRegistryId, int offeredByPartyId, int coveredByPartyId, CancellationToken cancellationToken = default) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationMetadataRepositoryMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "ResourceRegistryDelegationChanges", $"{resourceRegistryId}", $"{offeredByPartyId}", $"p{coveredByPartyId}", "delegationchange.json"); + } + + private static string GetResourceRegistryDelegationPath_ForCoveredByUserId(string resourceRegistryId, int offeredByPartyId, int coveredByUserId, CancellationToken cancellationToken = default) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationMetadataRepositoryMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "ResourceRegistryDelegationChanges", $"{resourceRegistryId}", $"{offeredByPartyId}", $"u{coveredByUserId}", "delegationchange.json"); + } + + private static InstanceDelegationChange CreateInstanceDelegationChange(InstanceDelegationSource source, string resourceId, string instanceId, Guid toUuid) + { + Random random = new Random(); + InstanceDelegationChange result = new InstanceDelegationChange + { + FromUuidType = UuidType.Organization, + FromUuid = Guid.Parse("B537C953-03C4-4822-B028-C15182ADC356"), + ToUuidType = UuidType.Person, + ToUuid = toUuid, + PerformedBy = "app_ttd_am-devtest-instancedelegation", + PerformedByType = UuidType.Resource, + BlobStoragePolicyPath = BuildPolicyPath(toUuid, InstanceDelegationMode.Normal, resourceId, instanceId), + BlobStorageVersionId = "2024-09-13T16:59:13.123Z", + Created = new DateTime(2024, 9, 13, 16, 59, 13, 347, DateTimeKind.Utc), + InstanceId = instanceId, + DelegationChangeType = DelegationChangeType.Grant, + InstanceDelegationChangeId = random.Next(1, 1000), + InstanceDelegationMode = InstanceDelegationMode.Normal, + ResourceId = resourceId + }; + + return result; + } + + private static string BuildPolicyPath(Guid to, InstanceDelegationMode mode, string resourceId, string instanceId) + { + StringBuilder sb = new StringBuilder(); + sb.Append($"Instance/{resourceId}"); + sb.Append('/'); + sb.Append(instanceId.ToUpper().AsSpan(24)); + sb.Append('/'); + sb.Append(mode.ToString().ToUpper().AsSpan(0, 1)); + sb.Append('/'); + sb.Append(to.ToString().ToUpper().AsSpan(24)); + sb.Append("/delegationpolicy.xml"); + return sb.ToString(); + } + + public Task> GetAllLatestInstanceDelegationChanges(InstanceDelegationSource source, string resourceID, string instanceID, CancellationToken cancellationToken = default) + { + List result = new List(); + switch (instanceID) + { + case "00000000-0000-0000-0000-000000000008": + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("CE4BA72B-D111-404F-95B5-313FB3847FA1"))); + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("0268B99A-5817-4BBF-9B62-D90B16D527EA"))); + return Task.FromResult(result); + case "00000000-0000-0000-0000-000000000010": + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("CE4BA72B-D111-404F-95B5-313FB3847FA1"))); + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("0268B99A-5817-4BBF-9B62-D90B16D527EA"))); + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("00000000-0000-0000-0001-000000000012"))); + result.Add(CreateInstanceDelegationChange(source, resourceID, instanceID, Guid.Parse("00000000-0000-0000-0001-000000000010"))); + return Task.FromResult(result); + default: + return Task.FromResult(result); + } + } + + public Task> GetAllCurrentReceivedInstanceDelegations(List toUuid, CancellationToken cancellationToken = default) + { + return Task.FromResult(new List()); + } + + public Task InsertMultipleInstanceDelegations(List policyWriteOutputs, CancellationToken cancellationToken = default) + { + return Task.FromResult(true); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationRequestMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationRequestMock.cs new file mode 100644 index 00000000..5189daaa --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/DelegationRequestMock.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Services.Interfaces; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class DelegationRequestMock : IDelegationRequestsWrapper + { + /// + public Task GetDelegationRequestsAsync(string who, string serviceCode, int? serviceEditionCode, RestAuthorizationRequestDirection direction, List status, string continuation) + { + DelegationRequests delRequests = []; + + string path = GetDelegationRequestPaths(); + + string filterFileName = GetFilterFileName(who, direction); + + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + + foreach (string file in files) + { + if (file.Contains(filterFileName)) + { + string content = File.ReadAllText(Path.Combine(path, file)); + DelegationRequest delegationRequest = JsonSerializer.Deserialize(content, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + + if (delegationRequest != null) + { + delRequests.Add(delegationRequest); + } + } + } + } + + return Task.FromResult(delRequests); + } + + private static string GetDelegationRequestPaths() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationRequestMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, @"..\..\..\Data\DelegationRequests\"); + } + + private string GetFilterFileName(string requestedFromParty, RestAuthorizationRequestDirection direction) + { + return "coveredby_UID1337"; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/JwtCookiePostConfigureOptionsStub.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/JwtCookiePostConfigureOptionsStub.cs new file mode 100644 index 00000000..b1d1fac4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/JwtCookiePostConfigureOptionsStub.cs @@ -0,0 +1,40 @@ +using System; + +using AltinnCore.Authentication.JwtCookie; + +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Represents a stub for the class to be used in integration tests. + /// + public class JwtCookiePostConfigureOptionsStub : IPostConfigureOptions + { + /// + public void PostConfigure(string name, JwtCookieOptions options) + { + if (string.IsNullOrEmpty(options.JwtCookieName)) + { + options.JwtCookieName = JwtCookieDefaults.CookiePrefix + name; + } + + if (options.CookieManager == null) + { + options.CookieManager = new ChunkingCookieManager(); + } + + if (!string.IsNullOrEmpty(options.MetadataAddress)) + { + if (!options.MetadataAddress.EndsWith("/", StringComparison.Ordinal)) + { + options.MetadataAddress += "/"; + } + } + + options.MetadataAddress += ".well-known/openid-configuration"; + options.ConfigurationManager = new ConfigurationManagerStub(); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/MessageHandlerMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/MessageHandlerMock.cs new file mode 100644 index 00000000..43ca1ba9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/MessageHandlerMock.cs @@ -0,0 +1,33 @@ +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Altinn.AccessManagement.Tests.Mocks; + + /// + /// Class for mocking http responses when testing + /// +public class MessageHandlerMock : DelegatingHandler +{ + private readonly HttpStatusCode _expectedResponseStatus; + private readonly HttpContent _httpContent; + + /// + /// Initializes a new instance of the class. + /// + /// Expected HttpStatusCode + /// Expected response content + public MessageHandlerMock(HttpStatusCode expectedResponseStatus, HttpContent httpContent) + { + _expectedResponseStatus = expectedResponseStatus; + _httpContent = httpContent; + } + + /// + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + return Task.FromResult(new HttpResponseMessage() + { StatusCode = _expectedResponseStatus, Content = _httpContent }); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PartiesClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PartiesClientMock.cs new file mode 100644 index 00000000..c16edc81 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PartiesClientMock.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Tests.Seeds; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Mocks; + +/// +/// Mock class for interface +/// +public class PartiesClientMock : IPartiesClient +{ + private Dictionary AdditionalParties { get; set; } = new Dictionary() + { + { PersonSeeds.Paula.PartyId, PersonSeeds.Paula.Party }, + { PersonSeeds.Kasper.PartyId, PersonSeeds.Kasper.Party }, + { PersonSeeds.Olav.PartyId, PersonSeeds.Olav.Party }, + }; + + /// + public Task> GetPartiesAsync(List partyIds, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + var result = new List(); + foreach (var partyId in partyIds) + { + if (AdditionalParties.TryGetValue(partyId, out var party)) + { + result.Add(party); + } + } + + List partyList = GetTestDataParties(); + List filteredList = (from int partyId in partyIds.Distinct() + let party = partyList.Find(p => p.PartyId == partyId) + where party != null + select party).ToList(); + result.AddRange(filteredList); + return Task.FromResult(filteredList); + } + + /// + public Task> GetPartiesAsync(List partyUuids, bool includeSubunits = false, CancellationToken cancellationToken = default) + { + List partyList = GetTestDataParties(); + return Task.FromResult((from Guid partyUuid in partyUuids.Distinct() + let party = partyList.Find(p => p.PartyUuid == partyUuid) + where party != null + select party).ToList()); + } + + /// + public Task GetPartyAsync(int partyId, CancellationToken cancellationToken = default) + { + return Task.FromResult(GetTestDataParties().Find(p => p.PartyId == partyId)); + } + + /// + public Task LookupPartyBySSNOrOrgNo(PartyLookup partyLookup, CancellationToken cancellationToken = default) + { + List partyList = GetTestDataParties(); + Party party = null; + + if (!string.IsNullOrWhiteSpace(partyLookup.OrgNo)) + { + party = partyList.Find(p => p.Organization?.OrgNumber == partyLookup.OrgNo); + } + else if (!string.IsNullOrWhiteSpace(partyLookup.Ssn)) + { + party = partyList.Find(p => p.Person?.SSN == partyLookup.Ssn); + } + + return Task.FromResult(party); + } + + /// + public Task> GetKeyRoleParties(int userId, CancellationToken cancellationToken = default) + { + List keyRoleUnitPartyIds = new(); + + string keyRoleUnitsPath = GetKeyRoleUnitsPaths(userId); + if (File.Exists(keyRoleUnitsPath)) + { + string content = File.ReadAllText(keyRoleUnitsPath); + keyRoleUnitPartyIds = (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + return Task.FromResult(keyRoleUnitPartyIds); + } + + /// + public Task> GetMainUnits(MainUnitQuery subunitPartyIds, CancellationToken cancellationToken = default) + { + List mainUnits = new(); + + foreach (int subunitPartyId in subunitPartyIds.PartyIds) + { + string mainUnitsPath = GetMainUnitsPath(subunitPartyId); + if (File.Exists(mainUnitsPath)) + { + string content = File.ReadAllText(mainUnitsPath); + List readMainUnits = (List)JsonSerializer.Deserialize(content, typeof(List), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + mainUnits.AddRange(readMainUnits); + } + } + + return Task.FromResult(mainUnits); + } + + /// + public Task> GetPartiesForUserAsync(int userId, CancellationToken cancellationToken = default) + { + return Task.FromResult(GetTestDataParties()); + } + + private static List GetTestDataParties() + { + List partyList = new List(); + + string partiesPath = GetPartiesPath(); + if (File.Exists(partiesPath)) + { + string content = File.ReadAllText(partiesPath); + partyList = JsonSerializer.Deserialize>(content); + } + + return partyList; + } + + private static string GetPartiesPath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PartiesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "Parties", "parties.json"); + } + + private static string GetMainUnitsPath(int subunitPartyId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PartiesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "MainUnits", $"{subunitPartyId}", "mainunits.json"); + } + + private static string GetKeyRoleUnitsPaths(int userId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PartiesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "KeyRoleUnits", $"{userId}", "keyroleunits.json"); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PdpPermitMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PdpPermitMock.cs new file mode 100644 index 00000000..601e9faf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PdpPermitMock.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using Altinn.Authorization.ABAC.Xacml.JsonProfile; +using Altinn.Common.PEP.Interfaces; + +namespace Altinn.AccessManagement.Tests.Mocks; + +/// +/// tmp +/// +public class PdpPermitMock: IPDP +{ + /// + public Task GetDecisionForRequest(XacmlJsonRequestRoot xacmlJsonRequest) + { + var response = new XacmlJsonResponse + { + Response = new List(new[] { new XacmlJsonResult { Decision = "Permit" } }) + }; + + return Task.FromResult(response); + } + + /// + public Task GetDecisionForUnvalidateRequest(XacmlJsonRequestRoot xacmlJsonRequest, ClaimsPrincipal user) + { + return Task.FromResult(true); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PepWithPDPAuthorizationMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PepWithPDPAuthorizationMock.cs new file mode 100644 index 00000000..82529bbf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PepWithPDPAuthorizationMock.cs @@ -0,0 +1,448 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using System.Xml; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Tests.Models; +using Altinn.Authorization.ABAC; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Authorization.ABAC.Utils; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Authorization.ABAC.Xacml.JsonProfile; +using Altinn.Common.PEP.Helpers; +using Altinn.Common.PEP.Interfaces; +using Altinn.Platform.Storage.Interface.Models; +using Newtonsoft.Json; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock for IPDP + /// + public class PepWithPDPAuthorizationMock : IPDP + { + private const string OrgAttributeId = "urn:altinn:org"; + + private const string AppAttributeId = "urn:altinn:app"; + + private const string UserAttributeId = "urn:altinn:userid"; + + private const string AltinnRoleAttributeId = "urn:altinn:rolecode"; + + private const string TaskAttributeId = "urn:altinn:task"; + + private const string PartyAttributeId = "urn:altinn:partyid"; + + /// + public async Task GetDecisionForRequest(XacmlJsonRequestRoot xacmlJsonRequest) + { + return await Authorize(xacmlJsonRequest.Request); + } + + private async Task Authorize(XacmlJsonRequest decisionRequest) + { + if (decisionRequest.MultiRequests == null || decisionRequest.MultiRequests.RequestReference == null + || decisionRequest.MultiRequests.RequestReference.Count < 2) + { + XacmlContextRequest request = XacmlJsonXmlConverter.ConvertRequest(decisionRequest); + XacmlContextResponse xmlResponse = await Authorize(request); + return XacmlJsonXmlConverter.ConvertResponse(xmlResponse); + } + else + { + XacmlJsonResponse multiResponse = new XacmlJsonResponse(); + foreach (XacmlJsonRequestReference xacmlJsonRequestReference in decisionRequest.MultiRequests.RequestReference) + { + XacmlJsonRequest jsonMultiRequestPart = new XacmlJsonRequest(); + + foreach (string refer in xacmlJsonRequestReference.ReferenceId) + { + List resourceCategoriesPart = decisionRequest.Resource.Where(i => i.Id.Equals(refer)).ToList(); + + if (resourceCategoriesPart.Count > 0) + { + if (jsonMultiRequestPart.Resource == null) + { + jsonMultiRequestPart.Resource = new List(); + } + + jsonMultiRequestPart.Resource.AddRange(resourceCategoriesPart); + } + + List subjectCategoriesPart = decisionRequest.AccessSubject.Where(i => i.Id.Equals(refer)).ToList(); + + if (subjectCategoriesPart.Count > 0) + { + if (jsonMultiRequestPart.AccessSubject == null) + { + jsonMultiRequestPart.AccessSubject = new List(); + } + + jsonMultiRequestPart.AccessSubject.AddRange(subjectCategoriesPart); + } + + List actionCategoriesPart = decisionRequest.Action.Where(i => i.Id.Equals(refer)).ToList(); + + if (actionCategoriesPart.Count > 0) + { + if (jsonMultiRequestPart.Action == null) + { + jsonMultiRequestPart.Action = new List(); + } + + jsonMultiRequestPart.Action.AddRange(actionCategoriesPart); + } + } + + XacmlContextResponse partResponse = await Authorize(XacmlJsonXmlConverter.ConvertRequest(jsonMultiRequestPart)); + XacmlJsonResponse xacmlJsonResponsePart = XacmlJsonXmlConverter.ConvertResponse(partResponse); + + if (multiResponse.Response == null) + { + multiResponse.Response = new List(); + } + + multiResponse.Response.Add(xacmlJsonResponsePart.Response.First()); + } + + return multiResponse; + } + } + + private async Task Authorize(XacmlContextRequest decisionRequest) + { + decisionRequest = await Enrich(decisionRequest); + + XacmlPolicy policy = await GetPolicyAsync(decisionRequest); + + PolicyDecisionPoint pdp = new PolicyDecisionPoint(); + XacmlContextResponse xacmlContextResponse = pdp.Authorize(decisionRequest, policy); + + return xacmlContextResponse; + } + + /// + public async Task GetDecisionForUnvalidateRequest(XacmlJsonRequestRoot xacmlJsonRequest, ClaimsPrincipal user) + { + XacmlJsonResponse response = await GetDecisionForRequest(xacmlJsonRequest); + return DecisionHelper.ValidatePdpDecision(response.Response, user); + } + + private async Task Enrich(XacmlContextRequest request) + { + await EnrichResourceAttributes(request); + + return request; + } + + private async Task EnrichResourceAttributes(XacmlContextRequest request) + { + XacmlContextAttributes resourceContextAttributes = request.GetResourceAttributes(); + XacmlResourceAttributes resourceAttributes = GetResourceAttributeValues(resourceContextAttributes); + + bool resourceAttributeComplete = false; + + if (!string.IsNullOrEmpty(resourceAttributes.OrgValue) && + !string.IsNullOrEmpty(resourceAttributes.AppValue) && + !string.IsNullOrEmpty(resourceAttributes.InstanceValue) && + !string.IsNullOrEmpty(resourceAttributes.ResourcePartyValue) && + !string.IsNullOrEmpty(resourceAttributes.TaskValue)) + { + // The resource attributes are complete + resourceAttributeComplete = true; + } + else if (!string.IsNullOrEmpty(resourceAttributes.OrgValue) && + !string.IsNullOrEmpty(resourceAttributes.AppValue) && + string.IsNullOrEmpty(resourceAttributes.InstanceValue) && + !string.IsNullOrEmpty(resourceAttributes.ResourcePartyValue) && + string.IsNullOrEmpty(resourceAttributes.TaskValue)) + { + // The resource attributes are complete + resourceAttributeComplete = true; + } + else if (!string.IsNullOrEmpty(resourceAttributes.OrgValue) && + !string.IsNullOrEmpty(resourceAttributes.AppValue) && + !string.IsNullOrEmpty(resourceAttributes.InstanceValue) && + !string.IsNullOrEmpty(resourceAttributes.ResourcePartyValue) && + !string.IsNullOrEmpty(resourceAttributes.AppResourceValue) && + resourceAttributes.AppResourceValue.Equals("events")) + { + // The resource attributes are complete + resourceAttributeComplete = true; + } + else if (!string.IsNullOrEmpty(resourceAttributes.ResourceRegistryId) && + !string.IsNullOrEmpty(resourceAttributes.ResourcePartyValue)) + { + // The resource attributes are complete + resourceAttributeComplete = true; + } + + if (!resourceAttributeComplete) + { + Instance instanceData = GetTestInstance(resourceAttributes.InstanceValue); + + if (string.IsNullOrEmpty(resourceAttributes.OrgValue)) + { + resourceContextAttributes.Attributes.Add(GetOrgAttribute(instanceData)); + } + + if (string.IsNullOrEmpty(resourceAttributes.AppValue)) + { + resourceContextAttributes.Attributes.Add(GetAppAttribute(instanceData)); + } + + if (string.IsNullOrEmpty(resourceAttributes.TaskValue)) + { + resourceContextAttributes.Attributes.Add(GetProcessElementAttribute(instanceData)); + } + + if (string.IsNullOrEmpty(resourceAttributes.ResourcePartyValue)) + { + resourceContextAttributes.Attributes.Add(GetPartyAttribute(instanceData)); + } + + resourceAttributes.ResourcePartyValue = instanceData.InstanceOwner.PartyId; + } + + await EnrichSubjectAttributes(request, resourceAttributes.ResourcePartyValue); + } + + private static XacmlAttribute GetOrgAttribute(Instance instance) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(OrgAttributeId), false); + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), instance.Org)); + return attribute; + } + + private static XacmlAttribute GetAppAttribute(Instance instance) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(AppAttributeId), false); + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), instance.AppId.Split('/')[1])); + return attribute; + } + + private static XacmlAttribute GetProcessElementAttribute(Instance instance) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(TaskAttributeId), false); + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), instance.Process.CurrentTask.ElementId)); + return attribute; + } + + private static XacmlAttribute GetPartyAttribute(Instance instance) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(PartyAttributeId), false); + + // When Party attribute is missing from input it is good to return it so PEP can get this information + attribute.IncludeInResult = true; + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), instance.InstanceOwner.PartyId)); + return attribute; + } + + private static XacmlAttribute GetRoleAttribute(List roles) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(AltinnRoleAttributeId), false); + foreach (Role role in roles) + { + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), role.Value)); + } + + return attribute; + } + + private static void AddIfValueDoesNotExist(XacmlContextAttributes resourceAttributes, string attributeId, string attributeValue, string newAttributeValue) + { + if (string.IsNullOrEmpty(attributeValue)) + { + resourceAttributes.Attributes.Add(GetAttribute(attributeId, newAttributeValue)); + } + } + + private static XacmlAttribute GetAttribute(string attributeId, string attributeValue) + { + XacmlAttribute attribute = new XacmlAttribute(new Uri(attributeId), false); + if (attributeId.Equals(XacmlRequestAttribute.PartyAttribute)) + { + // When Party attribute is missing from input it is good to return it so PEP can get this information + attribute.IncludeInResult = true; + } + + attribute.AttributeValues.Add(new XacmlAttributeValue(new Uri(XacmlConstants.DataTypes.XMLString), attributeValue)); + return attribute; + } + + private async Task EnrichSubjectAttributes(XacmlContextRequest request, string resourceParty) + { + // If there is no resource party then it is impossible to enrich roles + if (string.IsNullOrEmpty(resourceParty)) + { + return; + } + + XacmlContextAttributes subjectContextAttributes = request.GetSubjectAttributes(); + + int subjectUserId = 0; + int resourcePartyId = Convert.ToInt32(resourceParty); + + foreach (XacmlAttribute xacmlAttribute in subjectContextAttributes.Attributes) + { + if (xacmlAttribute.AttributeId.OriginalString.Equals(UserAttributeId)) + { + subjectUserId = Convert.ToInt32(xacmlAttribute.AttributeValues.First().Value); + } + } + + if (subjectUserId == 0) + { + return; + } + + List roleList = await GetDecisionPointRolesForUser(subjectUserId, resourcePartyId) ?? new List(); + + subjectContextAttributes.Attributes.Add(GetRoleAttribute(roleList)); + } + + private static XacmlResourceAttributes GetResourceAttributeValues(XacmlContextAttributes resourceContextAttributes) + { + XacmlResourceAttributes resourceAttributes = new XacmlResourceAttributes(); + + foreach (XacmlAttribute attribute in resourceContextAttributes.Attributes) + { + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.OrgAttribute)) + { + resourceAttributes.OrgValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.AppAttribute)) + { + resourceAttributes.AppValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.InstanceAttribute)) + { + resourceAttributes.InstanceValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.PartyAttribute)) + { + resourceAttributes.ResourcePartyValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.TaskAttribute)) + { + resourceAttributes.TaskValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.AppResourceAttribute)) + { + resourceAttributes.AppResourceValue = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.ResourceRegistryAttribute)) + { + resourceAttributes.ResourceRegistryId = attribute.AttributeValues.First().Value; + } + + if (attribute.AttributeId.OriginalString.Equals(XacmlRequestAttribute.OrganizationNumberAttribute)) + { + resourceAttributes.OrganizationNumber = attribute.AttributeValues.First().Value; + } + } + + return resourceAttributes; + } + + private static Task> GetDecisionPointRolesForUser(int coveredByUserId, int offeredByPartyId) + { + string rolesPath = GetRolesPath(coveredByUserId, offeredByPartyId); + + List roles = new List(); + if (File.Exists(rolesPath)) + { + string content = File.ReadAllText(rolesPath); + roles = (List)JsonConvert.DeserializeObject(content, typeof(List)); + } + + return Task.FromResult(roles); + } + + private static string GetRolesPath(int userId, int resourcePartyId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PepWithPDPAuthorizationMock).Assembly.Location).LocalPath); + var fullRolePath = Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Roles", "user_" + userId, "party_" + resourcePartyId, "roles.json"); + return fullRolePath; + } + + private async Task GetPolicyAsync(XacmlContextRequest request) + { + XacmlPolicy xacmlPolicy = ParsePolicy("policy.xml", GetPolicyPath(request)); + return await Task.FromResult(xacmlPolicy); + } + + private static string GetPolicyPath(XacmlContextRequest request) + { + var resourceId = string.Empty; + var partyId = string.Empty; + foreach (var attributes in request.Attributes) + { + if (attributes.Category.OriginalString.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + foreach (var attribute in attributes.Attributes) + { + switch (attribute.AttributeId.OriginalString) + { + case XacmlRequestAttribute + .ResourceRegistryAttribute: + resourceId = attribute.AttributeValues.First().Value; + break; + case XacmlRequestAttribute.PartyAttribute: + partyId = attribute.AttributeValues.First().Value; + break; + } + } + } + } + + return GetResourceAccessPolicyPath(resourceId); + } + + private static XacmlPolicy ParsePolicy(string policyDocumentTitle, string policyPath) + { + XmlDocument policyDocument = new XmlDocument(); + policyDocument.Load(Path.Combine(policyPath, policyDocumentTitle)); + XacmlPolicy policy; + using (XmlReader reader = XmlReader.Create(new StringReader(policyDocument.OuterXml))) + { + policy = XacmlParser.ParseXacmlPolicy(reader); + } + + return policy; + } + + private static string GetResourceAccessPolicyPath(string ressursid) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PepWithPDPAuthorizationMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Xacml", "3.0", "ResourceRegistry", $"{ressursid}"); + } + + private static string GetInstancePath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PepWithPDPAuthorizationMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Instances"); + } + + private Instance GetTestInstance(string instanceId) + { + string partyPart = instanceId.Split('/')[0]; + string instancePart = instanceId.Split('/')[1]; + + string content = File.ReadAllText(Path.Combine(GetInstancePath(), $"{partyPart}/{instancePart}.json")); + Instance instance = (Instance)JsonConvert.DeserializeObject(content, typeof(Instance)); + return instance; + } + } + +#pragma warning restore SA1600 // ElementsMustBeDocumented +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyFactoryMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyFactoryMock.cs new file mode 100644 index 00000000..a2d52aaa --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyFactoryMock.cs @@ -0,0 +1,23 @@ +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Microsoft.Extensions.Logging; + +namespace Altinn.AccessManagement.Tests.Mocks; + +/// +public class PolicyFactoryMock(ILogger logger) : IPolicyFactory +{ + private ILogger Logger { get; } = logger; + + /// + public IPolicyRepository Create(PolicyAccountType account, string filepath) + { + return new PolicyRepositoryMock(filepath, Logger); + } + + /// + public IPolicyRepository Create(string filepath) + { + return new PolicyRepositoryMock(filepath, Logger); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRepositoryMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRepositoryMock.cs new file mode 100644 index 00000000..86204827 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRepositoryMock.cs @@ -0,0 +1,142 @@ +using System; +using System.IO; +using System.Net; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Azure; +using Azure.Storage.Blobs.Models; +using Microsoft.Extensions.Logging; +using Moq; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class PolicyRepositoryMock(string filepath, ILogger logger) : IPolicyRepository + { + private string Filepath { get; } = filepath; + + private ILogger Logger { get; } = logger; + + /// + public Task GetPolicyAsync(CancellationToken cancellationToken = default) + { + return Task.FromResult(GetTestDataStream(Filepath)); + } + + /// + public Task GetPolicyVersionAsync(string version, CancellationToken cancellationToken = default) + { + return Task.FromResult(GetTestDataStream(Filepath)); + } + + /// + public Task> WritePolicyAsync(Stream fileStream, CancellationToken cancellationToken = default) + { + return WriteStreamToTestDataFolder(Filepath, fileStream); + } + + /// + public Task DeletePolicyVersionAsync(string version, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + public async Task> WritePolicyConditionallyAsync(Stream fileStream, string blobLeaseId, CancellationToken cancellationToken = default) + { + if (blobLeaseId == "CorrectLeaseId" && !Filepath.Contains("error/blobstorageleaselockwritefail")) + { + return await WriteStreamToTestDataFolder(Filepath, fileStream); + } + + throw new RequestFailedException((int)HttpStatusCode.PreconditionFailed, "The condition specified using HTTP conditional header(s) is not met."); + } + + /// + public Task TryAcquireBlobLease(CancellationToken cancellationToken = default) + { + if (Filepath.Contains("error/blobstoragegetleaselockfail")) + { + return Task.FromResult((string)null); + } + + return Task.FromResult("CorrectLeaseId"); + } + + /// + public void ReleaseBlobLease(string leaseId, CancellationToken cancellationToken = default) + { + } + + /// + public Task PolicyExistsAsync(CancellationToken cancellationToken = default) + { + string fullpath = Path.Combine(GetDataInputBlobPath(), Filepath); + + if (File.Exists(fullpath)) + { + return Task.FromResult(true); + } + + Logger.LogWarning("Policy not found for full path" + fullpath); + + return Task.FromResult(false); + } + + private static string GetDataOutputBlobPath() + { + return Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Data", "blobs", "output"); + } + + private static string GetDataInputBlobPath() + { + return Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Data", "blobs", "input"); + } + + private static Stream GetTestDataStream(string filepath) + { + string dataPath = Path.Combine(GetDataInputBlobPath(), filepath); + Stream ms = new MemoryStream(); + if (File.Exists(dataPath)) + { + using FileStream file = new FileStream(dataPath, FileMode.Open, FileAccess.Read); + file.CopyTo(ms); + } + + return ms; + } + + private static async Task> WriteStreamToTestDataFolder(string filepath, Stream fileStream) + { + string dataPath = Path.Combine(GetDataOutputBlobPath(), filepath); + + if (!Directory.Exists(Path.GetDirectoryName(dataPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(dataPath)); + } + + int filesize; + + using (Stream streamToWriteTo = File.Open(dataPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) + { + await fileStream.CopyToAsync(streamToWriteTo); + streamToWriteTo.Flush(); + filesize = (int)streamToWriteTo.Length; + } + + BlobContentInfo mockedBlobInfo = BlobsModelFactory.BlobContentInfo(new ETag("ETagSuccess"), DateTime.Now, new byte[1], DateTime.Now.ToUniversalTime().ToString(), "encryptionKeySha256", "encryptionScope", 1); + Mock> mockResponse = new Mock>(); + mockResponse.SetupGet(r => r.Value).Returns(mockedBlobInfo); + + Mock responseMock = new Mock(); + responseMock.SetupGet(r => r.Status).Returns((int)HttpStatusCode.Created); + mockResponse.Setup(r => r.GetRawResponse()).Returns(responseMock.Object); + + return mockResponse.Object; + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRetrievalPointMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRetrievalPointMock.cs new file mode 100644 index 00000000..3956287b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/PolicyRetrievalPointMock.cs @@ -0,0 +1,181 @@ +using System.Xml; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Tests.Controllers; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Authorization.ABAC.Utils; +using Altinn.Authorization.ABAC.Xacml; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class PolicyRetrievalPointMock : IPolicyRetrievalPoint + { + private readonly IHttpContextAccessor _httpContextAccessor; + + private readonly ILogger _logger; + + private readonly string _orgAttributeId = "urn:altinn:org"; + + private readonly string _appAttributeId = "urn:altinn:app"; + + /// + /// Constructor setting up dependencies + /// + /// httpContextAccessor + /// logger + public PolicyRetrievalPointMock(IHttpContextAccessor httpContextAccessor, ILogger logger) + { + _httpContextAccessor = httpContextAccessor; + _logger = logger; + } + + /// + /// Empty constructor. + /// + public PolicyRetrievalPointMock() + { + } + + /// + public async Task GetPolicyAsync(XacmlContextRequest request, CancellationToken cancellationToken = default) + { + string testID = GetTestId(_httpContextAccessor.HttpContext); + if (!string.IsNullOrEmpty(testID) && testID.ToLower().Contains("altinnapps")) + { + if (File.Exists(Path.Combine(GetPolicyPath(request), "policy.xml"))) + { + return await Task.FromResult(ParsePolicy("policy.xml", GetPolicyPath(request))); + } + + return await Task.FromResult(ParsePolicy(testID + "Policy.xml", GetAltinnAppsPath())); + } + else + { + return await Task.FromResult(ParsePolicy(testID + "Policy.xml", GetConformancePath())); + } + } + + /// + public async Task GetPolicyAsync(string org, string app, CancellationToken cancellationToken = default) + { + if (File.Exists(Path.Combine(GetAltinnAppsPolicyPath(org, app), "policy.xml"))) + { + return await Task.FromResult(ParsePolicy("policy.xml", GetAltinnAppsPolicyPath(org, app))); + } + + return null; + } + + /// + public async Task GetPolicyAsync(string resourceRegistry, CancellationToken cancellationToken = default) + { + if (File.Exists(Path.Combine(GetAltinnResourcePolicyPath(resourceRegistry), "resourcepolicy.xml"))) + { + return await Task.FromResult(ParsePolicy("resourcepolicy.xml", GetAltinnResourcePolicyPath(resourceRegistry))); + } + + return null; + } + + /// + public async Task GetPolicyVersionAsync(string policyPath, string version, CancellationToken cancellationToken = default) + { + string path = GetAltinnAppsDelegationPolicyPath(policyPath); + if (File.Exists(path)) + { + return await Task.FromResult(ParsePolicy(string.Empty, path)); + } + + _logger.LogWarning("Policy Version did not found policy " + path); + + return null; + } + + private static XacmlPolicy ParsePolicy(string policyDocumentTitle, string policyPath) + { + XmlDocument policyDocument = new XmlDocument(); + + policyDocument.Load(Path.Combine(policyPath, policyDocumentTitle)); + XacmlPolicy policy; + using (XmlReader reader = XmlReader.Create(new StringReader(policyDocument.OuterXml))) + { + policy = XacmlParser.ParseXacmlPolicy(reader); + } + + return policy; + } + + private string GetPolicyPath(XacmlContextRequest request) + { + string org = string.Empty; + string app = string.Empty; + foreach (XacmlContextAttributes attr in request.Attributes) + { + if (attr.Category.OriginalString.Equals(XacmlConstants.MatchAttributeCategory.Resource)) + { + foreach (XacmlAttribute asd in attr.Attributes) + { + if (asd.AttributeId.OriginalString.Equals(_orgAttributeId)) + { + foreach (var asff in asd.AttributeValues) + { + org = asff.Value; + break; + } + } + + if (asd.AttributeId.OriginalString.Equals(_appAttributeId)) + { + foreach (var asff in asd.AttributeValues) + { + app = asff.Value; + break; + } + } + } + } + } + + return GetAltinnAppsPolicyPath(org, app); + } + + private string GetAltinnAppsPolicyPath(string org, string app) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Xacml", "3.0", "AltinnApps", org, app); + } + + private string GetAltinnResourcePolicyPath(string resourceRegistryId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Xacml", "3.0", "ResourceRegistry", resourceRegistryId); + } + + private static string GetAltinnAppsDelegationPolicyPath(string policyPath) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "blobs", "input", policyPath); + } + + private string GetTestId(HttpContext context) + { + return context.Request.Headers["testcase"]; + } + + private string GetAltinnAppsPath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Xacml", "3.0", "AltinnApps"); + } + + private string GetConformancePath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "Xacml", "3.0", "ConformanceTests"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ProfileClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ProfileClientMock.cs new file mode 100644 index 00000000..630ec783 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ProfileClientMock.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models.Profile; +using Altinn.Platform.Profile.Models; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class ProfileClientMock : IProfileClient + { + /// + public Task GetUser(UserProfileLookup userProfileLookup, CancellationToken cancellationToken = default) + { + UserProfile userProfile = null; + + string userProfilePath = GetUserProfilePath(userProfileLookup); + + if (File.Exists(userProfilePath)) + { + string content = File.ReadAllText(userProfilePath); + userProfile = (UserProfile)JsonSerializer.Deserialize(content, typeof(UserProfile), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + + return Task.FromResult(userProfile); + } + + private static string GetUserProfilePath(UserProfileLookup userProfileLookup) + { + string userIdentifier = userProfileLookup.UserId > 0 ? userProfileLookup.UserId.ToString() : userProfileLookup.Ssn ?? userProfileLookup.Username ?? userProfileLookup.UserUuid?.ToString(); + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(ProfileClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "UserProfile", $"{userIdentifier}.json"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceMetadataRepositoryMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceMetadataRepositoryMock.cs new file mode 100644 index 00000000..dbaefa11 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceMetadataRepositoryMock.cs @@ -0,0 +1,40 @@ +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock for ResourceMetadataRepository + /// + public class ResourceMetadataRepositoryMock : IResourceMetadataRepository + { + /// + /// Mock + /// + /// the resource to store in AccessManagment + /// CancellationToken + /// the inserted/updated resource + public Task InsertAccessManagementResource(AccessManagementResource resource, CancellationToken cancellationToken = default) + { + AccessManagementResource result = null + ; + if (resource.ResourceRegistryId == "string3") + { + return Task.FromResult(result); + } + + Stream dataStream = File.OpenRead($"Data/Json/InsertAccessManagementResource/InsertData_{resource.ResourceRegistryId}.json"); + JsonSerializerOptions options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + result = JsonSerializer.Deserialize(dataStream, options); + return Task.FromResult(result); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceRegistryClientMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceRegistryClientMock.cs new file mode 100644 index 00000000..ac0d6cef --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/ResourceRegistryClientMock.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Integration.Clients; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock class for interface + /// + public class ResourceRegistryClientMock : IResourceRegistryClient + { + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Initializes a new instance of the class + /// + public ResourceRegistryClientMock() + { + } + + /// + public async Task GetResource(string resourceId, CancellationToken cancellationToken = default) + { + ServiceResource resource = null; + string rolesPath = GetResourcePath(resourceId); + if (File.Exists(rolesPath)) + { + string content = File.ReadAllText(rolesPath); + resource = (ServiceResource)JsonSerializer.Deserialize(content, typeof(ServiceResource), _serializerOptions); + } + + return await Task.FromResult(resource); + } + + /// + public Task> GetResources(CancellationToken cancellationToken = default) + { + List resources = new List(); + + string path = GetDataPathForResources(); + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + foreach (string file in files) + { + if (file.Contains("resources")) + { + string content = File.ReadAllText(Path.Combine(path, file)); + resources = JsonSerializer.Deserialize>(content, _serializerOptions); + } + } + } + + return Task.FromResult(resources); + } + + /// + public Task> GetResourceList(CancellationToken cancellationToken = default) + { + string content = File.ReadAllText($"Data/Resources/resourceList.json"); + List resources = (List)JsonSerializer.Deserialize(content, typeof(List), _serializerOptions); + + return Task.FromResult(resources); + } + + /// + public Task>> GetSubjectResources(IEnumerable subjects, CancellationToken cancellationToken = default) + { + string content = File.ReadAllText($"Data/Resources/subjectResources.json"); + PaginatedResult allSubjectResources = (PaginatedResult)JsonSerializer.Deserialize(content, typeof(PaginatedResult), _serializerOptions); + + IDictionary> result = new Dictionary>(); + if (allSubjectResources != null && allSubjectResources.Items != null) + { + foreach (SubjectResources resultItem in allSubjectResources.Items.Where(sr => subjects.Contains(sr.Subject.Urn))) + { + result.Add(resultItem.Subject.Urn, resultItem.Resources); + } + } + + return Task.FromResult(result); + } + + private static string GetResourcePath(string resourceRegistryId) + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(ResourceRegistryClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "Data", "ResourceRegistryResources", $"{resourceRegistryId}", "resource.json"); + } + + private static string GetDataPathForResources() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(ResourceRegistryClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "Resources"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/SigningKeyResolverMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/SigningKeyResolverMock.cs new file mode 100644 index 00000000..12c61d48 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Mocks/SigningKeyResolverMock.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; +using Altinn.Common.AccessToken.Services; +using Microsoft.IdentityModel.Tokens; + +namespace Altinn.AccessManagement.Tests.Mocks +{ + /// + /// Mock for finding signing key on disk + /// + public class SigningKeyResolverMock : IPublicSigningKeyProvider + { + /// + /// Not implemented + /// + public SigningCredentials GetSigningCredentials() + { + throw new NotImplementedException(); + } + + /// + public Task> GetSigningKeys(string issuer) + { + List signingKeys = new List(); + + X509Certificate2 cert = new X509Certificate2($"{issuer}-org.pem"); + SecurityKey key = new X509SecurityKey(cert); + + signingKeys.Add(key); + + return Task.FromResult(signingKeys.AsEnumerable()); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Role.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Role.cs new file mode 100644 index 00000000..0f100f08 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Role.cs @@ -0,0 +1,23 @@ +using System; +using Newtonsoft.Json; + +namespace Altinn.AccessManagement.Tests.Models; + +/// +/// Entity representing a Role +/// +[Serializable] +public class Role +{ + /// + /// Gets or sets the role type + /// + [JsonProperty] + public string Type { get; set; } + + /// + /// Gets or sets the role + /// + [JsonProperty] + public string Value { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ActionIdentifierTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ActionIdentifierTest.cs new file mode 100644 index 00000000..6a6a4441 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ActionIdentifierTest.cs @@ -0,0 +1,141 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.Rights; + +namespace Altinn.AccessManagement.Tests.Models.Urn +{ + public class ActionIdentifierTest + { + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Scenario: + /// Tests the ActionIdentifier Json deserializing + /// Input: + /// Parse a valid ActionIdentifier + /// Expected Result: + /// Create a ActionIdentifier with the value from the input + /// + [Fact] + public void TestActionIdentifierJson_DeSerializng_Success() + { + string actionIdentifierString = @"""read"""; + ActionIdentifier actionIdentifier = JsonSerializer.Deserialize(actionIdentifierString, JsonOptions); + + Assert.Equal("read", actionIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ActionIdentifier Json serializing + /// Input: + /// Parse a valid ActionIdentifier + /// Expected Result: + /// Create a ActionIdentifier with the value from the input + /// + [Fact] + public void TestActionIdentifierJson_Serializng_Success() + { + ActionIdentifier actionIdentifier = ActionIdentifier.Parse("read"); + string actionIdentifierJson = JsonSerializer.Serialize(actionIdentifier, JsonOptions); + + Assert.Equal(@"""read""", actionIdentifierJson); + } + + /// + /// Scenario: + /// Tests the ActionIdentifier Parse string + /// Input: + /// Parse a valid ActionIdentifier + /// Expected Result: + /// Create a Organization number with the value from the input + /// + [Fact] + public void TestActionIdentifierString_Parse_Success() + { + ActionIdentifier actionIdentifier = ActionIdentifier.Parse("read"); + Assert.Equal("read", actionIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ActionIdentifier Parse ReadOnlyCharSpan + /// Input: + /// Parse a valid ActionIdentifier + /// Expected Result: + /// Create a ActionIdentifier with the value from the input + /// + [Fact] + public void TestActionIdentifierReadOnlyCharSpan_Parse_Success() + { + ReadOnlySpan actionIdentifierSpan = "read"; + ActionIdentifier actionIdentifier = ActionIdentifier.Parse(actionIdentifierSpan); + Assert.Equal("read", actionIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ActionIdentifier GetExample + /// Input: + /// Get expected Example + /// Expected Result: + /// Create a ActionIdentifier with the value from the input + /// + [Fact] + public void TestActionIdentifier_GetExample_Success() + { + List expected = new List(); + expected.Add(ActionIdentifier.Parse("read")); + expected.Add(ActionIdentifier.Parse("write")); + + List actual = ActionIdentifier.GetExamples(new Swashbuckle.Examples.ExampleDataOptions()).ToList(); + + Assert.Equal(expected.Count, actual.Count); + + for (int i = 0; i < expected.Count; i++) + { + Assert.Equal(expected[i].ToString(), actual[i].ToString()); + } + } + + /// + /// Scenario: + /// Tests the ActionIdentifier TryFormat + /// Input: + /// TryFormat an ActionIdentifier into a Span exactly the length og orgnr + /// Expected Result: + /// Formats the ActionIdentifier into the expected span and returns true and sends the number of characters formated into result + /// + [Fact] + public void TestActionIdentifier_TryFormat_Success() + { + string expected = "read"; + ActionIdentifier actionIdentifier = ActionIdentifier.Parse(expected); + Span result = new Span(new char[expected.Length]); + bool ok = actionIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result.ToString().Trim()); + Assert.Equal(expected.Length, charsWritten); + Assert.True(ok); + } + + /// + /// Scenario: + /// Tests the ActionIdentifier TryFormat + /// Input: + /// TryFormat an ActionIdentifier into a Span to small + /// Expected Result: + /// Does nothing and returns false and outputs 0 as the number of characters formated + /// + [Fact] + public void TestActionIdentifier_TryFormat_Fail() + { + string input = "read"; + ActionIdentifier actionIdentifier = ActionIdentifier.Parse(input); + Span result = new Span(new char[3]); + Span expected = new Span(new char[3]); + bool ok = actionIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result); + Assert.Equal(0, charsWritten); + Assert.False(ok); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/OrganizationNumberTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/OrganizationNumberTest.cs new file mode 100644 index 00000000..4e47428d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/OrganizationNumberTest.cs @@ -0,0 +1,213 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.Register; + +namespace Altinn.AccessManagement.Tests.Models.Urn +{ + [Collection("Models Test")] + public class OrganizationNumberTest + { + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Scenario: + /// Tests the OrganizationNumber Json Deserializing + /// Input: + /// Parse a valid OrganizationNumber + /// Expected Result: + /// Create a OrganizationNumber with the value from the input + /// + [Fact] + public void TestOrganizationNumberJson_DeSerializng_Success() + { + string orgNumberString = @"""123456789"""; + OrganizationNumber orgNr = JsonSerializer.Deserialize(orgNumberString, JsonOptions); + + Assert.Equal("123456789", orgNr.ToString()); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber Json Deserializing + /// Input: + /// Parse a invalid OrganizationNumber + /// Expected Result: + /// Throws an exception + /// + [Fact] + public void TestOrganizationNumberJson_DeSerializng_Fail() + { + string orgNumberString = @"""123456f89"""; + try + { + OrganizationNumber orgNr = JsonSerializer.Deserialize(orgNumberString, JsonOptions); + } + catch + { + return; + } + + Assert.Fail("Should fail and not reach here"); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber Json Serializing + /// Input: + /// Parse a valid OrganizationNumber + /// Expected Result: + /// Create a OrganizationNumber with the value from the input + /// + [Fact] + public void TestOrganizationNumberJson_Serializng_Success() + { + OrganizationNumber orgNr = OrganizationNumber.Parse("123456789"); + string orgNrJson = JsonSerializer.Serialize(orgNr, JsonOptions); + + Assert.Equal(@"""123456789""", orgNrJson); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber Parse String + /// Input: + /// Parse a valid OrganizationNumber + /// Expected Result: + /// Create a OrganizationNumber with the value from the input + /// + [Fact] + public void TestOrganizationNumberString_Parse_Success() + { + OrganizationNumber orgNr = OrganizationNumber.Parse("123456789"); + Assert.Equal("123456789", orgNr.ToString()); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber + /// Input: + /// Parse a valid OrganizationNumber Parse CharSpan + /// Expected Result: + /// Create a Organization number with the value from the input + /// + [Fact] + public void TestOrganizationNumberReadOnlyCharSpan_Parse_Success() + { + ReadOnlySpan orgNrSpan = "123456789"; + OrganizationNumber orgNr = OrganizationNumber.Parse(orgNrSpan); + Assert.Equal("123456789", orgNr.ToString()); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber Parse CharSpan + /// Input: + /// Parse a invalid OrganizationNumber + /// Expected Result: + /// Fails with exception + /// + [Fact] + public void TestOrganizationNumberReadOnlyCharSpan_Fail() + { + try + { + ReadOnlySpan orgNrSpan = "1234567890"; + OrganizationNumber orgNr = OrganizationNumber.Parse(orgNrSpan); + } + catch + { + return; + } + + Assert.Fail("Should fail and never reach this block"); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber Parse String + /// Input: + /// Parse a invalid OrganizationNumber + /// Expected Result: + /// Fails with exception + /// + [Fact] + public void TestOrganizationNumberString_Parse_Fail() + { + try + { + OrganizationNumber orgNr = OrganizationNumber.Parse("123456g89"); + } + catch + { + return; + } + + Assert.Fail("Should fail and never reach this block"); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber GetExample + /// Input: + /// Get expected Example + /// Expected Result: + /// Gets the expected Example + /// + [Fact] + public void TestOrganizationNumber_GetExample_Success() + { + List expected = new List(); + expected.Add(OrganizationNumber.Parse("987654321")); + expected.Add(OrganizationNumber.Parse("123456789")); + + List actual = OrganizationNumber.GetExamples(new Swashbuckle.Examples.ExampleDataOptions()).ToList(); + + Assert.Equal(expected.Count, actual.Count); + + for (int i = 0; i < expected.Count; i++) + { + Assert.Equal(expected[i].ToString(), actual[i].ToString()); + } + } + + /// + /// Scenario: + /// Tests the OrganizationNumber TryFormat + /// Input: + /// TryFormat an OrganizationNumber into a Span exactly the length og orgnr + /// Expected Result: + /// Formats the organizationNumber into the expected span and returns true and sends the number of characters formated into result + /// + [Fact] + public void TestOrganizationNumber_TryFormat_Success() + { + string expected = "987654321"; + OrganizationNumber organizationNumber = OrganizationNumber.Parse(expected); + Span result = new Span(new char[expected.Length]); + bool ok = organizationNumber.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result.ToString().Trim()); + Assert.Equal(expected.Length, charsWritten); + Assert.True(ok); + } + + /// + /// Scenario: + /// Tests the OrganizationNumber TryFormat + /// Input: + /// TryFormat an OrganizationNumber into a Span to small + /// Expected Result: + /// Does nothing and returns false and outputs 0 as the number of characters formated + /// + [Fact] + public void TestOrganizationNumber_TryFormat_Fail() + { + string input = "987654321"; + OrganizationNumber organizationNumber = OrganizationNumber.Parse(input); + Span result = new Span(new char[6]); + Span expected = new Span(new char[6]); + bool ok = organizationNumber.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result); + Assert.Equal(0, charsWritten); + Assert.False(ok); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceIdentifierTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceIdentifierTest.cs new file mode 100644 index 00000000..9f88c357 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceIdentifierTest.cs @@ -0,0 +1,212 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Tests.Models.Urn +{ + public class ResourceIdentifierTest + { + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Scenario: + /// Tests the ResourceIdentifier Json Deserializing + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifierJson_DeSerializng_Success() + { + string resourceIdentifierString = @"""example-resourceid"""; + ResourceIdentifier resourceIdentifier = JsonSerializer.Deserialize(resourceIdentifierString, JsonOptions); + + Assert.Equal("example-resourceid", resourceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Json Deserializing + /// Input: + /// Parse a invalid ResourceIdentifier + /// Expected Result: + /// Throws exception + /// + [Fact] + public void TestResourceIdentifierJson_DeSerializng_Fail() + { + string resourceIdentifierString = @"""exa"""; + try + { + ResourceIdentifier resourceIdentifier = JsonSerializer.Deserialize(resourceIdentifierString, JsonOptions); + } + catch + { + return; + } + + Assert.Fail("Should fail and not reach here"); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Json Serializing + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifierJson_Serializng_Success() + { + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse("example-resourceid"); + string orgNrJson = JsonSerializer.Serialize(resourceIdentifier, JsonOptions); + + Assert.Equal(@"""example-resourceid""", orgNrJson); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Parse String + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifierString_Parse_Success() + { + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse("example-resourceid"); + Assert.Equal("example-resourceid", resourceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Parse CharSpan + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifierReadOnlyCharSpan_Parse_Success() + { + ReadOnlySpan resourceIdentifierSpan = "example-resourceid"; + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse(resourceIdentifierSpan); + Assert.Equal("example-resourceid", resourceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Parse CharSpan + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifierReadOnlyCharSpan_Fail() + { + try + { + ReadOnlySpan resourceIdentifierSpan = "exa"; + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse(resourceIdentifierSpan); + } + catch + { + return; + } + + Assert.Fail("Should fail and never reach this block"); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier Parse String + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Throws an exception + /// + [Fact] + public void TestResourceIdentifierString_Parse_Fail() + { + try + { + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse("exa"); + } + catch + { + return; + } + + Assert.Fail("Should fail and never reach this block"); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier + /// Input: + /// Parse a valid ResourceIdentifier + /// Expected Result: + /// Create a ResourceIdentifier with the value from the input + /// + [Fact] + public void TestResourceIdentifier_GetExample_Success() + { + List expected = new List(); + expected.Add(ResourceIdentifier.Parse("example-resourceid")); + expected.Add(ResourceIdentifier.Parse("app_skd_flyttemelding")); + + List actual = ResourceIdentifier.GetExamples(new Swashbuckle.Examples.ExampleDataOptions()).ToList(); + + Assert.Equal(expected.Count, actual.Count); + + for (int i = 0; i < expected.Count; i++) + { + Assert.Equal(expected[i].ToString(), actual[i].ToString()); + } + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier TryFormat + /// Input: + /// TryFormat an ResourceIdentifier into a Span exactly the length og orgnr + /// Expected Result: + /// Formats the ResourceIdentifier into the expected span and returns true and sends the number of characters formated into result + /// + [Fact] + public void TestResourceIdentifier_TryFormat_Success() + { + string expected = "example-resourceid"; + ResourceIdentifier resourceInstanceIdentifier = ResourceIdentifier.Parse(expected); + Span result = new Span(new char[expected.Length]); + bool ok = resourceInstanceIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result.ToString().Trim()); + Assert.Equal(expected.Length, charsWritten); + Assert.True(ok); + } + + /// + /// Scenario: + /// Tests the ResourceIdentifier TryFormat + /// Input: + /// TryFormat an ResourceIdentifier into a Span to small + /// Expected Result: + /// Does nothing and returns false and outputs 0 as the number of characters formated + /// + [Fact] + public void TestResourceInstanceIdentifier_TryFormat_Fail() + { + string input = "example-resourceid"; + ResourceIdentifier resourceInstanceIdentifier = ResourceIdentifier.Parse(input); + Span result = new Span(new char[6]); + Span expected = new Span(new char[6]); + bool ok = resourceInstanceIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result); + Assert.Equal(0, charsWritten); + Assert.False(ok); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceInstanceIdentifierTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceInstanceIdentifierTest.cs new file mode 100644 index 00000000..a4c400fe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/Urn/ResourceInstanceIdentifierTest.cs @@ -0,0 +1,141 @@ +using System.Text.Json; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Tests.Models.Urn +{ + public class ResourceInstanceIdentifierTest + { + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier Json Deserializing + /// Input: + /// Parse a valid ResourceInstanceIdentifier + /// Expected Result: + /// Create a ResourceInstanceIdentifier with the value from the input + /// + [Fact] + public void TestResourceInstanceIdentifierJson_DeSerializng_Success() + { + string resourceInstanceIdentifierString = @"""0191579e-72bc-7977-af5d-f9e92af4393b"""; + ResourceInstanceIdentifier resourceInstanceIdentifier = JsonSerializer.Deserialize(resourceInstanceIdentifierString, JsonOptions); + + Assert.Equal("0191579e-72bc-7977-af5d-f9e92af4393b", resourceInstanceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier Json Deserializing + /// Input: + /// Parse a valid ResourceInstanceIdentifier + /// Expected Result: + /// Create a ResourceInstanceIdentifier with the value from the input + /// + [Fact] + public void TestResourceInstanceIdentifierJson_Serializng_Success() + { + ResourceInstanceIdentifier resourceInstanceIdentifier = ResourceInstanceIdentifier.Parse("0191579e-72bc-7977-af5d-f9e92af4393b"); + string orgNrJson = JsonSerializer.Serialize(resourceInstanceIdentifier, JsonOptions); + + Assert.Equal(@"""0191579e-72bc-7977-af5d-f9e92af4393b""", orgNrJson); + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier Parse String + /// Input: + /// Parse a valid ResourceInstanceIdentifier + /// Expected Result: + /// Create a ResourceInstanceIdentifier with the value from the input + /// + [Fact] + public void TestResourceInstanceIdentifierString_Parse_Success() + { + ResourceInstanceIdentifier resourceInstanceIdentifier = ResourceInstanceIdentifier.Parse("0191579e-72bc-7977-af5d-f9e92af4393b"); + Assert.Equal("0191579e-72bc-7977-af5d-f9e92af4393b", resourceInstanceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier Parse CharSpan + /// Input: + /// Parse a valid ResourceInstanceIdentifier + /// Expected Result: + /// Create a ResourceInstanceIdentifier with the value from the input + /// + [Fact] + public void TestResourceInstanceIdentifierReadOnlyCharSpan_Parse_Success() + { + ReadOnlySpan resourceInstanceIdentifierSpan = "0191579e-72bc-7977-af5d-f9e92af4393b"; + ResourceInstanceIdentifier resourceInstanceIdentifier = ResourceInstanceIdentifier.Parse(resourceInstanceIdentifierSpan); + Assert.Equal("0191579e-72bc-7977-af5d-f9e92af4393b", resourceInstanceIdentifier.ToString()); + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier GetExample + /// Input: + /// Nothing + /// Expected Result: + /// Returns ResourceInstanceIdentifier Examples + /// + [Fact] + public void TestResourceInstanceIdentifier_GetExample_Success() + { + List expected = new List(); + expected.Add(ResourceIdentifier.Parse("0191579e-72bc-7977-af5d-f9e92af4393b")); + expected.Add(ResourceIdentifier.Parse("ext_1337")); + + List actual = ResourceInstanceIdentifier.GetExamples(new Swashbuckle.Examples.ExampleDataOptions()).ToList(); + + Assert.Equal(expected.Count, actual.Count); + + for (int i = 0; i < expected.Count; i++) + { + Assert.Equal(expected[i].ToString(), actual[i].ToString()); + } + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier TryFormat + /// Input: + /// TryFormat an ResourceInstanceIdentifier into a Span exactly the length og orgnr + /// Expected Result: + /// Formats the ResourceInstanceIdentifier into the expected span and returns true and sends the number of characters formated into result + /// + [Fact] + public void TestResourceInstanceIdentifier_TryFormat_Success() + { + string expected = "0191579e-72bc-7977-af5d-f9e92af4393b"; + ResourceInstanceIdentifier resourceInstanceIdentifier = ResourceInstanceIdentifier.Parse(expected); + Span result = new Span(new char[36]); + bool ok = resourceInstanceIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result.ToString().Trim()); + Assert.Equal(expected.Length, charsWritten); + Assert.True(ok); + } + + /// + /// Scenario: + /// Tests the ResourceInstanceIdentifier TryFormat + /// Input: + /// TryFormat an ResourceInstanceIdentifier into a Span to small + /// Expected Result: + /// Does nothing and returns false and outputs 0 as the number of characters formated + /// + [Fact] + public void TestResourceInstanceIdentifier_TryFormat_Fail() + { + string input = "0191579e-72bc-7977-af5d-f9e92af4393b"; + ResourceInstanceIdentifier resourceInstanceIdentifier = ResourceInstanceIdentifier.Parse(input); + Span result = new Span(new char[25]); + Span expected = new Span(new char[25]); + bool ok = resourceInstanceIdentifier.TryFormat(result, out int charsWritten, null, null); + Assert.Equal(expected, result); + Assert.Equal(0, charsWritten); + Assert.False(ok); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/XacmlResourceAttributes.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/XacmlResourceAttributes.cs new file mode 100644 index 00000000..4f8b6e9d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Models/XacmlResourceAttributes.cs @@ -0,0 +1,47 @@ +namespace Altinn.AccessManagement.Tests.Models; + +/// +/// TT +/// +public class XacmlResourceAttributes +{ + /// + /// Gets or sets the value for org attribute + /// + public string OrgValue { get; set; } + + /// + /// Gets or sets the value for app attribute + /// + public string AppValue { get; set; } + + /// + /// Gets or sets the value for instance attribute + /// + public string InstanceValue { get; set; } + + /// + /// Gets or sets the value for resourceparty attribute + /// + public string ResourcePartyValue { get; set; } + + /// + /// Gets or sets the value for task attribute + /// + public string TaskValue { get; set; } + + /// + /// Gets or sets the value for app resource. + /// + public string AppResourceValue { get; set; } + + /// + /// Gets or sets the resource registry Id + /// + public string ResourceRegistryId { get; set; } + + /// + /// Gets or sets the OrganizationNumber for the org owning the resource + /// + public string OrganizationNumber { get; set; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/PolicyAdministrationPointTest.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/PolicyAdministrationPointTest.cs new file mode 100644 index 00000000..0678d512 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/PolicyAdministrationPointTest.cs @@ -0,0 +1,1620 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.AccessManagement.Tests.Utils; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Altinn.AccessManagement.Tests +{ + /// + /// Test class for + /// + [Collection("PolicyAdministrationPointTest")] + public class PolicyAdministrationPointTest + { + private readonly IPolicyAdministrationPoint _pap; + private readonly IPolicyFactory _prp; + private readonly IDelegationChangeEventQueue _eventQueue; + private readonly Mock> _logger; + private DelegationMetadataRepositoryMock _delegationMetadataRepositoryMock; + + /// + /// Constructor setting up dependencies + /// + public PolicyAdministrationPointTest() + { + ServiceCollection services = new ServiceCollection(); + services.AddMemoryCache(); + ServiceProvider serviceProvider = services.BuildServiceProvider(); + + IMemoryCache memoryCache = serviceProvider.GetService(); + + _logger = new Mock>(); + _delegationMetadataRepositoryMock = new DelegationMetadataRepositoryMock(); + _prp = new PolicyFactoryMock(new Mock>().Object); + _eventQueue = new DelegationChangeEventQueueMock(); + _pap = new PolicyAdministrationPoint( + new PolicyRetrievalPoint(_prp, memoryCache, Options.Create(new CacheConfig { PolicyCacheTimeout = 1 })), + _prp, + _delegationMetadataRepositoryMock, + _eventQueue, + _logger.Object); + } + + /// + /// Test case: Write to storage a file. + /// Expected: WritePolicyAsync returns true. + /// + [Fact] + public async Task WritePolicy_TC01() + { + // Arrange + Stream dataStream = File.OpenRead("Data/Policies/policy.xml"); + + // Act + bool successfullyStored = await _pap.WritePolicyAsync("org", "app", dataStream); + SetupUtils.DeleteAppBlobData("org", "app"); + + // Assert + Assert.True(successfullyStored); + } + + /// + /// Test case: Write a file to storage where the org parameter arguments is empty. + /// Expected: WritePolicyAsync throws ArgumentException. + /// + [Fact] + public async Task WritePolicy_TC02() + { + // Act & Assert + await Assert.ThrowsAsync(() => _pap.WritePolicyAsync(string.Empty, "app", new MemoryStream())); + } + + /// + /// Test case: Write a file to storage where the app parameter arguments is empty. + /// Expected: WritePolicyAsync throws ArgumentException. + /// + [Fact] + public async Task WritePolicy_TC03() + { + // Act & Assert + await Assert.ThrowsAsync(() => _pap.WritePolicyAsync("org", string.Empty, new MemoryStream())); + } + + /// + /// Test case: Write to storage a file that is null. + /// Expected: WritePolicyAsync throws ArgumentException. + /// + [Fact] + public async Task WritePolicy_TC04() + { + // Act & Assert + await Assert.ThrowsAsync(() => _pap.WritePolicyAsync("org", "app", null)); + } + + /// + /// Test case: Write to storage a file that is null. + /// Expected: WritePolicyAsync throws ArgumentException. + /// + [Fact] + public async Task WritePolicy_TC05() + { + // Act & Assert + await Assert.ThrowsAsync(() => _pap.WritePolicyAsync("org", "app", null)); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, where all rules are deleted the db is updated with RevokeLast status + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_Valid() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app4", new List { "adfa64fa-5859-46e5-8d0d-62762082f3b9" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app4", createdSuccessfully: true) + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + { "org1/app4/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app4", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, where all rules are deleted the db is updated with RevokeLast status, + /// but pushing RevokeLast event to DelegationChangeEventQueue fails which should trigger crittical error logging + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules are deleted from policy and delegationchange stored in postgresql, critical error is logged + /// Success Criteria: + /// All returned rules match expected, and critical error has been logged + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_Valid_DelegationEventQueue_Push_Exception() + { + // Arrange + int performedByUserId = 20001337; + int offeredByPartyId = 50001337; + int coveredBy = 20001336; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "delegationeventfail", new List { "c73079c1-ed67-4958-91e3-a388ee355097" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "error", "delegationeventfail", createdSuccessfully: true) + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "error/delegationeventfail/50001337/u20001336", new List { TestDataUtil.GetAltinnAppDelegationChange("error/delegationeventfail", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Critical, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("DeleteRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange:") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one policy is returned as already deleted the rules ok to delete is deleted the one already deleted ignored + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of deleted policy is ignored rest is deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_PolicyAlredyDeleted() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app5", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app4", new List { "adfa64fa-5859-46e5-8d0d-62762082f3b9" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app4", createdSuccessfully: true) + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + { "org1/app4/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app4", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "The policy is already deleted for: org1/app5 CoveredBy: 20001337 OfferedBy: 50001337"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether all rules are returned as successfully deleated whera all rules are deleted the db is also updated with isDeleted status + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_ForOrganizationValid() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 50001336; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app1", new List { "57b3ee85-f932-42c6-9ab0-941eb6c96eb0", "78e5cced-3bcb-42b6-9089-63c834f89e73" }, coveredByPartyId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app1", "task1", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app1/50001337/p50001336", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app1", offeredByPartyId, performedByUserId: performedByUserId, coveredByPartyId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one rules are returned as not successfully deleated due to error retriving data from db whera all rules are deleted the db is also updated with isDeleted status + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_DBFetchFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "postgregetcurrentfail", new List { "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one rules are returned as not successfully deleted due to error locking data for update in blob storage where all rules are deleted the db is also updated with isDeleted status + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_DataStorageLeaseFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "blobstoragegetleaselockfail", new List { "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Could not acquire blob lease lock on delegation policy at path: error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one rules are returned as not successfully deleted due to error writing data for update in blob storage. + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_DataWriteFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "blobstorageleaselockwritefail", new List { "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Writing of delegation policy at path: error/blobstorageleaselockwritefail/50001337/u20001337/delegationpolicy.xml failed. Is delegation blob storage account alive and well?" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one rules are returned as not successfully deleted due to undefined resource + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_PolicyPathInvalid() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app4", new List { "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" }, coveredByUserId: 0) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Not possible to build policy path for: org1/app4 CoveredBy: (null) OfferedBy: 50001337 RuleIds: ade3b138-7fa4-4c83-9306-8ec4a72c2daa" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one policy are returned as not successfully deleted due to error update changelog. + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_PostgreeUpdateFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94", "6f11dd0b-5e5d-4bd1-85f0-9796300dfded" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "postgrewritechangefail", new List { "ade3b138-7fa4-4c83-9306-8ec4a72c2daa" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + { "error/postgrewritechangefail/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("error/postgrewritechangefail", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml. is authorization postgresql database alive and well?" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, whether one rules are returned as not successfully deleated due to error finding the file on blob storage where all rules are deleted the db is also updated with isDeleted status + /// Input: + /// List of unordered rules for deletion multiple apps same OfferedBy to one CoveredBy user, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules actualy deleted. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicyRules_PolicyPathDoesNotExist() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app8", new List { "0d0c8570-64fb-49f9-9f7d-45c057fddf94" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", new List { "244278c1-7c6b-4f6b-b6e9-2bd41f84812f" }, coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app4", new List { "adfa64fa-5859-46e5-8d0d-62762082f3b9" }, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app4", createdSuccessfully: true) + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } }, + { "org1/app4/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app4", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.Revoke) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicyRules(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, all rules are returned as successfully created + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_Valid() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app4", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app4", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app4", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org1/app4/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app4", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryDeleteDelegationPolicies operation, where all rules in a given delegation policy are deleted and stored in delegationchange database with RevokeLast status, + /// but pushing RevokeLast event to DelegationChangeEventQueue fails which should trigger crittical error logging + /// Input: + /// List of RequestToDelete models identifying the delegation policies to be deleted + /// Expected Result: + /// List of all rules are deleted from policy and delegationchange stored in postgresql, critical error is logged + /// Success Criteria: + /// All returned rules match expected, and critical error has been logged + /// + [Fact] + public async Task TryDeleteDelegationPolicies_Valid_DelegationEventQueue_Push_Exception() + { + // Arrange + int performedByUserId = 20001337; + int offeredByPartyId = 50001337; + int coveredBy = 20001336; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "delegationeventfail", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "error", "delegationeventfail", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "error", "delegationeventfail", createdSuccessfully: true) + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "error/delegationeventfail/50001337/u20001336", new List { TestDataUtil.GetAltinnAppDelegationChange("error/delegationeventfail", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Critical, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("DeletePolicy could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange:") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to error locking the data for update + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_StorageLeaseFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "blobstoragegetleaselockfail", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Could not acquire blob lease on delegation policy at path: error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to error fetching data from DB + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_DBFetchFail() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "postgregetcurrentfail", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to error finding data on blob storage + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_PolicyPathDoesNotExist() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app8", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to error updating data in DB + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_DBUpdateFails() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "error", "postgrewritechangefail", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "error/postgrewritechangefail/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("error/postgrewritechangefail", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml. is authorization postgresql database alive and well?" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to error in resource to delete + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_UndefinedResource() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", string.Empty, coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Not possible to build policy path for: org1/ CoveredBy: 20001337 OfferedBy: 50001337" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicies function, one rule are returned as failed due to policy already deleted + /// Input: + /// List of unordered rules for deletion of the same apps from the same OfferedBy to one CoveredBy user + /// Expected Result: + /// List of all rules deleted returned. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryDeleteDelegationPolicies_PolicyAlreadyDeleted() + { + // Arrange + int performedByUserId = 20001336; + int offeredByPartyId = 50001337; + int coveredBy = 20001337; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + _delegationMetadataRepositoryMock.MetadataChanges = new Dictionary>(); + + List inputRuleMatchess = new List + { + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org2", "app3", coveredByUserId: coveredBy), + TestDataUtil.GetRequestToDeleteModel(performedByUserId, offeredByPartyId, "org1", "app5", coveredByUserId: coveredBy) + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org1", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "read", "org2", "app3", createdSuccessfully: true), + TestDataUtil.GetRuleModel(performedByUserId, offeredByPartyId, coveredBy.ToString(), coveredByType, "write", "org2", "app3", createdSuccessfully: true), + }; + + Dictionary> expectedDbUpdates = new Dictionary> + { + { "org1/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org1/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } }, + { "org2/app3/50001337/u20001337", new List { TestDataUtil.GetAltinnAppDelegationChange("org2/app3", offeredByPartyId, performedByUserId: performedByUserId, coveredByUserId: coveredBy, changeType: DelegationChangeType.RevokeLast) } } + }; + + // Act + List actual = await _pap.TryDeleteDelegationPolicies(inputRuleMatchess); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + AssertionUtil.AssertEqual(expectedDbUpdates, _delegationMetadataRepositoryMock.MetadataChanges); + _logger.Verify( + x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "The policy is already deleted for: org1/app5 CoveredBy: 20001337 OfferedBy: 50001337" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Tests the TryWriteDelegationPolicyRules function, whether all rules are returned as successfully created + /// Input: + /// List of unordered rules for delegation of the same apps from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules (now in sorted order of the resulting 3 delegation policy files) with success flag and rule id set. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_Valid() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app2"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1"), // Should be sorted together with the first rule + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app2", createdSuccessfully: true) + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when only partial set of the rules are returned as successfully created. + /// Input: + /// List of unordered rules for delegation from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// One of the rules are for an app where no app policy exists and should fail. + /// Expected Result: + /// List of all rules (now in sorted order of the resulting 3 delegation policy files). + /// Only stored rules should have success flag and rule id set. + /// Success Criteria: + /// All returned rules match expected + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_UnknownApp_PartialSuccess() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "unknownorg", "unknownapp"), // Should fail as there is no App Policy for this app + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1"), // Should be sorted together with the first rule + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "unknownorg", "unknownapp", createdSuccessfully: false) + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.Where(r => r.CreatedSuccessfully).All(r => !string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.Where(r => !r.CreatedSuccessfully).All(r => string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "No valid App policy found for delegation policy path: unknownorg/unknownapp/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when only partial set of the rules are returned as successfully created. + /// Input: + /// List of unordered rules for delegation from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// One of the rules for org1, app1 contains a non-existing resource and should fail all rules for that app. + /// Expected Result: + /// List of all rules (now in sorted order of the resulting 3 delegation policy files). + /// Only stored rules should have success flag and rule id set. + /// Success Criteria: + /// All returned rules match expected + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_UnknownResource_PartialSuccess() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", task: null, "event1") // This should fail all rules for org1, app1 as there is no event1 resource in the App Policy for this app + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", createdSuccessfully: false), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1", createdSuccessfully: false), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", task: null, "event1", createdSuccessfully: false), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1", createdSuccessfully: true) + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.Where(r => r.CreatedSuccessfully).All(r => !string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.Where(r => !r.CreatedSuccessfully).All(r => string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("Matching rule not found in app policy. Action might not exist for Resource, or Resource itself might not exist. Delegation policy path: org1/app1/50001337/u20001337/delegationpolicy.xml") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when only partial set of the rules are returned as successfully created. + /// Input: + /// List of unordered rules for delegation from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// One of the rules for org1, app1 is for an action which does not exist for that resource in the app policy and should fail all rules for that app. + /// Expected Result: + /// List of all rules (now in sorted order of the resulting 3 delegation policy files). + /// Only stored rules should have success flag and rule id set. + /// Success Criteria: + /// All returned rules match expected + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_UnknownActionForResource_PartialSuccess() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", "task1"), // This should fail all rules for org1, app1 as there is no read action for the resource in the App Policy for this app + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", createdSuccessfully: false), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", "task1", createdSuccessfully: false), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1", createdSuccessfully: true), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.Where(r => r.CreatedSuccessfully).All(r => !string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.Where(r => !r.CreatedSuccessfully).All(r => string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("Matching rule not found in app policy. Action might not exist for Resource, or Resource itself might not exist. Delegation policy path: org1/app1/50001337/u20001337/delegationpolicy.xml") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when only partial set of the rules are returned as successfully created, caused by one of the rules not having a complete model for sorting to a delegation policy filepath + /// Input: + /// List of unordered rules for delegation of the same apps from the same OfferedBy to two CoveredBy users, and one coveredBy organization/partyid + /// Expected Result: + /// List of all rules (now in sorted order of the resulting 3 delegation policy files) with success flag and rule id set. + /// Success Criteria: + /// All returned rules match expected and have success flag and rule id set + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_PartialSuccess_UnsortableRule() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1"), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", null, null), // Should fail as the rule model is not complete (missing org/app) + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1"), // Should be sorted together with the first rule + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org1", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "sign", "org1", "app1", "task1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "org2", "app1", createdSuccessfully: true), + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", null, null, createdSuccessfully: false) + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.Where(r => r.CreatedSuccessfully).All(r => !string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.Where(r => !r.CreatedSuccessfully).All(r => string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("One or more rules could not be processed because of incomplete input:") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when blobLeaseClient.AcquireAsync throws exception when trying to get lease lock on delegation policy blob + /// Input: + /// Single rule + /// Expected Result: + /// The blob storage throws exception when aqcuiring lease lock + /// Success Criteria: + /// The blob storage exception is handled and logged. The rule is returned as not created. + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_Error_BlobStorageAqcuireLeaseLockException() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "blobstoragegetleaselockfail"), + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "blobstoragegetleaselockfail", createdSuccessfully: false), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.All(r => !r.CreatedSuccessfully)); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Information, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Could not acquire blob lease lock on delegation policy at path: error/blobstoragegetleaselockfail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when blob storage write throws exception caused by lease locking + /// Input: + /// Single rule + /// Expected Result: + /// The blob storage write throws exception + /// Success Criteria: + /// The blob storage exception is handled and logged. The rule is returned as not created. + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_Error_BlobStorageLeaseLockWriteException() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "blobstorageleaselockwritefail"), + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "blobstorageleaselockwritefail", createdSuccessfully: false), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.All(r => !r.CreatedSuccessfully)); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "An exception occured while processing authorization rules for delegation on delegation policy path: error/blobstorageleaselockwritefail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when getting current delegation change from postgre fails + /// Input: + /// Single rule + /// Expected Result: + /// The postgre integration throws exception when getting the current change from the database + /// Success Criteria: + /// The postgre exception is handled and logged. The rule is returned as not created. + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_Error_PostgreGetCurrentException() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "postgregetcurrentfail"), + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "postgregetcurrentfail", createdSuccessfully: false), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.All(r => !r.CreatedSuccessfully)); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "An exception occured while processing authorization rules for delegation on delegation policy path: error/postgregetcurrentfail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, when writing the new current delegation change to postgre fails + /// Input: + /// Single rule + /// Expected Result: + /// The postgre integration throws exception when writing the new delegation change to the database + /// Success Criteria: + /// The postgre exception is handled and logged. The rule is returned as not created. + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_Error_PostgreWriteDelegationChangeException() + { + // Arrange + int delegatedByUserId = 20001336; + int offeredByPartyId = 50001337; + string coveredBy = "20001337"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "postgrewritechangefail"), + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "error", "error", "postgrewritechangefail", createdSuccessfully: false), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => string.IsNullOrEmpty(r.RuleId))); + Assert.True(actual.All(r => !r.CreatedSuccessfully)); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((@object, @type) => @object.ToString() == "Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: error/postgrewritechangefail/50001337/u20001337/delegationpolicy.xml" && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// Scenario: + /// Tests the TryWriteDelegationPolicyRules function, but pushing the delegation event to the queue fails. + /// Input: + /// List with a rule for delegation of the app error/delegationeventfail between for a single offeredby/coveredby combination resulting in a single delegation policy. + /// Expected Result: + /// Internal exception cause pushing delegation event to fail, after delegation has been stored. + /// Success Criteria: + /// TryWriteDelegationPolicyRules returns rules as created, but a Critical Error has been logged + /// + [Fact] + public async Task TryWriteDelegationPolicyRules_DelegationEventQueue_Push_Exception() + { + // Arrange + int delegatedByUserId = 20001337; + int offeredByPartyId = 50001337; + string coveredBy = "20001336"; + string coveredByType = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + + List unsortedRules = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "error", "delegationeventfail"), + }; + + List expected = new List + { + TestDataUtil.GetRuleModel(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, "read", "error", "delegationeventfail", createdSuccessfully: true), + }; + + // Act + List actual = await _pap.TryWriteDelegationPolicyRules(unsortedRules); + + // Assert + Assert.Equal(expected.Count, actual.Count); + Assert.True(actual.All(r => r.CreatedSuccessfully)); + Assert.True(actual.All(r => !string.IsNullOrEmpty(r.RuleId))); + AssertionUtil.AssertEqual(expected, actual); + _logger.Verify( + x => x.Log( + LogLevel.Critical, + It.IsAny(), + It.Is((@object, @type) => @object.ToString().StartsWith("AddRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange:") && @type.Name == "FormattedLogValues"), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnOrganizationResolverTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnOrganizationResolverTests.cs new file mode 100644 index 00000000..7691707e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnOrganizationResolverTests.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Resolvers; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Resolvers.Altinn; + +/// +/// Resolver tests +/// +[Collection(nameof(AttributeResolver))] +public class AltinnOrganizationResolverTests +{ + /// + /// Organization resolver tests + /// + /// attributes that are given by callee + /// attributes that are wanted by callee + /// assert method that verifies the result + [Theory] + [MemberData(nameof(ResolveIdentifierNoToPartyId), MemberType = typeof(AltinnOrganizationResolverTests))] + [MemberData(nameof(ResolvePartyIdToIdentifierNo), MemberType = typeof(AltinnOrganizationResolverTests))] + [MemberData(nameof(ResolveUnkownPartyIdToEmptyResult), MemberType = typeof(AltinnOrganizationResolverTests))] + public async Task TestResolveOrganzation(IEnumerable attributes, IEnumerable wants, Action> assert) + { + var resolver = ResolverServiceCollection.ConfigureServices(ResolverServiceCollection.DefaultServiceCollection); + + var result = await resolver.Resolve(attributes, wants, default); + + assert(result); + } + + /// + /// should resolve + /// + public static TheoryData, List, Action>> ResolveIdentifierNoToPartyId => + new() + { + { + [new(BaseUrn.Altinn.Organization.IdentifierNo, "910493353")], + [BaseUrn.Altinn.Organization.PartyId], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Organization.PartyId, "50006078")) + } + }; + + /// + /// should resolve + /// + public static TheoryData, List, Action>> ResolvePartyIdToIdentifierNo => + new() + { + { + [new(BaseUrn.Altinn.Organization.PartyId, "50006078")], + [BaseUrn.Altinn.Organization.IdentifierNo], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Organization.IdentifierNo, "910493353")) + } + }; + + /// + /// should trigger , but return the same result as input as given + /// party ID don't exist. + /// + public static TheoryData, List, Action>> ResolveUnkownPartyIdToEmptyResult => + new() + { + { + [new(BaseUrn.Altinn.Organization.PartyId, "00000000")], + [BaseUrn.Altinn.Organization.IdentifierNo], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Organization.PartyId, "00000000")) + } + }; + + private static Action> AssertEqual(params AttributeMatch[] attributes) => result => + { + AssertContains(attributes)(result); + AssertContains([.. result])(attributes); + }; + + private static Action> AssertContains(params AttributeMatch[] attributes) => result => + { + foreach (var attribute in attributes) + { + foreach (var item in result) + { + Assert.Contains(attribute, result); + } + } + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnPersonResolverTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnPersonResolverTests.cs new file mode 100644 index 00000000..40b0b848 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/Altinn/AltinnPersonResolverTests.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Resolvers; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Resolvers.Altinn; + +/// +/// Resolver tests +/// +[Collection(nameof(AttributeResolver))] +public class AltinnPersonResolverTests +{ + /// + /// Person resolver tests + /// + /// attributes that are given by callee + /// attributes that are wanted by callee + /// assert method that verifies the result + [Theory] + [MemberData(nameof(ResolveProfileUsingIdentifierNo), MemberType = typeof(AltinnPersonResolverTests))] + [MemberData(nameof(ResolveProfileUsingUserId), MemberType = typeof(AltinnPersonResolverTests))] + [MemberData(nameof(ResolveUnkownPartyIdToEmptyResult), MemberType = typeof(AltinnPersonResolverTests))] + [MemberData(nameof(ResolveProfileUsingPartyId), MemberType = typeof(AltinnPersonResolverTests))] + public async Task TestResolvePerson(IEnumerable attributes, IEnumerable wants, Action> assert) + { + var resolver = ResolverServiceCollection.ConfigureServices(ResolverServiceCollection.DefaultServiceCollection); + + var result = await resolver.Resolve(attributes, wants, default); + + assert(result); + } + + /// + /// should resolve + /// + public static TheoryData, List, Action>> ResolveProfileUsingIdentifierNo => + new() + { + { + [new(BaseUrn.Altinn.Person.IdentifierNo, "02056260016")], + [BaseUrn.Altinn.Person.PartyId], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Person.UserId, "20000095")) + } + }; + + /// + /// should resolve + /// + public static TheoryData, List, Action>> ResolveProfileUsingUserId => + new() + { + { + [new(BaseUrn.Altinn.Person.UserId, "20000095")], + [BaseUrn.Altinn.Person.IdentifierNo], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Person.IdentifierNo, "02056260016")) + } + }; + + /// + /// should resolve + /// + public static TheoryData, List, Action>> ResolvePartyUsingPartyId => + new() + { + { + [new(BaseUrn.Altinn.Person.UserId, "20000095")], + [BaseUrn.Altinn.Person.IdentifierNo], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Person.IdentifierNo, "02056260016")) + } + }; + + /// + /// should trigger /> + /// + public static TheoryData, List, Action>> ResolveProfileUsingPartyId => + new() + { + { + [new(BaseUrn.Altinn.Person.PartyId, "50002203")], + [BaseUrn.Altinn.Person.UserId], + AssertContains(new AttributeMatch(BaseUrn.Altinn.Person.UserId, "20000095")) + } + }; + + /// + /// should trigger , but return the same result as input as given + /// party ID don't exist. + /// + public static TheoryData, List, Action>> ResolveUnkownPartyIdToEmptyResult => + new() + { + { + [new(BaseUrn.Altinn.Person.UserId, "00000000")], + [BaseUrn.Altinn.Person.IdentifierNo], + AssertEqual(new AttributeMatch(BaseUrn.Altinn.Person.UserId, "00000000")) + } + }; + + private static Action> AssertEqual(params AttributeMatch[] attributes) => result => + { + AssertContains(attributes)(result); + AssertContains([.. result])(attributes); + }; + + private static Action> AssertContains(params AttributeMatch[] attributes) => result => + { + foreach (var attribute in attributes) + { + Assert.Contains(attribute, result); + } + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/ResolverServiceCollection.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/ResolverServiceCollection.cs new file mode 100644 index 00000000..4e1066e3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Resolvers/ResolverServiceCollection.cs @@ -0,0 +1,71 @@ +using System; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Configuration; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Resolvers; +using Altinn.AccessManagement.Core.Resolvers.Extensions; +using Altinn.AccessManagement.Core.Services; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Resolvers; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.Common.AccessToken.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Altinn.AccessManagement.Tests.Resolvers; + +/// +/// ResolverServiceCollection +/// +public static class ResolverServiceCollection +{ + /// + /// ConfigureServices + /// + /// actions + public static IAttributeResolver ConfigureServices(params Action[] actions) + { + var services = new ServiceCollection(); + foreach (var action in actions) + { + action(services); + } + + return services.BuildServiceProvider().GetService(); + } + + /// + /// DefaultServiceCollection + /// + public static void DefaultServiceCollection(IServiceCollection services) + { + services.AddMemoryCache(); + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.Configure(options => + { + options.PartyCacheTimeout = 5; + }); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/DelegationScenarios.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/DelegationScenarios.cs new file mode 100644 index 00000000..2ae480b2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/DelegationScenarios.cs @@ -0,0 +1,223 @@ +using System; +using System.Data; +using System.Linq; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.SblBridge; +using Altinn.AccessManagement.Tests.Contexts; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Seeds; +using Altinn.Platform.Register.Models; +using Microsoft.AspNetCore.Hosting; + +namespace Altinn.AccessManagement.Tests.Scenarios; + +/// +/// Different scenarios that populates mock context and postgres db with data. +/// +public static class DelegationScenarios +{ + private static readonly Random Random = new(DateTime.UtcNow.Nanosecond); + + private static int RandPartyId => Random.Next(9000, 9999); + + private static int RandUserId => Random.Next(8000, 9000); + + /// + /// Defaults setup + /// 1. Add resources to dn + /// 2. Add random delegation to delegationchange table. + /// - Uses random ID in range [9000, 99999] + /// + public static void Defaults(MockContext mock) + { + mock.Resources.AddRange([ + ResourceSeeds.AltinnApp.Defaults, + ResourceSeeds.MaskinportenSchema.Defaults, + ]); + + mock.Parties.AddRange([ + PersonSeeds.Paula.Party, + PersonSeeds.Kasper.Party, + PersonSeeds.Olav.Party, + OrganizationSeeds.Voss.Defaults, + OrganizationSeeds.VossAccounting.Defaults, + OrganizationSeeds.VossConsulting.Defaults, + ]); + + mock.UserProfiles.AddRange([ + PersonSeeds.Paula.Defaults, + PersonSeeds.Kasper.Defaults, + PersonSeeds.Olav.Defaults, + ]); + + // Seed databases resources + mock.DbSeeds.AddRange([ + async postgres => await postgres.ResourceMetadataRepository.InsertAccessManagementResource(ResourceSeeds.AltinnApp.Defaults.DbResource), + async postgres => await postgres.ResourceMetadataRepository.InsertAccessManagementResource(ResourceSeeds.MaskinportenSchema.Defaults.DbResource), + ]); + + foreach (var random in Enumerable.Range(0, Random.Next(20))) + { + mock.DbSeeds.AddRange([ + async postgres => + { + var delegation = DelegationChangeComposer.New( + DelegationChangeComposer.WithToParty(RandPartyId), + DelegationChangeComposer.WithFrom(RandPartyId), + DelegationChangeComposer.WithResource(ResourceSeeds.AltinnApp.Defaults)); + + await postgres.DelegationMetadataRepository.InsertDelegation(ResourceAttributeMatchType.AltinnAppId, delegation); + }, + async postgres => + { + var delegation = DelegationChangeComposer.New( + DelegationChangeComposer.WithToUser(RandUserId), + DelegationChangeComposer.WithFrom(RandPartyId), + DelegationChangeComposer.WithResource(ResourceSeeds.MaskinportenSchema.Defaults)); + + await postgres.DelegationMetadataRepository.InsertDelegation(ResourceAttributeMatchType.ResourceRegistry, delegation); + } + ]); + } + } + + /// + /// Ensures that given profile has a key role for given org i mock context + /// + /// profile + /// organization + /// + public static Scenario WherePersonHasKeyRole(IUserProfile profile, params IParty[] organizations) => mock => + { + var partyids = organizations.Select(organization => organization?.Party?.PartyId ?? 0); + if (mock.KeyRoles.TryGetValue(profile.UserProfile.UserId, out var value)) + { + value.AddRange(partyids); + } + else + { + mock.KeyRoles.Add(profile.UserProfile.UserId, partyids.ToList()); + } + }; + + /// + /// Add subunit as a mainunit in mock context + /// + /// subunit + /// mainunit + /// + public static Scenario WhereUnitHasMainUnit(IParty subunit, IParty mainunit) => mock => + { + mock.MainUnits[subunit.Party.PartyId] = new MainUnit + { + PartyId = mainunit.Party.PartyId, + OrganizationName = mainunit?.Party?.Organization?.Name ?? "Unknown", + OrganizationNumber = mainunit?.Party?.Organization?.OrgNumber ?? string.Empty, + SubunitPartyId = subunit.Party.PartyId, + }; + }; + + /// + /// Removes a resource from mock context + /// + public static Scenario WithoutResource(IAccessManagementResource resource) => mock => + { + mock.Resources.RemoveAt(mock.Resources.FindIndex(r => r.Identifier == resource.Resource.Identifier)); + }; + + /// + /// Add revoke delegation to db from given party to user + /// + /// organization that revoking delegation + /// person that lose the delegation to the organization + /// resource + /// + public static Scenario WithRevokedDelegationToUser(IParty organization, IUserProfile person, IAccessManagementResource resource = null) => mock => + { + resource ??= ResourceSeeds.AltinnApp.Defaults; + + mock.DbSeeds.AddRange([ + async postgres => await postgres.DelegationMetadataRepository.InsertDelegation( + ResourceAttributeMatchType.AltinnAppId, + DelegationChangeComposer.New( + DelegationChangeComposer.WithFrom(organization), + DelegationChangeComposer.WithToUser(person), + DelegationChangeComposer.WithResource(resource), + DelegationChangeComposer.WithDelegationChangeRevokeLast)) + ]); + }; + + public static Scenario WithInstanceDelegation(IParty from, IParty to, IAccessManagementResource resource, string instanceId) => mock => + { + var insert = new InstanceDelegationChange() + { + DelegationChangeType = DelegationChangeType.Grant, + BlobStoragePolicyPath = "https://blob.storage.no", + BlobStorageVersionId = "v1", + ResourceId = resource.Resource.Identifier, + InstanceId = instanceId, + FromUuid = (Guid)from.Party.PartyUuid, + FromUuidType = string.IsNullOrEmpty(from.Party.SSN) ? Enums.UuidType.Organization : Enums.UuidType.Person, + ToUuid = (Guid)to.Party.PartyUuid, + ToUuidType = string.IsNullOrEmpty(to.Party.SSN) ? Enums.UuidType.Organization : Enums.UuidType.Person, + InstanceDelegationMode = InstanceDelegationMode.Normal, + PerformedBy = from.Party.PartyId.ToString(), + PerformedByType = Enums.UuidType.Person + }; + + mock.DbSeeds.AddRange([ + async postgres => await postgres.DelegationMetadataRepository.InsertInstanceDelegation(insert), + ]); + }; + + /// + /// Adds mock context and db seeds. for given organization, person and resource + /// + /// from organization + /// to person + /// resource + /// + public static Scenario FromOrganizationToPerson(IParty from, IUserProfile to, IAccessManagementResource resource = null) => mock => + { + resource ??= ResourceSeeds.AltinnApp.Defaults; + + mock.Resources.Add(resource.Resource); + mock.UserProfiles.Add(to.UserProfile); + mock.Parties.AddRange([from.Party, to.UserProfile.Party]); + + mock.DbSeeds.AddRange([ + async postgres => await postgres.DelegationMetadataRepository.InsertDelegation( + resource.Resource.ResourceType == ResourceType.AltinnApp ? ResourceAttributeMatchType.AltinnAppId : ResourceAttributeMatchType.ResourceRegistry, + DelegationChangeComposer.New( + DelegationChangeComposer.WithFrom(from), + DelegationChangeComposer.WithToUser(to), + DelegationChangeComposer.WithResource(resource))) + ]); + }; + + /// + /// Adds mock context and db seeds. for given organization, person and resource + /// + /// from organization + /// to person + /// resource + /// + public static Scenario FromOrganizationToOrganization(IParty from, IParty to, IAccessManagementResource resource = null) => mock => + { + resource ??= ResourceSeeds.AltinnApp.Defaults; + + mock.Resources.Add(resource.Resource); + mock.Parties.AddRange([from.Party, to.Party]); + + mock.DbSeeds.AddRange([ + async postgres => await postgres.DelegationMetadataRepository.InsertDelegation( + resource.Resource.ResourceType == ResourceType.AltinnApp ? ResourceAttributeMatchType.AltinnAppId : ResourceAttributeMatchType.ResourceRegistry, + DelegationChangeComposer.New( + DelegationChangeComposer.WithFrom(from), + DelegationChangeComposer.WithToParty(to), + DelegationChangeComposer.WithResource(resource))) + ]); + }; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/Scenario.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/Scenario.cs new file mode 100644 index 00000000..7be98118 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/Scenario.cs @@ -0,0 +1,11 @@ +using Altinn.AccessManagement.Tests.Contexts; +using Altinn.AccessManagement.Tests.Fixtures; +using Microsoft.AspNetCore.Hosting; + +namespace Altinn.AccessManagement.Tests.Scenarios; + +/// +/// Scenario function signature +/// +/// mock context object +public delegate void Scenario(MockContext mock); diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/TokenScenario.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/TokenScenario.cs new file mode 100644 index 00000000..b23f02cd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Scenarios/TokenScenario.cs @@ -0,0 +1,36 @@ +using Altinn.AccessManagement.Tests.Contexts; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Seeds; +using Altinn.AccessManagement.Tests.Util; + +namespace Altinn.AccessManagement.Tests.Scenarios +{ + /// + /// Creates a bearer token that's used when calling the test server. The token will be attached to the HTTP client right after creating + /// the client. + /// + public static class TokenScenario + { + /// + /// creates a JWT user token for given person and sets the field + /// + /// The person which a token should be generated + /// level of authentication [1, 2, 3] + /// + public static Scenario PersonToken(PersonSeeds.PersonBase person, int authenticationLevel = 2) => mock => + { + mock.HttpHeaders.TryAdd("Authorization", $"Bearer {PrincipalUtil.GetToken(person.UserId, person.PartyId, authenticationLevel)}"); + }; + + /// + /// Sets headers PlatformAccessToken with an access token containing given claims issuer and app + /// + /// issuer of the token + /// name of the app + /// + public static Scenario PlatformToken(string issuer, string app) => mock => + { + mock.HttpHeaders.Add("PlatformAccessToken", PrincipalUtil.GetAccessToken(issuer, app)); + }; + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/EnterpriseUserSeeds.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/EnterpriseUserSeeds.cs new file mode 100644 index 00000000..c7958614 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/EnterpriseUserSeeds.cs @@ -0,0 +1,5 @@ +namespace Altinn.AccessManagement.Tests.Seeds; + +public class EnterpriseUserSeeds +{ +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/Interfaces.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/Interfaces.cs new file mode 100644 index 00000000..8640e83c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/Interfaces.cs @@ -0,0 +1,44 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Seeds; + +/// +/// For seeds +/// +public interface IParty +{ + /// + /// Get Party profile from seed + /// + Party Party { get; } +} + +/// +/// For seeds +/// +public interface IUserProfile +{ + /// + /// Get User profile from seed + /// + UserProfile UserProfile { get; } +} + +/// +/// For seeds +/// +public interface IAccessManagementResource +{ + /// + /// Db resource + /// + AccessManagementResource DbResource { get; } + + /// + /// Get resource from seed + /// + ServiceResource Resource { get; } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/MaskinPortenSchemaResourceSeeds.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/MaskinPortenSchemaResourceSeeds.cs new file mode 100644 index 00000000..4f5f348d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/MaskinPortenSchemaResourceSeeds.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Tests.Seeds +{ + public static class MaskinPortenSchemaResourceSeeds + { + public class MaskinPortenSchema : ServiceResource + { + public new static readonly string Identifier = "scope-access-schema"; + + public new static readonly string Status = "Active"; + + public new static readonly bool Delegable = true; + + public new static readonly ResourceType ResourceType = ResourceType.MaskinportenSchema; + + public new static readonly List AuthorizationReference = new List + { + new() + { + Id = "urn:altinn:resource", + Value = "scope-access-schema" + } + }; + + public static MaskinPortenSchema Defaults { get; } = new MaskinPortenSchema(); + + public MaskinPortenSchema(params Action[] modifiers) + { + base.Identifier = Identifier; + base.Status = Status; + base.Delegable = Delegable; + base.ResourceType = ResourceType; + base.AuthorizationReference = AuthorizationReference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/OrganizationSeeds.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/OrganizationSeeds.cs new file mode 100644 index 00000000..a1e0b7d3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/OrganizationSeeds.cs @@ -0,0 +1,139 @@ +using System; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Seeds; + +public static class OrganizationSeeds +{ + public abstract class OrganizationBase : Party, IParty + { + public Party Party => this; + } + + public class Voss : OrganizationBase + { + public new static readonly int PartyId = 200; + + public new static readonly Guid? PartyUuid = new Guid("00000000-0000-0000-0000-000000000200"); + + public new static readonly PartyType PartyTypeName = PartyType.Organisation; + + public new static readonly string OrgNumber = "910459880"; + + public new static readonly string Name = "Voss AS"; + + public new static readonly string UnitType = "AS"; + + public new static readonly Organization Organization = new() + { + OrgNumber = OrgNumber, + Name = Name, + UnitType = UnitType, + EMailAddress = "hello@voss.no", + }; + + public static Voss Defaults { get; } = new Voss(); + + public Voss(params Action[] modifiers) + { + base.PartyId = PartyId; + base.PartyUuid = PartyUuid; + base.PartyTypeName = PartyTypeName; + base.OrgNumber = OrgNumber; + base.Name = Name; + base.UnitType = UnitType; + base.Organization = Organization; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + + public class VossConsulting : OrganizationBase + { + public new static readonly int PartyId = 201; + + public new static readonly Guid? PartyUuid = new Guid("00000000-0000-0000-0000-000000000201"); + + public new static readonly PartyType PartyTypeName = PartyType.Organisation; + + public new static readonly string OrgNumber = "810418982"; + + public new static readonly string Name = "Voss Consulting"; + + public new static readonly string UnitType = "AS"; + + public new static readonly Organization Organization = new() + { + OrgNumber = OrgNumber, + Name = Name, + UnitType = UnitType, + EMailAddress = "hello@consulting.voss.no", + }; + + public new static readonly List ChildParties = new() { VossAccounting.Defaults }; + + public VossConsulting(params Action[] modifiers) + { + base.PartyId = PartyId; + base.PartyUuid = PartyUuid; + base.PartyTypeName = PartyTypeName; + base.OrgNumber = OrgNumber; + base.Name = Name; + base.UnitType = UnitType; + base.Organization = Organization; + base.ChildParties = ChildParties; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + + public static VossConsulting Defaults { get; } = new VossConsulting(); + } + + public class VossAccounting : OrganizationBase + { + public new static readonly int PartyId = 202; + + public new static readonly Guid? PartyUuid = new Guid("00000000-0000-0000-0000-000000000202"); + + public new static readonly PartyType PartyTypeName = PartyType.Organisation; + + public new static readonly string OrgNumber = "810419172"; + + public new static readonly string Name = "Voss Accounting"; + + public new static readonly string UnitType = "AS"; + + public new static readonly Organization Organization = new() + { + OrgNumber = OrgNumber, + Name = Name, + UnitType = UnitType, + EMailAddress = "hello@accounting.voss.no", + }; + + public static VossAccounting Defaults { get; } = new VossAccounting(); + + public VossAccounting(params Action[] modifiers) + { + base.PartyId = PartyId; + base.PartyUuid = PartyUuid; + base.PartyTypeName = PartyTypeName; + base.OrgNumber = OrgNumber; + base.Name = Name; + base.UnitType = UnitType; + base.Organization = Organization; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/PersonSeeds.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/PersonSeeds.cs new file mode 100644 index 00000000..6c13c74a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/PersonSeeds.cs @@ -0,0 +1,179 @@ +using System; +using Altinn.Platform.Profile.Models; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Seeds; + +public static class PersonSeeds +{ + public abstract class PersonBase : UserProfile, IParty, IUserProfile + { + public UserProfile UserProfile => this; + } + + public class Paula : PersonBase + { + public new static readonly int UserId = 1000; + + public new static readonly Guid? UserUuid = new Guid("00000000-0000-0000-0000-000000000100"); + + public new static readonly int PartyId = 100; + + public new static readonly Party Party = new() + { + PartyTypeName = PartyType.Person, + SSN = "02056260016", + PartyId = PartyId, + Name = "PAULA RIMSTAD", + IsDeleted = false, + OnlyHierarchyElementWithNoAccess = false, + PartyUuid = UserUuid, + Person = new() + { + SSN = "02056260016", + Name = "PAULA RIMSTAD", + FirstName = "PAULA", + LastName = "RIMSTAD", + MailingAddress = "Brannpostveien 15 3014 DRAMMEN", + MailingPostalCode = "3014", + MailingPostalCity = "DRAMMEN", + AddressPostalCode = "3014", + AddressCity = "DRAMMEN", + } + }; + + public new static readonly ProfileSettingPreference ProfileSettingPreference = new() + { + Language = "no", + PreSelectedPartyId = 0, + DoNotPromptForParty = false + }; + + public static Paula Defaults { get; } = new Paula(); + + public Paula(params Action[] modifiers) + { + base.UserId = UserId; + base.UserUuid = UserUuid; + base.PartyId = PartyId; + base.Party = Party; + base.ProfileSettingPreference = ProfileSettingPreference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + + public class Olav : PersonBase + { + public new static readonly int UserId = 1001; + + public new static readonly Guid? UserUuid = new Guid("00000000-0000-0000-0000-000000000101"); + + public new static readonly int PartyId = 101; + + public new static readonly Party Party = new() + { + PartyTypeName = PartyType.Person, + SSN = "27099450067", + PartyUuid = UserUuid, + PartyId = PartyId, + Name = "ØRJAN RAVNÅS", + IsDeleted = false, + OnlyHierarchyElementWithNoAccess = false, + Person = new() + { + SSN = "27099450067", + Name = "ØRJAN RAVNÅS", + FirstName = "ØRJAN", + LastName = "RAVNÅS", + MailingAddress = "Bjerkeveien 23 1726 SARPSBORG", + MailingPostalCode = "1726", + MailingPostalCity = "SARPSBORG", + AddressPostalCode = "1726", + AddressCity = "SARPSBORG", + } + }; + + public new static readonly ProfileSettingPreference ProfileSettingPreference = new() + { + Language = "no", + PreSelectedPartyId = 0, + DoNotPromptForParty = false + }; + + public static Olav Defaults { get; } = new Olav(); + + public Olav(params Action[] modifiers) + { + base.UserId = UserId; + base.UserUuid = UserUuid; + base.PartyId = PartyId; + base.Party = Party; + base.ProfileSettingPreference = ProfileSettingPreference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + + public class Kasper : PersonBase + { + public new static readonly int UserId = 1002; + + public new static readonly Guid? UserUuid = new Guid("00000000-0000-0000-0000-000000000102"); + + public new static readonly int PartyId = 102; + + public new static readonly Party Party = new() + { + PartyTypeName = PartyType.Person, + SSN = "07124912037", + PartyId = PartyId, + PartyUuid = UserUuid, + Name = "KASPER BØRSTAD", + IsDeleted = false, + OnlyHierarchyElementWithNoAccess = false, + Person = new() + { + SSN = "07124912037", + Name = "KASPER BØRSTAD", + FirstName = "KASPER", + LastName = "BØRSTAD", + MailingAddress = "Skålevikstølen 7 5178 LODDEFJORD", + MailingPostalCode = "5178", + MailingPostalCity = "LODDEFJORD", + AddressPostalCode = "5178", + AddressCity = "LODDEFJORD", + } + }; + + public new static readonly ProfileSettingPreference ProfileSettingPreference = new() + { + Language = "no", + PreSelectedPartyId = 0, + DoNotPromptForParty = false + }; + + public static Kasper Defaults { get; } = new Kasper(); + + public Kasper(params Action[] modifiers) + { + base.UserId = UserId; + base.UserUuid = UserUuid; + base.PartyId = PartyId; + base.Party = Party; + base.ProfileSettingPreference = ProfileSettingPreference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/ResourceSeeds.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/ResourceSeeds.cs new file mode 100644 index 00000000..a1095847 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Seeds/ResourceSeeds.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; + +namespace Altinn.AccessManagement.Tests.Seeds; + +public static class ResourceSeeds +{ + public class ResourceBase : ServiceResource, IAccessManagementResource + { + public ServiceResource Resource => this; + + public AccessManagementResource DbResource => new AccessManagementResource + { + ResourceRegistryId = Resource.ResourceType == ResourceType.AltinnApp ? $"{Resource.AuthorizationReference.First(p => p.Id == AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute)}/{Resource.Identifier}" : Resource.Identifier, + ResourceType = Resource.ResourceType, + }; + } + + public class ChalkboardResource : ResourceBase + { + public new static readonly ResourceType ResourceType = ResourceType.GenericAccessResource; + + public new static readonly string Identifier = "chalkboard"; + + public static ChalkboardResource Defaults { get; } = new ChalkboardResource(); + + public ChalkboardResource(params Action[] modifiers) + { + base.ResourceType = ResourceType.Systemresource; + base.Identifier = Identifier; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + + public class MaskinportenSchema : ResourceBase + { + public new static readonly string Identifier = "maskinportenschema"; + + public new static readonly string Status = "Active"; + + public new static readonly bool Delegable = true; + + public new static readonly ResourceType ResourceType = ResourceType.MaskinportenSchema; + + public new static readonly List ResourceReferences = + [ + ]; + + public new static readonly List AuthorizationReference = + [ + ]; + + public static MaskinportenSchema Defaults { get; } = new MaskinportenSchema(); + + public MaskinportenSchema(params Action[] modifiers) + { + base.Identifier = Identifier; + base.Status = Status; + base.Delegable = Delegable; + base.ResourceType = ResourceType; + base.ResourceReferences = ResourceReferences; + base.AuthorizationReference = AuthorizationReference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } + + public class AltinnApp : ResourceBase + { + public new static readonly string Identifier = "app_ttd_am-devtest-person-to-org"; + + public new static readonly string Status = "Active"; + + public new static readonly bool Delegable = true; + + public new static readonly ResourceType ResourceType = ResourceType.AltinnApp; + + public new static readonly List ResourceReferences = + [ + new() + { + ReferenceSource = ReferenceSource.Altinn3, + Reference = "ttd/am-devtest-person-to-org", + ReferenceType = ReferenceType.ApplicationId + } + ]; + + public new static readonly List AuthorizationReference = + [ + new() + { + Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute, + Value = "ttd" + }, + new() + { + Id = AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute, + Value = "am-devtest-person-to-org" + }, + ]; + + public static AltinnApp Defaults { get; } = new AltinnApp(); + + public AltinnApp(params Action[] modifiers) + { + base.Identifier = Identifier; + base.Status = Status; + base.Delegable = Delegable; + base.ResourceType = ResourceType; + base.ResourceReferences = ResourceReferences; + base.AuthorizationReference = AuthorizationReference; + + foreach (var modifer in modifiers) + { + modifer(this); + } + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Services/DelegationRequestTests.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Services/DelegationRequestTests.cs new file mode 100644 index 00000000..9413d1f8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Services/DelegationRequestTests.cs @@ -0,0 +1,72 @@ +using System.Net; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Tests.Utils; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Services +{ + /// + /// Test class for + /// + public class DelegationRequestTests : IClassFixture> + { + private readonly CustomWebApplicationFactory factory; + private readonly HttpClient client; + + /// + /// Constructor setting up factory, test client and dependencies + /// + /// CustomWebApplicationFactory + public DelegationRequestTests(CustomWebApplicationFactory factory) + { + this.factory = factory; + client = SetupUtils.GetTestClient(factory); + } + + /// + /// Test1 + /// + /// Result + [Fact(Skip = "Incomplete implementation")] + public async Task Test1() + { + string requestUri = "/accessmanagement/api/v1/delegationrequests"; + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) + { + }; + + HttpResponseMessage response = await client.SendAsync(httpRequestMessage); + + string responseContent = await response.Content.ReadAsStringAsync(); + DelegationRequests delegationRequest = JsonSerializer.Deserialize(responseContent, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }) as DelegationRequests; + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(delegationRequest); + } + + /// + /// Test2 + /// + /// Result + [Fact(Skip = "Incomplete implementation")] + public async Task Test2() + { + string requestUri = "/accessmanagement/api/v1/delegationrequests/23"; + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) + { + }; + + HttpResponseMessage response = await client.SendAsync(httpRequestMessage); + + string responseContent = await response.Content.ReadAsStringAsync(); + DelegationRequest delegationRequest = JsonSerializer.Deserialize(responseContent, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }) as DelegationRequest; + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(delegationRequest); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/ControllerTestTemplate.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/ControllerTestTemplate.cs new file mode 100644 index 00000000..0136514c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/ControllerTestTemplate.cs @@ -0,0 +1,68 @@ +using System; +using System.Threading.Tasks; +using Altinn.AccessManagement.Tests.Fixtures; +using Altinn.AccessManagement.Tests.Scenarios; +using Altinn.AccessManagement.Tests.Seeds; +using Xunit; + +namespace Altinn.AccessManagement.Tests; + +/// +/// Controller Name, use XML tag see +/// +public class ControllerTestTemplate(WebApplicationFixture fixture) : IClassFixture +{ + private WebApplicationFixture Fixture { get; } = fixture; + + /* + Test Collection asserters + + WithAssertResponse + WithAssertApi + + */ + + /// + /// Seeds for + /// + /// Acceptance Criteria + /// parameter to api route + /// modifiers for + public class SeedNameOfEndpoint(string acceptanceCriteria, int partyId, params Action[] actions) : AcceptanceCriteriaComposer( + acceptanceCriteria, + actions, + WithRequestRoute("route", "to", "endpoint", partyId)) + { + /// + /// List of test scenarios + /// + public static TheoryData Seeds() => + [ + + // new( + // /* Acceptance Criteria */ @" + // GIVEN that organization Voss consulting has delegated a MaskinportenSchema resource to Voss Accounting + // WHEN DAGL Olav for voss consulting requests delegations that Voss consulting has offered + // THEN Voss accounting should be in the list of offered delegations", + // + // /* Additional arguments */ + // OrganizationSeeds.VossConsulting.PartyId, + // + // /* Scenario */ + // WithScenarios( + // DelegationScenarios.Defaults, + // DelegationScenarios.FromOrganizationToOrganization(OrganizationSeeds.VossConsulting.Defaults, OrganizationSeeds.VossAccounting.Defaults, ResourceSeeds.MaskinportenSchema.Defaults)), + // + // /* Assertions */ + // WithAssertResponseStatusCodeSuccessful) + ]; + } + + /// + /// Controller Action Name and prefix method, use XML tag see + /// + /// acceptance criteria + // [Theory] + // [MemberData(nameof(SeedNameOfEndpoint.Seeds), MemberType = typeof(SeedNameOfEndpoint))] + public async Task POST_SeedNameOfEndpoint(SeedNameOfEndpoint acceptanceCriteria) => await acceptanceCriteria.Test(Fixture); +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/DatabaseTestTemplate.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/DatabaseTestTemplate.cs new file mode 100644 index 00000000..f329b28f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Templates/DatabaseTestTemplate.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using Altinn.AccessManagement.Tests.Fixtures; +using Xunit; + +namespace Altinn.AccessManagement.Tests.Templates; + +/// +/// Template +/// +public class DatabaseTestTemplate(PostgresFixture fixture) : IClassFixture +{ + private PostgresDatabase Database { get; } = fixture.New(); + + /// + /// Template + /// + // [Fact] + public async Task Test_DatabaseTestTemplate() + { + var result = await Database.ResourceMetadata.InsertAccessManagementResource(new() + { + ResourceRegistryId = "1", + ResourceType = Core.Models.ResourceRegistry.ResourceType.Systemresource + }); + + Assert.NotNull(result.ResourceId); + Assert.Equal("1", result.ResourceRegistryId); + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/AssertionUtil.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/AssertionUtil.cs new file mode 100644 index 00000000..9572fec1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/AssertionUtil.cs @@ -0,0 +1,1007 @@ +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.Register; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Core.Models.Rights; +using Altinn.AccessManagement.Models; +using Altinn.Authorization.ABAC.Xacml; +using Altinn.Authorization.ABAC.Xacml.JsonProfile; +using Altinn.Urn.Json; +using Microsoft.AspNetCore.Mvc; + +namespace Altinn.AccessManagement.Tests.Utils +{ + /// + /// Class with methods that can help with assertions of larger objects. + /// + public static class AssertionUtil + { + /// + /// Asserts that two collections of objects have the same property values in the same positions. + /// + /// The Type + /// A collection of expected instances + /// The collection of actual instances + /// The assertion method to be used + public static void AssertCollections(ICollection expected, ICollection actual, Action assertMethod) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + + Dictionary expectedDict = new Dictionary(); + Dictionary actualDict = new Dictionary(); + + int i = 1; + foreach (T ex in expected) + { + expectedDict.Add(i, ex); + i++; + } + + i = 1; + foreach (T ac in actual) + { + actualDict.Add(i, ac); + i++; + } + + foreach (int key in expectedDict.Keys) + { + assertMethod(expectedDict[key], actualDict[key]); + } + } + + /// + /// Asserts that two paginations of object lists have the same property values in the same positions and have egal link to next pagination. + /// + /// The Type + /// A pagination of expected instances + /// The pagination of actual instances + /// The assertion method to be used + public static void AssertPagination(Paginated expected, Paginated actual, Action assertMethod) + { + Assert.Equal(expected.Links, actual.Links); + AssertCollections(expected.Items.ToList(), actual.Items.ToList(), assertMethod); + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(XacmlContextResponse expected, XacmlContextResponse actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + Assert.Equal(expected.Results.Count, actual.Results.Count); + + if (expected.Results.Count > 0) + { + AssertEqual(expected.Results.First(), actual.Results.First()); + } + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(XacmlJsonResponse expected, XacmlJsonResponse actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + Assert.Equal(expected.Response.Count, actual.Response.Count); + + if (expected.Response.Count > 0) + { + for (int i = 0; i < expected.Response.Count; i++) + { + AssertEqual(expected.Response[i], actual.Response[i]); + } + } + } + + /// + /// Assert that two dictionaries of have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(Dictionary> expected, Dictionary> actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + foreach (KeyValuePair> expectedEntry in expected) + { + List actualValue = actual[expectedEntry.Key]; + Assert.NotNull(actualValue); + AssertEqual(expectedEntry.Value, actualValue); + } + } + + /// + /// Assert that two lists of have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(List expected, List actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + foreach (DelegationChange expectedEntity in expected) + { + DelegationChange actualentity = + actual.FirstOrDefault(a => a.ResourceId == expectedEntity.ResourceId && + a.ResourceType == expectedEntity.ResourceType && + a.BlobStoragePolicyPath == expectedEntity.BlobStoragePolicyPath && + a.CoveredByPartyId == expectedEntity.CoveredByPartyId && + a.CoveredByUserId == expectedEntity.CoveredByUserId && + a.OfferedByPartyId == expectedEntity.OfferedByPartyId && + a.DelegationChangeType == expectedEntity.DelegationChangeType); + Assert.NotNull(actualentity); + } + } + + /// + /// Assert that two lists of have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(List expected, List actual) + { + Assert.Equal(expected.Count, actual.Count); + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expected[i], actual[i]); + } + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(DelegationChangeEventList expected, DelegationChangeEventList actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.DelegationChangeEvents.Count, actual.DelegationChangeEvents.Count); + for (int i = 0; i < expected.DelegationChangeEvents.Count; i++) + { + AssertEqual(expected.DelegationChangeEvents[i], actual.DelegationChangeEvents[i]); + } + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(DelegationChangeEvent expected, DelegationChangeEvent actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.EventType, actual.EventType); + AssertEqual(expected.DelegationChange, actual.DelegationChange); + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(SimpleDelegationChange expected, SimpleDelegationChange actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.DelegationChangeId, actual.DelegationChangeId); + Assert.Equal(expected.AltinnAppId, actual.AltinnAppId); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + Assert.Equal(expected.CoveredByPartyId, actual.CoveredByPartyId); + Assert.Equal(expected.CoveredByUserId, actual.CoveredByUserId); + Assert.Equal(expected.PerformedByUserId, actual.PerformedByUserId); + Assert.Equal(expected.Created, actual.Created); + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertEqual(XacmlContextRequest expected, XacmlContextRequest actual) + { + Assert.Equal(expected.Attributes.Count, actual.Attributes.Count); + Assert.Equal(expected.GetResourceAttributes().Attributes.Count, actual.GetResourceAttributes().Attributes.Count); + Assert.Equal(expected.GetSubjectAttributes().Attributes.Count, actual.GetSubjectAttributes().Attributes.Count); + AssertEqual(expected.Attributes, actual.Attributes); + } + + /// + /// Assert that two Lists of have the same number of rules and each rule have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + /// Whether output only values should also be asserted + public static void AssertEqual(List expected, List actual, bool assertOutputValues = false) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expected[i], actual[i], assertOutputValues); + } + } + + /// + /// Assert that two have the same property values. + /// + /// An instance with the expected values. + /// The instance to verify. + /// Whether output only values should also be asserted + public static void AssertEqual(Rule expected, Rule actual, bool assertOutputValues = false) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + if (assertOutputValues) + { + Assert.Equal(expected.RuleId, actual.RuleId); + Assert.Equal(expected.Type, actual.Type); + } + + Assert.Equal(expected.CreatedSuccessfully, actual.CreatedSuccessfully); + Assert.Equal(expected.DelegatedByUserId, actual.DelegatedByUserId); + Assert.Equal(expected.DelegatedByPartyId, actual.DelegatedByPartyId); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + AssertEqual(expected.CoveredBy, actual.CoveredBy); + AssertEqual(expected.Resource, actual.Resource); + AssertEqual(expected.Action, actual.Action); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertMaskinportenSchemaDelegationExternalEqual(MaskinportenSchemaDelegationExternal expected, MaskinportenSchemaDelegationExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + Assert.Equal(expected.OfferedByName, actual.OfferedByName); + Assert.Equal(expected.OfferedByOrganizationNumber, actual.OfferedByOrganizationNumber); + Assert.Equal(expected.CoveredByPartyId, actual.CoveredByPartyId); + Assert.Equal(expected.CoveredByName, actual.CoveredByName); + Assert.Equal(expected.CoveredByOrganizationNumber, actual.CoveredByOrganizationNumber); + ////Assert.Equal(expected.PerformedByUserId, actual.PerformedByUserId); + Assert.Equal(expected.ResourceId, actual.ResourceId); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertCompetentAuthorityEqual(CompetentAuthorityExternal expected, CompetentAuthorityExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected?.Orgcode, actual.Orgcode); + Assert.Equal(expected?.Organization, actual.Organization); + Assert.Equal(expected?.Name, actual.Name); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertDelegationEqual(MPDelegationExternal expected, MPDelegationExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.SupplierOrg, actual.SupplierOrg); + Assert.Equal(expected.ConsumerOrg, actual.ConsumerOrg); + Assert.Equal(expected.Scopes, actual.Scopes); + Assert.Equal(expected.DelegationSchemeId, actual.DelegationSchemeId); + Assert.Equal(expected.Created, actual.Created); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertPartyEqual(PartyExternal expected, PartyExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.PartyTypeName, actual.PartyTypeName); + Assert.Equal(expected.OrgNumber, actual.OrgNumber); + Assert.Equal(expected.Organization.Name, actual.Organization.Name); + Assert.Equal(expected.Organization.OrgNumber, actual.Organization.OrgNumber); + Assert.Equal(expected.Organization.UnitType, actual.Organization.UnitType); + Assert.Equal(expected.PartyId, actual.PartyId); + Assert.Equal(expected.UnitType, actual.UnitType); + Assert.Equal(expected.Name, actual.Name); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRuleEqual(Rule expected, Rule actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.CreatedSuccessfully, actual.CreatedSuccessfully); + Assert.Equal(expected.DelegatedByUserId, actual.DelegatedByUserId); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + Assert.Equal(expected.Type, actual.Type); + AssertEqual(expected.CoveredBy, actual.CoveredBy); + AssertEqual(expected.Resource, actual.Resource); + AssertEqual(expected.Action, actual.Action); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRightExternalEqual(RightExternal expected, RightExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.RightKey, actual.RightKey); + AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchExternalEqual); + Assert.Equal(expected.Action, actual.Action); + Assert.Equal(expected.HasPermit, actual.HasPermit); + Assert.Equal(expected.CanDelegate, actual.CanDelegate); + AssertCollections(expected.RightSources, actual.RightSources, AssertRightSourceExternalEqual); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRightSourceExternalEqual(RightSourceExternal expected, RightSourceExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.RightSourceType, actual.RightSourceType); + Assert.Equal(expected.PolicyId, actual.PolicyId); + Assert.Equal(expected.PolicyVersion, actual.PolicyVersion); + Assert.Equal(expected.RuleId, actual.RuleId); + Assert.Equal(expected.HasPermit, actual.HasPermit); + Assert.Equal(expected.CanDelegate, actual.CanDelegate); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + + AssertCollections(expected.UserSubjects, actual.UserSubjects, AssertAttributeMatchExternalEqual); + AssertCollections(expected.PolicySubjects, actual.PolicySubjects, AssertPolicySubjects); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertBaseRightExternalEqual(BaseRightExternal expected, BaseRightExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchExternalEqual); + Assert.Equal(expected.Action, actual.Action); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRightsDelegationResponseExternalEqual(RightsDelegationResponseExternal expected, RightsDelegationResponseExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertCollections(expected.To, actual.To, AssertAttributeMatchExternalEqual); + AssertCollections(expected.RightDelegationResults, actual.RightDelegationResults, AssertRightDelegationResultExternalEqual); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRightDelegationResultExternalEqual(RightDelegationResultExternal expected, RightDelegationResultExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.RightKey, actual.RightKey); + AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchExternalEqual); + Assert.Equal(expected.Action, actual.Action); + Assert.Equal(expected.Status, actual.Status); + AssertCollections(expected.Details, actual.Details, AssertDetailExternalEqual); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertValidationProblemDetailsEqual(ValidationProblemDetails expected, ValidationProblemDetails actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Type, actual.Type); + Assert.Equal(expected.Title, actual.Title); + Assert.Equal(expected.Status, actual.Status); + + Assert.Equal(expected.Errors.Keys.Count, actual.Errors.Keys.Count); + Assert.True(expected.Errors.Keys.All(expectedKey => actual.Errors.ContainsKey(expectedKey))); + foreach (string expectedKey in expected.Errors.Keys) + { + Assert.Equal(expected.Errors[expectedKey], actual.Errors[expectedKey]); + } + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRightDelegationCheckExternalEqual(RightDelegationCheckResultExternal expected, RightDelegationCheckResultExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.RightKey, actual.RightKey); + AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchExternalEqual); + Assert.Equal(expected.Action, actual.Action); + Assert.Equal(expected.Status, actual.Status); + AssertCollections(expected.Details, actual.Details, AssertDetailExternalEqual); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertDetailExternalEqual(DetailExternal expected, DetailExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Code, actual.Code); + Assert.Equal(expected.Description, actual.Description); + AssertDetailParametersExternal(expected.Parameters, actual.Parameters); + } + + /// + /// Assert that two detail parameter dictionaries have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertDetailParametersExternal(Dictionary> expected, Dictionary> actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Keys.Count, actual.Keys.Count); + Assert.True(expected.Keys.All(expectedKey => actual.Keys.Contains(expectedKey))); + foreach (string key in expected.Keys) + { + AssertCollections(expected[key], actual[key], AssertAttributeMatchExternalEqual); + } + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertAuthorizedParty(AuthorizedParty expected, AuthorizedParty actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.PartyId, actual.PartyId); + Assert.Equal(expected.PartyUuid, actual.PartyUuid); + Assert.Equal(expected.Type, actual.Type); + Assert.Equal(expected.OrganizationNumber, actual.OrganizationNumber); + Assert.Equal(expected.PersonId, actual.PersonId); + Assert.Equal(expected.UnitType, actual.UnitType); + Assert.Equal(expected.Name, actual.Name); + Assert.Equal(expected.IsDeleted, actual.IsDeleted); + Assert.Equal(expected.OnlyHierarchyElementWithNoAccess, actual.OnlyHierarchyElementWithNoAccess); + Assert.Equal(expected.AuthorizedResources, actual.AuthorizedResources); + Assert.Equal(expected.AuthorizedRoles, actual.AuthorizedRoles); + AssertCollections(expected.Subunits, actual.Subunits, AssertAuthorizedParty); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertResourceRightDelegationCheckResultDto(ResourceRightDelegationCheckResultDto expected, ResourceRightDelegationCheckResultDto actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.RightKey, actual.RightKey); + Assert.Equal(expected.Status, actual.Status); + Assert.Equal(expected.Action.Value, actual.Action.Value); + AssertCollections(expected.Resource.ToList(), actual.Resource.ToList(), AssertUrnJsonTypeValue); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertAppsInstanceDelegationResponseDto(AppsInstanceDelegationResponseDto expected, AppsInstanceDelegationResponseDto actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertPartyUrn(expected.From, actual.From); + Assert.Equal(expected.To.Value, actual.To.Value); + Assert.Equal(expected.ResourceId, actual.ResourceId); + Assert.Equal(expected.InstanceId, actual.InstanceId); + AssertionUtil.AssertCollections(expected.Rights.ToList(), actual.Rights.ToList(), AssertDelegationRights); + } + + public static void AssertAppsInstanceRevokeResponseDto(AppsInstanceRevokeResponseDto expected, AppsInstanceRevokeResponseDto actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertPartyUrn(expected.From, actual.From); + Assert.Equal(expected.To.Value, actual.To.Value); + Assert.Equal(expected.ResourceId, actual.ResourceId); + Assert.Equal(expected.InstanceId, actual.InstanceId); + AssertionUtil.AssertCollections(expected.Rights.ToList(), actual.Rights.ToList(), AssertRevokeRights); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertDelegationRights(RightDelegationResultDto expected, RightDelegationResultDto actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertActionUrn(expected.Action, actual.Action); + Assert.Equal(expected.Status, actual.Status); + AssertionUtil.AssertCollections(expected.Resource.ToList(), actual.Resource.ToList(), AssertResource); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertRevokeRights(RightRevokeResultDto expected, RightRevokeResultDto actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + AssertActionUrn(expected.Action, actual.Action); + Assert.Equal(expected.Status, actual.Status); + AssertionUtil.AssertCollections(expected.Resource.ToList(), actual.Resource.ToList(), AssertResource); + } + + /// + /// Assert that two have the same property in the same positions. + /// + /// An instance with the expected values. + /// The instance to verify. + public static void AssertResource(UrnJsonTypeValue expected, UrnJsonTypeValue actual) + { + Assert.True(actual.HasValue); + Assert.True(expected.HasValue); + + Assert.Equal(expected.Value, actual.Value); + } + + /// + /// Assert that two have equal value. + /// + /// the expected value + /// the actual value + public static void AssertActionUrn(UrnJsonTypeValue expected, UrnJsonTypeValue actual) + { + Assert.True(actual.HasValue); + Assert.True(expected.HasValue); + + Assert.Equal(expected.Value.Urn, actual.Value.Urn); + } + + public static void AssertPartyUrn(UrnJsonTypeValue expected, UrnJsonTypeValue actual) + { + Assert.True(actual.HasValue); + Assert.True(expected.HasValue); + + Assert.Equal(expected.Value.Urn, actual.Value.Urn); + } + + private static void AssertUrnJsonTypeValue(UrnJsonTypeValue expected, UrnJsonTypeValue actual) + { + Assert.Equal(expected.Value, actual.Value); + } + + private static void AssertPolicySubjects(List expected, List actual) + { + AssertCollections(expected, actual, AssertPolicyAttributeMatchExternalEqual); + } + + private static void AssertPolicyAttributeMatchExternalEqual(PolicyAttributeMatchExternal expected, PolicyAttributeMatchExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.MatchFound, actual.MatchFound); + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Value, actual.Value); + } + + private static void AssertAttributeMatchExternalEqual(AttributeMatchExternal expected, AttributeMatchExternal actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Value, actual.Value); + } + + /// + /// Compares two list contains the same data + /// + /// the expected list + /// the actual list + public static void ListAccessManagementResourceAreEqual(List expected, List actual) + { + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < actual.Count; i++) + { + AccessManagementResource currentExpectedElement = expected[i]; + AccessManagementResource currentActualElement = actual[i]; + + Assert.Equal(currentExpectedElement.Created, currentActualElement.Created); + Assert.Equal(currentExpectedElement.Modified, currentActualElement.Modified); + Assert.Equal(currentExpectedElement.ResourceRegistryId, currentActualElement.ResourceRegistryId); + Assert.Equal(currentExpectedElement.ResourceId, currentActualElement.ResourceId); + Assert.Equal(currentExpectedElement.ResourceType, currentActualElement.ResourceType); + } + } + + private static void AssertEqual(List expected, List actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expected[i], actual[i]); + } + } + + private static void AssertEqual(AttributeMatch expected, AttributeMatch actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Value, actual.Value); + } + + private static void AssertEqual(XacmlJsonResult expected, XacmlJsonResult actual) + { + Assert.Equal(expected.Decision, actual.Decision); + Assert.Equal(expected.Status.StatusCode.Value, actual.Status.StatusCode.Value); + AssertEqual(expected.Obligations, actual.Obligations); + AssertEqual(expected.Category, actual.Category); + } + + private static void AssertEqual(List expected, List actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.NotNull(actual); + + Assert.Equal(expected.Count, actual.Count); + + AssertEqual(expected.FirstOrDefault(), actual.FirstOrDefault()); + } + + private static void AssertEqual(List expected, List actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.NotNull(actual); + + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expected[i], actual[i]); + } + } + + private static void AssertEqual(XacmlJsonCategory expected, XacmlJsonCategory actual) + { + Assert.Equal(expected.CategoryId, actual.CategoryId); + Assert.Equal(expected.Content, actual.Content); + Assert.Equal(expected.Id, actual.Id); + AssertEqual(expected.Attribute, actual.Attribute); + } + + private static void AssertEqual(XacmlJsonObligationOrAdvice expected, XacmlJsonObligationOrAdvice actual) + { + Assert.Equal(expected.AttributeAssignment.Count, actual.AttributeAssignment.Count); + + AssertEqual(expected.AttributeAssignment.FirstOrDefault(), actual.AttributeAssignment.FirstOrDefault()); + } + + private static void AssertEqual(XacmlJsonAttributeAssignment expected, XacmlJsonAttributeAssignment actual) + { + Assert.Equal(expected.AttributeId, actual.AttributeId); + Assert.Equal(expected.Category, actual.Category); + Assert.Equal(expected.DataType, actual.DataType); + Assert.Equal(expected.Issuer, actual.Issuer); + Assert.Equal(expected.Value, actual.Value, true); + } + + private static void AssertEqual(List expected, List actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.Equal(expected.Count, actual.Count); + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expected[i], actual[i]); + } + } + + private static void AssertEqual(XacmlJsonAttribute expected, XacmlJsonAttribute actual) + { + Assert.Equal(expected.AttributeId, actual.AttributeId); + Assert.Equal(expected.DataType, actual.DataType); + Assert.Equal(expected.IncludeInResult, actual.IncludeInResult); + Assert.Equal(expected.Issuer, actual.Issuer); + Assert.Equal(expected.Value, actual.Value, true); + } + + private static void AssertEqual(XacmlContextResult expected, XacmlContextResult actual) + { + Assert.NotNull(actual); + Assert.NotNull(expected); + + Assert.Equal(expected.Decision, actual.Decision); + + AssertEqual(expected.Status, actual.Status); + + AssertEqual(expected.Attributes, actual.Attributes); + + Assert.Equal(expected.Obligations.Count, actual.Obligations.Count); + + if (expected.Obligations.Count > 0) + { + AssertEqual(expected.Obligations.First(), actual.Obligations.First()); + } + } + + private static void AssertEqual(XacmlContextStatus expected, XacmlContextStatus actual) + { + if (expected != null) + { + Assert.NotNull(actual); + Assert.Equal(expected.StatusCode.StatusCode, actual.StatusCode.StatusCode); + } + } + + private static void AssertEqual(XacmlObligation expected, XacmlObligation actual) + { + Assert.Equal(expected.FulfillOn, actual.FulfillOn); + Assert.Equal(expected.ObligationId, actual.ObligationId); + Assert.Equal(expected.AttributeAssignment.Count, expected.AttributeAssignment.Count); + + if (expected.AttributeAssignment.Count > 0) + { + AssertEqual(expected.AttributeAssignment.First(), actual.AttributeAssignment.First()); + } + } + + private static void AssertEqual(ICollection expected, ICollection actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.NotNull(actual); + Assert.Equal(expected.Count, actual.Count); + + List expectedList = expected.ToList(); + List actualList = actual.ToList(); + + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expectedList[i], actualList[i]); + } + } + + private static void AssertEqual(XacmlContextAttributes expected, XacmlContextAttributes actual) + { + Assert.Equal(expected.Category.OriginalString, actual.Category.OriginalString); + + List expectedList = expected.Attributes.ToList(); + List actualList = actual.Attributes.ToList(); + + for (int i = 0; i < expected.Attributes.Count; i++) + { + AssertEqual(expectedList[i], actualList[i]); + } + } + + private static void AssertEqual(XacmlAttribute expected, XacmlAttribute actual) + { + Assert.Equal(expected.AttributeId, actual.AttributeId); + Assert.Equal(expected.IncludeInResult, actual.IncludeInResult); + Assert.Equal(expected.Issuer, actual.Issuer); + Assert.Equal(expected.AttributeValues.Count, actual.AttributeValues.Count); + AssertEqual(expected.AttributeValues, actual.AttributeValues); + } + + private static void AssertEqual(ICollection expected, ICollection actual) + { + List expectedList = expected.ToList(); + List actualList = actual.ToList(); + + for (int i = 0; i < expected.Count; i++) + { + AssertEqual(expectedList[i], actualList[i]); + } + } + + private static void AssertEqual(XacmlAttributeValue expected, XacmlAttributeValue actual) + { + Assert.Equal(expected.DataType, actual.DataType); + Assert.Equal(expected.Value, actual.Value, ignoreCase: true); + } + + private static void AssertEqual(XacmlAttributeAssignment expected, XacmlAttributeAssignment actual) + { + Assert.Equal(expected.Value, actual.Value, ignoreCase: true); + Assert.Equal(expected.Category, actual.Category); + Assert.Equal(expected.AttributeId, actual.AttributeId); + Assert.Equal(expected.DataType, actual.DataType); + } + + private static void AssertResourcePolicyEqual(ResourcePolicy expected, ResourcePolicy actual) + { + Assert.Equal(expected.Title, actual.Title); + AssertCollections(expected.Actions, actual.Actions, AssertResourceActionEqual); + AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchEqual); + if (expected.Description != null || actual.Description != null) + { + Assert.Equal(expected.Description, actual.Description); + } + } + + private static void AssertResourceActionEqual(ResourceAction expected, ResourceAction actual) + { + Assert.Equal(expected.Title, actual.Title); + AssertAttributeMatchEqual(expected.Match, actual.Match); + AssertCollections(expected.RoleGrants, actual.RoleGrants, AssertRoleGrantEqual); + + if (expected.Description != null && actual.Description != null) + { + Assert.Equal(expected.Description, actual.Description); + } + } + + private static void AssertRoleGrantEqual(RoleGrant expected, RoleGrant actual) + { + Assert.Equal(expected.IsDelegable, actual.IsDelegable); + Assert.Equal(expected.RoleTypeCode, actual.RoleTypeCode); + } + + private static void AssertAttributeMatchEqual(AttributeMatch expected, AttributeMatch actual) + { + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Value, actual.Value); + } + + private static void AssertEqual(Delegation expected, Delegation actual) + { + Assert.Equal(expected.CoveredByPartyId, actual.CoveredByPartyId); + Assert.Equal(expected.PerformedByUserId, actual.PerformedByUserId); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + Assert.Equal(expected.CoveredByName, actual.CoveredByName); + Assert.Equal(expected.CoveredByOrganizationNumber, actual.CoveredByOrganizationNumber); + } + + private static void AssertEqual(ServiceResource expected, ServiceResource actual) + { + Assert.Equal(expected.Identifier, actual.Identifier); + Assert.Equal(expected.Title, actual.Title); + } + + private static void AssertEqual(DelegationChangeExternal expected, DelegationChangeExternal actual) + { + Assert.Equal(expected.DelegationChangeId, actual.DelegationChangeId); + Assert.Equal(expected.ResourceRegistryDelegationChangeId, actual.ResourceRegistryDelegationChangeId); + Assert.Equal(expected.DelegationChangeType, actual.DelegationChangeType); + Assert.Equal(expected.ResourceId, actual.ResourceId); + Assert.Equal(expected.ResourceType, actual.ResourceType); + Assert.Equal(expected.OfferedByPartyId, actual.OfferedByPartyId); + Assert.Equal(expected.CoveredByPartyId, actual.CoveredByPartyId); + Assert.Equal(expected.CoveredByUserId, actual.CoveredByUserId); + Assert.Equal(expected.PerformedByUserId, actual.PerformedByUserId); + Assert.Equal(expected.PerformedByPartyId, actual.PerformedByPartyId); + Assert.Equal(expected.BlobStoragePolicyPath, actual.BlobStoragePolicyPath); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/JwtTokenMock.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/JwtTokenMock.cs new file mode 100644 index 00000000..56ed2aa2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/JwtTokenMock.cs @@ -0,0 +1,55 @@ +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography.X509Certificates; + +using Microsoft.IdentityModel.Tokens; + +namespace Altinn.AccessManagement.Tests.Utils +{ + /// + /// Represents a mechanism for creating JSON Web tokens for use in integration tests. + /// + public static class JwtTokenMock + { + /// + /// Generates a token with a self signed certificate included in the integration test project. + /// + /// The claims principal to include in the token. + /// How long the token should be valid for. + /// The URL of the token issuer + /// A new token. + public static string GenerateToken(ClaimsPrincipal principal, TimeSpan tokenExpiry, string issuer = "UnitTest") + { + JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); + SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(principal.Identity), + Expires = DateTime.UtcNow.AddSeconds(tokenExpiry.TotalSeconds), + SigningCredentials = GetSigningCredentials(issuer), + Audience = "altinn.no", + Issuer = issuer + }; + + SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); + string serializedToken = tokenHandler.WriteToken(token); + + return serializedToken; + } + + private static SigningCredentials GetSigningCredentials(string issuer) + { + string certPath = "selfSignedTestCertificate.pfx"; + if (!issuer.Equals("sbl.authorization") && !issuer.Equals("www.altinn.no") && !issuer.Equals("UnitTest")) + { + certPath = $"{issuer}-org.pfx"; + + X509Certificate2 certIssuer = new X509Certificate2(certPath); + return new X509SigningCredentials(certIssuer, SecurityAlgorithms.RsaSha256); + } + + X509Certificate2 cert = new X509Certificate2(certPath, "qwer1234"); + return new X509SigningCredentials(cert, SecurityAlgorithms.RsaSha256); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/PrincipalUtil.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/PrincipalUtil.cs new file mode 100644 index 00000000..f7652593 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/PrincipalUtil.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using Altinn.AccessManagement.Tests.Utils; +using Altinn.Common.AccessTokenClient.Constants; +using AltinnCore.Authentication.Constants; + +namespace Altinn.AccessManagement.Tests.Util +{ + /// + /// Utility class for usefull common operations for setup of authentication tokens for integration tests + /// + public static class PrincipalUtil + { + /// + /// Gets a user token + /// + /// The user id + /// The users party id + /// The users authentication level + /// jwt token string + public static string GetToken(int userId, int partyId, int authenticationLevel = 2) + { + List claims = new List(); + string issuer = "www.altinn.no"; + claims.Add(new Claim(AltinnCoreClaimTypes.UserId, userId.ToString(), ClaimValueTypes.String, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.UserName, "UserOne", ClaimValueTypes.String, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.PartyID, partyId.ToString(), ClaimValueTypes.Integer32, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticateMethod, "Mock", ClaimValueTypes.String, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticationLevel, authenticationLevel.ToString(), ClaimValueTypes.Integer32, issuer)); + + ClaimsIdentity identity = new ClaimsIdentity("mock"); + identity.AddClaims(claims); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); + string token = JwtTokenMock.GenerateToken(principal, new TimeSpan(1, 1, 1)); + + return token; + } + + /// + /// Get access token for issuer + /// + /// + public static string GetAccessToken(string issuer, string app) + { + List claims = new List + { + new Claim(AccessTokenClaimTypes.App, app, ClaimValueTypes.String, issuer) + }; + + ClaimsIdentity identity = new ClaimsIdentity("mock"); + identity.AddClaims(claims); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); + string token = JwtTokenMock.GenerateToken(principal, new TimeSpan(0, 1, 5), issuer); + + return token; + } + + /// + /// Gets an access token for an app + /// + /// The app to add as claim + /// + public static string GetAccessToken(string appId) + { + List claims = new List(); + string issuer = "www.altinn.no"; + if (!string.IsNullOrEmpty(appId)) + { + claims.Add(new Claim("urn:altinn:app", appId, ClaimValueTypes.String, issuer)); + } + + ClaimsIdentity identity = new ClaimsIdentity("mock-org"); + identity.AddClaims(claims); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); + string token = JwtTokenMock.GenerateToken(principal, new TimeSpan(1, 1, 1), issuer); + + return token; + } + + /// + /// Builds a claims principal used to generate an Altinn-token for an organization with the provided scopes, essentially mocking a Maskinporten-token exchanged to an Altinn-token. + /// + /// Org code + /// Organization number + /// Scopes to add to token + /// If maskinporten token sets the scope prefixes the organization owns or authorized for + /// Claims principal + public static ClaimsPrincipal GetClaimsPrincipal(string org, string orgNumber, string scope = null, string[] consumerPrefix = null) + { + string issuer = "https://platform.altinn.cloud/authentication/api/v1/openid/"; + + List claims = new List(); + if (scope != null) + { + claims.Add(new Claim("scope", scope, ClaimValueTypes.String)); + } + + if (consumerPrefix != null) + { + foreach (string prefix in consumerPrefix) + { + claims.Add(new Claim("consumer_prefix", prefix, ClaimValueTypes.String)); + } + } + + if (!string.IsNullOrEmpty(org)) + { + claims.Add(new Claim(AltinnCoreClaimTypes.Org, org, ClaimValueTypes.String, issuer)); + } + + claims.Add(new Claim("consumer", GetOrgNoObject(orgNumber))); + claims.Add(new Claim(AltinnCoreClaimTypes.OrgNumber, orgNumber.ToString(), ClaimValueTypes.Integer32, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticateMethod, "IntegrationTestMock", ClaimValueTypes.String, issuer)); + claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticationLevel, "3", ClaimValueTypes.Integer32, issuer)); + + ClaimsIdentity identity = new ClaimsIdentity("mock-org"); + identity.AddClaims(claims); + + return new ClaimsPrincipal(identity); + } + + /// + /// Generates an Altinn-token for an organization with the provided scopes, essentially mocking a Maskinporten-token exchanged to an Altinn-token. + /// + /// Org code + /// Organization number + /// Scopes to add to token + /// If maskinporten token sets the scope prefixes the organization owns or authorized for + /// Altinn org-token + public static string GetOrgToken(string org, string orgNumber = "991825827", string scope = null, string[] consumerPrefix = null) + { + ClaimsPrincipal principal = GetClaimsPrincipal(org, orgNumber, scope, consumerPrefix); + + string token = JwtTokenMock.GenerateToken(principal, new TimeSpan(0, 30, 0)); + + return token; + } + + private static string GetOrgNoObject(string orgNo) + { + return $"{{ \"authority\":\"iso6523-actorid-upis\", \"ID\":\"0192:{orgNo}\"}}"; + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/SetupUtils.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/SetupUtils.cs new file mode 100644 index 00000000..1107cedc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/SetupUtils.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using System.Net.Http; +using Altinn.AccessManagement.Controllers; +using Altinn.AccessManagement.Core.Clients.Interfaces; +using Altinn.AccessManagement.Core.Repositories.Interfaces; +using Altinn.AccessManagement.Core.Services.Interfaces; +using Altinn.AccessManagement.Tests.Controllers; +using Altinn.AccessManagement.Tests.Mocks; +using AltinnCore.Authentication.JwtCookie; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Altinn.AccessManagement.Tests.Utils +{ + /// + /// Utility class for usefull common operations for setup for unittests + /// + public static class SetupUtils + { + /// + /// Gets a HttpClient for unittests testing + /// + /// Web app factory to configure test services for + /// HttpClient + public static HttpClient GetTestClient(CustomWebApplicationFactory customFactory) + { + WebApplicationFactory factory = customFactory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton, JwtCookiePostConfigureOptionsStub>(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + }); + }); + factory.Server.AllowSynchronousIO = true; + return factory.CreateClient(); + } + + /// + /// Deletes a app blob stored locally + /// + /// Org + /// App + public static void DeleteAppBlobData(string org, string app) + { + string blobPath = Path.Combine(GetDataBlobPath(), $"{org}/{app}"); + + if (Directory.Exists(blobPath)) + { + Directory.Delete(blobPath, true); + } + } + + /// + /// Adds an auth cookie to the request message + /// + /// the request message + /// the tijen to be added in the cookie + /// the name of the cookie + /// the xsrf token + public static void AddAuthCookie(HttpRequestMessage requestMessage, string token, string cookieName, string xsrfToken = null) + { + requestMessage.Headers.Add("Cookie", cookieName + "=" + token); + if (xsrfToken != null) + { + requestMessage.Headers.Add("X-XSRF-TOKEN", xsrfToken); + } + } + + private static string GetDataBlobPath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "..", "..", "..", "data", "blobs"); + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/TestDataUtil.cs b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/TestDataUtil.cs new file mode 100644 index 00000000..7731c5ae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/Utils/TestDataUtil.cs @@ -0,0 +1,544 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Altinn.AccessManagement.Core.Constants; +using Altinn.AccessManagement.Core.Enums; +using Altinn.AccessManagement.Core.Models; +using Altinn.AccessManagement.Core.Models.ResourceRegistry; +using Altinn.AccessManagement.Enums.ResourceRegistry; +using Altinn.AccessManagement.Models; +using Altinn.AccessManagement.Tests.Controllers; +using Altinn.AccessManagement.Tests.Mocks; +using Altinn.Authorization.ABAC.Constants; +using Altinn.Platform.Register.Models; + +namespace Altinn.AccessManagement.Tests.Utils +{ + /// + /// Mock class for helping setup test data + /// + public static class TestDataUtil + { + /// + /// Creates a rule model from the input + /// + /// delegatedBy + /// offeredByPartyId + /// coveredBy + /// coveredByAttributeType + /// action + /// org + /// app + /// task + /// appresource + /// createdSuccessfully + /// ruleType + /// resourceregistry id. + /// Value indicating delegatedBy is party + /// Rule model + public static Rule GetRuleModel(int delegatedBy, int offeredByPartyId, string coveredBy, string coveredByAttributeType, string action, string org, string app, string task = null, string appresource = null, bool createdSuccessfully = false, RuleType ruleType = RuleType.None, string resourceRegistryId = null, bool delegatedByParty = false) + { + Rule rule; + + if (!string.IsNullOrEmpty(resourceRegistryId)) + { + rule = new Rule + { + DelegatedByUserId = delegatedByParty ? null : delegatedBy, + DelegatedByPartyId = delegatedByParty ? delegatedBy : null, + OfferedByPartyId = offeredByPartyId, + CoveredBy = new List { new AttributeMatch { Id = coveredByAttributeType, Value = coveredBy } }, + Resource = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.ResourceRegistryAttribute, Value = resourceRegistryId } }, + Action = new AttributeMatch { Id = XacmlConstants.MatchAttributeIdentifiers.ActionId, Value = action }, + CreatedSuccessfully = createdSuccessfully, + Type = ruleType + }; + } + else + { + rule = new Rule + { + DelegatedByUserId = delegatedByParty ? null : delegatedBy, + DelegatedByPartyId = delegatedByParty ? delegatedBy : null, + OfferedByPartyId = offeredByPartyId, + CoveredBy = new List { new AttributeMatch { Id = coveredByAttributeType, Value = coveredBy } }, + Resource = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute, Value = org }, new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute, Value = app } }, + Action = new AttributeMatch { Id = XacmlConstants.MatchAttributeIdentifiers.ActionId, Value = action }, + CreatedSuccessfully = createdSuccessfully, + Type = ruleType + }; + } + + if (task != null) + { + rule.Resource.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.TaskAttribute, Value = task }); + } + + if (appresource != null) + { + rule.Resource.Add(new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.AppResourceAttribute, Value = appresource }); + } + + return rule; + } + + /// + /// Creates a RequestToDelete model from the input + /// + /// lastChangedByUserId + /// offeredByPartyId + /// org + /// app + /// ruleIds + /// coveredByPartyId + /// coveredByUserId + /// + public static RequestToDelete GetRequestToDeleteModel(int lastChangedByUserId, int offeredByPartyId, string org, string app, List ruleIds = null, int? coveredByPartyId = null, int? coveredByUserId = null) + { + AttributeMatch coveredBy = new AttributeMatch(); + if (coveredByUserId == null) + { + coveredBy.Id = AltinnXacmlConstants.MatchAttributeIdentifiers.PartyAttribute; + coveredBy.Value = coveredByPartyId.ToString(); + } + else + { + coveredBy.Id = AltinnXacmlConstants.MatchAttributeIdentifiers.UserAttribute; + coveredBy.Value = coveredByUserId.ToString(); + } + + RequestToDelete requestToDelete = new RequestToDelete + { + DeletedByUserId = lastChangedByUserId, + PolicyMatch = new PolicyMatch + { + CoveredBy = new List { coveredBy }, + OfferedByPartyId = offeredByPartyId, + Resource = new List { new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.OrgAttribute, Value = org }, new AttributeMatch { Id = AltinnXacmlConstants.MatchAttributeIdentifiers.AppAttribute, Value = app } } + }, + RuleIds = ruleIds + }; + + return requestToDelete; + } + + /// + /// Creates a DelegationChange model from the input + /// + /// altinnAppId + /// offeredByPartyId + /// coveredByUserId + /// coveredByPartyId + /// performedByUserId + /// changeType + /// changeId + /// + public static DelegationChange GetAltinnAppDelegationChange(string altinnAppId, int offeredByPartyId, int? coveredByUserId = null, int? coveredByPartyId = null, int performedByUserId = 20001336, DelegationChangeType changeType = DelegationChangeType.Grant, int changeId = 1337) + { + string coveredBy = coveredByPartyId != null ? $"p{coveredByPartyId}" : $"u{coveredByUserId}"; + return new DelegationChange + { + DelegationChangeId = changeId, + DelegationChangeType = changeType, + ResourceId = altinnAppId, + ResourceType = ResourceAttributeMatchType.AltinnAppId.ToString(), + OfferedByPartyId = offeredByPartyId, + CoveredByPartyId = coveredByPartyId, + CoveredByUserId = coveredByUserId, + PerformedByUserId = performedByUserId, + BlobStoragePolicyPath = $"{altinnAppId}/{offeredByPartyId}/{coveredBy}/delegationpolicy.xml", + BlobStorageVersionId = "CorrectLeaseId", + Created = DateTime.Now + }; + } + + /// + /// Sets up mock data for delegation list + /// + /// partyid of the reportee that delegated the resource + /// resource identifier + /// Resource name + /// who performed the delegation + /// + public static List GetDelegations(int offeredByPartyId, string resourceId, string resourceName, int performedByUserId) + { + List delegations = new List(); + delegations.Add(new Delegation + { + OfferedByPartyId = offeredByPartyId, + PerformedByUserId = performedByUserId, + CoveredByName = "KOLSAAS OG FLAAM", + CoveredByOrganizationNumber = "810418192", + CoveredByPartyId = 50004219, + }); + delegations.Add(new Delegation + { + OfferedByPartyId = offeredByPartyId, + PerformedByUserId = performedByUserId, + CoveredByName = "NORDRE FROGN OG MORTENHALS", + CoveredByOrganizationNumber = "810418362", + CoveredByPartyId = 50004220, + }); + delegations.Add(new Delegation + { + OfferedByPartyId = offeredByPartyId, + PerformedByUserId = performedByUserId, + CoveredByName = "LUNDAMO OG FLEINVAR", + CoveredByOrganizationNumber = "810418532", + CoveredByPartyId = 50004221, + }); + return delegations; + } + + /// + /// Creates a ServiceResource model. + /// + /// ResourceId. + /// title of the resource + /// Type of the resource + /// Description of the resource + /// The valid from date + /// The valid to date + /// The status of resource + /// Returns the newly created ServiceResource. + public static ServiceResource GetResource(string resourceId, string resourceTitle, ResourceType resourceType, string description = "Test", DateTime? validFrom = null, DateTime? validTo = null, string status = "Active") + { + if (resourceId == "nav1_aa_distribution") + { + return new ServiceResource + { + Identifier = resourceId, + Title = new Dictionary + { + { "en", "Not Available" }, + { "nb-no", "ikke tilgjengelig" }, + { "nn-no", "ikkje tilgjengelig" }, + }, + Description = new Dictionary + { + { "Description", resourceTitle } + }, + Status = "NA", + ResourceType = resourceType, + }; + } + else + { + return new ServiceResource + { + Identifier = resourceId, + Title = new Dictionary + { + { "en", resourceTitle }, + { "nb-no", resourceTitle }, + { "nn-no", resourceTitle }, + }, + Description = new Dictionary + { + { "en", description }, + { "nb-no", description }, + { "nn-no", description } + }, + Status = status, + ResourceType = resourceType, + }; + } + } + + /// + /// Creates a DelegationChange model from the input. + /// + /// DelegationChange. + public static DelegationChange GetResourceRegistryDelegationChange(string resourceRegistryId, ResourceType resourceType, int offeredByPartyId, DateTime? created, int? coveredByUserId = null, int? coveredByPartyId = null, int performedByUserId = 20001336, DelegationChangeType changeType = DelegationChangeType.Grant, int changeId = 1337) + { + string coveredBy = coveredByPartyId != null ? $"p{coveredByPartyId}" : $"u{coveredByUserId}"; + + return new DelegationChange + { + DelegationChangeId = changeId, + DelegationChangeType = changeType, + ResourceId = resourceRegistryId, + ResourceType = resourceType.ToString(), + OfferedByPartyId = offeredByPartyId, + CoveredByPartyId = coveredByPartyId, + CoveredByUserId = coveredByUserId, + PerformedByUserId = performedByUserId, + BlobStoragePolicyPath = $"resourceregistry/{resourceRegistryId}/{offeredByPartyId}/{coveredBy}/delegationpolicy.xml", + BlobStorageVersionId = "CorrectLeaseId", + Created = created + }; + } + + /// + /// Creates a list of roles. + /// + /// The newly created list of roles. + public static List GetRolesWithAccess() + { + List roles = new List(); + roles.Add("BEST"); + roles.Add("BOBE"); + roles.Add("DAGL"); + roles.Add("DTPR"); + roles.Add("DTSO"); + roles.Add("INNH"); + roles.Add("KEMN"); + roles.Add("KOMP"); + roles.Add("LEDE"); + roles.Add("REPR"); + + return roles; + } + + /// + /// Sets up mock data for offered maskinporten schema delegations + /// + /// The party id of the reportee to retrieve offered delegations for + /// Offered maskinporten schema delegations + public static List GetOfferedMaskinportenSchemaDelegations(int offeredByPartyId) + { + List delegations = null; + + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + string path = Path.Combine(unitTestFolder, "Data", "Json", "MaskinportenSchema", "Offered.json"); + if (File.Exists(path)) + { + string content = File.ReadAllText(path); + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + try + { + delegations = JsonSerializer.Deserialize>(content, options); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + + if (offeredByPartyId != 0) + { + return delegations.FindAll(d => d.OfferedByPartyId == offeredByPartyId); + } + } + + return delegations; + } + + /// + /// Sets up mock data for received maskinporten schema delegations + /// + /// The party id of the reportee to retrieve received delegations for + /// Received maskinporten schema delegations + public static List GetReceivedMaskinportenSchemaDelegations(int coveredByPartyId) + { + List delegations = null; + + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + string path = Path.Combine(unitTestFolder, "Data", "Json", "MaskinportenSchema", "Received.json"); + if (File.Exists(path)) + { + string content = File.ReadAllText(path); + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + + try + { + delegations = JsonSerializer.Deserialize>(content, options); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + + if (coveredByPartyId != 0) + { + return delegations.FindAll(d => d.CoveredByPartyId == coveredByPartyId); + } + } + + return delegations; + } + + /// + /// Sets up mock data for admin delegation list + /// + /// partyid of the reportee that delegated the resource + /// partyid of the reportee that received the delegation + /// resource id + /// Received delegations + public static List GetAdminDelegations(string supplierOrg, string consumerOrg, List resourceIds = null) + { + List delegations = null; + List filteredDelegations = new List(); + string fileName = "admindelegations"; + string path = GetDelegationPath(); + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + + foreach (string file in files) + { + if (file.Contains(fileName)) + { + string content = File.ReadAllText(Path.Combine(path, file)); + try + { + delegations = JsonSerializer.Deserialize>(content); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + } + + foreach (MPDelegationExternal delegation in delegations) + { + if (delegation.SupplierOrg == supplierOrg && delegation.ConsumerOrg == consumerOrg && resourceIds.Contains(delegation.ResourceId)) + { + filteredDelegations.Add(delegation); + } + } + } + + return filteredDelegations; + } + + /// + /// Gets the organisation information + /// + /// the organisation number + /// organisation information + public static PartyExternal GetOrganisation(string orgNummer) + { + List partyList = new List(); + PartyExternal party = null; + + string path = GetPartiesPath(); + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + + foreach (string file in files) + { + if (file.Contains("parties")) + { + string content = File.ReadAllText(Path.Combine(path, file)); + partyList = JsonSerializer.Deserialize>(content); + } + } + + party = partyList.Find(p => p.Organization?.OrgNumber == orgNummer); + } + + return party; + } + + /// + /// Gets the party information + /// + /// The party id + /// Party information + public static PartyExternal GetTestParty(int partyId) + { + List partyList = new List(); + PartyExternal party = null; + + string path = GetPartiesPath(); + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + + foreach (string file in files) + { + if (file.Contains("parties")) + { + string content = File.ReadAllText(Path.Combine(path, file)); + partyList = JsonSerializer.Deserialize>(content); + } + } + + party = partyList.Find(p => p.PartyId == partyId); + } + + return party; + } + + /// + /// Gets the party information for a party with subunit + /// + /// The party id + /// Party information + public static PartyExternal GetTestPartyWithSubUnit(int partyId) + { + List partyList = new List(); + + string path = GetPartiesPath(); + if (Directory.Exists(path)) + { + string[] files = Directory.GetFiles(path); + + foreach (string file in files) + { + if (file.Contains("parties")) + { + string content = File.ReadAllText(Path.Combine(path, file)); + partyList = JsonSerializer.Deserialize>(content); + } + } + + foreach (PartyExternal party in partyList) + { + if (party != null && party.PartyId == partyId) + { + return party; + } + else if (party != null && party.ChildParties != null && party.ChildParties.Count > 0) + { + foreach (Party childParty in party.ChildParties) + { + if (childParty.PartyId == partyId) + { + return MapPartyToPartyExternal(childParty); + } + } + } + } + } + + return null; + } + + private static PartyExternal MapPartyToPartyExternal(Party party) + { + PartyExternal partyExternal = new PartyExternal + { + PartyId = party.PartyId, + PartyTypeName = party.PartyTypeName, + OrgNumber = party.OrgNumber, + SSN = party.SSN, + UnitType = party.UnitType, + Name = party.Name, + IsDeleted = party.IsDeleted, + OnlyHierarchyElementWithNoAccess = party.OnlyHierarchyElementWithNoAccess, + Person = party.Person, + Organization = party.Organization, + ChildParties = party.ChildParties + }; + + return partyExternal; + } + + private static string GetDelegationPath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(DelegationsControllerTest).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "Json", "MaskinportenSchema"); + } + + private static string GetPartiesPath() + { + string unitTestFolder = Path.GetDirectoryName(new Uri(typeof(PartiesClientMock).Assembly.Location).LocalPath); + return Path.Combine(unitTestFolder, "Data", "Parties"); + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/appsettings.test.json b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/appsettings.test.json new file mode 100644 index 00000000..3df74ead --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/appsettings.test.json @@ -0,0 +1,34 @@ +{ + "AzureStorageConfiguration": { + "MetadataAccountName": "devstoreaccount1", + "MetadataAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "MetadataContainer": "metadata", + "MetadataBlobEndpoint": "http://127.0.0.1:10000/devstoreaccount1", + "DelegationsAccountName": "devstoreaccount1", + "DelegationsAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "DelegationsContainer": "metadata", + "DelegationsBlobEndpoint": "http://127.0.0.1:10000/devstoreaccount1", + "BlobLeaseTimeout": 15, + "DelegationEventQueueEndpoint": "http://127.0.0.1:10000/devstoreaccount1", + "DelegationEventQueueAccountName": "devstoreaccount1", + "DelegationEventQueueAccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + }, + "AzureCosmosSettings": { + "EndpointUri": "https://localhost:8081", + "PrimaryKey": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", + "Database": "Storage", + "InstanceCollection": "instances", + "ApplicationCollection": "applications" + }, + "PostgreSQLSettings": { + "EnableDBConnection": "false" + }, + "GeneralSettings": { + "BridgeApiEndpoint": "http://localhost:88/sblbridge/authorization/api/", + "SBLBaseAdress": "https://at22.altinn.cloud/", + "RoleCacheTimeout": 5, + "MainUnitCacheTimeout": 5, + "KeyrolePartyIdsCacheTimeout": 5, + "PolicyCacheTimeout": 10 + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pem b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pem new file mode 100644 index 00000000..f2a42d40 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAeugAwIBAgIJANTdO8o3I8x5MA0GCSqGSIb3DQEBCwUAMA4xDDAKBgNV +BAMTA3R0ZDAeFw0yMDA1MjUxMjIxMzdaFw0zMDA1MjQxMjIxMzdaMA4xDDAKBgNV +BAMTA3R0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcfTsXwwLyC +UkIz06eadWJvG3yrzT+ZB2Oy/WPaZosDnPcnZvCDueN+oy0zTx5TyH5gCi1FvzX2 +7G2eZEKwQaRPv0yuM+McHy1rXxMSOlH/ebP9KJj3FDMUgZl1DCAjJxSAANdTwdrq +ydVg1Crp37AQx8IIEjnBhXsfQh1uPGt1XwgeNyjl00IejxvQOPzd1CofYWwODVtQ +l3PKn1SEgOGcB6wuHNRlnZPCIelQmqxWkcEZiu/NU+kst3NspVUQG2Jf2AF8UWgC +rnrhMQR0Ra1Vi7bWpu6QIKYkN9q0NRHeRSsELOvTh1FgDySYJtNd2xDRSf6IvOiu +tSipl1NZlV0CAwEAAaNkMGIwIAYDVR0OAQH/BBYEFIwq/KbSMzLETdo9NNxj0rz4 +qMqVMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAE56UmH5gEYbe +1kVw7nrfH0R9FyVZGeQQWBn4/6Ifn+eMS9mxqe0Lq74Ue1zEzvRhRRqWYi9JlKNf +7QQNrc+DzCceIa1U6cMXgXKuXquVHLmRfqvKHbWHJfIkaY8Mlfy++77UmbkvIzly +T1HVhKKp6Xx0r5koa6frBh4Xo/vKBlEyQxWLWF0RPGpGErnYIosJ41M3Po3nw3lY +f7lmH47cdXatcntj2Ho/b2wGi9+W29teVCDfHn2/0oqc7K0EOY9c2ODLjUvQyPZR +OD2yykpyh9x/YeYHFDYdLDJ76/kIdxN43kLU4/hTrh9tMb1PZF+/4DshpAlRoQuL +o8I8avQm/A== +-----END CERTIFICATE----- diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pfx b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pfx new file mode 100644 index 00000000..6da835fb Binary files /dev/null and b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/platform-org.pfx differ diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificate.pfx b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificate.pfx new file mode 100644 index 00000000..e99715b3 Binary files /dev/null and b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificate.pfx differ diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificatePublic.cer b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificatePublic.cer new file mode 100644 index 00000000..b7698d9d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/selfSignedTestCertificatePublic.cer @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID/zCCAuegAwIBAgIQF2ov3ZZUmJVKtoz0a1fabDANBgkqhkiG9w0BAQsFADB/ +MRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHY29udG9zbzEU +MBIGCgmSJomT8ixkARkWBGNvcnAxFTATBgNVBAsMDFVzZXJBY2NvdW50czEiMCAG +A1UEAwwZQWx0aW5uIFBsYXRmb3JtIFVuaXQgdGVzdDAgFw0yMDA0MTQwOTMwMTda +GA8yMTIwMDQxNDA5NDAxOFowfzETMBEGCgmSJomT8ixkARkWA2NvbTEXMBUGCgmS +JomT8ixkARkWB2NvbnRvc28xFDASBgoJkiaJk/IsZAEZFgRjb3JwMRUwEwYDVQQL +DAxVc2VyQWNjb3VudHMxIjAgBgNVBAMMGUFsdGlubiBQbGF0Zm9ybSBVbml0IHRl +c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCAKc+q5jbYFyQFxM1 +xU3v0N477ppnMu03K8qlEkX0+yffRHcR1I0Kku8yg1S+LQjeqh1K42b270myKiIt +vxeuNnanRwdehTZthThembr8RXoGcmzaXfMet7NVDgUa7gNzPXbqjhTFdyWoZzeU +X6TWTgFtciTs5M1F50H+3nieGKX2dvLUIEXWFO7yevj9bqtI8k0b66eLgBjchnjW +8B7oYOFZW44VDDnqQrvFJ9aMQ44FfLAWWLcy6nBzcDdK+Z+yq9FNVgduyl0J7vRo +3UtcVazLUvmDdwASLIB3IwB7YmT6fuOyM+6eyw5F1CdjXbc/bhop0pCDY1aAEsZA +CjT9AgMBAAGjdTBzMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcD +AjAtBgNVHREEJjAkoCIGCisGAQQBgjcUAgOgFAwSdGVzdEBhbHRpbm4uc3R1ZGlv +MB0GA1UdDgQWBBTv8Cpf5J7nfmGds20LU/J3bg05XTANBgkqhkiG9w0BAQsFAAOC +AQEAahWeu6ymaiJe9+LiMlQwNsUIV4KaLX+jCsRyF1jUJ0C13aFALGM4k9svqqXR +DzBdCXXr0c1E+Ks3sCwBLfK5yj5fTI+pL26ceEmHahcVyLvzEBljtNb4FnGFs92P +CH0NuCz45hQ2O9/Tv4cZAdgledTznJTKzzQNaF8M6iINmP6sf4kOg0BQx0K71K4f +7j2oQvYKiT7Zv1e83cdk9pS4ihDe+ZWYiGUM/IuaXNPl6OzVk4rY88PZJAoz7q33 +rYjlT+zkcl3dzTc3E0CWzbIWjhaXCRWvlI44cLRtdpmPqJUHI6a/tcGwNb5vWiT4 +YfZJ0EZ2iSRQlpU3+jMs8Ci2AA== +-----END CERTIFICATE----- diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pem b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pem new file mode 100644 index 00000000..f2a42d40 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAeugAwIBAgIJANTdO8o3I8x5MA0GCSqGSIb3DQEBCwUAMA4xDDAKBgNV +BAMTA3R0ZDAeFw0yMDA1MjUxMjIxMzdaFw0zMDA1MjQxMjIxMzdaMA4xDDAKBgNV +BAMTA3R0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcfTsXwwLyC +UkIz06eadWJvG3yrzT+ZB2Oy/WPaZosDnPcnZvCDueN+oy0zTx5TyH5gCi1FvzX2 +7G2eZEKwQaRPv0yuM+McHy1rXxMSOlH/ebP9KJj3FDMUgZl1DCAjJxSAANdTwdrq +ydVg1Crp37AQx8IIEjnBhXsfQh1uPGt1XwgeNyjl00IejxvQOPzd1CofYWwODVtQ +l3PKn1SEgOGcB6wuHNRlnZPCIelQmqxWkcEZiu/NU+kst3NspVUQG2Jf2AF8UWgC +rnrhMQR0Ra1Vi7bWpu6QIKYkN9q0NRHeRSsELOvTh1FgDySYJtNd2xDRSf6IvOiu +tSipl1NZlV0CAwEAAaNkMGIwIAYDVR0OAQH/BBYEFIwq/KbSMzLETdo9NNxj0rz4 +qMqVMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAE56UmH5gEYbe +1kVw7nrfH0R9FyVZGeQQWBn4/6Ifn+eMS9mxqe0Lq74Ue1zEzvRhRRqWYi9JlKNf +7QQNrc+DzCceIa1U6cMXgXKuXquVHLmRfqvKHbWHJfIkaY8Mlfy++77UmbkvIzly +T1HVhKKp6Xx0r5koa6frBh4Xo/vKBlEyQxWLWF0RPGpGErnYIosJ41M3Po3nw3lY +f7lmH47cdXatcntj2Ho/b2wGi9+W29teVCDfHn2/0oqc7K0EOY9c2ODLjUvQyPZR +OD2yykpyh9x/YeYHFDYdLDJ76/kIdxN43kLU4/hTrh9tMb1PZF+/4DshpAlRoQuL +o8I8avQm/A== +-----END CERTIFICATE----- diff --git a/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pfx b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pfx new file mode 100644 index 00000000..6da835fb Binary files /dev/null and b/src/apps/Altinn.AccessManagement/test/Altinn.AccessManagement.Tests/ttd-org.pfx differ diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.env.sample b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.env.sample new file mode 100644 index 00000000..661d0e6a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.env.sample @@ -0,0 +1,2 @@ +TOKEN_BASIC_AUTH_USER= +TOKEN_BASIC_AUTH_PW= diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.gitignore b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.gitignore new file mode 100644 index 00000000..ca52a3f9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/.gitignore @@ -0,0 +1,3 @@ +# Bruno +local +.env diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl.bru new file mode 100644 index 00000000..b227a989 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl.bru @@ -0,0 +1,75 @@ +meta { + name: InstDelgParties_AsAccMngr_ToOrg_Dagl + type: http + seq: 5 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.organizations.legitimJusterbarTiger.dagl.personId, + auth_userId: testdata.organizations.legitimJusterbarTiger.dagl.userId, + auth_partyId: testdata.organizations.legitimJusterbarTiger.dagl.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.organizations.legitimJusterbarTiger.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToOrg_Dagl"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl_InclA2.bru new file mode 100644 index 00000000..4d645ce4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToOrg_Dagl_InclA2.bru @@ -0,0 +1,75 @@ +meta { + name: InstDelgParties_AsAccMngr_ToOrg_Dagl_InclA2 + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.organizations.legitimJusterbarTiger.dagl.personId, + auth_userId: testdata.organizations.legitimJusterbarTiger.dagl.userId, + auth_partyId: testdata.organizations.legitimJusterbarTiger.dagl.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.organizations.legitimJusterbarTiger.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToOrg_Dagl_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self.bru new file mode 100644 index 00000000..8ca7e73d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self.bru @@ -0,0 +1,78 @@ +meta { + name: InstDelgParties_AsAccMngr_ToPerson_Self + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.hakkeDyr.personId, + auth_userId: testdata.persons.hakkeDyr.userId, + auth_partyId: testdata.persons.hakkeDyr.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.persons.hakkeDyr.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToPerson_Self"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self_InclA2.bru new file mode 100644 index 00000000..25fb9919 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_Self_InclA2.bru @@ -0,0 +1,78 @@ +meta { + name: InstDelgParties_AsAccMngr_ToPerson_Self_InclA2 + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.hakkeDyr.personId, + auth_userId: testdata.persons.hakkeDyr.userId, + auth_partyId: testdata.persons.hakkeDyr.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.persons.hakkeDyr.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToPerson_Self_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly.bru new file mode 100644 index 00000000..99d54108 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly.bru @@ -0,0 +1,61 @@ +meta { + name: InstDelgParties_AsAccMngr_ToPerson_SubOnly + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.spesifikkSmaragd.personId, + auth_userId: testdata.persons.spesifikkSmaragd.userId, + auth_partyId: testdata.persons.spesifikkSmaragd.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.persons.spesifikkSmaragd.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToPerson_SubOnly"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly_InclA2.bru new file mode 100644 index 00000000..974b27c7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAccessManager/InstDelgParties_AsAccMngr_ToPerson_SubOnly_InclA2.bru @@ -0,0 +1,61 @@ +meta { + name: InstDelgParties_AsAccMngr_ToPerson_SubOnly_InclA2 + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.spesifikkSmaragd.personId, + auth_userId: testdata.persons.spesifikkSmaragd.userId, + auth_partyId: testdata.persons.spesifikkSmaragd.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + bru.setVar("party", testdata.persons.spesifikkSmaragd.partyId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAccMngr_ToPerson_SubOnly_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl.bru new file mode 100644 index 00000000..a9eacc95 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl.bru @@ -0,0 +1,74 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToOrg_Dagl + type: http + seq: 5 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.organizations.legitimJusterbarTiger.dagl.personId, + auth_userId: testdata.organizations.legitimJusterbarTiger.dagl.userId, + auth_partyId: testdata.organizations.legitimJusterbarTiger.dagl.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToOrg_Dagl"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl_InclA2.bru new file mode 100644 index 00000000..db410c39 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToOrg_Dagl_InclA2.bru @@ -0,0 +1,74 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToOrg_Dagl_InclA2 + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.organizations.legitimJusterbarTiger.dagl.personId, + auth_userId: testdata.organizations.legitimJusterbarTiger.dagl.userId, + auth_partyId: testdata.organizations.legitimJusterbarTiger.dagl.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToOrg_Dagl_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson.bru new file mode 100644 index 00000000..910d6b6c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson.bru @@ -0,0 +1,77 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToPerson + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.hakkeDyr.personId, + auth_userId: testdata.persons.hakkeDyr.userId, + auth_partyId: testdata.persons.hakkeDyr.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToPerson"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_InclA2.bru new file mode 100644 index 00000000..58cac01a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_InclA2.bru @@ -0,0 +1,77 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToPerson_InclA2 + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.hakkeDyr.personId, + auth_userId: testdata.persons.hakkeDyr.userId, + auth_partyId: testdata.persons.hakkeDyr.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToPerson_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnly.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnly.bru new file mode 100644 index 00000000..e719f374 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnly.bru @@ -0,0 +1,60 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToPerson_SubOnly + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.spesifikkSmaragd.personId, + auth_userId: testdata.persons.spesifikkSmaragd.userId, + auth_partyId: testdata.persons.spesifikkSmaragd.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToPerson_SubOnly"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnlyInclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnlyInclA2.bru new file mode 100644 index 00000000..aa7a08ec --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsAuthenticatedUser/InstDelgParties_AsAuthnUser_ToPerson_SubOnlyInclA2.bru @@ -0,0 +1,60 @@ +meta { + name: InstDelgParties_AsAuthnUser_ToPerson_SubOnlyInclA2 + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_ssn: testdata.persons.spesifikkSmaragd.personId, + auth_userId: testdata.persons.spesifikkSmaragd.userId, + auth_partyId: testdata.persons.spesifikkSmaragd.partyId + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsAuthnUser_ToPerson_SubOnlyInclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg.bru new file mode 100644 index 00000000..91ec1f22 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg.bru @@ -0,0 +1,83 @@ +meta { + name: InstDelgParties_AsResOwner_ToOrg + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:organization:identifier-no", + "value": "{{toOrganizationId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toOrganizationId", testdata.organizations.legitimJusterbarTiger.organizationNumber); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToOrg"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl.bru new file mode 100644 index 00000000..d54348b0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl.bru @@ -0,0 +1,83 @@ +meta { + name: InstDelgParties_AsResOwner_ToOrg_Dagl + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.organizations.legitimJusterbarTiger.dagl.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToOrg_Dagl"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl_InclA2.bru new file mode 100644 index 00000000..ae92d76b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_Dagl_InclA2.bru @@ -0,0 +1,83 @@ +meta { + name: InstDelgParties_AsResOwner_ToOrg_Dagl_InclA2 + type: http + seq: 8 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.organizations.legitimJusterbarTiger.dagl.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToOrg_Dagl_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_InclA2.bru new file mode 100644 index 00000000..ab979096 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToOrg_InclA2.bru @@ -0,0 +1,83 @@ +meta { + name: InstDelgParties_AsResOwner_ToOrg_InclA2 + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:organization:identifier-no", + "value": "{{toOrganizationId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toOrganizationId", testdata.organizations.legitimJusterbarTiger.organizationNumber); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToOrg_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_O2O_MainUnitDelegatedFrom", function() { + const instanceId = testdata.instances.o2o.instanceId; + const mainUnit = body.find(party => party.partyUuid === testdata.instances.o2o.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.mobilBeskjedenTiger.organizationNumber} to have Subunit ${testdata.organizations.mobilBeskjedenTiger.subunits.mobilBeskjedenTiger.organizationNumber}. Maybe this bug has been fixed: https://github.com/Altinn/altinn-access-management/issues/873 ? If so update this test to not expect to find subunit.`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_P2O_PersonDelegatedFrom", function() { + const instanceId_1 = testdata.instances.p2o.instanceId_1; + const instanceId_2 = testdata.instances.p2o.instanceId_2; + const person = body.find(party => party.partyUuid === testdata.instances.p2o.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation_1 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_1); + assert.isOk(personDelegation_1, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + + const personDelegation_2 = person.authorizedInstances.find(delegation => delegation.instanceId === instanceId_2); + assert.isOk(personDelegation_2, `InstanceId ${instanceId_1} not found in AuthorizedInstances on Person having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson.bru new file mode 100644 index 00000000..360ed071 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson.bru @@ -0,0 +1,86 @@ +meta { + name: InstDelgParties_AsResOwner_ToPerson + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.persons.hakkeDyr.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToPerson"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_InclA2.bru new file mode 100644 index 00000000..877d50a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_InclA2.bru @@ -0,0 +1,86 @@ +meta { + name: InstDelgParties_AsResOwner_ToPerson_InclA2 + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.persons.hakkeDyr.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToPerson_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_P2P_PersonDelegatedFrom", function() { + const person = body.find(party => party.partyUuid === testdata.instances.p2p.from); + assert.isOk(person, `Person having delegated instance access was not found in AuthorizedParties for recipient`); + + const personDelegation = person.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.p2p.instanceId); + assert.isOk(personDelegation, `InstanceId ${testdata.instances.p2p.instanceId} not found in AuthorizedInstances on Person having delegated the instance`); + }); + + test(requestName + "|Contains_Main2P_MainUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.partyUuid === testdata.instances.main2p.from); + assert.isOk(mainUnit, `MainUnit having delegated instance access was not found in AuthorizedParties for recipient`); + + const mainUnitDelegation = mainUnit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isOk(mainUnitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} not found in AuthorizedInstances on MainUnit having delegated the instance`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.partyUuid); + assert.isOk(subunit, `Expected MainUnit ${testdata.organizations.legitimJusterbarTiger.organizationNumber} to have Subunit ${testdata.organizations.legitimJusterbarTiger.subunits.legitimJusterbarTiger.organizationNumber}`); + + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.main2p.instanceId); + assert.isNotOk(subunitDelegation, `InstanceId ${testdata.instances.main2p.instanceId} should not be found in AuthorizedInstances on Subunit`); + }); + + test(requestName + "|Contains_Sub2P_SubUnitDelegatedFrom", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.sub2p.from); + const subunitDelegation = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.sub2p.instanceId); + assert.isOk(subunitDelegation, `InstanceId ${testdata.instances.sub2p.instanceId} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly.bru new file mode 100644 index 00000000..f81ca2c0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly.bru @@ -0,0 +1,69 @@ +meta { + name: InstDelgParties_AsResOwner_ToPerson_SubOnly + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=false + body: json + auth: inherit +} + +params:query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.persons.spesifikkSmaragd.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToPerson_SubOnly"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly_InclA2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly_InclA2.bru new file mode 100644 index 00000000..06a44152 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/AuthorizedParties/AsResourceOwner/InstDelgParties_AsResOwner_ToPerson_SubOnly_InclA2.bru @@ -0,0 +1,69 @@ +meta { + name: InstDelgParties_AsResOwner_ToPerson_SubOnly_InclA2 + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: inherit +} + +params:query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "{{toPersonId}}" + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + + var getTokenParameters = { + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_orgNo: sharedtestdata.serviceOwners.ttd.orgno, + auth_scopes: sharedtestdata.auth_scopes.authorizedPartiesResourceOwner + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("bearerToken", token); + + bru.setVar("toPersonId", testdata.persons.spesifikkSmaragd.personId); +} + +tests { + // Should be the same as the .bru request file. Used as prefix in test name which also shows in test result in pipeline. + const requestName = "InstDelgParties_AsResOwner_ToPerson_SubOnly_InclA2"; + const testdata = require(`./Testdata/instance-delegation-authorized-parties/${bru.getEnvVar("tokenEnv")}.json`); + const body = res.getBody(); + + test(requestName + "|HttpStatus.OK", function() { + expect(res.status).to.equal(200); + }); + + test(requestName + "|Contains_SubOnly2P_MainUnitOnlyHierarchy_SubunitWithInstanceIds", function() { + const mainUnit = body.find(party => party.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from)); + assert.isOk(mainUnit, `Subunit was not found as a subunit on any party in AuthorizedParties for recipient`); + assert.isOk(mainUnit.onlyHierarchyElementWithNoAccess, `Expected mainUnit.onlyHierarchyElementWithNoAccess to be true. Recipient should only have Subunit access.`); + + const subunit = mainUnit.subunits.find(subunit => subunit.partyUuid === testdata.instances.subonly2p.from); + + const subunitInstanceDelegation_1 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_1); + assert.isOk(subunitInstanceDelegation_1, `InstanceId ${testdata.instances.subonly2p.instanceId_1} not found in AuthorizedInstances on Subunit having delegated the instance`); + + const subunitInstanceDelegation_2 = subunit.authorizedInstances.find(delegation => delegation.instanceId === testdata.instances.subonly2p.instanceId_2); + assert.isOk(subunitInstanceDelegation_2, `InstanceId ${testdata.instances.subonly2p.instanceId_2} not found in AuthorizedInstances on Subunit having delegated the instance`); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/1. DelegateInstanceRights.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/1. DelegateInstanceRights.bru new file mode 100644 index 00000000..0f60d6f8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/1. DelegateInstanceRights.bru @@ -0,0 +1,109 @@ +meta { + name: 1. DelegateInstanceRights + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation ReadSign", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + + expect(data.resourceId).to.equal(resource); + expect(data.instanceId).to.equal(testdata.instanceid); + + expect(data.from.value).to.equal(testdata.org1.partyuuid); + expect(data.to.value).to.equal(testdata.person1.partyuuid); + + expect(data.rights[0].status).to.equal('Delegated'); + expect(data.rights[0].action.value).to.equal('read'); + expect(data.rights[0].resource[0].value).to.equal(resource); + expect(data.rights[0].resource[1].value).to.equal('task_1'); + + expect(data.rights[1].status).to.equal('Delegated'); + expect(data.rights[1].action.value).to.equal('sign'); + expect(data.rights[1].resource[0].value).to.equal(resource); + expect(data.rights[1].resource[1].value).to.equal('task_1'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/2. GetInstanceRights.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/2. GetInstanceRights.bru new file mode 100644 index 00000000..921aa4d7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/2. GetInstanceRights.bru @@ -0,0 +1,63 @@ +meta { + name: 2. GetInstanceRights + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("get InstanceDelegation ReadSign", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.data.length).to.equal(1); + + expect(data.data[0].resourceId).to.equal(resource); + expect(data.data[0].instanceId).to.equal(testdata.instanceid); + + expect(data.data[0].from.value).to.equal(testdata.org1.partyuuid); + expect(data.data[0].to.value).to.equal(testdata.person1.partyuuid); + + expect(data.data[0].rights.length).to.equal(2); + + expect(data.data[0].rights[0].status).to.equal('Delegated'); + expect(data.data[0].rights[0].action.value).to.equal('read'); + expect(data.data[0].rights[0].resource[0].value).to.equal(resource); + expect(data.data[0].rights[0].resource[1].value).to.equal('task_1'); + + expect(data.data[0].rights[1].status).to.equal('Delegated'); + expect(data.data[0].rights[1].action.value).to.equal('sign'); + expect(data.data[0].rights[1].resource[0].value).to.equal(resource); + expect(data.data[0].rights[1].resource[1].value).to.equal('task_1'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/3. RevokeInstanceRead.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/3. RevokeInstanceRead.bru new file mode 100644 index 00000000..864a6549 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/3. RevokeInstanceRead.bru @@ -0,0 +1,86 @@ +meta { + name: 3. RevokeInstanceRead + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationrevoke/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation RevokeRead", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + + expect(data.resourceId).to.equal(resource); + expect(data.instanceId).to.equal(testdata.instanceid); + + expect(data.from.value).to.equal(testdata.org1.partyuuid); + expect(data.to.value).to.equal(testdata.person1.partyuuid); + + expect(data.rights[0].status).to.equal('Revoked'); + expect(data.rights[0].action.value).to.equal('read'); + expect(data.rights[0].resource[0].value).to.equal(resource); + expect(data.rights[0].resource[1].value).to.equal('task_1'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/4. GetInstanceRights.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/4. GetInstanceRights.bru new file mode 100644 index 00000000..ebce9fec --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/4. GetInstanceRights.bru @@ -0,0 +1,58 @@ +meta { + name: 4. GetInstanceRights + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("get InstanceDelegation Sign", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.data.length).to.equal(1); + + expect(data.data[0].resourceId).to.equal(resource); + expect(data.data[0].instanceId).to.equal(testdata.instanceid); + + expect(data.data[0].from.value).to.equal(testdata.org1.partyuuid); + expect(data.data[0].to.value).to.equal(testdata.person1.partyuuid); + + expect(data.data[0].rights.length).to.equal(1); + + expect(data.data[0].rights[0].status).to.equal('Delegated'); + expect(data.data[0].rights[0].action.value).to.equal('sign'); + expect(data.data[0].rights[0].resource[0].value).to.equal(resource); + expect(data.data[0].rights[0].resource[1].value).to.equal('task_1'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/5. RevokeInstanceSign.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/5. RevokeInstanceSign.bru new file mode 100644 index 00000000..7dec4fa7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/5. RevokeInstanceSign.bru @@ -0,0 +1,86 @@ +meta { + name: 5. RevokeInstanceSign + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationrevoke/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation RevokeSign", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + + expect(data.resourceId).to.equal(resource); + expect(data.instanceId).to.equal(testdata.instanceid); + + expect(data.from.value).to.equal(testdata.org1.partyuuid); + expect(data.to.value).to.equal(testdata.person1.partyuuid); + + expect(data.rights[0].status).to.equal('Revoked'); + expect(data.rights[0].action.value).to.equal('sign'); + expect(data.rights[0].resource[0].value).to.equal(resource); + expect(data.rights[0].resource[1].value).to.equal('task_1'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/6. GetInstanceRights.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/6. GetInstanceRights.bru new file mode 100644 index 00000000..6ee4543e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegateGetRevokeSeries/6. GetInstanceRights.bru @@ -0,0 +1,45 @@ +meta { + name: 6. GetInstanceRights + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("get InstanceDelegation EmptyResponce", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.data.length).to.equal(0); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithDelegableRights_Ok.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithDelegableRights_Ok.bru new file mode 100644 index 00000000..6f01c5c8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithDelegableRights_Ok.bru @@ -0,0 +1,55 @@ +meta { + name: AppWithDelegableRights_Ok + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationcheck/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + instanceId: {{instanceId}} + resourceId: app_{{org}}_{{app}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "authz-bruno-instancedelegation"; + bru.setVar("app", app); + + bru.setVar("instanceId", "b39a2326-9fff-4414-a209-61e6f9835564"); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation DelegationCheck GET AppWithDelegableRights_Ok", function() { + var body = res.getBody(); + var data = body.data; + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('rightKey', 'app_ttd_authz-bruno-instancedelegation,task_1:read') + expect(data[0]).to.have.property('status', 'Delegable') + expect(data[1]).to.have.property('rightKey', 'app_ttd_authz-bruno-instancedelegation,task_1:sign') + expect(data[1]).to.have.property('status', 'Delegable') + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithoutDelegableRights_BadRequest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithoutDelegableRights_BadRequest.bru new file mode 100644 index 00000000..7c2a3d98 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/AppWithoutDelegableRights_BadRequest.bru @@ -0,0 +1,52 @@ +meta { + name: AppWithoutDelegableRights_BadRequest + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationcheck/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + resourceId: app_ttd_authz-bruno-instancedelegation + instanceId: {{instanceId}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "apps-test"; + bru.setVar("app", app); + + bru.setVar("instanceId", "b39a2326-9fff-4414-a209-61e6f9835564"); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation DelegationCheck GET AppWithoutDelegableRights_Forbidden", function() { + var body = res.getBody(); + expect(res.status).to.equal(400); + expect(body.validationErrors[0].code).to.equal("AM.VLD-00004"); + expect(body.validationErrors[0].paths[0]).to.equal("appInstanceDelegationRequest.Resource"); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/MissingToken_NotAuthorized.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/MissingToken_NotAuthorized.bru new file mode 100644 index 00000000..04c6f39e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/MissingToken_NotAuthorized.bru @@ -0,0 +1,37 @@ +meta { + name: MissingToken_NotAuthorized + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationcheck/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + resourceId: app_ttd_authz-bruno-instancedelegation + instanceId: {{instanceId}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + + bru.setVar("instanceId", "b39a2326-9fff-4414-a209-61e6f9835564"); + bru.setVar("platformAccessToken", ""); +} + +tests { + test("AppsInstanceDelegation DelegationCheck GET MissingToken_NotAuthorized", function() { + var body = res.getBody(); + expect(res.status).to.equal(401); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/PlatformAccessToken_BadRequest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/PlatformAccessToken_BadRequest.bru new file mode 100644 index 00000000..3b52d93a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/DelegationCheck/PlatformAccessToken_BadRequest.bru @@ -0,0 +1,52 @@ +meta { + name: PlatformAccessToken_BadRequest + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationcheck/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + resourceId: app_ttd_authz-bruno-instancedelegation + instanceId: {{instanceId}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + + const org = "platform"; + bru.setVar("org", org); + const app = "some-random-app"; + bru.setVar("app", app); + + bru.setVar("instanceId", "b39a2326-9fff-4414-a209-61e6f9835564"); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation DelegationCheck GET PlatformAccessToken_Forbidden", function() { + var body = res.getBody(); + expect(res.status).to.equal(400); + expect(body.validationErrors[0].code).to.equal("AM.VLD-00004"); + expect(body.validationErrors[0].paths[0]).to.equal("appInstanceDelegationRequest.Resource"); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateExistingAppNoRightsDelegable.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateExistingAppNoRightsDelegable.bru new file mode 100644 index 00000000..45985887 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateExistingAppNoRightsDelegable.bru @@ -0,0 +1,99 @@ +meta { + name: DelegateExistingAppNoRightsDelegable + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + "authz-bruno-testapp1"; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: "authz-bruno-testapp1", + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation NoRights", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00004"); + expect(data.validationErrors[0].paths[0]).to.equal("appInstanceDelegationRequest.Resource"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateNonExistingResource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateNonExistingResource.bru new file mode 100644 index 00000000..cb1ec2ca --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateNonExistingResource.bru @@ -0,0 +1,99 @@ +meta { + name: DelegateNonExistingResource + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_NonExistingApp"; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation NoResource", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_NonExistingApp"; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00002"); + expect(data.validationErrors[0].paths[0]).to.equal("appInstanceDelegationRequest.Resource"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongFrom.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongFrom.bru new file mode 100644 index 00000000..096f697a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongFrom.bru @@ -0,0 +1,99 @@ +meta { + name: DelegateWrongFrom + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org2.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation NotExistFrom", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00001"); + expect(data.validationErrors[0].paths[0]).to.equal("From"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongTo.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongTo.bru new file mode 100644 index 00000000..57437365 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/DelegateWrongTo.bru @@ -0,0 +1,99 @@ +meta { + name: DelegateWrongTo + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: json + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "{{fromUuid}}" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "{{toUuid}}" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + }, + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "{{resourceId}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "sign" + } + } + ] + } +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person2.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: testdata.app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("post InstanceDelegation NotExistTo", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + testdata.app; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00001"); + expect(data.validationErrors[0].paths[0]).to.equal("To"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNoRightsToDelegate.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNoRightsToDelegate.bru new file mode 100644 index 00000000..d3567897 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNoRightsToDelegate.bru @@ -0,0 +1,52 @@ +meta { + name: GetInstanceDelegationNoRightsToDelegate + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: none + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + "authz-bruno-testapp1"; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: "authz-bruno-testapp1", + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("get InstanceDelegation NoRihts", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + "ttd/authz-bruno-testapp1"; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00004"); + expect(data.validationErrors[0].paths[0]).to.equal("request.Resource"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNonExistingResource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNonExistingResource.bru new file mode 100644 index 00000000..fb058647 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/AppsInstanceDelegation/NegativeTests/GetInstanceDelegationNonExistingResource.bru @@ -0,0 +1,52 @@ +meta { + name: GetInstanceDelegationNonExistingResource + type: http + seq: 5 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/{{resourceId}}/instance/{{instanceId}} + body: none + auth: none +} + +headers { + PlatformAccessToken: {{platformAccessToken}} +} + +script:pre-request { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_NonExistingApp"; + + bru.setVar("resourceId", resource); + bru.setVar("instanceId", testdata.instanceid); + bru.setVar("fromUuid", testdata.org1.partyuuid); + bru.setVar("toUuid", testdata.person1.partyuuid); + + var getTokenParameters = { + auth_org: sharedtestdata.serviceOwners.ttd.org, + auth_app: "authz-bruno-testapp1", + auth_tokenType: sharedtestdata.authTokenType.platformAccess + }; + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("get InstanceDelegation NoResource", function() { + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const testdata = require(`./Testdata/instance-delegation/${bru.getEnvVar("tokenEnv")}.json`); + const resource = "app_" + sharedtestdata.serviceOwners.ttd.org + "_" + "authz-bruno-testapp1"; + + const data = res.getBody(); + expect(res.status).to.equal(400); + + expect(data.status).to.equal(400); + + expect(data.validationErrors[0].code).to.equal("AM.VLD-00002"); + expect(data.validationErrors[0].paths[0]).to.equal("request.Resource"); + + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru new file mode 100644 index 00000000..4c4cfad3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru @@ -0,0 +1,62 @@ +meta { + name: digdir-am-k6-read + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/maskinporten/delegations?supplierOrg=&consumerOrg=&scope={{scope}} + body: none + auth: inherit +} + +query { + supplierOrg: {{supplierOrg}} + consumerOrg: {{consumerOrg}} + scope: {{scope}} +} + +headers { + Accept: application/json +} + +vars:pre-request { + supplierOrg: + consumerOrg: + scope: test:am/k6.read + auth_tokenType: Enterprise + auth_partyId: + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:maskinporten/delegations.admin + bearerToken: +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + bru.setVar("scope", sharedtestdata.scopes.k6Read); + + var getTokenParameters = { + auth_org: testdata.digdir.partyid, + auth_orgNo: testdata.digdir.orgno, + scope: sharedtestdata.scopes.k6Read, + auth_tokenType: sharedtestdata.authTokenType.enterprise, + auth_scopes: sharedtestdata.auth_scopes.maskinportenAdmin + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("getMaskinportenDelegations", function() { + var body = res.getBody(); + expect(res.status).to.equal(200); + expect(body[0]).to.have.property('resourceid', 'ttd-am-k6'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-forbidden.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-forbidden.bru new file mode 100644 index 00000000..4b585541 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-forbidden.bru @@ -0,0 +1,71 @@ +meta { + name: delegationcheck-forbidden + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_bruno-gar" + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + party: testdata.org2.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post MaskinportenSchema - forbidden", function() { + const data = res.getBody(); + expect(res.status).to.equal(403); + }); +} + +docs { + does a delegationcheck on as someone who does not have access +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-invalid-resource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-invalid-resource.bru new file mode 100644 index 00000000..9c8bba55 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-invalid-resource.bru @@ -0,0 +1,71 @@ +meta { + name: delegationcheck-invalid-resource + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_bruno-gar" + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post MaskinportenSchema - invalid resource", function() { + const data = res.getBody(); + expect(res.status).to.equal(400); + }); +} + +docs { + does a delegationcheck on a generic resource and gets an error message saying that only MaskinportenSchema resources are supported. +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-delegable-for-dagl.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-delegable-for-dagl.bru new file mode 100644 index 00000000..9a711978 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-delegable-for-dagl.bru @@ -0,0 +1,73 @@ +meta { + name: delegationcheck-is-delegable-for-dagl + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post maskinportenschema delegationcheck - status is delegable", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'Delegable'); + }); +} + +docs { + does a delegationcheck on a valid resource as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-notdelegable-for-dagl.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-notdelegable-for-dagl.bru new file mode 100644 index 00000000..c6dbc60f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/delegationcheck/delegationcheck-is-notdelegable-for-dagl.bru @@ -0,0 +1,73 @@ +meta { + name: delegationcheck-is-notdelegable-for-dagl + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6-nuf" + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post maskinportenschema delegationcheck - status is notdelegable", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'NotDelegable'); + }); +} + +docs { + does a delegationcheck on a valid resource as apiadm, and status is "NotDelegable" +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaOfferedTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaOfferedTest.bru new file mode 100644 index 00000000..75ecdafa --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaOfferedTest.bru @@ -0,0 +1,71 @@ +meta { + name: getMaskinPortenSchemaOfferedTest + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid) + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + to_partyid: testdata.org2.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Offered", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('offeredByPartyId', testdata.org1.partyid); + expect(data[0]).to.have.property('offeredByName', 'ALDRA OG FORTUN'); + expect(data[0]).to.have.property('coveredByPartyId', testdata.org2.partyid); + expect(data[0]).to.have.property('coveredByName', 'LARKOLLEN OG FAUSKE'); + expect(data[0]).to.have.property('coveredByOrganizationNumber', testdata.org2.orgno); + expect(data[0]).to.have.property('performedByUserId', testdata.org1.dagl.userid); + expect(data.map(e=>(e.resourceId))).to.include('ttd-am-k6-nuf'); + + }); +} + +docs { + Check that list of offered maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaReceivedTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaReceivedTest.bru new file mode 100644 index 00000000..055aa4de --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinPortenSchemaReceivedTest.bru @@ -0,0 +1,72 @@ +meta { + name: getMaskinPortenSchemaReceivedTest + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/received + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("auth_userId", testdata.org2.dagl.userid); + bru.setVar("party", testdata.org2.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + party: testdata.org2.partyid, + to_partyid: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Received", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); 5 + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('offeredByPartyId', testdata.org1.partyid); + expect(data[0]).to.have.property('offeredByName', 'ALDRA OG FORTUN'); + expect(data[0]).to.have.property('coveredByPartyId', testdata.org2.partyid); + expect(data[0]).to.have.property('coveredByName', 'LARKOLLEN OG FAUSKE'); + expect(data[0]).to.have.property('coveredByOrganizationNumber', testdata.org2.orgno); + expect(data[0]).to.have.property('performedByUserId', testdata.org1.dagl.userid); + expect(data.map(e=>(e.resourceId))).to.include('ttd-am-k6-nuf'); + + }); +} + +docs { + Check that list of received maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaOffered-empty-response-body.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaOffered-empty-response-body.bru new file mode 100644 index 00000000..63af520e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaOffered-empty-response-body.bru @@ -0,0 +1,62 @@ +meta { + name: getMaskinportenSchemaOffered-empty-response-body + type: http + seq: 8 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid) + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Offered - empty response body", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); +} + +docs { + Check that list of offered maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-empty-response-body.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-empty-response-body.bru new file mode 100644 index 00000000..257817c7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-empty-response-body.bru @@ -0,0 +1,62 @@ +meta { + name: getMaskinportenSchemaReceived-empty-response-body + type: http + seq: 9 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/received + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid) + + var getTokenParameters = { + auth_userId: testdata.org3.dagl.userid, + auth_partyId: testdata.org3.dagl.partyid, + auth_ssn: testdata.org3.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Received - empty response body", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); +} + +docs { + Check that list of offered maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-scope.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-scope.bru new file mode 100644 index 00000000..590cdcae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-scope.bru @@ -0,0 +1,62 @@ +meta { + name: getMaskinportenSchemaReceived-invalid-scope + type: http + seq: 11 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/received + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid) + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Received - invalid scope", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(403); + expect(data).to.be.empty; + });5 +} + +docs { + Check that list of offered maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-token.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-token.bru new file mode 100644 index 00000000..e28f4394 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/getMaskinportenSchemaReceived-invalid-token.bru @@ -0,0 +1,62 @@ +meta { + name: getMaskinportenSchemaReceived-invalid-token + type: http + seq: 10 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/received + body: none + auth: inherit +} + +headers { + Accept: application/json +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: +} + +assert { + ~res.status: eq 200 + ~res.body: contains created +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid) + + var getTokenParameters = { + auth_userId: testdata.org3.dagl.userid, + auth_partyId: testdata.org3.dagl.partyid, + auth_ssn: testdata.org3.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + + test("get MaskinPortenSchema Received - invalid token", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(403); + expect(data).to.be.empty; + });5 +} + +docs { + Check that list of offered maschinportenschemas is correct +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenDAGLCannotDelegateNUFResource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenDAGLCannotDelegateNUFResource.bru new file mode 100644 index 00000000..d625265f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenDAGLCannotDelegateNUFResource.bru @@ -0,0 +1,85 @@ +meta { + name: postMaskinportenDAGLCannotDelegateNUFResource + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{to_partyid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6-nuf" + } + ] + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_partyid: +} + +assert { + ~res.status: eq 400 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_partyid", testdata.org2.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + to_partyid: testdata.org2.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post Maskinporten DAGL Cannot Delegate NUF Resource", function() { + const data = res.getBody(); + expect(res.status).to.equal(400); + expect(data).to.have.property('title', 'One or more validation errors occurred.'); + expect(data.errors['right[0].Resource']).to.include('Authenticated user does not have any delegable rights for the resource: ttd-am-k6-nuf'); + }); +} + +docs { + try and fail to delegate maskinportenschema to a person +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberSelfTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberSelfTest.bru new file mode 100644 index 00000000..74b00840 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberSelfTest.bru @@ -0,0 +1,85 @@ +meta { + name: postMaskinportenSchemaToOrgNumberSelfTest + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 400 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_orgno", testdata.org1.orgno); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post Maskinporten Schema To Self", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(400); + expect(data).to.have.property('status', 400); + expect(data.errors.To[0]).to.include('Maskinporten schema delegation can not have the same party in the From and To Attributes:'); + }); +} + +docs { + offer a maskinportenschema using same partyid in from and to +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberTest.bru new file mode 100644 index 00000000..b7dc4d7e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToOrgNumberTest.bru @@ -0,0 +1,90 @@ +meta { + name: postMaskinportenSchemaToOrgNumberTest + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_orgno: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post MaskinportenSchema To OrgNumber", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(201); + expect(data.to[0]).to.have.property('id', 'urn:altinn:organizationnumber'); + expect(data.to[0]).to.have.property('value', testdata.org2.orgno); + expect(data.rightDelegationResults[0]).to.have.property('rightKey', 'ttd-am-k6:ScopeAccess'); + expect(data.rightDelegationResults[0].resource[0]).to.have.property('id', 'urn:altinn:resource'); + expect(data.rightDelegationResults[0].resource[0]).to.have.property('value', 'ttd-am-k6'); + expect(data.rightDelegationResults[0]).to.have.property('action', 'ScopeAccess'); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); +} + +docs { + offer a maskinportenschema using an organization number +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdSelfTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdSelfTest.bru new file mode 100644 index 00000000..b6caaec6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdSelfTest.bru @@ -0,0 +1,85 @@ +meta { + name: postMaskinportenSchemaToPartyIdSelfTest + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{to_partyid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_partyid: +} + +assert { + ~res.status: eq 400 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_partyid", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + party: testdata.org1.partyid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post Maskinporten Schema To Self", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(400); + expect(data).to.have.property('status', 400); + expect(data.errors.To[0]).to.include('Maskinporten schema delegation can not have the same party in the From and To Attributes:'); + }); +} + +docs { + offer a maskinportenschema using same partyid in from and to +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdTest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdTest.bru new file mode 100644 index 00000000..6158b4fe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/Maskinportenschema/postMaskinportenSchemaToPartyIdTest.bru @@ -0,0 +1,89 @@ +meta { + name: postMaskinportenSchemaToPartyIdTest + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: inherit +} + +headers { + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{to_partyid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "ttd-am-k6" + } + ] + } + ] + } +} + +vars:pre-request { + scope: altinn:instances.read + auth_tokenType: Personal + auth_userId: + auth_scopes: altinn:instances.read + auth_partyId: + auth_ssn: + party: 50067258 + to_partyid: +} + +assert { + ~res.status: eq 201 +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_partyid", testdata.org2.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("post Maskinporten Schema To PartyId", function() { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(201); + expect(data.to[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data.to[0]).to.have.property('value', testdata.org2.partyid.toString()); + expect(data.rightDelegationResults[0]).to.have.property('rightKey', 'ttd-am-k6:ScopeAccess'); + expect(data.rightDelegationResults[0].resource[0]).to.have.property('id', 'urn:altinn:resource'); + expect(data.rightDelegationResults[0].resource[0]).to.have.property('value', 'ttd-am-k6'); + expect(data.rightDelegationResults[0]).to.have.property('action', 'ScopeAccess'); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); +} + +docs { + offer a maskinportenschema using an organization's party id +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-app.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-app.bru new file mode 100644 index 00000000..8055b2be --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-app.bru @@ -0,0 +1,72 @@ +meta { + name: delegationcheck-dagl-can-delegate-app + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: inherit +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 200 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org3.dagl.userid, + auth_partyId: testdata.org3.dagl.partyid, + auth_ssn: testdata.org3.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("delegationcheck - dagl gets status is delegable for altinn app", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'Delegable'); + }); +} + +docs { + does a delegationcheck on a valid altinn app as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-resource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-resource.bru new file mode 100644 index 00000000..47c3e8bd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-dagl-can-delegate-resource.bru @@ -0,0 +1,68 @@ +meta { + name: delegationcheck-dagl-can-delegate-resource + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: inherit +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resource}}" + } + ] + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 200 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("resource", testdata.resource); + + var getTokenParameters = { + auth_userId: testdata.org3.dagl.userid, + auth_partyId: testdata.org3.dagl.partyid, + auth_ssn: testdata.org3.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("delegationcheck - dagl gets status is delegable for generic resource", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'Delegable'); + }); +} + +docs { + does a delegationcheck on a valid generic resource as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-app.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-app.bru new file mode 100644 index 00000000..3c45c794 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-app.bru @@ -0,0 +1,72 @@ +meta { + name: delegationcheck-tilg-can-delegate-app + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: inherit +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 200 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("delegationcheck - tilg gets status is delegable for altinn app", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'Delegable'); + }); +} + +docs { + does a delegationcheck on a valid altinn app as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-resource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-resource.bru new file mode 100644 index 00000000..a62bb526 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-can-delegate-resource.bru @@ -0,0 +1,68 @@ +meta { + name: delegationcheck-tilg-can-delegate-resource + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: inherit +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resource}}" + } + ] + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 200 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("delegationcheck - tilg gets status is delegable for generic resource", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'Delegable'); + }); +} + +docs { + does a delegationcheck on a valid altinn app as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-cannot-delegate-app.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-cannot-delegate-app.bru new file mode 100644 index 00000000..a375e348 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/delegationcheck/delegationcheck-tilg-cannot-delegate-app.bru @@ -0,0 +1,72 @@ +meta { + name: delegationcheck-tilg-cannot-delegate-app + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: inherit +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "spraak-test" + } + ] + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 200 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("delegationcheck - tilg gets status is notdelegable for altinn app", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0]).to.have.property('status', 'NotDelegable'); + }); +} + +docs { + does a delegationcheck on a valid altinn app as dagl +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see offered delegations.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see offered delegations.bru new file mode 100644 index 00000000..287dbc58 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see offered delegations.bru @@ -0,0 +1,46 @@ +meta { + name: non-tilgangsstyrer cannot see offered delegations + type: http + seq: 41 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.meda.userid, + auth_partyId: testdata.org1.meda.partyid, + auth_ssn: testdata.org1.meda.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("non-tilgangsstyrer cannot see offered delegations", function() { + const data = res.getBody(); + expect(res.status).to.equal(403); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see received delegations.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see received delegations.bru new file mode 100644 index 00000000..744e8b71 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/non-tilgangsstyrer cannot see received delegations.bru @@ -0,0 +1,46 @@ +meta { + name: non-tilgangsstyrer cannot see received delegations + type: http + seq: 42 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org1.meda.userid, + auth_partyId: testdata.org1.meda.partyid, + auth_ssn: testdata.org1.meda.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("non-tilgangsstyrer cannot see offered delegations", function() { + const data = res.getBody(); + expect(res.status).to.equal(403); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o cannot delegate to itself.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o cannot delegate to itself.bru new file mode 100644 index 00000000..f7aabdd9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o cannot delegate to itself.bru @@ -0,0 +1,46 @@ +meta { + name: o2o cannot delegate to itself + type: http + seq: 36 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("no new delegations appear when an org attempts to delegate to itself", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org (again).bru new file mode 100644 index 00000000..f26d71cb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org (again).bru @@ -0,0 +1,84 @@ +meta { + name: o2o delegate org2org (again) + type: http + seq: 25 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to organization delegation (again)", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org.bru new file mode 100644 index 00000000..a9b1a3a4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o delegate org2org.bru @@ -0,0 +1,84 @@ +meta { + name: o2o delegate org2org + type: http + seq: 21 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to organization delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org attempts to delegate to itself.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org attempts to delegate to itself.bru new file mode 100644 index 00000000..85f9faff --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org attempts to delegate to itself.bru @@ -0,0 +1,70 @@ +meta { + name: o2o org attempts to delegate to itself + type: http + seq: 35 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + fromPartyId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org2.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org2org delegation successful.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org2org delegation successful.bru new file mode 100644 index 00000000..9b369de5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o org2org delegation successful.bru @@ -0,0 +1,53 @@ +meta { + name: o2o org2org delegation successful + type: http + seq: 22 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization successfully delegated to an organization", function() { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].from[0]).to.have.property('value', testdata.org1.partyid.toString()); + expect(data[0].to[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].to[0]).to.have.property('value', testdata.org2.partyid.toString()); + expect(data[0].resource[0]).to.have.property('id', 'urn:altinn:org'); + expect(data[0].resource[0]).to.have.property('value', bru.getVar('org')); + expect(data[0].resource[1]).to.have.property('id', 'urn:altinn:app'); + expect(data[0].resource[1]).to.have.property('value', bru.getVar('app')); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation (again).bru new file mode 100644 index 00000000..b05e7d21 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation (again).bru @@ -0,0 +1,46 @@ +meta { + name: o2o receiving org no longer has delegation (again) + type: http + seq: 27 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the offering organization successfully revoked delegation to organization", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation.bru new file mode 100644 index 00000000..cc07c80f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org no longer has delegation.bru @@ -0,0 +1,46 @@ +meta { + name: o2o receiving org no longer has delegation + type: http + seq: 24 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the receiving organization successfully revoked delegation from organization", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org revokes delegation from org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org revokes delegation from org.bru new file mode 100644 index 00000000..d357595e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o receiving org revokes delegation from org.bru @@ -0,0 +1,70 @@ +meta { + name: o2o receiving org revokes delegation from org + type: http + seq: 23 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + fromPartyId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org1.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o sending org revokes delegation to org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o sending org revokes delegation to org.bru new file mode 100644 index 00000000..57292d14 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o sending org revokes delegation to org.bru @@ -0,0 +1,70 @@ +meta { + name: o2o sending org revokes delegation to org + type: http + seq: 26 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: inherit +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{to_partyid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + toUserId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_partyid", testdata.org2.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o testdata cleanup (revoke delegation).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o testdata cleanup (revoke delegation).bru new file mode 100644 index 00000000..50ceaeac --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2o testdata cleanup (revoke delegation).bru @@ -0,0 +1,74 @@ +meta { + name: o2o testdata cleanup (revoke delegation) + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org1.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person (again).bru new file mode 100644 index 00000000..9474f376 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person (again).bru @@ -0,0 +1,89 @@ +meta { + name: o2p delegate org2person (again) + type: http + seq: 18 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to person delegation (again)", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person.bru new file mode 100644 index 00000000..bb2ad0a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p delegate org2person.bru @@ -0,0 +1,89 @@ +meta { + name: o2p delegate org2person + type: http + seq: 14 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to person delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p org2person delegation successful.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p org2person delegation successful.bru new file mode 100644 index 00000000..b4e5c4ff --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p org2person delegation successful.bru @@ -0,0 +1,53 @@ +meta { + name: o2p org2person delegation successful + type: http + seq: 15 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization successfully delegated to a person", function() { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].from[0]).to.have.property('value', testdata.org1.partyid.toString()); + expect(data[0].to[0]).to.have.property('id', 'urn:altinn:userid'); + expect(data[0].to[0]).to.have.property('value', testdata.org2.dagl.userid.toString()); + expect(data[0].resource[0]).to.have.property('id', 'urn:altinn:org'); + expect(data[0].resource[0]).to.have.property('value', testdata.org); + expect(data[0].resource[1]).to.have.property('id', 'urn:altinn:app'); + expect(data[0].resource[1]).to.have.property('value', testdata.app); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person has no delegation (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person has no delegation (again).bru new file mode 100644 index 00000000..c6bd9665 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person has no delegation (again).bru @@ -0,0 +1,46 @@ +meta { + name: o2p receiving person has no delegation (again) + type: http + seq: 20 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the offering organization successfully revoked delegation to person", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person no longer has delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person no longer has delegation.bru new file mode 100644 index 00000000..ccce97d7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person no longer has delegation.bru @@ -0,0 +1,46 @@ +meta { + name: o2p receiving person no longer has delegation + type: http + seq: 17 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the receiving person successfully revoked delegation from organization", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person revokes delegation from org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person revokes delegation from org.bru new file mode 100644 index 00000000..15982be0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p receiving person revokes delegation from org.bru @@ -0,0 +1,68 @@ +meta { + name: o2p receiving person revokes delegation from org + type: http + seq: 16 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + fromPartyId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + bru.setVar("fromPartyId", testdata.org1.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p sending org revokes delegation to person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p sending org revokes delegation to person.bru new file mode 100644 index 00000000..4d823b73 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p sending org revokes delegation to person.bru @@ -0,0 +1,70 @@ +meta { + name: o2p sending org revokes delegation to person + type: http + seq: 19 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: inherit +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:userid", + "value": "{{to_userid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + toUserId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_userid", testdata.org2.dagl.userid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p testdata cleanup (revoke delegation).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p testdata cleanup (revoke delegation).bru new file mode 100644 index 00000000..1e4f4c08 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/o2p testdata cleanup (revoke delegation).bru @@ -0,0 +1,74 @@ +meta { + name: o2p testdata cleanup (revoke delegation) + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org1.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org (again).bru new file mode 100644 index 00000000..7c1a24e9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org (again).bru @@ -0,0 +1,84 @@ +meta { + name: p2o delegate person2org (again) + type: http + seq: 32 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to organization delegation (again)", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org.bru new file mode 100644 index 00000000..c5e4f6e0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o delegate person2org.bru @@ -0,0 +1,84 @@ +meta { + name: p2o delegate person2org + type: http + seq: 28 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to organization delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o person2org delegation successful.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o person2org delegation successful.bru new file mode 100644 index 00000000..e95bde67 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o person2org delegation successful.bru @@ -0,0 +1,53 @@ +meta { + name: p2o person2org delegation successful + type: http + seq: 29 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person successfully delegated to an organization", function() { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].from[0]).to.have.property('value', testdata.org1.dagl.partyid.toString()); + expect(data[0].to[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].to[0]).to.have.property('value', testdata.org2.partyid.toString()); + expect(data[0].resource[0]).to.have.property('id', 'urn:altinn:org'); + expect(data[0].resource[0]).to.have.property('value', bru.getVar('org')); + expect(data[0].resource[1]).to.have.property('id', 'urn:altinn:app'); + expect(data[0].resource[1]).to.have.property('value', bru.getVar('app')); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation (again).bru new file mode 100644 index 00000000..1cbf0a53 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation (again).bru @@ -0,0 +1,46 @@ +meta { + name: p2o receiving org no longer has delegation (again) + type: http + seq: 34 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the sending person successfully revoked delegation from organization", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation.bru new file mode 100644 index 00000000..8f0edd2d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org no longer has delegation.bru @@ -0,0 +1,46 @@ +meta { + name: p2o receiving org no longer has delegation + type: http + seq: 31 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the receiving org successfully revoked delegation from person", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org revokes delegation from person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org revokes delegation from person.bru new file mode 100644 index 00000000..05b9f660 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o receiving org revokes delegation from person.bru @@ -0,0 +1,70 @@ +meta { + name: p2o receiving org revokes delegation from person + type: http + seq: 30 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + fromPartyId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org1.dagl.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o sending person revokes delegation to org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o sending person revokes delegation to org.bru new file mode 100644 index 00000000..2c2b2ce5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o sending person revokes delegation to org.bru @@ -0,0 +1,70 @@ +meta { + name: p2o sending person revokes delegation to org + type: http + seq: 33 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: inherit +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{to_partyid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + toUserId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("to_partyid", testdata.org2.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o testdata cleanup (revoke delegation).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o testdata cleanup (revoke delegation).bru new file mode 100644 index 00000000..a08799ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2o testdata cleanup (revoke delegation).bru @@ -0,0 +1,74 @@ +meta { + name: p2o testdata cleanup (revoke delegation) + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.partyid); + bru.setVar("fromPartyId", testdata.org1.dagl.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person (again).bru new file mode 100644 index 00000000..21e62609 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person (again).bru @@ -0,0 +1,89 @@ +meta { + name: p2p delegate person2person (again) + type: http + seq: 11 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: + app: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to person delegation (again)", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person.bru new file mode 100644 index 00000000..c0930c28 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegate person2person.bru @@ -0,0 +1,88 @@ +meta { + name: p2p delegate person2person + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to person delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegation successful.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegation successful.bru new file mode 100644 index 00000000..14c95b01 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p delegation successful.bru @@ -0,0 +1,53 @@ +meta { + name: p2p delegation successful + type: http + seq: 8 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person successfully delegated to a person", function() { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[0].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].from[0]).to.have.property('value', testdata.org1.dagl.partyid.toString()); + expect(data[0].to[0]).to.have.property('id', 'urn:altinn:userid'); + expect(data[0].to[0]).to.have.property('value', testdata.org2.dagl.userid.toString()); + expect(data[0].resource[0]).to.have.property('id', 'urn:altinn:org'); + expect(data[0].resource[0]).to.have.property('value', bru.getVar('org')); + expect(data[0].resource[1]).to.have.property('id', 'urn:altinn:app'); + expect(data[0].resource[1]).to.have.property('value', bru.getVar('app')); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person has no delegation (again).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person has no delegation (again).bru new file mode 100644 index 00000000..41f0fd09 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person has no delegation (again).bru @@ -0,0 +1,46 @@ +meta { + name: p2p receiving person has no delegation (again) + type: http + seq: 13 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("the offering person successfully revoked delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person no longer has delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person no longer has delegation.bru new file mode 100644 index 00000000..8336f7e8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person no longer has delegation.bru @@ -0,0 +1,46 @@ +meta { + name: p2p receiving person no longer has delegation + type: http + seq: 10 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("receiving person successfully revoked delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data).to.be.empty; + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person revokes delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person revokes delegation.bru new file mode 100644 index 00000000..242be0bc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p receiving person revokes delegation.bru @@ -0,0 +1,70 @@ +meta { + name: p2p receiving person revokes delegation + type: http + seq: 9 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + fromPartyId: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + bru.setVar("fromPartyId", testdata.org1.dagl.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p testdata cleanup (revoke delegation).bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p testdata cleanup (revoke delegation).bru new file mode 100644 index 00000000..a49d04df --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p testdata cleanup (revoke delegation).bru @@ -0,0 +1,74 @@ +meta { + name: p2p testdata cleanup (revoke delegation) + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org2.dagl.partyid); + bru.setVar("fromPartyId", testdata.org1.dagl.partyid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org2.dagl.userid, + auth_partyId: testdata.org2.dagl.partyid, + auth_ssn: testdata.org2.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p the offering person revokes delegation.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p the offering person revokes delegation.bru new file mode 100644 index 00000000..988fc9b1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/p2p the offering person revokes delegation.bru @@ -0,0 +1,71 @@ +meta { + name: p2p the offering person revokes delegation + type: http + seq: 12 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: inherit +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:userid", + "value": "{{toUserId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: + app: + toLastName: + toSsn: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("toUserId", testdata.org2.dagl.userid); + bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg app testdata cleanup.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg app testdata cleanup.bru new file mode 100644 index 00000000..e303d299 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg app testdata cleanup.bru @@ -0,0 +1,72 @@ +meta { + name: tilg app testdata cleanup + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test-tba" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.randomUser.partyid); + bru.setVar("fromPartyId", testdata.org3.partyid); + + var getTokenParameters = { + auth_userId: testdata.randomUser.userid, + auth_partyId: testdata.randomUser.partyid, + auth_ssn: testdata.randomUser.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate altinn app they have access to.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate altinn app they have access to.bru new file mode 100644 index 00000000..c53fc807 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate altinn app they have access to.bru @@ -0,0 +1,87 @@ +meta { + name: tilg can delegate altinn app they have access to + type: http + seq: 37 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test-tba + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("toSsn", testdata.randomUser.pid); + bru.setVar("toLastName", testdata.randomUser.lastname); + //bru.setVar("org", testdata.org); + bru.setVar("app", testdata.app); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + auth_tokenType: sharedtestdata.authTokenType.personal, + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("tilgangsstyrer can delegate app they have access to", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate resource they have access to.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate resource they have access to.bru new file mode 100644 index 00000000..325fefa3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg can delegate resource they have access to.bru @@ -0,0 +1,83 @@ +meta { + name: tilg can delegate resource they have access to + type: http + seq: 38 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_bruno-gar" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test-tba + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("toSsn", testdata.randomUser.pid); + bru.setVar("toLastName", testdata.randomUser.lastname); + //bru.setVar("org", testdata.org); + bru.setVar("app", "apps-test-tba"); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + auth_tokenType: sharedtestdata.authTokenType.personal, + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("tilgangsstyrer can delegate app they have access to", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg cannot delegate app they don't have access to.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg cannot delegate app they don't have access to.bru new file mode 100644 index 00000000..5afa2f38 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg cannot delegate app they don't have access to.bru @@ -0,0 +1,86 @@ +meta { + name: tilg cannot delegate app they don't have access to + type: http + seq: 39 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "spraak-test" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: spraak-test + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org3.partyid); + bru.setVar("toSsn", testdata.randomUser.pid); + bru.setVar("toLastName", testdata.randomUser.lastname); + + var getTokenParameters = { + auth_userId: testdata.org3.tilg.userid, + auth_partyId: testdata.org3.tilg.partyid, + auth_ssn: testdata.org3.tilg.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person can't delegate app they don't have access to", function() { + const data = res.getBody(); + expect(res.status).to.equal(400); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg resource testdata cleanup.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg resource testdata cleanup.bru new file mode 100644 index 00000000..0c74a85b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg resource testdata cleanup.bru @@ -0,0 +1,68 @@ +meta { + name: tilg resource testdata cleanup + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: inherit +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_bruno-gar" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: + org: ttd + app: apps-test-prod + fromPartyId: +} + +assert { + res.status: eq 204 +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.randomUser.partyid); + bru.setVar("fromPartyId", testdata.org3.partyid); + + var getTokenParameters = { + auth_userId: testdata.randomUser.userid, + auth_partyId: testdata.randomUser.partyid, + auth_ssn: testdata.randomUser.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg successfully delegated app and resource.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg successfully delegated app and resource.bru new file mode 100644 index 00000000..4abc7d86 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal/tilg successfully delegated app and resource.bru @@ -0,0 +1,59 @@ +meta { + name: tilg successfully delegated app and resource + type: http + seq: 40 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: inherit +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.randomUser.partyid); + + var getTokenParameters = { + auth_userId: testdata.randomUser.userid, + auth_partyId: testdata.randomUser.partyid, + auth_ssn: testdata.randomUser.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person successfully delegated to a person", function() { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data[1].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[1].from[0]).to.have.property('value', testdata.org3.partyid.toString()); + expect(data[1].to[0]).to.have.property('id', 'urn:altinn:userid'); + expect(data[1].to[0]).to.have.property('value', testdata.randomUser.userid.toString()); + expect(data[1].resource[0]).to.have.property('id', 'urn:altinn:org'); + expect(data[1].resource[0]).to.have.property('value', 'ttd'); + expect(data[1].resource[1]).to.have.property('id', 'urn:altinn:app'); + expect(data[1].resource[1]).to.have.property('value', testdata.app); + expect(data[0].from[0]).to.have.property('id', 'urn:altinn:partyid'); + expect(data[0].from[0]).to.have.property('value', testdata.org3.partyid.toString()); + expect(data[0].to[0]).to.have.property('id', 'urn:altinn:userid'); + expect(data[0].to[0]).to.have.property('value', testdata.randomUser.userid.toString()); + expect(data[0].resource[0]).to.have.property('id', 'urn:altinn:resource'); + expect(data[0].resource[0]).to.have.property('value', 'devtest_gar_bruno-gar'); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2o delegate org2org A2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2o delegate org2org A2.bru new file mode 100644 index 00000000..24759d82 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2o delegate org2org A2.bru @@ -0,0 +1,84 @@ +meta { + name: o2o delegate org2org A2 + type: http + seq: 15 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "{{servicecode}}" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "{{serviceeditioncode}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("servicecode", testdata.servicecode); + bru.setVar("serviceeditioncode", testdata.serviceeditioncode); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to organization Altinn2 delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2p delegate org2person A2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2p delegate org2person A2.bru new file mode 100644 index 00000000..2316d700 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/o2p delegate org2person A2.bru @@ -0,0 +1,89 @@ +meta { + name: o2p delegate org2person A2 + type: http + seq: 8 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "{{servicecode}}" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "{{serviceeditioncode}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("servicecode", testdata.servicecode); + bru.setVar("serviceeditioncode", testdata.serviceeditioncode); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("organization to person Altinn2 delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2o delegate person2org A2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2o delegate person2org A2.bru new file mode 100644 index 00000000..5775b607 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2o delegate person2org A2.bru @@ -0,0 +1,84 @@ +meta { + name: p2o delegate person2org A2 + type: http + seq: 22 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{to_orgno}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "{{servicecode}}" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "{{serviceeditioncode}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("to_orgno", testdata.org2.orgno); + bru.setVar("servicecode", testdata.servicecode); + bru.setVar("serviceeditioncode", testdata.serviceeditioncode); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to organization Altinn2 delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2p delegate person2person A2.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2p delegate person2person A2.bru new file mode 100644 index 00000000..53ea7992 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Automatic Test Collection/RightsInternal_Altinn2/p2p delegate person2person A2.bru @@ -0,0 +1,89 @@ +meta { + name: p2p delegate person2person A2 + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: inherit +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "{{servicecode}}" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "{{serviceeditioncode}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: + toLastName: + servicecode: + serviceeditioncode: + auth_tokenType: Personal + auth_userId: + auth_partyId: + auth_ssn: + party: +} + +script:pre-request { + const testdata = require(`./Testdata/rights-delegations/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + bru.setVar("party", testdata.org1.dagl.partyid); + bru.setVar("toSsn", testdata.org2.dagl.pid); + bru.setVar("toLastName", testdata.org2.dagl.lastname); + bru.setVar("servicecode", testdata.servicecode); + bru.setVar("serviceeditioncode", testdata.serviceeditioncode); + + var getTokenParameters = { + auth_userId: testdata.org1.dagl.userid, + auth_partyId: testdata.org1.dagl.partyid, + auth_ssn: testdata.org1.dagl.pid, + scope: sharedtestdata.scopes.read, + auth_tokenType: sharedtestdata.authTokenType.personal, + auth_scopes: sharedtestdata.auth_scopes.read + } + const token = await testTokenGenerator.getToken(getTokenParameters); + + bru.setVar("bearerToken", token); +} + +tests { + test("person to person Altinn2 delegation", function() { + const data = res.getBody(); + expect(res.status).to.equal(200); + expect(data.rightDelegationResults[0]).to.have.property('status', 'Delegated'); + }); + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegateInstance.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegateInstance.bru new file mode 100644 index 00000000..67d185a8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegateInstance.bru @@ -0,0 +1,83 @@ +meta { + name: DelegateInstance + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + instanceId: {{instanceId}} + resourceId: app_{{org}}_{{app}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "ff6fbedd-95ef-4de2-aed3-e6aeb292bd50" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "c632a24e-910a-4332-a087-076bc98d600f" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_{{org}}_{{app}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] + } +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const { v4: uuidv4 } = require('uuid'); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "am-devtest-instancedelegation"; + bru.setVar("app", app); + + const uuid = uuidv4(); + bru.setVar("instanceId", uuid); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation Delegation POST {InsertRequestName}", function() { + var body = res.getBody(); + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegationCheck.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegationCheck.bru new file mode 100644 index 00000000..cf6d50bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/DelegationCheck.bru @@ -0,0 +1,52 @@ +meta { + name: DelegationCheck + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationcheck/resource/:resourceId/instance/:instanceId + body: json + auth: none +} + +params:path { + resourceId: app_{{org}}_{{app}} + instanceId: {{instanceId}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const { v4: uuidv4 } = require('uuid'); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "am-devtest-instancedelegation"; + bru.setVar("app", app); + + const uuid = uuidv4(); + bru.setVar("instanceId", uuid); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation DelegationCheck GET {InsertRequestName}", function() { + var body = res.getBody(); + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/GetInstanceDelegations.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/GetInstanceDelegations.bru new file mode 100644 index 00000000..8b3f5002 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/GetInstanceDelegations.bru @@ -0,0 +1,52 @@ +meta { + name: GetInstanceDelegations + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegations/resource/:resourceId/instance/:instanceId + body: none + auth: none +} + +params:path { + instanceId: d615bf53-dfda-44af-89c1-a2ccfbfd8db8 + resourceId: app_{{org}}_{{app}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const { v4: uuidv4 } = require('uuid'); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "am-devtest-instancedelegation"; + bru.setVar("app", app); + + const uuid = uuidv4(); + bru.setVar("instanceId", uuid); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation Delegation GET {InsertRequestName}", function() { + var body = res.getBody(); + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/RevokeInstanceDelegations.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/RevokeInstanceDelegations.bru new file mode 100644 index 00000000..9661b350 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AppsInstanceDelegation/RevokeInstanceDelegations.bru @@ -0,0 +1,83 @@ +meta { + name: RevokeInstanceDelegations + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/app/delegationrevoke/resource/:resourceId/instance/:instanceId/ + body: json + auth: none +} + +params:path { + resourceId: app_{{org}}_{{app}} + instanceId: {{instanceId}} +} + +headers { + Accept: application/json + PlatformAccessToken: {{platformAccessToken}} + ~Ocp-Apim-Subscription-Key: {{apimSubscriptionKey}} +} + +body:json { + { + "from": { + "type": "urn:altinn:party:uuid", + "value": "ff6fbedd-95ef-4de2-aed3-e6aeb292bd50" + }, + "to": { + "type": "urn:altinn:party:uuid", + "value": "c632a24e-910a-4332-a087-076bc98d600f" + }, + "rights": [ + { + "resource": [ + { + "type": "urn:altinn:resource", + "value": "app_{{org}}_{{app}}" + }, + { + "type": "urn:altinn:task", + "value": "task_1" + } + ], + "action": { + "type": "urn:oasis:names:tc:xacml:1.0:action:action-id", + "value": "read" + } + } + ] + } +} + +script:pre-request { + const testdata = require(`./Testdata/maskinportenschema/${bru.getEnvVar("tokenEnv")}testdata.json`); + const sharedtestdata = require(`./Testdata/sharedtestdata.json`); + const { v4: uuidv4 } = require('uuid'); + + const org = sharedtestdata.serviceOwners.ttd.org; + bru.setVar("org", org); + const app = "am-devtest-instancedelegation"; + bru.setVar("app", app); + + const uuid = uuidv4(); + bru.setVar("instanceId", uuid); + + var getTokenParameters = { + auth_org: org, + auth_app: app, + auth_tokenType: sharedtestdata.authTokenType.platformAccess + } + + const token = await testTokenGenerator.getToken(getTokenParameters); + bru.setVar("platformAccessToken", token); +} + +tests { + test("AppsInstanceDelegation Revoke POST {InsertRequestName}", function() { + var body = res.getBody(); + expect(res.status).to.equal(204); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSelf.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSelf.bru new file mode 100644 index 00000000..41990b7a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSelf.bru @@ -0,0 +1,38 @@ +meta { + name: KasperForSelf + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50002598 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSkrova_Forbidden.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSkrova_Forbidden.bru new file mode 100644 index 00000000..df0fbb84 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperForSkrova_Forbidden.bru @@ -0,0 +1,38 @@ +meta { + name: KasperForSkrova_Forbidden + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50076451 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 403 Forbidden", function() { + expect(res.status).to.equal(403); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperFor\303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperFor\303\230rsta.bru" new file mode 100644 index 00000000..e94b3bc6 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/KasperFor\303\230rsta.bru" @@ -0,0 +1,38 @@ +meta { + name: KasperForØrsta + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/PaulaForKasper_Forbidden.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/PaulaForKasper_Forbidden.bru new file mode 100644 index 00000000..f48245cb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/PaulaForKasper_Forbidden.bru @@ -0,0 +1,38 @@ +meta { + name: PaulaForKasper_Forbidden + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' + party: 50002598 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 403 Forbidden", function() { + expect(res.status).to.equal(403); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/UnauthenticatedForWhatever.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/UnauthenticatedForWhatever.bru new file mode 100644 index 00000000..a2b620c1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAccessManager/UnauthenticatedForWhatever.bru @@ -0,0 +1,38 @@ +meta { + name: UnauthenticatedForWhatever + type: http + seq: 5 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + party: 50002598 + ~auth_tokenType: + ~auth_userId: + ~auth_partyId: + ~auth_ssn: +} + +script:pre-request { + //await tokenGenerator.getToken(); +} + +tests { + test("Should return 401 Anauthorized", function() { + expect(res.status).to.equal(401); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Amund.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Amund.bru new file mode 100644 index 00000000..bfb21bed --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Amund.bru @@ -0,0 +1,37 @@ +meta { + name: Amund + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000071 + auth_partyId: 50002179 + auth_ssn: '01114270071' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Asle.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Asle.bru new file mode 100644 index 00000000..a650c4d2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Asle.bru @@ -0,0 +1,37 @@ +meta { + name: Asle + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: none +} + +query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper TT02.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper TT02.bru new file mode 100644 index 00000000..859e0c29 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper TT02.bru @@ -0,0 +1,37 @@ +meta { + name: Kasper TT02 + type: http + seq: 5 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 55899 + auth_partyId: 50027004 + auth_ssn: '07125602120' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper.bru new file mode 100644 index 00000000..f3a6257b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Kasper.bru @@ -0,0 +1,37 @@ +meta { + name: Kasper + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake TT02.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake TT02.bru new file mode 100644 index 00000000..39b3c2fe --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake TT02.bru @@ -0,0 +1,37 @@ +meta { + name: Ostekake TT02 + type: http + seq: 8 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: none +} + +query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 341548 + auth_partyId: 52127981 + auth_ssn: '15923648388' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake.bru new file mode 100644 index 00000000..1b33a440 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Ostekake.bru @@ -0,0 +1,37 @@ +meta { + name: Ostekake + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=false + body: json + auth: none +} + +query { + includeAltinn2: false +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20009645 + auth_partyId: 51221245 + auth_ssn: '15923648388' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Paula.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Paula.bru new file mode 100644 index 00000000..d62ad9d4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Paula.bru @@ -0,0 +1,37 @@ +meta { + name: Paula + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Prod.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Prod.bru new file mode 100644 index 00000000..0e5390e4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsAuthenticatedUser/Prod.bru @@ -0,0 +1,30 @@ +meta { + name: Prod + type: http + seq: 7 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparties?includeAltinn2=true + body: json + auth: bearer +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +auth:bearer { + token: {{ProdToken}} +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByNationalIdentity.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByNationalIdentity.bru new file mode 100644 index 00000000..88e3943f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByNationalIdentity.bru @@ -0,0 +1,44 @@ +meta { + name: KasperByNationalIdentity + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:identifier-no", + "value": "07124912037" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByPartyId.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByPartyId.bru new file mode 100644 index 00000000..210236ad --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByPartyId.bru @@ -0,0 +1,44 @@ +meta { + name: KasperByPartyId + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:partyid", + "value": "50002598" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUserId.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUserId.bru new file mode 100644 index 00000000..c13d162d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUserId.bru @@ -0,0 +1,44 @@ +meta { + name: KasperByUserId + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:userid", + "value": "20000490" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUuid.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUuid.bru new file mode 100644 index 00000000..26116580 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/KasperByUuid.bru @@ -0,0 +1,44 @@ +meta { + name: KasperByUuid + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:uuid", + "value": "ee007db6-0db4-4e55-ac21-2a888f04d846" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUsername.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUsername.bru new file mode 100644 index 00000000..23df469b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUsername.bru @@ -0,0 +1,44 @@ +meta { + name: OrstaECUserByUsername + type: http + seq: 8 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:enterpriseuser:username", + "value": "OrstaECUser" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUuid.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUuid.bru new file mode 100644 index 00000000..2a0621e0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/OrstaECUserByUuid.bru @@ -0,0 +1,44 @@ +meta { + name: OrstaECUserByUuid + type: http + seq: 9 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:enterpriseuser:uuid", + "value": "002209f9-57fc-4d7c-9a60-ef0ab8e4eb06" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByOrgNo.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByOrgNo.bru" new file mode 100644 index 00000000..e2979f25 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByOrgNo.bru" @@ -0,0 +1,44 @@ +meta { + name: ØrstaByOrgNo + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:organization:identifier-no", + "value": "910459880" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByPartyId.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByPartyId.bru" new file mode 100644 index 00000000..90bb2e36 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByPartyId.bru" @@ -0,0 +1,44 @@ +meta { + name: ØrstaByPartyId + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:partyid", + "value": "50005545" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByUuid.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByUuid.bru" new file mode 100644 index 00000000..382cf9d8 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AsServiceOwner/\303\230rstaByUuid.bru" @@ -0,0 +1,44 @@ +meta { + name: ØrstaByUuid + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/resourceowner/authorizedparties?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:organization:uuid", + "value": "ff6fbedd-95ef-4de2-aed3-e6aeb292bd50" + } +} + +vars:pre-request { + auth_tokenType: Enterprise + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:accessmanagement/authorizedparties.resourceowner +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetMain.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetMain.bru new file mode 100644 index 00000000..79bcf5b4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetMain.bru @@ -0,0 +1,38 @@ +meta { + name: KasperGetMain + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparty/{{partyId}}?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + partyId: 50076451 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSelf.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSelf.bru new file mode 100644 index 00000000..84e80eab --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSelf.bru @@ -0,0 +1,38 @@ +meta { + name: KasperGetSelf + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparty/{{partyId}}?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + partyId: 50002598 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSubunit.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSubunit.bru new file mode 100644 index 00000000..db838446 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGetSubunit.bru @@ -0,0 +1,38 @@ +meta { + name: KasperGetSubunit + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparty/{{partyId}}?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + partyId: 50074838 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGet\303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGet\303\230rsta.bru" new file mode 100644 index 00000000..a1768088 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/AuthorizedParties/AuthorizedPartyById/KasperGet\303\230rsta.bru" @@ -0,0 +1,38 @@ +meta { + name: KasperGetØrsta + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/authorizedparty/{{partyId}}?includeAltinn2=true + body: json + auth: none +} + +query { + includeAltinn2: true +} + +headers { + Content-Type: application/json + Accept: application/json +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + partyId: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Lookup/get -accessmanagement-api-v1-lookup-reportee--partyId-.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Lookup/get -accessmanagement-api-v1-lookup-reportee--partyId-.bru new file mode 100644 index 00000000..a1b7ff91 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Lookup/get -accessmanagement-api-v1-lookup-reportee--partyId-.bru @@ -0,0 +1,15 @@ +meta { + name: get -accessmanagement-api-v1-lookup-reportee--partyId- + type: http + seq: 1 +} + +get { + url: http://accessmanagement/api/v1/lookup/reportee/{partyId} + body: none + auth: none +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru new file mode 100644 index 00000000..20f76bc0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/DigDir/digdir-am-k6-read.bru @@ -0,0 +1,36 @@ +meta { + name: digdir-am-k6-read + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/maskinporten/delegations?supplierOrg={{supplierOrg}}&consumerOrg={{consumerOrg}}&scope={{scope}} + body: none + auth: none +} + +query { + supplierOrg: {{supplierOrg}} + consumerOrg: {{consumerOrg}} + scope: {{scope}} +} + +headers { + Accept: application/json +} + +vars:pre-request { + supplierOrg: + consumerOrg: + scope: test:am/k6.read + auth_tokenType: Enterprise + auth_partyId: 50088610 + auth_org: digdir + auth_orgNo: 991825827 + auth_scopes: altinn:maskinporten/delegations.admin +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-admin-delegations-maskinportenschema.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-admin-delegations-maskinportenschema.bru new file mode 100644 index 00000000..7edcbeba --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-admin-delegations-maskinportenschema.bru @@ -0,0 +1,21 @@ +meta { + name: get -accessmanagement-api-v1-admin-delegations-maskinportenschema + type: http + seq: 1 +} + +get { + url: http://accessmanagement/api/v1/admin/delegations/maskinportenschema + body: none + auth: none +} + +query { + ~supplierOrg: + ~consumerOrg: + ~scope: +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-maskinporten-delegations.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-maskinporten-delegations.bru new file mode 100644 index 00000000..a6f734d3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Maskinporten/get -accessmanagement-api-v1-maskinporten-delegations.bru @@ -0,0 +1,21 @@ +meta { + name: get -accessmanagement-api-v1-maskinporten-delegations + type: http + seq: 2 +} + +get { + url: http://accessmanagement/api/v1/maskinporten/delegations + body: none + auth: none +} + +query { + ~supplierOrg: + ~consumerOrg: + ~scope: +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Mainunit to Organization.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Mainunit to Organization.bru new file mode 100644 index 00000000..0b725022 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Mainunit to Organization.bru @@ -0,0 +1,57 @@ +meta { + name: Mainunit to Organization + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_mps_authparties-main-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Subunit to Organization.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Subunit to Organization.bru new file mode 100644 index 00000000..faf45b3b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/Delegation/Authorized Parties Test Data Setup/Subunit to Organization.bru @@ -0,0 +1,57 @@ +meta { + name: Subunit to Organization + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_mps_authparties-sub-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50004386 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/altinnapp-badrequest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/altinnapp-badrequest.bru new file mode 100644 index 00000000..277a4552 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/altinnapp-badrequest.bru @@ -0,0 +1,56 @@ +meta { + name: altinnapp-badrequest + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } +} + +vars:pre-request { + org: ttd + app: apps-test + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 400 BADREQUEST", function() { + expect(res.status).to.equal(400); + }); + + test("Should return error message", function() { + const error = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/success.bru new file mode 100644 index 00000000..7f2535db --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/DelegationCheck/DAGL/success.bru @@ -0,0 +1,51 @@ +meta { + name: success + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/{{party}}/maskinportenschema/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resource}}" + } + ] + } +} + +vars:pre-request { + resource: ttd-am-k6 + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); + + test("Should return error message", function() { + const error = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-offered.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-offered.bru new file mode 100644 index 00000000..ff31703a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-offered.bru @@ -0,0 +1,15 @@ +meta { + name: get -accessmanagement-api-v1--party--maskinportenschema-offered + type: http + seq: 3 +} + +get { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/offered + body: none + auth: none +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-received.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-received.bru new file mode 100644 index 00000000..0358b880 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/get -accessmanagement-api-v1--party--maskinportenschema-received.bru @@ -0,0 +1,15 @@ +meta { + name: get -accessmanagement-api-v1--party--maskinportenschema-received + type: http + seq: 5 +} + +get { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/received + body: none + auth: none +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-delegationcheck.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-delegationcheck.bru new file mode 100644 index 00000000..b4d87b31 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-delegationcheck.bru @@ -0,0 +1,21 @@ +meta { + name: post -accessmanagement-api-v1--party--maskinportenschema-delegationcheck + type: http + seq: 1 +} + +post { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/delegationcheck + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + { + "resource": [] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered-revoke.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered-revoke.bru new file mode 100644 index 00000000..005db848 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered-revoke.bru @@ -0,0 +1,22 @@ +meta { + name: post -accessmanagement-api-v1--party--maskinportenschema-offered-revoke + type: http + seq: 4 +} + +post { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/offered/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + { + "to": [], + "rights": [] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered.bru new file mode 100644 index 00000000..edac8198 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-offered.bru @@ -0,0 +1,22 @@ +meta { + name: post -accessmanagement-api-v1--party--maskinportenschema-offered + type: http + seq: 2 +} + +post { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/offered + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + { + "to": [], + "rights": [] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-received-revoke.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-received-revoke.bru new file mode 100644 index 00000000..f8eec0e7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/MaskinportenSchema/post -accessmanagement-api-v1--party--maskinportenschema-received-revoke.bru @@ -0,0 +1,22 @@ +meta { + name: post -accessmanagement-api-v1--party--maskinportenschema-received-revoke + type: http + seq: 6 +} + +post { + url: http://accessmanagement/api/v1/{party}/maskinportenschema/received/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + { + "from": [], + "rights": [] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for MainUnit.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for MainUnit.bru new file mode 100644 index 00000000..9b0ef681 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for MainUnit.bru @@ -0,0 +1,30 @@ +meta { + name: Karlstad for MainUnit + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: none +} + +body:json { + { + "subject": { + "id": "urn:altinn:partyid", + "value": "50004222" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50006037" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-main-to-org" + } + ] + } +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for \303\230rsta.bru" new file mode 100644 index 00000000..fe82d774 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Karlstad for \303\230rsta.bru" @@ -0,0 +1,30 @@ +meta { + name: Karlstad for Ørsta + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: none +} + +body:json { + { + "subject": { + "id": "urn:altinn:partyid", + "value": "50004222" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "test-ressurs-rf-1086-altinn-autorisasjon" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for MainUnit.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for MainUnit.bru new file mode 100644 index 00000000..615aa400 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for MainUnit.bru @@ -0,0 +1,30 @@ +meta { + name: Paula for MainUnit + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: none +} + +body:json { + { + "subject": { + "id": "urn:altinn:userid", + "value": "20000095" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50006037" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "devtest_gar_authparties-main-to-org" + } + ] + } +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for \303\230rsta.bru" new file mode 100644 index 00000000..6741bcd8 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/GetDelegationChanges/Paula for \303\230rsta.bru" @@ -0,0 +1,30 @@ +meta { + name: Paula for Ørsta + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: none +} + +body:json { + { + "subject": { + "id": "urn:altinn:userid", + "value": "20000095" + }, + "party": { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": [ + { + "id": "urn:altinn:resource", + "value": "test-ressurs-rf-1086-altinn-autorisasjon" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/PersonToPerson/Paula for Kasper.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/PersonToPerson/Paula for Kasper.bru new file mode 100644 index 00000000..128f1bda --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/PersonToPerson/Paula for Kasper.bru @@ -0,0 +1,33 @@ +meta { + name: Paula for Kasper + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: inherit +} + +body:json { + { + "subject": + { + "id": "urn:altinn:userid", + "value": "20000095" + }, + "party": + { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": + [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on App for Orsta.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on App for Orsta.bru new file mode 100644 index 00000000..9997cc5f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on App for Orsta.bru @@ -0,0 +1,37 @@ +meta { + name: SystemUser on App for Orsta + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: inherit +} + +body:json { + { + "subject": + { + "id": "urn:altinn:systemuser:uuid", + "value": "fc59de4f-9715-4fe5-b317-ed4b12d57126" + }, + "party": + { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": + [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on Resource for Orsta.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on Resource for Orsta.bru new file mode 100644 index 00000000..34ed9e3e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/SystemUser/SystemUser on Resource for Orsta.bru @@ -0,0 +1,33 @@ +meta { + name: SystemUser on Resource for Orsta + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: inherit +} + +body:json { + { + "subject": + { + "id": "urn:altinn:systemuser:uuid", + "value": "a6355a68-86b8-4344-8a81-0248cb461468" + }, + "party": + { + "id": "urn:altinn:partyid", + "value": "50005545" + }, + "resource": + [ + { + "id": "urn:altinn:resource", + "value": "generic-access-resource" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/post -accessmanagement-api-v1-policyinformation-getdelegationchanges.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/post -accessmanagement-api-v1-policyinformation-getdelegationchanges.bru new file mode 100644 index 00000000..240ee5c3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/PolicyInformationPoint/post -accessmanagement-api-v1-policyinformation-getdelegationchanges.bru @@ -0,0 +1,33 @@ +meta { + name: post -accessmanagement-api-v1-policyinformation-getdelegationchanges + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/policyinformation/getdelegationchanges + body: json + auth: inherit +} + +body:json { + { + "subject": + { + "id": "", + "value": "" + }, + "party": + { + "id": "", + "value": "" + }, + "resource": + [ + { + "id": "", + "value": "" + } + ] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/post -accessmanagement-api-v1-internal-resources.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/post -accessmanagement-api-v1-internal-resources.bru new file mode 100644 index 00000000..9052ca7f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/post -accessmanagement-api-v1-internal-resources.bru @@ -0,0 +1,15 @@ +meta { + name: post -accessmanagement-api-v1-internal-resources + type: http + seq: 1 +} + +post { + url: http://accessmanagement/api/v1/internal/resources + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/put -accessmanagement-api-v1-internal-resources.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/put -accessmanagement-api-v1-internal-resources.bru new file mode 100644 index 00000000..cd44bd9e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/Resource/put -accessmanagement-api-v1-internal-resources.bru @@ -0,0 +1,15 @@ +meta { + name: put -accessmanagement-api-v1-internal-resources + type: http + seq: 2 +} + +put { + url: http://accessmanagement/api/v1/internal/resources + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Asle.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Asle.bru" new file mode 100644 index 00000000..662f2cbc --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Asle.bru" @@ -0,0 +1,40 @@ +meta { + name: Ørsta to Asle + type: http + seq: 1 +} + +put { + url: {{baseUrl}}/accessmanagement/api/v1/internal/50005545/accesscache/clear + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:uuid", + "value": "182ad02e-34b5-431e-8ae2-2bdf14eaa436" + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Hovdebygda.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Hovdebygda.bru" new file mode 100644 index 00000000..a25389b2 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Hovdebygda.bru" @@ -0,0 +1,40 @@ +meta { + name: Ørsta to Hovdebygda + type: http + seq: 2 +} + +put { + url: {{baseUrl}}/accessmanagement/api/v1/internal/50005545/accesscache/clear + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:organization:uuid", + "value": "44d9839a-8be6-4735-ba88-186992493cfe" + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to OrstaECUser.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to OrstaECUser.bru" new file mode 100644 index 00000000..9a694ce0 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to OrstaECUser.bru" @@ -0,0 +1,40 @@ +meta { + name: Ørsta to OrstaECUser + type: http + seq: 3 +} + +put { + url: {{baseUrl}}/accessmanagement/api/v1/internal/50005545/accesscache/clear + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:enterpriseuser:uuid", + "value": "002209f9-57fc-4d7c-9a60-ef0ab8e4eb06" + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Ostekake.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Ostekake.bru" new file mode 100644 index 00000000..7b4bc1cc --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/ClearAccessCache/\303\230rsta to Ostekake.bru" @@ -0,0 +1,40 @@ +meta { + name: Ørsta to Ostekake + type: http + seq: 4 +} + +put { + url: {{baseUrl}}/accessmanagement/api/v1/internal/50005545/accesscache/clear + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "type": "urn:altinn:person:uuid", + "value": "88bc3eff-bed2-46fe-8dd8-64dce1f94691" + } +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn 2 Service/Person to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn 2 Service/Person to Person.bru new file mode 100644 index 00000000..e392cdd5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn 2 Service/Person to Person.bru @@ -0,0 +1,64 @@ +meta { + name: Person to Person + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50002650 + serviceCode: 2802 + serviceEditionCode: 2203 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Org.bru new file mode 100644 index 00000000..68c85c04 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Org.bru @@ -0,0 +1,63 @@ +meta { + name: Main to Org + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + org: ttd + app: am-devtest-main-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Person.bru new file mode 100644 index 00000000..109e973c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Main to Person.bru @@ -0,0 +1,68 @@ +meta { + name: Main to Person + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + org: ttd + app: am-devtest-main-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Org.bru new file mode 100644 index 00000000..eb3fa9ea --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Org.bru @@ -0,0 +1,63 @@ +meta { + name: Person to Org + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + org: ttd + app: am-devtest-person-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50002650 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Person.bru new file mode 100644 index 00000000..6c9a2f34 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Person to Person.bru @@ -0,0 +1,68 @@ +meta { + name: Person to Person + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + org: ttd + app: am-devtest-person-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50002650 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Org.bru new file mode 100644 index 00000000..1aaaa0e2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Org.bru @@ -0,0 +1,63 @@ +meta { + name: Sub to Org + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + org: ttd + app: am-devtest-sub-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006038 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Person.bru new file mode 100644 index 00000000..f7c9d91e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Altinn App/Sub to Person.bru @@ -0,0 +1,68 @@ +meta { + name: Sub to Person + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + org: ttd + app: am-devtest-sub-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006038 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Organization.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Organization.bru new file mode 100644 index 00000000..b76644c3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Organization.bru @@ -0,0 +1,58 @@ +meta { + name: Mainunit to Organization + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_gar_authparties-main-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Person.bru new file mode 100644 index 00000000..cd286a66 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Mainunit to Person.bru @@ -0,0 +1,63 @@ +meta { + name: Mainunit to Person + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + resourceId: devtest_gar_authparties-main-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Org.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Org.bru new file mode 100644 index 00000000..e80fb5a8 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Org.bru @@ -0,0 +1,58 @@ +meta { + name: Person to Org + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_gar_authparties-person-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50002650 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Person.bru new file mode 100644 index 00000000..10ea1419 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Person to Person.bru @@ -0,0 +1,63 @@ +meta { + name: Person to Person + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + resourceId: devtest_gar_authparties-person-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50002650 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Organization.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Organization.bru new file mode 100644 index 00000000..0429c5da --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Organization.bru @@ -0,0 +1,58 @@ +meta { + name: Subunit to Organization + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_gar_authparties-sub-to-org + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50004386 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Person.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Person.bru new file mode 100644 index 00000000..3dde373f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Authorized Parties Test Data Setup/Generic Access Resource/Subunit to Person.bru @@ -0,0 +1,63 @@ +meta { + name: Subunit to Person + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + resourceId: devtest_gar_authparties-sub-to-person + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50004386 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/app_ttd_am-devtest-main-to-person should fail.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/app_ttd_am-devtest-main-to-person should fail.bru new file mode 100644 index 00000000..4c24d1de --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/app_ttd_am-devtest-main-to-person should fail.bru @@ -0,0 +1,63 @@ +meta { + name: app_ttd_am-devtest-main-to-person should fail + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + resourceId: app_ttd_am-devtest-main-to-person + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/generic-access-resource_success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/generic-access-resource_success.bru new file mode 100644 index 00000000..5c7cf91f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/generic-access-resource_success.bru @@ -0,0 +1,63 @@ +meta { + name: generic-access-resource_success + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + resourceId: devtest-generic-access-resource + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper apps-test-prod to rimstad.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper apps-test-prod to rimstad.bru new file mode 100644 index 00000000..f4020a29 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper apps-test-prod to rimstad.bru @@ -0,0 +1,68 @@ +meta { + name: kasper apps-test-prod to rimstad + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to org karlstad ttd-apps-test-prod.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to org karlstad ttd-apps-test-prod.bru new file mode 100644 index 00000000..0711923d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to org karlstad ttd-apps-test-prod.bru @@ -0,0 +1,64 @@ +meta { + name: kasper to org karlstad ttd-apps-test-prod + type: http + seq: 9 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrgNumber}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + toOrgNumber: '810418672' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to rimstad ttd-apps-test-prod.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to rimstad ttd-apps-test-prod.bru new file mode 100644 index 00000000..1d2fcf06 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/kasper to rimstad ttd-apps-test-prod.bru @@ -0,0 +1,69 @@ +meta { + name: kasper to rimstad ttd-apps-test-prod + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 + toParty: 50004222 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/org \303\270rsta to rimstad ttd-apps-test-prod.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/org \303\270rsta to rimstad ttd-apps-test-prod.bru" new file mode 100644 index 00000000..d935ab84 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/org \303\270rsta to rimstad ttd-apps-test-prod.bru" @@ -0,0 +1,68 @@ +meta { + name: org ørsta to rimstad ttd-apps-test-prod + type: http + seq: 8 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + org: ttd + app: apps-test-prod + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/to person uuid.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/to person uuid.bru new file mode 100644 index 00000000..267e1194 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/to person uuid.bru @@ -0,0 +1,58 @@ +meta { + name: to person uuid + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:uuid", + "value": "{{toPersonUuid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toPersonUuid: 14f553af-2ab4-46e3-bf9e-9dda1d27f87c + resourceId: generic-access-resource + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-am-k6_badrequest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-am-k6_badrequest.bru new file mode 100644 index 00000000..0e735f9b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-am-k6_badrequest.bru @@ -0,0 +1,62 @@ +meta { + name: ttd-am-k6_badrequest + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "ScopeAccess" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + resourceId: ttd-am-k6 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 400 BADREQUEST", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-apps-test_success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-apps-test_success.bru new file mode 100644 index 00000000..ed9772f4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to Person/ttd-apps-test_success.bru @@ -0,0 +1,68 @@ +meta { + name: ttd-apps-test_success + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:ssn", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '02056260016' + toLastName: Rimstad + org: ttd + app: apps-test + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/app to system uuid.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/app to system uuid.bru new file mode 100644 index 00000000..4e0cf856 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/app to system uuid.bru @@ -0,0 +1,65 @@ +meta { + name: app to system uuid + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "{{toSystemUserUuid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toPersonUuid: 14f553af-2ab4-46e3-bf9e-9dda1d27f87c + resourceId: generic-access-resource + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 + toSystemUserUuid: a6355a68-86b8-4344-8a81-0248cb461468 + org: ttd + app: apps-test +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/resource to system uuid.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/resource to system uuid.bru new file mode 100644 index 00000000..af891c01 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Org to SystemUser/resource to system uuid.bru @@ -0,0 +1,59 @@ +meta { + name: resource to system uuid + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:systemuser:uuid", + "value": "{{toSystemUserUuid}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toPersonUuid: 14f553af-2ab4-46e3-bf9e-9dda1d27f87c + resourceId: generic-access-resource + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 + toSystemUserUuid: a6355a68-86b8-4344-8a81-0248cb461468 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Asle to Hovdebygda.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Asle to Hovdebygda.bru new file mode 100644 index 00000000..d0f4db88 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Asle to Hovdebygda.bru @@ -0,0 +1,58 @@ +meta { + name: Asle to Hovdebygda + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_gar_authparties-person-to-org + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Kasper to Asle.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Kasper to Asle.bru new file mode 100644 index 00000000..ec439cfc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/Kasper to Asle.bru @@ -0,0 +1,63 @@ +meta { + name: Kasper to Asle + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + resourceId: devtest_gar_authparties-person-to-person + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50002598 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Asle.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Asle.bru" new file mode 100644 index 00000000..c3599ef0 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Asle.bru" @@ -0,0 +1,63 @@ +meta { + name: Ørsta to Asle + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "{{toSsn}}" + }, + { + "id": "urn:altinn:person:lastname", + "value": "{{toLastName}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toSsn: '17105431031' + toLastName: Natvik + resourceId: devtest_gar_authparties-main-to-person + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Hovdebygda.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Hovdebygda.bru" new file mode 100644 index 00000000..a6df773a --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/CreateDelegation/Revoke Test Data Setup/\303\230rsta to Hovdebygda.bru" @@ -0,0 +1,58 @@ +meta { + name: Ørsta to Hovdebygda + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:organizationnumber", + "value": "{{toOrg}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toOrg: 910434217 + resourceId: devtest_gar_authparties-main-to-org + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 201 CREATED", function() { + expect(res.status).to.equal(201); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/apps-test_success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/apps-test_success.bru new file mode 100644 index 00000000..b6b95916 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/apps-test_success.bru @@ -0,0 +1,56 @@ +meta { + name: apps-test_success + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } +} + +vars:pre-request { + org: ttd + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + app: apps-test +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); + + test("Should return expected rights", function() { + const rights = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest-generic-access-resource_success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest-generic-access-resource_success.bru new file mode 100644 index 00000000..f5649e30 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest-generic-access-resource_success.bru @@ -0,0 +1,51 @@ +meta { + name: devtest-generic-access-resource_success + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } +} + +vars:pre-request { + resourceId: devtest-generic-access-resource + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); + + test("Should return expected rights", function() { + const rights = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest_gar_bloop.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest_gar_bloop.bru new file mode 100644 index 00000000..29936d1c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/devtest_gar_bloop.bru @@ -0,0 +1,52 @@ +meta { + name: devtest_gar_bloop + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json + Altinn-Party-OrganizationNumber: {{partyOrganizationNumber}} +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } +} + +vars:pre-request { + resourceId: devtest_gar_bloop + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); + + test("Should return expected rights", function() { + const rights = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/generic-access-resource_success.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/generic-access-resource_success.bru new file mode 100644 index 00000000..f2d59c35 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/generic-access-resource_success.bru @@ -0,0 +1,51 @@ +meta { + name: generic-access-resource_success + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } +} + +vars:pre-request { + resourceId: devtest-generic-access-resource + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +script:pre-request { + //await tokenGenerator.getToken(); +} + +tests { + test("Should return 200 OK", function() { + expect(res.status).to.equal(200); + }); + + test("Should return expected rights", function() { + const rights = res.getBody(); + // ToDo Expect Result + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/ttd-am-k6_badrequest.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/ttd-am-k6_badrequest.bru new file mode 100644 index 00000000..2e4c3299 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/DelegationCheck/ttd-am-k6_badrequest.bru @@ -0,0 +1,63 @@ +meta { + name: ttd-am-k6_badrequest + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/delegationcheck + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ] + } +} + +vars:pre-request { + resourceId: ttd-am-k6 + party: 50005545 + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' +} + +vars:post-response { + errors: res.body.errors +} + +assert { + res.status: eq 400 + res.body.type: eq https://tools.ietf.org/html/rfc7231#section-6.5.1 + res.body.title: eq One or more validation errors occurred. + res.body.status: eq 400 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 400 BADREQUEST", function() { + expect(res.status).to.equal(400); + }); + + test("Should return expected error message", function() { + const valError = res.getBody(); + // ToDo Expect Result + expect(valError.type).to.equal('https://tools.ietf.org/html/rfc7231#section-6.5.1'); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Kasper Get Offered from \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Kasper Get Offered from \303\230rsta.bru" new file mode 100644 index 00000000..1ca3400c --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Kasper Get Offered from \303\230rsta.bru" @@ -0,0 +1,27 @@ +meta { + name: Kasper Get Offered from Ørsta + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Noa R\303\270gerberg Get Offered from Natvik.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Noa R\303\270gerberg Get Offered from Natvik.bru" new file mode 100644 index 00000000..1b40238a --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOffered/Noa R\303\270gerberg Get Offered from Natvik.bru" @@ -0,0 +1,27 @@ +meta { + name: Noa Røgerberg Get Offered from Natvik + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from Rimstad.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from Rimstad.bru new file mode 100644 index 00000000..3d4eb82e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from Rimstad.bru @@ -0,0 +1,58 @@ +meta { + name: Kasper Revoke Offered from Rimstad + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:userid", + "value": "{{toUserId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 + org: ttd + app: apps-test-prod + toUserId: 20000095 + ~toSsn: 02056260016 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from \303\230rsta.bru" new file mode 100644 index 00000000..82f6ad04 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Kasper Revoke Offered from \303\230rsta.bru" @@ -0,0 +1,64 @@ +meta { + name: Kasper Revoke Offered from Ørsta + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "50005545" + } + ], + "to": [ + { + "id": "urn:altinn:ssn", + "value": "02056260016" + }, + { + "id": "urn:altinn:lastname", + "value": "Rimstad" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Noa Revoke Offered from Natvik.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Noa Revoke Offered from Natvik.bru new file mode 100644 index 00000000..0faf1cfd --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Noa Revoke Offered from Natvik.bru @@ -0,0 +1,54 @@ +meta { + name: Noa Revoke Offered from Natvik + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:person:identifier-no", + "value": "02056260016" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "ttd" + }, + { + "id": "urn:altinn:app", + "value": "apps-test" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000542 + auth_partyId: 50002650 + auth_ssn: '08109412032' + party: 50006037 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from Kasper.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from Kasper.bru new file mode 100644 index 00000000..c91dd518 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from Kasper.bru @@ -0,0 +1,58 @@ +meta { + name: Rimstad Revoke Received from Kasper + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:person:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' + party: 50005545 + org: ttd + app: apps-test-prod + fromPartyId: 50002598 + ~toSsn: 02056260016 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from org Karlstad.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from org Karlstad.bru new file mode 100644 index 00000000..232c615c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/Rimstad Revoke Received from org Karlstad.bru @@ -0,0 +1,58 @@ +meta { + name: Rimstad Revoke Received from org Karlstad + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "from": [ + { + "id": "urn:altinn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' + party: 50005545 + org: ttd + app: apps-test-prod + fromPartyId: 50002598 + ~toSsn: 02056260016 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/org karlstad Revoke Offered from org \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/org karlstad Revoke Offered from org \303\230rsta.bru" new file mode 100644 index 00000000..21c6ba47 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetOfferedRevoke/org karlstad Revoke Offered from org \303\230rsta.bru" @@ -0,0 +1,58 @@ +meta { + name: org karlstad Revoke Offered from org Ørsta + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +body:json { + + { + "to": [ + { + "id": "urn:altinn:organization:partyid", + "value": "{{toPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:org", + "value": "{{org}}" + }, + { + "id": "urn:altinn:app", + "value": "{{app}}" + } + ] + } + ] + } + +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 + org: ttd + app: apps-test-prod + toPartyId: 50002203 + ~toSsn: 02056260016 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Kasper Get Received to \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Kasper Get Received to \303\230rsta.bru" new file mode 100644 index 00000000..2285b633 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Kasper Get Received to \303\230rsta.bru" @@ -0,0 +1,27 @@ +meta { + name: Kasper Get Received to Ørsta + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Natvik Get Received to self.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Natvik Get Received to self.bru new file mode 100644 index 00000000..b2d795d4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/Natvik Get Received to self.bru @@ -0,0 +1,27 @@ +meta { + name: Natvik Get Received to self + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/ + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/X Get Received to Y.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/X Get Received to Y.bru new file mode 100644 index 00000000..a09ca71f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/X Get Received to Y.bru @@ -0,0 +1,27 @@ +meta { + name: X Get Received to Y + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/ + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/org \303\230rsta Get Received from Kasper.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/org \303\230rsta Get Received from Kasper.bru" new file mode 100644 index 00000000..c6d4b37e --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/org \303\230rsta Get Received from Kasper.bru" @@ -0,0 +1,27 @@ +meta { + name: org Ørsta Get Received from Kasper + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/rimstad Get Received from Kasper.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/rimstad Get Received from Kasper.bru new file mode 100644 index 00000000..abb1b0b5 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/GetReceived/rimstad Get Received from Kasper.bru @@ -0,0 +1,27 @@ +meta { + name: rimstad Get Received from Kasper + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{auth_partyId}}/rights/delegation/received + body: json + auth: none +} + +headers { + Authorization: {{apiKey}} +} + +vars:pre-request { + auth_tokenType: Personal + auth_userId: 20000095 + auth_partyId: 50002203 + auth_ssn: '02056260016' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Asle to Hovdebygda.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Asle to Hovdebygda.bru new file mode 100644 index 00000000..f07cd2c2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Asle to Hovdebygda.bru @@ -0,0 +1,58 @@ +meta { + name: Asle to Hovdebygda + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{toPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toPartyId: 50004674 + resourceId: devtest_gar_authparties-person-to-org + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Kasper to Asle.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Kasper to Asle.bru new file mode 100644 index 00000000..65e14313 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/Kasper to Asle.bru @@ -0,0 +1,58 @@ +meta { + name: Kasper to Asle + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:userid", + "value": "{{toUserId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toUserId: 20001121 + resourceId: devtest_gar_authparties-person-to-person + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50002598 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Asle.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Asle.bru" new file mode 100644 index 00000000..e0d6152b --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Asle.bru" @@ -0,0 +1,58 @@ +meta { + name: Ørsta to Asle + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:userid", + "value": "{{toUserId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toUserId: 20001121 + resourceId: devtest_gar_authparties-main-to-person + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Hovdebygda.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Hovdebygda.bru" new file mode 100644 index 00000000..33901c4c --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeOffered/\303\230rsta to Hovdebygda.bru" @@ -0,0 +1,58 @@ +meta { + name: Ørsta to Hovdebygda + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/offered/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "to": [ + { + "id": "urn:altinn:partyid", + "value": "{{toPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + toPartyId: 50004674 + resourceId: devtest_gar_authparties-main-to-org + auth_tokenType: Personal + auth_userId: 20000490 + auth_partyId: 50002598 + auth_ssn: '07124912037' + party: 50005545 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From Kasper.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From Kasper.bru new file mode 100644 index 00000000..31c235f1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From Kasper.bru @@ -0,0 +1,58 @@ +meta { + name: Asle From Kasper + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "from": [ + { + "id": "urn:altinn:userid", + "value": "{{fromUserId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + fromUserId: 20000490 + resourceId: devtest_gar_authparties-person-to-person + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From \303\230rsta.bru" new file mode 100644 index 00000000..1c5a9be9 --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Asle From \303\230rsta.bru" @@ -0,0 +1,58 @@ +meta { + name: Asle From Ørsta + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + fromPartyId: 50005545 + resourceId: devtest_gar_authparties-main-to-person + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50003229 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From Asle.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From Asle.bru new file mode 100644 index 00000000..b7501347 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From Asle.bru @@ -0,0 +1,58 @@ +meta { + name: Hovdebygda From Asle + type: http + seq: 4 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + fromPartyId: 50003229 + resourceId: devtest_gar_authparties-person-to-org + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50004674 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git "a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From \303\230rsta.bru" "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From \303\230rsta.bru" new file mode 100644 index 00000000..d4f4711f --- /dev/null +++ "b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Manual Test Collection/RightsInternal/RevokeReceived/Hovdebygda From \303\230rsta.bru" @@ -0,0 +1,58 @@ +meta { + name: Hovdebygda From Ørsta + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/accessmanagement/api/v1/internal/{{party}}/rights/delegation/received/revoke + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "from": [ + { + "id": "urn:altinn:partyid", + "value": "{{fromPartyId}}" + } + ], + "rights": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "{{resourceId}}" + } + ], + "action": "read" + } + ] + } +} + +vars:pre-request { + fromPartyId: 50005545 + resourceId: devtest_gar_authparties-main-to-org + auth_tokenType: Personal + auth_userId: 20001121 + auth_partyId: 50003229 + auth_ssn: '17105431031' + party: 50004674 +} + +script:pre-request { + await tokenGenerator.getToken(); +} + +tests { + test("Should return 204 No Content", function() { + expect(res.status).to.equal(204); + }); +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/TestToolsTokenGenerator.js b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/TestToolsTokenGenerator.js new file mode 100644 index 00000000..98762743 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/TestToolsTokenGenerator.js @@ -0,0 +1,53 @@ + +exports.getToken = async function (getTokenParameters) { + const axios = require("axios"); + const btoa = require("btoa"); + + const tokenBaseUrl = "https://altinn-testtools-token-generator.azurewebsites.net"; + const basicAuthUser = bru.getEnvVar("tokenBasicAuthUser"); + const basicAuthPw = bru.getEnvVar("tokenBasicAuthPw"); + const Authorization = 'Basic ' + btoa(`${basicAuthUser}:${basicAuthPw}`); + + const tokenEnv = bru.getEnvVar("tokenEnv"); + const tokenType = getTokenParameters.auth_tokenType; + const tokenScopes = getTokenParameters.auth_scopes; + + let tokenUrl; + + if (tokenType == "Personal") { + const tokenUser = getTokenParameters.auth_userId; + const tokenParty = getTokenParameters.auth_partyId; + const tokenPid = getTokenParameters.auth_ssn; + + tokenUrl = `${tokenBaseUrl}/api/Get${tokenType}Token?env=${tokenEnv}&scopes=${tokenScopes}&pid=${tokenPid}&userid=${tokenUser}&partyid=${tokenParty}&authLvl=3&ttl=3000`; + } + + else if (tokenType == "Enterprise") { + const tokenOrg = getTokenParameters.auth_org; + const tokenOrgNo = getTokenParameters.auth_orgNo; + + tokenUrl = `${tokenBaseUrl}/api/Get${tokenType}Token?env=${tokenEnv}&scopes=${tokenScopes}&org=${tokenOrg}&orgNo=${tokenOrgNo}&ttl=30`; + } + + else if (tokenType == "EnterpriseUser") { + const tokenUser = getTokenParameters.auth_userId; + const tokenParty = getTokenParameters.auth_partyId; + const tokenOrgNo = getTokenParameters.auth_orgNo; + const tokenUserName = getTokenParameters.auth_username; + + tokenUrl = `${tokenBaseUrl}/api/Get${tokenType}Token?env=${tokenEnv}&scopes=${tokenScopes}&orgNo=${tokenOrgNo}&userId=${tokenUser}&partyId=${tokenParty}&userName=${tokenUserName}&ttl=30`; + } + + else if (tokenType == "PlatformAccess") { + const tokenOrg = getTokenParameters.auth_org; + const tokenApp = getTokenParameters.auth_app; + + tokenUrl = `${tokenBaseUrl}/api/Get${tokenType}Token?env=${tokenEnv}&org=${tokenOrg}&app=${tokenApp}&ttl=30`; + } + + const response = await axios.get(tokenUrl, { + headers: { Authorization } + }); + + return response.data; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/at22.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/at22.json new file mode 100644 index 00000000..39d94666 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/at22.json @@ -0,0 +1,113 @@ +{ + "env": "at22", + "resources": { + "appInstanceDelegation": { + "resourceId": "app_ttd_authz-bruno-instancedelegation", + "org": "ttd", + "app": "authz-bruno-instancedelegation" + } + }, + "instances": { + "p2p": { + "instanceId": "93994414-07dc-4df3-b2c6-047722169b6c", + "from": "5daf2382-adee-4cd6-9995-3c5f3fc058af", + "to": "bd90e954-efe5-4b65-be8a-f9fccbb36342" + }, + "main2p": { + "instanceId": "df333e75-5896-4254-a69f-146736eaf668", + "from": "01712d4f-cfb2-4d12-8aac-2eb7ad0d9c86", + "to": "bd90e954-efe5-4b65-be8a-f9fccbb36342" + }, + "sub2p": { + "instanceId": "49513daa-beb1-4a83-a07e-83da1378c8a9", + "from": "e21a640b-9558-4d59-b47f-7b87d2cd9ee0", + "to": "bd90e954-efe5-4b65-be8a-f9fccbb36342" + }, + "subonly2p": { + "instanceId_1": "a5215400-1de1-46eb-abff-54aac49745e2", + "instanceId_2": "6afa0a58-a6d1-4ff3-9973-7040cef0763a", + "from": "e21a640b-9558-4d59-b47f-7b87d2cd9ee0", + "to": "db684960-0b7d-4c11-b948-1ec9268c4a13" + }, + "o2o": { + "instanceId": "0d55d70c-6e81-4728-b0e6-7ff1ede1a4fe", + "from": "f7e2eb77-6b5e-4aeb-9fe9-f261013401c9", + "to": "01712d4f-cfb2-4d12-8aac-2eb7ad0d9c86" + }, + "p2o": { + "instanceId_1": "6ad65bea-59f4-462c-9077-04ac488322b6", + "instanceId_2": "23820c6b-4ba4-412d-8781-b92517cb3715", + "from": "db684960-0b7d-4c11-b948-1ec9268c4a13", + "to": "01712d4f-cfb2-4d12-8aac-2eb7ad0d9c86" + } + }, + "organizations": { + "mobilBeskjedenTiger": { + "partyUuid": "f7e2eb77-6b5e-4aeb-9fe9-f261013401c9", + "name": "MOBIL BESKJEDEN TIGER AS", + "organizationNumber": "310705071", + "partyId": 51373625, + "subunits": { + "mobilBeskjedenTiger": { + "partyUuid": "2177ee69-fd11-4b38-904a-e0e2f1958f86", + "name": "MOBIL BESKJEDEN TIGER AS", + "organizationNumber": "314410343", + "partyId": 51690212, + "dagl": null + } + }, + "dagl": { + "name": "HAKKE DYR", + "personId": "29917997339", + "userId": 20012883, + "partyUuid": "bd90e954-efe5-4b65-be8a-f9fccbb36342", + "partyId": 50127680 + } + }, + "legitimJusterbarTiger": { + "partyUuid": "01712d4f-cfb2-4d12-8aac-2eb7ad0d9c86", + "name": "LEGITIM JUSTERBAR TIGER AS", + "organizationNumber": "311041371", + "partyId": 51403263, + "subunits": { + "legitimJusterbarTiger": { + "partyUuid": "e21a640b-9558-4d59-b47f-7b87d2cd9ee0", + "name": "LEGITIM JUSTERBAR TIGER AS", + "organizationNumber": "315684617", + "partyId": 51806076, + "dagl": null + } + }, + "dagl": { + "name": "ØVELSE EMPIRISK", + "personId": "25884699358", + "userId": 20012882, + "partyUuid": "5daf2382-adee-4cd6-9995-3c5f3fc058af", + "partyId": 51195601 + } + } + }, + "persons": { + "ovelseEmpirisk": { + "name": "ØVELSE EMPIRISK", + "personId": "25884699358", + "userId": 20012882, + "partyUuid": "5daf2382-adee-4cd6-9995-3c5f3fc058af", + "partyId": 51195601 + }, + "hakkeDyr": { + "name": "HAKKE DYR", + "personId": "29917997339", + "userId": 20012883, + "partyUuid": "bd90e954-efe5-4b65-be8a-f9fccbb36342", + "partyId": 50127680 + }, + "spesifikkSmaragd": { + "name": "SPESIFIKK SMARAGD", + "personId": "05869598129", + "userId": 20012925, + "partyUuid": "db684960-0b7d-4c11-b948-1ec9268c4a13", + "partyId": 50370250 + } + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/tt02.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/tt02.json new file mode 100644 index 00000000..ba9b8f8d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation-authorized-parties/tt02.json @@ -0,0 +1,113 @@ +{ + "env": "tt02", + "resources": { + "appInstanceDelegation": { + "resourceId": "app_ttd_authz-bruno-instancedelegation", + "org": "ttd", + "app": "authz-bruno-instancedelegation" + } + }, + "instances": { + "p2p": { + "instanceId": "16e679bc-9bb9-46f9-86e1-3657b267af26", + "from": "f9b2750f-f2aa-442c-91b7-418e2f627a8b", + "to": "07336d43-1f0e-40a8-a02b-2c6019013cc7" + }, + "main2p": { + "instanceId": "e0c55fe6-442b-4442-aabc-aeafda8d94fe", + "from": "58c0acd2-793e-48f1-a19f-169c171066f4", + "to": "07336d43-1f0e-40a8-a02b-2c6019013cc7" + }, + "sub2p": { + "instanceId": "3e8b4812-c26c-4bfa-82f5-5c99c9ad90e3", + "from": "65018cec-9bd4-45ad-998d-357ac181eaf3", + "to": "07336d43-1f0e-40a8-a02b-2c6019013cc7" + }, + "subonly2p": { + "instanceId_1": "ab194d3a-96a4-4237-8fb9-3a995cb177a6", + "instanceId_2": "1a404054-17b1-432a-979f-5be965441e5c", + "from": "65018cec-9bd4-45ad-998d-357ac181eaf3", + "to": "6971e33b-59c2-4605-8bdb-7ce3257fd1c7" + }, + "o2o": { + "instanceId": "1f80ab14-ef45-48ab-8fef-7c5562683706", + "from": "9d263473-4f08-459e-bf27-1de535c40607", + "to": "58c0acd2-793e-48f1-a19f-169c171066f4" + }, + "p2o": { + "instanceId_1": "a75f521f-e00c-4f1c-ab1d-1843e04bfc77", + "instanceId_2": "1946c07c-c785-4131-9d3c-f6ffe5c8f560", + "from": "6971e33b-59c2-4605-8bdb-7ce3257fd1c7", + "to": "58c0acd2-793e-48f1-a19f-169c171066f4" + } + }, + "organizations": { + "mobilBeskjedenTiger": { + "partyUuid": "9d263473-4f08-459e-bf27-1de535c40607", + "name": "MOBIL BESKJEDEN TIGER AS", + "organizationNumber": "310705071", + "partyId": 51587157, + "subunits": { + "mobilBeskjedenTiger": { + "partyUuid": "4f849f61-c36f-470a-b0b5-924568e3e10a", + "name": "MOBIL BESKJEDEN TIGER AS", + "organizationNumber": "314410343", + "partyId": 51903584, + "dagl": null + } + }, + "dagl": { + "name": "HAKKE DYR", + "personId": "29917997339", + "userId": 1424053, + "partyUuid": "07336d43-1f0e-40a8-a02b-2c6019013cc7", + "partyId": 51015472 + } + }, + "legitimJusterbarTiger": { + "partyUuid": "58c0acd2-793e-48f1-a19f-169c171066f4", + "name": "LEGITIM JUSTERBAR TIGER AS", + "organizationNumber": "311041371", + "partyId": 51616797, + "subunits": { + "legitimJusterbarTiger": { + "partyUuid": "65018cec-9bd4-45ad-998d-357ac181eaf3", + "name": "LEGITIM JUSTERBAR TIGER AS", + "organizationNumber": "315684617", + "partyId": 52019430, + "dagl": null + } + }, + "dagl": { + "name": "ØVELSE EMPIRISK", + "personId": "25884699358", + "userId": 1424054, + "partyUuid": "f9b2750f-f2aa-442c-91b7-418e2f627a8b", + "partyId": 51443447 + } + } + }, + "persons": { + "ovelseEmpirisk": { + "name": "ØVELSE EMPIRISK", + "personId": "25884699358", + "userId": 1424054, + "partyUuid": "f9b2750f-f2aa-442c-91b7-418e2f627a8b", + "partyId": 51443447 + }, + "hakkeDyr": { + "name": "HAKKE DYR", + "personId": "29917997339", + "userId": 1424053, + "partyUuid": "07336d43-1f0e-40a8-a02b-2c6019013cc7", + "partyId": 51015472 + }, + "spesifikkSmaragd": { + "name": "SPESIFIKK SMARAGD", + "personId": "05869598129", + "userId": 1416991, + "partyUuid": "6971e33b-59c2-4605-8bdb-7ce3257fd1c7", + "partyId": 50826949 + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/at22.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/at22.json new file mode 100644 index 00000000..9702ccb7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/at22.json @@ -0,0 +1,32 @@ +{ + "env": "at22", + "app": "authz-bruno-instancedelegation", + "instanceid": "1cc971b6-c518-43ab-9345-21daab7e919e", + "org1": { + "orgno": "310438707", + "partyid": 51350052, + "partyuuid": "f200a9cb-31ce-4ed6-aad3-ed08b3cbbeee", + "dagl": { + "pid": "22855296954", + "lastname": "LARM", + "userid": 20012043, + "partyid": 50717658, + "partyuuid": "24425b64-9d4d-4bf6-8ba1-a33e58882a4e" + } + }, + "org2": { + "orgno": "405002701", + "partyuuid": "60610979-39fe-4997-90da-03069736d75d" + }, + "person1": { + "pid": "23862849957", + "userid": 20002641, + "lastname": "FAKTURA", + "partyid": 50020219, + "partyuuid": "a7459193-ae52-4550-871b-42916e6a1778" + }, + "person2": { + "pid": "29907329133", + "partyuuid": "b35ba3e9-6c73-410c-abd8-4e0205837f88" + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/tt02.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/tt02.json new file mode 100644 index 00000000..7345aabb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/instance-delegation/tt02.json @@ -0,0 +1,32 @@ +{ + "env": "tt02", + "app": "authz-bruno-instancedelegation", + "instanceid": "1cc971b6-c518-43ab-9345-21daab7e919e", + "org1": { + "orgno": "310438707", + "partyid": 51563583, + "partyuuid": "7df033f9-9d72-42c7-a2d8-9533d925ddc5", + "dagl": { + "pid": "22855296954", + "lastname": "LARM", + "userid": 1278314, + "partyid": 50783137, + "partyuuid": "a39359de-f1d2-4dc7-b2ba-f9841ea1a799" + } + }, + "org2": { + "orgno": "405002701", + "partyuuid": "60610979-39fe-4997-90da-03069736d75d" + }, + "person1": { + "pid": "23862849957", + "userid": 91561, + "lastname": "FAKTURA", + "partyid": 50041694, + "partyuuid": "9e5eeb84-dd37-4d74-8862-27e96f58f29b" + }, + "person2": { + "pid": "29917329042", + "partyuuid": "b35ba3e9-6c73-410c-abd8-4e0205837f88" + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at21testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at21testdata.json new file mode 100644 index 00000000..f99b8668 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at21testdata.json @@ -0,0 +1,37 @@ +{ + "env": "at21", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": 50079380, + "dagl": { + "pid":"21025400167", + "userid": 20004475, + "partyid": 50012796 + }, + "hadm": { + "pid": "17048001742", + "userid": 20003092, + "partyid": 50012941 + }, + "apiadm": { + "pid": "18036000194", + "userid": 20003823, + "partyid": 50009383 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50079370, + "dagl": { + "pid": "26013000394", + "userid": 20003812, + "partyid": 50012091 + } + }, + "digdir": { + "orgno": "991825827", + "partyid": 50088610 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at22testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at22testdata.json new file mode 100644 index 00000000..cf810ce6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at22testdata.json @@ -0,0 +1,58 @@ +{ + "env": "at22", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": 50067258, + "dagl": { + "pid":"21025400167", + "userid": 20004896, + "partyid": 50020295 + }, + "hadm": { + "pid": "17048001742", + "userid": 20003595, + "partyid": 50020440 + }, + "apiadm": { + "pid": "18036000194", + "userid": 20004282, + "partyid": 50009383 + }, + "tilg": { + "pid": "19856499459", + "userid": 20012825, + "partyid": 50465571 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50066506, + "dagl": { + "pid": "26013000394", + "userid": 20004270, + "partyid": 50019590 + } + }, + "org3": { + "orgno": "312822881", + "partyid": 51423446, + "dagl": { + "pid": "47827602783", + "lastname": "ELEV", + "userid": 20012697, + "partyid": 510247625 + }, + "tilg": { + "pid":"05859399586", + "lastname": "DESIMETER", + "userid": 20012650, + "partyid": 50592431 + } + }, + "digdir": { + "orgno": "991825827", + "partyid": 50088610 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at23testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at23testdata.json new file mode 100644 index 00000000..cee5b7bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at23testdata.json @@ -0,0 +1,37 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": 50024759, + "dagl": { + "pid":"21025400167", + "userid": 20002359, + "partyid": 50012796 + }, + "hadm": { + "pid": "17048001742", + "userid": 20003618, + "partyid": 50012941 + }, + "apiadm": { + "pid": "18036000194", + "userid": 20003412, + "partyid": 50009383 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50024778, + "dagl": { + "pid": "26013000394", + "userid": 20002644, + "partyid": 50012091 + } + }, + "digdir": { + "orgno": "991825827", + "partyid": 50004483 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at24testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at24testdata.json new file mode 100644 index 00000000..c5f46a11 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/at24testdata.json @@ -0,0 +1,37 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": 50024756, + "dagl": { + "pid":"21025400167", + "userid": 20014526, + "partyid": 50012796 + }, + "hadm": { + "pid": "17048001742", + "userid": 20013232, + "partyid": 50012941 + }, + "apiadm": { + "pid": "18036000194", + "userid": 20013942, + "partyid": 50009383 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50024778, + "dagl": { + "pid": "26013000394", + "userid": 20013938, + "partyid": 50012091 + } + }, + "digdir": { + "orgno": "991825827", + "partyid": 50040763 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/tt02testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/tt02testdata.json new file mode 100644 index 00000000..88b45e3b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/maskinportenschema/tt02testdata.json @@ -0,0 +1,53 @@ +{ + "env": "tt02", + "org": "ttd", + "app": "apps-test-undeploy", + "org1": { + "orgno": "810414782", + "partyid": 50189353, + "dagl": { + "pid":"21025400167", + "userid": 92356, + "partyid": 50077669 + }, + "hadm": { + "pid": "17048001742", + "userid": 92095, + "partyid": 50063278 + }, + "apiadm": { + "pid": "18036000275", + "userid": 92147, + "partyid": 50066592 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50189988, + "dagl": { + "pid": "26013000394", + "userid": 92630, + "partyid": 50096367 + } + }, + "org3": { + "orgno": "312822881", + "partyid": 51636963, + "dagl": { + "pid": "47827602783", + "lastname": "ELEV", + "userid": 1420963, + "partyid": 51275190 + }, + "tilg": { + "pid":"05859399586", + "lastname": "DESIMETER", + "userid": 1420959, + "partyid": 50553001 + } + }, + "digdir": { + "orgno": "991825827", + "partyid": 50167512 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at21testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at21testdata.json new file mode 100644 index 00000000..874be1a6 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at21testdata.json @@ -0,0 +1,27 @@ +{ + "env": "at21", + "org": "ttd", + "app": "apps-test", + "servicecode": "2802", + "serviceeditioncode": "3", + "org1": { + "orgno": "310438707", + "partyid": 51350052, + "dagl": { + "pid":"22855296954", + "lastname": "LARM", + "userid": 20012043, + "partyid": 50717658 + } + }, + "org2": { + "orgno": "313818608", + "partyid": 51658512, + "dagl": { + "pid": "02856099884", + "lastname": "ALKOVE", + "userid": 20012044, + "partyid": 51138305 + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at22testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at22testdata.json new file mode 100644 index 00000000..0af2c192 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at22testdata.json @@ -0,0 +1,56 @@ +{ + "env": "at22", + "org": "ttd", + "app": "apps-test-tba", + "servicecode": "2802", + "serviceeditioncode": "3", + "resource": "devtest_gar_bruno-gar", + "org1": { + "orgno": "310438707", + "partyid": 51350052, + "dagl": { + "pid":"22855296954", + "lastname": "LARM", + "userid": 20012043, + "partyid": 50717658 + }, + "meda": { + "pid":"18868496661", + "lastname": "BALL", + "userid": 20012682, + "partyid": 50861065 + } + }, + "org2": { + "orgno": "313818608", + "partyid": 51658512, + "dagl": { + "pid": "02856099884", + "lastname": "ALKOVE", + "userid": 20012044, + "partyid": 51138305 + } + }, + "org3": { + "orgno": "312822881", + "partyid": 51423446, + "dagl": { + "pid": "47827602783", + "lastname": "ELEV", + "userid": 20012697, + "partyid": 51024762 + }, + "tilg": { + "pid":"05859399586", + "lastname": "DESIMETER", + "userid": 20012650, + "partyid": 50592431 + } + }, + "randomUser": { + "pid": "12896198376", + "lastname": "KLOSETT", + "userid": 20012655, + "partyid": 50146491 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at23testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at23testdata.json new file mode 100644 index 00000000..ac86aaae --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at23testdata.json @@ -0,0 +1,27 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "servicecode": "2802", + "serviceeditioncode": "3", + "org1": { + "orgno": "310438707", + "partyid": 51224780, + "dagl": { + "pid":"22855296954", + "lastname": "LARM", + "userid": 20020373, + "partyid": 50810451 + } + }, + "org2": { + "orgno": "313818608", + "partyid": 51534400, + "dagl": { + "pid": "02856099884", + "lastname": "ALKOVE", + "userid": 20020374, + "partyid": 50620311 + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at24testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at24testdata.json new file mode 100644 index 00000000..2336f2e3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/at24testdata.json @@ -0,0 +1,27 @@ +{ + "env": "at24", + "org": "ttd", + "app": "apps-test", + "servicecode": "2802", + "serviceeditioncode": "3", + "org1": { + "orgno": "310438707", + "partyid": 51312064, + "dagl": { + "pid":"22855296954", + "lastname": "LARM", + "userid": 20020118, + "partyid": 50669123 + } + }, + "org2": { + "orgno": "313818608", + "partyid": 51620367, + "dagl": { + "pid": "02856099884", + "lastname": "ALKOVE", + "userid": 20020119, + "partyid": 51101871 + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/localtestdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/localtestdata.json new file mode 100644 index 00000000..52c1ca2b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/localtestdata.json @@ -0,0 +1,31 @@ +{ + "env": "at22", + "org": "ttd", + "app": "apps-test", + "servicecode": "2802", + "serviceeditioncode": "3", + "resource": "", + "org1": { + "orgno": "810414782", + "partyid": 50067258, + "dagl": { + "pid":"21025400167", + "userid": 20004896, + "partyid": 50020295 + }, + "hadm": { + "pid": "17048001742", + "userid": 20003595, + "partyid": 50020440 + } + }, + "org2": { + "orgno": "910049356", + "partyid": 50066506, + "dagl": { + "pid": "26013000394", + "userid": 20004270, + "partyid": 50019590 + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/tt02testdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/tt02testdata.json new file mode 100644 index 00000000..be7ddf99 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/rights-delegations/tt02testdata.json @@ -0,0 +1,56 @@ +{ + "env": "tt02", + "org": "ttd", + "app": "apps-test-undeploy", + "servicecode": "2802", + "serviceeditioncode": "2203", + "resource": "devtest_gar_bruno-gar", + "org1": { + "orgno": "310438707", + "partyid": 51563583, + "dagl": { + "pid":"22855296954", + "lastname": "LARM", + "userid": 1278314, + "partyid": 50783137 + }, + "meda": { + "pid":"18868496661", + "lastname": "BALL", + "userid": 1420961, + "partyid": 51054789 + } + }, + "org2": { + "orgno": "313818608", + "partyid": 51871883, + "dagl": { + "pid": "02856099884", + "lastname": "ALKOVE", + "userid": 1278315, + "partyid": 51386822 + } + }, + "org3": { + "orgno": "312822881", + "partyid": 51636963, + "dagl": { + "pid": "47827602783", + "lastname": "ELEV", + "userid": 1420963, + "partyid": 51275190 + }, + "tilg": { + "pid":"05859399586", + "lastname": "DESIMETER", + "userid": 1420959, + "partyid": 50553001 + } + }, + "randomUser": { + "pid": "12896198376", + "lastname": "KLOSETT", + "userid": 1420960, + "partyid": 51032967 + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/sharedtestdata.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/sharedtestdata.json new file mode 100644 index 00000000..ea7b14e2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/Testdata/sharedtestdata.json @@ -0,0 +1,26 @@ +{ + "scopes": { + "read": "altinn:instances:read", + "k6Read": "test:am/k6.read" + }, + "auth_scopes": { + "read": "altinn:instances:read", + "maskinportenAdmin": "altinn:maskinporten/delegations.admin", + "authorizedParties": "altinn:accessmanagement/authorizedparties", + "authorizedPartiesResourceOwner": "altinn:accessmanagement/authorizedparties.resourceowner", + "authorizedPartiesAdmin": "altinn:accessmanagement/authorizedparties.admin" + }, + "authTokenType": { + "personal": "Personal", + "enterprise": "Enterprise", + "enterpriseUser": "EnterpriseUser", + "platformAccess": "PlatformAccess" + }, + "serviceOwners": { + "ttd": + { + "org": "ttd", + "orgno": "991825827" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/bruno.json b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/bruno.json new file mode 100644 index 00000000..df88f70c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "Altinn.AccessManagement", + "type": "collection", + "presets": { + "requestType": "http", + "requestUrl": "{{baseUrl}}/accessmanagement/api/v1" + } +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/collection.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/collection.bru new file mode 100644 index 00000000..60cf6ba2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/collection.bru @@ -0,0 +1,45 @@ +auth { + mode: bearer +} + +auth:bearer { + token: {{bearerToken}} +} + +script:pre-request { + const testTokenGenerator = require("./TestToolsTokenGenerator.js"); +} + +script:post-response { + // Reset request vars so auth token data does not bleed between requests. + // Probably better ways of doing this? + bru.setVar("auth_tokenType", null); + bru.setVar("auth_userId", null); + bru.setVar("auth_partyId", null); + bru.setVar("auth_ssn", null); + bru.setVar("auth_scopes", null); + bru.setVar("auth_org", null); + bru.setVar("auth_orgNo", null); + bru.setVar("auth_username", null); + bru.setVar("bearerToken", null); +} + +docs { + Dokumentasjon havner i collection.bru filen i rotmappa. + + # Støtter markdown + Ja, det gjør det! + + ## Undertittel + Her er en *undertittel*. + + ### under-undertittel + Her er en **under-undertittel**. + + ### Bullet points + * bullet point 1 + * bullet point 2 + - bullet point 3 + - bullet point 4 + +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT22.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT22.bru new file mode 100644 index 00000000..043bcfa4 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT22.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.at22.altinn.cloud + tokenEnv: at22 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} + apimSubscriptionKey: {{process.env.AT22_APIM_SUBSCRIPTION_KEY}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT23.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT23.bru new file mode 100644 index 00000000..c8d10c49 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT23.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.at23.altinn.cloud + tokenEnv: at23 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} + apimSubscriptionKey: {{process.env.AT23_APIM_SUBSCRIPTION_KEY}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT24.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT24.bru new file mode 100644 index 00000000..05dc4919 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/AT24.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.at24.altinn.cloud + tokenEnv: at24 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} + apimSubscriptionKey: {{process.env.AT24_APIM_SUBSCRIPTION_KEY}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/DEV.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/DEV.bru new file mode 100644 index 00000000..57faf8d2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/DEV.bru @@ -0,0 +1,6 @@ +vars { + baseUrl: http://localhost:5117 + tokenEnv: at22 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/PROD.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/PROD.bru new file mode 100644 index 00000000..6d620ca7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/PROD.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.altinn.no +} +vars:secret [ + ProdToken, + apimSubscriptionKey +] diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/TT02.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/TT02.bru new file mode 100644 index 00000000..412001ce --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/TT02.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.tt02.altinn.no + tokenEnv: tt02 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} + apimSubscriptionKey: {{process.env.TT02_APIM_SUBSCRIPTION_KEY}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/YT01.bru b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/YT01.bru new file mode 100644 index 00000000..9eeb2bb2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Bruno/Altinn.AccessManagement/environments/YT01.bru @@ -0,0 +1,7 @@ +vars { + baseUrl: https://platform.yt01.altinn.cloud + tokenEnv: at22 + tokenBasicAuthUser: {{process.env.TOKEN_BASIC_AUTH_USER}} + tokenBasicAuthPw: {{process.env.TOKEN_BASIC_AUTH_PW}} + apimSubscriptionKey: {{process.env.YT01_APIM_SUBSCRIPTION_KEY}} +} diff --git a/src/apps/Altinn.AccessManagement/test/Directory.Build.props b/src/apps/Altinn.AccessManagement/test/Directory.Build.props new file mode 100644 index 00000000..b264d151 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + true + true + + + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/.eslintrc.json b/src/apps/Altinn.AccessManagement/test/K6/.eslintrc.json new file mode 100644 index 00000000..2dab5e6a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.eslintrc.json @@ -0,0 +1,26 @@ +{ + "globals": { + "__ENV": "readonly" + }, + "parser": "@babel/eslint-parser", + "parserOptions": { + "requireConfigFile": false + }, + "ignorePatterns": ["src/data", "src/reports"], + "rules": { + "import/no-unresolved": "off", + "no-restricted-globals": "off", + "import/extensions": "off", + "eol-last": "error", + "indent": ["warn", 2, { "SwitchCase": 1 }], + "quotes": [ + "warn", + "single", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ], + "semi": ["warn", "always", { "omitLastInOneLineBlock": true }] + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/.gitignore b/src/apps/Altinn.AccessManagement/test/K6/.gitignore new file mode 100644 index 00000000..e7c266d7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.gitignore @@ -0,0 +1,22 @@ +**/data/*.txt +**/data/users*.json +**/data/*.csv +**/data/xml*.xml + +#Junit reports +**/reports/ + +#Logs +**/logs/ + +#Dependency directories +node_modules/ + +#https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored +/.pnp.* +/.yarn/* +!/.yarn/patches +!/.yarn/plugins +!/.yarn/releases +!/.yarn/sdks +!/.yarn/versions diff --git a/src/apps/Altinn.AccessManagement/test/K6/.prettierrc b/src/apps/Altinn.AccessManagement/test/K6/.prettierrc new file mode 100644 index 00000000..996868e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.prettierrc @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "trailingComma": "all", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "printWidth": 160 +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs b/src/apps/Altinn.AccessManagement/test/K6/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs new file mode 100644 index 00000000..1584885e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs @@ -0,0 +1,364 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { + name: "@yarnpkg/plugin-interactive-tools", + factory: function (require) { + var plugin=(()=>{var PR=Object.create,J1=Object.defineProperty,MR=Object.defineProperties,FR=Object.getOwnPropertyDescriptor,LR=Object.getOwnPropertyDescriptors,RR=Object.getOwnPropertyNames,hh=Object.getOwnPropertySymbols,NR=Object.getPrototypeOf,Z4=Object.prototype.hasOwnProperty,aD=Object.prototype.propertyIsEnumerable;var dD=(i,u,f)=>u in i?J1(i,u,{enumerable:!0,configurable:!0,writable:!0,value:f}):i[u]=f,dt=(i,u)=>{for(var f in u||(u={}))Z4.call(u,f)&&dD(i,f,u[f]);if(hh)for(var f of hh(u))aD.call(u,f)&&dD(i,f,u[f]);return i},zn=(i,u)=>MR(i,LR(u)),BR=i=>J1(i,"__esModule",{value:!0});var Si=(i,u)=>{var f={};for(var c in i)Z4.call(i,c)&&u.indexOf(c)<0&&(f[c]=i[c]);if(i!=null&&hh)for(var c of hh(i))u.indexOf(c)<0&&aD.call(i,c)&&(f[c]=i[c]);return f};var Me=(i,u)=>()=>(u||i((u={exports:{}}).exports,u),u.exports),jR=(i,u)=>{for(var f in u)J1(i,f,{get:u[f],enumerable:!0})},UR=(i,u,f)=>{if(u&&typeof u=="object"||typeof u=="function")for(let c of RR(u))!Z4.call(i,c)&&c!=="default"&&J1(i,c,{get:()=>u[c],enumerable:!(f=FR(u,c))||f.enumerable});return i},Er=i=>UR(BR(J1(i!=null?PR(NR(i)):{},"default",i&&i.__esModule&&"default"in i?{get:()=>i.default,enumerable:!0}:{value:i,enumerable:!0})),i);var ey=Me((YH,pD)=>{"use strict";var hD=Object.getOwnPropertySymbols,qR=Object.prototype.hasOwnProperty,zR=Object.prototype.propertyIsEnumerable;function WR(i){if(i==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(i)}function HR(){try{if(!Object.assign)return!1;var i=new String("abc");if(i[5]="de",Object.getOwnPropertyNames(i)[0]==="5")return!1;for(var u={},f=0;f<10;f++)u["_"+String.fromCharCode(f)]=f;var c=Object.getOwnPropertyNames(u).map(function(t){return u[t]});if(c.join("")!=="0123456789")return!1;var g={};return"abcdefghijklmnopqrst".split("").forEach(function(t){g[t]=t}),Object.keys(Object.assign({},g)).join("")==="abcdefghijklmnopqrst"}catch(t){return!1}}pD.exports=HR()?Object.assign:function(i,u){for(var f,c=WR(i),g,t=1;t{"use strict";var ty=ey(),as=typeof Symbol=="function"&&Symbol.for,Q1=as?Symbol.for("react.element"):60103,bR=as?Symbol.for("react.portal"):60106,GR=as?Symbol.for("react.fragment"):60107,VR=as?Symbol.for("react.strict_mode"):60108,YR=as?Symbol.for("react.profiler"):60114,$R=as?Symbol.for("react.provider"):60109,KR=as?Symbol.for("react.context"):60110,XR=as?Symbol.for("react.forward_ref"):60112,JR=as?Symbol.for("react.suspense"):60113,QR=as?Symbol.for("react.memo"):60115,ZR=as?Symbol.for("react.lazy"):60116,mD=typeof Symbol=="function"&&Symbol.iterator;function Z1(i){for(var u="https://reactjs.org/docs/error-decoder.html?invariant="+i,f=1;fmh.length&&mh.push(i)}function uy(i,u,f,c){var g=typeof i;(g==="undefined"||g==="boolean")&&(i=null);var t=!1;if(i===null)t=!0;else switch(g){case"string":case"number":t=!0;break;case"object":switch(i.$$typeof){case Q1:case bR:t=!0}}if(t)return f(c,i,u===""?"."+sy(i,0):u),1;if(t=0,u=u===""?".":u+":",Array.isArray(i))for(var C=0;C{"use strict";kD.exports=xD()});var AD=Me((ga,e2)=>{(function(){var i,u="4.17.21",f=200,c="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",g="Expected a function",t="Invalid `variable` option passed into `_.template`",C="__lodash_hash_undefined__",A=500,x="__lodash_placeholder__",D=1,L=2,N=4,j=1,$=2,h=1,re=2,ce=4,Q=8,oe=16,Se=32,me=64,De=128,J=256,Te=512,Oe=30,Le="...",ot=800,ct=16,Ue=1,be=2,At=3,Ot=1/0,Nt=9007199254740991,Je=17976931348623157e292,V=0/0,ne=4294967295,ge=ne-1,Z=ne>>>1,Ae=[["ary",De],["bind",h],["bindKey",re],["curry",Q],["curryRight",oe],["flip",Te],["partial",Se],["partialRight",me],["rearg",J]],at="[object Arguments]",it="[object Array]",Ft="[object AsyncFunction]",jt="[object Boolean]",hn="[object Date]",Un="[object DOMException]",Jt="[object Error]",Yt="[object Function]",cr="[object GeneratorFunction]",w="[object Map]",pt="[object Number]",Mn="[object Null]",Bn="[object Object]",Xn="[object Promise]",vr="[object Proxy]",gr="[object RegExp]",r0="[object Set]",Ci="[object String]",yo="[object Symbol]",Ds="[object Undefined]",Mu="[object WeakMap]",Gf="[object WeakSet]",iu="[object ArrayBuffer]",ou="[object DataView]",ol="[object Float32Array]",ul="[object Float64Array]",Es="[object Int8Array]",Uo="[object Int16Array]",sl="[object Int32Array]",Ss="[object Uint8Array]",Cs="[object Uint8ClampedArray]",Ti="[object Uint16Array]",Fu="[object Uint32Array]",ll=/\b__p \+= '';/g,fl=/\b(__p \+=) '' \+/g,cl=/(__e\(.*?\)|\b__t\)) \+\n'';/g,al=/&(?:amp|lt|gt|quot|#39);/g,Ui=/[&<>"']/g,Mr=RegExp(al.source),Ac=RegExp(Ui.source),of=/<%-([\s\S]+?)%>/g,Ts=/<%([\s\S]+?)%>/g,xs=/<%=([\s\S]+?)%>/g,dl=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,qi=/^\w*$/,qo=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,kr=/[\\^$.*+?()[\]{}|]/g,Fr=RegExp(kr.source),si=/^\s+/,H0=/\s/,b0=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Bt=/\{\n\/\* \[wrapped with (.+)\] \*/,Lu=/,? & /,c0=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Ru=/[()=,{}\[\]\/\s]/,ks=/\\(\\)?/g,As=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,uu=/\w*$/,wo=/^[-+]0x[0-9a-f]+$/i,zo=/^0b[01]+$/i,Os=/^\[object .+?Constructor\]$/,Is=/^0o[0-7]+$/i,uf=/^(?:0|[1-9]\d*)$/,_n=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Nu=/($^)/,Wo=/['\n\r\u2028\u2029\\]/g,su="\\ud800-\\udfff",Ps="\\u0300-\\u036f",pl="\\ufe20-\\ufe2f",Vf="\\u20d0-\\u20ff",hl=Ps+pl+Vf,Bu="\\u2700-\\u27bf",ju="a-z\\xdf-\\xf6\\xf8-\\xff",sf="\\xac\\xb1\\xd7\\xf7",ro="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",Ms="\\u2000-\\u206f",ml=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Uu="A-Z\\xc0-\\xd6\\xd8-\\xde",G0="\\ufe0e\\ufe0f",Fs=sf+ro+Ms+ml,tt="['\u2019]",zi="["+su+"]",lu="["+Fs+"]",Ho="["+hl+"]",O0="\\d+",vl="["+Bu+"]",gl="["+ju+"]",fu="[^"+su+Fs+O0+Bu+ju+Uu+"]",_l="\\ud83c[\\udffb-\\udfff]",Sn="(?:"+Ho+"|"+_l+")",gt="[^"+su+"]",en="(?:\\ud83c[\\udde6-\\uddff]){2}",I0="[\\ud800-\\udbff][\\udc00-\\udfff]",li="["+Uu+"]",qu="\\u200d",Wi="(?:"+gl+"|"+fu+")",zu="(?:"+li+"|"+fu+")",Wu="(?:"+tt+"(?:d|ll|m|re|s|t|ve))?",Ls="(?:"+tt+"(?:D|LL|M|RE|S|T|VE))?",fi=Sn+"?",e0="["+G0+"]?",io="(?:"+qu+"(?:"+[gt,en,I0].join("|")+")"+e0+fi+")*",D0="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Do="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",i0=e0+fi+io,Rs="(?:"+[vl,en,I0].join("|")+")"+i0,a0="(?:"+[gt+Ho+"?",Ho,en,I0,zi].join("|")+")",Hu=RegExp(tt,"g"),V0=RegExp(Ho,"g"),bu=RegExp(_l+"(?="+_l+")|"+a0+i0,"g"),Ns=RegExp([li+"?"+gl+"+"+Wu+"(?="+[lu,li,"$"].join("|")+")",zu+"+"+Ls+"(?="+[lu,li+Wi,"$"].join("|")+")",li+"?"+Wi+"+"+Wu,li+"+"+Ls,Do,D0,O0,Rs].join("|"),"g"),bo=RegExp("["+qu+su+hl+G0+"]"),P0=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,ln=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],lf=-1,nr={};nr[ol]=nr[ul]=nr[Es]=nr[Uo]=nr[sl]=nr[Ss]=nr[Cs]=nr[Ti]=nr[Fu]=!0,nr[at]=nr[it]=nr[iu]=nr[jt]=nr[ou]=nr[hn]=nr[Jt]=nr[Yt]=nr[w]=nr[pt]=nr[Bn]=nr[gr]=nr[r0]=nr[Ci]=nr[Mu]=!1;var rr={};rr[at]=rr[it]=rr[iu]=rr[ou]=rr[jt]=rr[hn]=rr[ol]=rr[ul]=rr[Es]=rr[Uo]=rr[sl]=rr[w]=rr[pt]=rr[Bn]=rr[gr]=rr[r0]=rr[Ci]=rr[yo]=rr[Ss]=rr[Cs]=rr[Ti]=rr[Fu]=!0,rr[Jt]=rr[Yt]=rr[Mu]=!1;var Go={\u00C0:"A",\u00C1:"A",\u00C2:"A",\u00C3:"A",\u00C4:"A",\u00C5:"A",\u00E0:"a",\u00E1:"a",\u00E2:"a",\u00E3:"a",\u00E4:"a",\u00E5:"a",\u00C7:"C",\u00E7:"c",\u00D0:"D",\u00F0:"d",\u00C8:"E",\u00C9:"E",\u00CA:"E",\u00CB:"E",\u00E8:"e",\u00E9:"e",\u00EA:"e",\u00EB:"e",\u00CC:"I",\u00CD:"I",\u00CE:"I",\u00CF:"I",\u00EC:"i",\u00ED:"i",\u00EE:"i",\u00EF:"i",\u00D1:"N",\u00F1:"n",\u00D2:"O",\u00D3:"O",\u00D4:"O",\u00D5:"O",\u00D6:"O",\u00D8:"O",\u00F2:"o",\u00F3:"o",\u00F4:"o",\u00F5:"o",\u00F6:"o",\u00F8:"o",\u00D9:"U",\u00DA:"U",\u00DB:"U",\u00DC:"U",\u00F9:"u",\u00FA:"u",\u00FB:"u",\u00FC:"u",\u00DD:"Y",\u00FD:"y",\u00FF:"y",\u00C6:"Ae",\u00E6:"ae",\u00DE:"Th",\u00FE:"th",\u00DF:"ss",\u0100:"A",\u0102:"A",\u0104:"A",\u0101:"a",\u0103:"a",\u0105:"a",\u0106:"C",\u0108:"C",\u010A:"C",\u010C:"C",\u0107:"c",\u0109:"c",\u010B:"c",\u010D:"c",\u010E:"D",\u0110:"D",\u010F:"d",\u0111:"d",\u0112:"E",\u0114:"E",\u0116:"E",\u0118:"E",\u011A:"E",\u0113:"e",\u0115:"e",\u0117:"e",\u0119:"e",\u011B:"e",\u011C:"G",\u011E:"G",\u0120:"G",\u0122:"G",\u011D:"g",\u011F:"g",\u0121:"g",\u0123:"g",\u0124:"H",\u0126:"H",\u0125:"h",\u0127:"h",\u0128:"I",\u012A:"I",\u012C:"I",\u012E:"I",\u0130:"I",\u0129:"i",\u012B:"i",\u012D:"i",\u012F:"i",\u0131:"i",\u0134:"J",\u0135:"j",\u0136:"K",\u0137:"k",\u0138:"k",\u0139:"L",\u013B:"L",\u013D:"L",\u013F:"L",\u0141:"L",\u013A:"l",\u013C:"l",\u013E:"l",\u0140:"l",\u0142:"l",\u0143:"N",\u0145:"N",\u0147:"N",\u014A:"N",\u0144:"n",\u0146:"n",\u0148:"n",\u014B:"n",\u014C:"O",\u014E:"O",\u0150:"O",\u014D:"o",\u014F:"o",\u0151:"o",\u0154:"R",\u0156:"R",\u0158:"R",\u0155:"r",\u0157:"r",\u0159:"r",\u015A:"S",\u015C:"S",\u015E:"S",\u0160:"S",\u015B:"s",\u015D:"s",\u015F:"s",\u0161:"s",\u0162:"T",\u0164:"T",\u0166:"T",\u0163:"t",\u0165:"t",\u0167:"t",\u0168:"U",\u016A:"U",\u016C:"U",\u016E:"U",\u0170:"U",\u0172:"U",\u0169:"u",\u016B:"u",\u016D:"u",\u016F:"u",\u0171:"u",\u0173:"u",\u0174:"W",\u0175:"w",\u0176:"Y",\u0177:"y",\u0178:"Y",\u0179:"Z",\u017B:"Z",\u017D:"Z",\u017A:"z",\u017C:"z",\u017E:"z",\u0132:"IJ",\u0133:"ij",\u0152:"Oe",\u0153:"oe",\u0149:"'n",\u017F:"s"},Gu={"&":"&","<":"<",">":">",'"':""","'":"'"},yl={"&":"&","<":"<",">":">",""":'"',"'":"'"},cu={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Bs=parseFloat,Vu=parseInt,M0=typeof global=="object"&&global&&global.Object===Object&&global,au=typeof self=="object"&&self&&self.Object===Object&&self,Lr=M0||au||Function("return this")(),F=typeof ga=="object"&&ga&&!ga.nodeType&&ga,R=F&&typeof e2=="object"&&e2&&!e2.nodeType&&e2,U=R&&R.exports===F,H=U&&M0.process,fe=function(){try{var ae=R&&R.require&&R.require("util").types;return ae||H&&H.binding&&H.binding("util")}catch(Be){}}(),ue=fe&&fe.isArrayBuffer,de=fe&&fe.isDate,W=fe&&fe.isMap,ve=fe&&fe.isRegExp,Fe=fe&&fe.isSet,Ge=fe&&fe.isTypedArray;function K(ae,Be,Ie){switch(Ie.length){case 0:return ae.call(Be);case 1:return ae.call(Be,Ie[0]);case 2:return ae.call(Be,Ie[0],Ie[1]);case 3:return ae.call(Be,Ie[0],Ie[1],Ie[2])}return ae.apply(Be,Ie)}function xe(ae,Be,Ie,ht){for(var mt=-1,wn=ae==null?0:ae.length;++mt-1}function wt(ae,Be,Ie){for(var ht=-1,mt=ae==null?0:ae.length;++ht-1;);return Ie}function js(ae,Be){for(var Ie=ae.length;Ie--&&Qe(Be,ae[Ie],0)>-1;);return Ie}function Dl(ae,Be){for(var Ie=ae.length,ht=0;Ie--;)ae[Ie]===Be&&++ht;return ht}var du=Cn(Go),Yu=Cn(Gu);function Us(ae){return"\\"+cu[ae]}function oo(ae,Be){return ae==null?i:ae[Be]}function Hi(ae){return bo.test(ae)}function qs(ae){return P0.test(ae)}function F0(ae){for(var Be,Ie=[];!(Be=ae.next()).done;)Ie.push(Be.value);return Ie}function Gr(ae){var Be=-1,Ie=Array(ae.size);return ae.forEach(function(ht,mt){Ie[++Be]=[mt,ht]}),Ie}function ir(ae,Be){return function(Ie){return ae(Be(Ie))}}function L0(ae,Be){for(var Ie=-1,ht=ae.length,mt=0,wn=[];++Ie-1}function Ju(a,p){var E=this.__data__,I=hf(E,a);return I<0?(++this.size,E.push([a,p])):E[I][1]=p,this}Z0.prototype.clear=df,Z0.prototype.delete=Ba,Z0.prototype.get=Oc,Z0.prototype.has=mu,Z0.prototype.set=Ju;function ei(a){var p=-1,E=a==null?0:a.length;for(this.clear();++p=p?a:p)),a}function vi(a,p,E,I,B,G){var te,se=p&D,Ee=p&L,$e=p&N;if(E&&(te=B?E(a,I,B,G):E(a)),te!==i)return te;if(!Jr(a))return a;var Ke=On(a);if(Ke){if(te=f1(a),!se)return Xr(a,te)}else{var nt=U0(a),Ct=nt==Yt||nt==cr;if(Eu(a))return Od(a,se);if(nt==Bn||nt==at||Ct&&!B){if(te=Ee||Ct?{}:zd(a),!se)return Ee?Zu(a,Wa(te,a)):j0(a,mf(te,a))}else{if(!rr[nt])return B?a:{};te=Wd(a,nt,se)}}G||(G=new co);var Gt=G.get(a);if(Gt)return Gt;G.set(a,te),kp(a)?a.forEach(function(dn){te.add(vi(dn,p,E,dn,a,G))}):Tp(a)&&a.forEach(function(dn,Yn){te.set(Yn,vi(dn,p,E,Yn,a,G))});var an=$e?Ee?Dn:r1:Ee?Yi:q0,qn=Ke?i:an(a);return je(qn||a,function(dn,Yn){qn&&(Yn=dn,dn=a[Yn]),xl(te,Yn,vi(dn,p,E,Yn,a,G))}),te}function Xf(a){var p=q0(a);return function(E){return Rc(E,a,p)}}function Rc(a,p,E){var I=E.length;if(a==null)return!I;for(a=$t(a);I--;){var B=E[I],G=p[B],te=a[B];if(te===i&&!(B in a)||!G(te))return!1}return!0}function Jf(a,p,E){if(typeof a!="function")throw new Yr(g);return wf(function(){a.apply(i,E)},p)}function ao(a,p,E,I){var B=-1,G=xt,te=!0,se=a.length,Ee=[],$e=p.length;if(!se)return Ee;E&&(p=lt(p,qr(E))),I?(G=wt,te=!1):p.length>=f&&(G=So,te=!1,p=new vu(p));e:for(;++BB?0:B+E),I=I===i||I>B?B:jn(I),I<0&&(I+=B),I=E>I?0:Ip(I);E0&&E(se)?p>1?k0(se,p-1,E,I,B):Rt(B,se):I||(B[B.length]=se)}return B}var v=ec(),m=ec(!0);function S(a,p){return a&&v(a,p,q0)}function O(a,p){return a&&m(a,p,q0)}function M(a,p){return st(p,function(E){return rs(a[E])})}function b(a,p){p=Gs(p,a);for(var E=0,I=p.length;a!=null&&Ep}function ut(a,p){return a!=null&&or.call(a,p)}function In(a,p){return a!=null&&p in $t(a)}function A0(a,p,E){return a>=kn(p,E)&&a=120&&Ke.length>=120)?new vu(te&&Ke):i}Ke=a[0];var nt=-1,Ct=se[0];e:for(;++nt-1;)se!==a&&C0.call(se,Ee,1),C0.call(a,Ee,1);return a}function jc(a,p){for(var E=a?p.length:0,I=E-1;E--;){var B=p[E];if(E==I||B!==G){var G=B;es(B)?C0.call(a,B,1):$a(a,B)}}return a}function Ga(a,p){return a+hu(Ai()*(p-a+1))}function Lm(a,p,E,I){for(var B=-1,G=wr(B0((p-a)/(E||1)),0),te=Ie(G);G--;)te[I?G:++B]=a,a+=E;return te}function Va(a,p){var E="";if(!a||p<1||p>Nt)return E;do p%2&&(E+=a),p=hu(p/2),p&&(a+=a);while(p);return E}function Wn(a,p){return m1(Gd(a,p,$i),a+"")}function wd(a){return Fc(Ef(a))}function Dd(a,p){var E=Ef(a);return Yc(E,mi(p,0,E.length))}function Ol(a,p,E,I){if(!Jr(a))return a;p=Gs(p,a);for(var B=-1,G=p.length,te=G-1,se=a;se!=null&&++BB?0:B+p),E=E>B?B:E,E<0&&(E+=B),B=p>E?0:E-p>>>0,p>>>=0;for(var G=Ie(B);++I>>1,te=a[G];te!==null&&!mo(te)&&(E?te<=p:te=f){var $e=p?null:bm(a);if($e)return Y0($e);te=!1,B=So,Ee=new vu}else Ee=p?[]:se;e:for(;++I=I?a:Oo(a,p,E)}var Ad=pu||function(a){return Lr.clearTimeout(a)};function Od(a,p){if(p)return a.slice();var E=a.length,I=Nr?Nr(E):new a.constructor(E);return a.copy(I),I}function Qa(a){var p=new a.constructor(a.byteLength);return new R0(p).set(new R0(a)),p}function jm(a,p){var E=p?Qa(a.buffer):a.buffer;return new a.constructor(E,a.byteOffset,a.byteLength)}function Um(a){var p=new a.constructor(a.source,uu.exec(a));return p.lastIndex=a.lastIndex,p}function qm(a){return Wr?$t(Wr.call(a)):{}}function Id(a,p){var E=p?Qa(a.buffer):a.buffer;return new a.constructor(E,a.byteOffset,a.length)}function Pd(a,p){if(a!==p){var E=a!==i,I=a===null,B=a===a,G=mo(a),te=p!==i,se=p===null,Ee=p===p,$e=mo(p);if(!se&&!$e&&!G&&a>p||G&&te&&Ee&&!se&&!$e||I&&te&&Ee||!E&&Ee||!B)return 1;if(!I&&!G&&!$e&&a=se)return Ee;var $e=E[I];return Ee*($e=="desc"?-1:1)}}return a.index-p.index}function gf(a,p,E,I){for(var B=-1,G=a.length,te=E.length,se=-1,Ee=p.length,$e=wr(G-te,0),Ke=Ie(Ee+$e),nt=!I;++se1?E[B-1]:i,te=B>2?E[2]:i;for(G=a.length>3&&typeof G=="function"?(B--,G):i,te&&Ii(E[0],E[1],te)&&(G=B<3?i:G,B=1),p=$t(p);++I-1?B[G?p[te]:te]:i}}function Rd(a){return yu(function(p){var E=p.length,I=E,B=Qn.prototype.thru;for(a&&p.reverse();I--;){var G=p[I];if(typeof G!="function")throw new Yr(g);if(B&&!te&&Gc(G)=="wrapper")var te=new Qn([],!0)}for(I=te?I:E;++I1&&er.reverse(),Ke&&Eese))return!1;var $e=G.get(a),Ke=G.get(p);if($e&&Ke)return $e==p&&Ke==a;var nt=-1,Ct=!0,Gt=E&$?new vu:i;for(G.set(a,p),G.set(p,a);++nt1?"& ":"")+p[I],p=p.join(E>2?", ":" "),a.replace(b0,`{ + /* [wrapped with `+p+`] */ + `)}function Xm(a){return On(a)||Ll(a)||!!(di&&a&&a[di])}function es(a,p){var E=typeof a;return p=p==null?Nt:p,!!p&&(E=="number"||E!="symbol"&&uf.test(a))&&a>-1&&a%1==0&&a0){if(++p>=ot)return arguments[0]}else p=0;return a.apply(i,arguments)}}function Yc(a,p){var E=-1,I=a.length,B=I-1;for(p=p===i?I:p;++E1?a[p-1]:i;return E=typeof E=="function"?(a.pop(),E):i,sp(a,E)});function fp(a){var p=z(a);return p.__chain__=!0,p}function cp(a,p){return p(a),a}function Kc(a,p){return p(a)}var Wv=yu(function(a){var p=a.length,E=p?a[0]:0,I=this.__wrapped__,B=function(G){return Hs(G,a)};return p>1||this.__actions__.length||!(I instanceof nn)||!es(E)?this.thru(B):(I=I.slice(E,+E+(p?1:0)),I.__actions__.push({func:Kc,args:[B],thisArg:i}),new Qn(I,this.__chain__).thru(function(G){return p&&!G.length&&G.push(i),G}))});function Hv(){return fp(this)}function bv(){return new Qn(this.value(),this.__chain__)}function Gv(){this.__values__===i&&(this.__values__=Op(this.value()));var a=this.__index__>=this.__values__.length,p=a?i:this.__values__[this.__index__++];return{done:a,value:p}}function Vv(){return this}function Yv(a){for(var p,E=this;E instanceof Or;){var I=Jd(E);I.__index__=0,I.__values__=i,p?B.__wrapped__=I:p=I;var B=I;E=E.__wrapped__}return B.__wrapped__=a,p}function Ml(){var a=this.__wrapped__;if(a instanceof nn){var p=a;return this.__actions__.length&&(p=new nn(this)),p=p.reverse(),p.__actions__.push({func:Kc,args:[g1],thisArg:i}),new Qn(p,this.__chain__)}return this.thru(g1)}function Fl(){return xd(this.__wrapped__,this.__actions__)}var Xc=_f(function(a,p,E){or.call(a,E)?++a[E]:ti(a,E,1)});function $v(a,p,E){var I=On(a)?rt:Nc;return E&&Ii(a,p,E)&&(p=i),I(a,cn(p,3))}function Kv(a,p){var E=On(a)?st:Qf;return E(a,cn(p,3))}var Xv=Ld(Qd),D1=Ld($c);function Jv(a,p){return k0(Jc(a,p),1)}function Qv(a,p){return k0(Jc(a,p),Ot)}function ap(a,p,E){return E=E===i?1:jn(E),k0(Jc(a,p),E)}function dp(a,p){var E=On(a)?je:$o;return E(a,cn(p,3))}function pp(a,p){var E=On(a)?Xe:kl;return E(a,cn(p,3))}var Zv=_f(function(a,p,E){or.call(a,E)?a[E].push(p):ti(a,E,[p])});function eg(a,p,E,I){a=Vi(a)?a:Ef(a),E=E&&!I?jn(E):0;var B=a.length;return E<0&&(E=wr(B+E,0)),ia(a)?E<=B&&a.indexOf(p,E)>-1:!!B&&Qe(a,p,E)>-1}var tg=Wn(function(a,p,E){var I=-1,B=typeof p=="function",G=Vi(a)?Ie(a.length):[];return $o(a,function(te){G[++I]=B?K(p,te,E):po(te,p,E)}),G}),hp=_f(function(a,p,E){ti(a,E,p)});function Jc(a,p){var E=On(a)?lt:vd;return E(a,cn(p,3))}function ng(a,p,E,I){return a==null?[]:(On(p)||(p=p==null?[]:[p]),E=I?i:E,On(E)||(E=E==null?[]:[E]),Oi(a,p,E))}var rg=_f(function(a,p,E){a[E?0:1].push(p)},function(){return[[],[]]});function mp(a,p,E){var I=On(a)?yn:bn,B=arguments.length<3;return I(a,cn(p,4),E,B,$o)}function ig(a,p,E){var I=On(a)?sn:bn,B=arguments.length<3;return I(a,cn(p,4),E,B,kl)}function og(a,p){var E=On(a)?st:Qf;return E(a,Zc(cn(p,3)))}function ug(a){var p=On(a)?Fc:wd;return p(a)}function sg(a,p,E){(E?Ii(a,p,E):p===i)?p=1:p=jn(p);var I=On(a)?Lc:Dd;return I(a,p)}function lg(a){var p=On(a)?Kf:Ao;return p(a)}function E1(a){if(a==null)return 0;if(Vi(a))return ia(a)?Rr(a):a.length;var p=U0(a);return p==w||p==r0?a.size:Zf(a).length}function fg(a,p,E){var I=On(a)?ar:Nm;return E&&Ii(a,p,E)&&(p=i),I(a,cn(p,3))}var cg=Wn(function(a,p){if(a==null)return[];var E=p.length;return E>1&&Ii(a,p[0],p[1])?p=[]:E>2&&Ii(p[0],p[1],p[2])&&(p=[p[0]]),Oi(a,k0(p,1),[])}),rc=Sl||function(){return Lr.Date.now()};function ag(a,p){if(typeof p!="function")throw new Yr(g);return a=jn(a),function(){if(--a<1)return p.apply(this,arguments)}}function vp(a,p,E){return p=E?i:p,p=a&&p==null?a.length:p,Lt(a,De,i,i,i,i,p)}function gp(a,p){var E;if(typeof p!="function")throw new Yr(g);return a=jn(a),function(){return--a>0&&(E=p.apply(this,arguments)),a<=1&&(p=i),E}}var S1=Wn(function(a,p,E){var I=h;if(E.length){var B=L0(E,An(S1));I|=Se}return Lt(a,I,p,E,B)}),_p=Wn(function(a,p,E){var I=h|re;if(E.length){var B=L0(E,An(_p));I|=Se}return Lt(p,I,a,E,B)});function C1(a,p,E){p=E?i:p;var I=Lt(a,Q,i,i,i,i,i,p);return I.placeholder=C1.placeholder,I}function yp(a,p,E){p=E?i:p;var I=Lt(a,oe,i,i,i,i,i,p);return I.placeholder=yp.placeholder,I}function wp(a,p,E){var I,B,G,te,se,Ee,$e=0,Ke=!1,nt=!1,Ct=!0;if(typeof a!="function")throw new Yr(g);p=Fo(p)||0,Jr(E)&&(Ke=!!E.leading,nt="maxWait"in E,G=nt?wr(Fo(E.maxWait)||0,p):G,Ct="trailing"in E?!!E.trailing:Ct);function Gt(f0){var Jo=I,Su=B;return I=B=i,$e=f0,te=a.apply(Su,Jo),te}function an(f0){return $e=f0,se=wf(Yn,p),Ke?Gt(f0):te}function qn(f0){var Jo=f0-Ee,Su=f0-$e,Zp=p-Jo;return nt?kn(Zp,G-Su):Zp}function dn(f0){var Jo=f0-Ee,Su=f0-$e;return Ee===i||Jo>=p||Jo<0||nt&&Su>=G}function Yn(){var f0=rc();if(dn(f0))return er(f0);se=wf(Yn,qn(f0))}function er(f0){return se=i,Ct&&I?Gt(f0):(I=B=i,te)}function vo(){se!==i&&Ad(se),$e=0,I=Ee=B=se=i}function Pi(){return se===i?te:er(rc())}function Mi(){var f0=rc(),Jo=dn(f0);if(I=arguments,B=this,Ee=f0,Jo){if(se===i)return an(Ee);if(nt)return Ad(se),se=wf(Yn,p),Gt(Ee)}return se===i&&(se=wf(Yn,p)),te}return Mi.cancel=vo,Mi.flush=Pi,Mi}var dg=Wn(function(a,p){return Jf(a,1,p)}),Dp=Wn(function(a,p,E){return Jf(a,Fo(p)||0,E)});function pg(a){return Lt(a,Te)}function Qc(a,p){if(typeof a!="function"||p!=null&&typeof p!="function")throw new Yr(g);var E=function(){var I=arguments,B=p?p.apply(this,I):I[0],G=E.cache;if(G.has(B))return G.get(B);var te=a.apply(this,I);return E.cache=G.set(B,te)||G,te};return E.cache=new(Qc.Cache||ei),E}Qc.Cache=ei;function Zc(a){if(typeof a!="function")throw new Yr(g);return function(){var p=arguments;switch(p.length){case 0:return!a.call(this);case 1:return!a.call(this,p[0]);case 2:return!a.call(this,p[0],p[1]);case 3:return!a.call(this,p[0],p[1],p[2])}return!a.apply(this,p)}}function ea(a){return gp(2,a)}var hg=Bm(function(a,p){p=p.length==1&&On(p[0])?lt(p[0],qr(cn())):lt(k0(p,1),qr(cn()));var E=p.length;return Wn(function(I){for(var B=-1,G=kn(I.length,E);++B=p}),Ll=_i(function(){return arguments}())?_i:function(a){return n0(a)&&or.call(a,"callee")&&!N0.call(a,"callee")},On=Ie.isArray,x1=ue?qr(ue):Re;function Vi(a){return a!=null&&na(a.length)&&!rs(a)}function l0(a){return n0(a)&&Vi(a)}function kg(a){return a===!0||a===!1||n0(a)&&Ye(a)==jt}var Eu=pi||W1,Ag=de?qr(de):Ce;function Og(a){return n0(a)&&a.nodeType===1&&!ic(a)}function Cp(a){if(a==null)return!0;if(Vi(a)&&(On(a)||typeof a=="string"||typeof a.splice=="function"||Eu(a)||Df(a)||Ll(a)))return!a.length;var p=U0(a);if(p==w||p==r0)return!a.size;if(nc(a))return!Zf(a).length;for(var E in a)if(or.call(a,E))return!1;return!0}function Ig(a,p){return ze(a,p)}function Pg(a,p,E){E=typeof E=="function"?E:i;var I=E?E(a,p):i;return I===i?ze(a,p,i,E):!!I}function k1(a){if(!n0(a))return!1;var p=Ye(a);return p==Jt||p==Un||typeof a.message=="string"&&typeof a.name=="string"&&!ic(a)}function Mg(a){return typeof a=="number"&&Br(a)}function rs(a){if(!Jr(a))return!1;var p=Ye(a);return p==Yt||p==cr||p==Ft||p==vr}function A1(a){return typeof a=="number"&&a==jn(a)}function na(a){return typeof a=="number"&&a>-1&&a%1==0&&a<=Nt}function Jr(a){var p=typeof a;return a!=null&&(p=="object"||p=="function")}function n0(a){return a!=null&&typeof a=="object"}var Tp=W?qr(W):on;function Fg(a,p){return a===p||sr(a,p,Nn(p))}function Lg(a,p,E){return E=typeof E=="function"?E:i,sr(a,p,Nn(p),E)}function Rg(a){return xp(a)&&a!=+a}function Ng(a){if(Zm(a))throw new mt(c);return mn(a)}function Bg(a){return a===null}function O1(a){return a==null}function xp(a){return typeof a=="number"||n0(a)&&Ye(a)==pt}function ic(a){if(!n0(a)||Ye(a)!=Bn)return!1;var p=uo(a);if(p===null)return!0;var E=or.call(p,"constructor")&&p.constructor;return typeof E=="function"&&E instanceof E&&bi.call(E)==af}var ra=ve?qr(ve):pr;function jg(a){return A1(a)&&a>=-Nt&&a<=Nt}var kp=Fe?qr(Fe):Hr;function ia(a){return typeof a=="string"||!On(a)&&n0(a)&&Ye(a)==Ci}function mo(a){return typeof a=="symbol"||n0(a)&&Ye(a)==yo}var Df=Ge?qr(Ge):Vn;function Ap(a){return a===i}function Ug(a){return n0(a)&&U0(a)==Mu}function qg(a){return n0(a)&&Ye(a)==Gf}var zg=bc(Ha),Wg=bc(function(a,p){return a<=p});function Op(a){if(!a)return[];if(Vi(a))return ia(a)?Jn(a):Xr(a);if(u0&&a[u0])return F0(a[u0]());var p=U0(a),E=p==w?Gr:p==r0?Y0:Ef;return E(a)}function is(a){if(!a)return a===0?a:0;if(a=Fo(a),a===Ot||a===-Ot){var p=a<0?-1:1;return p*Je}return a===a?a:0}function jn(a){var p=is(a),E=p%1;return p===p?E?p-E:p:0}function Ip(a){return a?mi(jn(a),0,ne):0}function Fo(a){if(typeof a=="number")return a;if(mo(a))return V;if(Jr(a)){var p=typeof a.valueOf=="function"?a.valueOf():a;a=Jr(p)?p+"":p}if(typeof a!="string")return a===0?a:+a;a=E0(a);var E=zo.test(a);return E||Is.test(a)?Vu(a.slice(2),E?2:8):wo.test(a)?V:+a}function oa(a){return yi(a,Yi(a))}function Hg(a){return a?mi(jn(a),-Nt,Nt):a===0?a:0}function yr(a){return a==null?"":ho(a)}var Pp=Io(function(a,p){if(nc(p)||Vi(p)){yi(p,q0(p),a);return}for(var E in p)or.call(p,E)&&xl(a,E,p[E])}),Mp=Io(function(a,p){yi(p,Yi(p),a)}),ua=Io(function(a,p,E,I){yi(p,Yi(p),a,I)}),bg=Io(function(a,p,E,I){yi(p,q0(p),a,I)}),Gg=yu(Hs);function Vg(a,p){var E=dr(a);return p==null?E:mf(E,p)}var Fp=Wn(function(a,p){a=$t(a);var E=-1,I=p.length,B=I>2?p[2]:i;for(B&&Ii(p[0],p[1],B)&&(I=1);++E1),G}),yi(a,Dn(a),E),I&&(E=vi(E,D|L|N,Gm));for(var B=p.length;B--;)$a(E,p[B]);return E});function l_(a,p){return Bp(a,Zc(cn(p)))}var f_=yu(function(a,p){return a==null?{}:Fm(a,p)});function Bp(a,p){if(a==null)return{};var E=lt(Dn(a),function(I){return[I]});return p=cn(p),yd(a,E,function(I,B){return p(I,B[0])})}function c_(a,p,E){p=Gs(p,a);var I=-1,B=p.length;for(B||(B=1,a=i);++Ip){var I=a;a=p,p=I}if(E||a%1||p%1){var B=Ai();return kn(a+B*(p-a+Bs("1e-"+((B+"").length-1))),p)}return Ga(a,p)}var __=yf(function(a,p,E){return p=p.toLowerCase(),a+(E?Wp(p):p)});function Wp(a){return L1(yr(a).toLowerCase())}function Hp(a){return a=yr(a),a&&a.replace(_n,du).replace(V0,"")}function y_(a,p,E){a=yr(a),p=ho(p);var I=a.length;E=E===i?I:mi(jn(E),0,I);var B=E;return E-=p.length,E>=0&&a.slice(E,B)==p}function M1(a){return a=yr(a),a&&Ac.test(a)?a.replace(Ui,Yu):a}function w_(a){return a=yr(a),a&&Fr.test(a)?a.replace(kr,"\\$&"):a}var D_=yf(function(a,p,E){return a+(E?"-":"")+p.toLowerCase()}),bp=yf(function(a,p,E){return a+(E?" ":"")+p.toLowerCase()}),E_=Fd("toLowerCase");function S_(a,p,E){a=yr(a),p=jn(p);var I=p?Rr(a):0;if(!p||I>=p)return a;var B=(p-I)/2;return Hc(hu(B),E)+a+Hc(B0(B),E)}function C_(a,p,E){a=yr(a),p=jn(p);var I=p?Rr(a):0;return p&&I>>0,E?(a=yr(a),a&&(typeof p=="string"||p!=null&&!ra(p))&&(p=ho(p),!p&&Hi(a))?Vs(Jn(a),0,E):a.split(p,E)):[]}var I_=yf(function(a,p,E){return a+(E?" ":"")+L1(p)});function P_(a,p,E){return a=yr(a),E=E==null?0:mi(jn(E),0,a.length),p=ho(p),a.slice(E,E+p.length)==p}function M_(a,p,E){var I=z.templateSettings;E&&Ii(a,p,E)&&(p=i),a=yr(a),p=ua({},p,I,n1);var B=ua({},p.imports,I.imports,n1),G=q0(B),te=Eo(B,G),se,Ee,$e=0,Ke=p.interpolate||Nu,nt="__p += '",Ct=X0((p.escape||Nu).source+"|"+Ke.source+"|"+(Ke===xs?As:Nu).source+"|"+(p.evaluate||Nu).source+"|$","g"),Gt="//# sourceURL="+(or.call(p,"sourceURL")?(p.sourceURL+"").replace(/\s/g," "):"lodash.templateSources["+ ++lf+"]")+` + `;a.replace(Ct,function(dn,Yn,er,vo,Pi,Mi){return er||(er=vo),nt+=a.slice($e,Mi).replace(Wo,Us),Yn&&(se=!0,nt+=`' + + __e(`+Yn+`) + + '`),Pi&&(Ee=!0,nt+=`'; + `+Pi+`; + __p += '`),er&&(nt+=`' + + ((__t = (`+er+`)) == null ? '' : __t) + + '`),$e=Mi+dn.length,dn}),nt+=`'; + `;var an=or.call(p,"variable")&&p.variable;if(!an)nt=`with (obj) { + `+nt+` + } + `;else if(Ru.test(an))throw new mt(t);nt=(Ee?nt.replace(ll,""):nt).replace(fl,"$1").replace(cl,"$1;"),nt="function("+(an||"obj")+`) { + `+(an?"":`obj || (obj = {}); + `)+"var __t, __p = ''"+(se?", __e = _.escape":"")+(Ee?`, __j = Array.prototype.join; + function print() { __p += __j.call(arguments, '') } + `:`; + `)+nt+`return __p + }`;var qn=$p(function(){return wn(G,Gt+"return "+nt).apply(i,te)});if(qn.source=nt,k1(qn))throw qn;return qn}function F_(a){return yr(a).toLowerCase()}function L_(a){return yr(a).toUpperCase()}function R_(a,p,E){if(a=yr(a),a&&(E||p===i))return E0(a);if(!a||!(p=ho(p)))return a;var I=Jn(a),B=Jn(p),G=wl(I,B),te=js(I,B)+1;return Vs(I,G,te).join("")}function F1(a,p,E){if(a=yr(a),a&&(E||p===i))return a.slice(0,ai(a)+1);if(!a||!(p=ho(p)))return a;var I=Jn(a),B=js(I,Jn(p))+1;return Vs(I,0,B).join("")}function N_(a,p,E){if(a=yr(a),a&&(E||p===i))return a.replace(si,"");if(!a||!(p=ho(p)))return a;var I=Jn(a),B=wl(I,Jn(p));return Vs(I,B).join("")}function B_(a,p){var E=Oe,I=Le;if(Jr(p)){var B="separator"in p?p.separator:B;E="length"in p?jn(p.length):E,I="omission"in p?ho(p.omission):I}a=yr(a);var G=a.length;if(Hi(a)){var te=Jn(a);G=te.length}if(E>=G)return a;var se=E-Rr(I);if(se<1)return I;var Ee=te?Vs(te,0,se).join(""):a.slice(0,se);if(B===i)return Ee+I;if(te&&(se+=Ee.length-se),ra(B)){if(a.slice(se).search(B)){var $e,Ke=Ee;for(B.global||(B=X0(B.source,yr(uu.exec(B))+"g")),B.lastIndex=0;$e=B.exec(Ke);)var nt=$e.index;Ee=Ee.slice(0,nt===i?se:nt)}}else if(a.indexOf(ho(B),se)!=se){var Ct=Ee.lastIndexOf(B);Ct>-1&&(Ee=Ee.slice(0,Ct))}return Ee+I}function Vp(a){return a=yr(a),a&&Mr.test(a)?a.replace(al,o0):a}var j_=yf(function(a,p,E){return a+(E?" ":"")+p.toUpperCase()}),L1=Fd("toUpperCase");function Yp(a,p,E){return a=yr(a),p=E?i:p,p===i?qs(a)?cf(a):d0(a):a.match(p)||[]}var $p=Wn(function(a,p){try{return K(a,i,p)}catch(E){return k1(E)?E:new mt(E)}}),U_=yu(function(a,p){return je(p,function(E){E=Xo(E),ti(a,E,S1(a[E],a))}),a});function Kp(a){var p=a==null?0:a.length,E=cn();return a=p?lt(a,function(I){if(typeof I[1]!="function")throw new Yr(g);return[E(I[0]),I[1]]}):[],Wn(function(I){for(var B=-1;++BNt)return[];var E=ne,I=kn(a,ne);p=cn(p),a-=ne;for(var B=ci(I,p);++E0||p<0)?new nn(E):(a<0?E=E.takeRight(-a):a&&(E=E.drop(a)),p!==i&&(p=jn(p),E=p<0?E.dropRight(-p):E.take(p-a)),E)},nn.prototype.takeRightWhile=function(a){return this.reverse().takeWhile(a).reverse()},nn.prototype.toArray=function(){return this.take(ne)},S(nn.prototype,function(a,p){var E=/^(?:filter|find|map|reject)|While$/.test(p),I=/^(?:head|last)$/.test(p),B=z[I?"take"+(p=="last"?"Right":""):p],G=I||/^find/.test(p);!B||(z.prototype[p]=function(){var te=this.__wrapped__,se=I?[1]:arguments,Ee=te instanceof nn,$e=se[0],Ke=Ee||On(te),nt=function(Yn){var er=B.apply(z,Rt([Yn],se));return I&&Ct?er[0]:er};Ke&&E&&typeof $e=="function"&&$e.length!=1&&(Ee=Ke=!1);var Ct=this.__chain__,Gt=!!this.__actions__.length,an=G&&!Ct,qn=Ee&&!Gt;if(!G&&Ke){te=qn?te:new nn(this);var dn=a.apply(te,se);return dn.__actions__.push({func:Kc,args:[nt],thisArg:i}),new Qn(dn,Ct)}return an&&qn?a.apply(this,se):(dn=this.thru(nt),an?I?dn.value()[0]:dn.value():dn)})}),je(["pop","push","shift","sort","splice","unshift"],function(a){var p=$r[a],E=/^(?:push|sort|unshift)$/.test(a)?"tap":"thru",I=/^(?:pop|shift)$/.test(a);z.prototype[a]=function(){var B=arguments;if(I&&!this.__chain__){var G=this.value();return p.apply(On(G)?G:[],B)}return this[E](function(te){return p.apply(On(te)?te:[],B)})}}),S(nn.prototype,function(a,p){var E=z[p];if(E){var I=E.name+"";or.call(bt,I)||(bt[I]=[]),bt[I].push({name:p,func:E})}}),bt[zc(i,re).name]=[{name:"wrapper",func:i}],nn.prototype.clone=s0,nn.prototype.reverse=t0,nn.prototype.value=g0,z.prototype.at=Wv,z.prototype.chain=Hv,z.prototype.commit=bv,z.prototype.next=Gv,z.prototype.plant=Yv,z.prototype.reverse=Ml,z.prototype.toJSON=z.prototype.valueOf=z.prototype.value=Fl,z.prototype.first=z.prototype.head,u0&&(z.prototype[u0]=Vv),z},K0=$0();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Lr._=K0,define(function(){return K0})):R?((R.exports=K0)._=K0,F._=K0):Lr._=K0}).call(ga)});var ay=Me((XH,cy)=>{"use strict";var fr=cy.exports;cy.exports.default=fr;var Pr="[",t2="]",ya="\x07",vh=";",OD=process.env.TERM_PROGRAM==="Apple_Terminal";fr.cursorTo=(i,u)=>{if(typeof i!="number")throw new TypeError("The `x` argument is required");return typeof u!="number"?Pr+(i+1)+"G":Pr+(u+1)+";"+(i+1)+"H"};fr.cursorMove=(i,u)=>{if(typeof i!="number")throw new TypeError("The `x` argument is required");let f="";return i<0?f+=Pr+-i+"D":i>0&&(f+=Pr+i+"C"),u<0?f+=Pr+-u+"A":u>0&&(f+=Pr+u+"B"),f};fr.cursorUp=(i=1)=>Pr+i+"A";fr.cursorDown=(i=1)=>Pr+i+"B";fr.cursorForward=(i=1)=>Pr+i+"C";fr.cursorBackward=(i=1)=>Pr+i+"D";fr.cursorLeft=Pr+"G";fr.cursorSavePosition=OD?"7":Pr+"s";fr.cursorRestorePosition=OD?"8":Pr+"u";fr.cursorGetPosition=Pr+"6n";fr.cursorNextLine=Pr+"E";fr.cursorPrevLine=Pr+"F";fr.cursorHide=Pr+"?25l";fr.cursorShow=Pr+"?25h";fr.eraseLines=i=>{let u="";for(let f=0;f[t2,"8",vh,vh,u,ya,i,t2,"8",vh,vh,ya].join("");fr.image=(i,u={})=>{let f=`${t2}1337;File=inline=1`;return u.width&&(f+=`;width=${u.width}`),u.height&&(f+=`;height=${u.height}`),u.preserveAspectRatio===!1&&(f+=";preserveAspectRatio=0"),f+":"+i.toString("base64")+ya};fr.iTerm={setCwd:(i=process.cwd())=>`${t2}50;CurrentDir=${i}${ya}`,annotation:(i,u={})=>{let f=`${t2}1337;`,c=typeof u.x!="undefined",g=typeof u.y!="undefined";if((c||g)&&!(c&&g&&typeof u.length!="undefined"))throw new Error("`x`, `y` and `length` must be defined when `x` or `y` is defined");return i=i.replace(/\|/g,""),f+=u.isHidden?"AddHiddenAnnotation=":"AddAnnotation=",u.length>0?f+=(c?[i,u.length,u.x,u.y]:[u.length,i]).join("|"):f+=i,f+ya}}});var PD=Me((JH,dy)=>{"use strict";var ID=(i,u)=>{for(let f of Reflect.ownKeys(u))Object.defineProperty(i,f,Object.getOwnPropertyDescriptor(u,f));return i};dy.exports=ID;dy.exports.default=ID});var FD=Me((QH,gh)=>{"use strict";var oN=PD(),_h=new WeakMap,MD=(i,u={})=>{if(typeof i!="function")throw new TypeError("Expected a function");let f,c=!1,g=0,t=i.displayName||i.name||"",C=function(...A){if(_h.set(C,++g),c){if(u.throw===!0)throw new Error(`Function \`${t}\` can only be called once`);return f}return c=!0,f=i.apply(this,A),i=null,f};return oN(C,i),_h.set(C,g),C};gh.exports=MD;gh.exports.default=MD;gh.exports.callCount=i=>{if(!_h.has(i))throw new Error(`The given function \`${i.name}\` is not wrapped by the \`onetime\` package`);return _h.get(i)}});var LD=Me((ZH,yh)=>{yh.exports=["SIGABRT","SIGALRM","SIGHUP","SIGINT","SIGTERM"];process.platform!=="win32"&&yh.exports.push("SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&yh.exports.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT","SIGUNUSED")});var vy=Me((eb,n2)=>{var uN=require("assert"),r2=LD(),sN=/^win/i.test(process.platform),wh=require("events");typeof wh!="function"&&(wh=wh.EventEmitter);var Bi;process.__signal_exit_emitter__?Bi=process.__signal_exit_emitter__:(Bi=process.__signal_exit_emitter__=new wh,Bi.count=0,Bi.emitted={});Bi.infinite||(Bi.setMaxListeners(Infinity),Bi.infinite=!0);n2.exports=function(i,u){uN.equal(typeof i,"function","a callback must be provided for exit handler"),i2===!1&&RD();var f="exit";u&&u.alwaysLast&&(f="afterexit");var c=function(){Bi.removeListener(f,i),Bi.listeners("exit").length===0&&Bi.listeners("afterexit").length===0&&py()};return Bi.on(f,i),c};n2.exports.unload=py;function py(){!i2||(i2=!1,r2.forEach(function(i){try{process.removeListener(i,hy[i])}catch(u){}}),process.emit=my,process.reallyExit=ND,Bi.count-=1)}function wa(i,u,f){Bi.emitted[i]||(Bi.emitted[i]=!0,Bi.emit(i,u,f))}var hy={};r2.forEach(function(i){hy[i]=function(){var f=process.listeners(i);f.length===Bi.count&&(py(),wa("exit",null,i),wa("afterexit",null,i),sN&&i==="SIGHUP"&&(i="SIGINT"),process.kill(process.pid,i))}});n2.exports.signals=function(){return r2};n2.exports.load=RD;var i2=!1;function RD(){i2||(i2=!0,Bi.count+=1,r2=r2.filter(function(i){try{return process.on(i,hy[i]),!0}catch(u){return!1}}),process.emit=fN,process.reallyExit=lN)}var ND=process.reallyExit;function lN(i){process.exitCode=i||0,wa("exit",process.exitCode,null),wa("afterexit",process.exitCode,null),ND.call(process,process.exitCode)}var my=process.emit;function fN(i,u){if(i==="exit"){u!==void 0&&(process.exitCode=u);var f=my.apply(this,arguments);return wa("exit",process.exitCode,null),wa("afterexit",process.exitCode,null),f}else return my.apply(this,arguments)}});var jD=Me((tb,BD)=>{"use strict";var cN=FD(),aN=vy();BD.exports=cN(()=>{aN(()=>{process.stderr.write("[?25h")},{alwaysLast:!0})})});var gy=Me(Da=>{"use strict";var dN=jD(),Dh=!1;Da.show=(i=process.stderr)=>{!i.isTTY||(Dh=!1,i.write("[?25h"))};Da.hide=(i=process.stderr)=>{!i.isTTY||(dN(),Dh=!0,i.write("[?25l"))};Da.toggle=(i,u)=>{i!==void 0&&(Dh=i),Dh?Da.show(u):Da.hide(u)}});var WD=Me(o2=>{"use strict";var UD=o2&&o2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(o2,"__esModule",{value:!0});var qD=UD(ay()),zD=UD(gy()),pN=(i,{showCursor:u=!1}={})=>{let f=0,c="",g=!1,t=C=>{!u&&!g&&(zD.default.hide(),g=!0);let A=C+` + `;A!==c&&(c=A,i.write(qD.default.eraseLines(f)+A),f=A.split(` + `).length)};return t.clear=()=>{i.write(qD.default.eraseLines(f)),c="",f=0},t.done=()=>{c="",f=0,u||(zD.default.show(),g=!1)},t};o2.default={create:pN}});var bD=Me((ib,HD)=>{HD.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var YD=Me(ru=>{"use strict";var GD=bD(),nl=process.env;Object.defineProperty(ru,"_vendors",{value:GD.map(function(i){return i.constant})});ru.name=null;ru.isPR=null;GD.forEach(function(i){var u=Array.isArray(i.env)?i.env:[i.env],f=u.every(function(c){return VD(c)});if(ru[i.constant]=f,f)switch(ru.name=i.name,typeof i.pr){case"string":ru.isPR=!!nl[i.pr];break;case"object":"env"in i.pr?ru.isPR=i.pr.env in nl&&nl[i.pr.env]!==i.pr.ne:"any"in i.pr?ru.isPR=i.pr.any.some(function(c){return!!nl[c]}):ru.isPR=VD(i.pr);break;default:ru.isPR=null}});ru.isCI=!!(nl.CI||nl.CONTINUOUS_INTEGRATION||nl.BUILD_NUMBER||nl.RUN_ID||ru.name);function VD(i){return typeof i=="string"?!!nl[i]:Object.keys(i).every(function(u){return nl[u]===i[u]})}});var KD=Me((ub,$D)=>{"use strict";$D.exports=YD().isCI});var JD=Me((sb,XD)=>{"use strict";var hN=i=>{let u=new Set;do for(let f of Reflect.ownKeys(i))u.add([i,f]);while((i=Reflect.getPrototypeOf(i))&&i!==Object.prototype);return u};XD.exports=(i,{include:u,exclude:f}={})=>{let c=g=>{let t=C=>typeof C=="string"?g===C:C.test(g);return u?u.some(t):f?!f.some(t):!0};for(let[g,t]of hN(i.constructor.prototype)){if(t==="constructor"||!c(t))continue;let C=Reflect.getOwnPropertyDescriptor(g,t);C&&typeof C.value=="function"&&(i[t]=i[t].bind(i))}return i}});var iE=Me(Sr=>{"use strict";Object.defineProperty(Sr,"__esModule",{value:!0});var Ea,u2,Eh,Sh,_y;typeof window=="undefined"||typeof MessageChannel!="function"?(Sa=null,yy=null,wy=function(){if(Sa!==null)try{var i=Sr.unstable_now();Sa(!0,i),Sa=null}catch(u){throw setTimeout(wy,0),u}},QD=Date.now(),Sr.unstable_now=function(){return Date.now()-QD},Ea=function(i){Sa!==null?setTimeout(Ea,0,i):(Sa=i,setTimeout(wy,0))},u2=function(i,u){yy=setTimeout(i,u)},Eh=function(){clearTimeout(yy)},Sh=function(){return!1},_y=Sr.unstable_forceFrameRate=function(){}):(Ch=window.performance,Dy=window.Date,ZD=window.setTimeout,eE=window.clearTimeout,typeof console!="undefined"&&(tE=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof tE!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")),typeof Ch=="object"&&typeof Ch.now=="function"?Sr.unstable_now=function(){return Ch.now()}:(nE=Dy.now(),Sr.unstable_now=function(){return Dy.now()-nE}),s2=!1,l2=null,Th=-1,Ey=5,Sy=0,Sh=function(){return Sr.unstable_now()>=Sy},_y=function(){},Sr.unstable_forceFrameRate=function(i){0>i||125kh(C,f))x!==void 0&&0>kh(x,C)?(i[c]=x,i[A]=f,c=A):(i[c]=C,i[t]=f,c=t);else if(x!==void 0&&0>kh(x,f))i[c]=x,i[A]=f,c=A;else break e}}return u}return null}function kh(i,u){var f=i.sortIndex-u.sortIndex;return f!==0?f:i.id-u.id}var ds=[],Nf=[],mN=1,_o=null,to=3,Oh=!1,pc=!1,f2=!1;function Ih(i){for(var u=Iu(Nf);u!==null;){if(u.callback===null)Ah(Nf);else if(u.startTime<=i)Ah(Nf),u.sortIndex=u.expirationTime,Ty(ds,u);else break;u=Iu(Nf)}}function xy(i){if(f2=!1,Ih(i),!pc)if(Iu(ds)!==null)pc=!0,Ea(ky);else{var u=Iu(Nf);u!==null&&u2(xy,u.startTime-i)}}function ky(i,u){pc=!1,f2&&(f2=!1,Eh()),Oh=!0;var f=to;try{for(Ih(u),_o=Iu(ds);_o!==null&&(!(_o.expirationTime>u)||i&&!Sh());){var c=_o.callback;if(c!==null){_o.callback=null,to=_o.priorityLevel;var g=c(_o.expirationTime<=u);u=Sr.unstable_now(),typeof g=="function"?_o.callback=g:_o===Iu(ds)&&Ah(ds),Ih(u)}else Ah(ds);_o=Iu(ds)}if(_o!==null)var t=!0;else{var C=Iu(Nf);C!==null&&u2(xy,C.startTime-u),t=!1}return t}finally{_o=null,to=f,Oh=!1}}function rE(i){switch(i){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var vN=_y;Sr.unstable_ImmediatePriority=1;Sr.unstable_UserBlockingPriority=2;Sr.unstable_NormalPriority=3;Sr.unstable_IdlePriority=5;Sr.unstable_LowPriority=4;Sr.unstable_runWithPriority=function(i,u){switch(i){case 1:case 2:case 3:case 4:case 5:break;default:i=3}var f=to;to=i;try{return u()}finally{to=f}};Sr.unstable_next=function(i){switch(to){case 1:case 2:case 3:var u=3;break;default:u=to}var f=to;to=u;try{return i()}finally{to=f}};Sr.unstable_scheduleCallback=function(i,u,f){var c=Sr.unstable_now();if(typeof f=="object"&&f!==null){var g=f.delay;g=typeof g=="number"&&0c?(i.sortIndex=g,Ty(Nf,i),Iu(ds)===null&&i===Iu(Nf)&&(f2?Eh():f2=!0,u2(xy,g-c))):(i.sortIndex=f,Ty(ds,i),pc||Oh||(pc=!0,Ea(ky))),i};Sr.unstable_cancelCallback=function(i){i.callback=null};Sr.unstable_wrapCallback=function(i){var u=to;return function(){var f=to;to=u;try{return i.apply(this,arguments)}finally{to=f}}};Sr.unstable_getCurrentPriorityLevel=function(){return to};Sr.unstable_shouldYield=function(){var i=Sr.unstable_now();Ih(i);var u=Iu(ds);return u!==_o&&_o!==null&&u!==null&&u.callback!==null&&u.startTime<=i&&u.expirationTime<_o.expirationTime||Sh()};Sr.unstable_requestPaint=vN;Sr.unstable_continueExecution=function(){pc||Oh||(pc=!0,Ea(ky))};Sr.unstable_pauseExecution=function(){};Sr.unstable_getFirstCallbackNode=function(){return Iu(ds)};Sr.unstable_Profiling=null});var Ay=Me((fb,oE)=>{"use strict";oE.exports=iE()});var uE=Me((cb,c2)=>{c2.exports=function i(u){"use strict";var f=ey(),c=lr(),g=Ay();function t(v){for(var m="https://reactjs.org/docs/error-decoder.html?invariant="+v,S=1;Sqo||(v.current=qi[qo],qi[qo]=null,qo--)}function Fr(v,m){qo++,qi[qo]=v.current,v.current=m}var si={},H0={current:si},b0={current:!1},Bt=si;function Lu(v,m){var S=v.type.contextTypes;if(!S)return si;var O=v.stateNode;if(O&&O.__reactInternalMemoizedUnmaskedChildContext===m)return O.__reactInternalMemoizedMaskedChildContext;var M={},b;for(b in S)M[b]=m[b];return O&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=m,v.__reactInternalMemoizedMaskedChildContext=M),M}function c0(v){return v=v.childContextTypes,v!=null}function Ru(v){kr(b0,v),kr(H0,v)}function ks(v){kr(b0,v),kr(H0,v)}function As(v,m,S){if(H0.current!==si)throw Error(t(168));Fr(H0,m,v),Fr(b0,S,v)}function uu(v,m,S){var O=v.stateNode;if(v=m.childContextTypes,typeof O.getChildContext!="function")return S;O=O.getChildContext();for(var M in O)if(!(M in v))throw Error(t(108,Oe(m)||"Unknown",M));return f({},S,{},O)}function wo(v){var m=v.stateNode;return m=m&&m.__reactInternalMemoizedMergedChildContext||si,Bt=H0.current,Fr(H0,m,v),Fr(b0,b0.current,v),!0}function zo(v,m,S){var O=v.stateNode;if(!O)throw Error(t(169));S?(m=uu(v,m,Bt),O.__reactInternalMemoizedMergedChildContext=m,kr(b0,v),kr(H0,v),Fr(H0,m,v)):kr(b0,v),Fr(b0,S,v)}var Os=g.unstable_runWithPriority,Is=g.unstable_scheduleCallback,uf=g.unstable_cancelCallback,_n=g.unstable_shouldYield,Nu=g.unstable_requestPaint,Wo=g.unstable_now,su=g.unstable_getCurrentPriorityLevel,Ps=g.unstable_ImmediatePriority,pl=g.unstable_UserBlockingPriority,Vf=g.unstable_NormalPriority,hl=g.unstable_LowPriority,Bu=g.unstable_IdlePriority,ju={},sf=Nu!==void 0?Nu:function(){},ro=null,Ms=null,ml=!1,Uu=Wo(),G0=1e4>Uu?Wo:function(){return Wo()-Uu};function Fs(){switch(su()){case Ps:return 99;case pl:return 98;case Vf:return 97;case hl:return 96;case Bu:return 95;default:throw Error(t(332))}}function tt(v){switch(v){case 99:return Ps;case 98:return pl;case 97:return Vf;case 96:return hl;case 95:return Bu;default:throw Error(t(332))}}function zi(v,m){return v=tt(v),Os(v,m)}function lu(v,m,S){return v=tt(v),Is(v,m,S)}function Ho(v){return ro===null?(ro=[v],Ms=Is(Ps,vl)):ro.push(v),ju}function O0(){if(Ms!==null){var v=Ms;Ms=null,uf(v)}vl()}function vl(){if(!ml&&ro!==null){ml=!0;var v=0;try{var m=ro;zi(99,function(){for(;v=m&&(ai=!0),v.firstContext=null)}function D0(v,m){if(zu!==v&&m!==!1&&m!==0)if((typeof m!="number"||m===1073741823)&&(zu=v,m=1073741823),m={context:v,observedBits:m,next:null},Wi===null){if(qu===null)throw Error(t(308));Wi=m,qu.dependencies={expirationTime:0,firstContext:m,responders:null}}else Wi=Wi.next=m;return Jt?v._currentValue:v._currentValue2}var Do=!1;function i0(v){return{baseState:v,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Rs(v){return{baseState:v.baseState,firstUpdate:v.firstUpdate,lastUpdate:v.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function a0(v,m){return{expirationTime:v,suspenseConfig:m,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function Hu(v,m){v.lastUpdate===null?v.firstUpdate=v.lastUpdate=m:(v.lastUpdate.next=m,v.lastUpdate=m)}function V0(v,m){var S=v.alternate;if(S===null){var O=v.updateQueue,M=null;O===null&&(O=v.updateQueue=i0(v.memoizedState))}else O=v.updateQueue,M=S.updateQueue,O===null?M===null?(O=v.updateQueue=i0(v.memoizedState),M=S.updateQueue=i0(S.memoizedState)):O=v.updateQueue=Rs(M):M===null&&(M=S.updateQueue=Rs(O));M===null||O===M?Hu(O,m):O.lastUpdate===null||M.lastUpdate===null?(Hu(O,m),Hu(M,m)):(Hu(O,m),M.lastUpdate=m)}function bu(v,m){var S=v.updateQueue;S=S===null?v.updateQueue=i0(v.memoizedState):Ns(v,S),S.lastCapturedUpdate===null?S.firstCapturedUpdate=S.lastCapturedUpdate=m:(S.lastCapturedUpdate.next=m,S.lastCapturedUpdate=m)}function Ns(v,m){var S=v.alternate;return S!==null&&m===S.updateQueue&&(m=v.updateQueue=Rs(m)),m}function bo(v,m,S,O,M,b){switch(S.tag){case 1:return v=S.payload,typeof v=="function"?v.call(b,O,M):v;case 3:v.effectTag=v.effectTag&-4097|64;case 0:if(v=S.payload,M=typeof v=="function"?v.call(b,O,M):v,M==null)break;return f({},O,M);case 2:Do=!0}return O}function P0(v,m,S,O,M){Do=!1,m=Ns(v,m);for(var b=m.baseState,ee=null,Ye=0,Ze=m.firstUpdate,ut=b;Ze!==null;){var In=Ze.expirationTime;Inpr?(Hr=mn,mn=null):Hr=mn.sibling;var Vn=jr(Re,mn,ze[pr],Et);if(Vn===null){mn===null&&(mn=Hr);break}v&&mn&&Vn.alternate===null&&m(Re,mn),Ce=b(Vn,Ce,pr),sr===null?on=Vn:sr.sibling=Vn,sr=Vn,mn=Hr}if(pr===ze.length)return S(Re,mn),on;if(mn===null){for(;prpr?(Hr=mn,mn=null):Hr=mn.sibling;var ni=jr(Re,mn,Vn.value,Et);if(ni===null){mn===null&&(mn=Hr);break}v&&mn&&ni.alternate===null&&m(Re,mn),Ce=b(ni,Ce,pr),sr===null?on=ni:sr.sibling=ni,sr=ni,mn=Hr}if(Vn.done)return S(Re,mn),on;if(mn===null){for(;!Vn.done;pr++,Vn=ze.next())Vn=A0(Re,Vn.value,Et),Vn!==null&&(Ce=b(Vn,Ce,pr),sr===null?on=Vn:sr.sibling=Vn,sr=Vn);return on}for(mn=O(Re,mn);!Vn.done;pr++,Vn=ze.next())Vn=gi(mn,Re,pr,Vn.value,Et),Vn!==null&&(v&&Vn.alternate!==null&&mn.delete(Vn.key===null?pr:Vn.key),Ce=b(Vn,Ce,pr),sr===null?on=Vn:sr.sibling=Vn,sr=Vn);return v&&mn.forEach(function(Zf){return m(Re,Zf)}),on}return function(Re,Ce,ze,Et){var on=typeof ze=="object"&&ze!==null&&ze.type===L&&ze.key===null;on&&(ze=ze.props.children);var sr=typeof ze=="object"&&ze!==null;if(sr)switch(ze.$$typeof){case x:e:{for(sr=ze.key,on=Ce;on!==null;){if(on.key===sr)if(on.tag===7?ze.type===L:on.elementType===ze.type){S(Re,on.sibling),Ce=M(on,ze.type===L?ze.props.children:ze.props,Et),Ce.ref=au(Re,on,ze),Ce.return=Re,Re=Ce;break e}else{S(Re,on);break}else m(Re,on);on=on.sibling}ze.type===L?(Ce=mi(ze.props.children,Re.mode,Et,ze.key),Ce.return=Re,Re=Ce):(Et=Hs(ze.type,ze.key,ze.props,null,Re.mode,Et),Et.ref=au(Re,Ce,ze),Et.return=Re,Re=Et)}return ee(Re);case D:e:{for(on=ze.key;Ce!==null;){if(Ce.key===on)if(Ce.tag===4&&Ce.stateNode.containerInfo===ze.containerInfo&&Ce.stateNode.implementation===ze.implementation){S(Re,Ce.sibling),Ce=M(Ce,ze.children||[],Et),Ce.return=Re,Re=Ce;break e}else{S(Re,Ce);break}else m(Re,Ce);Ce=Ce.sibling}Ce=Xf(ze,Re.mode,Et),Ce.return=Re,Re=Ce}return ee(Re)}if(typeof ze=="string"||typeof ze=="number")return ze=""+ze,Ce!==null&&Ce.tag===6?(S(Re,Ce.sibling),Ce=M(Ce,ze,Et),Ce.return=Re,Re=Ce):(S(Re,Ce),Ce=vi(ze,Re.mode,Et),Ce.return=Re,Re=Ce),ee(Re);if(M0(ze))return po(Re,Ce,ze,Et);if(J(ze))return _i(Re,Ce,ze,Et);if(sr&&Lr(Re,ze),typeof ze=="undefined"&&!on)switch(Re.tag){case 1:case 0:throw Re=Re.type,Error(t(152,Re.displayName||Re.name||"Component"))}return S(Re,Ce)}}var R=F(!0),U=F(!1),H={},fe={current:H},ue={current:H},de={current:H};function W(v){if(v===H)throw Error(t(174));return v}function ve(v,m){Fr(de,m,v),Fr(ue,v,v),Fr(fe,H,v),m=Ot(m),kr(fe,v),Fr(fe,m,v)}function Fe(v){kr(fe,v),kr(ue,v),kr(de,v)}function Ge(v){var m=W(de.current),S=W(fe.current);m=Nt(S,v.type,m),S!==m&&(Fr(ue,v,v),Fr(fe,m,v))}function K(v){ue.current===v&&(kr(fe,v),kr(ue,v))}var xe={current:0};function je(v){for(var m=v;m!==null;){if(m.tag===13){var S=m.memoizedState;if(S!==null&&(S=S.dehydrated,S===null||ll(S)||fl(S)))return m}else if(m.tag===19&&m.memoizedProps.revealOrder!==void 0){if((m.effectTag&64)!=0)return m}else if(m.child!==null){m.child.return=m,m=m.child;continue}if(m===v)break;for(;m.sibling===null;){if(m.return===null||m.return===v)return null;m=m.return}m.sibling.return=m.return,m=m.sibling}return null}function Xe(v,m){return{responder:v,props:m}}var rt=C.ReactCurrentDispatcher,st=C.ReactCurrentBatchConfig,xt=0,wt=null,lt=null,Rt=null,yn=null,sn=null,ar=null,rn=0,Hn=null,d0=0,Cr=!1,He=null,Qe=0;function Ne(){throw Error(t(321))}function ft(v,m){if(m===null)return!1;for(var S=0;Srn&&(rn=In,pf(rn))):(Yf(In,Ze.suspenseConfig),b=Ze.eagerReducer===v?Ze.eagerState:v(b,Ze.action)),ee=Ze,Ze=Ze.next}while(Ze!==null&&Ze!==O);ut||(Ye=ee,M=b),Sn(b,m.memoizedState)||(ai=!0),m.memoizedState=b,m.baseUpdate=Ye,m.baseState=M,S.lastRenderedState=b}return[m.memoizedState,S.dispatch]}function ci(v){var m=Cn();return typeof v=="function"&&(v=v()),m.memoizedState=m.baseState=v,v=m.queue={last:null,dispatch:null,lastRenderedReducer:p0,lastRenderedState:v},v=v.dispatch=Us.bind(null,wt,v),[m.memoizedState,v]}function xi(v){return h0(p0,v)}function E0(v,m,S,O){return v={tag:v,create:m,destroy:S,deps:O,next:null},Hn===null?(Hn={lastEffect:null},Hn.lastEffect=v.next=v):(m=Hn.lastEffect,m===null?Hn.lastEffect=v.next=v:(S=m.next,m.next=v,v.next=S,Hn.lastEffect=v)),v}function qr(v,m,S,O){var M=Cn();d0|=v,M.memoizedState=E0(m,S,void 0,O===void 0?null:O)}function Eo(v,m,S,O){var M=bn();O=O===void 0?null:O;var b=void 0;if(lt!==null){var ee=lt.memoizedState;if(b=ee.destroy,O!==null&&ft(O,ee.deps)){E0(0,S,b,O);return}}d0|=v,M.memoizedState=E0(m,S,b,O)}function So(v,m){return qr(516,192,v,m)}function wl(v,m){return Eo(516,192,v,m)}function js(v,m){if(typeof m=="function")return v=v(),m(v),function(){m(null)};if(m!=null)return v=v(),m.current=v,function(){m.current=null}}function Dl(){}function du(v,m){return Cn().memoizedState=[v,m===void 0?null:m],v}function Yu(v,m){var S=bn();m=m===void 0?null:m;var O=S.memoizedState;return O!==null&&m!==null&&ft(m,O[1])?O[0]:(S.memoizedState=[v,m],v)}function Us(v,m,S){if(!(25>Qe))throw Error(t(301));var O=v.alternate;if(v===wt||O!==null&&O===wt)if(Cr=!0,v={expirationTime:xt,suspenseConfig:null,action:S,eagerReducer:null,eagerState:null,next:null},He===null&&(He=new Map),S=He.get(m),S===void 0)He.set(m,v);else{for(m=S;m.next!==null;)m=m.next;m.next=v}else{var M=g0(),b=nr.suspense;M=Kr(M,v,b),b={expirationTime:M,suspenseConfig:b,action:S,eagerReducer:null,eagerState:null,next:null};var ee=m.last;if(ee===null)b.next=b;else{var Ye=ee.next;Ye!==null&&(b.next=Ye),ee.next=b}if(m.last=b,v.expirationTime===0&&(O===null||O.expirationTime===0)&&(O=m.lastRenderedReducer,O!==null))try{var Ze=m.lastRenderedState,ut=O(Ze,S);if(b.eagerReducer=O,b.eagerState=ut,Sn(ut,Ze))return}catch(In){}finally{}_0(v,M)}}var oo={readContext:D0,useCallback:Ne,useContext:Ne,useEffect:Ne,useImperativeHandle:Ne,useLayoutEffect:Ne,useMemo:Ne,useReducer:Ne,useRef:Ne,useState:Ne,useDebugValue:Ne,useResponder:Ne,useDeferredValue:Ne,useTransition:Ne},Hi={readContext:D0,useCallback:du,useContext:D0,useEffect:So,useImperativeHandle:function(v,m,S){return S=S!=null?S.concat([v]):null,qr(4,36,js.bind(null,m,v),S)},useLayoutEffect:function(v,m){return qr(4,36,v,m)},useMemo:function(v,m){var S=Cn();return m=m===void 0?null:m,v=v(),S.memoizedState=[v,m],v},useReducer:function(v,m,S){var O=Cn();return m=S!==void 0?S(m):m,O.memoizedState=O.baseState=m,v=O.queue={last:null,dispatch:null,lastRenderedReducer:v,lastRenderedState:m},v=v.dispatch=Us.bind(null,wt,v),[O.memoizedState,v]},useRef:function(v){var m=Cn();return v={current:v},m.memoizedState=v},useState:ci,useDebugValue:Dl,useResponder:Xe,useDeferredValue:function(v,m){var S=ci(v),O=S[0],M=S[1];return So(function(){g.unstable_next(function(){var b=st.suspense;st.suspense=m===void 0?null:m;try{M(v)}finally{st.suspense=b}})},[v,m]),O},useTransition:function(v){var m=ci(!1),S=m[0],O=m[1];return[du(function(M){O(!0),g.unstable_next(function(){var b=st.suspense;st.suspense=v===void 0?null:v;try{O(!1),M()}finally{st.suspense=b}})},[v,S]),S]}},qs={readContext:D0,useCallback:Yu,useContext:D0,useEffect:wl,useImperativeHandle:function(v,m,S){return S=S!=null?S.concat([v]):null,Eo(4,36,js.bind(null,m,v),S)},useLayoutEffect:function(v,m){return Eo(4,36,v,m)},useMemo:function(v,m){var S=bn();m=m===void 0?null:m;var O=S.memoizedState;return O!==null&&m!==null&&ft(m,O[1])?O[0]:(v=v(),S.memoizedState=[v,m],v)},useReducer:h0,useRef:function(){return bn().memoizedState},useState:xi,useDebugValue:Dl,useResponder:Xe,useDeferredValue:function(v,m){var S=xi(v),O=S[0],M=S[1];return wl(function(){g.unstable_next(function(){var b=st.suspense;st.suspense=m===void 0?null:m;try{M(v)}finally{st.suspense=b}})},[v,m]),O},useTransition:function(v){var m=xi(!1),S=m[0],O=m[1];return[Yu(function(M){O(!0),g.unstable_next(function(){var b=st.suspense;st.suspense=v===void 0?null:v;try{O(!1),M()}finally{st.suspense=b}})},[v,S]),S]}},F0=null,Gr=null,ir=!1;function L0(v,m){var S=xo(5,null,null,0);S.elementType="DELETED",S.type="DELETED",S.stateNode=m,S.return=v,S.effectTag=8,v.lastEffect!==null?(v.lastEffect.nextEffect=S,v.lastEffect=S):v.firstEffect=v.lastEffect=S}function Y0(v,m){switch(v.tag){case 5:return m=Ti(m,v.type,v.pendingProps),m!==null?(v.stateNode=m,!0):!1;case 6:return m=Fu(m,v.pendingProps),m!==null?(v.stateNode=m,!0):!1;case 13:return!1;default:return!1}}function Co(v){if(ir){var m=Gr;if(m){var S=m;if(!Y0(v,m)){if(m=cl(S),!m||!Y0(v,m)){v.effectTag=v.effectTag&-1025|2,ir=!1,F0=v;return}L0(F0,S)}F0=v,Gr=al(m)}else v.effectTag=v.effectTag&-1025|2,ir=!1,F0=v}}function $u(v){for(v=v.return;v!==null&&v.tag!==5&&v.tag!==3&&v.tag!==13;)v=v.return;F0=v}function Vo(v){if(!w||v!==F0)return!1;if(!ir)return $u(v),ir=!0,!1;var m=v.type;if(v.tag!==5||m!=="head"&&m!=="body"&&!at(m,v.memoizedProps))for(m=Gr;m;)L0(v,m),m=cl(m);if($u(v),v.tag===13){if(!w)throw Error(t(316));if(v=v.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(t(317));Gr=Ac(v)}else Gr=F0?cl(v.stateNode):null;return!0}function Rr(){w&&(Gr=F0=null,ir=!1)}var Jn=C.ReactCurrentOwner,ai=!1;function o0(v,m,S,O){m.child=v===null?U(m,null,S,O):R(m,v.child,S,O)}function Vr(v,m,S,O,M){S=S.render;var b=m.ref;return io(m,M),O=St(v,m,S,O,b,M),v!==null&&!ai?(m.updateQueue=v.updateQueue,m.effectTag&=-517,v.expirationTime<=M&&(v.expirationTime=0),X0(v,m,M)):(m.effectTag|=1,o0(v,m,O,M),m.child)}function ff(v,m,S,O,M,b){if(v===null){var ee=S.type;return typeof ee=="function"&&!mf(ee)&&ee.defaultProps===void 0&&S.compare===null&&S.defaultProps===void 0?(m.tag=15,m.type=ee,cf(v,m,ee,O,M,b)):(v=Hs(S.type,null,O,null,m.mode,b),v.ref=m.ref,v.return=m,m.child=v)}return ee=v.child,Mm)&&Qn.set(v,m)))}}function Gi(v,m){v.expirationTimev?m:v)}function x0(v){if(v.lastExpiredTime!==0)v.callbackExpirationTime=1073741823,v.callbackPriority=99,v.callbackNode=Ho(Z0.bind(null,v));else{var m=fo(v),S=v.callbackNode;if(m===0)S!==null&&(v.callbackNode=null,v.callbackExpirationTime=0,v.callbackPriority=90);else{var O=g0();if(m===1073741823?O=99:m===1||m===2?O=95:(O=10*(1073741821-m)-10*(1073741821-O),O=0>=O?99:250>=O?98:5250>=O?97:95),S!==null){var M=v.callbackPriority;if(v.callbackExpirationTime===m&&M>=O)return;S!==ju&&uf(S)}v.callbackExpirationTime=m,v.callbackPriority=O,m=m===1073741823?Ho(Z0.bind(null,v)):lu(O,Xu.bind(null,v),{timeout:10*(1073741821-m)-G0()}),v.callbackNode=m}}}function Xu(v,m){if(t0=0,m)return m=g0(),kl(v,m),x0(v),null;var S=fo(v);if(S!==0){if(m=v.callbackNode,(Kt&(Br|zr))!==Fn)throw Error(t(327));if(Ws(),v===X&&S===ye||mu(v,S),Y!==null){var O=Kt;Kt|=Br;var M=ei(v);do try{Ua();break}catch(Ye){Ju(v,Ye)}while(1);if(Wu(),Kt=O,B0.current=M,he===wr)throw m=We,mu(v,S),ao(v,S),x0(v),m;if(Y===null)switch(M=v.finishedWork=v.current.alternate,v.finishedExpirationTime=S,O=he,X=null,O){case lo:case wr:throw Error(t(345));case kn:kl(v,2=S){v.lastPingedTime=S,mu(v,S);break}}if(b=fo(v),b!==0&&b!==S)break;if(O!==0&&O!==S){v.lastPingedTime=O;break}v.timeoutHandle=jt(gu.bind(null,v),M);break}gu(v);break;case hi:if(ao(v,S),O=v.lastSuspendedTime,S===O&&(v.nextKnownPendingLevel=$f(M)),qt&&(M=v.lastPingedTime,M===0||M>=S)){v.lastPingedTime=S,mu(v,S);break}if(M=fo(v),M!==0&&M!==S)break;if(O!==0&&O!==S){v.lastPingedTime=O;break}if(Dt!==1073741823?O=10*(1073741821-Dt)-G0():et===1073741823?O=0:(O=10*(1073741821-et)-5e3,M=G0(),S=10*(1073741821-S)-M,O=M-O,0>O&&(O=0),O=(120>O?120:480>O?480:1080>O?1080:1920>O?1920:3e3>O?3e3:4320>O?4320:1960*Cl(O/1960))-O,S=O?O=0:(M=ee.busyDelayMs|0,b=G0()-(10*(1073741821-b)-(ee.timeoutMs|0||5e3)),O=b<=M?0:M+O-b),10 component higher in the tree to provide a loading indicator or placeholder to display.`+dl(M))}he!==Ai&&(he=kn),b=zs(b,M),Ze=O;do{switch(Ze.tag){case 3:ee=b,Ze.effectTag|=4096,Ze.expirationTime=m;var Ce=pu(Ze,ee,m);bu(Ze,Ce);break e;case 1:ee=b;var ze=Ze.type,Et=Ze.stateNode;if((Ze.effectTag&64)==0&&(typeof ze.getDerivedStateFromError=="function"||Et!==null&&typeof Et.componentDidCatch=="function"&&(Ar===null||!Ar.has(Et)))){Ze.effectTag|=4096,Ze.expirationTime=m;var on=Sl(Ze,ee,m);bu(Ze,on);break e}}Ze=Ze.return}while(Ze!==null)}Y=vu(Y)}catch(sr){m=sr;continue}break}while(1)}function ei(){var v=B0.current;return B0.current=oo,v===null?oo:v}function Yf(v,m){vZt&&(Zt=v)}function ja(){for(;Y!==null;)Y=Ic(Y)}function Ua(){for(;Y!==null&&!_n();)Y=Ic(Y)}function Ic(v){var m=Lc(v.alternate,v,ye);return v.memoizedProps=v.pendingProps,m===null&&(m=vu(v)),hu.current=null,m}function vu(v){Y=v;do{var m=Y.alternate;if(v=Y.return,(Y.effectTag&2048)==0){e:{var S=m;m=Y;var O=ye,M=m.pendingProps;switch(m.tag){case 2:break;case 16:break;case 15:case 0:break;case 1:c0(m.type)&&Ru(m);break;case 3:Fe(m),ks(m),M=m.stateNode,M.pendingContext&&(M.context=M.pendingContext,M.pendingContext=null),(S===null||S.child===null)&&Vo(m)&&ki(m),$r(m);break;case 5:K(m);var b=W(de.current);if(O=m.type,S!==null&&m.stateNode!=null)m0(S,m,O,M,b),S.ref!==m.ref&&(m.effectTag|=128);else if(M){if(S=W(fe.current),Vo(m)){if(M=m,!w)throw Error(t(175));S=Ui(M.stateNode,M.type,M.memoizedProps,b,S,M),M.updateQueue=S,S=S!==null,S&&ki(m)}else{var ee=ne(O,M,b,S,m);Yr(ee,m,!1,!1),m.stateNode=ee,Z(ee,O,M,b,S)&&ki(m)}m.ref!==null&&(m.effectTag|=128)}else if(m.stateNode===null)throw Error(t(166));break;case 6:if(S&&m.stateNode!=null)Tn(S,m,S.memoizedProps,M);else{if(typeof M!="string"&&m.stateNode===null)throw Error(t(166));if(S=W(de.current),b=W(fe.current),Vo(m)){if(S=m,!w)throw Error(t(176));(S=Mr(S.stateNode,S.memoizedProps,S))&&ki(m)}else m.stateNode=Ft(M,S,b,m)}break;case 11:break;case 13:if(kr(xe,m),M=m.memoizedState,(m.effectTag&64)!=0){m.expirationTime=O;break e}M=M!==null,b=!1,S===null?m.memoizedProps.fallback!==void 0&&Vo(m):(O=S.memoizedState,b=O!==null,M||O===null||(O=S.child.sibling,O!==null&&(ee=m.firstEffect,ee!==null?(m.firstEffect=O,O.nextEffect=ee):(m.firstEffect=m.lastEffect=O,O.nextEffect=null),O.effectTag=8))),M&&!b&&(m.mode&2)!=0&&(S===null&&m.memoizedProps.unstable_avoidThisFallback!==!0||(xe.current&1)!=0?he===lo&&(he=T0):((he===lo||he===T0)&&(he=hi),Zt!==0&&X!==null&&(ao(X,ye),$o(X,Zt)))),cr&&M&&(m.effectTag|=4),Yt&&(M||b)&&(m.effectTag|=4);break;case 7:break;case 8:break;case 12:break;case 4:Fe(m),$r(m);break;case 10:fi(m);break;case 9:break;case 14:break;case 17:c0(m.type)&&Ru(m);break;case 19:if(kr(xe,m),M=m.memoizedState,M===null)break;if(b=(m.effectTag&64)!=0,ee=M.rendering,ee===null){if(b)bi(M,!1);else if(he!==lo||S!==null&&(S.effectTag&64)!=0)for(S=m.child;S!==null;){if(ee=je(S),ee!==null){for(m.effectTag|=64,bi(M,!1),S=ee.updateQueue,S!==null&&(m.updateQueue=S,m.effectTag|=4),M.lastEffect===null&&(m.firstEffect=null),m.lastEffect=M.lastEffect,S=O,M=m.child;M!==null;)b=M,O=S,b.effectTag&=2,b.nextEffect=null,b.firstEffect=null,b.lastEffect=null,ee=b.alternate,ee===null?(b.childExpirationTime=0,b.expirationTime=O,b.child=null,b.memoizedProps=null,b.memoizedState=null,b.updateQueue=null,b.dependencies=null):(b.childExpirationTime=ee.childExpirationTime,b.expirationTime=ee.expirationTime,b.child=ee.child,b.memoizedProps=ee.memoizedProps,b.memoizedState=ee.memoizedState,b.updateQueue=ee.updateQueue,O=ee.dependencies,b.dependencies=O===null?null:{expirationTime:O.expirationTime,firstContext:O.firstContext,responders:O.responders}),M=M.sibling;Fr(xe,xe.current&1|2,m),m=m.child;break e}S=S.sibling}}else{if(!b)if(S=je(ee),S!==null){if(m.effectTag|=64,b=!0,S=S.updateQueue,S!==null&&(m.updateQueue=S,m.effectTag|=4),bi(M,!0),M.tail===null&&M.tailMode==="hidden"&&!ee.alternate){m=m.lastEffect=M.lastEffect,m!==null&&(m.nextEffect=null);break}}else G0()>M.tailExpiration&&1M&&(M=O),ee>M&&(M=ee),b=b.sibling;S.childExpirationTime=M}if(m!==null)return m;v!==null&&(v.effectTag&2048)==0&&(v.firstEffect===null&&(v.firstEffect=Y.firstEffect),Y.lastEffect!==null&&(v.lastEffect!==null&&(v.lastEffect.nextEffect=Y.firstEffect),v.lastEffect=Y.lastEffect),1v?m:v}function gu(v){var m=Fs();return zi(99,co.bind(null,v,m)),null}function co(v,m){do Ws();while(dr!==null);if((Kt&(Br|zr))!==Fn)throw Error(t(327));var S=v.finishedWork,O=v.finishedExpirationTime;if(S===null)return null;if(v.finishedWork=null,v.finishedExpirationTime=0,S===v.current)throw Error(t(177));v.callbackNode=null,v.callbackExpirationTime=0,v.callbackPriority=90,v.nextKnownPendingLevel=0;var M=$f(S);if(v.firstPendingTime=M,O<=v.lastSuspendedTime?v.firstSuspendedTime=v.lastSuspendedTime=v.nextKnownPendingLevel=0:O<=v.firstSuspendedTime&&(v.firstSuspendedTime=O-1),O<=v.lastPingedTime&&(v.lastPingedTime=0),O<=v.lastExpiredTime&&(v.lastExpiredTime=0),v===X&&(Y=X=null,ye=0),1=S?mt(v,m,S):(Fr(xe,xe.current&1,m),m=X0(v,m,S),m!==null?m.sibling:null);Fr(xe,xe.current&1,m);break;case 19:if(O=m.childExpirationTime>=S,(v.effectTag&64)!=0){if(O)return $t(v,m,S);m.effectTag|=64}if(M=m.memoizedState,M!==null&&(M.rendering=null,M.tail=null),Fr(xe,xe.current,m),!O)return null}return X0(v,m,S)}ai=!1}}else ai=!1;switch(m.expirationTime=0,m.tag){case 2:if(O=m.type,v!==null&&(v.alternate=null,m.alternate=null,m.effectTag|=2),v=m.pendingProps,M=Lu(m,H0.current),io(m,S),M=St(null,m,O,v,M,S),m.effectTag|=1,typeof M=="object"&&M!==null&&typeof M.render=="function"&&M.$$typeof===void 0){if(m.tag=1,Qt(),c0(O)){var b=!0;wo(m)}else b=!1;m.memoizedState=M.state!==null&&M.state!==void 0?M.state:null;var ee=O.getDerivedStateFromProps;typeof ee=="function"&&Go(m,O,ee,v),M.updater=Gu,m.stateNode=M,M._reactInternalFiber=m,Vu(m,O,v,S),m=Be(null,m,O,!0,b,S)}else m.tag=0,o0(null,m,M,S),m=m.child;return m;case 16:if(M=m.elementType,v!==null&&(v.alternate=null,m.alternate=null,m.effectTag|=2),v=m.pendingProps,Te(M),M._status!==1)throw M._result;switch(M=M._result,m.type=M,b=m.tag=Wa(M),v=I0(M,v),b){case 0:m=K0(null,m,M,v,S);break;case 1:m=ae(null,m,M,v,S);break;case 11:m=Vr(null,m,M,v,S);break;case 14:m=ff(null,m,M,I0(M.type,v),O,S);break;default:throw Error(t(306,M,""))}return m;case 0:return O=m.type,M=m.pendingProps,M=m.elementType===O?M:I0(O,M),K0(v,m,O,M,S);case 1:return O=m.type,M=m.pendingProps,M=m.elementType===O?M:I0(O,M),ae(v,m,O,M,S);case 3:if(Ie(m),O=m.updateQueue,O===null)throw Error(t(282));if(M=m.memoizedState,M=M!==null?M.element:null,P0(m,O,m.pendingProps,null,S),O=m.memoizedState.element,O===M)Rr(),m=X0(v,m,S);else{if((M=m.stateNode.hydrate)&&(w?(Gr=al(m.stateNode.containerInfo),F0=m,M=ir=!0):M=!1),M)for(S=U(m,null,O,S),m.child=S;S;)S.effectTag=S.effectTag&-3|1024,S=S.sibling;else o0(v,m,O,S),Rr();m=m.child}return m;case 5:return Ge(m),v===null&&Co(m),O=m.type,M=m.pendingProps,b=v!==null?v.memoizedProps:null,ee=M.children,at(O,M)?ee=null:b!==null&&at(O,b)&&(m.effectTag|=16),$0(v,m),m.mode&4&&S!==1&&it(O,M)?(m.expirationTime=m.childExpirationTime=1,m=null):(o0(v,m,ee,S),m=m.child),m;case 6:return v===null&&Co(m),null;case 13:return mt(v,m,S);case 4:return ve(m,m.stateNode.containerInfo),O=m.pendingProps,v===null?m.child=R(m,null,O,S):o0(v,m,O,S),m.child;case 11:return O=m.type,M=m.pendingProps,M=m.elementType===O?M:I0(O,M),Vr(v,m,O,M,S);case 7:return o0(v,m,m.pendingProps,S),m.child;case 8:return o0(v,m,m.pendingProps.children,S),m.child;case 12:return o0(v,m,m.pendingProps.children,S),m.child;case 10:e:{if(O=m.type._context,M=m.pendingProps,ee=m.memoizedProps,b=M.value,Ls(m,b),ee!==null){var Ye=ee.value;if(b=Sn(Ye,b)?0:(typeof O._calculateChangedBits=="function"?O._calculateChangedBits(Ye,b):1073741823)|0,b===0){if(ee.children===M.children&&!b0.current){m=X0(v,m,S);break e}}else for(Ye=m.child,Ye!==null&&(Ye.return=m);Ye!==null;){var Ze=Ye.dependencies;if(Ze!==null){ee=Ye.child;for(var ut=Ze.firstContext;ut!==null;){if(ut.context===O&&(ut.observedBits&b)!=0){Ye.tag===1&&(ut=a0(S,null),ut.tag=2,V0(Ye,ut)),Ye.expirationTime=m&&v<=m}function ao(v,m){var S=v.firstSuspendedTime,O=v.lastSuspendedTime;Sm||S===0)&&(v.lastSuspendedTime=m),m<=v.lastPingedTime&&(v.lastPingedTime=0),m<=v.lastExpiredTime&&(v.lastExpiredTime=0)}function $o(v,m){m>v.firstPendingTime&&(v.firstPendingTime=m);var S=v.firstSuspendedTime;S!==0&&(m>=S?v.firstSuspendedTime=v.lastSuspendedTime=v.nextKnownPendingLevel=0:m>=v.lastSuspendedTime&&(v.lastSuspendedTime=m+1),m>v.nextKnownPendingLevel&&(v.nextKnownPendingLevel=m))}function kl(v,m){var S=v.lastExpiredTime;(S===0||S>m)&&(v.lastExpiredTime=m)}function Nc(v){var m=v._reactInternalFiber;if(m===void 0)throw typeof v.render=="function"?Error(t(188)):Error(t(268,Object.keys(v)));return v=Ue(m),v===null?null:v.stateNode}function Al(v,m){v=v.memoizedState,v!==null&&v.dehydrated!==null&&v.retryTime{"use strict";sE.exports=uE()});var cE=Me((db,fE)=>{"use strict";var gN={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};fE.exports=gN});var hE=Me((pb,aE)=>{"use strict";var _N=Object.assign||function(i){for(var u=1;u"}}]),i}(),dE=function(){Ph(i,null,[{key:"fromJS",value:function(f){var c=f.width,g=f.height;return new i(c,g)}}]);function i(u,f){Iy(this,i),this.width=u,this.height=f}return Ph(i,[{key:"fromJS",value:function(f){f(this.width,this.height)}},{key:"toString",value:function(){return""}}]),i}(),pE=function(){function i(u,f){Iy(this,i),this.unit=u,this.value=f}return Ph(i,[{key:"fromJS",value:function(f){f(this.unit,this.value)}},{key:"toString",value:function(){switch(this.unit){case ps.UNIT_POINT:return String(this.value);case ps.UNIT_PERCENT:return this.value+"%";case ps.UNIT_AUTO:return"auto";default:return this.value+"?"}}},{key:"valueOf",value:function(){return this.value}}]),i}();aE.exports=function(i,u){function f(C,A,x){var D=C[A];C[A]=function(){for(var L=arguments.length,N=Array(L),j=0;j1?N-1:0),$=1;$1&&arguments[1]!==void 0?arguments[1]:NaN,x=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,D=arguments.length>3&&arguments[3]!==void 0?arguments[3]:ps.DIRECTION_LTR;return C.call(this,A,x,D)}),_N({Config:u.Config,Node:u.Node,Layout:i("Layout",yN),Size:i("Size",dE),Value:i("Value",pE),getInstanceCount:function(){return u.getInstanceCount.apply(u,arguments)}},ps)}});var mE=Me((exports,module)=>{(function(i,u){typeof define=="function"&&define.amd?define([],function(){return u}):typeof module=="object"&&module.exports?module.exports=u:(i.nbind=i.nbind||{}).init=u})(exports,function(Module,cb){typeof Module=="function"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(i,u){return function(){i&&i.apply(this,arguments);try{Module.ccall("nbind_init")}catch(f){u(f);return}u(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module!="undefined"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT==="WEB")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT==="WORKER")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT==="NODE")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT==="SHELL")ENVIRONMENT_IS_SHELL=!0;else throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ENVIRONMENT_IS_WEB=typeof window=="object",ENVIRONMENT_IS_WORKER=typeof importScripts=="function",ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof require=="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(u,f){nodeFS||(nodeFS={}("")),nodePath||(nodePath={}("")),u=nodePath.normalize(u);var c=nodeFS.readFileSync(u);return f?c:c.toString()},Module.readBinary=function(u){var f=Module.read(u,!0);return f.buffer||(f=new Uint8Array(f)),assert(f.buffer),f},Module.load=function(u){globalEval(read(u))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\/g,"/"):Module.thisProgram="unknown-program"),Module.arguments=process.argv.slice(2),typeof module!="undefined"&&(module.exports=Module),Module.inspect=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr!="undefined"&&(Module.printErr=printErr),typeof read!="undefined"?Module.read=read:Module.read=function(){throw"no read() available"},Module.readBinary=function(u){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(u));var f=read(u,"binary");return assert(typeof f=="object"),f},typeof scriptArgs!="undefined"?Module.arguments=scriptArgs:typeof arguments!="undefined"&&(Module.arguments=arguments),typeof quit=="function"&&(Module.quit=function(i,u){quit(i)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(u){var f=new XMLHttpRequest;return f.open("GET",u,!1),f.send(null),f.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(u){var f=new XMLHttpRequest;return f.open("GET",u,!1),f.responseType="arraybuffer",f.send(null),new Uint8Array(f.response)}),Module.readAsync=function(u,f,c){var g=new XMLHttpRequest;g.open("GET",u,!0),g.responseType="arraybuffer",g.onload=function(){g.status==200||g.status==0&&g.response?f(g.response):c()},g.onerror=c,g.send(null)},typeof arguments!="undefined"&&(Module.arguments=arguments),typeof console!="undefined")Module.print||(Module.print=function(u){console.log(u)}),Module.printErr||(Module.printErr=function(u){console.warn(u)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump!="undefined"?function(i){dump(i)}:function(i){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle=="undefined"&&(Module.setWindowTitle=function(i){document.title=i})}else throw"Unknown runtime environment. Where are we?";function globalEval(i){eval.call(null,i)}!Module.load&&Module.read&&(Module.load=function(u){globalEval(Module.read(u))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram="./this.program"),Module.quit||(Module.quit=function(i,u){throw u}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(i){return tempRet0=i,i},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(i){STACKTOP=i},getNativeTypeSize:function(i){switch(i){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(i[i.length-1]==="*")return Runtime.QUANTUM_SIZE;if(i[0]==="i"){var u=parseInt(i.substr(1));return assert(u%8==0),u/8}else return 0}}},getNativeFieldSize:function(i){return Math.max(Runtime.getNativeTypeSize(i),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(i,u){return u==="double"||u==="i64"?i&7&&(assert((i&7)==4),i+=4):assert((i&3)==0),i},getAlignSize:function(i,u,f){return!f&&(i=="i64"||i=="double")?8:i?Math.min(u||(i?Runtime.getNativeFieldSize(i):0),Runtime.QUANTUM_SIZE):Math.min(u,8)},dynCall:function(i,u,f){return f&&f.length?Module["dynCall_"+i].apply(null,[u].concat(f)):Module["dynCall_"+i].call(null,u)},functionPointers:[],addFunction:function(i){for(var u=0;u>2],f=(u+i+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=f,f>=TOTAL_MEMORY){var c=enlargeMemory();if(!c)return HEAP32[DYNAMICTOP_PTR>>2]=u,0}return u},alignMemory:function(i,u){var f=i=Math.ceil(i/(u||16))*(u||16);return f},makeBigInt:function(i,u,f){var c=f?+(i>>>0)+ +(u>>>0)*4294967296:+(i>>>0)+ +(u|0)*4294967296;return c},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(i,u){i||abort("Assertion failed: "+u)}function getCFunc(ident){var func=Module["_"+ident];if(!func)try{func=eval("_"+ident)}catch(i){}return assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(i){var u=Runtime.stackAlloc(i.length);return writeArrayToMemory(i,u),u},stringToC:function(i){var u=0;if(i!=null&&i!==0){var f=(i.length<<2)+1;u=Runtime.stackAlloc(f),stringToUTF8(i,u,f)}return u}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(u,f,c,g,t){var C=getCFunc(u),A=[],x=0;if(g)for(var D=0;D>0]=u;break;case"i8":HEAP8[i>>0]=u;break;case"i16":HEAP16[i>>1]=u;break;case"i32":HEAP32[i>>2]=u;break;case"i64":tempI64=[u>>>0,(tempDouble=u,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[i>>2]=tempI64[0],HEAP32[i+4>>2]=tempI64[1];break;case"float":HEAPF32[i>>2]=u;break;case"double":HEAPF64[i>>3]=u;break;default:abort("invalid type for setValue: "+f)}}Module.setValue=setValue;function getValue(i,u,f){switch(u=u||"i8",u.charAt(u.length-1)==="*"&&(u="i32"),u){case"i1":return HEAP8[i>>0];case"i8":return HEAP8[i>>0];case"i16":return HEAP16[i>>1];case"i32":return HEAP32[i>>2];case"i64":return HEAP32[i>>2];case"float":return HEAPF32[i>>2];case"double":return HEAPF64[i>>3];default:abort("invalid type for setValue: "+u)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(i,u,f,c){var g,t;typeof i=="number"?(g=!0,t=i):(g=!1,t=i.length);var C=typeof u=="string"?u:null,A;if(f==ALLOC_NONE?A=c:A=[typeof _malloc=="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][f===void 0?ALLOC_STATIC:f](Math.max(t,C?1:u.length)),g){var c=A,x;for(assert((A&3)==0),x=A+(t&~3);c>2]=0;for(x=A+t;c>0]=0;return A}if(C==="i8")return i.subarray||i.slice?HEAPU8.set(i,A):HEAPU8.set(new Uint8Array(i),A),A;for(var D=0,L,N,j;D>0],f|=c,!(c==0&&!u||(g++,u&&g==u)););u||(u=g);var t="";if(f<128){for(var C=1024,A;u>0;)A=String.fromCharCode.apply(String,HEAPU8.subarray(i,i+Math.min(u,C))),t=t?t+A:A,i+=C,u-=C;return t}return Module.UTF8ToString(i)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(i){for(var u="";;){var f=HEAP8[i++>>0];if(!f)return u;u+=String.fromCharCode(f)}}Module.AsciiToString=AsciiToString;function stringToAscii(i,u){return writeAsciiToMemory(i,u,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):void 0;function UTF8ArrayToString(i,u){for(var f=u;i[f];)++f;if(f-u>16&&i.subarray&&UTF8Decoder)return UTF8Decoder.decode(i.subarray(u,f));for(var c,g,t,C,A,x,D="";;){if(c=i[u++],!c)return D;if(!(c&128)){D+=String.fromCharCode(c);continue}if(g=i[u++]&63,(c&224)==192){D+=String.fromCharCode((c&31)<<6|g);continue}if(t=i[u++]&63,(c&240)==224?c=(c&15)<<12|g<<6|t:(C=i[u++]&63,(c&248)==240?c=(c&7)<<18|g<<12|t<<6|C:(A=i[u++]&63,(c&252)==248?c=(c&3)<<24|g<<18|t<<12|C<<6|A:(x=i[u++]&63,c=(c&1)<<30|g<<24|t<<18|C<<12|A<<6|x))),c<65536)D+=String.fromCharCode(c);else{var L=c-65536;D+=String.fromCharCode(55296|L>>10,56320|L&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(i){return UTF8ArrayToString(HEAPU8,i)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(i,u,f,c){if(!(c>0))return 0;for(var g=f,t=f+c-1,C=0;C=55296&&A<=57343&&(A=65536+((A&1023)<<10)|i.charCodeAt(++C)&1023),A<=127){if(f>=t)break;u[f++]=A}else if(A<=2047){if(f+1>=t)break;u[f++]=192|A>>6,u[f++]=128|A&63}else if(A<=65535){if(f+2>=t)break;u[f++]=224|A>>12,u[f++]=128|A>>6&63,u[f++]=128|A&63}else if(A<=2097151){if(f+3>=t)break;u[f++]=240|A>>18,u[f++]=128|A>>12&63,u[f++]=128|A>>6&63,u[f++]=128|A&63}else if(A<=67108863){if(f+4>=t)break;u[f++]=248|A>>24,u[f++]=128|A>>18&63,u[f++]=128|A>>12&63,u[f++]=128|A>>6&63,u[f++]=128|A&63}else{if(f+5>=t)break;u[f++]=252|A>>30,u[f++]=128|A>>24&63,u[f++]=128|A>>18&63,u[f++]=128|A>>12&63,u[f++]=128|A>>6&63,u[f++]=128|A&63}}return u[f]=0,f-g}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(i,u,f){return stringToUTF8Array(i,HEAPU8,u,f)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(i){for(var u=0,f=0;f=55296&&c<=57343&&(c=65536+((c&1023)<<10)|i.charCodeAt(++f)&1023),c<=127?++u:c<=2047?u+=2:c<=65535?u+=3:c<=2097151?u+=4:c<=67108863?u+=5:u+=6}return u}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf-16le"):void 0;function demangle(i){var u=Module.___cxa_demangle||Module.__cxa_demangle;if(u){try{var f=i.substr(1),c=lengthBytesUTF8(f)+1,g=_malloc(c);stringToUTF8(f,g,c);var t=_malloc(4),C=u(g,0,0,t);if(getValue(t,"i32")===0&&C)return Pointer_stringify(C)}catch(A){}finally{g&&_free(g),t&&_free(t),C&&_free(C)}return i}return Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"),i}function demangleAll(i){var u=/__Z[\w\d_]+/g;return i.replace(u,function(f){var c=demangle(f);return f===c?f:f+" ["+c+"]"})}function jsStackTrace(){var i=new Error;if(!i.stack){try{throw new Error(0)}catch(u){i=u}if(!i.stack)return"(no stack trace available)"}return i.stack.toString()}function stackTrace(){var i=jsStackTrace();return Module.extraStackTrace&&(i+=` + `+Module.extraStackTrace()),demangleAll(i)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY0;){var u=i.shift();if(typeof u=="function"){u();continue}var f=u.func;typeof f=="number"?u.arg===void 0?Module.dynCall_v(f):Module.dynCall_vi(f,u.arg):f(u.arg===void 0?null:u.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(i){__ATPRERUN__.unshift(i)}Module.addOnPreRun=addOnPreRun;function addOnInit(i){__ATINIT__.unshift(i)}Module.addOnInit=addOnInit;function addOnPreMain(i){__ATMAIN__.unshift(i)}Module.addOnPreMain=addOnPreMain;function addOnExit(i){__ATEXIT__.unshift(i)}Module.addOnExit=addOnExit;function addOnPostRun(i){__ATPOSTRUN__.unshift(i)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(i,u,f){var c=f>0?f:lengthBytesUTF8(i)+1,g=new Array(c),t=stringToUTF8Array(i,g,0,g.length);return u&&(g.length=t),g}Module.intArrayFromString=intArrayFromString;function intArrayToString(i){for(var u=[],f=0;f255&&(c&=255),u.push(String.fromCharCode(c))}return u.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(i,u,f){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var c,g;f&&(g=u+lengthBytesUTF8(i),c=HEAP8[g]),stringToUTF8(i,u,Infinity),f&&(HEAP8[g]=c)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(i,u){HEAP8.set(i,u)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(i,u,f){for(var c=0;c>0]=i.charCodeAt(c);f||(HEAP8[u>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function(u,f){var c=u>>>16,g=u&65535,t=f>>>16,C=f&65535;return g*C+(c*C+g*t<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(i){return froundBuffer[0]=i,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(i){i=i>>>0;for(var u=0;u<32;u++)if(i&1<<31-u)return u;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(i){return i<0?Math.ceil(i):Math.floor(i)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(i){return i}function addRunDependency(i){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(i){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var u=dependenciesFulfilled;dependenciesFulfilled=null,u()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(i,u,f,c,g,t,C,A){return _nbind.callbackSignatureList[i].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(i,u,f,c,g,t,C,A){return ASM_CONSTS[i](u,f,c,g,t,C,A)}function _emscripten_asm_const_iiiii(i,u,f,c,g){return ASM_CONSTS[i](u,f,c,g)}function _emscripten_asm_const_iiidddddd(i,u,f,c,g,t,C,A,x){return ASM_CONSTS[i](u,f,c,g,t,C,A,x)}function _emscripten_asm_const_iiididi(i,u,f,c,g,t,C){return ASM_CONSTS[i](u,f,c,g,t,C)}function _emscripten_asm_const_iiii(i,u,f,c){return ASM_CONSTS[i](u,f,c)}function _emscripten_asm_const_iiiid(i,u,f,c,g){return ASM_CONSTS[i](u,f,c,g)}function _emscripten_asm_const_iiiiii(i,u,f,c,g,t){return ASM_CONSTS[i](u,f,c,g,t)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(i,u){__ATEXIT__.unshift({func:i,arg:u})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr("missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj"),abort(-1)}function __decorate(i,u,f,c){var g=arguments.length,t=g<3?u:c===null?c=Object.getOwnPropertyDescriptor(u,f):c,C;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(i,u,f,c);else for(var A=i.length-1;A>=0;A--)(C=i[A])&&(t=(g<3?C(t):g>3?C(u,f,t):C(u,f))||t);return g>3&&t&&Object.defineProperty(u,f,t),t}function _defineHidden(i){return function(u,f){Object.defineProperty(u,f,{configurable:!1,enumerable:!1,value:i,writable:!0})}}var _nbind={};function __nbind_free_external(i){_nbind.externalList[i].dereference(i)}function __nbind_reference_external(i){_nbind.externalList[i].reference()}function _llvm_stackrestore(i){var u=_llvm_stacksave,f=u.LLVM_SAVEDSTACKS[i];u.LLVM_SAVEDSTACKS.splice(i,1),Runtime.stackRestore(f)}function __nbind_register_pool(i,u,f,c){_nbind.Pool.pageSize=i,_nbind.Pool.usedPtr=u/4,_nbind.Pool.rootPtr=f,_nbind.Pool.pagePtr=c/4,HEAP32[u/4]=16909060,HEAP8[u]==1&&(_nbind.bigEndian=!0),HEAP32[u/4]=0,_nbind.makeTypeKindTbl=(t={},t[1024]=_nbind.PrimitiveType,t[64]=_nbind.Int64Type,t[2048]=_nbind.BindClass,t[3072]=_nbind.BindClassPtr,t[4096]=_nbind.SharedClassPtr,t[5120]=_nbind.ArrayType,t[6144]=_nbind.ArrayType,t[7168]=_nbind.CStringType,t[9216]=_nbind.CallbackType,t[10240]=_nbind.BindType,t),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,"cbFunction &":_nbind.CallbackType,"const cbFunction &":_nbind.CallbackType,"const std::string &":_nbind.StringType,"std::string":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var g=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:""});g.proto=Module,_nbind.BindClass.list.push(g);var t}function _emscripten_set_main_loop_timing(i,u){if(Browser.mainLoop.timingMode=i,Browser.mainLoop.timingValue=u,!Browser.mainLoop.func)return 1;if(i==0)Browser.mainLoop.scheduler=function(){var C=Math.max(0,Browser.mainLoop.tickStartTime+u-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,C)},Browser.mainLoop.method="timeout";else if(i==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method="rAF";else if(i==2){if(!window.setImmediate){let t=function(C){C.source===window&&C.data===c&&(C.stopPropagation(),f.shift()())};var g=t,f=[],c="setimmediate";window.addEventListener("message",t,!0),window.setImmediate=function(A){f.push(A),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(A),window.postMessage({target:c})):window.postMessage(c,"*")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(i,u,f,c,g){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),Browser.mainLoop.func=i,Browser.mainLoop.arg=c;var t;typeof c!="undefined"?t=function(){Module.dynCall_vi(i,c)}:t=function(){Module.dynCall_v(i)};var C=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var x=Date.now(),D=Browser.mainLoop.queue.shift();if(D.func(D.arg),Browser.mainLoop.remainingBlockers){var L=Browser.mainLoop.remainingBlockers,N=L%1==0?L-1:Math.floor(L);D.counted?Browser.mainLoop.remainingBlockers=N:(N=N+.5,Browser.mainLoop.remainingBlockers=(8*L+N)/9)}if(console.log('main loop blocker "'+D.name+'" took '+(Date.now()-x)+" ms"),Browser.mainLoop.updateStatus(),C1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method==="timeout"&&Module.ctx&&(Module.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Browser.mainLoop.method=""),Browser.mainLoop.runIter(t),!(C0?_emscripten_set_main_loop_timing(0,1e3/u):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),f)throw"SimulateInfiniteLoop"}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var i=Browser.mainLoop.timingMode,u=Browser.mainLoop.timingValue,f=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(f,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(i,u),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var i=Module.statusMessage||"Please wait...",u=Browser.mainLoop.remainingBlockers,f=Browser.mainLoop.expectedBlockers;u?u=6;){var Le=J>>Te-6&63;Te-=6,De+=Se[Le]}return Te==2?(De+=Se[(J&3)<<4],De+=me+me):Te==4&&(De+=Se[(J&15)<<2],De+=me),De}h.src="data:audio/x-"+C.substr(-3)+";base64,"+Q(t),L(h)},h.src=$,Browser.safeSetTimeout(function(){L(h)},1e4)}else return N()},Module.preloadPlugins.push(u);function f(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var c=Module.canvas;c&&(c.requestPointerLock=c.requestPointerLock||c.mozRequestPointerLock||c.webkitRequestPointerLock||c.msRequestPointerLock||function(){},c.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},c.exitPointerLock=c.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",f,!1),document.addEventListener("mozpointerlockchange",f,!1),document.addEventListener("webkitpointerlockchange",f,!1),document.addEventListener("mspointerlockchange",f,!1),Module.elementPointerLock&&c.addEventListener("click",function(g){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),g.preventDefault())},!1))},createContext:function(i,u,f,c){if(u&&Module.ctx&&i==Module.canvas)return Module.ctx;var g,t;if(u){var C={antialias:!1,alpha:!1};if(c)for(var A in c)C[A]=c[A];t=GL.createContext(i,C),t&&(g=GL.getContext(t).GLctx)}else g=i.getContext("2d");return g?(f&&(u||assert(typeof GLctx=="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),Module.ctx=g,u&&GL.makeContextCurrent(t),Module.useWebGL=u,Browser.moduleContextCreatedCallbacks.forEach(function(x){x()}),Browser.init()),g):null},destroyContext:function(i,u,f){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(i,u,f){Browser.lockPointer=i,Browser.resizeCanvas=u,Browser.vrDevice=f,typeof Browser.lockPointer=="undefined"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas=="undefined"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice=="undefined"&&(Browser.vrDevice=null);var c=Module.canvas;function g(){Browser.isFullscreen=!1;var C=c.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===C?(c.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},c.exitFullscreen=c.exitFullscreen.bind(document),Browser.lockPointer&&c.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(C.parentNode.insertBefore(c,C),C.parentNode.removeChild(C),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(c)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",g,!1),document.addEventListener("mozfullscreenchange",g,!1),document.addEventListener("webkitfullscreenchange",g,!1),document.addEventListener("MSFullscreenChange",g,!1));var t=document.createElement("div");c.parentNode.insertBefore(t,c),t.appendChild(c),t.requestFullscreen=t.requestFullscreen||t.mozRequestFullScreen||t.msRequestFullscreen||(t.webkitRequestFullscreen?function(){t.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(t.webkitRequestFullScreen?function(){t.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),f?t.requestFullscreen({vrDisplay:f}):t.requestFullscreen()},requestFullScreen:function(i,u,f){return Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."),Browser.requestFullScreen=function(c,g,t){return Browser.requestFullscreen(c,g,t)},Browser.requestFullscreen(i,u,f)},nextRAF:0,fakeRequestAnimationFrame:function(i){var u=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=u+1e3/60;else for(;u+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var f=Math.max(Browser.nextRAF-u,0);setTimeout(i,f)},requestAnimationFrame:function(u){typeof window=="undefined"?Browser.fakeRequestAnimationFrame(u):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(u))},safeCallback:function(i){return function(){if(!ABORT)return i.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var i=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],i.forEach(function(u){u()})}},safeRequestAnimationFrame:function(i){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?i():Browser.queuedAsyncCallbacks.push(i))})},safeSetTimeout:function(i,u){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?i():Browser.queuedAsyncCallbacks.push(i))},u)},safeSetInterval:function(i,u){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&i()},u)},getMimetype:function(i){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[i.substr(i.lastIndexOf(".")+1)]},getUserMedia:function(i){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(i)},getMovementX:function(i){return i.movementX||i.mozMovementX||i.webkitMovementX||0},getMovementY:function(i){return i.movementY||i.mozMovementY||i.webkitMovementY||0},getMouseWheelDelta:function(i){var u=0;switch(i.type){case"DOMMouseScroll":u=i.detail;break;case"mousewheel":u=i.wheelDelta;break;case"wheel":u=i.deltaY;break;default:throw"unrecognized mouse wheel event: "+i.type}return u},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(i){if(Browser.pointerLock)i.type!="mousemove"&&"mozMovementX"in i?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(i),Browser.mouseMovementY=Browser.getMovementY(i)),typeof SDL!="undefined"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var u=Module.canvas.getBoundingClientRect(),f=Module.canvas.width,c=Module.canvas.height,g=typeof window.scrollX!="undefined"?window.scrollX:window.pageXOffset,t=typeof window.scrollY!="undefined"?window.scrollY:window.pageYOffset;if(i.type==="touchstart"||i.type==="touchend"||i.type==="touchmove"){var C=i.touch;if(C===void 0)return;var A=C.pageX-(g+u.left),x=C.pageY-(t+u.top);A=A*(f/u.width),x=x*(c/u.height);var D={x:A,y:x};if(i.type==="touchstart")Browser.lastTouches[C.identifier]=D,Browser.touches[C.identifier]=D;else if(i.type==="touchend"||i.type==="touchmove"){var L=Browser.touches[C.identifier];L||(L=D),Browser.lastTouches[C.identifier]=L,Browser.touches[C.identifier]=D}return}var N=i.pageX-(g+u.left),j=i.pageY-(t+u.top);N=N*(f/u.width),j=j*(c/u.height),Browser.mouseMovementX=N-Browser.mouseX,Browser.mouseMovementY=j-Browser.mouseY,Browser.mouseX=N,Browser.mouseY=j}},asyncLoad:function(i,u,f,c){var g=c?"":getUniqueRunDependency("al "+i);Module.readAsync(i,function(t){assert(t,'Loading data file "'+i+'" failed (no arrayBuffer).'),u(new Uint8Array(t)),g&&removeRunDependency(g)},function(t){if(f)f();else throw'Loading data file "'+i+'" failed.'}),g&&addRunDependency(g)},resizeListeners:[],updateResizeListeners:function(){var i=Module.canvas;Browser.resizeListeners.forEach(function(u){u(i.width,i.height)})},setCanvasSize:function(i,u,f){var c=Module.canvas;Browser.updateCanvasDimensions(c,i,u),f||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var i=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];i=i|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=i}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var i=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];i=i&~8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=i}Browser.updateResizeListeners()},updateCanvasDimensions:function(i,u,f){u&&f?(i.widthNative=u,i.heightNative=f):(u=i.widthNative,f=i.heightNative);var c=u,g=f;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(c/g>2];return u},getStr:function(){var i=Pointer_stringify(SYSCALLS.get());return i},get64:function(){var i=SYSCALLS.get(),u=SYSCALLS.get();return i>=0?assert(u===0):assert(u===-1),i},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(i,u){SYSCALLS.varargs=u;try{var f=SYSCALLS.getStreamFromFD();return FS.close(f),0}catch(c){return(typeof FS=="undefined"||!(c instanceof FS.ErrnoError))&&abort(c),-c.errno}}function ___syscall54(i,u){SYSCALLS.varargs=u;try{return 0}catch(f){return(typeof FS=="undefined"||!(f instanceof FS.ErrnoError))&&abort(f),-f.errno}}function _typeModule(i){var u=[[0,1,"X"],[1,1,"const X"],[128,1,"X *"],[256,1,"X &"],[384,1,"X &&"],[512,1,"std::shared_ptr"],[640,1,"std::unique_ptr"],[5120,1,"std::vector"],[6144,2,"std::array"],[9216,-1,"std::function"]];function f(x,D,L,N,j,$){if(D==1){var h=N&896;(h==128||h==256||h==384)&&(x="X const")}var re;return $?re=L.replace("X",x).replace("Y",j):re=x.replace("X",L).replace("Y",j),re.replace(/([*&]) (?=[*&])/g,"$1")}function c(x,D,L,N,j){throw new Error(x+" type "+L.replace("X",D+"?")+(N?" with flag "+N:"")+" in "+j)}function g(x,D,L,N,j,$,h,re){$===void 0&&($="X"),re===void 0&&(re=1);var ce=L(x);if(ce)return ce;var Q=N(x),oe=Q.placeholderFlag,Se=u[oe];h&&Se&&($=f(h[2],h[0],$,Se[0],"?",!0));var me;oe==0&&(me="Unbound"),oe>=10&&(me="Corrupt"),re>20&&(me="Deeply nested"),me&&c(me,x,$,oe,j||"?");var De=Q.paramList[0],J=g(De,D,L,N,j,$,Se,re+1),Te,Oe={flags:Se[0],id:x,name:"",paramList:[J]},Le=[],ot="?";switch(Q.placeholderFlag){case 1:Te=J.spec;break;case 2:if((J.flags&15360)==1024&&J.spec.ptrSize==1){Oe.flags=7168;break}case 3:case 6:case 5:Te=J.spec,(J.flags&15360)!=2048;break;case 8:ot=""+Q.paramList[1],Oe.paramList.push(Q.paramList[1]);break;case 9:for(var ct=0,Ue=Q.paramList[1];ct>2]=i),i}function _llvm_stacksave(){var i=_llvm_stacksave;return i.LLVM_SAVEDSTACKS||(i.LLVM_SAVEDSTACKS=[]),i.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),i.LLVM_SAVEDSTACKS.length-1}function ___syscall140(i,u){SYSCALLS.varargs=u;try{var f=SYSCALLS.getStreamFromFD(),c=SYSCALLS.get(),g=SYSCALLS.get(),t=SYSCALLS.get(),C=SYSCALLS.get(),A=g;return FS.llseek(f,A,C),HEAP32[t>>2]=f.position,f.getdents&&A===0&&C===0&&(f.getdents=null),0}catch(x){return(typeof FS=="undefined"||!(x instanceof FS.ErrnoError))&&abort(x),-x.errno}}function ___syscall146(i,u){SYSCALLS.varargs=u;try{var f=SYSCALLS.get(),c=SYSCALLS.get(),g=SYSCALLS.get(),t=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(L,N){var j=___syscall146.buffers[L];assert(j),N===0||N===10?((L===1?Module.print:Module.printErr)(UTF8ArrayToString(j,0)),j.length=0):j.push(N)});for(var C=0;C>2],x=HEAP32[c+(C*8+4)>>2],D=0;Di.pageSize/2||u>i.pageSize-f){var c=_nbind.typeNameTbl.NBind.proto;return c.lalloc(u)}else return HEAPU32[i.usedPtr]=f+u,i.rootPtr+f},i.lreset=function(u,f){var c=HEAPU32[i.pagePtr];if(c){var g=_nbind.typeNameTbl.NBind.proto;g.lreset(u,f)}else HEAPU32[i.usedPtr]=u},i}();_nbind.Pool=Pool;function constructType(i,u){var f=i==10240?_nbind.makeTypeNameTbl[u.name]||_nbind.BindType:_nbind.makeTypeKindTbl[i],c=new f(u);return typeIdTbl[u.id]=c,_nbind.typeNameTbl[u.name]=c,c}_nbind.constructType=constructType;function getType(i){return typeIdTbl[i]}_nbind.getType=getType;function queryType(i){var u=HEAPU8[i],f=_nbind.structureList[u][1];i/=4,f<0&&(++i,f=HEAPU32[i]+1);var c=Array.prototype.slice.call(HEAPU32.subarray(i+1,i+1+f));return u==9&&(c=[c[0],c.slice(1)]),{paramList:c,placeholderFlag:u}}_nbind.queryType=queryType;function getTypes(i,u){return i.map(function(f){return typeof f=="number"?_nbind.getComplexType(f,constructType,getType,queryType,u):_nbind.typeNameTbl[f]})}_nbind.getTypes=getTypes;function readTypeIdList(i,u){return Array.prototype.slice.call(HEAPU32,i/4,i/4+u)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(i){for(var u=i;HEAPU8[u++];);return String.fromCharCode.apply("",HEAPU8.subarray(i,u-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(i){var u={};if(i)for(;;){var f=HEAPU32[i/4];if(!f)break;u[readAsciiString(f)]=!0,i+=4}return u}_nbind.readPolicyList=readPolicyList;function getDynCall(i,u){var f={float32_t:"d",float64_t:"d",int64_t:"d",uint64_t:"d",void:"v"},c=i.map(function(t){return f[t.name]||"i"}).join(""),g=Module["dynCall_"+c];if(!g)throw new Error("dynCall_"+c+" not found for "+u+"("+i.map(function(t){return t.name}).join(", ")+")");return g}_nbind.getDynCall=getDynCall;function addMethod(i,u,f,c){var g=i[u];i.hasOwnProperty(u)&&g?((g.arity||g.arity===0)&&(g=_nbind.makeOverloader(g,g.arity),i[u]=g),g.addMethod(f,c)):(f.arity=c,i[u]=f)}_nbind.addMethod=addMethod;function throwError(i){throw new Error(i)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(i){__extends(u,i);function u(){var f=i!==null&&i.apply(this,arguments)||this;return f.heap=HEAPU32,f.ptrSize=4,f}return u.prototype.needsWireRead=function(f){return!!this.wireRead||!!this.makeWireRead},u.prototype.needsWireWrite=function(f){return!!this.wireWrite||!!this.makeWireWrite},u}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(i){__extends(u,i);function u(f){var c=i.call(this,f)||this,g=f.flags&32?{32:HEAPF32,64:HEAPF64}:f.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return c.heap=g[f.ptrSize*8],c.ptrSize=f.ptrSize,c}return u.prototype.needsWireWrite=function(f){return!!f&&!!f.Strict},u.prototype.makeWireWrite=function(f,c){return c&&c.Strict&&function(g){if(typeof g=="number")return g;throw new Error("Type mismatch")}},u}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(i,u){if(i==null){if(u&&u.Nullable)return 0;throw new Error("Type mismatch")}if(u&&u.Strict){if(typeof i!="string")throw new Error("Type mismatch")}else i=i.toString();var f=Module.lengthBytesUTF8(i)+1,c=_nbind.Pool.lalloc(f);return Module.stringToUTF8Array(i,HEAPU8,c,f),c}_nbind.pushCString=pushCString;function popCString(i){return i===0?null:Module.Pointer_stringify(i)}_nbind.popCString=popCString;var CStringType=function(i){__extends(u,i);function u(){var f=i!==null&&i.apply(this,arguments)||this;return f.wireRead=popCString,f.wireWrite=pushCString,f.readResources=[_nbind.resources.pool],f.writeResources=[_nbind.resources.pool],f}return u.prototype.makeWireWrite=function(f,c){return function(g){return pushCString(g,c)}},u}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(i){__extends(u,i);function u(){var f=i!==null&&i.apply(this,arguments)||this;return f.wireRead=function(c){return!!c},f}return u.prototype.needsWireWrite=function(f){return!!f&&!!f.Strict},u.prototype.makeWireRead=function(f){return"!!("+f+")"},u.prototype.makeWireWrite=function(f,c){return c&&c.Strict&&function(g){if(typeof g=="boolean")return g;throw new Error("Type mismatch")}||f},u}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function i(){}return i.prototype.persist=function(){this.__nbindState|=1},i}();_nbind.Wrapper=Wrapper;function makeBound(i,u){var f=function(c){__extends(g,c);function g(t,C,A,x){var D=c.call(this)||this;if(!(D instanceof g))return new(Function.prototype.bind.apply(g,Array.prototype.concat.apply([null],arguments)));var L=C,N=A,j=x;if(t!==_nbind.ptrMarker){var $=D.__nbindConstructor.apply(D,arguments);L=4096|512,j=HEAPU32[$/4],N=HEAPU32[$/4+1]}var h={configurable:!0,enumerable:!1,value:null,writable:!1},re={__nbindFlags:L,__nbindPtr:N};j&&(re.__nbindShared=j,_nbind.mark(D));for(var ce=0,Q=Object.keys(re);ce>=1;var f=_nbind.valueList[i];return _nbind.valueList[i]=firstFreeValue,firstFreeValue=i,f}else{if(u)return _nbind.popShared(i,u);throw new Error("Invalid value slot "+i)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(i){return typeof i=="number"?i:pushValue(i)*4096+valueBase}function pop64(i){return i=3?C=Buffer.from(t):C=new Buffer(t),C.copy(c)}else getBuffer(c).set(t)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var i=0,u=dirtyList;i>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(i,u,f,c,g,t){try{Module.dynCall_viiiii(i,u,f,c,g,t)}catch(C){if(typeof C!="number"&&C!=="longjmp")throw C;Module.setThrew(1,0)}}function invoke_vif(i,u,f){try{Module.dynCall_vif(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_vid(i,u,f){try{Module.dynCall_vid(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_fiff(i,u,f,c){try{return Module.dynCall_fiff(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_vi(i,u){try{Module.dynCall_vi(i,u)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_vii(i,u,f){try{Module.dynCall_vii(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_ii(i,u){try{return Module.dynCall_ii(i,u)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_viddi(i,u,f,c,g){try{Module.dynCall_viddi(i,u,f,c,g)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_vidd(i,u,f,c){try{Module.dynCall_vidd(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_iiii(i,u,f,c){try{return Module.dynCall_iiii(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_diii(i,u,f,c){try{return Module.dynCall_diii(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_di(i,u){try{return Module.dynCall_di(i,u)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_iid(i,u,f){try{return Module.dynCall_iid(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_iii(i,u,f){try{return Module.dynCall_iii(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_viiddi(i,u,f,c,g,t){try{Module.dynCall_viiddi(i,u,f,c,g,t)}catch(C){if(typeof C!="number"&&C!=="longjmp")throw C;Module.setThrew(1,0)}}function invoke_viiiiii(i,u,f,c,g,t,C){try{Module.dynCall_viiiiii(i,u,f,c,g,t,C)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_dii(i,u,f){try{return Module.dynCall_dii(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_i(i){try{return Module.dynCall_i(i)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_iiiiii(i,u,f,c,g,t){try{return Module.dynCall_iiiiii(i,u,f,c,g,t)}catch(C){if(typeof C!="number"&&C!=="longjmp")throw C;Module.setThrew(1,0)}}function invoke_viiid(i,u,f,c,g){try{Module.dynCall_viiid(i,u,f,c,g)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_viififi(i,u,f,c,g,t,C){try{Module.dynCall_viififi(i,u,f,c,g,t,C)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_viii(i,u,f,c){try{Module.dynCall_viii(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_v(i){try{Module.dynCall_v(i)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_viid(i,u,f,c){try{Module.dynCall_viid(i,u,f,c)}catch(g){if(typeof g!="number"&&g!=="longjmp")throw g;Module.setThrew(1,0)}}function invoke_idd(i,u,f){try{return Module.dynCall_idd(i,u,f)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_viiii(i,u,f,c,g){try{Module.dynCall_viiii(i,u,f,c,g)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:Infinity},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(i,u,f){var c=new i.Int8Array(f),g=new i.Int16Array(f),t=new i.Int32Array(f),C=new i.Uint8Array(f),A=new i.Uint16Array(f),x=new i.Uint32Array(f),D=new i.Float32Array(f),L=new i.Float64Array(f),N=u.DYNAMICTOP_PTR|0,j=u.tempDoublePtr|0,$=u.ABORT|0,h=u.STACKTOP|0,re=u.STACK_MAX|0,ce=u.cttz_i8|0,Q=u.___dso_handle|0,oe=0,Se=0,me=0,De=0,J=i.NaN,Te=i.Infinity,Oe=0,Le=0,ot=0,ct=0,Ue=0,be=0,At=i.Math.floor,Ot=i.Math.abs,Nt=i.Math.sqrt,Je=i.Math.pow,V=i.Math.cos,ne=i.Math.sin,ge=i.Math.tan,Z=i.Math.acos,Ae=i.Math.asin,at=i.Math.atan,it=i.Math.atan2,Ft=i.Math.exp,jt=i.Math.log,hn=i.Math.ceil,Un=i.Math.imul,Jt=i.Math.min,Yt=i.Math.max,cr=i.Math.clz32,w=i.Math.fround,pt=u.abort,Mn=u.assert,Bn=u.enlargeMemory,Xn=u.getTotalMemory,vr=u.abortOnCannotGrowMemory,gr=u.invoke_viiiii,r0=u.invoke_vif,Ci=u.invoke_vid,yo=u.invoke_fiff,Ds=u.invoke_vi,Mu=u.invoke_vii,Gf=u.invoke_ii,iu=u.invoke_viddi,ou=u.invoke_vidd,ol=u.invoke_iiii,ul=u.invoke_diii,Es=u.invoke_di,Uo=u.invoke_iid,sl=u.invoke_iii,Ss=u.invoke_viiddi,Cs=u.invoke_viiiiii,Ti=u.invoke_dii,Fu=u.invoke_i,ll=u.invoke_iiiiii,fl=u.invoke_viiid,cl=u.invoke_viififi,al=u.invoke_viii,Ui=u.invoke_v,Mr=u.invoke_viid,Ac=u.invoke_idd,of=u.invoke_viiii,Ts=u._emscripten_asm_const_iiiii,xs=u._emscripten_asm_const_iiidddddd,dl=u._emscripten_asm_const_iiiid,qi=u.__nbind_reference_external,qo=u._emscripten_asm_const_iiiiiiii,kr=u._removeAccessorPrefix,Fr=u._typeModule,si=u.__nbind_register_pool,H0=u.__decorate,b0=u._llvm_stackrestore,Bt=u.___cxa_atexit,Lu=u.__extends,c0=u.__nbind_get_value_object,Ru=u.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,ks=u._emscripten_set_main_loop_timing,As=u.__nbind_register_primitive,uu=u.__nbind_register_type,wo=u._emscripten_memcpy_big,zo=u.__nbind_register_function,Os=u.___setErrNo,Is=u.__nbind_register_class,uf=u.__nbind_finish,_n=u._abort,Nu=u._nbind_value,Wo=u._llvm_stacksave,su=u.___syscall54,Ps=u._defineHidden,pl=u._emscripten_set_main_loop,Vf=u._emscripten_get_now,hl=u.__nbind_register_callback_signature,Bu=u._emscripten_asm_const_iiiiii,ju=u.__nbind_free_external,sf=u._emscripten_asm_const_iiii,ro=u._emscripten_asm_const_iiididi,Ms=u.___syscall6,ml=u._atexit,Uu=u.___syscall140,G0=u.___syscall146,Fs=w(0);let tt=w(0);function zi(e){e=e|0;var n=0;return n=h,h=h+e|0,h=h+15&-16,n|0}function lu(){return h|0}function Ho(e){e=e|0,h=e}function O0(e,n){e=e|0,n=n|0,h=e,re=n}function vl(e,n){e=e|0,n=n|0,oe||(oe=e,Se=n)}function gl(e){e=e|0,be=e}function fu(){return be|0}function _l(){var e=0,n=0;vn(8104,8,400)|0,vn(8504,408,540)|0,e=9044,n=e+44|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));c[9088]=0,c[9089]=1,t[2273]=0,t[2274]=948,t[2275]=948,Bt(17,8104,Q|0)|0}function Sn(e){e=e|0,lf(e+948|0)}function gt(e){return e=w(e),((Ar(e)|0)&2147483647)>>>0>2139095040|0}function en(e,n,r){e=e|0,n=n|0,r=r|0;e:do if(t[e+(n<<3)+4>>2]|0)e=e+(n<<3)|0;else{if((n|2|0)==3?t[e+60>>2]|0:0){e=e+56|0;break}switch(n|0){case 0:case 2:case 4:case 5:{if(t[e+52>>2]|0){e=e+48|0;break e}break}default:}if(t[e+68>>2]|0){e=e+64|0;break}else{e=(n|1|0)==5?948:r;break}}while(0);return e|0}function I0(e){e=e|0;var n=0;return n=uh(1e3)|0,li(e,(n|0)!=0,2456),t[2276]=(t[2276]|0)+1,vn(n|0,8104,1e3)|0,c[e+2>>0]|0&&(t[n+4>>2]=2,t[n+12>>2]=4),t[n+976>>2]=e,n|0}function li(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;s=h,h=h+16|0,o=s,n||(t[o>>2]=r,zs(e,5,3197,o)),h=s}function qu(){return I0(956)|0}function Wi(e){e=e|0;var n=0;return n=Tt(1e3)|0,zu(n,e),li(t[e+976>>2]|0,1,2456),t[2276]=(t[2276]|0)+1,t[n+944>>2]=0,n|0}function zu(e,n){e=e|0,n=n|0;var r=0;vn(e|0,n|0,948)|0,af(e+948|0,n+948|0),r=e+960|0,e=n+960|0,n=r+40|0;do t[r>>2]=t[e>>2],r=r+4|0,e=e+4|0;while((r|0)<(n|0))}function Wu(e){e=e|0;var n=0,r=0,o=0,s=0;if(n=e+944|0,r=t[n>>2]|0,r|0&&(Ls(r+948|0,e)|0,t[n>>2]=0),r=fi(e)|0,r|0){n=0;do t[(e0(e,n)|0)+944>>2]=0,n=n+1|0;while((n|0)!=(r|0))}r=e+948|0,o=t[r>>2]|0,s=e+952|0,n=t[s>>2]|0,(n|0)!=(o|0)&&(t[s>>2]=n+(~((n+-4-o|0)>>>2)<<2)),io(r),sh(e),t[2276]=(t[2276]|0)+-1}function Ls(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0;o=t[e>>2]|0,_=e+4|0,r=t[_>>2]|0,l=r;e:do if((o|0)==(r|0))s=o,d=4;else for(e=o;;){if((t[e>>2]|0)==(n|0)){s=e,d=4;break e}if(e=e+4|0,(e|0)==(r|0)){e=0;break}}while(0);return(d|0)==4&&((s|0)!=(r|0)?(o=s+4|0,e=l-o|0,n=e>>2,n&&(Y1(s|0,o|0,e|0)|0,r=t[_>>2]|0),e=s+(n<<2)|0,(r|0)==(e|0)||(t[_>>2]=r+(~((r+-4-e|0)>>>2)<<2)),e=1):e=0),e|0}function fi(e){return e=e|0,(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2|0}function e0(e,n){e=e|0,n=n|0;var r=0;return r=t[e+948>>2]|0,(t[e+952>>2]|0)-r>>2>>>0>n>>>0?e=t[r+(n<<2)>>2]|0:e=0,e|0}function io(e){e=e|0;var n=0,r=0,o=0,s=0;o=h,h=h+32|0,n=o,s=t[e>>2]|0,r=(t[e+4>>2]|0)-s|0,((t[e+8>>2]|0)-s|0)>>>0>r>>>0&&(s=r>>2,z(n,s,s,e+8|0),dr(e,n),Or(n)),h=o}function D0(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0;k=fi(e)|0;do if(k|0){if((t[(e0(e,0)|0)+944>>2]|0)==(e|0)){if(!(Ls(e+948|0,n)|0))break;vn(n+400|0,8504,540)|0,t[n+944>>2]=0,ln(e);break}d=t[(t[e+976>>2]|0)+12>>2]|0,_=e+948|0,y=(d|0)==0,r=0,l=0;do o=t[(t[_>>2]|0)+(l<<2)>>2]|0,(o|0)==(n|0)?ln(e):(s=Wi(o)|0,t[(t[_>>2]|0)+(r<<2)>>2]=s,t[s+944>>2]=e,y||Q4[d&15](o,s,e,r),r=r+1|0),l=l+1|0;while((l|0)!=(k|0));if(r>>>0>>0){y=e+948|0,_=e+952|0,d=r,r=t[_>>2]|0;do l=(t[y>>2]|0)+(d<<2)|0,o=l+4|0,s=r-o|0,n=s>>2,n&&(Y1(l|0,o|0,s|0)|0,r=t[_>>2]|0),s=r,o=l+(n<<2)|0,(s|0)!=(o|0)&&(r=s+(~((s+-4-o|0)>>>2)<<2)|0,t[_>>2]=r),d=d+1|0;while((d|0)!=(k|0))}}while(0)}function Do(e){e=e|0;var n=0,r=0,o=0,s=0;i0(e,(fi(e)|0)==0,2491),i0(e,(t[e+944>>2]|0)==0,2545),n=e+948|0,r=t[n>>2]|0,o=e+952|0,s=t[o>>2]|0,(s|0)!=(r|0)&&(t[o>>2]=s+(~((s+-4-r|0)>>>2)<<2)),io(n),n=e+976|0,r=t[n>>2]|0,vn(e|0,8104,1e3)|0,c[r+2>>0]|0&&(t[e+4>>2]=2,t[e+12>>2]=4),t[n>>2]=r}function i0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;s=h,h=h+16|0,o=s,n||(t[o>>2]=r,wn(e,5,3197,o)),h=s}function Rs(){return t[2276]|0}function a0(){var e=0;return e=uh(20)|0,Hu((e|0)!=0,2592),t[2277]=(t[2277]|0)+1,t[e>>2]=t[239],t[e+4>>2]=t[240],t[e+8>>2]=t[241],t[e+12>>2]=t[242],t[e+16>>2]=t[243],e|0}function Hu(e,n){e=e|0,n=n|0;var r=0,o=0;o=h,h=h+16|0,r=o,e||(t[r>>2]=n,wn(0,5,3197,r)),h=o}function V0(e){e=e|0,sh(e),t[2277]=(t[2277]|0)+-1}function bu(e,n){e=e|0,n=n|0;var r=0;n?(i0(e,(fi(e)|0)==0,2629),r=1):(r=0,n=0),t[e+964>>2]=n,t[e+988>>2]=r}function Ns(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,l=o+8|0,s=o+4|0,d=o,t[s>>2]=n,i0(e,(t[n+944>>2]|0)==0,2709),i0(e,(t[e+964>>2]|0)==0,2763),bo(e),n=e+948|0,t[d>>2]=(t[n>>2]|0)+(r<<2),t[l>>2]=t[d>>2],P0(n,l,s)|0,t[(t[s>>2]|0)+944>>2]=e,ln(e),h=o}function bo(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0;if(r=fi(e)|0,r|0?(t[(e0(e,0)|0)+944>>2]|0)!=(e|0):0){o=t[(t[e+976>>2]|0)+12>>2]|0,s=e+948|0,l=(o|0)==0,n=0;do d=t[(t[s>>2]|0)+(n<<2)>>2]|0,_=Wi(d)|0,t[(t[s>>2]|0)+(n<<2)>>2]=_,t[_+944>>2]=e,l||Q4[o&15](d,_,e,n),n=n+1|0;while((n|0)!=(r|0))}}function P0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0;Pe=h,h=h+64|0,P=Pe+52|0,_=Pe+48|0,q=Pe+28|0,we=Pe+24|0,le=Pe+20|0,ie=Pe,o=t[e>>2]|0,l=o,n=o+((t[n>>2]|0)-l>>2<<2)|0,o=e+4|0,s=t[o>>2]|0,d=e+8|0;do if(s>>>0<(t[d>>2]|0)>>>0){if((n|0)==(s|0)){t[n>>2]=t[r>>2],t[o>>2]=(t[o>>2]|0)+4;break}Qn(e,n,s,n+4|0),n>>>0<=r>>>0&&(r=(t[o>>2]|0)>>>0>r>>>0?r+4|0:r),t[n>>2]=t[r>>2]}else{o=(s-l>>2)+1|0,s=Q0(e)|0,s>>>0>>0&&$n(e),T=t[e>>2]|0,k=(t[d>>2]|0)-T|0,l=k>>1,z(ie,k>>2>>>0>>1>>>0?l>>>0>>0?o:l:s,n-T>>2,e+8|0),T=ie+8|0,o=t[T>>2]|0,l=ie+12|0,k=t[l>>2]|0,d=k,y=o;do if((o|0)==(k|0)){if(k=ie+4|0,o=t[k>>2]|0,ke=t[ie>>2]|0,s=ke,o>>>0<=ke>>>0){o=d-s>>1,o=(o|0)==0?1:o,z(q,o,o>>>2,t[ie+16>>2]|0),t[we>>2]=t[k>>2],t[le>>2]=t[T>>2],t[_>>2]=t[we>>2],t[P>>2]=t[le>>2],s0(q,_,P),o=t[ie>>2]|0,t[ie>>2]=t[q>>2],t[q>>2]=o,o=q+4|0,ke=t[k>>2]|0,t[k>>2]=t[o>>2],t[o>>2]=ke,o=q+8|0,ke=t[T>>2]|0,t[T>>2]=t[o>>2],t[o>>2]=ke,o=q+12|0,ke=t[l>>2]|0,t[l>>2]=t[o>>2],t[o>>2]=ke,Or(q),o=t[T>>2]|0;break}l=o,d=((l-s>>2)+1|0)/-2|0,_=o+(d<<2)|0,s=y-l|0,l=s>>2,l&&(Y1(_|0,o|0,s|0)|0,o=t[k>>2]|0),ke=_+(l<<2)|0,t[T>>2]=ke,t[k>>2]=o+(d<<2),o=ke}while(0);t[o>>2]=t[r>>2],t[T>>2]=(t[T>>2]|0)+4,n=nn(e,ie,n)|0,Or(ie)}while(0);return h=Pe,n|0}function ln(e){e=e|0;var n=0;do{if(n=e+984|0,c[n>>0]|0)break;c[n>>0]=1,D[e+504>>2]=w(J),e=t[e+944>>2]|0}while((e|0)!=0)}function lf(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),Ve(r))}function nr(e){return e=e|0,t[e+944>>2]|0}function rr(e){e=e|0,i0(e,(t[e+964>>2]|0)!=0,2832),ln(e)}function Go(e){return e=e|0,(c[e+984>>0]|0)!=0|0}function Gu(e,n){e=e|0,n=n|0,fL(e,n,400)|0&&(vn(e|0,n|0,400)|0,ln(e))}function yl(e){e=e|0;var n=tt;return n=w(D[e+44>>2]),e=gt(n)|0,w(e?w(0):n)}function cu(e){e=e|0;var n=tt;return n=w(D[e+48>>2]),gt(n)|0&&(n=c[(t[e+976>>2]|0)+2>>0]|0?w(1):w(0)),w(n)}function Bs(e,n){e=e|0,n=n|0,t[e+980>>2]=n}function Vu(e){return e=e|0,t[e+980>>2]|0}function M0(e,n){e=e|0,n=n|0;var r=0;r=e+4|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function au(e){return e=e|0,t[e+4>>2]|0}function Lr(e,n){e=e|0,n=n|0;var r=0;r=e+8|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function F(e){return e=e|0,t[e+8>>2]|0}function R(e,n){e=e|0,n=n|0;var r=0;r=e+12|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function U(e){return e=e|0,t[e+12>>2]|0}function H(e,n){e=e|0,n=n|0;var r=0;r=e+16|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function fe(e){return e=e|0,t[e+16>>2]|0}function ue(e,n){e=e|0,n=n|0;var r=0;r=e+20|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function de(e){return e=e|0,t[e+20>>2]|0}function W(e,n){e=e|0,n=n|0;var r=0;r=e+24|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function ve(e){return e=e|0,t[e+24>>2]|0}function Fe(e,n){e=e|0,n=n|0;var r=0;r=e+28|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function Ge(e){return e=e|0,t[e+28>>2]|0}function K(e,n){e=e|0,n=n|0;var r=0;r=e+32|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function xe(e){return e=e|0,t[e+32>>2]|0}function je(e,n){e=e|0,n=n|0;var r=0;r=e+36|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,ln(e))}function Xe(e){return e=e|0,t[e+36>>2]|0}function rt(e,n){e=e|0,n=w(n);var r=0;r=e+40|0,w(D[r>>2])!=n&&(D[r>>2]=n,ln(e))}function st(e,n){e=e|0,n=w(n);var r=0;r=e+44|0,w(D[r>>2])!=n&&(D[r>>2]=n,ln(e))}function xt(e,n){e=e|0,n=w(n);var r=0;r=e+48|0,w(D[r>>2])!=n&&(D[r>>2]=n,ln(e))}function wt(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+52|0,s=e+56|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function lt(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+52|0,r=e+56|0,(w(D[o>>2])==n?(t[r>>2]|0)==2:0)||(D[o>>2]=n,o=gt(n)|0,t[r>>2]=o?3:2,ln(e))}function Rt(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+52|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function yn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=(l^1)&1,s=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function sn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=l?0:2,s=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function ar(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+132+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function rn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=(l^1)&1,s=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function Hn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=l?0:2,s=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function d0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+60+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function Cr(e,n){e=e|0,n=n|0;var r=0;r=e+60+(n<<3)+4|0,(t[r>>2]|0)!=3&&(D[e+60+(n<<3)>>2]=w(J),t[r>>2]=3,ln(e))}function He(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=(l^1)&1,s=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function Qe(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=l?0:2,s=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function Ne(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+204+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function ft(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0,l=0;l=gt(r)|0,o=(l^1)&1,s=e+276+(n<<3)|0,n=e+276+(n<<3)+4|0,(l|w(D[s>>2])==r?(t[n>>2]|0)==(o|0):0)||(D[s>>2]=r,t[n>>2]=o,ln(e))}function St(e,n){return e=e|0,n=n|0,w(D[e+276+(n<<3)>>2])}function Qt(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+348|0,s=e+352|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Cn(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+348|0,r=e+352|0,(w(D[o>>2])==n?(t[r>>2]|0)==2:0)||(D[o>>2]=n,o=gt(n)|0,t[r>>2]=o?3:2,ln(e))}function bn(e){e=e|0;var n=0;n=e+352|0,(t[n>>2]|0)!=3&&(D[e+348>>2]=w(J),t[n>>2]=3,ln(e))}function p0(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+348|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function h0(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+356|0,s=e+360|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function ci(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+356|0,r=e+360|0,(w(D[o>>2])==n?(t[r>>2]|0)==2:0)||(D[o>>2]=n,o=gt(n)|0,t[r>>2]=o?3:2,ln(e))}function xi(e){e=e|0;var n=0;n=e+360|0,(t[n>>2]|0)!=3&&(D[e+356>>2]=w(J),t[n>>2]=3,ln(e))}function E0(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+356|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function qr(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+364|0,s=e+368|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Eo(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=l?0:2,o=e+364|0,s=e+368|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function So(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+364|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function wl(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+372|0,s=e+376|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function js(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=l?0:2,o=e+372|0,s=e+376|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Dl(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+372|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function du(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+380|0,s=e+384|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Yu(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=l?0:2,o=e+380|0,s=e+384|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Us(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+380|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function oo(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=(l^1)&1,o=e+388|0,s=e+392|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function Hi(e,n){e=e|0,n=w(n);var r=0,o=0,s=0,l=0;l=gt(n)|0,r=l?0:2,o=e+388|0,s=e+392|0,(l|w(D[o>>2])==n?(t[s>>2]|0)==(r|0):0)||(D[o>>2]=n,t[s>>2]=r,ln(e))}function qs(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+388|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function F0(e,n){e=e|0,n=w(n);var r=0;r=e+396|0,w(D[r>>2])!=n&&(D[r>>2]=n,ln(e))}function Gr(e){return e=e|0,w(D[e+396>>2])}function ir(e){return e=e|0,w(D[e+400>>2])}function L0(e){return e=e|0,w(D[e+404>>2])}function Y0(e){return e=e|0,w(D[e+408>>2])}function Co(e){return e=e|0,w(D[e+412>>2])}function $u(e){return e=e|0,w(D[e+416>>2])}function Vo(e){return e=e|0,w(D[e+420>>2])}function Rr(e,n){switch(e=e|0,n=n|0,i0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(D[e+424+(n<<2)>>2])}function Jn(e,n){switch(e=e|0,n=n|0,i0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(D[e+448+(n<<2)>>2])}function ai(e,n){switch(e=e|0,n=n|0,i0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(D[e+472+(n<<2)>>2])}function o0(e,n){e=e|0,n=n|0;var r=0,o=tt;return r=t[e+4>>2]|0,(r|0)==(t[n+4>>2]|0)?r?(o=w(D[e>>2]),e=w(Ot(w(o-w(D[n>>2]))))>2]=0,t[o+4>>2]=0,t[o+8>>2]=0,Ru(o|0,e|0,n|0,0),wn(e,3,(c[o+11>>0]|0)<0?t[o>>2]|0:o,r),ML(o),h=r}function $0(e,n,r,o){e=w(e),n=w(n),r=r|0,o=o|0;var s=tt;e=w(e*n),s=w(V4(e,w(1)));do if(Vr(s,w(0))|0)e=w(e-s);else{if(e=w(e-s),Vr(s,w(1))|0){e=w(e+w(1));break}if(r){e=w(e+w(1));break}o||(s>w(.5)?s=w(1):(o=Vr(s,w(.5))|0,s=w(o?1:0)),e=w(e+s))}while(0);return w(e/n)}function K0(e,n,r,o,s,l,d,_,y,k,T,P,q){e=e|0,n=w(n),r=r|0,o=w(o),s=s|0,l=w(l),d=d|0,_=w(_),y=w(y),k=w(k),T=w(T),P=w(P),q=q|0;var we=0,le=tt,ie=tt,Pe=tt,ke=tt,qe=tt,pe=tt;return y>2]),le!=w(0)):0)?(Pe=w($0(n,le,0,0)),ke=w($0(o,le,0,0)),ie=w($0(l,le,0,0)),le=w($0(_,le,0,0))):(ie=l,Pe=n,le=_,ke=o),(s|0)==(e|0)?we=Vr(ie,Pe)|0:we=0,(d|0)==(r|0)?q=Vr(le,ke)|0:q=0,((we?0:(qe=w(n-T),!(ae(e,qe,y)|0)))?!(Be(e,qe,s,y)|0):0)?we=Ie(e,qe,s,l,y)|0:we=1,((q?0:(pe=w(o-P),!(ae(r,pe,k)|0)))?!(Be(r,pe,d,k)|0):0)?q=Ie(r,pe,d,_,k)|0:q=1,q=we&q),q|0}function ae(e,n,r){return e=e|0,n=w(n),r=w(r),(e|0)==1?e=Vr(n,r)|0:e=0,e|0}function Be(e,n,r,o){return e=e|0,n=w(n),r=r|0,o=w(o),(e|0)==2&(r|0)==0?n>=o?e=1:e=Vr(n,o)|0:e=0,e|0}function Ie(e,n,r,o,s){return e=e|0,n=w(n),r=r|0,o=w(o),s=w(s),(e|0)==2&(r|0)==2&o>n?s<=n?e=1:e=Vr(n,s)|0:e=0,e|0}function ht(e,n,r,o,s,l,d,_,y,k,T){e=e|0,n=w(n),r=w(r),o=o|0,s=s|0,l=l|0,d=w(d),_=w(_),y=y|0,k=k|0,T=T|0;var P=0,q=0,we=0,le=0,ie=tt,Pe=tt,ke=0,qe=0,pe=0,_e=0,vt=0,Ln=0,Ht=0,It=0,gn=0,Pn=0,zt=0,Dr=tt,Ki=tt,Xi=tt,Ji=0,Ro=0;zt=h,h=h+160|0,It=zt+152|0,Ht=zt+120|0,Ln=zt+104|0,pe=zt+72|0,le=zt+56|0,vt=zt+8|0,qe=zt,_e=(t[2279]|0)+1|0,t[2279]=_e,gn=e+984|0,((c[gn>>0]|0)!=0?(t[e+512>>2]|0)!=(t[2278]|0):0)?ke=4:(t[e+516>>2]|0)==(o|0)?Pn=0:ke=4,(ke|0)==4&&(t[e+520>>2]=0,t[e+924>>2]=-1,t[e+928>>2]=-1,D[e+932>>2]=w(-1),D[e+936>>2]=w(-1),Pn=1);e:do if(t[e+964>>2]|0)if(ie=w(mt(e,2,d)),Pe=w(mt(e,0,d)),P=e+916|0,Xi=w(D[P>>2]),Ki=w(D[e+920>>2]),Dr=w(D[e+932>>2]),K0(s,n,l,r,t[e+924>>2]|0,Xi,t[e+928>>2]|0,Ki,Dr,w(D[e+936>>2]),ie,Pe,T)|0)ke=22;else if(we=t[e+520>>2]|0,!we)ke=21;else for(q=0;;){if(P=e+524+(q*24|0)|0,Dr=w(D[P>>2]),Ki=w(D[e+524+(q*24|0)+4>>2]),Xi=w(D[e+524+(q*24|0)+16>>2]),K0(s,n,l,r,t[e+524+(q*24|0)+8>>2]|0,Dr,t[e+524+(q*24|0)+12>>2]|0,Ki,Xi,w(D[e+524+(q*24|0)+20>>2]),ie,Pe,T)|0){ke=22;break e}if(q=q+1|0,q>>>0>=we>>>0){ke=21;break}}else{if(y){if(P=e+916|0,!(Vr(w(D[P>>2]),n)|0)){ke=21;break}if(!(Vr(w(D[e+920>>2]),r)|0)){ke=21;break}if((t[e+924>>2]|0)!=(s|0)){ke=21;break}P=(t[e+928>>2]|0)==(l|0)?P:0,ke=22;break}if(we=t[e+520>>2]|0,!we)ke=21;else for(q=0;;){if(P=e+524+(q*24|0)|0,((Vr(w(D[P>>2]),n)|0?Vr(w(D[e+524+(q*24|0)+4>>2]),r)|0:0)?(t[e+524+(q*24|0)+8>>2]|0)==(s|0):0)?(t[e+524+(q*24|0)+12>>2]|0)==(l|0):0){ke=22;break e}if(q=q+1|0,q>>>0>=we>>>0){ke=21;break}}}while(0);do if((ke|0)==21)c[11697]|0?(P=0,ke=28):(P=0,ke=31);else if((ke|0)==22){if(q=(c[11697]|0)!=0,!((P|0)!=0&(Pn^1)))if(q){ke=28;break}else{ke=31;break}le=P+16|0,t[e+908>>2]=t[le>>2],we=P+20|0,t[e+912>>2]=t[we>>2],(c[11698]|0)==0|q^1||(t[qe>>2]=Gn(_e)|0,t[qe+4>>2]=_e,wn(e,4,2972,qe),q=t[e+972>>2]|0,q|0&&Nl[q&127](e),s=$t(s,y)|0,l=$t(l,y)|0,Ro=+w(D[le>>2]),Ji=+w(D[we>>2]),t[vt>>2]=s,t[vt+4>>2]=l,L[vt+8>>3]=+n,L[vt+16>>3]=+r,L[vt+24>>3]=Ro,L[vt+32>>3]=Ji,t[vt+40>>2]=k,wn(e,4,2989,vt))}while(0);return(ke|0)==28&&(q=Gn(_e)|0,t[le>>2]=q,t[le+4>>2]=_e,t[le+8>>2]=Pn?3047:11699,wn(e,4,3038,le),q=t[e+972>>2]|0,q|0&&Nl[q&127](e),vt=$t(s,y)|0,ke=$t(l,y)|0,t[pe>>2]=vt,t[pe+4>>2]=ke,L[pe+8>>3]=+n,L[pe+16>>3]=+r,t[pe+24>>2]=k,wn(e,4,3049,pe),ke=31),(ke|0)==31&&(X0(e,n,r,o,s,l,d,_,y,T),c[11697]|0&&(q=t[2279]|0,vt=Gn(q)|0,t[Ln>>2]=vt,t[Ln+4>>2]=q,t[Ln+8>>2]=Pn?3047:11699,wn(e,4,3083,Ln),q=t[e+972>>2]|0,q|0&&Nl[q&127](e),vt=$t(s,y)|0,Ln=$t(l,y)|0,Ji=+w(D[e+908>>2]),Ro=+w(D[e+912>>2]),t[Ht>>2]=vt,t[Ht+4>>2]=Ln,L[Ht+8>>3]=Ji,L[Ht+16>>3]=Ro,t[Ht+24>>2]=k,wn(e,4,3092,Ht)),t[e+516>>2]=o,P||(q=e+520|0,P=t[q>>2]|0,(P|0)==16&&(c[11697]|0&&wn(e,4,3124,It),t[q>>2]=0,P=0),y?P=e+916|0:(t[q>>2]=P+1,P=e+524+(P*24|0)|0),D[P>>2]=n,D[P+4>>2]=r,t[P+8>>2]=s,t[P+12>>2]=l,t[P+16>>2]=t[e+908>>2],t[P+20>>2]=t[e+912>>2],P=0)),y&&(t[e+416>>2]=t[e+908>>2],t[e+420>>2]=t[e+912>>2],c[e+985>>0]=1,c[gn>>0]=0),t[2279]=(t[2279]|0)+-1,t[e+512>>2]=t[2278],h=zt,Pn|(P|0)==0|0}function mt(e,n,r){e=e|0,n=n|0,r=w(r);var o=tt;return o=w(Tr(e,n,r)),w(o+w(R0(e,n,r)))}function wn(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=h,h=h+16|0,s=l,t[s>>2]=o,e?o=t[e+976>>2]|0:o=0,Ku(o,e,n,r,s),h=l}function Gn(e){return e=e|0,(e>>>0>60?3201:3201+(60-e)|0)|0}function $t(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;return s=h,h=h+32|0,r=s+12|0,o=s,t[r>>2]=t[254],t[r+4>>2]=t[255],t[r+8>>2]=t[256],t[o>>2]=t[257],t[o+4>>2]=t[258],t[o+8>>2]=t[259],(e|0)>2?e=11699:e=t[(n?o:r)+(e<<2)>>2]|0,h=s,e|0}function X0(e,n,r,o,s,l,d,_,y,k){e=e|0,n=w(n),r=w(r),o=o|0,s=s|0,l=l|0,d=w(d),_=w(_),y=y|0,k=k|0;var T=0,P=0,q=0,we=0,le=tt,ie=tt,Pe=tt,ke=tt,qe=tt,pe=tt,_e=tt,vt=0,Ln=0,Ht=0,It=tt,gn=tt,Pn=0,zt=tt,Dr=0,Ki=0,Xi=0,Ji=0,Ro=0,kf=0,Af=0,Cu=0,Of=0,Js=0,Qs=0,If=0,Pf=0,Mf=0,Kn=0,Tu=0,Ff=0,us=0,Lf=tt,Rf=tt,Zs=tt,el=tt,ss=tt,Fi=0,nu=0,go=0,xu=0,jl=0,Ul=tt,tl=tt,ql=tt,zl=tt,Li=tt,Di=tt,ku=0,xr=tt,Wl=tt,Qi=tt,ls=tt,Zi=tt,fs=tt,Hl=0,bl=0,cs=tt,Ri=tt,Au=0,Gl=0,Vl=0,Yl=0,En=tt,br=0,Ei=0,eo=0,Ni=0,xn=0,Vt=0,Ou=0,kt=tt,$l=0,Qr=0;Ou=h,h=h+16|0,Fi=Ou+12|0,nu=Ou+8|0,go=Ou+4|0,xu=Ou,i0(e,(s|0)==0|(gt(n)|0)^1,3326),i0(e,(l|0)==0|(gt(r)|0)^1,3406),Ei=so(e,o)|0,t[e+496>>2]=Ei,xn=N0(2,Ei)|0,Vt=N0(0,Ei)|0,D[e+440>>2]=w(Tr(e,xn,d)),D[e+444>>2]=w(R0(e,xn,d)),D[e+428>>2]=w(Tr(e,Vt,d)),D[e+436>>2]=w(R0(e,Vt,d)),D[e+464>>2]=w(C0(e,xn)),D[e+468>>2]=w(di(e,xn)),D[e+452>>2]=w(C0(e,Vt)),D[e+460>>2]=w(di(e,Vt)),D[e+488>>2]=w(u0(e,xn,d)),D[e+492>>2]=w(v0(e,xn,d)),D[e+476>>2]=w(u0(e,Vt,d)),D[e+484>>2]=w(v0(e,Vt,d));do if(t[e+964>>2]|0)To(e,n,r,s,l,d,_);else{if(eo=e+948|0,Ni=(t[e+952>>2]|0)-(t[eo>>2]|0)>>2,!Ni){pu(e,n,r,s,l,d,_);break}if(y?0:Sl(e,n,r,s,l,d,_)|0)break;bo(e),Tu=e+508|0,c[Tu>>0]=0,xn=N0(t[e+4>>2]|0,Ei)|0,Vt=Cl(xn,Ei)|0,br=Nr(xn)|0,Ff=t[e+8>>2]|0,Gl=e+28|0,us=(t[Gl>>2]|0)!=0,Zi=br?d:_,cs=br?_:d,Lf=w(B0(e,xn,d)),Rf=w(hu(e,xn,d)),le=w(B0(e,Vt,d)),fs=w(Fn(e,xn,d)),Ri=w(Fn(e,Vt,d)),Ht=br?s:l,Au=br?l:s,En=br?fs:Ri,qe=br?Ri:fs,ls=w(mt(e,2,d)),ke=w(mt(e,0,d)),ie=w(w(Tn(e+364|0,d))-En),Pe=w(w(Tn(e+380|0,d))-En),pe=w(w(Tn(e+372|0,_))-qe),_e=w(w(Tn(e+388|0,_))-qe),Zs=br?ie:pe,el=br?Pe:_e,ls=w(n-ls),n=w(ls-En),gt(n)|0?En=n:En=w(Ur(w(cc(n,Pe)),ie)),Wl=w(r-ke),n=w(Wl-qe),gt(n)|0?Qi=n:Qi=w(Ur(w(cc(n,_e)),pe)),ie=br?En:Qi,xr=br?Qi:En;e:do if((Ht|0)==1)for(o=0,P=0;;){if(T=e0(e,P)|0,!o)(w(Br(T))>w(0)?w(zr(T))>w(0):0)?o=T:o=0;else if(pi(T)|0){we=0;break e}if(P=P+1|0,P>>>0>=Ni>>>0){we=o;break}}else we=0;while(0);vt=we+500|0,Ln=we+504|0,o=0,T=0,n=w(0),q=0;do{if(P=t[(t[eo>>2]|0)+(q<<2)>>2]|0,(t[P+36>>2]|0)==1)lo(P),c[P+985>>0]=1,c[P+984>>0]=0;else{$r(P),y&&Yo(P,so(P,Ei)|0,ie,xr,En);do if((t[P+24>>2]|0)!=1)if((P|0)==(we|0)){t[vt>>2]=t[2278],D[Ln>>2]=w(0);break}else{wr(e,P,En,s,Qi,En,Qi,l,Ei,k);break}else T|0&&(t[T+960>>2]=P),t[P+960>>2]=0,T=P,o=(o|0)==0?P:o;while(0);Di=w(D[P+504>>2]),n=w(n+w(Di+w(mt(P,xn,En))))}q=q+1|0}while((q|0)!=(Ni|0));for(Xi=n>ie,ku=us&((Ht|0)==2&Xi)?1:Ht,Dr=(Au|0)==1,Ro=Dr&(y^1),kf=(ku|0)==1,Af=(ku|0)==2,Cu=976+(xn<<2)|0,Of=(Au|2|0)==2,Mf=Dr&(us^1),Js=1040+(Vt<<2)|0,Qs=1040+(xn<<2)|0,If=976+(Vt<<2)|0,Pf=(Au|0)!=1,Xi=us&((Ht|0)!=0&Xi),Ki=e+976|0,Dr=Dr^1,n=ie,Pn=0,Ji=0,Di=w(0),ss=w(0);;){e:do if(Pn>>>0>>0)for(Ln=t[eo>>2]|0,q=0,_e=w(0),pe=w(0),Pe=w(0),ie=w(0),P=0,T=0,we=Pn;;){if(vt=t[Ln+(we<<2)>>2]|0,(t[vt+36>>2]|0)!=1?(t[vt+940>>2]=Ji,(t[vt+24>>2]|0)!=1):0){if(ke=w(mt(vt,xn,En)),Kn=t[Cu>>2]|0,r=w(Tn(vt+380+(Kn<<3)|0,Zi)),qe=w(D[vt+504>>2]),r=w(cc(r,qe)),r=w(Ur(w(Tn(vt+364+(Kn<<3)|0,Zi)),r)),us&(q|0)!=0&w(ke+w(pe+r))>n){l=q,ke=_e,Ht=we;break e}ke=w(ke+r),r=w(pe+ke),ke=w(_e+ke),pi(vt)|0&&(Pe=w(Pe+w(Br(vt))),ie=w(ie-w(qe*w(zr(vt))))),T|0&&(t[T+960>>2]=vt),t[vt+960>>2]=0,q=q+1|0,T=vt,P=(P|0)==0?vt:P}else ke=_e,r=pe;if(we=we+1|0,we>>>0>>0)_e=ke,pe=r;else{l=q,Ht=we;break}}else l=0,ke=w(0),Pe=w(0),ie=w(0),P=0,Ht=Pn;while(0);Kn=Pe>w(0)&Pew(0)&ieel&((gt(el)|0)^1))n=el,Kn=51;else if(c[(t[Ki>>2]|0)+3>>0]|0)Kn=51;else{if(It!=w(0)?w(Br(e))!=w(0):0){Kn=53;break}n=ke,Kn=53}while(0);if((Kn|0)==51&&(Kn=0,gt(n)|0?Kn=53:(gn=w(n-ke),zt=n)),(Kn|0)==53&&(Kn=0,ke>2]|0,we=gnw(0),pe=w(gn/It),Pe=w(0),ke=w(0),n=w(0),T=P;do r=w(Tn(T+380+(q<<3)|0,Zi)),ie=w(Tn(T+364+(q<<3)|0,Zi)),ie=w(cc(r,w(Ur(ie,w(D[T+504>>2]))))),we?(r=w(ie*w(zr(T))),(r!=w(-0)?(kt=w(ie-w(qe*r)),Ul=w(kn(T,xn,kt,zt,En)),kt!=Ul):0)&&(Pe=w(Pe-w(Ul-ie)),n=w(n+r))):((vt?(tl=w(Br(T)),tl!=w(0)):0)?(kt=w(ie+w(pe*tl)),ql=w(kn(T,xn,kt,zt,En)),kt!=ql):0)&&(Pe=w(Pe-w(ql-ie)),ke=w(ke-tl)),T=t[T+960>>2]|0;while((T|0)!=0);if(n=w(_e+n),ie=w(gn+Pe),jl)n=w(0);else{qe=w(It+ke),we=t[Cu>>2]|0,vt=iew(0),qe=w(ie/qe),n=w(0);do{kt=w(Tn(P+380+(we<<3)|0,Zi)),Pe=w(Tn(P+364+(we<<3)|0,Zi)),Pe=w(cc(kt,w(Ur(Pe,w(D[P+504>>2]))))),vt?(kt=w(Pe*w(zr(P))),ie=w(-kt),kt!=w(-0)?(kt=w(pe*ie),ie=w(kn(P,xn,w(Pe+(Ln?ie:kt)),zt,En))):ie=Pe):(q?(zl=w(Br(P)),zl!=w(0)):0)?ie=w(kn(P,xn,w(Pe+w(qe*zl)),zt,En)):ie=Pe,n=w(n-w(ie-Pe)),ke=w(mt(P,xn,En)),r=w(mt(P,Vt,En)),ie=w(ie+ke),D[nu>>2]=ie,t[xu>>2]=1,Pe=w(D[P+396>>2]);e:do if(gt(Pe)|0){T=gt(xr)|0;do if(!T){if(Xi|(m0(P,Vt,xr)|0|Dr)||(T0(e,P)|0)!=4||(t[(hi(P,Vt)|0)+4>>2]|0)==3||(t[(Ai(P,Vt)|0)+4>>2]|0)==3)break;D[Fi>>2]=xr,t[go>>2]=1;break e}while(0);if(m0(P,Vt,xr)|0){T=t[P+992+(t[If>>2]<<2)>>2]|0,kt=w(r+w(Tn(T,xr))),D[Fi>>2]=kt,T=Pf&(t[T+4>>2]|0)==2,t[go>>2]=((gt(kt)|0|T)^1)&1;break}else{D[Fi>>2]=xr,t[go>>2]=T?0:2;break}}else kt=w(ie-ke),It=w(kt/Pe),kt=w(Pe*kt),t[go>>2]=1,D[Fi>>2]=w(r+(br?It:kt));while(0);Kt(P,xn,zt,En,xu,nu),Kt(P,Vt,xr,En,go,Fi);do if(m0(P,Vt,xr)|0?0:(T0(e,P)|0)==4){if((t[(hi(P,Vt)|0)+4>>2]|0)==3){T=0;break}T=(t[(Ai(P,Vt)|0)+4>>2]|0)!=3}else T=0;while(0);kt=w(D[nu>>2]),It=w(D[Fi>>2]),$l=t[xu>>2]|0,Qr=t[go>>2]|0,ht(P,br?kt:It,br?It:kt,Ei,br?$l:Qr,br?Qr:$l,En,Qi,y&(T^1),3488,k)|0,c[Tu>>0]=c[Tu>>0]|c[P+508>>0],P=t[P+960>>2]|0}while((P|0)!=0)}}else n=w(0);if(n=w(gn+n),Qr=n>0]=Qr|C[Tu>>0],Af&n>w(0)?(T=t[Cu>>2]|0,((t[e+364+(T<<3)+4>>2]|0)!=0?(Li=w(Tn(e+364+(T<<3)|0,Zi)),Li>=w(0)):0)?ie=w(Ur(w(0),w(Li-w(zt-n)))):ie=w(0)):ie=n,vt=Pn>>>0>>0,vt){we=t[eo>>2]|0,q=Pn,T=0;do P=t[we+(q<<2)>>2]|0,t[P+24>>2]|0||(T=((t[(hi(P,xn)|0)+4>>2]|0)==3&1)+T|0,T=T+((t[(Ai(P,xn)|0)+4>>2]|0)==3&1)|0),q=q+1|0;while((q|0)!=(Ht|0));T?(ke=w(0),r=w(0)):Kn=101}else Kn=101;e:do if((Kn|0)==101)switch(Kn=0,Ff|0){case 1:{T=0,ke=w(ie*w(.5)),r=w(0);break e}case 2:{T=0,ke=ie,r=w(0);break e}case 3:{if(l>>>0<=1){T=0,ke=w(0),r=w(0);break e}r=w((l+-1|0)>>>0),T=0,ke=w(0),r=w(w(Ur(ie,w(0)))/r);break e}case 5:{r=w(ie/w((l+1|0)>>>0)),T=0,ke=r;break e}case 4:{r=w(ie/w(l>>>0)),T=0,ke=w(r*w(.5));break e}default:{T=0,ke=w(0),r=w(0);break e}}while(0);if(n=w(Lf+ke),vt){Pe=w(ie/w(T|0)),q=t[eo>>2]|0,P=Pn,ie=w(0);do{T=t[q+(P<<2)>>2]|0;e:do if((t[T+36>>2]|0)!=1){switch(t[T+24>>2]|0){case 1:{if(X(T,xn)|0){if(!y)break e;kt=w(Y(T,xn,zt)),kt=w(kt+w(C0(e,xn))),kt=w(kt+w(Tr(T,xn,En))),D[T+400+(t[Qs>>2]<<2)>>2]=kt;break e}break}case 0:if(Qr=(t[(hi(T,xn)|0)+4>>2]|0)==3,kt=w(Pe+n),n=Qr?kt:n,y&&(Qr=T+400+(t[Qs>>2]<<2)|0,D[Qr>>2]=w(n+w(D[Qr>>2]))),Qr=(t[(Ai(T,xn)|0)+4>>2]|0)==3,kt=w(Pe+n),n=Qr?kt:n,Ro){kt=w(r+w(mt(T,xn,En))),ie=xr,n=w(n+w(kt+w(D[T+504>>2])));break e}else{n=w(n+w(r+w(ye(T,xn,En)))),ie=w(Ur(ie,w(ye(T,Vt,En))));break e}default:}y&&(kt=w(ke+w(C0(e,xn))),Qr=T+400+(t[Qs>>2]<<2)|0,D[Qr>>2]=w(kt+w(D[Qr>>2])))}while(0);P=P+1|0}while((P|0)!=(Ht|0))}else ie=w(0);if(r=w(Rf+n),Of?ke=w(w(kn(e,Vt,w(Ri+ie),cs,d))-Ri):ke=xr,Pe=w(w(kn(e,Vt,w(Ri+(Mf?xr:ie)),cs,d))-Ri),vt&y){P=Pn;do{q=t[(t[eo>>2]|0)+(P<<2)>>2]|0;do if((t[q+36>>2]|0)!=1){if((t[q+24>>2]|0)==1){if(X(q,Vt)|0){if(kt=w(Y(q,Vt,xr)),kt=w(kt+w(C0(e,Vt))),kt=w(kt+w(Tr(q,Vt,En))),T=t[Js>>2]|0,D[q+400+(T<<2)>>2]=kt,!(gt(kt)|0))break}else T=t[Js>>2]|0;kt=w(C0(e,Vt)),D[q+400+(T<<2)>>2]=w(kt+w(Tr(q,Vt,En)));break}T=T0(e,q)|0;do if((T|0)==4){if((t[(hi(q,Vt)|0)+4>>2]|0)==3){Kn=139;break}if((t[(Ai(q,Vt)|0)+4>>2]|0)==3){Kn=139;break}if(m0(q,Vt,xr)|0){n=le;break}$l=t[q+908+(t[Cu>>2]<<2)>>2]|0,t[Fi>>2]=$l,n=w(D[q+396>>2]),Qr=gt(n)|0,ie=(t[j>>2]=$l,w(D[j>>2])),Qr?n=Pe:(gn=w(mt(q,Vt,En)),kt=w(ie/n),n=w(n*ie),n=w(gn+(br?kt:n))),D[nu>>2]=n,D[Fi>>2]=w(w(mt(q,xn,En))+ie),t[go>>2]=1,t[xu>>2]=1,Kt(q,xn,zt,En,go,Fi),Kt(q,Vt,xr,En,xu,nu),n=w(D[Fi>>2]),gn=w(D[nu>>2]),kt=br?n:gn,n=br?gn:n,Qr=((gt(kt)|0)^1)&1,ht(q,kt,n,Ei,Qr,((gt(n)|0)^1)&1,En,Qi,1,3493,k)|0,n=le}else Kn=139;while(0);e:do if((Kn|0)==139){Kn=0,n=w(ke-w(ye(q,Vt,En)));do if((t[(hi(q,Vt)|0)+4>>2]|0)==3){if((t[(Ai(q,Vt)|0)+4>>2]|0)!=3)break;n=w(le+w(Ur(w(0),w(n*w(.5)))));break e}while(0);if((t[(Ai(q,Vt)|0)+4>>2]|0)==3){n=le;break}if((t[(hi(q,Vt)|0)+4>>2]|0)==3){n=w(le+w(Ur(w(0),n)));break}switch(T|0){case 1:{n=le;break e}case 2:{n=w(le+w(n*w(.5)));break e}default:{n=w(le+n);break e}}}while(0);kt=w(Di+n),Qr=q+400+(t[Js>>2]<<2)|0,D[Qr>>2]=w(kt+w(D[Qr>>2]))}while(0);P=P+1|0}while((P|0)!=(Ht|0))}if(Di=w(Di+Pe),ss=w(Ur(ss,r)),l=Ji+1|0,Ht>>>0>=Ni>>>0)break;n=zt,Pn=Ht,Ji=l}do if(y){if(T=l>>>0>1,T?0:!(he(e)|0))break;if(!(gt(xr)|0)){n=w(xr-Di);e:do switch(t[e+12>>2]|0){case 3:{le=w(le+n),pe=w(0);break}case 2:{le=w(le+w(n*w(.5))),pe=w(0);break}case 4:{xr>Di?pe=w(n/w(l>>>0)):pe=w(0);break}case 7:if(xr>Di){le=w(le+w(n/w(l<<1>>>0))),pe=w(n/w(l>>>0)),pe=T?pe:w(0);break e}else{le=w(le+w(n*w(.5))),pe=w(0);break e}case 6:{pe=w(n/w(Ji>>>0)),pe=xr>Di&T?pe:w(0);break}default:pe=w(0)}while(0);if(l|0)for(vt=1040+(Vt<<2)|0,Ln=976+(Vt<<2)|0,we=0,P=0;;){e:do if(P>>>0>>0)for(ie=w(0),Pe=w(0),n=w(0),q=P;;){T=t[(t[eo>>2]|0)+(q<<2)>>2]|0;do if((t[T+36>>2]|0)!=1?(t[T+24>>2]|0)==0:0){if((t[T+940>>2]|0)!=(we|0))break e;if(We(T,Vt)|0&&(kt=w(D[T+908+(t[Ln>>2]<<2)>>2]),n=w(Ur(n,w(kt+w(mt(T,Vt,En)))))),(T0(e,T)|0)!=5)break;Li=w(et(T)),Li=w(Li+w(Tr(T,0,En))),kt=w(D[T+912>>2]),kt=w(w(kt+w(mt(T,0,En)))-Li),Li=w(Ur(Pe,Li)),kt=w(Ur(ie,kt)),ie=kt,Pe=Li,n=w(Ur(n,w(Li+kt)))}while(0);if(T=q+1|0,T>>>0>>0)q=T;else{q=T;break}}else Pe=w(0),n=w(0),q=P;while(0);if(qe=w(pe+n),r=le,le=w(le+qe),P>>>0>>0){ke=w(r+Pe),T=P;do{P=t[(t[eo>>2]|0)+(T<<2)>>2]|0;e:do if((t[P+36>>2]|0)!=1?(t[P+24>>2]|0)==0:0)switch(T0(e,P)|0){case 1:{kt=w(r+w(Tr(P,Vt,En))),D[P+400+(t[vt>>2]<<2)>>2]=kt;break e}case 3:{kt=w(w(le-w(R0(P,Vt,En)))-w(D[P+908+(t[Ln>>2]<<2)>>2])),D[P+400+(t[vt>>2]<<2)>>2]=kt;break e}case 2:{kt=w(r+w(w(qe-w(D[P+908+(t[Ln>>2]<<2)>>2]))*w(.5))),D[P+400+(t[vt>>2]<<2)>>2]=kt;break e}case 4:{if(kt=w(r+w(Tr(P,Vt,En))),D[P+400+(t[vt>>2]<<2)>>2]=kt,m0(P,Vt,xr)|0||(br?(ie=w(D[P+908>>2]),n=w(ie+w(mt(P,xn,En))),Pe=qe):(Pe=w(D[P+912>>2]),Pe=w(Pe+w(mt(P,Vt,En))),n=qe,ie=w(D[P+908>>2])),Vr(n,ie)|0?Vr(Pe,w(D[P+912>>2]))|0:0))break e;ht(P,n,Pe,Ei,1,1,En,Qi,1,3501,k)|0;break e}case 5:{D[P+404>>2]=w(w(ke-w(et(P)))+w(Y(P,0,xr)));break e}default:break e}while(0);T=T+1|0}while((T|0)!=(q|0))}if(we=we+1|0,(we|0)==(l|0))break;P=q}}}while(0);if(D[e+908>>2]=w(kn(e,2,ls,d,d)),D[e+912>>2]=w(kn(e,0,Wl,_,d)),((ku|0)!=0?(Hl=t[e+32>>2]|0,bl=(ku|0)==2,!(bl&(Hl|0)!=2)):0)?bl&(Hl|0)==2&&(n=w(fs+zt),n=w(Ur(w(cc(n,w(Dt(e,xn,ss,Zi)))),fs)),Kn=198):(n=w(kn(e,xn,ss,Zi,d)),Kn=198),(Kn|0)==198&&(D[e+908+(t[976+(xn<<2)>>2]<<2)>>2]=n),((Au|0)!=0?(Vl=t[e+32>>2]|0,Yl=(Au|0)==2,!(Yl&(Vl|0)!=2)):0)?Yl&(Vl|0)==2&&(n=w(Ri+xr),n=w(Ur(w(cc(n,w(Dt(e,Vt,w(Ri+Di),cs)))),Ri)),Kn=204):(n=w(kn(e,Vt,w(Ri+Di),cs,d)),Kn=204),(Kn|0)==204&&(D[e+908+(t[976+(Vt<<2)>>2]<<2)>>2]=n),y){if((t[Gl>>2]|0)==2){P=976+(Vt<<2)|0,q=1040+(Vt<<2)|0,T=0;do we=e0(e,T)|0,t[we+24>>2]|0||($l=t[P>>2]|0,kt=w(D[e+908+($l<<2)>>2]),Qr=we+400+(t[q>>2]<<2)|0,kt=w(kt-w(D[Qr>>2])),D[Qr>>2]=w(kt-w(D[we+908+($l<<2)>>2]))),T=T+1|0;while((T|0)!=(Ni|0))}if(o|0){T=br?ku:s;do bt(e,o,En,T,Qi,Ei,k),o=t[o+960>>2]|0;while((o|0)!=0)}if(T=(xn|2|0)==3,P=(Vt|2|0)==3,T|P){o=0;do q=t[(t[eo>>2]|0)+(o<<2)>>2]|0,(t[q+36>>2]|0)!=1&&(T&&Zt(e,q,xn),P&&Zt(e,q,Vt)),o=o+1|0;while((o|0)!=(Ni|0))}}}while(0);h=Ou}function ki(e,n){e=e|0,n=w(n);var r=0;li(e,n>=w(0),3147),r=n==w(0),D[e+4>>2]=r?w(0):n}function Yr(e,n,r,o){e=e|0,n=w(n),r=w(r),o=o|0;var s=tt,l=tt,d=0,_=0,y=0;t[2278]=(t[2278]|0)+1,$r(e),m0(e,2,n)|0?(s=w(Tn(t[e+992>>2]|0,n)),y=1,s=w(s+w(mt(e,2,n)))):(s=w(Tn(e+380|0,n)),s>=w(0)?y=2:(y=((gt(n)|0)^1)&1,s=n)),m0(e,0,r)|0?(l=w(Tn(t[e+996>>2]|0,r)),_=1,l=w(l+w(mt(e,0,n)))):(l=w(Tn(e+388|0,r)),l>=w(0)?_=2:(_=((gt(r)|0)^1)&1,l=r)),d=e+976|0,(ht(e,s,l,o,y,_,n,r,1,3189,t[d>>2]|0)|0?(Yo(e,t[e+496>>2]|0,n,r,n),bi(e,w(D[(t[d>>2]|0)+4>>2]),w(0),w(0)),c[11696]|0):0)&&ff(e,7)}function $r(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;_=h,h=h+32|0,d=_+24|0,l=_+16|0,o=_+8|0,s=_,r=0;do n=e+380+(r<<3)|0,((t[e+380+(r<<3)+4>>2]|0)!=0?(y=n,k=t[y+4>>2]|0,T=o,t[T>>2]=t[y>>2],t[T+4>>2]=k,T=e+364+(r<<3)|0,k=t[T+4>>2]|0,y=s,t[y>>2]=t[T>>2],t[y+4>>2]=k,t[l>>2]=t[o>>2],t[l+4>>2]=t[o+4>>2],t[d>>2]=t[s>>2],t[d+4>>2]=t[s+4>>2],o0(l,d)|0):0)||(n=e+348+(r<<3)|0),t[e+992+(r<<2)>>2]=n,r=r+1|0;while((r|0)!=2);h=_}function m0(e,n,r){e=e|0,n=n|0,r=w(r);var o=0;switch(e=t[e+992+(t[976+(n<<2)>>2]<<2)>>2]|0,t[e+4>>2]|0){case 0:case 3:{e=0;break}case 1:{w(D[e>>2])>2])>2]|0){case 2:{n=w(w(w(D[e>>2])*n)/w(100));break}case 1:{n=w(D[e>>2]);break}default:n=w(J)}return w(n)}function Yo(e,n,r,o,s){e=e|0,n=n|0,r=w(r),o=w(o),s=w(s);var l=0,d=tt;n=t[e+944>>2]|0?n:1,l=N0(t[e+4>>2]|0,n)|0,n=Cl(l,n)|0,r=w(Wr(e,l,r)),o=w(Wr(e,n,o)),d=w(r+w(Tr(e,l,s))),D[e+400+(t[1040+(l<<2)>>2]<<2)>>2]=d,r=w(r+w(R0(e,l,s))),D[e+400+(t[1e3+(l<<2)>>2]<<2)>>2]=r,r=w(o+w(Tr(e,n,s))),D[e+400+(t[1040+(n<<2)>>2]<<2)>>2]=r,s=w(o+w(R0(e,n,s))),D[e+400+(t[1e3+(n<<2)>>2]<<2)>>2]=s}function bi(e,n,r,o){e=e|0,n=w(n),r=w(r),o=w(o);var s=0,l=0,d=tt,_=tt,y=0,k=0,T=tt,P=0,q=tt,we=tt,le=tt,ie=tt;if(n!=w(0)&&(s=e+400|0,ie=w(D[s>>2]),l=e+404|0,le=w(D[l>>2]),P=e+416|0,we=w(D[P>>2]),k=e+420|0,d=w(D[k>>2]),q=w(ie+r),T=w(le+o),o=w(q+we),_=w(T+d),y=(t[e+988>>2]|0)==1,D[s>>2]=w($0(ie,n,0,y)),D[l>>2]=w($0(le,n,0,y)),r=w(V4(w(we*n),w(1))),Vr(r,w(0))|0?l=0:l=(Vr(r,w(1))|0)^1,r=w(V4(w(d*n),w(1))),Vr(r,w(0))|0?s=0:s=(Vr(r,w(1))|0)^1,ie=w($0(o,n,y&l,y&(l^1))),D[P>>2]=w(ie-w($0(q,n,0,y))),ie=w($0(_,n,y&s,y&(s^1))),D[k>>2]=w(ie-w($0(T,n,0,y))),l=(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2,l|0)){s=0;do bi(e0(e,s)|0,n,q,T),s=s+1|0;while((s|0)!=(l|0))}}function or(e,n,r,o,s){switch(e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,r|0){case 5:case 0:{e=q8(t[489]|0,o,s)|0;break}default:e=AL(o,s)|0}return e|0}function zs(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;s=h,h=h+16|0,l=s,t[l>>2]=o,Ku(e,0,n,r,l),h=s}function Ku(e,n,r,o,s){if(e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,e=e|0?e:956,sD[t[e+8>>2]&1](e,n,r,o,s)|0,(r|0)==5)_n();else return}function J0(e,n,r){e=e|0,n=n|0,r=r|0,c[e+n>>0]=r&1}function af(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(S0(e,o),El(e,t[n>>2]|0,t[r>>2]|0,o))}function S0(e,n){e=e|0,n=n|0;var r=0;if((Q0(e)|0)>>>0>>0&&$n(e),n>>>0>1073741823)_n();else{r=Tt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function El(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(vn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function Q0(e){return e=e|0,1073741823}function Tr(e,n,r){return e=e|0,n=n|0,r=w(r),(Nr(n)|0?(t[e+96>>2]|0)!=0:0)?e=e+92|0:e=en(e+60|0,t[1040+(n<<2)>>2]|0,992)|0,w(uo(e,r))}function R0(e,n,r){return e=e|0,n=n|0,r=w(r),(Nr(n)|0?(t[e+104>>2]|0)!=0:0)?e=e+100|0:e=en(e+60|0,t[1e3+(n<<2)>>2]|0,992)|0,w(uo(e,r))}function Nr(e){return e=e|0,(e|1|0)==3|0}function uo(e,n){return e=e|0,n=w(n),(t[e+4>>2]|0)==3?n=w(0):n=w(Tn(e,n)),w(n)}function so(e,n){return e=e|0,n=n|0,e=t[e>>2]|0,((e|0)==0?(n|0)>1?n:1:e)|0}function N0(e,n){e=e|0,n=n|0;var r=0;e:do if((n|0)==2){switch(e|0){case 2:{e=3;break e}case 3:break;default:{r=4;break e}}e=2}else r=4;while(0);return e|0}function C0(e,n){e=e|0,n=n|0;var r=tt;return((Nr(n)|0?(t[e+312>>2]|0)!=0:0)?(r=w(D[e+308>>2]),r>=w(0)):0)||(r=w(Ur(w(D[(en(e+276|0,t[1040+(n<<2)>>2]|0,992)|0)>>2]),w(0)))),w(r)}function di(e,n){e=e|0,n=n|0;var r=tt;return((Nr(n)|0?(t[e+320>>2]|0)!=0:0)?(r=w(D[e+316>>2]),r>=w(0)):0)||(r=w(Ur(w(D[(en(e+276|0,t[1e3+(n<<2)>>2]|0,992)|0)>>2]),w(0)))),w(r)}function u0(e,n,r){e=e|0,n=n|0,r=w(r);var o=tt;return((Nr(n)|0?(t[e+240>>2]|0)!=0:0)?(o=w(Tn(e+236|0,r)),o>=w(0)):0)||(o=w(Ur(w(Tn(en(e+204|0,t[1040+(n<<2)>>2]|0,992)|0,r)),w(0)))),w(o)}function v0(e,n,r){e=e|0,n=n|0,r=w(r);var o=tt;return((Nr(n)|0?(t[e+248>>2]|0)!=0:0)?(o=w(Tn(e+244|0,r)),o>=w(0)):0)||(o=w(Ur(w(Tn(en(e+204|0,t[1e3+(n<<2)>>2]|0,992)|0,r)),w(0)))),w(o)}function To(e,n,r,o,s,l,d){e=e|0,n=w(n),r=w(r),o=o|0,s=s|0,l=w(l),d=w(d);var _=tt,y=tt,k=tt,T=tt,P=tt,q=tt,we=0,le=0,ie=0;ie=h,h=h+16|0,we=ie,le=e+964|0,i0(e,(t[le>>2]|0)!=0,3519),_=w(Fn(e,2,n)),y=w(Fn(e,0,n)),k=w(mt(e,2,n)),T=w(mt(e,0,n)),gt(n)|0?P=n:P=w(Ur(w(0),w(w(n-k)-_))),gt(r)|0?q=r:q=w(Ur(w(0),w(w(r-T)-y))),(o|0)==1&(s|0)==1?(D[e+908>>2]=w(kn(e,2,w(n-k),l,l)),n=w(kn(e,0,w(r-T),d,l))):(lD[t[le>>2]&1](we,e,P,o,q,s),P=w(_+w(D[we>>2])),q=w(n-k),D[e+908>>2]=w(kn(e,2,(o|2|0)==2?P:q,l,l)),q=w(y+w(D[we+4>>2])),n=w(r-T),n=w(kn(e,0,(s|2|0)==2?q:n,d,l))),D[e+912>>2]=n,h=ie}function pu(e,n,r,o,s,l,d){e=e|0,n=w(n),r=w(r),o=o|0,s=s|0,l=w(l),d=w(d);var _=tt,y=tt,k=tt,T=tt;k=w(Fn(e,2,l)),_=w(Fn(e,0,l)),T=w(mt(e,2,l)),y=w(mt(e,0,l)),n=w(n-T),D[e+908>>2]=w(kn(e,2,(o|2|0)==2?k:n,l,l)),r=w(r-y),D[e+912>>2]=w(kn(e,0,(s|2|0)==2?_:r,d,l))}function Sl(e,n,r,o,s,l,d){e=e|0,n=w(n),r=w(r),o=o|0,s=s|0,l=w(l),d=w(d);var _=0,y=tt,k=tt;return _=(o|0)==2,((n<=w(0)&_?0:!(r<=w(0)&(s|0)==2))?!((o|0)==1&(s|0)==1):0)?e=0:(y=w(mt(e,0,l)),k=w(mt(e,2,l)),_=n>2]=w(kn(e,2,_?w(0):n,l,l)),n=w(r-y),_=r>2]=w(kn(e,0,_?w(0):n,d,l)),e=1),e|0}function Cl(e,n){return e=e|0,n=n|0,qt(e)|0?e=N0(2,n)|0:e=0,e|0}function B0(e,n,r){return e=e|0,n=n|0,r=w(r),r=w(u0(e,n,r)),w(r+w(C0(e,n)))}function hu(e,n,r){return e=e|0,n=n|0,r=w(r),r=w(v0(e,n,r)),w(r+w(di(e,n)))}function Fn(e,n,r){e=e|0,n=n|0,r=w(r);var o=tt;return o=w(B0(e,n,r)),w(o+w(hu(e,n,r)))}function pi(e){return e=e|0,t[e+24>>2]|0?e=0:w(Br(e))!=w(0)?e=1:e=w(zr(e))!=w(0),e|0}function Br(e){e=e|0;var n=tt;if(t[e+944>>2]|0){if(n=w(D[e+44>>2]),gt(n)|0)return n=w(D[e+40>>2]),e=n>w(0)&((gt(n)|0)^1),w(e?n:w(0))}else n=w(0);return w(n)}function zr(e){e=e|0;var n=tt,r=0,o=tt;do if(t[e+944>>2]|0){if(n=w(D[e+48>>2]),gt(n)|0){if(r=c[(t[e+976>>2]|0)+2>>0]|0,r<<24>>24==0?(o=w(D[e+40>>2]),o>24?w(1):w(0)}}else n=w(0);while(0);return w(n)}function lo(e){e=e|0;var n=0,r=0;if(pa(e+400|0,0,540)|0,c[e+985>>0]=1,bo(e),r=fi(e)|0,r|0){n=e+948|0,e=0;do lo(t[(t[n>>2]|0)+(e<<2)>>2]|0),e=e+1|0;while((e|0)!=(r|0))}}function wr(e,n,r,o,s,l,d,_,y,k){e=e|0,n=n|0,r=w(r),o=o|0,s=w(s),l=w(l),d=w(d),_=_|0,y=y|0,k=k|0;var T=0,P=tt,q=0,we=0,le=tt,ie=tt,Pe=0,ke=tt,qe=0,pe=tt,_e=0,vt=0,Ln=0,Ht=0,It=0,gn=0,Pn=0,zt=0,Dr=0,Ki=0;Dr=h,h=h+16|0,Ln=Dr+12|0,Ht=Dr+8|0,It=Dr+4|0,gn=Dr,zt=N0(t[e+4>>2]|0,y)|0,_e=Nr(zt)|0,P=w(Tn(Ut(n)|0,_e?l:d)),vt=m0(n,2,l)|0,Pn=m0(n,0,d)|0;do if(gt(P)|0?0:!(gt(_e?r:s)|0)){if(T=n+504|0,!(gt(w(D[T>>2]))|0)&&(!(fn(t[n+976>>2]|0,0)|0)||(t[n+500>>2]|0)==(t[2278]|0)))break;D[T>>2]=w(Ur(P,w(Fn(n,zt,l))))}else q=7;while(0);do if((q|0)==7){if(qe=_e^1,!(qe|vt^1)){d=w(Tn(t[n+992>>2]|0,l)),D[n+504>>2]=w(Ur(d,w(Fn(n,2,l))));break}if(!(_e|Pn^1)){d=w(Tn(t[n+996>>2]|0,d)),D[n+504>>2]=w(Ur(d,w(Fn(n,0,l))));break}D[Ln>>2]=w(J),D[Ht>>2]=w(J),t[It>>2]=0,t[gn>>2]=0,ke=w(mt(n,2,l)),pe=w(mt(n,0,l)),vt?(le=w(ke+w(Tn(t[n+992>>2]|0,l))),D[Ln>>2]=le,t[It>>2]=1,we=1):(we=0,le=w(J)),Pn?(P=w(pe+w(Tn(t[n+996>>2]|0,d))),D[Ht>>2]=P,t[gn>>2]=1,T=1):(T=0,P=w(J)),q=t[e+32>>2]|0,_e&(q|0)==2?q=2:(gt(le)|0?!(gt(r)|0):0)&&(D[Ln>>2]=r,t[It>>2]=2,we=2,le=r),(((q|0)==2&qe?0:gt(P)|0)?!(gt(s)|0):0)&&(D[Ht>>2]=s,t[gn>>2]=2,T=2,P=s),ie=w(D[n+396>>2]),Pe=gt(ie)|0;do if(Pe)q=we;else{if((we|0)==1&qe){D[Ht>>2]=w(w(le-ke)/ie),t[gn>>2]=1,T=1,q=1;break}_e&(T|0)==1?(D[Ln>>2]=w(ie*w(P-pe)),t[It>>2]=1,T=1,q=1):q=we}while(0);Ki=gt(r)|0,we=(T0(e,n)|0)!=4,(_e|vt|((o|0)!=1|Ki)|(we|(q|0)==1)?0:(D[Ln>>2]=r,t[It>>2]=1,!Pe))&&(D[Ht>>2]=w(w(r-ke)/ie),t[gn>>2]=1,T=1),(Pn|qe|((_|0)!=1|(gt(s)|0))|(we|(T|0)==1)?0:(D[Ht>>2]=s,t[gn>>2]=1,!Pe))&&(D[Ln>>2]=w(ie*w(s-pe)),t[It>>2]=1),Kt(n,2,l,l,It,Ln),Kt(n,0,d,l,gn,Ht),r=w(D[Ln>>2]),s=w(D[Ht>>2]),ht(n,r,s,y,t[It>>2]|0,t[gn>>2]|0,l,d,0,3565,k)|0,d=w(D[n+908+(t[976+(zt<<2)>>2]<<2)>>2]),D[n+504>>2]=w(Ur(d,w(Fn(n,zt,l))))}while(0);t[n+500>>2]=t[2278],h=Dr}function kn(e,n,r,o,s){return e=e|0,n=n|0,r=w(r),o=w(o),s=w(s),o=w(Dt(e,n,r,o)),w(Ur(o,w(Fn(e,n,s))))}function T0(e,n){return e=e|0,n=n|0,n=n+20|0,n=t[((t[n>>2]|0)==0?e+16|0:n)>>2]|0,((n|0)==5?qt(t[e+4>>2]|0)|0:0)&&(n=1),n|0}function hi(e,n){return e=e|0,n=n|0,(Nr(n)|0?(t[e+96>>2]|0)!=0:0)?n=4:n=t[1040+(n<<2)>>2]|0,e+60+(n<<3)|0}function Ai(e,n){return e=e|0,n=n|0,(Nr(n)|0?(t[e+104>>2]|0)!=0:0)?n=5:n=t[1e3+(n<<2)>>2]|0,e+60+(n<<3)|0}function Kt(e,n,r,o,s,l){switch(e=e|0,n=n|0,r=w(r),o=w(o),s=s|0,l=l|0,r=w(Tn(e+380+(t[976+(n<<2)>>2]<<3)|0,r)),r=w(r+w(mt(e,n,o))),t[s>>2]|0){case 2:case 1:{s=gt(r)|0,o=w(D[l>>2]),D[l>>2]=s|o>2]=2,D[l>>2]=r);break}default:}}function X(e,n){return e=e|0,n=n|0,e=e+132|0,(Nr(n)|0?(t[(en(e,4,948)|0)+4>>2]|0)!=0:0)?e=1:e=(t[(en(e,t[1040+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function Y(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0;return e=e+132|0,(Nr(n)|0?(o=en(e,4,948)|0,(t[o+4>>2]|0)!=0):0)?s=4:(o=en(e,t[1040+(n<<2)>>2]|0,948)|0,t[o+4>>2]|0?s=4:r=w(0)),(s|0)==4&&(r=w(Tn(o,r))),w(r)}function ye(e,n,r){e=e|0,n=n|0,r=w(r);var o=tt;return o=w(D[e+908+(t[976+(n<<2)>>2]<<2)>>2]),o=w(o+w(Tr(e,n,r))),w(o+w(R0(e,n,r)))}function he(e){e=e|0;var n=0,r=0,o=0;e:do if(qt(t[e+4>>2]|0)|0)n=0;else if((t[e+16>>2]|0)!=5)if(r=fi(e)|0,!r)n=0;else for(n=0;;){if(o=e0(e,n)|0,(t[o+24>>2]|0)==0?(t[o+20>>2]|0)==5:0){n=1;break e}if(n=n+1|0,n>>>0>=r>>>0){n=0;break}}else n=1;while(0);return n|0}function We(e,n){e=e|0,n=n|0;var r=tt;return r=w(D[e+908+(t[976+(n<<2)>>2]<<2)>>2]),r>=w(0)&((gt(r)|0)^1)|0}function et(e){e=e|0;var n=tt,r=0,o=0,s=0,l=0,d=0,_=0,y=tt;if(r=t[e+968>>2]|0,r)y=w(D[e+908>>2]),n=w(D[e+912>>2]),n=w(rD[r&0](e,y,n)),i0(e,(gt(n)|0)^1,3573);else{l=fi(e)|0;do if(l|0){for(r=0,s=0;;){if(o=e0(e,s)|0,t[o+940>>2]|0){d=8;break}if((t[o+24>>2]|0)!=1)if(_=(T0(e,o)|0)==5,_){r=o;break}else r=(r|0)==0?o:r;if(s=s+1|0,s>>>0>=l>>>0){d=8;break}}if((d|0)==8&&!r)break;return n=w(et(r)),w(n+w(D[r+404>>2]))}while(0);n=w(D[e+912>>2])}return w(n)}function Dt(e,n,r,o){e=e|0,n=n|0,r=w(r),o=w(o);var s=tt,l=0;return qt(n)|0?(n=1,l=3):Nr(n)|0?(n=0,l=3):(o=w(J),s=w(J)),(l|0)==3&&(s=w(Tn(e+364+(n<<3)|0,o)),o=w(Tn(e+380+(n<<3)|0,o))),l=o=w(0)&((gt(o)|0)^1)),r=l?o:r,l=s>=w(0)&((gt(s)|0)^1)&r>2]|0,l)|0,le=Cl(Pe,l)|0,ie=Nr(Pe)|0,P=w(mt(n,2,r)),q=w(mt(n,0,r)),m0(n,2,r)|0?_=w(P+w(Tn(t[n+992>>2]|0,r))):(X(n,2)|0?_t(n,2)|0:0)?(_=w(D[e+908>>2]),y=w(C0(e,2)),y=w(_-w(y+w(di(e,2)))),_=w(Y(n,2,r)),_=w(kn(n,2,w(y-w(_+w(_r(n,2,r)))),r,r))):_=w(J),m0(n,0,s)|0?y=w(q+w(Tn(t[n+996>>2]|0,s))):(X(n,0)|0?_t(n,0)|0:0)?(y=w(D[e+912>>2]),qe=w(C0(e,0)),qe=w(y-w(qe+w(di(e,0)))),y=w(Y(n,0,s)),y=w(kn(n,0,w(qe-w(y+w(_r(n,0,s)))),s,r))):y=w(J),k=gt(_)|0,T=gt(y)|0;do if(k^T?(we=w(D[n+396>>2]),!(gt(we)|0)):0)if(k){_=w(P+w(w(y-q)*we));break}else{qe=w(q+w(w(_-P)/we)),y=T?qe:y;break}while(0);T=gt(_)|0,k=gt(y)|0,T|k&&(pe=(T^1)&1,o=r>w(0)&((o|0)!=0&T),_=ie?_:o?r:_,ht(n,_,y,l,ie?pe:o?2:pe,T&(k^1)&1,_,y,0,3623,d)|0,_=w(D[n+908>>2]),_=w(_+w(mt(n,2,r))),y=w(D[n+912>>2]),y=w(y+w(mt(n,0,r)))),ht(n,_,y,l,1,1,_,y,1,3635,d)|0,(_t(n,Pe)|0?!(X(n,Pe)|0):0)?(pe=t[976+(Pe<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(qe-w(D[n+908+(pe<<2)>>2])),qe=w(qe-w(di(e,Pe))),qe=w(qe-w(R0(n,Pe,r))),qe=w(qe-w(_r(n,Pe,ie?r:s))),D[n+400+(t[1040+(Pe<<2)>>2]<<2)>>2]=qe):ke=21;do if((ke|0)==21){if(X(n,Pe)|0?0:(t[e+8>>2]|0)==1){pe=t[976+(Pe<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(w(qe-w(D[n+908+(pe<<2)>>2]))*w(.5)),D[n+400+(t[1040+(Pe<<2)>>2]<<2)>>2]=qe;break}(X(n,Pe)|0?0:(t[e+8>>2]|0)==2)&&(pe=t[976+(Pe<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(qe-w(D[n+908+(pe<<2)>>2])),D[n+400+(t[1040+(Pe<<2)>>2]<<2)>>2]=qe)}while(0);(_t(n,le)|0?!(X(n,le)|0):0)?(pe=t[976+(le<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(qe-w(D[n+908+(pe<<2)>>2])),qe=w(qe-w(di(e,le))),qe=w(qe-w(R0(n,le,r))),qe=w(qe-w(_r(n,le,ie?s:r))),D[n+400+(t[1040+(le<<2)>>2]<<2)>>2]=qe):ke=30;do if((ke|0)==30?!(X(n,le)|0):0){if((T0(e,n)|0)==2){pe=t[976+(le<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(w(qe-w(D[n+908+(pe<<2)>>2]))*w(.5)),D[n+400+(t[1040+(le<<2)>>2]<<2)>>2]=qe;break}pe=(T0(e,n)|0)==3,pe^(t[e+28>>2]|0)==2&&(pe=t[976+(le<<2)>>2]|0,qe=w(D[e+908+(pe<<2)>>2]),qe=w(qe-w(D[n+908+(pe<<2)>>2])),D[n+400+(t[1040+(le<<2)>>2]<<2)>>2]=qe)}while(0)}function Zt(e,n,r){e=e|0,n=n|0,r=r|0;var o=tt,s=0;s=t[976+(r<<2)>>2]|0,o=w(D[n+908+(s<<2)>>2]),o=w(w(D[e+908+(s<<2)>>2])-o),o=w(o-w(D[n+400+(t[1040+(r<<2)>>2]<<2)>>2])),D[n+400+(t[1e3+(r<<2)>>2]<<2)>>2]=o}function qt(e){return e=e|0,(e|1|0)==1|0}function Ut(e){e=e|0;var n=tt;switch(t[e+56>>2]|0){case 0:case 3:{n=w(D[e+40>>2]),n>w(0)&((gt(n)|0)^1)?e=c[(t[e+976>>2]|0)+2>>0]|0?1056:992:e=1056;break}default:e=e+52|0}return e|0}function fn(e,n){return e=e|0,n=n|0,(c[e+n>>0]|0)!=0|0}function _t(e,n){return e=e|0,n=n|0,e=e+132|0,(Nr(n)|0?(t[(en(e,5,948)|0)+4>>2]|0)!=0:0)?e=1:e=(t[(en(e,t[1e3+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function _r(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,s=0;return e=e+132|0,(Nr(n)|0?(o=en(e,5,948)|0,(t[o+4>>2]|0)!=0):0)?s=4:(o=en(e,t[1e3+(n<<2)>>2]|0,948)|0,t[o+4>>2]|0?s=4:r=w(0)),(s|0)==4&&(r=w(Tn(o,r))),w(r)}function Wr(e,n,r){return e=e|0,n=n|0,r=w(r),X(e,n)|0?r=w(Y(e,n,r)):r=w(-w(_r(e,n,r))),w(r)}function Ar(e){return e=w(e),D[j>>2]=e,t[j>>2]|0|0}function z(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)_n();else{s=Tt(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<2)}function dr(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>2)<<2)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Or(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Ve(e)}function Qn(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;if(d=e+4|0,_=t[d>>2]|0,s=_-o|0,l=s>>2,e=n+(l<<2)|0,e>>>0>>0){o=_;do t[o>>2]=t[e>>2],e=e+4|0,o=(t[d>>2]|0)+4|0,t[d>>2]=o;while(e>>>0>>0)}l|0&&Y1(_+(0-l<<2)|0,n|0,s|0)|0}function nn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0;return _=n+4|0,y=t[_>>2]|0,s=t[e>>2]|0,d=r,l=d-s|0,o=y+(0-(l>>2)<<2)|0,t[_>>2]=o,(l|0)>0&&vn(o|0,s|0,l|0)|0,s=e+4|0,l=n+8|0,o=(t[s>>2]|0)-d|0,(o|0)>0&&(vn(t[l>>2]|0,r|0,o|0)|0,t[l>>2]=(t[l>>2]|0)+(o>>>2<<2)),d=t[e>>2]|0,t[e>>2]=t[_>>2],t[_>>2]=d,d=t[s>>2]|0,t[s>>2]=t[l>>2],t[l>>2]=d,d=e+8|0,r=n+12|0,e=t[d>>2]|0,t[d>>2]=t[r>>2],t[r>>2]=e,t[n>>2]=t[_>>2],y|0}function s0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;if(d=t[n>>2]|0,l=t[r>>2]|0,(d|0)!=(l|0)){s=e+8|0,r=((l+-4-d|0)>>>2)+1|0,e=d,o=t[s>>2]|0;do t[o>>2]=t[e>>2],o=(t[s>>2]|0)+4|0,t[s>>2]=o,e=e+4|0;while((e|0)!=(l|0));t[n>>2]=d+(r<<2)}}function t0(){_l()}function g0(){var e=0;return e=Tt(4)|0,Kr(e),e|0}function Kr(e){e=e|0,t[e>>2]=a0()|0}function _0(e){e=e|0,e|0&&(Gi(e),Ve(e))}function Gi(e){e=e|0,V0(t[e>>2]|0)}function fo(e,n,r){e=e|0,n=n|0,r=r|0,J0(t[e>>2]|0,n,r)}function x0(e,n){e=e|0,n=w(n),ki(t[e>>2]|0,n)}function Xu(e,n){return e=e|0,n=n|0,fn(t[e>>2]|0,n)|0}function Z0(){var e=0;return e=Tt(8)|0,df(e,0),e|0}function df(e,n){e=e|0,n=n|0,n?n=I0(t[n>>2]|0)|0:n=qu()|0,t[e>>2]=n,t[e+4>>2]=0,Bs(n,e)}function Ba(e){e=e|0;var n=0;return n=Tt(8)|0,df(n,e),n|0}function Oc(e){e=e|0,e|0&&(mu(e),Ve(e))}function mu(e){e=e|0;var n=0;Wu(t[e>>2]|0),n=e+4|0,e=t[n>>2]|0,t[n>>2]=0,e|0&&(Ju(e),Ve(e))}function Ju(e){e=e|0,ei(e)}function ei(e){e=e|0,e=t[e>>2]|0,e|0&&ju(e|0)}function Yf(e){return e=e|0,Vu(e)|0}function pf(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(Ju(n),Ve(n)),Do(t[e>>2]|0)}function ja(e,n){e=e|0,n=n|0,Gu(t[e>>2]|0,t[n>>2]|0)}function Ua(e,n){e=e|0,n=n|0,W(t[e>>2]|0,n)}function Ic(e,n,r){e=e|0,n=n|0,r=+r,yn(t[e>>2]|0,n,w(r))}function vu(e,n,r){e=e|0,n=n|0,r=+r,sn(t[e>>2]|0,n,w(r))}function $f(e,n){e=e|0,n=n|0,R(t[e>>2]|0,n)}function gu(e,n){e=e|0,n=n|0,H(t[e>>2]|0,n)}function co(e,n){e=e|0,n=n|0,ue(t[e>>2]|0,n)}function qa(e,n){e=e|0,n=n|0,M0(t[e>>2]|0,n)}function Ws(e,n){e=e|0,n=n|0,Fe(t[e>>2]|0,n)}function za(e,n){e=e|0,n=n|0,Lr(t[e>>2]|0,n)}function Pc(e,n,r){e=e|0,n=n|0,r=+r,rn(t[e>>2]|0,n,w(r))}function Qu(e,n,r){e=e|0,n=n|0,r=+r,Hn(t[e>>2]|0,n,w(r))}function Mc(e,n){e=e|0,n=n|0,Cr(t[e>>2]|0,n)}function Fc(e,n){e=e|0,n=n|0,K(t[e>>2]|0,n)}function Lc(e,n){e=e|0,n=n|0,je(t[e>>2]|0,n)}function Kf(e,n){e=e|0,n=+n,rt(t[e>>2]|0,w(n))}function Tl(e,n){e=e|0,n=+n,wt(t[e>>2]|0,w(n))}function xl(e,n){e=e|0,n=+n,lt(t[e>>2]|0,w(n))}function hf(e,n){e=e|0,n=+n,st(t[e>>2]|0,w(n))}function xo(e,n){e=e|0,n=+n,xt(t[e>>2]|0,w(n))}function mf(e,n){e=e|0,n=+n,Qt(t[e>>2]|0,w(n))}function Wa(e,n){e=e|0,n=+n,Cn(t[e>>2]|0,w(n))}function ti(e){e=e|0,bn(t[e>>2]|0)}function Hs(e,n){e=e|0,n=+n,h0(t[e>>2]|0,w(n))}function mi(e,n){e=e|0,n=+n,ci(t[e>>2]|0,w(n))}function vi(e){e=e|0,xi(t[e>>2]|0)}function Xf(e,n){e=e|0,n=+n,qr(t[e>>2]|0,w(n))}function Rc(e,n){e=e|0,n=+n,Eo(t[e>>2]|0,w(n))}function Jf(e,n){e=e|0,n=+n,wl(t[e>>2]|0,w(n))}function ao(e,n){e=e|0,n=+n,js(t[e>>2]|0,w(n))}function $o(e,n){e=e|0,n=+n,du(t[e>>2]|0,w(n))}function kl(e,n){e=e|0,n=+n,Yu(t[e>>2]|0,w(n))}function Nc(e,n){e=e|0,n=+n,oo(t[e>>2]|0,w(n))}function Al(e,n){e=e|0,n=+n,Hi(t[e>>2]|0,w(n))}function vf(e,n){e=e|0,n=+n,F0(t[e>>2]|0,w(n))}function Qf(e,n,r){e=e|0,n=n|0,r=+r,ft(t[e>>2]|0,n,w(r))}function k0(e,n,r){e=e|0,n=n|0,r=+r,He(t[e>>2]|0,n,w(r))}function v(e,n,r){e=e|0,n=n|0,r=+r,Qe(t[e>>2]|0,n,w(r))}function m(e){return e=e|0,ve(t[e>>2]|0)|0}function S(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;o=h,h=h+16|0,s=o,ar(s,t[n>>2]|0,r),O(e,s),h=o}function O(e,n){e=e|0,n=n|0,M(e,t[n+4>>2]|0,+w(D[n>>2]))}function M(e,n,r){e=e|0,n=n|0,r=+r,t[e>>2]=n,L[e+8>>3]=r}function b(e){return e=e|0,U(t[e>>2]|0)|0}function ee(e){return e=e|0,fe(t[e>>2]|0)|0}function Ye(e){return e=e|0,de(t[e>>2]|0)|0}function Ze(e){return e=e|0,au(t[e>>2]|0)|0}function ut(e){return e=e|0,Ge(t[e>>2]|0)|0}function In(e){return e=e|0,F(t[e>>2]|0)|0}function A0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;o=h,h=h+16|0,s=o,d0(s,t[n>>2]|0,r),O(e,s),h=o}function jr(e){return e=e|0,xe(t[e>>2]|0)|0}function gi(e){return e=e|0,Xe(t[e>>2]|0)|0}function po(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,Rt(o,t[n>>2]|0),O(e,o),h=r}function _i(e){return e=e|0,+ +w(yl(t[e>>2]|0))}function Re(e){return e=e|0,+ +w(cu(t[e>>2]|0))}function Ce(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,p0(o,t[n>>2]|0),O(e,o),h=r}function ze(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,E0(o,t[n>>2]|0),O(e,o),h=r}function Et(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,So(o,t[n>>2]|0),O(e,o),h=r}function on(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,Dl(o,t[n>>2]|0),O(e,o),h=r}function sr(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,Us(o,t[n>>2]|0),O(e,o),h=r}function mn(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,qs(o,t[n>>2]|0),O(e,o),h=r}function pr(e){return e=e|0,+ +w(Gr(t[e>>2]|0))}function Hr(e,n){return e=e|0,n=n|0,+ +w(St(t[e>>2]|0,n))}function Vn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;o=h,h=h+16|0,s=o,Ne(s,t[n>>2]|0,r),O(e,s),h=o}function ni(e,n,r){e=e|0,n=n|0,r=r|0,Ns(t[e>>2]|0,t[n>>2]|0,r)}function Zf(e,n){e=e|0,n=n|0,D0(t[e>>2]|0,t[n>>2]|0)}function Pm(e){return e=e|0,fi(t[e>>2]|0)|0}function Ha(e){return e=e|0,e=nr(t[e>>2]|0)|0,e?e=Yf(e)|0:e=0,e|0}function vd(e,n){return e=e|0,n=n|0,e=e0(t[e>>2]|0,n)|0,e?e=Yf(e)|0:e=0,e|0}function gd(e,n){e=e|0,n=n|0;var r=0,o=0;o=Tt(4)|0,ba(o,n),r=e+4|0,n=t[r>>2]|0,t[r>>2]=o,n|0&&(Ju(n),Ve(n)),bu(t[e>>2]|0,1)}function ba(e,n){e=e|0,n=n|0,Oo(e,n)}function Bc(e,n,r,o,s,l){e=e|0,n=n|0,r=w(r),o=o|0,s=w(s),l=l|0;var d=0,_=0;d=h,h=h+16|0,_=d,Mm(_,Vu(n)|0,+r,o,+s,l),D[e>>2]=w(+L[_>>3]),D[e+4>>2]=w(+L[_+8>>3]),h=d}function Mm(e,n,r,o,s,l){e=e|0,n=n|0,r=+r,o=o|0,s=+s,l=l|0;var d=0,_=0,y=0,k=0,T=0;d=h,h=h+32|0,T=d+8|0,k=d+20|0,y=d,_=d+16|0,L[T>>3]=r,t[k>>2]=o,L[y>>3]=s,t[_>>2]=l,_d(e,t[n+4>>2]|0,T,k,y,_),h=d}function _d(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0;d=h,h=h+16|0,_=d,Zo(_),n=Oi(n)|0,Fm(e,n,+L[r>>3],t[o>>2]|0,+L[s>>3],t[l>>2]|0),eu(_),h=d}function Oi(e){return e=e|0,t[e>>2]|0}function Fm(e,n,r,o,s,l){e=e|0,n=n|0,r=+r,o=o|0,s=+s,l=l|0;var d=0;d=ko(yd()|0)|0,r=+Ko(r),o=jc(o)|0,s=+Ko(s),Ga(e,ro(0,d|0,n|0,+r,o|0,+s,jc(l)|0)|0)}function yd(){var e=0;return c[7608]|0||(Ed(9120),e=7608,t[e>>2]=1,t[e+4>>2]=0),9120}function ko(e){return e=e|0,t[e+8>>2]|0}function Ko(e){return e=+e,+ +Ol(e)}function jc(e){return e=e|0,Dd(e)|0}function Ga(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;s=h,h=h+32|0,r=s,o=n,o&1?(Lm(r,0),c0(o|0,r|0)|0,Va(e,r),Wn(r)):(t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]),h=s}function Lm(e,n){e=e|0,n=n|0,wd(e,n),t[e+8>>2]=0,c[e+24>>0]=0}function Va(e,n){e=e|0,n=n|0,n=n+8|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]}function Wn(e){e=e|0,c[e+24>>0]=0}function wd(e,n){e=e|0,n=n|0,t[e>>2]=n}function Dd(e){return e=e|0,e|0}function Ol(e){return e=+e,+e}function Ed(e){e=e|0,Ao(e,Rm()|0,4)}function Rm(){return 1064}function Ao(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=hl(n|0,r+1|0)|0}function Oo(e,n){e=e|0,n=n|0,n=t[n>>2]|0,t[e>>2]=n,qi(n|0)}function Nm(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(Ju(n),Ve(n)),bu(t[e>>2]|0,0)}function Uc(e){e=e|0,rr(t[e>>2]|0)}function Ya(e){return e=e|0,Go(t[e>>2]|0)|0}function Sd(e,n,r,o){e=e|0,n=+n,r=+r,o=o|0,Yr(t[e>>2]|0,w(n),w(r),o)}function Cd(e){return e=e|0,+ +w(ir(t[e>>2]|0))}function ho(e){return e=e|0,+ +w(Y0(t[e>>2]|0))}function bs(e){return e=e|0,+ +w(L0(t[e>>2]|0))}function $a(e){return e=e|0,+ +w(Co(t[e>>2]|0))}function Td(e){return e=e|0,+ +w($u(t[e>>2]|0))}function qc(e){return e=e|0,+ +w(Vo(t[e>>2]|0))}function xd(e,n){e=e|0,n=n|0,L[e>>3]=+w(ir(t[n>>2]|0)),L[e+8>>3]=+w(Y0(t[n>>2]|0)),L[e+16>>3]=+w(L0(t[n>>2]|0)),L[e+24>>3]=+w(Co(t[n>>2]|0)),L[e+32>>3]=+w($u(t[n>>2]|0)),L[e+40>>3]=+w(Vo(t[n>>2]|0))}function Ka(e,n){return e=e|0,n=n|0,+ +w(Rr(t[e>>2]|0,n))}function kd(e,n){return e=e|0,n=n|0,+ +w(Jn(t[e>>2]|0,n))}function Xa(e,n){return e=e|0,n=n|0,+ +w(ai(t[e>>2]|0,n))}function Ja(){return Rs()|0}function Gs(){Bm(),Vs(),Ad(),Od(),Qa(),jm()}function Bm(){hO(11713,4938,1)}function Vs(){FA(10448)}function Ad(){hA(10408)}function Od(){Bk(10324)}function Qa(){Gx(10096)}function jm(){Um(9132)}function Um(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0,qe=0,pe=0,_e=0,vt=0,Ln=0,Ht=0,It=0,gn=0,Pn=0,zt=0,Dr=0,Ki=0,Xi=0,Ji=0,Ro=0,kf=0,Af=0,Cu=0,Of=0,Js=0,Qs=0,If=0,Pf=0,Mf=0,Kn=0,Tu=0,Ff=0,us=0,Lf=0,Rf=0,Zs=0,el=0,ss=0,Fi=0,nu=0,go=0,xu=0,jl=0,Ul=0,tl=0,ql=0,zl=0,Li=0,Di=0,ku=0,xr=0,Wl=0,Qi=0,ls=0,Zi=0,fs=0,Hl=0,bl=0,cs=0,Ri=0,Au=0,Gl=0,Vl=0,Yl=0,En=0,br=0,Ei=0,eo=0,Ni=0,xn=0,Vt=0,Ou=0;n=h,h=h+672|0,r=n+656|0,Ou=n+648|0,Vt=n+640|0,xn=n+632|0,Ni=n+624|0,eo=n+616|0,Ei=n+608|0,br=n+600|0,En=n+592|0,Yl=n+584|0,Vl=n+576|0,Gl=n+568|0,Au=n+560|0,Ri=n+552|0,cs=n+544|0,bl=n+536|0,Hl=n+528|0,fs=n+520|0,Zi=n+512|0,ls=n+504|0,Qi=n+496|0,Wl=n+488|0,xr=n+480|0,ku=n+472|0,Di=n+464|0,Li=n+456|0,zl=n+448|0,ql=n+440|0,tl=n+432|0,Ul=n+424|0,jl=n+416|0,xu=n+408|0,go=n+400|0,nu=n+392|0,Fi=n+384|0,ss=n+376|0,el=n+368|0,Zs=n+360|0,Rf=n+352|0,Lf=n+344|0,us=n+336|0,Ff=n+328|0,Tu=n+320|0,Kn=n+312|0,Mf=n+304|0,Pf=n+296|0,If=n+288|0,Qs=n+280|0,Js=n+272|0,Of=n+264|0,Cu=n+256|0,Af=n+248|0,kf=n+240|0,Ro=n+232|0,Ji=n+224|0,Xi=n+216|0,Ki=n+208|0,Dr=n+200|0,zt=n+192|0,Pn=n+184|0,gn=n+176|0,It=n+168|0,Ht=n+160|0,Ln=n+152|0,vt=n+144|0,_e=n+136|0,pe=n+128|0,qe=n+120|0,ke=n+112|0,Pe=n+104|0,ie=n+96|0,le=n+88|0,we=n+80|0,q=n+72|0,P=n+64|0,T=n+56|0,k=n+48|0,y=n+40|0,_=n+32|0,d=n+24|0,l=n+16|0,s=n+8|0,o=n,qm(e,3646),Id(e,3651,2)|0,Pd(e,3665,2)|0,zm(e,3682,18)|0,t[Ou>>2]=19,t[Ou+4>>2]=0,t[r>>2]=t[Ou>>2],t[r+4>>2]=t[Ou+4>>2],gf(e,3690,r)|0,t[Vt>>2]=1,t[Vt+4>>2]=0,t[r>>2]=t[Vt>>2],t[r+4>>2]=t[Vt+4>>2],Md(e,3696,r)|0,t[xn>>2]=2,t[xn+4>>2]=0,t[r>>2]=t[xn>>2],t[r+4>>2]=t[xn+4>>2],Xr(e,3706,r)|0,t[Ni>>2]=1,t[Ni+4>>2]=0,t[r>>2]=t[Ni>>2],t[r+4>>2]=t[Ni+4>>2],yi(e,3722,r)|0,t[eo>>2]=2,t[eo+4>>2]=0,t[r>>2]=t[eo>>2],t[r+4>>2]=t[eo+4>>2],yi(e,3734,r)|0,t[Ei>>2]=3,t[Ei+4>>2]=0,t[r>>2]=t[Ei>>2],t[r+4>>2]=t[Ei+4>>2],Xr(e,3753,r)|0,t[br>>2]=4,t[br+4>>2]=0,t[r>>2]=t[br>>2],t[r+4>>2]=t[br+4>>2],Xr(e,3769,r)|0,t[En>>2]=5,t[En+4>>2]=0,t[r>>2]=t[En>>2],t[r+4>>2]=t[En+4>>2],Xr(e,3783,r)|0,t[Yl>>2]=6,t[Yl+4>>2]=0,t[r>>2]=t[Yl>>2],t[r+4>>2]=t[Yl+4>>2],Xr(e,3796,r)|0,t[Vl>>2]=7,t[Vl+4>>2]=0,t[r>>2]=t[Vl>>2],t[r+4>>2]=t[Vl+4>>2],Xr(e,3813,r)|0,t[Gl>>2]=8,t[Gl+4>>2]=0,t[r>>2]=t[Gl>>2],t[r+4>>2]=t[Gl+4>>2],Xr(e,3825,r)|0,t[Au>>2]=3,t[Au+4>>2]=0,t[r>>2]=t[Au>>2],t[r+4>>2]=t[Au+4>>2],yi(e,3843,r)|0,t[Ri>>2]=4,t[Ri+4>>2]=0,t[r>>2]=t[Ri>>2],t[r+4>>2]=t[Ri+4>>2],yi(e,3853,r)|0,t[cs>>2]=9,t[cs+4>>2]=0,t[r>>2]=t[cs>>2],t[r+4>>2]=t[cs+4>>2],Xr(e,3870,r)|0,t[bl>>2]=10,t[bl+4>>2]=0,t[r>>2]=t[bl>>2],t[r+4>>2]=t[bl+4>>2],Xr(e,3884,r)|0,t[Hl>>2]=11,t[Hl+4>>2]=0,t[r>>2]=t[Hl>>2],t[r+4>>2]=t[Hl+4>>2],Xr(e,3896,r)|0,t[fs>>2]=1,t[fs+4>>2]=0,t[r>>2]=t[fs>>2],t[r+4>>2]=t[fs+4>>2],j0(e,3907,r)|0,t[Zi>>2]=2,t[Zi+4>>2]=0,t[r>>2]=t[Zi>>2],t[r+4>>2]=t[Zi+4>>2],j0(e,3915,r)|0,t[ls>>2]=3,t[ls+4>>2]=0,t[r>>2]=t[ls>>2],t[r+4>>2]=t[ls+4>>2],j0(e,3928,r)|0,t[Qi>>2]=4,t[Qi+4>>2]=0,t[r>>2]=t[Qi>>2],t[r+4>>2]=t[Qi+4>>2],j0(e,3948,r)|0,t[Wl>>2]=5,t[Wl+4>>2]=0,t[r>>2]=t[Wl>>2],t[r+4>>2]=t[Wl+4>>2],j0(e,3960,r)|0,t[xr>>2]=6,t[xr+4>>2]=0,t[r>>2]=t[xr>>2],t[r+4>>2]=t[xr+4>>2],j0(e,3974,r)|0,t[ku>>2]=7,t[ku+4>>2]=0,t[r>>2]=t[ku>>2],t[r+4>>2]=t[ku+4>>2],j0(e,3983,r)|0,t[Di>>2]=20,t[Di+4>>2]=0,t[r>>2]=t[Di>>2],t[r+4>>2]=t[Di+4>>2],gf(e,3999,r)|0,t[Li>>2]=8,t[Li+4>>2]=0,t[r>>2]=t[Li>>2],t[r+4>>2]=t[Li+4>>2],j0(e,4012,r)|0,t[zl>>2]=9,t[zl+4>>2]=0,t[r>>2]=t[zl>>2],t[r+4>>2]=t[zl+4>>2],j0(e,4022,r)|0,t[ql>>2]=21,t[ql+4>>2]=0,t[r>>2]=t[ql>>2],t[r+4>>2]=t[ql+4>>2],gf(e,4039,r)|0,t[tl>>2]=10,t[tl+4>>2]=0,t[r>>2]=t[tl>>2],t[r+4>>2]=t[tl+4>>2],j0(e,4053,r)|0,t[Ul>>2]=11,t[Ul+4>>2]=0,t[r>>2]=t[Ul>>2],t[r+4>>2]=t[Ul+4>>2],j0(e,4065,r)|0,t[jl>>2]=12,t[jl+4>>2]=0,t[r>>2]=t[jl>>2],t[r+4>>2]=t[jl+4>>2],j0(e,4084,r)|0,t[xu>>2]=13,t[xu+4>>2]=0,t[r>>2]=t[xu>>2],t[r+4>>2]=t[xu+4>>2],j0(e,4097,r)|0,t[go>>2]=14,t[go+4>>2]=0,t[r>>2]=t[go>>2],t[r+4>>2]=t[go+4>>2],j0(e,4117,r)|0,t[nu>>2]=15,t[nu+4>>2]=0,t[r>>2]=t[nu>>2],t[r+4>>2]=t[nu+4>>2],j0(e,4129,r)|0,t[Fi>>2]=16,t[Fi+4>>2]=0,t[r>>2]=t[Fi>>2],t[r+4>>2]=t[Fi+4>>2],j0(e,4148,r)|0,t[ss>>2]=17,t[ss+4>>2]=0,t[r>>2]=t[ss>>2],t[r+4>>2]=t[ss+4>>2],j0(e,4161,r)|0,t[el>>2]=18,t[el+4>>2]=0,t[r>>2]=t[el>>2],t[r+4>>2]=t[el+4>>2],j0(e,4181,r)|0,t[Zs>>2]=5,t[Zs+4>>2]=0,t[r>>2]=t[Zs>>2],t[r+4>>2]=t[Zs+4>>2],yi(e,4196,r)|0,t[Rf>>2]=6,t[Rf+4>>2]=0,t[r>>2]=t[Rf>>2],t[r+4>>2]=t[Rf+4>>2],yi(e,4206,r)|0,t[Lf>>2]=7,t[Lf+4>>2]=0,t[r>>2]=t[Lf>>2],t[r+4>>2]=t[Lf+4>>2],yi(e,4217,r)|0,t[us>>2]=3,t[us+4>>2]=0,t[r>>2]=t[us>>2],t[r+4>>2]=t[us+4>>2],Zu(e,4235,r)|0,t[Ff>>2]=1,t[Ff+4>>2]=0,t[r>>2]=t[Ff>>2],t[r+4>>2]=t[Ff+4>>2],_f(e,4251,r)|0,t[Tu>>2]=4,t[Tu+4>>2]=0,t[r>>2]=t[Tu>>2],t[r+4>>2]=t[Tu+4>>2],Zu(e,4263,r)|0,t[Kn>>2]=5,t[Kn+4>>2]=0,t[r>>2]=t[Kn>>2],t[r+4>>2]=t[Kn+4>>2],Zu(e,4279,r)|0,t[Mf>>2]=6,t[Mf+4>>2]=0,t[r>>2]=t[Mf>>2],t[r+4>>2]=t[Mf+4>>2],Zu(e,4293,r)|0,t[Pf>>2]=7,t[Pf+4>>2]=0,t[r>>2]=t[Pf>>2],t[r+4>>2]=t[Pf+4>>2],Zu(e,4306,r)|0,t[If>>2]=8,t[If+4>>2]=0,t[r>>2]=t[If>>2],t[r+4>>2]=t[If+4>>2],Zu(e,4323,r)|0,t[Qs>>2]=9,t[Qs+4>>2]=0,t[r>>2]=t[Qs>>2],t[r+4>>2]=t[Qs+4>>2],Zu(e,4335,r)|0,t[Js>>2]=2,t[Js+4>>2]=0,t[r>>2]=t[Js>>2],t[r+4>>2]=t[Js+4>>2],_f(e,4353,r)|0,t[Of>>2]=12,t[Of+4>>2]=0,t[r>>2]=t[Of>>2],t[r+4>>2]=t[Of+4>>2],Io(e,4363,r)|0,t[Cu>>2]=1,t[Cu+4>>2]=0,t[r>>2]=t[Cu>>2],t[r+4>>2]=t[Cu+4>>2],_u(e,4376,r)|0,t[Af>>2]=2,t[Af+4>>2]=0,t[r>>2]=t[Af>>2],t[r+4>>2]=t[Af+4>>2],_u(e,4388,r)|0,t[kf>>2]=13,t[kf+4>>2]=0,t[r>>2]=t[kf>>2],t[r+4>>2]=t[kf+4>>2],Io(e,4402,r)|0,t[Ro>>2]=14,t[Ro+4>>2]=0,t[r>>2]=t[Ro>>2],t[r+4>>2]=t[Ro+4>>2],Io(e,4411,r)|0,t[Ji>>2]=15,t[Ji+4>>2]=0,t[r>>2]=t[Ji>>2],t[r+4>>2]=t[Ji+4>>2],Io(e,4421,r)|0,t[Xi>>2]=16,t[Xi+4>>2]=0,t[r>>2]=t[Xi>>2],t[r+4>>2]=t[Xi+4>>2],Io(e,4433,r)|0,t[Ki>>2]=17,t[Ki+4>>2]=0,t[r>>2]=t[Ki>>2],t[r+4>>2]=t[Ki+4>>2],Io(e,4446,r)|0,t[Dr>>2]=18,t[Dr+4>>2]=0,t[r>>2]=t[Dr>>2],t[r+4>>2]=t[Dr+4>>2],Io(e,4458,r)|0,t[zt>>2]=3,t[zt+4>>2]=0,t[r>>2]=t[zt>>2],t[r+4>>2]=t[zt+4>>2],_u(e,4471,r)|0,t[Pn>>2]=1,t[Pn+4>>2]=0,t[r>>2]=t[Pn>>2],t[r+4>>2]=t[Pn+4>>2],ec(e,4486,r)|0,t[gn>>2]=10,t[gn+4>>2]=0,t[r>>2]=t[gn>>2],t[r+4>>2]=t[gn+4>>2],Zu(e,4496,r)|0,t[It>>2]=11,t[It+4>>2]=0,t[r>>2]=t[It>>2],t[r+4>>2]=t[It+4>>2],Zu(e,4508,r)|0,t[Ht>>2]=3,t[Ht+4>>2]=0,t[r>>2]=t[Ht>>2],t[r+4>>2]=t[Ht+4>>2],_f(e,4519,r)|0,t[Ln>>2]=4,t[Ln+4>>2]=0,t[r>>2]=t[Ln>>2],t[r+4>>2]=t[Ln+4>>2],Wm(e,4530,r)|0,t[vt>>2]=19,t[vt+4>>2]=0,t[r>>2]=t[vt>>2],t[r+4>>2]=t[vt+4>>2],Fd(e,4542,r)|0,t[_e>>2]=12,t[_e+4>>2]=0,t[r>>2]=t[_e>>2],t[r+4>>2]=t[_e+4>>2],yf(e,4554,r)|0,t[pe>>2]=13,t[pe+4>>2]=0,t[r>>2]=t[pe>>2],t[r+4>>2]=t[pe+4>>2],tc(e,4568,r)|0,t[qe>>2]=2,t[qe+4>>2]=0,t[r>>2]=t[qe>>2],t[r+4>>2]=t[qe+4>>2],Hm(e,4578,r)|0,t[ke>>2]=20,t[ke+4>>2]=0,t[r>>2]=t[ke>>2],t[r+4>>2]=t[ke+4>>2],Ld(e,4587,r)|0,t[Pe>>2]=22,t[Pe+4>>2]=0,t[r>>2]=t[Pe>>2],t[r+4>>2]=t[Pe+4>>2],gf(e,4602,r)|0,t[ie>>2]=23,t[ie+4>>2]=0,t[r>>2]=t[ie>>2],t[r+4>>2]=t[ie+4>>2],gf(e,4619,r)|0,t[le>>2]=14,t[le+4>>2]=0,t[r>>2]=t[le>>2],t[r+4>>2]=t[le+4>>2],Rd(e,4629,r)|0,t[we>>2]=1,t[we+4>>2]=0,t[r>>2]=t[we>>2],t[r+4>>2]=t[we+4>>2],zc(e,4637,r)|0,t[q>>2]=4,t[q+4>>2]=0,t[r>>2]=t[q>>2],t[r+4>>2]=t[q+4>>2],_u(e,4653,r)|0,t[P>>2]=5,t[P+4>>2]=0,t[r>>2]=t[P>>2],t[r+4>>2]=t[P+4>>2],_u(e,4669,r)|0,t[T>>2]=6,t[T+4>>2]=0,t[r>>2]=t[T>>2],t[r+4>>2]=t[T+4>>2],_u(e,4686,r)|0,t[k>>2]=7,t[k+4>>2]=0,t[r>>2]=t[k>>2],t[r+4>>2]=t[k+4>>2],_u(e,4701,r)|0,t[y>>2]=8,t[y+4>>2]=0,t[r>>2]=t[y>>2],t[r+4>>2]=t[y+4>>2],_u(e,4719,r)|0,t[_>>2]=9,t[_+4>>2]=0,t[r>>2]=t[_>>2],t[r+4>>2]=t[_+4>>2],_u(e,4736,r)|0,t[d>>2]=21,t[d+4>>2]=0,t[r>>2]=t[d>>2],t[r+4>>2]=t[d+4>>2],Nd(e,4754,r)|0,t[l>>2]=2,t[l+4>>2]=0,t[r>>2]=t[l>>2],t[r+4>>2]=t[l+4>>2],ec(e,4772,r)|0,t[s>>2]=3,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],ec(e,4790,r)|0,t[o>>2]=4,t[o+4>>2]=0,t[r>>2]=t[o>>2],t[r+4>>2]=t[o+4>>2],ec(e,4808,r)|0,h=n}function qm(e,n){e=e|0,n=n|0;var r=0;r=Nx()|0,t[e>>2]=r,Bx(r,n),Cf(t[e>>2]|0)}function Id(e,n,r){return e=e|0,n=n|0,r=r|0,Ex(e,Zn(n)|0,r,0),e|0}function Pd(e,n,r){return e=e|0,n=n|0,r=r|0,ux(e,Zn(n)|0,r,0),e|0}function zm(e,n,r){return e=e|0,n=n|0,r=r|0,V9(e,Zn(n)|0,r,0),e|0}function gf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],I9(e,n,s),h=o,e|0}function Md(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],vo(e,n,s),h=o,e|0}function Xr(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],a(e,n,s),h=o,e|0}function yi(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],n4(e,n,s),h=o,e|0}function j0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],b_(e,n,s),h=o,e|0}function Zu(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],L_(e,n,s),h=o,e|0}function _f(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Hp(e,n,s),h=o,e|0}function Io(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],e_(e,n,s),h=o,e|0}function _u(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Ip(e,n,s),h=o,e|0}function ec(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Ng(e,n,s),h=o,e|0}function Wm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],l0(e,n,s),h=o,e|0}function Fd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],hg(e,n,s),h=o,e|0}function yf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],sg(e,n,s),h=o,e|0}function tc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Kv(e,n,s),h=o,e|0}function Hm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],y1(e,n,s),h=o,e|0}function Ld(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],wv(e,n,s),h=o,e|0}function Rd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],fv(e,n,s),h=o,e|0}function zc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Gd(e,n,s),h=o,e|0}function Nd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Wc(e,n,s),h=o,e|0}function Wc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Hc(e,r,s,1),h=o}function Zn(e){return e=e|0,e|0}function Hc(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=Za()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Bd(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,bc(l,o)|0,o),h=s}function Za(){var e=0,n=0;if(c[7616]|0||(yu(9136),Bt(24,9136,Q|0)|0,n=7616,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9136)|0)){e=9136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));yu(9136)}return 9136}function Bd(e){return e=e|0,0}function bc(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=Za()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],n1(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(jd(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function ur(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0;d=h,h=h+32|0,q=d+24|0,P=d+20|0,y=d+16|0,T=d+12|0,k=d+8|0,_=d+4|0,we=d,t[P>>2]=n,t[y>>2]=r,t[T>>2]=o,t[k>>2]=s,t[_>>2]=l,l=e+28|0,t[we>>2]=t[l>>2],t[q>>2]=t[we>>2],e1(e+24|0,q,P,T,k,y,_)|0,t[l>>2]=t[t[l>>2]>>2],h=d}function e1(e,n,r,o,s,l,d){return e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,d=d|0,e=bm(n)|0,n=Tt(24)|0,t1(n+4|0,t[r>>2]|0,t[o>>2]|0,t[s>>2]|0,t[l>>2]|0,t[d>>2]|0),t[n>>2]=t[e>>2],t[e>>2]=n,n|0}function bm(e){return e=e|0,t[e>>2]|0}function t1(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=o,t[e+12>>2]=s,t[e+16>>2]=l}function Lt(e,n){return e=e|0,n=n|0,n|e|0}function n1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function jd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=Gm(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Ud(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],n1(l,o,r),t[y>>2]=(t[y>>2]|0)+12,Vm(e,_),Ym(_),h=k;return}}function Gm(e){return e=e|0,357913941}function Ud(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function Vm(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Ym(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function yu(e){e=e|0,Gc(e)}function r1(e){e=e|0,i1(e+24|0)}function Dn(e){return e=e|0,t[e>>2]|0}function i1(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Gc(e){e=e|0;var n=0;n=An()|0,Nn(e,2,3,n,cn()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function An(){return 9228}function cn(){return 1140}function Vc(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=Il(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=$m(n,o)|0,h=r,n|0}function Nn(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=o,t[e+12>>2]=s,t[e+16>>2]=l}function Il(e){return e=e|0,(t[(Za()|0)+24>>2]|0)+(e*12|0)|0}function $m(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;return s=h,h=h+48|0,o=s,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Bl[r&31](o,e),o=o1(o)|0,h=s,o|0}function o1(e){e=e|0;var n=0,r=0,o=0,s=0;return s=h,h=h+32|0,n=s+12|0,r=s,o=U0(u1()|0)|0,o?(s1(n,o),l1(r,n),qd(e,r),e=f1(n)|0):e=zd(e)|0,h=s,e|0}function u1(){var e=0;return c[7632]|0||(nc(9184),Bt(25,9184,Q|0)|0,e=7632,t[e>>2]=1,t[e+4>>2]=0),9184}function U0(e){return e=e|0,t[e+36>>2]|0}function s1(e,n){e=e|0,n=n|0,t[e>>2]=n,t[e+4>>2]=e,t[e+8>>2]=0}function l1(e,n){e=e|0,n=n|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=0}function qd(e,n){e=e|0,n=n|0,Ii(n,e,e+8|0,e+16|0,e+24|0,e+32|0,e+40|0)|0}function f1(e){return e=e|0,t[(t[e+4>>2]|0)+8>>2]|0}function zd(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0;y=h,h=h+16|0,r=y+4|0,o=y,s=Qo(8)|0,l=s,d=Tt(48)|0,_=d,n=_+48|0;do t[_>>2]=t[e>>2],_=_+4|0,e=e+4|0;while((_|0)<(n|0));return n=l+4|0,t[n>>2]=d,_=Tt(8)|0,d=t[n>>2]|0,t[o>>2]=0,t[r>>2]=t[o>>2],Wd(_,d,r),t[s>>2]=_,h=y,l|0}function Wd(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Tt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1092,t[r+12>>2]=n,t[e+4>>2]=r}function Km(e){e=e|0,da(e),Ve(e)}function Xm(e){e=e|0,e=t[e+12>>2]|0,e|0&&Ve(e)}function es(e){e=e|0,Ve(e)}function Ii(e,n,r,o,s,l,d){return e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,d=d|0,l=c1(t[e>>2]|0,n,r,o,s,l,d)|0,d=e+4|0,t[(t[d>>2]|0)+8>>2]=l,t[(t[d>>2]|0)+8>>2]|0}function c1(e,n,r,o,s,l,d){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,d=d|0;var _=0,y=0;return _=h,h=h+16|0,y=_,Zo(y),e=Oi(e)|0,d=Jm(e,+L[n>>3],+L[r>>3],+L[o>>3],+L[s>>3],+L[l>>3],+L[d>>3])|0,eu(y),h=_,d|0}function Jm(e,n,r,o,s,l,d){e=e|0,n=+n,r=+r,o=+o,s=+s,l=+l,d=+d;var _=0;return _=ko(a1()|0)|0,n=+Ko(n),r=+Ko(r),o=+Ko(o),s=+Ko(s),l=+Ko(l),xs(0,_|0,e|0,+n,+r,+o,+s,+l,+ +Ko(d))|0}function a1(){var e=0;return c[7624]|0||(Qm(9172),e=7624,t[e>>2]=1,t[e+4>>2]=0),9172}function Qm(e){e=e|0,Ao(e,Zm()|0,6)}function Zm(){return 1112}function nc(e){e=e|0,Ys(e)}function Hd(e){e=e|0,d1(e+24|0),bd(e+16|0)}function d1(e){e=e|0,tv(e)}function bd(e){e=e|0,ev(e)}function ev(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Ve(r);while((n|0)!=0);t[e>>2]=0}function tv(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Ve(r);while((n|0)!=0);t[e>>2]=0}function Ys(e){e=e|0;var n=0;t[e+16>>2]=0,t[e+20>>2]=0,n=e+24|0,t[n>>2]=0,t[e+28>>2]=n,t[e+36>>2]=0,c[e+40>>0]=0,c[e+41>>0]=0}function Gd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Vd(e,r,s,0),h=o}function Vd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=p1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=h1(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Yd(l,o)|0,o),h=s}function p1(){var e=0,n=0;if(c[7640]|0||(Xo(9232),Bt(26,9232,Q|0)|0,n=7640,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9232)|0)){e=9232,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Xo(9232)}return 9232}function h1(e){return e=e|0,0}function Yd(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=p1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],wf(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(m1(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function wf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function m1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=$d(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Kd(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],wf(l,o,r),t[y>>2]=(t[y>>2]|0)+12,Yc(e,_),Xd(_),h=k;return}}function $d(e){return e=e|0,357913941}function Kd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function Yc(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Xd(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Xo(e){e=e|0,Jd(e)}function Pl(e){e=e|0,nv(e+24|0)}function nv(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Jd(e){e=e|0;var n=0;n=An()|0,Nn(e,2,1,n,rv()|0,3),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function rv(){return 1144}function iv(e,n,r,o,s){e=e|0,n=n|0,r=+r,o=+o,s=s|0;var l=0,d=0,_=0,y=0;l=h,h=h+16|0,d=l+8|0,_=l,y=ov(e)|0,e=t[y+4>>2]|0,t[_>>2]=t[y>>2],t[_+4>>2]=e,t[d>>2]=t[_>>2],t[d+4>>2]=t[_+4>>2],uv(n,d,r,o,s),h=l}function ov(e){return e=e|0,(t[(p1()|0)+24>>2]|0)+(e*12|0)|0}function uv(e,n,r,o,s){e=e|0,n=n|0,r=+r,o=+o,s=s|0;var l=0,d=0,_=0,y=0,k=0;k=h,h=h+16|0,d=k+2|0,_=k+1|0,y=k,l=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(l=t[(t[e>>2]|0)+l>>2]|0),wu(d,r),r=+Du(d,r),wu(_,o),o=+Du(_,o),ts(y,s),y=ns(y,s)|0,iD[l&1](e,r,o,y),h=k}function wu(e,n){e=e|0,n=+n}function Du(e,n){return e=e|0,n=+n,+ +lv(n)}function ts(e,n){e=e|0,n=n|0}function ns(e,n){return e=e|0,n=n|0,sv(n)|0}function sv(e){return e=e|0,e|0}function lv(e){return e=+e,+e}function fv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Qd(e,r,s,1),h=o}function Qd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=$c()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Zd(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,cv(l,o)|0,o),h=s}function $c(){var e=0,n=0;if(c[7648]|0||(np(9268),Bt(27,9268,Q|0)|0,n=7648,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9268)|0)){e=9268,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));np(9268)}return 9268}function Zd(e){return e=e|0,0}function cv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=$c()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],ep(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(av(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function ep(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function av(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=tp(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,dv(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],ep(l,o,r),t[y>>2]=(t[y>>2]|0)+12,pv(e,_),hv(_),h=k;return}}function tp(e){return e=e|0,357913941}function dv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function pv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function hv(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function np(e){e=e|0,Po(e)}function mv(e){e=e|0,vv(e+24|0)}function vv(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Po(e){e=e|0;var n=0;n=An()|0,Nn(e,2,4,n,gv()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function gv(){return 1160}function _v(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=yv(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=rp(n,o)|0,h=r,n|0}function yv(e){return e=e|0,(t[($c()|0)+24>>2]|0)+(e*12|0)|0}function rp(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),ip(dc[r&31](e)|0)|0}function ip(e){return e=e|0,e&1|0}function wv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Dv(e,r,s,0),h=o}function Dv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=v1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=g1(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Ev(l,o)|0,o),h=s}function v1(){var e=0,n=0;if(c[7656]|0||(up(9304),Bt(28,9304,Q|0)|0,n=7656,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9304)|0)){e=9304,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));up(9304)}return 9304}function g1(e){return e=e|0,0}function Ev(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=v1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],op(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Sv(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function op(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Sv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=Cv(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Tv(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],op(l,o,r),t[y>>2]=(t[y>>2]|0)+12,xv(e,_),kv(_),h=k;return}}function Cv(e){return e=e|0,357913941}function Tv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function xv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function kv(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function up(e){e=e|0,Iv(e)}function Av(e){e=e|0,Ov(e+24|0)}function Ov(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Iv(e){e=e|0;var n=0;n=An()|0,Nn(e,2,5,n,Pv()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Pv(){return 1164}function Mv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=Fv(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Lv(n,s,r),h=o}function Fv(e){return e=e|0,(t[(v1()|0)+24>>2]|0)+(e*12|0)|0}function Lv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),$s(s,r),r=Ks(s,r)|0,Bl[o&31](e,r),Xs(s),h=l}function $s(e,n){e=e|0,n=n|0,Rv(e,n)}function Ks(e,n){return e=e|0,n=n|0,e|0}function Xs(e){e=e|0,Ju(e)}function Rv(e,n){e=e|0,n=n|0,_1(e,n)}function _1(e,n){e=e|0,n=n|0,t[e>>2]=n}function y1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],sp(e,r,s,0),h=o}function sp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=w1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Nv(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Bv(l,o)|0,o),h=s}function w1(){var e=0,n=0;if(c[7664]|0||(cp(9340),Bt(29,9340,Q|0)|0,n=7664,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9340)|0)){e=9340,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));cp(9340)}return 9340}function Nv(e){return e=e|0,0}function Bv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=w1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],lp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(jv(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function lp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function jv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=Uv(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,qv(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],lp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,zv(e,_),fp(_),h=k;return}}function Uv(e){return e=e|0,357913941}function qv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function zv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function fp(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function cp(e){e=e|0,Hv(e)}function Kc(e){e=e|0,Wv(e+24|0)}function Wv(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Hv(e){e=e|0;var n=0;n=An()|0,Nn(e,2,4,n,bv()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function bv(){return 1180}function Gv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=Vv(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],r=Yv(n,s,r)|0,h=o,r|0}function Vv(e){return e=e|0,(t[(w1()|0)+24>>2]|0)+(e*12|0)|0}function Yv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;return l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),Ml(s,r),s=Fl(s,r)|0,s=Xc(J4[o&15](e,s)|0)|0,h=l,s|0}function Ml(e,n){e=e|0,n=n|0}function Fl(e,n){return e=e|0,n=n|0,$v(n)|0}function Xc(e){return e=e|0,e|0}function $v(e){return e=e|0,e|0}function Kv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Xv(e,r,s,0),h=o}function Xv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=D1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Jv(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Qv(l,o)|0,o),h=s}function D1(){var e=0,n=0;if(c[7672]|0||(hp(9376),Bt(30,9376,Q|0)|0,n=7672,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9376)|0)){e=9376,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));hp(9376)}return 9376}function Jv(e){return e=e|0,0}function Qv(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=D1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],ap(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(dp(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function ap(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function dp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=pp(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Zv(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],ap(l,o,r),t[y>>2]=(t[y>>2]|0)+12,eg(e,_),tg(_),h=k;return}}function pp(e){return e=e|0,357913941}function Zv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function eg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function tg(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function hp(e){e=e|0,rg(e)}function Jc(e){e=e|0,ng(e+24|0)}function ng(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function rg(e){e=e|0;var n=0;n=An()|0,Nn(e,2,5,n,mp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function mp(){return 1196}function ig(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=og(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=ug(n,o)|0,h=r,n|0}function og(e){return e=e|0,(t[(D1()|0)+24>>2]|0)+(e*12|0)|0}function ug(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Xc(dc[r&31](e)|0)|0}function sg(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],lg(e,r,s,1),h=o}function lg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=E1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=fg(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,cg(l,o)|0,o),h=s}function E1(){var e=0,n=0;if(c[7680]|0||(C1(9412),Bt(31,9412,Q|0)|0,n=7680,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9412)|0)){e=9412,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));C1(9412)}return 9412}function fg(e){return e=e|0,0}function cg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=E1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],rc(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(ag(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function rc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function ag(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=vp(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,gp(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],rc(l,o,r),t[y>>2]=(t[y>>2]|0)+12,S1(e,_),_p(_),h=k;return}}function vp(e){return e=e|0,357913941}function gp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function S1(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function _p(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function C1(e){e=e|0,dg(e)}function yp(e){e=e|0,wp(e+24|0)}function wp(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function dg(e){e=e|0;var n=0;n=An()|0,Nn(e,2,6,n,Dp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Dp(){return 1200}function pg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=Qc(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=Zc(n,o)|0,h=r,n|0}function Qc(e){return e=e|0,(t[(E1()|0)+24>>2]|0)+(e*12|0)|0}function Zc(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),ea(dc[r&31](e)|0)|0}function ea(e){return e=e|0,e|0}function hg(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],T1(e,r,s,0),h=o}function T1(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=ta()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=mg(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,vg(l,o)|0,o),h=s}function ta(){var e=0,n=0;if(c[7688]|0||(Sp(9448),Bt(32,9448,Q|0)|0,n=7688,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9448)|0)){e=9448,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Sp(9448)}return 9448}function mg(e){return e=e|0,0}function vg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=ta()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Ep(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(gg(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Ep(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function gg(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=_g(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,yg(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Ep(l,o,r),t[y>>2]=(t[y>>2]|0)+12,wg(e,_),Dg(_),h=k;return}}function _g(e){return e=e|0,357913941}function yg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function wg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Dg(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Sp(e){e=e|0,Cg(e)}function Eg(e){e=e|0,Sg(e+24|0)}function Sg(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Cg(e){e=e|0;var n=0;n=An()|0,Nn(e,2,6,n,Mo()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Mo(){return 1204}function Tg(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=xg(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Ll(n,s,r),h=o}function xg(e){return e=e|0,(t[(ta()|0)+24>>2]|0)+(e*12|0)|0}function Ll(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),On(s,r),s=x1(s,r)|0,Bl[o&31](e,s),h=l}function On(e,n){e=e|0,n=n|0}function x1(e,n){return e=e|0,n=n|0,Vi(n)|0}function Vi(e){return e=e|0,e|0}function l0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],kg(e,r,s,0),h=o}function kg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=Eu()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Ag(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Og(l,o)|0,o),h=s}function Eu(){var e=0,n=0;if(c[7696]|0||(A1(9484),Bt(33,9484,Q|0)|0,n=7696,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9484)|0)){e=9484,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));A1(9484)}return 9484}function Ag(e){return e=e|0,0}function Og(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=Eu()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Cp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Ig(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Cp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Ig(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=Pg(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,k1(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Cp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,Mg(e,_),rs(_),h=k;return}}function Pg(e){return e=e|0,357913941}function k1(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function Mg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function rs(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function A1(e){e=e|0,n0(e)}function na(e){e=e|0,Jr(e+24|0)}function Jr(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function n0(e){e=e|0;var n=0;n=An()|0,Nn(e,2,1,n,Tp()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Tp(){return 1212}function Fg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+16|0,l=s+8|0,d=s,_=Lg(e)|0,e=t[_+4>>2]|0,t[d>>2]=t[_>>2],t[d+4>>2]=e,t[l>>2]=t[d>>2],t[l+4>>2]=t[d+4>>2],Rg(n,l,r,o),h=s}function Lg(e){return e=e|0,(t[(Eu()|0)+24>>2]|0)+(e*12|0)|0}function Rg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;_=h,h=h+16|0,l=_+1|0,d=_,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),On(l,r),l=x1(l,r)|0,Ml(d,o),d=Fl(d,o)|0,X1[s&15](e,l,d),h=_}function Ng(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Bg(e,r,s,1),h=o}function Bg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=O1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=xp(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,ic(l,o)|0,o),h=s}function O1(){var e=0,n=0;if(c[7704]|0||(Ap(9520),Bt(34,9520,Q|0)|0,n=7704,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9520)|0)){e=9520,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ap(9520)}return 9520}function xp(e){return e=e|0,0}function ic(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=O1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],ra(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(jg(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function ra(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function jg(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=kp(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,ia(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],ra(l,o,r),t[y>>2]=(t[y>>2]|0)+12,mo(e,_),Df(_),h=k;return}}function kp(e){return e=e|0,357913941}function ia(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function mo(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Df(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Ap(e){e=e|0,zg(e)}function Ug(e){e=e|0,qg(e+24|0)}function qg(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function zg(e){e=e|0;var n=0;n=An()|0,Nn(e,2,1,n,Wg()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Wg(){return 1224}function Op(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;return s=h,h=h+16|0,l=s+8|0,d=s,_=is(e)|0,e=t[_+4>>2]|0,t[d>>2]=t[_>>2],t[d+4>>2]=e,t[l>>2]=t[d>>2],t[l+4>>2]=t[d+4>>2],o=+jn(n,l,r),h=s,+o}function is(e){return e=e|0,(t[(O1()|0)+24>>2]|0)+(e*12|0)|0}function jn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),ts(s,r),s=ns(s,r)|0,d=+Ol(+uD[o&7](e,s)),h=l,+d}function Ip(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Fo(e,r,s,1),h=o}function Fo(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=oa()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=Hg(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,yr(l,o)|0,o),h=s}function oa(){var e=0,n=0;if(c[7712]|0||(Fp(9556),Bt(35,9556,Q|0)|0,n=7712,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9556)|0)){e=9556,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Fp(9556)}return 9556}function Hg(e){return e=e|0,0}function yr(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=oa()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Pp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Mp(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Pp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Mp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=ua(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,bg(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Pp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,Gg(e,_),Vg(_),h=k;return}}function ua(e){return e=e|0,357913941}function bg(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function Gg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Vg(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Fp(e){e=e|0,Kg(e)}function Yg(e){e=e|0,$g(e+24|0)}function $g(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Kg(e){e=e|0;var n=0;n=An()|0,Nn(e,2,5,n,Xg()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Xg(){return 1232}function Jg(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=Qg(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],r=+Zg(n,s),h=o,+r}function Qg(e){return e=e|0,(t[(oa()|0)+24>>2]|0)+(e*12|0)|0}function Zg(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),+ +Ol(+oD[r&15](e))}function e_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],t_(e,r,s,1),h=o}function t_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=oc()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=n_(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,I1(l,o)|0,o),h=s}function oc(){var e=0,n=0;if(c[7720]|0||(Rp(9592),Bt(36,9592,Q|0)|0,n=7720,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9592)|0)){e=9592,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Rp(9592)}return 9592}function n_(e){return e=e|0,0}function I1(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=oc()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Lp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(r_(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Lp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function r_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=i_(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,q0(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Lp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,Yi(e,_),o_(_),h=k;return}}function i_(e){return e=e|0,357913941}function q0(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function Yi(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function o_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Rp(e){e=e|0,s_(e)}function u_(e){e=e|0,Np(e+24|0)}function Np(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function s_(e){e=e|0;var n=0;n=An()|0,Nn(e,2,7,n,l_()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function l_(){return 1276}function f_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=Bp(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=c_(n,o)|0,h=r,n|0}function Bp(e){return e=e|0,(t[(oc()|0)+24>>2]|0)+(e*12|0)|0}function c_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;return s=h,h=h+16|0,o=s,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Bl[r&31](o,e),o=jp(o)|0,h=s,o|0}function jp(e){e=e|0;var n=0,r=0,o=0,s=0;return s=h,h=h+32|0,n=s+12|0,r=s,o=U0(Up()|0)|0,o?(s1(n,o),l1(r,n),qp(e,r),e=f1(n)|0):e=zp(e)|0,h=s,e|0}function Up(){var e=0;return c[7736]|0||(Wp(9640),Bt(25,9640,Q|0)|0,e=7736,t[e>>2]=1,t[e+4>>2]=0),9640}function qp(e,n){e=e|0,n=n|0,Ef(n,e,e+8|0)|0}function zp(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0;return r=h,h=h+16|0,s=r+4|0,d=r,o=Qo(8)|0,n=o,_=Tt(16)|0,t[_>>2]=t[e>>2],t[_+4>>2]=t[e+4>>2],t[_+8>>2]=t[e+8>>2],t[_+12>>2]=t[e+12>>2],l=n+4|0,t[l>>2]=_,e=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],P1(e,l,s),t[o>>2]=e,h=r,n|0}function P1(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Tt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1244,t[r+12>>2]=n,t[e+4>>2]=r}function a_(e){e=e|0,da(e),Ve(e)}function d_(e){e=e|0,e=t[e+12>>2]|0,e|0&&Ve(e)}function p_(e){e=e|0,Ve(e)}function Ef(e,n,r){return e=e|0,n=n|0,r=r|0,n=h_(t[e>>2]|0,n,r)|0,r=e+4|0,t[(t[r>>2]|0)+8>>2]=n,t[(t[r>>2]|0)+8>>2]|0}function h_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;return o=h,h=h+16|0,s=o,Zo(s),e=Oi(e)|0,r=m_(e,t[n>>2]|0,+L[r>>3])|0,eu(s),h=o,r|0}function m_(e,n,r){e=e|0,n=n|0,r=+r;var o=0;return o=ko(v_()|0)|0,n=jc(n)|0,dl(0,o|0,e|0,n|0,+ +Ko(r))|0}function v_(){var e=0;return c[7728]|0||(g_(9628),e=7728,t[e>>2]=1,t[e+4>>2]=0),9628}function g_(e){e=e|0,Ao(e,__()|0,2)}function __(){return 1264}function Wp(e){e=e|0,Ys(e)}function Hp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],y_(e,r,s,1),h=o}function y_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=M1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=w_(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,D_(l,o)|0,o),h=s}function M1(){var e=0,n=0;if(c[7744]|0||(Gp(9684),Bt(37,9684,Q|0)|0,n=7744,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9684)|0)){e=9684,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Gp(9684)}return 9684}function w_(e){return e=e|0,0}function D_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=M1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],bp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(E_(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function bp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function E_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=S_(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,C_(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],bp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,T_(e,_),x_(_),h=k;return}}function S_(e){return e=e|0,357913941}function C_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function T_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function x_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Gp(e){e=e|0,O_(e)}function k_(e){e=e|0,A_(e+24|0)}function A_(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function O_(e){e=e|0;var n=0;n=An()|0,Nn(e,2,5,n,I_()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function I_(){return 1280}function P_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=M_(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],r=F_(n,s,r)|0,h=o,r|0}function M_(e){return e=e|0,(t[(M1()|0)+24>>2]|0)+(e*12|0)|0}function F_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return d=h,h=h+32|0,s=d,l=d+16|0,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),ts(l,r),l=ns(l,r)|0,X1[o&15](s,e,l),l=jp(s)|0,h=d,l|0}function L_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],R_(e,r,s,1),h=o}function R_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=F1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=N_(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,B_(l,o)|0,o),h=s}function F1(){var e=0,n=0;if(c[7752]|0||(Kp(9720),Bt(38,9720,Q|0)|0,n=7752,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9720)|0)){e=9720,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Kp(9720)}return 9720}function N_(e){return e=e|0,0}function B_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=F1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Vp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(j_(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Vp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function j_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=L1(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Yp(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Vp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,$p(e,_),U_(_),h=k;return}}function L1(e){return e=e|0,357913941}function Yp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function $p(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function U_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Kp(e){e=e|0,z_(e)}function q_(e){e=e|0,R1(e+24|0)}function R1(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function z_(e){e=e|0;var n=0;n=An()|0,Nn(e,2,8,n,W_()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function W_(){return 1288}function H_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;return r=h,h=h+16|0,o=r+8|0,s=r,l=$i(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],n=N1(n,o)|0,h=r,n|0}function $i(e){return e=e|0,(t[(F1()|0)+24>>2]|0)+(e*12|0)|0}function N1(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Dd(dc[r&31](e)|0)|0}function b_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],G_(e,r,s,0),h=o}function G_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=B1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=V_(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,j1(l,o)|0,o),h=s}function B1(){var e=0,n=0;if(c[7760]|0||(q1(9756),Bt(39,9756,Q|0)|0,n=7760,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9756)|0)){e=9756,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));q1(9756)}return 9756}function V_(e){return e=e|0,0}function j1(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=B1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Xp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(U1(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Xp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function U1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=Y_(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,$_(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Xp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,K_(e,_),X_(_),h=k;return}}function Y_(e){return e=e|0,357913941}function $_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function K_(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function X_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function q1(e){e=e|0,Z_(e)}function J_(e){e=e|0,Q_(e+24|0)}function Q_(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function Z_(e){e=e|0;var n=0;n=An()|0,Nn(e,2,8,n,z1()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function z1(){return 1292}function W1(e,n,r){e=e|0,n=n|0,r=+r;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=e4(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],t4(n,s,r),h=o}function e4(e){return e=e|0,(t[(B1()|0)+24>>2]|0)+(e*12|0)|0}function t4(e,n,r){e=e|0,n=n|0,r=+r;var o=0,s=0,l=0;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),wu(s,r),r=+Du(s,r),nD[o&31](e,r),h=l}function n4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],r4(e,r,s,0),h=o}function r4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=H1()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=i4(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,o4(l,o)|0,o),h=s}function H1(){var e=0,n=0;if(c[7768]|0||(Qp(9792),Bt(40,9792,Q|0)|0,n=7768,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9792)|0)){e=9792,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Qp(9792)}return 9792}function i4(e){return e=e|0,0}function o4(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=H1()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Jp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(u4(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Jp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function u4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=s4(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,l4(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Jp(l,o,r),t[y>>2]=(t[y>>2]|0)+12,f4(e,_),c4(_),h=k;return}}function s4(e){return e=e|0,357913941}function l4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function f4(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function c4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Qp(e){e=e|0,p4(e)}function a4(e){e=e|0,d4(e+24|0)}function d4(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function p4(e){e=e|0;var n=0;n=An()|0,Nn(e,2,1,n,h4()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function h4(){return 1300}function m4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o;var s=0,l=0,d=0,_=0;s=h,h=h+16|0,l=s+8|0,d=s,_=v4(e)|0,e=t[_+4>>2]|0,t[d>>2]=t[_>>2],t[d+4>>2]=e,t[l>>2]=t[d>>2],t[l+4>>2]=t[d+4>>2],g4(n,l,r,o),h=s}function v4(e){return e=e|0,(t[(H1()|0)+24>>2]|0)+(e*12|0)|0}function g4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o;var s=0,l=0,d=0,_=0;_=h,h=h+16|0,l=_+1|0,d=_,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),ts(l,r),l=ns(l,r)|0,wu(d,o),o=+Du(d,o),cD[s&15](e,l,o),h=_}function a(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],p(e,r,s,0),h=o}function p(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=E()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=I(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,B(l,o)|0,o),h=s}function E(){var e=0,n=0;if(c[7776]|0||(nt(9828),Bt(41,9828,Q|0)|0,n=7776,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9828)|0)){e=9828,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));nt(9828)}return 9828}function I(e){return e=e|0,0}function B(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=E()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],G(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(te(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function G(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function te(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=se(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,Ee(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],G(l,o,r),t[y>>2]=(t[y>>2]|0)+12,$e(e,_),Ke(_),h=k;return}}function se(e){return e=e|0,357913941}function Ee(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function $e(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Ke(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function nt(e){e=e|0,an(e)}function Ct(e){e=e|0,Gt(e+24|0)}function Gt(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function an(e){e=e|0;var n=0;n=An()|0,Nn(e,2,7,n,qn()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function qn(){return 1312}function dn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=Yn(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],er(n,s,r),h=o}function Yn(e){return e=e|0,(t[(E()|0)+24>>2]|0)+(e*12|0)|0}function er(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),ts(s,r),s=ns(s,r)|0,Bl[o&31](e,s),h=l}function vo(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Pi(e,r,s,0),h=o}function Pi(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=Mi()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=f0(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,Jo(l,o)|0,o),h=s}function Mi(){var e=0,n=0;if(c[7784]|0||(kw(9864),Bt(42,9864,Q|0)|0,n=7784,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9864)|0)){e=9864,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));kw(9864)}return 9864}function f0(e){return e=e|0,0}function Jo(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=Mi()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Su(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Zp(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Su(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Zp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=v9(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,g9(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Su(l,o,r),t[y>>2]=(t[y>>2]|0)+12,_9(e,_),y9(_),h=k;return}}function v9(e){return e=e|0,357913941}function g9(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function _9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function y9(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function kw(e){e=e|0,E9(e)}function w9(e){e=e|0,D9(e+24|0)}function D9(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function E9(e){e=e|0;var n=0;n=An()|0,Nn(e,2,8,n,S9()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function S9(){return 1320}function C9(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=T9(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],x9(n,s,r),h=o}function T9(e){return e=e|0,(t[(Mi()|0)+24>>2]|0)+(e*12|0)|0}function x9(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),k9(s,r),s=A9(s,r)|0,Bl[o&31](e,s),h=l}function k9(e,n){e=e|0,n=n|0}function A9(e,n){return e=e|0,n=n|0,O9(n)|0}function O9(e){return e=e|0,e|0}function I9(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],P9(e,r,s,0),h=o}function P9(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=_4()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=M9(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,F9(l,o)|0,o),h=s}function _4(){var e=0,n=0;if(c[7792]|0||(Ow(9900),Bt(43,9900,Q|0)|0,n=7792,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9900)|0)){e=9900,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ow(9900)}return 9900}function M9(e){return e=e|0,0}function F9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=_4()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Aw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(L9(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Aw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function L9(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=R9(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,N9(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Aw(l,o,r),t[y>>2]=(t[y>>2]|0)+12,B9(e,_),j9(_),h=k;return}}function R9(e){return e=e|0,357913941}function N9(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function B9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function j9(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Ow(e){e=e|0,z9(e)}function U9(e){e=e|0,q9(e+24|0)}function q9(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function z9(e){e=e|0;var n=0;n=An()|0,Nn(e,2,22,n,W9()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function W9(){return 1344}function H9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0;r=h,h=h+16|0,o=r+8|0,s=r,l=b9(e)|0,e=t[l+4>>2]|0,t[s>>2]=t[l>>2],t[s+4>>2]=e,t[o>>2]=t[s>>2],t[o+4>>2]=t[s+4>>2],G9(n,o),h=r}function b9(e){return e=e|0,(t[(_4()|0)+24>>2]|0)+(e*12|0)|0}function G9(e,n){e=e|0,n=n|0;var r=0;r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Nl[r&127](e)}function V9(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=y4()|0,e=Y9(r)|0,ur(l,n,s,e,$9(r,o)|0,o)}function y4(){var e=0,n=0;if(c[7800]|0||(Pw(9936),Bt(44,9936,Q|0)|0,n=7800,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9936)|0)){e=9936,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Pw(9936)}return 9936}function Y9(e){return e=e|0,e|0}function $9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=y4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(Iw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(K9(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function Iw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function K9(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=X9(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,J9(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,Iw(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,Q9(e,s),Z9(s),h=_;return}}function X9(e){return e=e|0,536870911}function J9(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function Q9(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Z9(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function Pw(e){e=e|0,nx(e)}function ex(e){e=e|0,tx(e+24|0)}function tx(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function nx(e){e=e|0;var n=0;n=An()|0,Nn(e,1,23,n,Mo()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function rx(e,n){e=e|0,n=n|0,ox(t[(ix(e)|0)>>2]|0,n)}function ix(e){return e=e|0,(t[(y4()|0)+24>>2]|0)+(e<<3)|0}function ox(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,On(o,n),n=x1(o,n)|0,Nl[e&127](n),h=r}function ux(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=w4()|0,e=sx(r)|0,ur(l,n,s,e,lx(r,o)|0,o)}function w4(){var e=0,n=0;if(c[7808]|0||(Fw(9972),Bt(45,9972,Q|0)|0,n=7808,t[n>>2]=1,t[n+4>>2]=0),!(Dn(9972)|0)){e=9972,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Fw(9972)}return 9972}function sx(e){return e=e|0,e|0}function lx(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=w4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(Mw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(fx(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function Mw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function fx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=cx(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,ax(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,Mw(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,dx(e,s),px(s),h=_;return}}function cx(e){return e=e|0,536870911}function ax(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function dx(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function px(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function Fw(e){e=e|0,vx(e)}function hx(e){e=e|0,mx(e+24|0)}function mx(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function vx(e){e=e|0;var n=0;n=An()|0,Nn(e,1,9,n,gx()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function gx(){return 1348}function _x(e,n){return e=e|0,n=n|0,wx(t[(yx(e)|0)>>2]|0,n)|0}function yx(e){return e=e|0,(t[(w4()|0)+24>>2]|0)+(e<<3)|0}function wx(e,n){e=e|0,n=n|0;var r=0,o=0;return r=h,h=h+16|0,o=r,Lw(o,n),n=Rw(o,n)|0,n=Xc(dc[e&31](n)|0)|0,h=r,n|0}function Lw(e,n){e=e|0,n=n|0}function Rw(e,n){return e=e|0,n=n|0,Dx(n)|0}function Dx(e){return e=e|0,e|0}function Ex(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=D4()|0,e=Sx(r)|0,ur(l,n,s,e,Cx(r,o)|0,o)}function D4(){var e=0,n=0;if(c[7816]|0||(Bw(10008),Bt(46,10008,Q|0)|0,n=7816,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10008)|0)){e=10008,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Bw(10008)}return 10008}function Sx(e){return e=e|0,e|0}function Cx(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=D4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(Nw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Tx(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function Nw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Tx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=xx(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,kx(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,Nw(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,Ax(e,s),Ox(s),h=_;return}}function xx(e){return e=e|0,536870911}function kx(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function Ax(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function Ox(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function Bw(e){e=e|0,Mx(e)}function Ix(e){e=e|0,Px(e+24|0)}function Px(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function Mx(e){e=e|0;var n=0;n=An()|0,Nn(e,1,15,n,mp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Fx(e){return e=e|0,Rx(t[(Lx(e)|0)>>2]|0)|0}function Lx(e){return e=e|0,(t[(D4()|0)+24>>2]|0)+(e<<3)|0}function Rx(e){return e=e|0,Xc(ph[e&7]()|0)|0}function Nx(){var e=0;return c[7832]|0||(bx(10052),Bt(25,10052,Q|0)|0,e=7832,t[e>>2]=1,t[e+4>>2]=0),10052}function Bx(e,n){e=e|0,n=n|0,t[e>>2]=jx()|0,t[e+4>>2]=Ux()|0,t[e+12>>2]=n,t[e+8>>2]=qx()|0,t[e+32>>2]=2}function jx(){return 11709}function Ux(){return 1188}function qx(){return eh()|0}function zx(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(Wx(r),Ve(r)):n|0&&(mu(n),Ve(n))}function Sf(e,n){return e=e|0,n=n|0,n&e|0}function Wx(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function eh(){var e=0;return c[7824]|0||(t[2511]=Hx()|0,t[2512]=0,e=7824,t[e>>2]=1,t[e+4>>2]=0),10044}function Hx(){return 0}function bx(e){e=e|0,Ys(e)}function Gx(e){e=e|0;var n=0,r=0,o=0,s=0,l=0;n=h,h=h+32|0,r=n+24|0,l=n+16|0,s=n+8|0,o=n,Vx(e,4827),Yx(e,4834,3)|0,$x(e,3682,47)|0,t[l>>2]=9,t[l+4>>2]=0,t[r>>2]=t[l>>2],t[r+4>>2]=t[l+4>>2],Kx(e,4841,r)|0,t[s>>2]=1,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],Xx(e,4871,r)|0,t[o>>2]=10,t[o+4>>2]=0,t[r>>2]=t[o>>2],t[r+4>>2]=t[o+4>>2],Jx(e,4891,r)|0,h=n}function Vx(e,n){e=e|0,n=n|0;var r=0;r=Ok()|0,t[e>>2]=r,Ik(r,n),Cf(t[e>>2]|0)}function Yx(e,n,r){return e=e|0,n=n|0,r=r|0,pk(e,Zn(n)|0,r,0),e|0}function $x(e,n,r){return e=e|0,n=n|0,r=r|0,Q7(e,Zn(n)|0,r,0),e|0}function Kx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],F7(e,n,s),h=o,e|0}function Xx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],h7(e,n,s),h=o,e|0}function Jx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=t[r+4>>2]|0,t[l>>2]=t[r>>2],t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Qx(e,n,s),h=o,e|0}function Qx(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],Zx(e,r,s,1),h=o}function Zx(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=E4()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=e7(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,t7(l,o)|0,o),h=s}function E4(){var e=0,n=0;if(c[7840]|0||(Uw(10100),Bt(48,10100,Q|0)|0,n=7840,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10100)|0)){e=10100,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Uw(10100)}return 10100}function e7(e){return e=e|0,0}function t7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=E4()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],jw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(n7(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function jw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function n7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=r7(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,i7(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],jw(l,o,r),t[y>>2]=(t[y>>2]|0)+12,o7(e,_),u7(_),h=k;return}}function r7(e){return e=e|0,357913941}function i7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function o7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function u7(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Uw(e){e=e|0,f7(e)}function s7(e){e=e|0,l7(e+24|0)}function l7(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function f7(e){e=e|0;var n=0;n=An()|0,Nn(e,2,6,n,c7()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function c7(){return 1364}function a7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;return o=h,h=h+16|0,s=o+8|0,l=o,d=d7(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],r=p7(n,s,r)|0,h=o,r|0}function d7(e){return e=e|0,(t[(E4()|0)+24>>2]|0)+(e*12|0)|0}function p7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;return l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),ts(s,r),s=ns(s,r)|0,s=ip(J4[o&15](e,s)|0)|0,h=l,s|0}function h7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],m7(e,r,s,0),h=o}function m7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=S4()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=v7(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,g7(l,o)|0,o),h=s}function S4(){var e=0,n=0;if(c[7848]|0||(zw(10136),Bt(49,10136,Q|0)|0,n=7848,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10136)|0)){e=10136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));zw(10136)}return 10136}function v7(e){return e=e|0,0}function g7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=S4()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],qw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(_7(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function qw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function _7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=y7(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,w7(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],qw(l,o,r),t[y>>2]=(t[y>>2]|0)+12,D7(e,_),E7(_),h=k;return}}function y7(e){return e=e|0,357913941}function w7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function D7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function E7(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function zw(e){e=e|0,T7(e)}function S7(e){e=e|0,C7(e+24|0)}function C7(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function T7(e){e=e|0;var n=0;n=An()|0,Nn(e,2,9,n,x7()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function x7(){return 1372}function k7(e,n,r){e=e|0,n=n|0,r=+r;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,s=o+8|0,l=o,d=A7(e)|0,e=t[d+4>>2]|0,t[l>>2]=t[d>>2],t[l+4>>2]=e,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],O7(n,s,r),h=o}function A7(e){return e=e|0,(t[(S4()|0)+24>>2]|0)+(e*12|0)|0}function O7(e,n,r){e=e|0,n=n|0,r=+r;var o=0,s=0,l=0,d=tt;l=h,h=h+16|0,s=l,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),I7(s,r),d=w(P7(s,r)),tD[o&1](e,d),h=l}function I7(e,n){e=e|0,n=+n}function P7(e,n){return e=e|0,n=+n,w(M7(n))}function M7(e){return e=+e,w(e)}function F7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,s=o+8|0,l=o,_=t[r>>2]|0,d=t[r+4>>2]|0,r=Zn(n)|0,t[l>>2]=_,t[l+4>>2]=d,t[s>>2]=t[l>>2],t[s+4>>2]=t[l+4>>2],L7(e,r,s,0),h=o}function L7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0,y=0,k=0,T=0;s=h,h=h+32|0,l=s+16|0,T=s+8|0,_=s,k=t[r>>2]|0,y=t[r+4>>2]|0,d=t[e>>2]|0,e=C4()|0,t[T>>2]=k,t[T+4>>2]=y,t[l>>2]=t[T>>2],t[l+4>>2]=t[T+4>>2],r=R7(l)|0,t[_>>2]=k,t[_+4>>2]=y,t[l>>2]=t[_>>2],t[l+4>>2]=t[_+4>>2],ur(d,n,e,r,N7(l,o)|0,o),h=s}function C4(){var e=0,n=0;if(c[7856]|0||(Hw(10172),Bt(50,10172,Q|0)|0,n=7856,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10172)|0)){e=10172,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Hw(10172)}return 10172}function R7(e){return e=e|0,0}function N7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0;return T=h,h=h+32|0,s=T+24|0,d=T+16|0,_=T,y=T+8|0,l=t[e>>2]|0,o=t[e+4>>2]|0,t[_>>2]=l,t[_+4>>2]=o,P=C4()|0,k=P+24|0,e=Lt(n,4)|0,t[y>>2]=e,n=P+28|0,r=t[n>>2]|0,r>>>0<(t[P+32>>2]|0)>>>0?(t[d>>2]=l,t[d+4>>2]=o,t[s>>2]=t[d>>2],t[s+4>>2]=t[d+4>>2],Ww(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(B7(k,_,y),e=t[n>>2]|0),h=T,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Ww(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function B7(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;if(k=h,h=h+48|0,o=k+32|0,d=k+24|0,_=k,y=e+4|0,s=(((t[y>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,l=j7(e)|0,l>>>0>>0)$n(e);else{T=t[e>>2]|0,q=((t[e+8>>2]|0)-T|0)/12|0,P=q<<1,U7(_,q>>>0>>1>>>0?P>>>0>>0?s:P:l,((t[y>>2]|0)-T|0)/12|0,e+8|0),y=_+8|0,l=t[y>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[d>>2]=t[n>>2],t[d+4>>2]=s,t[o>>2]=t[d>>2],t[o+4>>2]=t[d+4>>2],Ww(l,o,r),t[y>>2]=(t[y>>2]|0)+12,q7(e,_),z7(_),h=k;return}}function j7(e){return e=e|0,357913941}function U7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)_n();else{s=Tt(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n*12|0)}function q7(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function z7(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Ve(e)}function Hw(e){e=e|0,b7(e)}function W7(e){e=e|0,H7(e+24|0)}function H7(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),Ve(r))}function b7(e){e=e|0;var n=0;n=An()|0,Nn(e,2,3,n,G7()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function G7(){return 1380}function V7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+16|0,l=s+8|0,d=s,_=Y7(e)|0,e=t[_+4>>2]|0,t[d>>2]=t[_>>2],t[d+4>>2]=e,t[l>>2]=t[d>>2],t[l+4>>2]=t[d+4>>2],$7(n,l,r,o),h=s}function Y7(e){return e=e|0,(t[(C4()|0)+24>>2]|0)+(e*12|0)|0}function $7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;_=h,h=h+16|0,l=_+1|0,d=_,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),ts(l,r),l=ns(l,r)|0,K7(d,o),d=X7(d,o)|0,X1[s&15](e,l,d),h=_}function K7(e,n){e=e|0,n=n|0}function X7(e,n){return e=e|0,n=n|0,J7(n)|0}function J7(e){return e=e|0,(e|0)!=0|0}function Q7(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=T4()|0,e=Z7(r)|0,ur(l,n,s,e,ek(r,o)|0,o)}function T4(){var e=0,n=0;if(c[7864]|0||(Gw(10208),Bt(51,10208,Q|0)|0,n=7864,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10208)|0)){e=10208,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Gw(10208)}return 10208}function Z7(e){return e=e|0,e|0}function ek(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=T4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(bw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(tk(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function bw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function tk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=nk(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,rk(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,bw(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,ik(e,s),ok(s),h=_;return}}function nk(e){return e=e|0,536870911}function rk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function ik(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function ok(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function Gw(e){e=e|0,lk(e)}function uk(e){e=e|0,sk(e+24|0)}function sk(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function lk(e){e=e|0;var n=0;n=An()|0,Nn(e,1,24,n,fk()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function fk(){return 1392}function ck(e,n){e=e|0,n=n|0,dk(t[(ak(e)|0)>>2]|0,n)}function ak(e){return e=e|0,(t[(T4()|0)+24>>2]|0)+(e<<3)|0}function dk(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,Lw(o,n),n=Rw(o,n)|0,Nl[e&127](n),h=r}function pk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=x4()|0,e=hk(r)|0,ur(l,n,s,e,mk(r,o)|0,o)}function x4(){var e=0,n=0;if(c[7872]|0||(Yw(10244),Bt(52,10244,Q|0)|0,n=7872,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10244)|0)){e=10244,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Yw(10244)}return 10244}function hk(e){return e=e|0,e|0}function mk(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=x4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(Vw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(vk(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function Vw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function vk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=gk(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,_k(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,Vw(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,yk(e,s),wk(s),h=_;return}}function gk(e){return e=e|0,536870911}function _k(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function yk(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function wk(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function Yw(e){e=e|0,Sk(e)}function Dk(e){e=e|0,Ek(e+24|0)}function Ek(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function Sk(e){e=e|0;var n=0;n=An()|0,Nn(e,1,16,n,Ck()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Ck(){return 1400}function Tk(e){return e=e|0,kk(t[(xk(e)|0)>>2]|0)|0}function xk(e){return e=e|0,(t[(x4()|0)+24>>2]|0)+(e<<3)|0}function kk(e){return e=e|0,Ak(ph[e&7]()|0)|0}function Ak(e){return e=e|0,e|0}function Ok(){var e=0;return c[7880]|0||(Nk(10280),Bt(25,10280,Q|0)|0,e=7880,t[e>>2]=1,t[e+4>>2]=0),10280}function Ik(e,n){e=e|0,n=n|0,t[e>>2]=Pk()|0,t[e+4>>2]=Mk()|0,t[e+12>>2]=n,t[e+8>>2]=Fk()|0,t[e+32>>2]=4}function Pk(){return 11711}function Mk(){return 1356}function Fk(){return eh()|0}function Lk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(Rk(r),Ve(r)):n|0&&(Gi(n),Ve(n))}function Rk(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function Nk(e){e=e|0,Ys(e)}function Bk(e){e=e|0,jk(e,4920),Uk(e)|0,qk(e)|0}function jk(e,n){e=e|0,n=n|0;var r=0;r=Up()|0,t[e>>2]=r,sA(r,n),Cf(t[e>>2]|0)}function Uk(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,Jk()|0),e|0}function qk(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,zk()|0),e|0}function zk(){var e=0;return c[7888]|0||($w(10328),Bt(53,10328,Q|0)|0,e=7888,t[e>>2]=1,t[e+4>>2]=0),Dn(10328)|0||$w(10328),10328}function uc(e,n){e=e|0,n=n|0,ur(e,0,n,0,0,0)}function $w(e){e=e|0,bk(e),sc(e,10)}function Wk(e){e=e|0,Hk(e+24|0)}function Hk(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function bk(e){e=e|0;var n=0;n=An()|0,Nn(e,5,1,n,$k()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Gk(e,n,r){e=e|0,n=n|0,r=+r,Vk(e,n,r)}function sc(e,n){e=e|0,n=n|0,t[e+20>>2]=n}function Vk(e,n,r){e=e|0,n=n|0,r=+r;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+16|0,l=o+8|0,_=o+13|0,s=o,d=o+12|0,ts(_,n),t[l>>2]=ns(_,n)|0,wu(d,r),L[s>>3]=+Du(d,r),Yk(e,l,s),h=o}function Yk(e,n,r){e=e|0,n=n|0,r=r|0,M(e+8|0,t[n>>2]|0,+L[r>>3]),c[e+24>>0]=1}function $k(){return 1404}function Kk(e,n){return e=e|0,n=+n,Xk(e,n)|0}function Xk(e,n){e=e|0,n=+n;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return o=h,h=h+16|0,l=o+4|0,d=o+8|0,_=o,s=Qo(8)|0,r=s,y=Tt(16)|0,ts(l,e),e=ns(l,e)|0,wu(d,n),M(y,e,+Du(d,n)),d=r+4|0,t[d>>2]=y,e=Tt(8)|0,d=t[d>>2]|0,t[_>>2]=0,t[l>>2]=t[_>>2],P1(e,d,l),t[s>>2]=e,h=o,r|0}function Jk(){var e=0;return c[7896]|0||(Kw(10364),Bt(54,10364,Q|0)|0,e=7896,t[e>>2]=1,t[e+4>>2]=0),Dn(10364)|0||Kw(10364),10364}function Kw(e){e=e|0,eA(e),sc(e,55)}function Qk(e){e=e|0,Zk(e+24|0)}function Zk(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function eA(e){e=e|0;var n=0;n=An()|0,Nn(e,5,4,n,iA()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function tA(e){e=e|0,nA(e)}function nA(e){e=e|0,rA(e)}function rA(e){e=e|0,Xw(e+8|0),c[e+24>>0]=1}function Xw(e){e=e|0,t[e>>2]=0,L[e+8>>3]=0}function iA(){return 1424}function oA(){return uA()|0}function uA(){var e=0,n=0,r=0,o=0,s=0,l=0,d=0;return n=h,h=h+16|0,s=n+4|0,d=n,r=Qo(8)|0,e=r,o=Tt(16)|0,Xw(o),l=e+4|0,t[l>>2]=o,o=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],P1(o,l,s),t[r>>2]=o,h=n,e|0}function sA(e,n){e=e|0,n=n|0,t[e>>2]=lA()|0,t[e+4>>2]=fA()|0,t[e+12>>2]=n,t[e+8>>2]=cA()|0,t[e+32>>2]=5}function lA(){return 11710}function fA(){return 1416}function cA(){return th()|0}function aA(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(dA(r),Ve(r)):n|0&&Ve(n)}function dA(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function th(){var e=0;return c[7904]|0||(t[2600]=pA()|0,t[2601]=0,e=7904,t[e>>2]=1,t[e+4>>2]=0),10400}function pA(){return t[357]|0}function hA(e){e=e|0,mA(e,4926),vA(e)|0}function mA(e,n){e=e|0,n=n|0;var r=0;r=u1()|0,t[e>>2]=r,kA(r,n),Cf(t[e>>2]|0)}function vA(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,gA()|0),e|0}function gA(){var e=0;return c[7912]|0||(Jw(10412),Bt(56,10412,Q|0)|0,e=7912,t[e>>2]=1,t[e+4>>2]=0),Dn(10412)|0||Jw(10412),10412}function Jw(e){e=e|0,wA(e),sc(e,57)}function _A(e){e=e|0,yA(e+24|0)}function yA(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function wA(e){e=e|0;var n=0;n=An()|0,Nn(e,5,5,n,CA()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function DA(e){e=e|0,EA(e)}function EA(e){e=e|0,SA(e)}function SA(e){e=e|0;var n=0,r=0;n=e+8|0,r=n+48|0;do t[n>>2]=0,n=n+4|0;while((n|0)<(r|0));c[e+56>>0]=1}function CA(){return 1432}function TA(){return xA()|0}function xA(){var e=0,n=0,r=0,o=0,s=0,l=0,d=0,_=0;d=h,h=h+16|0,e=d+4|0,n=d,r=Qo(8)|0,o=r,s=Tt(48)|0,l=s,_=l+48|0;do t[l>>2]=0,l=l+4|0;while((l|0)<(_|0));return l=o+4|0,t[l>>2]=s,_=Tt(8)|0,l=t[l>>2]|0,t[n>>2]=0,t[e>>2]=t[n>>2],Wd(_,l,e),t[r>>2]=_,h=d,o|0}function kA(e,n){e=e|0,n=n|0,t[e>>2]=AA()|0,t[e+4>>2]=OA()|0,t[e+12>>2]=n,t[e+8>>2]=IA()|0,t[e+32>>2]=6}function AA(){return 11704}function OA(){return 1436}function IA(){return th()|0}function PA(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(MA(r),Ve(r)):n|0&&Ve(n)}function MA(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function FA(e){e=e|0,LA(e,4933),RA(e)|0,NA(e)|0}function LA(e,n){e=e|0,n=n|0;var r=0;r=uO()|0,t[e>>2]=r,sO(r,n),Cf(t[e>>2]|0)}function RA(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,XA()|0),e|0}function NA(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,BA()|0),e|0}function BA(){var e=0;return c[7920]|0||(Qw(10452),Bt(58,10452,Q|0)|0,e=7920,t[e>>2]=1,t[e+4>>2]=0),Dn(10452)|0||Qw(10452),10452}function Qw(e){e=e|0,qA(e),sc(e,1)}function jA(e){e=e|0,UA(e+24|0)}function UA(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function qA(e){e=e|0;var n=0;n=An()|0,Nn(e,5,1,n,bA()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function zA(e,n,r){e=e|0,n=+n,r=+r,WA(e,n,r)}function WA(e,n,r){e=e|0,n=+n,r=+r;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+32|0,l=o+8|0,_=o+17|0,s=o,d=o+16|0,wu(_,n),L[l>>3]=+Du(_,n),wu(d,r),L[s>>3]=+Du(d,r),HA(e,l,s),h=o}function HA(e,n,r){e=e|0,n=n|0,r=r|0,Zw(e+8|0,+L[n>>3],+L[r>>3]),c[e+24>>0]=1}function Zw(e,n,r){e=e|0,n=+n,r=+r,L[e>>3]=n,L[e+8>>3]=r}function bA(){return 1472}function GA(e,n){return e=+e,n=+n,VA(e,n)|0}function VA(e,n){e=+e,n=+n;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return o=h,h=h+16|0,d=o+4|0,_=o+8|0,y=o,s=Qo(8)|0,r=s,l=Tt(16)|0,wu(d,e),e=+Du(d,e),wu(_,n),Zw(l,e,+Du(_,n)),_=r+4|0,t[_>>2]=l,l=Tt(8)|0,_=t[_>>2]|0,t[y>>2]=0,t[d>>2]=t[y>>2],e8(l,_,d),t[s>>2]=l,h=o,r|0}function e8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Tt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1452,t[r+12>>2]=n,t[e+4>>2]=r}function YA(e){e=e|0,da(e),Ve(e)}function $A(e){e=e|0,e=t[e+12>>2]|0,e|0&&Ve(e)}function KA(e){e=e|0,Ve(e)}function XA(){var e=0;return c[7928]|0||(t8(10488),Bt(59,10488,Q|0)|0,e=7928,t[e>>2]=1,t[e+4>>2]=0),Dn(10488)|0||t8(10488),10488}function t8(e){e=e|0,ZA(e),sc(e,60)}function JA(e){e=e|0,QA(e+24|0)}function QA(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function ZA(e){e=e|0;var n=0;n=An()|0,Nn(e,5,6,n,rO()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function eO(e){e=e|0,tO(e)}function tO(e){e=e|0,nO(e)}function nO(e){e=e|0,n8(e+8|0),c[e+24>>0]=1}function n8(e){e=e|0,t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,t[e+12>>2]=0}function rO(){return 1492}function iO(){return oO()|0}function oO(){var e=0,n=0,r=0,o=0,s=0,l=0,d=0;return n=h,h=h+16|0,s=n+4|0,d=n,r=Qo(8)|0,e=r,o=Tt(16)|0,n8(o),l=e+4|0,t[l>>2]=o,o=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],e8(o,l,s),t[r>>2]=o,h=n,e|0}function uO(){var e=0;return c[7936]|0||(pO(10524),Bt(25,10524,Q|0)|0,e=7936,t[e>>2]=1,t[e+4>>2]=0),10524}function sO(e,n){e=e|0,n=n|0,t[e>>2]=lO()|0,t[e+4>>2]=fO()|0,t[e+12>>2]=n,t[e+8>>2]=cO()|0,t[e+32>>2]=7}function lO(){return 11700}function fO(){return 1484}function cO(){return th()|0}function aO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(dO(r),Ve(r)):n|0&&Ve(n)}function dO(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function pO(e){e=e|0,Ys(e)}function hO(e,n,r){e=e|0,n=n|0,r=r|0,e=Zn(n)|0,n=mO(r)|0,r=vO(r,0)|0,VO(e,n,r,k4()|0,0)}function mO(e){return e=e|0,e|0}function vO(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=k4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(i8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(SO(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function k4(){var e=0,n=0;if(c[7944]|0||(r8(10568),Bt(61,10568,Q|0)|0,n=7944,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10568)|0)){e=10568,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));r8(10568)}return 10568}function r8(e){e=e|0,yO(e)}function gO(e){e=e|0,_O(e+24|0)}function _O(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function yO(e){e=e|0;var n=0;n=An()|0,Nn(e,1,17,n,Dp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function wO(e){return e=e|0,EO(t[(DO(e)|0)>>2]|0)|0}function DO(e){return e=e|0,(t[(k4()|0)+24>>2]|0)+(e<<3)|0}function EO(e){return e=e|0,ea(ph[e&7]()|0)|0}function i8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function SO(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=CO(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,TO(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,i8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,xO(e,s),kO(s),h=_;return}}function CO(e){return e=e|0,536870911}function TO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function xO(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function kO(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function AO(){OO()}function OO(){IO(10604)}function IO(e){e=e|0,PO(e,4955)}function PO(e,n){e=e|0,n=n|0;var r=0;r=MO()|0,t[e>>2]=r,FO(r,n),Cf(t[e>>2]|0)}function MO(){var e=0;return c[7952]|0||(WO(10612),Bt(25,10612,Q|0)|0,e=7952,t[e>>2]=1,t[e+4>>2]=0),10612}function FO(e,n){e=e|0,n=n|0,t[e>>2]=BO()|0,t[e+4>>2]=jO()|0,t[e+12>>2]=n,t[e+8>>2]=UO()|0,t[e+32>>2]=8}function Cf(e){e=e|0;var n=0,r=0;n=h,h=h+16|0,r=n,sa()|0,t[r>>2]=e,LO(10608,r),h=n}function sa(){return c[11714]|0||(t[2652]=0,Bt(62,10608,Q|0)|0,c[11714]=1),10608}function LO(e,n){e=e|0,n=n|0;var r=0;r=Tt(8)|0,t[r+4>>2]=t[n>>2],t[r>>2]=t[e>>2],t[e>>2]=r}function RO(e){e=e|0,NO(e)}function NO(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Ve(r);while((n|0)!=0);t[e>>2]=0}function BO(){return 11715}function jO(){return 1496}function UO(){return eh()|0}function qO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(zO(r),Ve(r)):n|0&&Ve(n)}function zO(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function WO(e){e=e|0,Ys(e)}function HO(e,n){e=e|0,n=n|0;var r=0,o=0;sa()|0,r=t[2652]|0;e:do if(r|0){for(;o=t[r+4>>2]|0,!(o|0?(U8(A4(o)|0,e)|0)==0:0);)if(r=t[r>>2]|0,!r)break e;bO(o,n)}while(0)}function A4(e){return e=e|0,t[e+12>>2]|0}function bO(e,n){e=e|0,n=n|0;var r=0;e=e+36|0,r=t[e>>2]|0,r|0&&(Ju(r),Ve(r)),r=Tt(4)|0,ba(r,n),t[e>>2]=r}function O4(){return c[11716]|0||(t[2664]=0,Bt(63,10656,Q|0)|0,c[11716]=1),10656}function o8(){var e=0;return c[11717]|0?e=t[2665]|0:(GO(),t[2665]=1504,c[11717]=1,e=1504),e|0}function GO(){c[11740]|0||(c[11718]=Lt(Lt(8,0)|0,0)|0,c[11719]=Lt(Lt(0,0)|0,0)|0,c[11720]=Lt(Lt(0,16)|0,0)|0,c[11721]=Lt(Lt(8,0)|0,0)|0,c[11722]=Lt(Lt(0,0)|0,0)|0,c[11723]=Lt(Lt(8,0)|0,0)|0,c[11724]=Lt(Lt(0,0)|0,0)|0,c[11725]=Lt(Lt(8,0)|0,0)|0,c[11726]=Lt(Lt(0,0)|0,0)|0,c[11727]=Lt(Lt(8,0)|0,0)|0,c[11728]=Lt(Lt(0,0)|0,0)|0,c[11729]=Lt(Lt(0,0)|0,32)|0,c[11730]=Lt(Lt(0,0)|0,32)|0,c[11740]=1)}function u8(){return 1572}function VO(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0,T=0;l=h,h=h+32|0,T=l+16|0,k=l+12|0,y=l+8|0,_=l+4|0,d=l,t[T>>2]=e,t[k>>2]=n,t[y>>2]=r,t[_>>2]=o,t[d>>2]=s,O4()|0,YO(10656,T,k,y,_,d),h=l}function YO(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0;d=Tt(24)|0,t1(d+4|0,t[n>>2]|0,t[r>>2]|0,t[o>>2]|0,t[s>>2]|0,t[l>>2]|0),t[d>>2]=t[e>>2],t[e>>2]=d}function s8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0,qe=0;if(qe=h,h=h+32|0,le=qe+20|0,ie=qe+8|0,Pe=qe+4|0,ke=qe,n=t[n>>2]|0,n|0){we=le+4|0,y=le+8|0,k=ie+4|0,T=ie+8|0,P=ie+8|0,q=le+8|0;do{if(d=n+4|0,_=I4(d)|0,_|0){if(s=b1(_)|0,t[le>>2]=0,t[we>>2]=0,t[y>>2]=0,o=(G1(_)|0)+1|0,$O(le,o),o|0)for(;o=o+-1|0,os(ie,t[s>>2]|0),l=t[we>>2]|0,l>>>0<(t[q>>2]|0)>>>0?(t[l>>2]=t[ie>>2],t[we>>2]=(t[we>>2]|0)+4):P4(le,ie),o;)s=s+4|0;o=V1(_)|0,t[ie>>2]=0,t[k>>2]=0,t[T>>2]=0;e:do if(t[o>>2]|0)for(s=0,l=0;;){if((s|0)==(l|0)?KO(ie,o):(t[s>>2]=t[o>>2],t[k>>2]=(t[k>>2]|0)+4),o=o+4|0,!(t[o>>2]|0))break e;s=t[k>>2]|0,l=t[P>>2]|0}while(0);t[Pe>>2]=nh(d)|0,t[ke>>2]=Dn(_)|0,XO(r,e,Pe,ke,le,ie),M4(ie),Rl(le)}n=t[n>>2]|0}while((n|0)!=0)}h=qe}function I4(e){return e=e|0,t[e+12>>2]|0}function b1(e){return e=e|0,t[e+12>>2]|0}function G1(e){return e=e|0,t[e+16>>2]|0}function $O(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;s=h,h=h+32|0,r=s,o=t[e>>2]|0,(t[e+8>>2]|0)-o>>2>>>0>>0&&(m8(r,n,(t[e+4>>2]|0)-o>>2,e+8|0),v8(e,r),g8(r)),h=s}function P4(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0;if(d=h,h=h+32|0,r=d,o=e+4|0,s=((t[o>>2]|0)-(t[e>>2]|0)>>2)+1|0,l=h8(e)|0,l>>>0>>0)$n(e);else{_=t[e>>2]|0,k=(t[e+8>>2]|0)-_|0,y=k>>1,m8(r,k>>2>>>0>>1>>>0?y>>>0>>0?s:y:l,(t[o>>2]|0)-_>>2,e+8|0),l=r+8|0,t[t[l>>2]>>2]=t[n>>2],t[l>>2]=(t[l>>2]|0)+4,v8(e,r),g8(r),h=d;return}}function V1(e){return e=e|0,t[e+8>>2]|0}function KO(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0;if(d=h,h=h+32|0,r=d,o=e+4|0,s=((t[o>>2]|0)-(t[e>>2]|0)>>2)+1|0,l=p8(e)|0,l>>>0>>0)$n(e);else{_=t[e>>2]|0,k=(t[e+8>>2]|0)-_|0,y=k>>1,mI(r,k>>2>>>0>>1>>>0?y>>>0>>0?s:y:l,(t[o>>2]|0)-_>>2,e+8|0),l=r+8|0,t[t[l>>2]>>2]=t[n>>2],t[l>>2]=(t[l>>2]|0)+4,vI(e,r),gI(r),h=d;return}}function nh(e){return e=e|0,t[e>>2]|0}function XO(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,JO(e,n,r,o,s,l)}function M4(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),Ve(r))}function Rl(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),Ve(r))}function JO(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0,y=0,k=0,T=0,P=0;d=h,h=h+48|0,T=d+40|0,_=d+32|0,P=d+24|0,y=d+12|0,k=d,Zo(_),e=Oi(e)|0,t[P>>2]=t[n>>2],r=t[r>>2]|0,o=t[o>>2]|0,F4(y,s),QO(k,l),t[T>>2]=t[P>>2],ZO(e,T,r,o,y,k),M4(k),Rl(y),eu(_),h=d}function F4(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(pI(e,o),hI(e,t[n>>2]|0,t[r>>2]|0,o))}function QO(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(aI(e,o),dI(e,t[n>>2]|0,t[r>>2]|0,o))}function ZO(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0,y=0,k=0,T=0,P=0;d=h,h=h+32|0,T=d+28|0,P=d+24|0,_=d+12|0,y=d,k=ko(eI()|0)|0,t[P>>2]=t[n>>2],t[T>>2]=t[P>>2],n=lc(T)|0,r=l8(r)|0,o=L4(o)|0,t[_>>2]=t[s>>2],T=s+4|0,t[_+4>>2]=t[T>>2],P=s+8|0,t[_+8>>2]=t[P>>2],t[P>>2]=0,t[T>>2]=0,t[s>>2]=0,s=R4(_)|0,t[y>>2]=t[l>>2],T=l+4|0,t[y+4>>2]=t[T>>2],P=l+8|0,t[y+8>>2]=t[P>>2],t[P>>2]=0,t[T>>2]=0,t[l>>2]=0,qo(0,k|0,e|0,n|0,r|0,o|0,s|0,tI(y)|0)|0,M4(y),Rl(_),h=d}function eI(){var e=0;return c[7968]|0||(fI(10708),e=7968,t[e>>2]=1,t[e+4>>2]=0),10708}function lc(e){return e=e|0,c8(e)|0}function l8(e){return e=e|0,f8(e)|0}function L4(e){return e=e|0,ea(e)|0}function R4(e){return e=e|0,rI(e)|0}function tI(e){return e=e|0,nI(e)|0}function nI(e){e=e|0;var n=0,r=0,o=0;if(o=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=o>>2,o=Qo(o+4|0)|0,t[o>>2]=r,r|0){n=0;do t[o+4+(n<<2)>>2]=f8(t[(t[e>>2]|0)+(n<<2)>>2]|0)|0,n=n+1|0;while((n|0)!=(r|0))}return o|0}function f8(e){return e=e|0,e|0}function rI(e){e=e|0;var n=0,r=0,o=0;if(o=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=o>>2,o=Qo(o+4|0)|0,t[o>>2]=r,r|0){n=0;do t[o+4+(n<<2)>>2]=c8((t[e>>2]|0)+(n<<2)|0)|0,n=n+1|0;while((n|0)!=(r|0))}return o|0}function c8(e){e=e|0;var n=0,r=0,o=0,s=0;return s=h,h=h+32|0,n=s+12|0,r=s,o=U0(a8()|0)|0,o?(s1(n,o),l1(r,n),UF(e,r),e=f1(n)|0):e=iI(e)|0,h=s,e|0}function a8(){var e=0;return c[7960]|0||(lI(10664),Bt(25,10664,Q|0)|0,e=7960,t[e>>2]=1,t[e+4>>2]=0),10664}function iI(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0;return r=h,h=h+16|0,s=r+4|0,d=r,o=Qo(8)|0,n=o,_=Tt(4)|0,t[_>>2]=t[e>>2],l=n+4|0,t[l>>2]=_,e=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],d8(e,l,s),t[o>>2]=e,h=r,n|0}function d8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Tt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1656,t[r+12>>2]=n,t[e+4>>2]=r}function oI(e){e=e|0,da(e),Ve(e)}function uI(e){e=e|0,e=t[e+12>>2]|0,e|0&&Ve(e)}function sI(e){e=e|0,Ve(e)}function lI(e){e=e|0,Ys(e)}function fI(e){e=e|0,Ao(e,cI()|0,5)}function cI(){return 1676}function aI(e,n){e=e|0,n=n|0;var r=0;if((p8(e)|0)>>>0>>0&&$n(e),n>>>0>1073741823)_n();else{r=Tt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function dI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(vn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function p8(e){return e=e|0,1073741823}function pI(e,n){e=e|0,n=n|0;var r=0;if((h8(e)|0)>>>0>>0&&$n(e),n>>>0>1073741823)_n();else{r=Tt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function hI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(vn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function h8(e){return e=e|0,1073741823}function mI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)_n();else{s=Tt(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<2)}function vI(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>2)<<2)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function gI(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Ve(e)}function m8(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)_n();else{s=Tt(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<2)}function v8(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>2)<<2)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function g8(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Ve(e)}function _I(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0;if(ie=h,h=h+32|0,T=ie+20|0,P=ie+12|0,k=ie+16|0,q=ie+4|0,we=ie,le=ie+8|0,_=o8()|0,l=t[_>>2]|0,d=t[l>>2]|0,d|0)for(y=t[_+8>>2]|0,_=t[_+4>>2]|0;os(T,d),yI(e,T,_,y),l=l+4|0,d=t[l>>2]|0,d;)y=y+1|0,_=_+1|0;if(l=u8()|0,d=t[l>>2]|0,d|0)do os(T,d),t[P>>2]=t[l+4>>2],wI(n,T,P),l=l+8|0,d=t[l>>2]|0;while((d|0)!=0);if(l=t[(sa()|0)>>2]|0,l|0)do n=t[l+4>>2]|0,os(T,t[(la(n)|0)>>2]|0),t[P>>2]=A4(n)|0,DI(r,T,P),l=t[l>>2]|0;while((l|0)!=0);if(os(k,0),l=O4()|0,t[T>>2]=t[k>>2],s8(T,l,s),l=t[(sa()|0)>>2]|0,l|0){e=T+4|0,n=T+8|0,r=T+8|0;do{if(y=t[l+4>>2]|0,os(P,t[(la(y)|0)>>2]|0),EI(q,_8(y)|0),d=t[q>>2]|0,d|0){t[T>>2]=0,t[e>>2]=0,t[n>>2]=0;do os(we,t[(la(t[d+4>>2]|0)|0)>>2]|0),_=t[e>>2]|0,_>>>0<(t[r>>2]|0)>>>0?(t[_>>2]=t[we>>2],t[e>>2]=(t[e>>2]|0)+4):P4(T,we),d=t[d>>2]|0;while((d|0)!=0);SI(o,P,T),Rl(T)}t[le>>2]=t[P>>2],k=y8(y)|0,t[T>>2]=t[le>>2],s8(T,k,s),bd(q),l=t[l>>2]|0}while((l|0)!=0)}h=ie}function yI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,RI(e,n,r,o)}function wI(e,n,r){e=e|0,n=n|0,r=r|0,LI(e,n,r)}function la(e){return e=e|0,e|0}function DI(e,n,r){e=e|0,n=n|0,r=r|0,II(e,n,r)}function _8(e){return e=e|0,e+16|0}function EI(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;if(l=h,h=h+16|0,s=l+8|0,r=l,t[e>>2]=0,o=t[n>>2]|0,t[s>>2]=o,t[r>>2]=e,r=OI(r)|0,o|0){if(o=Tt(12)|0,d=(w8(s)|0)+4|0,e=t[d+4>>2]|0,n=o+4|0,t[n>>2]=t[d>>2],t[n+4>>2]=e,n=t[t[s>>2]>>2]|0,t[s>>2]=n,!n)e=o;else for(n=o;e=Tt(12)|0,y=(w8(s)|0)+4|0,_=t[y+4>>2]|0,d=e+4|0,t[d>>2]=t[y>>2],t[d+4>>2]=_,t[n>>2]=e,d=t[t[s>>2]>>2]|0,t[s>>2]=d,d;)n=e;t[e>>2]=t[r>>2],t[r>>2]=o}h=l}function SI(e,n,r){e=e|0,n=n|0,r=r|0,CI(e,n,r)}function y8(e){return e=e|0,e+24|0}function CI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+32|0,d=o+24|0,s=o+16|0,_=o+12|0,l=o,Zo(s),e=Oi(e)|0,t[_>>2]=t[n>>2],F4(l,r),t[d>>2]=t[_>>2],TI(e,d,l),Rl(l),eu(s),h=o}function TI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=h,h=h+32|0,d=o+16|0,_=o+12|0,s=o,l=ko(xI()|0)|0,t[_>>2]=t[n>>2],t[d>>2]=t[_>>2],n=lc(d)|0,t[s>>2]=t[r>>2],d=r+4|0,t[s+4>>2]=t[d>>2],_=r+8|0,t[s+8>>2]=t[_>>2],t[_>>2]=0,t[d>>2]=0,t[r>>2]=0,Ts(0,l|0,e|0,n|0,R4(s)|0)|0,Rl(s),h=o}function xI(){var e=0;return c[7976]|0||(kI(10720),e=7976,t[e>>2]=1,t[e+4>>2]=0),10720}function kI(e){e=e|0,Ao(e,AI()|0,2)}function AI(){return 1732}function OI(e){return e=e|0,t[e>>2]|0}function w8(e){return e=e|0,t[e>>2]|0}function II(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+32|0,l=o+16|0,s=o+8|0,d=o,Zo(s),e=Oi(e)|0,t[d>>2]=t[n>>2],r=t[r>>2]|0,t[l>>2]=t[d>>2],D8(e,l,r),eu(s),h=o}function D8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+16|0,l=o+4|0,d=o,s=ko(PI()|0)|0,t[d>>2]=t[n>>2],t[l>>2]=t[d>>2],n=lc(l)|0,Ts(0,s|0,e|0,n|0,l8(r)|0)|0,h=o}function PI(){var e=0;return c[7984]|0||(MI(10732),e=7984,t[e>>2]=1,t[e+4>>2]=0),10732}function MI(e){e=e|0,Ao(e,FI()|0,2)}function FI(){return 1744}function LI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;o=h,h=h+32|0,l=o+16|0,s=o+8|0,d=o,Zo(s),e=Oi(e)|0,t[d>>2]=t[n>>2],r=t[r>>2]|0,t[l>>2]=t[d>>2],D8(e,l,r),eu(s),h=o}function RI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+32|0,d=s+16|0,l=s+8|0,_=s,Zo(l),e=Oi(e)|0,t[_>>2]=t[n>>2],r=c[r>>0]|0,o=c[o>>0]|0,t[d>>2]=t[_>>2],NI(e,d,r,o),eu(l),h=s}function NI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+16|0,d=s+4|0,_=s,l=ko(BI()|0)|0,t[_>>2]=t[n>>2],t[d>>2]=t[_>>2],n=lc(d)|0,r=fa(r)|0,Bu(0,l|0,e|0,n|0,r|0,fa(o)|0)|0,h=s}function BI(){var e=0;return c[7992]|0||(UI(10744),e=7992,t[e>>2]=1,t[e+4>>2]=0),10744}function fa(e){return e=e|0,jI(e)|0}function jI(e){return e=e|0,e&255|0}function UI(e){e=e|0,Ao(e,qI()|0,3)}function qI(){return 1756}function zI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;switch(q=h,h=h+32|0,_=q+8|0,y=q+4|0,k=q+20|0,T=q,_1(e,0),o=jF(n)|0,t[_>>2]=0,P=_+4|0,t[P>>2]=0,t[_+8>>2]=0,o<<24>>24){case 0:{c[k>>0]=0,WI(y,r,k),rh(e,y)|0,ei(y);break}case 8:{P=z4(n)|0,c[k>>0]=8,os(T,t[P+4>>2]|0),HI(y,r,k,T,P+8|0),rh(e,y)|0,ei(y);break}case 9:{if(l=z4(n)|0,n=t[l+4>>2]|0,n|0)for(d=_+8|0,s=l+12|0;n=n+-1|0,os(y,t[s>>2]|0),o=t[P>>2]|0,o>>>0<(t[d>>2]|0)>>>0?(t[o>>2]=t[y>>2],t[P>>2]=(t[P>>2]|0)+4):P4(_,y),n;)s=s+4|0;c[k>>0]=9,os(T,t[l+8>>2]|0),bI(y,r,k,T,_),rh(e,y)|0,ei(y);break}default:P=z4(n)|0,c[k>>0]=o,os(T,t[P+4>>2]|0),GI(y,r,k,T),rh(e,y)|0,ei(y)}Rl(_),h=q}function WI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;o=h,h=h+16|0,s=o,Zo(s),n=Oi(n)|0,iP(e,n,c[r>>0]|0),eu(s),h=o}function rh(e,n){e=e|0,n=n|0;var r=0;return r=t[e>>2]|0,r|0&&ju(r|0),t[e>>2]=t[n>>2],t[n>>2]=0,e|0}function HI(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0;l=h,h=h+32|0,_=l+16|0,d=l+8|0,y=l,Zo(d),n=Oi(n)|0,r=c[r>>0]|0,t[y>>2]=t[o>>2],s=t[s>>2]|0,t[_>>2]=t[y>>2],eP(e,n,r,_,s),eu(d),h=l}function bI(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0;l=h,h=h+32|0,y=l+24|0,d=l+16|0,k=l+12|0,_=l,Zo(d),n=Oi(n)|0,r=c[r>>0]|0,t[k>>2]=t[o>>2],F4(_,s),t[y>>2]=t[k>>2],XI(e,n,r,y,_),Rl(_),eu(d),h=l}function GI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+32|0,d=s+16|0,l=s+8|0,_=s,Zo(l),n=Oi(n)|0,r=c[r>>0]|0,t[_>>2]=t[o>>2],t[d>>2]=t[_>>2],VI(e,n,r,d),eu(l),h=s}function VI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0,d=0,_=0;s=h,h=h+16|0,l=s+4|0,_=s,d=ko(YI()|0)|0,r=fa(r)|0,t[_>>2]=t[o>>2],t[l>>2]=t[_>>2],ih(e,Ts(0,d|0,n|0,r|0,lc(l)|0)|0),h=s}function YI(){var e=0;return c[8e3]|0||($I(10756),e=8e3,t[e>>2]=1,t[e+4>>2]=0),10756}function ih(e,n){e=e|0,n=n|0,_1(e,n)}function $I(e){e=e|0,Ao(e,KI()|0,2)}function KI(){return 1772}function XI(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0;l=h,h=h+32|0,y=l+16|0,k=l+12|0,d=l,_=ko(JI()|0)|0,r=fa(r)|0,t[k>>2]=t[o>>2],t[y>>2]=t[k>>2],o=lc(y)|0,t[d>>2]=t[s>>2],y=s+4|0,t[d+4>>2]=t[y>>2],k=s+8|0,t[d+8>>2]=t[k>>2],t[k>>2]=0,t[y>>2]=0,t[s>>2]=0,ih(e,Bu(0,_|0,n|0,r|0,o|0,R4(d)|0)|0),Rl(d),h=l}function JI(){var e=0;return c[8008]|0||(QI(10768),e=8008,t[e>>2]=1,t[e+4>>2]=0),10768}function QI(e){e=e|0,Ao(e,ZI()|0,3)}function ZI(){return 1784}function eP(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0;l=h,h=h+16|0,_=l+4|0,y=l,d=ko(tP()|0)|0,r=fa(r)|0,t[y>>2]=t[o>>2],t[_>>2]=t[y>>2],o=lc(_)|0,ih(e,Bu(0,d|0,n|0,r|0,o|0,L4(s)|0)|0),h=l}function tP(){var e=0;return c[8016]|0||(nP(10780),e=8016,t[e>>2]=1,t[e+4>>2]=0),10780}function nP(e){e=e|0,Ao(e,rP()|0,3)}function rP(){return 1800}function iP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=ko(oP()|0)|0,ih(e,sf(0,o|0,n|0,fa(r)|0)|0)}function oP(){var e=0;return c[8024]|0||(uP(10792),e=8024,t[e>>2]=1,t[e+4>>2]=0),10792}function uP(e){e=e|0,Ao(e,sP()|0,1)}function sP(){return 1816}function lP(){fP(),cP(),aP()}function fP(){t[2702]=K8(65536)|0}function cP(){PP(10856)}function aP(){dP(10816)}function dP(e){e=e|0,pP(e,5044),hP(e)|0}function pP(e,n){e=e|0,n=n|0;var r=0;r=a8()|0,t[e>>2]=r,TP(r,n),Cf(t[e>>2]|0)}function hP(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,mP()|0),e|0}function mP(){var e=0;return c[8032]|0||(E8(10820),Bt(64,10820,Q|0)|0,e=8032,t[e>>2]=1,t[e+4>>2]=0),Dn(10820)|0||E8(10820),10820}function E8(e){e=e|0,_P(e),sc(e,25)}function vP(e){e=e|0,gP(e+24|0)}function gP(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function _P(e){e=e|0;var n=0;n=An()|0,Nn(e,5,18,n,EP()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function yP(e,n){e=e|0,n=n|0,wP(e,n)}function wP(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;r=h,h=h+16|0,o=r,s=r+4|0,Ml(s,n),t[o>>2]=Fl(s,n)|0,DP(e,o),h=r}function DP(e,n){e=e|0,n=n|0,S8(e+4|0,t[n>>2]|0),c[e+8>>0]=1}function S8(e,n){e=e|0,n=n|0,t[e>>2]=n}function EP(){return 1824}function SP(e){return e=e|0,CP(e)|0}function CP(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0;return r=h,h=h+16|0,s=r+4|0,d=r,o=Qo(8)|0,n=o,_=Tt(4)|0,Ml(s,e),S8(_,Fl(s,e)|0),l=n+4|0,t[l>>2]=_,e=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],d8(e,l,s),t[o>>2]=e,h=r,n|0}function Qo(e){e=e|0;var n=0,r=0;return e=e+7&-8,(e>>>0<=32768?(n=t[2701]|0,e>>>0<=(65536-n|0)>>>0):0)?(r=(t[2702]|0)+n|0,t[2701]=n+e,e=r):(e=K8(e+8|0)|0,t[e>>2]=t[2703],t[2703]=e,e=e+8|0),e|0}function TP(e,n){e=e|0,n=n|0,t[e>>2]=xP()|0,t[e+4>>2]=kP()|0,t[e+12>>2]=n,t[e+8>>2]=AP()|0,t[e+32>>2]=9}function xP(){return 11744}function kP(){return 1832}function AP(){return th()|0}function OP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(IP(r),Ve(r)):n|0&&Ve(n)}function IP(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function PP(e){e=e|0,MP(e,5052),FP(e)|0,LP(e,5058,26)|0,RP(e,5069,1)|0,NP(e,5077,10)|0,BP(e,5087,19)|0,jP(e,5094,27)|0}function MP(e,n){e=e|0,n=n|0;var r=0;r=IF()|0,t[e>>2]=r,PF(r,n),Cf(t[e>>2]|0)}function FP(e){e=e|0;var n=0;return n=t[e>>2]|0,uc(n,vF()|0),e|0}function LP(e,n,r){return e=e|0,n=n|0,r=r|0,QM(e,Zn(n)|0,r,0),e|0}function RP(e,n,r){return e=e|0,n=n|0,r=r|0,BM(e,Zn(n)|0,r,0),e|0}function NP(e,n,r){return e=e|0,n=n|0,r=r|0,mM(e,Zn(n)|0,r,0),e|0}function BP(e,n,r){return e=e|0,n=n|0,r=r|0,eM(e,Zn(n)|0,r,0),e|0}function C8(e,n){e=e|0,n=n|0;var r=0,o=0;e:for(;;){for(r=t[2703]|0;;){if((r|0)==(n|0))break e;if(o=t[r>>2]|0,t[2703]=o,!r)r=o;else break}Ve(r)}t[2701]=e}function jP(e,n,r){return e=e|0,n=n|0,r=r|0,UP(e,Zn(n)|0,r,0),e|0}function UP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=N4()|0,e=qP(r)|0,ur(l,n,s,e,zP(r,o)|0,o)}function N4(){var e=0,n=0;if(c[8040]|0||(x8(10860),Bt(65,10860,Q|0)|0,n=8040,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10860)|0)){e=10860,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));x8(10860)}return 10860}function qP(e){return e=e|0,e|0}function zP(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=N4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(T8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(WP(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function T8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function WP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=HP(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,bP(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,T8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,GP(e,s),VP(s),h=_;return}}function HP(e){return e=e|0,536870911}function bP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function GP(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function VP(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function x8(e){e=e|0,KP(e)}function YP(e){e=e|0,$P(e+24|0)}function $P(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function KP(e){e=e|0;var n=0;n=An()|0,Nn(e,1,11,n,XP()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function XP(){return 1840}function JP(e,n,r){e=e|0,n=n|0,r=r|0,ZP(t[(QP(e)|0)>>2]|0,n,r)}function QP(e){return e=e|0,(t[(N4()|0)+24>>2]|0)+(e<<3)|0}function ZP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;o=h,h=h+16|0,l=o+1|0,s=o,Ml(l,n),n=Fl(l,n)|0,Ml(s,r),r=Fl(s,r)|0,Bl[e&31](n,r),h=o}function eM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=B4()|0,e=tM(r)|0,ur(l,n,s,e,nM(r,o)|0,o)}function B4(){var e=0,n=0;if(c[8048]|0||(A8(10896),Bt(66,10896,Q|0)|0,n=8048,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10896)|0)){e=10896,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));A8(10896)}return 10896}function tM(e){return e=e|0,e|0}function nM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=B4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(k8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(rM(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function k8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function rM(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=iM(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,oM(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,k8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,uM(e,s),sM(s),h=_;return}}function iM(e){return e=e|0,536870911}function oM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function uM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function sM(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function A8(e){e=e|0,cM(e)}function lM(e){e=e|0,fM(e+24|0)}function fM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function cM(e){e=e|0;var n=0;n=An()|0,Nn(e,1,11,n,aM()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function aM(){return 1852}function dM(e,n){return e=e|0,n=n|0,hM(t[(pM(e)|0)>>2]|0,n)|0}function pM(e){return e=e|0,(t[(B4()|0)+24>>2]|0)+(e<<3)|0}function hM(e,n){e=e|0,n=n|0;var r=0,o=0;return r=h,h=h+16|0,o=r,Ml(o,n),n=Fl(o,n)|0,n=ea(dc[e&31](n)|0)|0,h=r,n|0}function mM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=j4()|0,e=vM(r)|0,ur(l,n,s,e,gM(r,o)|0,o)}function j4(){var e=0,n=0;if(c[8056]|0||(I8(10932),Bt(67,10932,Q|0)|0,n=8056,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10932)|0)){e=10932,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));I8(10932)}return 10932}function vM(e){return e=e|0,e|0}function gM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=j4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(O8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(_M(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function O8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function _M(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=yM(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,wM(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,O8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,DM(e,s),EM(s),h=_;return}}function yM(e){return e=e|0,536870911}function wM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function DM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function EM(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function I8(e){e=e|0,TM(e)}function SM(e){e=e|0,CM(e+24|0)}function CM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function TM(e){e=e|0;var n=0;n=An()|0,Nn(e,1,7,n,xM()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function xM(){return 1860}function kM(e,n,r){return e=e|0,n=n|0,r=r|0,OM(t[(AM(e)|0)>>2]|0,n,r)|0}function AM(e){return e=e|0,(t[(j4()|0)+24>>2]|0)+(e<<3)|0}function OM(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0;return o=h,h=h+32|0,d=o+12|0,l=o+8|0,_=o,y=o+16|0,s=o+4|0,IM(y,n),PM(_,y,n),$s(s,r),r=Ks(s,r)|0,t[d>>2]=t[_>>2],X1[e&15](l,d,r),r=MM(l)|0,ei(l),Xs(s),h=o,r|0}function IM(e,n){e=e|0,n=n|0}function PM(e,n,r){e=e|0,n=n|0,r=r|0,FM(e,r)}function MM(e){return e=e|0,Oi(e)|0}function FM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0;s=h,h=h+16|0,r=s,o=n,o&1?(LM(r,0),c0(o|0,r|0)|0,RM(e,r),NM(r)):t[e>>2]=t[n>>2],h=s}function LM(e,n){e=e|0,n=n|0,wd(e,n),t[e+4>>2]=0,c[e+8>>0]=0}function RM(e,n){e=e|0,n=n|0,t[e>>2]=t[n+4>>2]}function NM(e){e=e|0,c[e+8>>0]=0}function BM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=U4()|0,e=jM(r)|0,ur(l,n,s,e,UM(r,o)|0,o)}function U4(){var e=0,n=0;if(c[8064]|0||(M8(10968),Bt(68,10968,Q|0)|0,n=8064,t[n>>2]=1,t[n+4>>2]=0),!(Dn(10968)|0)){e=10968,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));M8(10968)}return 10968}function jM(e){return e=e|0,e|0}function UM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=U4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(P8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(qM(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function P8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function qM(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=zM(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,WM(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,P8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,HM(e,s),bM(s),h=_;return}}function zM(e){return e=e|0,536870911}function WM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function HM(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function bM(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function M8(e){e=e|0,YM(e)}function GM(e){e=e|0,VM(e+24|0)}function VM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function YM(e){e=e|0;var n=0;n=An()|0,Nn(e,1,1,n,$M()|0,5),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function $M(){return 1872}function KM(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,JM(t[(XM(e)|0)>>2]|0,n,r,o,s,l)}function XM(e){return e=e|0,(t[(U4()|0)+24>>2]|0)+(e<<3)|0}function JM(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0,y=0,k=0,T=0,P=0;d=h,h=h+32|0,_=d+16|0,y=d+12|0,k=d+8|0,T=d+4|0,P=d,$s(_,n),n=Ks(_,n)|0,$s(y,r),r=Ks(y,r)|0,$s(k,o),o=Ks(k,o)|0,$s(T,s),s=Ks(T,s)|0,$s(P,l),l=Ks(P,l)|0,eD[e&1](n,r,o,s,l),Xs(P),Xs(T),Xs(k),Xs(y),Xs(_),h=d}function QM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;l=t[e>>2]|0,s=q4()|0,e=ZM(r)|0,ur(l,n,s,e,eF(r,o)|0,o)}function q4(){var e=0,n=0;if(c[8072]|0||(L8(11004),Bt(69,11004,Q|0)|0,n=8072,t[n>>2]=1,t[n+4>>2]=0),!(Dn(11004)|0)){e=11004,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));L8(11004)}return 11004}function ZM(e){return e=e|0,e|0}function eF(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0,_=0,y=0;return _=h,h=h+16|0,s=_,l=_+4|0,t[s>>2]=e,y=q4()|0,d=y+24|0,n=Lt(n,4)|0,t[l>>2]=n,r=y+28|0,o=t[r>>2]|0,o>>>0<(t[y+32>>2]|0)>>>0?(F8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(tF(d,s,l),n=t[r>>2]|0),h=_,(n-(t[d>>2]|0)>>3)+-1|0}function F8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function tF(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0;if(_=h,h=h+32|0,s=_,l=e+4|0,d=((t[l>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=nF(e)|0,o>>>0>>0)$n(e);else{y=t[e>>2]|0,T=(t[e+8>>2]|0)-y|0,k=T>>2,rF(s,T>>3>>>0>>1>>>0?k>>>0>>0?d:k:o,(t[l>>2]|0)-y>>3,e+8|0),d=s+8|0,F8(t[d>>2]|0,t[n>>2]|0,t[r>>2]|0),t[d>>2]=(t[d>>2]|0)+8,iF(e,s),oF(s),h=_;return}}function nF(e){return e=e|0,536870911}function rF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)_n();else{s=Tt(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,o=s+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=s+(n<<3)}function iF(e,n){e=e|0,n=n|0;var r=0,o=0,s=0,l=0,d=0;o=t[e>>2]|0,d=e+4|0,l=n+4|0,s=(t[d>>2]|0)-o|0,r=(t[l>>2]|0)+(0-(s>>3)<<3)|0,t[l>>2]=r,(s|0)>0?(vn(r|0,o|0,s|0)|0,o=l,r=t[l>>2]|0):o=l,l=t[e>>2]|0,t[e>>2]=r,t[o>>2]=l,l=n+8|0,s=t[d>>2]|0,t[d>>2]=t[l>>2],t[l>>2]=s,l=e+8|0,d=n+12|0,e=t[l>>2]|0,t[l>>2]=t[d>>2],t[d>>2]=e,t[n>>2]=t[o>>2]}function oF(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Ve(e)}function L8(e){e=e|0,lF(e)}function uF(e){e=e|0,sF(e+24|0)}function sF(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function lF(e){e=e|0;var n=0;n=An()|0,Nn(e,1,12,n,fF()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function fF(){return 1896}function cF(e,n,r){e=e|0,n=n|0,r=r|0,dF(t[(aF(e)|0)>>2]|0,n,r)}function aF(e){return e=e|0,(t[(q4()|0)+24>>2]|0)+(e<<3)|0}function dF(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;o=h,h=h+16|0,l=o+4|0,s=o,pF(l,n),n=hF(l,n)|0,$s(s,r),r=Ks(s,r)|0,Bl[e&31](n,r),Xs(s),h=o}function pF(e,n){e=e|0,n=n|0}function hF(e,n){return e=e|0,n=n|0,mF(n)|0}function mF(e){return e=e|0,e|0}function vF(){var e=0;return c[8080]|0||(R8(11040),Bt(70,11040,Q|0)|0,e=8080,t[e>>2]=1,t[e+4>>2]=0),Dn(11040)|0||R8(11040),11040}function R8(e){e=e|0,yF(e),sc(e,71)}function gF(e){e=e|0,_F(e+24|0)}function _F(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),Ve(r))}function yF(e){e=e|0;var n=0;n=An()|0,Nn(e,5,7,n,SF()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function wF(e){e=e|0,DF(e)}function DF(e){e=e|0,EF(e)}function EF(e){e=e|0,c[e+8>>0]=1}function SF(){return 1936}function CF(){return TF()|0}function TF(){var e=0,n=0,r=0,o=0,s=0,l=0,d=0;return n=h,h=h+16|0,s=n+4|0,d=n,r=Qo(8)|0,e=r,l=e+4|0,t[l>>2]=Tt(1)|0,o=Tt(8)|0,l=t[l>>2]|0,t[d>>2]=0,t[s>>2]=t[d>>2],xF(o,l,s),t[r>>2]=o,h=n,e|0}function xF(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Tt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1916,t[r+12>>2]=n,t[e+4>>2]=r}function kF(e){e=e|0,da(e),Ve(e)}function AF(e){e=e|0,e=t[e+12>>2]|0,e|0&&Ve(e)}function OF(e){e=e|0,Ve(e)}function IF(){var e=0;return c[8088]|0||(BF(11076),Bt(25,11076,Q|0)|0,e=8088,t[e>>2]=1,t[e+4>>2]=0),11076}function PF(e,n){e=e|0,n=n|0,t[e>>2]=MF()|0,t[e+4>>2]=FF()|0,t[e+12>>2]=n,t[e+8>>2]=LF()|0,t[e+32>>2]=10}function MF(){return 11745}function FF(){return 1940}function LF(){return eh()|0}function RF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(Sf(o,896)|0)==512?r|0&&(NF(r),Ve(r)):n|0&&Ve(n)}function NF(e){e=e|0,e=t[e+4>>2]|0,e|0&&Tf(e)}function BF(e){e=e|0,Ys(e)}function os(e,n){e=e|0,n=n|0,t[e>>2]=n}function z4(e){return e=e|0,t[e>>2]|0}function jF(e){return e=e|0,c[t[e>>2]>>0]|0}function UF(e,n){e=e|0,n=n|0;var r=0,o=0;r=h,h=h+16|0,o=r,t[o>>2]=t[e>>2],qF(n,o)|0,h=r}function qF(e,n){e=e|0,n=n|0;var r=0;return r=zF(t[e>>2]|0,n)|0,n=e+4|0,t[(t[n>>2]|0)+8>>2]=r,t[(t[n>>2]|0)+8>>2]|0}function zF(e,n){e=e|0,n=n|0;var r=0,o=0;return r=h,h=h+16|0,o=r,Zo(o),e=Oi(e)|0,n=WF(e,t[n>>2]|0)|0,eu(o),h=r,n|0}function Zo(e){e=e|0,t[e>>2]=t[2701],t[e+4>>2]=t[2703]}function WF(e,n){e=e|0,n=n|0;var r=0;return r=ko(HF()|0)|0,sf(0,r|0,e|0,L4(n)|0)|0}function eu(e){e=e|0,C8(t[e>>2]|0,t[e+4>>2]|0)}function HF(){var e=0;return c[8096]|0||(bF(11120),e=8096,t[e>>2]=1,t[e+4>>2]=0),11120}function bF(e){e=e|0,Ao(e,GF()|0,1)}function GF(){return 1948}function VF(){YF()}function YF(){var e=0,n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0;if(le=h,h=h+16|0,T=le+4|0,P=le,si(65536,10804,t[2702]|0,10812),r=o8()|0,n=t[r>>2]|0,e=t[n>>2]|0,e|0)for(o=t[r+8>>2]|0,r=t[r+4>>2]|0;As(e|0,C[r>>0]|0|0,c[o>>0]|0),n=n+4|0,e=t[n>>2]|0,e;)o=o+1|0,r=r+1|0;if(e=u8()|0,n=t[e>>2]|0,n|0)do uu(n|0,t[e+4>>2]|0),e=e+8|0,n=t[e>>2]|0;while((n|0)!=0);uu($F()|0,5167),k=sa()|0,e=t[k>>2]|0;e:do if(e|0){do KF(t[e+4>>2]|0),e=t[e>>2]|0;while((e|0)!=0);if(e=t[k>>2]|0,e|0){y=k;do{for(;s=e,e=t[e>>2]|0,s=t[s+4>>2]|0,!!(XF(s)|0);)if(t[P>>2]=y,t[T>>2]=t[P>>2],JF(k,T)|0,!e)break e;if(QF(s),y=t[y>>2]|0,n=N8(s)|0,l=Wo()|0,d=h,h=h+((1*(n<<2)|0)+15&-16)|0,_=h,h=h+((1*(n<<2)|0)+15&-16)|0,n=t[(_8(s)|0)>>2]|0,n|0)for(r=d,o=_;t[r>>2]=t[(la(t[n+4>>2]|0)|0)>>2],t[o>>2]=t[n+8>>2],n=t[n>>2]|0,n;)r=r+4|0,o=o+4|0;ie=la(s)|0,n=ZF(s)|0,r=N8(s)|0,o=eL(s)|0,Is(ie|0,n|0,d|0,_|0,r|0,o|0,A4(s)|0),b0(l|0)}while((e|0)!=0)}}while(0);if(e=t[(O4()|0)>>2]|0,e|0)do ie=e+4|0,k=I4(ie)|0,s=V1(k)|0,l=b1(k)|0,d=(G1(k)|0)+1|0,_=oh(k)|0,y=B8(ie)|0,k=Dn(k)|0,T=nh(ie)|0,P=W4(ie)|0,zo(0,s|0,l|0,d|0,_|0,y|0,k|0,T|0,P|0,H4(ie)|0),e=t[e>>2]|0;while((e|0)!=0);e=t[(sa()|0)>>2]|0;e:do if(e|0){t:for(;;){if(n=t[e+4>>2]|0,n|0?(q=t[(la(n)|0)>>2]|0,we=t[(y8(n)|0)>>2]|0,we|0):0){r=we;do{n=r+4|0,o=I4(n)|0;n:do if(o|0)switch(Dn(o)|0){case 0:break t;case 4:case 3:case 2:{_=V1(o)|0,y=b1(o)|0,k=(G1(o)|0)+1|0,T=oh(o)|0,P=Dn(o)|0,ie=nh(n)|0,zo(q|0,_|0,y|0,k|0,T|0,0,P|0,ie|0,W4(n)|0,H4(n)|0);break n}case 1:{d=V1(o)|0,_=b1(o)|0,y=(G1(o)|0)+1|0,k=oh(o)|0,T=B8(n)|0,P=Dn(o)|0,ie=nh(n)|0,zo(q|0,d|0,_|0,y|0,k|0,T|0,P|0,ie|0,W4(n)|0,H4(n)|0);break n}case 5:{k=V1(o)|0,T=b1(o)|0,P=(G1(o)|0)+1|0,ie=oh(o)|0,zo(q|0,k|0,T|0,P|0,ie|0,tL(o)|0,Dn(o)|0,0,0,0);break n}default:break n}while(0);r=t[r>>2]|0}while((r|0)!=0)}if(e=t[e>>2]|0,!e)break e}_n()}while(0);uf(),h=le}function $F(){return 11703}function KF(e){e=e|0,c[e+40>>0]=0}function XF(e){return e=e|0,(c[e+40>>0]|0)!=0|0}function JF(e,n){return e=e|0,n=n|0,n=nL(n)|0,e=t[n>>2]|0,t[n>>2]=t[e>>2],Ve(e),t[n>>2]|0}function QF(e){e=e|0,c[e+40>>0]=1}function N8(e){return e=e|0,t[e+20>>2]|0}function ZF(e){return e=e|0,t[e+8>>2]|0}function eL(e){return e=e|0,t[e+32>>2]|0}function oh(e){return e=e|0,t[e+4>>2]|0}function B8(e){return e=e|0,t[e+4>>2]|0}function W4(e){return e=e|0,t[e+8>>2]|0}function H4(e){return e=e|0,t[e+16>>2]|0}function tL(e){return e=e|0,t[e+20>>2]|0}function nL(e){return e=e|0,t[e>>2]|0}function uh(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0,qe=0,pe=0,_e=0,vt=0;vt=h,h=h+16|0,q=vt;do if(e>>>0<245){if(k=e>>>0<11?16:e+11&-8,e=k>>>3,P=t[2783]|0,r=P>>>e,r&3|0)return n=(r&1^1)+e|0,e=11172+(n<<1<<2)|0,r=e+8|0,o=t[r>>2]|0,s=o+8|0,l=t[s>>2]|0,(e|0)==(l|0)?t[2783]=P&~(1<>2]=e,t[r>>2]=l),_e=n<<3,t[o+4>>2]=_e|3,_e=o+_e+4|0,t[_e>>2]=t[_e>>2]|1,_e=s,h=vt,_e|0;if(T=t[2785]|0,k>>>0>T>>>0){if(r|0)return n=2<>>12&16,n=n>>>d,r=n>>>5&8,n=n>>>r,s=n>>>2&4,n=n>>>s,e=n>>>1&2,n=n>>>e,o=n>>>1&1,o=(r|d|s|e|o)+(n>>>o)|0,n=11172+(o<<1<<2)|0,e=n+8|0,s=t[e>>2]|0,d=s+8|0,r=t[d>>2]|0,(n|0)==(r|0)?(e=P&~(1<>2]=n,t[e>>2]=r,e=P),l=(o<<3)-k|0,t[s+4>>2]=k|3,o=s+k|0,t[o+4>>2]=l|1,t[o+l>>2]=l,T|0&&(s=t[2788]|0,n=T>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=s,t[n+12>>2]=s,t[s+8>>2]=n,t[s+12>>2]=r),t[2785]=l,t[2788]=o,_e=d,h=vt,_e|0;if(_=t[2784]|0,_){if(r=(_&0-_)+-1|0,d=r>>>12&16,r=r>>>d,l=r>>>5&8,r=r>>>l,y=r>>>2&4,r=r>>>y,o=r>>>1&2,r=r>>>o,e=r>>>1&1,e=t[11436+((l|d|y|o|e)+(r>>>e)<<2)>>2]|0,r=(t[e+4>>2]&-8)-k|0,o=t[e+16+(((t[e+16>>2]|0)==0&1)<<2)>>2]|0,!o)y=e,l=r;else{do d=(t[o+4>>2]&-8)-k|0,y=d>>>0>>0,r=y?d:r,e=y?o:e,o=t[o+16+(((t[o+16>>2]|0)==0&1)<<2)>>2]|0;while((o|0)!=0);y=e,l=r}if(d=y+k|0,y>>>0>>0){s=t[y+24>>2]|0,n=t[y+12>>2]|0;do if((n|0)==(y|0)){if(e=y+20|0,n=t[e>>2]|0,!n&&(e=y+16|0,n=t[e>>2]|0,!n)){r=0;break}for(;;){if(r=n+20|0,o=t[r>>2]|0,o|0){n=o,e=r;continue}if(r=n+16|0,o=t[r>>2]|0,o)n=o,e=r;else break}t[e>>2]=0,r=n}else r=t[y+8>>2]|0,t[r+12>>2]=n,t[n+8>>2]=r,r=n;while(0);do if(s|0){if(n=t[y+28>>2]|0,e=11436+(n<<2)|0,(y|0)==(t[e>>2]|0)){if(t[e>>2]=r,!r){t[2784]=_&~(1<>2]|0)!=(y|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=s,n=t[y+16>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),n=t[y+20>>2]|0,n|0&&(t[r+20>>2]=n,t[n+24>>2]=r)}while(0);return l>>>0<16?(_e=l+k|0,t[y+4>>2]=_e|3,_e=y+_e+4|0,t[_e>>2]=t[_e>>2]|1):(t[y+4>>2]=k|3,t[d+4>>2]=l|1,t[d+l>>2]=l,T|0&&(o=t[2788]|0,n=T>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=P|n,n=r,e=r+8|0),t[e>>2]=o,t[n+12>>2]=o,t[o+8>>2]=n,t[o+12>>2]=r),t[2785]=l,t[2788]=d),_e=y+8|0,h=vt,_e|0}else P=k}else P=k}else P=k}else if(e>>>0<=4294967231)if(e=e+11|0,k=e&-8,y=t[2784]|0,y){o=0-k|0,e=e>>>8,e?k>>>0>16777215?_=31:(P=(e+1048320|0)>>>16&8,pe=e<>>16&4,pe=pe<>>16&2,_=14-(T|P|_)+(pe<<_>>>15)|0,_=k>>>(_+7|0)&1|_<<1):_=0,r=t[11436+(_<<2)>>2]|0;e:do if(!r)r=0,e=0,pe=57;else for(e=0,d=k<<((_|0)==31?0:25-(_>>>1)|0),l=0;;){if(s=(t[r+4>>2]&-8)-k|0,s>>>0>>0)if(s)e=r,o=s;else{e=r,o=0,s=r,pe=61;break e}if(s=t[r+20>>2]|0,r=t[r+16+(d>>>31<<2)>>2]|0,l=(s|0)==0|(s|0)==(r|0)?l:s,s=(r|0)==0,s){r=l,pe=57;break}else d=d<<((s^1)&1)}while(0);if((pe|0)==57){if((r|0)==0&(e|0)==0){if(e=2<<_,e=y&(e|0-e),!e){P=k;break}P=(e&0-e)+-1|0,d=P>>>12&16,P=P>>>d,l=P>>>5&8,P=P>>>l,_=P>>>2&4,P=P>>>_,T=P>>>1&2,P=P>>>T,r=P>>>1&1,e=0,r=t[11436+((l|d|_|T|r)+(P>>>r)<<2)>>2]|0}r?(s=r,pe=61):(_=e,d=o)}if((pe|0)==61)for(;;)if(pe=0,r=(t[s+4>>2]&-8)-k|0,P=r>>>0>>0,r=P?r:o,e=P?s:e,s=t[s+16+(((t[s+16>>2]|0)==0&1)<<2)>>2]|0,s)o=r,pe=61;else{_=e,d=r;break}if((_|0)!=0?d>>>0<((t[2785]|0)-k|0)>>>0:0){if(l=_+k|0,_>>>0>=l>>>0)return _e=0,h=vt,_e|0;s=t[_+24>>2]|0,n=t[_+12>>2]|0;do if((n|0)==(_|0)){if(e=_+20|0,n=t[e>>2]|0,!n&&(e=_+16|0,n=t[e>>2]|0,!n)){n=0;break}for(;;){if(r=n+20|0,o=t[r>>2]|0,o|0){n=o,e=r;continue}if(r=n+16|0,o=t[r>>2]|0,o)n=o,e=r;else break}t[e>>2]=0}else _e=t[_+8>>2]|0,t[_e+12>>2]=n,t[n+8>>2]=_e;while(0);do if(s){if(e=t[_+28>>2]|0,r=11436+(e<<2)|0,(_|0)==(t[r>>2]|0)){if(t[r>>2]=n,!n){o=y&~(1<>2]|0)!=(_|0)&1)<<2)>>2]=n,!n){o=y;break}t[n+24>>2]=s,e=t[_+16>>2]|0,e|0&&(t[n+16>>2]=e,t[e+24>>2]=n),e=t[_+20>>2]|0,e&&(t[n+20>>2]=e,t[e+24>>2]=n),o=y}else o=y;while(0);do if(d>>>0>=16){if(t[_+4>>2]=k|3,t[l+4>>2]=d|1,t[l+d>>2]=d,n=d>>>3,d>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=l,t[n+12>>2]=l,t[l+8>>2]=n,t[l+12>>2]=r;break}if(n=d>>>8,n?d>>>0>16777215?n=31:(pe=(n+1048320|0)>>>16&8,_e=n<>>16&4,_e=_e<>>16&2,n=14-(qe|pe|n)+(_e<>>15)|0,n=d>>>(n+7|0)&1|n<<1):n=0,r=11436+(n<<2)|0,t[l+28>>2]=n,e=l+16|0,t[e+4>>2]=0,t[e>>2]=0,e=1<>2]=l,t[l+24>>2]=r,t[l+12>>2]=l,t[l+8>>2]=l;break}for(e=d<<((n|0)==31?0:25-(n>>>1)|0),r=t[r>>2]|0;;){if((t[r+4>>2]&-8|0)==(d|0)){pe=97;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{pe=96;break}}if((pe|0)==96){t[o>>2]=l,t[l+24>>2]=r,t[l+12>>2]=l,t[l+8>>2]=l;break}else if((pe|0)==97){pe=r+8|0,_e=t[pe>>2]|0,t[_e+12>>2]=l,t[pe>>2]=l,t[l+8>>2]=_e,t[l+12>>2]=r,t[l+24>>2]=0;break}}else _e=d+k|0,t[_+4>>2]=_e|3,_e=_+_e+4|0,t[_e>>2]=t[_e>>2]|1;while(0);return _e=_+8|0,h=vt,_e|0}else P=k}else P=k;else P=-1;while(0);if(r=t[2785]|0,r>>>0>=P>>>0)return n=r-P|0,e=t[2788]|0,n>>>0>15?(_e=e+P|0,t[2788]=_e,t[2785]=n,t[_e+4>>2]=n|1,t[_e+n>>2]=n,t[e+4>>2]=P|3):(t[2785]=0,t[2788]=0,t[e+4>>2]=r|3,_e=e+r+4|0,t[_e>>2]=t[_e>>2]|1),_e=e+8|0,h=vt,_e|0;if(d=t[2786]|0,d>>>0>P>>>0)return qe=d-P|0,t[2786]=qe,_e=t[2789]|0,pe=_e+P|0,t[2789]=pe,t[pe+4>>2]=qe|1,t[_e+4>>2]=P|3,_e=_e+8|0,h=vt,_e|0;if(t[2901]|0?e=t[2903]|0:(t[2903]=4096,t[2902]=4096,t[2904]=-1,t[2905]=-1,t[2906]=0,t[2894]=0,e=q&-16^1431655768,t[q>>2]=e,t[2901]=e,e=4096),_=P+48|0,y=P+47|0,l=e+y|0,s=0-e|0,k=l&s,k>>>0<=P>>>0||(e=t[2893]|0,e|0?(T=t[2891]|0,q=T+k|0,q>>>0<=T>>>0|q>>>0>e>>>0):0))return _e=0,h=vt,_e|0;e:do if(t[2894]&4)n=0,pe=133;else{r=t[2789]|0;t:do if(r){for(o=11580;e=t[o>>2]|0,!(e>>>0<=r>>>0?(ie=o+4|0,(e+(t[ie>>2]|0)|0)>>>0>r>>>0):0);)if(e=t[o+8>>2]|0,e)o=e;else{pe=118;break t}if(n=l-d&s,n>>>0<2147483647)if(e=xf(n|0)|0,(e|0)==((t[o>>2]|0)+(t[ie>>2]|0)|0)){if((e|0)!=(-1|0)){d=n,l=e,pe=135;break e}}else o=e,pe=126;else n=0}else pe=118;while(0);do if((pe|0)==118)if(r=xf(0)|0,(r|0)!=(-1|0)?(n=r,we=t[2902]|0,le=we+-1|0,n=((le&n|0)==0?0:(le+n&0-we)-n|0)+k|0,we=t[2891]|0,le=n+we|0,n>>>0>P>>>0&n>>>0<2147483647):0){if(ie=t[2893]|0,ie|0?le>>>0<=we>>>0|le>>>0>ie>>>0:0){n=0;break}if(e=xf(n|0)|0,(e|0)==(r|0)){d=n,l=r,pe=135;break e}else o=e,pe=126}else n=0;while(0);do if((pe|0)==126){if(r=0-n|0,!(_>>>0>n>>>0&(n>>>0<2147483647&(o|0)!=(-1|0))))if((o|0)==(-1|0)){n=0;break}else{d=n,l=o,pe=135;break e}if(e=t[2903]|0,e=y-n+e&0-e,e>>>0>=2147483647){d=n,l=o,pe=135;break e}if((xf(e|0)|0)==(-1|0)){xf(r|0)|0,n=0;break}else{d=e+n|0,l=o,pe=135;break e}}while(0);t[2894]=t[2894]|4,pe=133}while(0);if((((pe|0)==133?k>>>0<2147483647:0)?(qe=xf(k|0)|0,ie=xf(0)|0,Pe=ie-qe|0,ke=Pe>>>0>(P+40|0)>>>0,!((qe|0)==(-1|0)|ke^1|qe>>>0>>0&((qe|0)!=(-1|0)&(ie|0)!=(-1|0))^1)):0)&&(d=ke?Pe:n,l=qe,pe=135),(pe|0)==135){n=(t[2891]|0)+d|0,t[2891]=n,n>>>0>(t[2892]|0)>>>0&&(t[2892]=n),y=t[2789]|0;do if(y){for(n=11580;;){if(e=t[n>>2]|0,r=n+4|0,o=t[r>>2]|0,(l|0)==(e+o|0)){pe=145;break}if(s=t[n+8>>2]|0,s)n=s;else break}if(((pe|0)==145?(t[n+12>>2]&8|0)==0:0)?y>>>0>>0&y>>>0>=e>>>0:0){t[r>>2]=o+d,_e=y+8|0,_e=(_e&7|0)==0?0:0-_e&7,pe=y+_e|0,_e=(t[2786]|0)+(d-_e)|0,t[2789]=pe,t[2786]=_e,t[pe+4>>2]=_e|1,t[pe+_e+4>>2]=40,t[2790]=t[2905];break}for(l>>>0<(t[2787]|0)>>>0&&(t[2787]=l),r=l+d|0,n=11580;;){if((t[n>>2]|0)==(r|0)){pe=153;break}if(e=t[n+8>>2]|0,e)n=e;else break}if((pe|0)==153?(t[n+12>>2]&8|0)==0:0){t[n>>2]=l,T=n+4|0,t[T>>2]=(t[T>>2]|0)+d,T=l+8|0,T=l+((T&7|0)==0?0:0-T&7)|0,n=r+8|0,n=r+((n&7|0)==0?0:0-n&7)|0,k=T+P|0,_=n-T-P|0,t[T+4>>2]=P|3;do if((n|0)!=(y|0)){if((n|0)==(t[2788]|0)){_e=(t[2785]|0)+_|0,t[2785]=_e,t[2788]=k,t[k+4>>2]=_e|1,t[k+_e>>2]=_e;break}if(e=t[n+4>>2]|0,(e&3|0)==1){d=e&-8,o=e>>>3;e:do if(e>>>0<256)if(e=t[n+8>>2]|0,r=t[n+12>>2]|0,(r|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=r,t[r+8>>2]=e;break}else{l=t[n+24>>2]|0,e=t[n+12>>2]|0;do if((e|0)==(n|0)){if(o=n+16|0,r=o+4|0,e=t[r>>2]|0,!e)if(e=t[o>>2]|0,e)r=o;else{e=0;break}for(;;){if(o=e+20|0,s=t[o>>2]|0,s|0){e=s,r=o;continue}if(o=e+16|0,s=t[o>>2]|0,s)e=s,r=o;else break}t[r>>2]=0}else _e=t[n+8>>2]|0,t[_e+12>>2]=e,t[e+8>>2]=_e;while(0);if(!l)break;r=t[n+28>>2]|0,o=11436+(r<<2)|0;do if((n|0)!=(t[o>>2]|0)){if(t[l+16+(((t[l+16>>2]|0)!=(n|0)&1)<<2)>>2]=e,!e)break e}else{if(t[o>>2]=e,e|0)break;t[2784]=t[2784]&~(1<>2]=l,r=n+16|0,o=t[r>>2]|0,o|0&&(t[e+16>>2]=o,t[o+24>>2]=e),r=t[r+4>>2]|0,!r)break;t[e+20>>2]=r,t[r+24>>2]=e}while(0);n=n+d|0,s=d+_|0}else s=_;if(n=n+4|0,t[n>>2]=t[n>>2]&-2,t[k+4>>2]=s|1,t[k+s>>2]=s,n=s>>>3,s>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=k,t[n+12>>2]=k,t[k+8>>2]=n,t[k+12>>2]=r;break}n=s>>>8;do if(!n)n=0;else{if(s>>>0>16777215){n=31;break}pe=(n+1048320|0)>>>16&8,_e=n<>>16&4,_e=_e<>>16&2,n=14-(qe|pe|n)+(_e<>>15)|0,n=s>>>(n+7|0)&1|n<<1}while(0);if(o=11436+(n<<2)|0,t[k+28>>2]=n,e=k+16|0,t[e+4>>2]=0,t[e>>2]=0,e=t[2784]|0,r=1<>2]=k,t[k+24>>2]=o,t[k+12>>2]=k,t[k+8>>2]=k;break}for(e=s<<((n|0)==31?0:25-(n>>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(s|0)){pe=194;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{pe=193;break}}if((pe|0)==193){t[o>>2]=k,t[k+24>>2]=r,t[k+12>>2]=k,t[k+8>>2]=k;break}else if((pe|0)==194){pe=r+8|0,_e=t[pe>>2]|0,t[_e+12>>2]=k,t[pe>>2]=k,t[k+8>>2]=_e,t[k+12>>2]=r,t[k+24>>2]=0;break}}else _e=(t[2786]|0)+_|0,t[2786]=_e,t[2789]=k,t[k+4>>2]=_e|1;while(0);return _e=T+8|0,h=vt,_e|0}for(n=11580;e=t[n>>2]|0,!(e>>>0<=y>>>0?(_e=e+(t[n+4>>2]|0)|0,_e>>>0>y>>>0):0);)n=t[n+8>>2]|0;s=_e+-47|0,e=s+8|0,e=s+((e&7|0)==0?0:0-e&7)|0,s=y+16|0,e=e>>>0>>0?y:e,n=e+8|0,r=l+8|0,r=(r&7|0)==0?0:0-r&7,pe=l+r|0,r=d+-40-r|0,t[2789]=pe,t[2786]=r,t[pe+4>>2]=r|1,t[pe+r+4>>2]=40,t[2790]=t[2905],r=e+4|0,t[r>>2]=27,t[n>>2]=t[2895],t[n+4>>2]=t[2896],t[n+8>>2]=t[2897],t[n+12>>2]=t[2898],t[2895]=l,t[2896]=d,t[2898]=0,t[2897]=n,n=e+24|0;do pe=n,n=n+4|0,t[n>>2]=7;while((pe+8|0)>>>0<_e>>>0);if((e|0)!=(y|0)){if(l=e-y|0,t[r>>2]=t[r>>2]&-2,t[y+4>>2]=l|1,t[e>>2]=l,n=l>>>3,l>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=y,t[n+12>>2]=y,t[y+8>>2]=n,t[y+12>>2]=r;break}if(n=l>>>8,n?l>>>0>16777215?r=31:(pe=(n+1048320|0)>>>16&8,_e=n<>>16&4,_e=_e<>>16&2,r=14-(qe|pe|r)+(_e<>>15)|0,r=l>>>(r+7|0)&1|r<<1):r=0,o=11436+(r<<2)|0,t[y+28>>2]=r,t[y+20>>2]=0,t[s>>2]=0,n=t[2784]|0,e=1<>2]=y,t[y+24>>2]=o,t[y+12>>2]=y,t[y+8>>2]=y;break}for(e=l<<((r|0)==31?0:25-(r>>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(l|0)){pe=216;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{pe=215;break}}if((pe|0)==215){t[o>>2]=y,t[y+24>>2]=r,t[y+12>>2]=y,t[y+8>>2]=y;break}else if((pe|0)==216){pe=r+8|0,_e=t[pe>>2]|0,t[_e+12>>2]=y,t[pe>>2]=y,t[y+8>>2]=_e,t[y+12>>2]=r,t[y+24>>2]=0;break}}}else{_e=t[2787]|0,(_e|0)==0|l>>>0<_e>>>0&&(t[2787]=l),t[2895]=l,t[2896]=d,t[2898]=0,t[2792]=t[2901],t[2791]=-1,n=0;do _e=11172+(n<<1<<2)|0,t[_e+12>>2]=_e,t[_e+8>>2]=_e,n=n+1|0;while((n|0)!=32);_e=l+8|0,_e=(_e&7|0)==0?0:0-_e&7,pe=l+_e|0,_e=d+-40-_e|0,t[2789]=pe,t[2786]=_e,t[pe+4>>2]=_e|1,t[pe+_e+4>>2]=40,t[2790]=t[2905]}while(0);if(n=t[2786]|0,n>>>0>P>>>0)return qe=n-P|0,t[2786]=qe,_e=t[2789]|0,pe=_e+P|0,t[2789]=pe,t[pe+4>>2]=qe|1,t[_e+4>>2]=P|3,_e=_e+8|0,h=vt,_e|0}return t[(ca()|0)>>2]=12,_e=0,h=vt,_e|0}function sh(e){e=e|0;var n=0,r=0,o=0,s=0,l=0,d=0,_=0,y=0;if(!!e){r=e+-8|0,s=t[2787]|0,e=t[e+-4>>2]|0,n=e&-8,y=r+n|0;do if(e&1)_=r,d=r;else{if(o=t[r>>2]|0,!(e&3)||(d=r+(0-o)|0,l=o+n|0,d>>>0>>0))return;if((d|0)==(t[2788]|0)){if(e=y+4|0,n=t[e>>2]|0,(n&3|0)!=3){_=d,n=l;break}t[2785]=l,t[e>>2]=n&-2,t[d+4>>2]=l|1,t[d+l>>2]=l;return}if(r=o>>>3,o>>>0<256)if(e=t[d+8>>2]|0,n=t[d+12>>2]|0,(n|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=n,t[n+8>>2]=e,_=d,n=l;break}s=t[d+24>>2]|0,e=t[d+12>>2]|0;do if((e|0)==(d|0)){if(r=d+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{e=0;break}for(;;){if(r=e+20|0,o=t[r>>2]|0,o|0){e=o,n=r;continue}if(r=e+16|0,o=t[r>>2]|0,o)e=o,n=r;else break}t[n>>2]=0}else _=t[d+8>>2]|0,t[_+12>>2]=e,t[e+8>>2]=_;while(0);if(s){if(n=t[d+28>>2]|0,r=11436+(n<<2)|0,(d|0)==(t[r>>2]|0)){if(t[r>>2]=e,!e){t[2784]=t[2784]&~(1<>2]|0)!=(d|0)&1)<<2)>>2]=e,!e){_=d,n=l;break}t[e+24>>2]=s,n=d+16|0,r=t[n>>2]|0,r|0&&(t[e+16>>2]=r,t[r+24>>2]=e),n=t[n+4>>2]|0,n?(t[e+20>>2]=n,t[n+24>>2]=e,_=d,n=l):(_=d,n=l)}else _=d,n=l}while(0);if(!(d>>>0>=y>>>0)&&(e=y+4|0,o=t[e>>2]|0,!!(o&1))){if(o&2)t[e>>2]=o&-2,t[_+4>>2]=n|1,t[d+n>>2]=n,s=n;else{if(e=t[2788]|0,(y|0)==(t[2789]|0)){if(y=(t[2786]|0)+n|0,t[2786]=y,t[2789]=_,t[_+4>>2]=y|1,(_|0)!=(e|0))return;t[2788]=0,t[2785]=0;return}if((y|0)==(e|0)){y=(t[2785]|0)+n|0,t[2785]=y,t[2788]=d,t[_+4>>2]=y|1,t[d+y>>2]=y;return}s=(o&-8)+n|0,r=o>>>3;do if(o>>>0<256)if(n=t[y+8>>2]|0,e=t[y+12>>2]|0,(e|0)==(n|0)){t[2783]=t[2783]&~(1<>2]=e,t[e+8>>2]=n;break}else{l=t[y+24>>2]|0,e=t[y+12>>2]|0;do if((e|0)==(y|0)){if(r=y+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{r=0;break}for(;;){if(r=e+20|0,o=t[r>>2]|0,o|0){e=o,n=r;continue}if(r=e+16|0,o=t[r>>2]|0,o)e=o,n=r;else break}t[n>>2]=0,r=e}else r=t[y+8>>2]|0,t[r+12>>2]=e,t[e+8>>2]=r,r=e;while(0);if(l|0){if(e=t[y+28>>2]|0,n=11436+(e<<2)|0,(y|0)==(t[n>>2]|0)){if(t[n>>2]=r,!r){t[2784]=t[2784]&~(1<>2]|0)!=(y|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=l,e=y+16|0,n=t[e>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),e=t[e+4>>2]|0,e|0&&(t[r+20>>2]=e,t[e+24>>2]=r)}}while(0);if(t[_+4>>2]=s|1,t[d+s>>2]=s,(_|0)==(t[2788]|0)){t[2785]=s;return}}if(e=s>>>3,s>>>0<256){r=11172+(e<<1<<2)|0,n=t[2783]|0,e=1<>2]|0):(t[2783]=n|e,e=r,n=r+8|0),t[n>>2]=_,t[e+12>>2]=_,t[_+8>>2]=e,t[_+12>>2]=r;return}e=s>>>8,e?s>>>0>16777215?e=31:(d=(e+1048320|0)>>>16&8,y=e<>>16&4,y=y<>>16&2,e=14-(l|d|e)+(y<>>15)|0,e=s>>>(e+7|0)&1|e<<1):e=0,o=11436+(e<<2)|0,t[_+28>>2]=e,t[_+20>>2]=0,t[_+16>>2]=0,n=t[2784]|0,r=1<>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(s|0)){e=73;break}if(o=r+16+(n>>>31<<2)|0,e=t[o>>2]|0,e)n=n<<1,r=e;else{e=72;break}}if((e|0)==72){t[o>>2]=_,t[_+24>>2]=r,t[_+12>>2]=_,t[_+8>>2]=_;break}else if((e|0)==73){d=r+8|0,y=t[d>>2]|0,t[y+12>>2]=_,t[d>>2]=_,t[_+8>>2]=y,t[_+12>>2]=r,t[_+24>>2]=0;break}}else t[2784]=n|r,t[o>>2]=_,t[_+24>>2]=o,t[_+12>>2]=_,t[_+8>>2]=_;while(0);if(y=(t[2791]|0)+-1|0,t[2791]=y,!y)e=11588;else return;for(;e=t[e>>2]|0,e;)e=e+8|0;t[2791]=-1}}}function rL(){return 11628}function iL(e){e=e|0;var n=0,r=0;return n=h,h=h+16|0,r=n,t[r>>2]=sL(t[e+60>>2]|0)|0,e=lh(Ms(6,r|0)|0)|0,h=n,e|0}function j8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0;P=h,h=h+48|0,k=P+16|0,l=P,s=P+32|0,_=e+28|0,o=t[_>>2]|0,t[s>>2]=o,y=e+20|0,o=(t[y>>2]|0)-o|0,t[s+4>>2]=o,t[s+8>>2]=n,t[s+12>>2]=r,o=o+r|0,d=e+60|0,t[l>>2]=t[d>>2],t[l+4>>2]=s,t[l+8>>2]=2,l=lh(G0(146,l|0)|0)|0;e:do if((o|0)!=(l|0)){for(n=2;!((l|0)<0);)if(o=o-l|0,we=t[s+4>>2]|0,q=l>>>0>we>>>0,s=q?s+8|0:s,n=(q<<31>>31)+n|0,we=l-(q?we:0)|0,t[s>>2]=(t[s>>2]|0)+we,q=s+4|0,t[q>>2]=(t[q>>2]|0)-we,t[k>>2]=t[d>>2],t[k+4>>2]=s,t[k+8>>2]=n,l=lh(G0(146,k|0)|0)|0,(o|0)==(l|0)){T=3;break e}t[e+16>>2]=0,t[_>>2]=0,t[y>>2]=0,t[e>>2]=t[e>>2]|32,(n|0)==2?r=0:r=r-(t[s+4>>2]|0)|0}else T=3;while(0);return(T|0)==3&&(we=t[e+44>>2]|0,t[e+16>>2]=we+(t[e+48>>2]|0),t[_>>2]=we,t[y>>2]=we),h=P,r|0}function oL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;return s=h,h=h+32|0,l=s,o=s+20|0,t[l>>2]=t[e+60>>2],t[l+4>>2]=0,t[l+8>>2]=n,t[l+12>>2]=o,t[l+16>>2]=r,(lh(Uu(140,l|0)|0)|0)<0?(t[o>>2]=-1,e=-1):e=t[o>>2]|0,h=s,e|0}function lh(e){return e=e|0,e>>>0>4294963200&&(t[(ca()|0)>>2]=0-e,e=-1),e|0}function ca(){return(uL()|0)+64|0}function uL(){return b4()|0}function b4(){return 2084}function sL(e){return e=e|0,e|0}function lL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;return s=h,h=h+32|0,o=s,t[e+36>>2]=1,((t[e>>2]&64|0)==0?(t[o>>2]=t[e+60>>2],t[o+4>>2]=21523,t[o+8>>2]=s+16,su(54,o|0)|0):0)&&(c[e+75>>0]=-1),o=j8(e,n,r)|0,h=s,o|0}function U8(e,n){e=e|0,n=n|0;var r=0,o=0;if(r=c[e>>0]|0,o=c[n>>0]|0,r<<24>>24==0?1:r<<24>>24!=o<<24>>24)e=o;else{do e=e+1|0,n=n+1|0,r=c[e>>0]|0,o=c[n>>0]|0;while(!(r<<24>>24==0?1:r<<24>>24!=o<<24>>24));e=o}return(r&255)-(e&255)|0}function fL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0;e:do if(!r)e=0;else{for(;o=c[e>>0]|0,s=c[n>>0]|0,o<<24>>24==s<<24>>24;)if(r=r+-1|0,r)e=e+1|0,n=n+1|0;else{e=0;break e}e=(o&255)-(s&255)|0}while(0);return e|0}function q8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0;ie=h,h=h+224|0,T=ie+120|0,P=ie+80|0,we=ie,le=ie+136|0,o=P,s=o+40|0;do t[o>>2]=0,o=o+4|0;while((o|0)<(s|0));return t[T>>2]=t[r>>2],(G4(0,n,T,we,P)|0)<0?r=-1:((t[e+76>>2]|0)>-1?q=cL(e)|0:q=0,r=t[e>>2]|0,k=r&32,(c[e+74>>0]|0)<1&&(t[e>>2]=r&-33),o=e+48|0,t[o>>2]|0?r=G4(e,n,T,we,P)|0:(s=e+44|0,l=t[s>>2]|0,t[s>>2]=le,d=e+28|0,t[d>>2]=le,_=e+20|0,t[_>>2]=le,t[o>>2]=80,y=e+16|0,t[y>>2]=le+80,r=G4(e,n,T,we,P)|0,l&&(dh[t[e+36>>2]&7](e,0,0)|0,r=(t[_>>2]|0)==0?-1:r,t[s>>2]=l,t[o>>2]=0,t[y>>2]=0,t[d>>2]=0,t[_>>2]=0)),o=t[e>>2]|0,t[e>>2]=o|k,q|0&&aL(e),r=(o&32|0)==0?r:-1),h=ie,r|0}function G4(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0,qe=0,pe=0,_e=0,vt=0,Ln=0,Ht=0,It=0,gn=0,Pn=0,zt=0;zt=h,h=h+64|0,Ht=zt+16|0,It=zt,vt=zt+24|0,gn=zt+8|0,Pn=zt+20|0,t[Ht>>2]=n,qe=(e|0)!=0,pe=vt+40|0,_e=pe,vt=vt+39|0,Ln=gn+4|0,d=0,l=0,T=0;e:for(;;){do if((l|0)>-1)if((d|0)>(2147483647-l|0)){t[(ca()|0)>>2]=75,l=-1;break}else{l=d+l|0;break}while(0);if(d=c[n>>0]|0,d<<24>>24)_=n;else{ke=87;break}t:for(;;){switch(d<<24>>24){case 37:{d=_,ke=9;break t}case 0:{d=_;break t}default:}Pe=_+1|0,t[Ht>>2]=Pe,d=c[Pe>>0]|0,_=Pe}t:do if((ke|0)==9)for(;;){if(ke=0,(c[_+1>>0]|0)!=37)break t;if(d=d+1|0,_=_+2|0,t[Ht>>2]=_,(c[_>>0]|0)==37)ke=9;else break}while(0);if(d=d-n|0,qe&&ri(e,n,d),d|0){n=_;continue}y=_+1|0,d=(c[y>>0]|0)+-48|0,d>>>0<10?(Pe=(c[_+2>>0]|0)==36,ie=Pe?d:-1,T=Pe?1:T,y=Pe?_+3|0:y):ie=-1,t[Ht>>2]=y,d=c[y>>0]|0,_=(d<<24>>24)+-32|0;t:do if(_>>>0<32)for(k=0,P=d;;){if(d=1<<_,!(d&75913)){d=P;break t}if(k=d|k,y=y+1|0,t[Ht>>2]=y,d=c[y>>0]|0,_=(d<<24>>24)+-32|0,_>>>0>=32)break;P=d}else k=0;while(0);if(d<<24>>24==42){if(_=y+1|0,d=(c[_>>0]|0)+-48|0,d>>>0<10?(c[y+2>>0]|0)==36:0)t[s+(d<<2)>>2]=10,d=t[o+((c[_>>0]|0)+-48<<3)>>2]|0,T=1,y=y+3|0;else{if(T|0){l=-1;break}qe?(T=(t[r>>2]|0)+(4-1)&~(4-1),d=t[T>>2]|0,t[r>>2]=T+4,T=0,y=_):(d=0,T=0,y=_)}t[Ht>>2]=y,Pe=(d|0)<0,d=Pe?0-d|0:d,k=Pe?k|8192:k}else{if(d=z8(Ht)|0,(d|0)<0){l=-1;break}y=t[Ht>>2]|0}do if((c[y>>0]|0)==46){if((c[y+1>>0]|0)!=42){t[Ht>>2]=y+1,_=z8(Ht)|0,y=t[Ht>>2]|0;break}if(P=y+2|0,_=(c[P>>0]|0)+-48|0,_>>>0<10?(c[y+3>>0]|0)==36:0){t[s+(_<<2)>>2]=10,_=t[o+((c[P>>0]|0)+-48<<3)>>2]|0,y=y+4|0,t[Ht>>2]=y;break}if(T|0){l=-1;break e}qe?(Pe=(t[r>>2]|0)+(4-1)&~(4-1),_=t[Pe>>2]|0,t[r>>2]=Pe+4):_=0,t[Ht>>2]=P,y=P}else _=-1;while(0);for(le=0;;){if(((c[y>>0]|0)+-65|0)>>>0>57){l=-1;break e}if(Pe=y+1|0,t[Ht>>2]=Pe,P=c[(c[y>>0]|0)+-65+(5178+(le*58|0))>>0]|0,q=P&255,(q+-1|0)>>>0<8)le=q,y=Pe;else break}if(!(P<<24>>24)){l=-1;break}we=(ie|0)>-1;do if(P<<24>>24==19)if(we){l=-1;break e}else ke=49;else{if(we){t[s+(ie<<2)>>2]=q,we=o+(ie<<3)|0,ie=t[we+4>>2]|0,ke=It,t[ke>>2]=t[we>>2],t[ke+4>>2]=ie,ke=49;break}if(!qe){l=0;break e}W8(It,q,r)}while(0);if((ke|0)==49?(ke=0,!qe):0){d=0,n=Pe;continue}y=c[y>>0]|0,y=(le|0)!=0&(y&15|0)==3?y&-33:y,we=k&-65537,ie=(k&8192|0)==0?k:we;t:do switch(y|0){case 110:switch((le&255)<<24>>24){case 0:{t[t[It>>2]>>2]=l,d=0,n=Pe;continue e}case 1:{t[t[It>>2]>>2]=l,d=0,n=Pe;continue e}case 2:{d=t[It>>2]|0,t[d>>2]=l,t[d+4>>2]=((l|0)<0)<<31>>31,d=0,n=Pe;continue e}case 3:{g[t[It>>2]>>1]=l,d=0,n=Pe;continue e}case 4:{c[t[It>>2]>>0]=l,d=0,n=Pe;continue e}case 6:{t[t[It>>2]>>2]=l,d=0,n=Pe;continue e}case 7:{d=t[It>>2]|0,t[d>>2]=l,t[d+4>>2]=((l|0)<0)<<31>>31,d=0,n=Pe;continue e}default:{d=0,n=Pe;continue e}}case 112:{y=120,_=_>>>0>8?_:8,n=ie|8,ke=61;break}case 88:case 120:{n=ie,ke=61;break}case 111:{y=It,n=t[y>>2]|0,y=t[y+4>>2]|0,q=pL(n,y,pe)|0,we=_e-q|0,k=0,P=5642,_=(ie&8|0)==0|(_|0)>(we|0)?_:we+1|0,we=ie,ke=67;break}case 105:case 100:if(y=It,n=t[y>>2]|0,y=t[y+4>>2]|0,(y|0)<0){n=fh(0,0,n|0,y|0)|0,y=be,k=It,t[k>>2]=n,t[k+4>>2]=y,k=1,P=5642,ke=66;break t}else{k=(ie&2049|0)!=0&1,P=(ie&2048|0)==0?(ie&1|0)==0?5642:5644:5643,ke=66;break t}case 117:{y=It,k=0,P=5642,n=t[y>>2]|0,y=t[y+4>>2]|0,ke=66;break}case 99:{c[vt>>0]=t[It>>2],n=vt,k=0,P=5642,q=pe,y=1,_=we;break}case 109:{y=hL(t[(ca()|0)>>2]|0)|0,ke=71;break}case 115:{y=t[It>>2]|0,y=y|0?y:5652,ke=71;break}case 67:{t[gn>>2]=t[It>>2],t[Ln>>2]=0,t[It>>2]=gn,q=-1,y=gn,ke=75;break}case 83:{n=t[It>>2]|0,_?(q=_,y=n,ke=75):(wi(e,32,d,0,ie),n=0,ke=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{d=vL(e,+L[It>>3],d,_,ie,y)|0,n=Pe;continue e}default:k=0,P=5642,q=pe,y=_,_=ie}while(0);t:do if((ke|0)==61)ie=It,le=t[ie>>2]|0,ie=t[ie+4>>2]|0,q=dL(le,ie,pe,y&32)|0,P=(n&8|0)==0|(le|0)==0&(ie|0)==0,k=P?0:2,P=P?5642:5642+(y>>4)|0,we=n,n=le,y=ie,ke=67;else if((ke|0)==66)q=aa(n,y,pe)|0,we=ie,ke=67;else if((ke|0)==71)ke=0,ie=mL(y,0,_)|0,le=(ie|0)==0,n=y,k=0,P=5642,q=le?y+_|0:ie,y=le?_:ie-y|0,_=we;else if((ke|0)==75){for(ke=0,P=y,n=0,_=0;k=t[P>>2]|0,!(!k||(_=H8(Pn,k)|0,(_|0)<0|_>>>0>(q-n|0)>>>0));)if(n=_+n|0,q>>>0>n>>>0)P=P+4|0;else break;if((_|0)<0){l=-1;break e}if(wi(e,32,d,n,ie),!n)n=0,ke=84;else for(k=0;;){if(_=t[y>>2]|0,!_){ke=84;break t}if(_=H8(Pn,_)|0,k=_+k|0,(k|0)>(n|0)){ke=84;break t}if(ri(e,Pn,_),k>>>0>=n>>>0){ke=84;break}else y=y+4|0}}while(0);if((ke|0)==67)ke=0,y=(n|0)!=0|(y|0)!=0,ie=(_|0)!=0|y,y=((y^1)&1)+(_e-q)|0,n=ie?q:pe,q=pe,y=ie?(_|0)>(y|0)?_:y:_,_=(_|0)>-1?we&-65537:we;else if((ke|0)==84){ke=0,wi(e,32,d,n,ie^8192),d=(d|0)>(n|0)?d:n,n=Pe;continue}le=q-n|0,we=(y|0)<(le|0)?le:y,ie=we+k|0,d=(d|0)<(ie|0)?ie:d,wi(e,32,d,ie,_),ri(e,P,k),wi(e,48,d,ie,_^65536),wi(e,48,we,le,0),ri(e,n,le),wi(e,32,d,ie,_^8192),n=Pe}e:do if((ke|0)==87&&!e)if(!T)l=0;else{for(l=1;n=t[s+(l<<2)>>2]|0,!!n;)if(W8(o+(l<<3)|0,n,r),l=l+1|0,(l|0)>=10){l=1;break e}for(;;){if(t[s+(l<<2)>>2]|0){l=-1;break e}if(l=l+1|0,(l|0)>=10){l=1;break}}}while(0);return h=zt,l|0}function cL(e){return e=e|0,0}function aL(e){e=e|0}function ri(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]&32||TL(n,r,e)|0}function z8(e){e=e|0;var n=0,r=0,o=0;if(r=t[e>>2]|0,o=(c[r>>0]|0)+-48|0,o>>>0<10){n=0;do n=o+(n*10|0)|0,r=r+1|0,t[e>>2]=r,o=(c[r>>0]|0)+-48|0;while(o>>>0<10)}else n=0;return n|0}function W8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;e:do if(n>>>0<=20)do switch(n|0){case 9:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,t[e>>2]=n;break e}case 10:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,o=e,t[o>>2]=n,t[o+4>>2]=((n|0)<0)<<31>>31;break e}case 11:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,o=e,t[o>>2]=n,t[o+4>>2]=0;break e}case 12:{o=(t[r>>2]|0)+(8-1)&~(8-1),n=o,s=t[n>>2]|0,n=t[n+4>>2]|0,t[r>>2]=o+8,o=e,t[o>>2]=s,t[o+4>>2]=n;break e}case 13:{s=(t[r>>2]|0)+(4-1)&~(4-1),o=t[s>>2]|0,t[r>>2]=s+4,o=(o&65535)<<16>>16,s=e,t[s>>2]=o,t[s+4>>2]=((o|0)<0)<<31>>31;break e}case 14:{s=(t[r>>2]|0)+(4-1)&~(4-1),o=t[s>>2]|0,t[r>>2]=s+4,s=e,t[s>>2]=o&65535,t[s+4>>2]=0;break e}case 15:{s=(t[r>>2]|0)+(4-1)&~(4-1),o=t[s>>2]|0,t[r>>2]=s+4,o=(o&255)<<24>>24,s=e,t[s>>2]=o,t[s+4>>2]=((o|0)<0)<<31>>31;break e}case 16:{s=(t[r>>2]|0)+(4-1)&~(4-1),o=t[s>>2]|0,t[r>>2]=s+4,s=e,t[s>>2]=o&255,t[s+4>>2]=0;break e}case 17:{s=(t[r>>2]|0)+(8-1)&~(8-1),l=+L[s>>3],t[r>>2]=s+8,L[e>>3]=l;break e}case 18:{s=(t[r>>2]|0)+(8-1)&~(8-1),l=+L[s>>3],t[r>>2]=s+8,L[e>>3]=l;break e}default:break e}while(0);while(0)}function dL(e,n,r,o){if(e=e|0,n=n|0,r=r|0,o=o|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,c[r>>0]=C[5694+(e&15)>>0]|0|o,e=ch(e|0,n|0,4)|0,n=be;while(!((e|0)==0&(n|0)==0));return r|0}function pL(e,n,r){if(e=e|0,n=n|0,r=r|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,c[r>>0]=e&7|48,e=ch(e|0,n|0,3)|0,n=be;while(!((e|0)==0&(n|0)==0));return r|0}function aa(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;if(n>>>0>0|(n|0)==0&e>>>0>4294967295){for(;o=K4(e|0,n|0,10,0)|0,r=r+-1|0,c[r>>0]=o&255|48,o=e,e=$4(e|0,n|0,10,0)|0,n>>>0>9|(n|0)==9&o>>>0>4294967295;)n=be;n=e}else n=e;if(n)for(;r=r+-1|0,c[r>>0]=(n>>>0)%10|0|48,!(n>>>0<10);)n=(n>>>0)/10|0;return r|0}function hL(e){return e=e|0,DL(e,t[(wL()|0)+188>>2]|0)|0}function mL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;l=n&255,o=(r|0)!=0;e:do if(o&(e&3|0)!=0)for(s=n&255;;){if((c[e>>0]|0)==s<<24>>24){d=6;break e}if(e=e+1|0,r=r+-1|0,o=(r|0)!=0,!(o&(e&3|0)!=0)){d=5;break}}else d=5;while(0);(d|0)==5&&(o?d=6:r=0);e:do if((d|0)==6&&(s=n&255,(c[e>>0]|0)!=s<<24>>24)){o=Un(l,16843009)|0;t:do if(r>>>0>3){for(;l=t[e>>2]^o,!((l&-2139062144^-2139062144)&l+-16843009|0);)if(e=e+4|0,r=r+-4|0,r>>>0<=3){d=11;break t}}else d=11;while(0);if((d|0)==11&&!r){r=0;break}for(;;){if((c[e>>0]|0)==s<<24>>24)break e;if(e=e+1|0,r=r+-1|0,!r){r=0;break}}}while(0);return(r|0?e:0)|0}function wi(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0;if(d=h,h=h+256|0,l=d,(r|0)>(o|0)&(s&73728|0)==0){if(s=r-o|0,pa(l|0,n|0,(s>>>0<256?s:256)|0)|0,s>>>0>255){n=r-o|0;do ri(e,l,256),s=s+-256|0;while(s>>>0>255);s=n&255}ri(e,l,s)}h=d}function H8(e,n){return e=e|0,n=n|0,e?e=_L(e,n,0)|0:e=0,e|0}function vL(e,n,r,o,s,l){e=e|0,n=+n,r=r|0,o=o|0,s=s|0,l=l|0;var d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0,ie=0,Pe=0,ke=0,qe=0,pe=0,_e=0,vt=0,Ln=0,Ht=0,It=0,gn=0,Pn=0,zt=0,Dr=0;Dr=h,h=h+560|0,y=Dr+8|0,Pe=Dr,zt=Dr+524|0,Pn=zt,k=Dr+512|0,t[Pe>>2]=0,gn=k+12|0,b8(n)|0,(be|0)<0?(n=-n,Ht=1,Ln=5659):(Ht=(s&2049|0)!=0&1,Ln=(s&2048|0)==0?(s&1|0)==0?5660:5665:5662),b8(n)|0,It=be&2146435072;do if(It>>>0<2146435072|(It|0)==2146435072&0<0){if(we=+gL(n,Pe)*2,d=we!=0,d&&(t[Pe>>2]=(t[Pe>>2]|0)+-1),qe=l|32,(qe|0)==97){le=l&32,q=(le|0)==0?Ln:Ln+9|0,P=Ht|2,d=12-o|0;do if(o>>>0>11|(d|0)==0)n=we;else{n=8;do d=d+-1|0,n=n*16;while((d|0)!=0);if((c[q>>0]|0)==45){n=-(n+(-we-n));break}else{n=we+n-n;break}}while(0);_=t[Pe>>2]|0,d=(_|0)<0?0-_|0:_,d=aa(d,((d|0)<0)<<31>>31,gn)|0,(d|0)==(gn|0)&&(d=k+11|0,c[d>>0]=48),c[d+-1>>0]=(_>>31&2)+43,T=d+-2|0,c[T>>0]=l+15,k=(o|0)<1,y=(s&8|0)==0,d=zt;do It=~~n,_=d+1|0,c[d>>0]=C[5694+It>>0]|le,n=(n-+(It|0))*16,((_-Pn|0)==1?!(y&(k&n==0)):0)?(c[_>>0]=46,d=d+2|0):d=_;while(n!=0);It=d-Pn|0,Pn=gn-T|0,gn=(o|0)!=0&(It+-2|0)<(o|0)?o+2|0:It,d=Pn+P+gn|0,wi(e,32,r,d,s),ri(e,q,P),wi(e,48,r,d,s^65536),ri(e,zt,It),wi(e,48,gn-It|0,0,0),ri(e,T,Pn),wi(e,32,r,d,s^8192);break}_=(o|0)<0?6:o,d?(d=(t[Pe>>2]|0)+-28|0,t[Pe>>2]=d,n=we*268435456):(n=we,d=t[Pe>>2]|0),It=(d|0)<0?y:y+288|0,y=It;do _e=~~n>>>0,t[y>>2]=_e,y=y+4|0,n=(n-+(_e>>>0))*1e9;while(n!=0);if((d|0)>0)for(k=It,P=y;;){if(T=(d|0)<29?d:29,d=P+-4|0,d>>>0>=k>>>0){y=0;do pe=X8(t[d>>2]|0,0,T|0)|0,pe=Y4(pe|0,be|0,y|0,0)|0,_e=be,ke=K4(pe|0,_e|0,1e9,0)|0,t[d>>2]=ke,y=$4(pe|0,_e|0,1e9,0)|0,d=d+-4|0;while(d>>>0>=k>>>0);y&&(k=k+-4|0,t[k>>2]=y)}for(y=P;!(y>>>0<=k>>>0);)if(d=y+-4|0,!(t[d>>2]|0))y=d;else break;if(d=(t[Pe>>2]|0)-T|0,t[Pe>>2]=d,(d|0)>0)P=y;else break}else k=It;if((d|0)<0){o=((_+25|0)/9|0)+1|0,ie=(qe|0)==102;do{if(le=0-d|0,le=(le|0)<9?le:9,k>>>0>>0){T=(1<>>le,q=0,d=k;do _e=t[d>>2]|0,t[d>>2]=(_e>>>le)+q,q=Un(_e&T,P)|0,d=d+4|0;while(d>>>0>>0);d=(t[k>>2]|0)==0?k+4|0:k,q?(t[y>>2]=q,k=d,d=y+4|0):(k=d,d=y)}else k=(t[k>>2]|0)==0?k+4|0:k,d=y;y=ie?It:k,y=(d-y>>2|0)>(o|0)?y+(o<<2)|0:d,d=(t[Pe>>2]|0)+le|0,t[Pe>>2]=d}while((d|0)<0);d=k,o=y}else d=k,o=y;if(_e=It,d>>>0>>0){if(y=(_e-d>>2)*9|0,T=t[d>>2]|0,T>>>0>=10){k=10;do k=k*10|0,y=y+1|0;while(T>>>0>=k>>>0)}}else y=0;if(ie=(qe|0)==103,ke=(_|0)!=0,k=_-((qe|0)!=102?y:0)+((ke&ie)<<31>>31)|0,(k|0)<(((o-_e>>2)*9|0)+-9|0)){if(k=k+9216|0,le=It+4+(((k|0)/9|0)+-1024<<2)|0,k=((k|0)%9|0)+1|0,(k|0)<9){T=10;do T=T*10|0,k=k+1|0;while((k|0)!=9)}else T=10;if(P=t[le>>2]|0,q=(P>>>0)%(T>>>0)|0,k=(le+4|0)==(o|0),k&(q|0)==0)k=le;else if(we=(((P>>>0)/(T>>>0)|0)&1|0)==0?9007199254740992:9007199254740994,pe=(T|0)/2|0,n=q>>>0>>0?.5:k&(q|0)==(pe|0)?1:1.5,Ht&&(pe=(c[Ln>>0]|0)==45,n=pe?-n:n,we=pe?-we:we),k=P-q|0,t[le>>2]=k,we+n!=we){if(pe=k+T|0,t[le>>2]=pe,pe>>>0>999999999)for(y=le;k=y+-4|0,t[y>>2]=0,k>>>0>>0&&(d=d+-4|0,t[d>>2]=0),pe=(t[k>>2]|0)+1|0,t[k>>2]=pe,pe>>>0>999999999;)y=k;else k=le;if(y=(_e-d>>2)*9|0,P=t[d>>2]|0,P>>>0>=10){T=10;do T=T*10|0,y=y+1|0;while(P>>>0>=T>>>0)}}else k=le;k=k+4|0,k=o>>>0>k>>>0?k:o,pe=d}else k=o,pe=d;for(qe=k;;){if(qe>>>0<=pe>>>0){Pe=0;break}if(d=qe+-4|0,!(t[d>>2]|0))qe=d;else{Pe=1;break}}o=0-y|0;do if(ie)if(d=((ke^1)&1)+_|0,(d|0)>(y|0)&(y|0)>-5?(T=l+-1|0,_=d+-1-y|0):(T=l+-2|0,_=d+-1|0),d=s&8,d)le=d;else{if(Pe?(vt=t[qe+-4>>2]|0,(vt|0)!=0):0)if((vt>>>0)%10|0)k=0;else{k=0,d=10;do d=d*10|0,k=k+1|0;while(!((vt>>>0)%(d>>>0)|0|0))}else k=9;if(d=((qe-_e>>2)*9|0)+-9|0,(T|32|0)==102){le=d-k|0,le=(le|0)>0?le:0,_=(_|0)<(le|0)?_:le,le=0;break}else{le=d+y-k|0,le=(le|0)>0?le:0,_=(_|0)<(le|0)?_:le,le=0;break}}else T=l,le=s&8;while(0);if(ie=_|le,P=(ie|0)!=0&1,q=(T|32|0)==102,q)ke=0,d=(y|0)>0?y:0;else{if(d=(y|0)<0?o:y,d=aa(d,((d|0)<0)<<31>>31,gn)|0,k=gn,(k-d|0)<2)do d=d+-1|0,c[d>>0]=48;while((k-d|0)<2);c[d+-1>>0]=(y>>31&2)+43,d=d+-2|0,c[d>>0]=T,ke=d,d=k-d|0}if(d=Ht+1+_+P+d|0,wi(e,32,r,d,s),ri(e,Ln,Ht),wi(e,48,r,d,s^65536),q){T=pe>>>0>It>>>0?It:pe,le=zt+9|0,P=le,q=zt+8|0,k=T;do{if(y=aa(t[k>>2]|0,0,le)|0,(k|0)==(T|0))(y|0)==(le|0)&&(c[q>>0]=48,y=q);else if(y>>>0>zt>>>0){pa(zt|0,48,y-Pn|0)|0;do y=y+-1|0;while(y>>>0>zt>>>0)}ri(e,y,P-y|0),k=k+4|0}while(k>>>0<=It>>>0);if(ie|0&&ri(e,5710,1),k>>>0>>0&(_|0)>0)for(;;){if(y=aa(t[k>>2]|0,0,le)|0,y>>>0>zt>>>0){pa(zt|0,48,y-Pn|0)|0;do y=y+-1|0;while(y>>>0>zt>>>0)}if(ri(e,y,(_|0)<9?_:9),k=k+4|0,y=_+-9|0,k>>>0>>0&(_|0)>9)_=y;else{_=y;break}}wi(e,48,_+9|0,9,0)}else{if(ie=Pe?qe:pe+4|0,(_|0)>-1){Pe=zt+9|0,le=(le|0)==0,o=Pe,P=0-Pn|0,q=zt+8|0,T=pe;do{y=aa(t[T>>2]|0,0,Pe)|0,(y|0)==(Pe|0)&&(c[q>>0]=48,y=q);do if((T|0)==(pe|0)){if(k=y+1|0,ri(e,y,1),le&(_|0)<1){y=k;break}ri(e,5710,1),y=k}else{if(y>>>0<=zt>>>0)break;pa(zt|0,48,y+P|0)|0;do y=y+-1|0;while(y>>>0>zt>>>0)}while(0);Pn=o-y|0,ri(e,y,(_|0)>(Pn|0)?Pn:_),_=_-Pn|0,T=T+4|0}while(T>>>0>>0&(_|0)>-1)}wi(e,48,_+18|0,18,0),ri(e,ke,gn-ke|0)}wi(e,32,r,d,s^8192)}else zt=(l&32|0)!=0,d=Ht+3|0,wi(e,32,r,d,s&-65537),ri(e,Ln,Ht),ri(e,n!=n|!1?zt?5686:5690:zt?5678:5682,3),wi(e,32,r,d,s^8192);while(0);return h=Dr,((d|0)<(r|0)?r:d)|0}function b8(e){e=+e;var n=0;return L[j>>3]=e,n=t[j>>2]|0,be=t[j+4>>2]|0,n|0}function gL(e,n){return e=+e,n=n|0,+ +G8(e,n)}function G8(e,n){e=+e,n=n|0;var r=0,o=0,s=0;switch(L[j>>3]=e,r=t[j>>2]|0,o=t[j+4>>2]|0,s=ch(r|0,o|0,52)|0,s&2047){case 0:{e!=0?(e=+G8(e*18446744073709552e3,n),r=(t[n>>2]|0)+-64|0):r=0,t[n>>2]=r;break}case 2047:break;default:t[n>>2]=(s&2047)+-1022,t[j>>2]=r,t[j+4>>2]=o&-2146435073|1071644672,e=+L[j>>3]}return+e}function _L(e,n,r){e=e|0,n=n|0,r=r|0;do if(e){if(n>>>0<128){c[e>>0]=n,e=1;break}if(!(t[t[(yL()|0)+188>>2]>>2]|0))if((n&-128|0)==57216){c[e>>0]=n,e=1;break}else{t[(ca()|0)>>2]=84,e=-1;break}if(n>>>0<2048){c[e>>0]=n>>>6|192,c[e+1>>0]=n&63|128,e=2;break}if(n>>>0<55296|(n&-8192|0)==57344){c[e>>0]=n>>>12|224,c[e+1>>0]=n>>>6&63|128,c[e+2>>0]=n&63|128,e=3;break}if((n+-65536|0)>>>0<1048576){c[e>>0]=n>>>18|240,c[e+1>>0]=n>>>12&63|128,c[e+2>>0]=n>>>6&63|128,c[e+3>>0]=n&63|128,e=4;break}else{t[(ca()|0)>>2]=84,e=-1;break}}else e=1;while(0);return e|0}function yL(){return b4()|0}function wL(){return b4()|0}function DL(e,n){e=e|0,n=n|0;var r=0,o=0;for(o=0;;){if((C[5712+o>>0]|0)==(e|0)){e=2;break}if(r=o+1|0,(r|0)==87){r=5800,o=87,e=5;break}else o=r}if((e|0)==2&&(o?(r=5800,e=5):r=5800),(e|0)==5)for(;;){do e=r,r=r+1|0;while((c[e>>0]|0)!=0);if(o=o+-1|0,o)e=5;else break}return EL(r,t[n+20>>2]|0)|0}function EL(e,n){return e=e|0,n=n|0,SL(e,n)|0}function SL(e,n){return e=e|0,n=n|0,n?n=CL(t[n>>2]|0,t[n+4>>2]|0,e)|0:n=0,(n|0?n:e)|0}function CL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0;q=(t[e>>2]|0)+1794895138|0,l=fc(t[e+8>>2]|0,q)|0,o=fc(t[e+12>>2]|0,q)|0,s=fc(t[e+16>>2]|0,q)|0;e:do if((l>>>0>>2>>>0?(P=n-(l<<2)|0,o>>>0

>>0&s>>>0

>>0):0)?((s|o)&3|0)==0:0){for(P=o>>>2,T=s>>>2,k=0;;){if(_=l>>>1,y=k+_|0,d=y<<1,s=d+P|0,o=fc(t[e+(s<<2)>>2]|0,q)|0,s=fc(t[e+(s+1<<2)>>2]|0,q)|0,!(s>>>0>>0&o>>>0<(n-s|0)>>>0)){o=0;break e}if(c[e+(s+o)>>0]|0){o=0;break e}if(o=U8(r,e+s|0)|0,!o)break;if(o=(o|0)<0,(l|0)==1){o=0;break e}else k=o?k:y,l=o?_:l-_|0}o=d+T|0,s=fc(t[e+(o<<2)>>2]|0,q)|0,o=fc(t[e+(o+1<<2)>>2]|0,q)|0,o>>>0>>0&s>>>0<(n-o|0)>>>0?o=(c[e+(o+s)>>0]|0)==0?e+o|0:0:o=0}else o=0;while(0);return o|0}function fc(e,n){e=e|0,n=n|0;var r=0;return r=Z8(e|0)|0,((n|0)==0?e:r)|0}function TL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0,_=0;o=r+16|0,s=t[o>>2]|0,s?l=5:xL(r)|0?o=0:(s=t[o>>2]|0,l=5);e:do if((l|0)==5){if(_=r+20|0,d=t[_>>2]|0,o=d,(s-d|0)>>>0>>0){o=dh[t[r+36>>2]&7](r,e,n)|0;break}t:do if((c[r+75>>0]|0)>-1){for(d=n;;){if(!d){l=0,s=e;break t}if(s=d+-1|0,(c[e+s>>0]|0)==10)break;d=s}if(o=dh[t[r+36>>2]&7](r,e,d)|0,o>>>0>>0)break e;l=d,s=e+d|0,n=n-d|0,o=t[_>>2]|0}else l=0,s=e;while(0);vn(o|0,s|0,n|0)|0,t[_>>2]=(t[_>>2]|0)+n,o=l+n|0}while(0);return o|0}function xL(e){e=e|0;var n=0,r=0;return n=e+74|0,r=c[n>>0]|0,c[n>>0]=r+255|r,n=t[e>>2]|0,n&8?(t[e>>2]=n|32,e=-1):(t[e+8>>2]=0,t[e+4>>2]=0,r=t[e+44>>2]|0,t[e+28>>2]=r,t[e+20>>2]=r,t[e+16>>2]=r+(t[e+48>>2]|0),e=0),e|0}function Ur(e,n){e=w(e),n=w(n);var r=0,o=0;r=V8(e)|0;do if((r&2147483647)>>>0<=2139095040){if(o=V8(n)|0,(o&2147483647)>>>0<=2139095040)if((o^r|0)<0){e=(r|0)<0?n:e;break}else{e=e>2]=e,t[j>>2]|0|0}function cc(e,n){e=w(e),n=w(n);var r=0,o=0;r=Y8(e)|0;do if((r&2147483647)>>>0<=2139095040){if(o=Y8(n)|0,(o&2147483647)>>>0<=2139095040)if((o^r|0)<0){e=(r|0)<0?e:n;break}else{e=e>2]=e,t[j>>2]|0|0}function V4(e,n){e=w(e),n=w(n);var r=0,o=0,s=0,l=0,d=0,_=0,y=0,k=0;l=(D[j>>2]=e,t[j>>2]|0),_=(D[j>>2]=n,t[j>>2]|0),r=l>>>23&255,d=_>>>23&255,y=l&-2147483648,s=_<<1;e:do if((s|0)!=0?!((r|0)==255|((kL(n)|0)&2147483647)>>>0>2139095040):0){if(o=l<<1,o>>>0<=s>>>0)return n=w(e*w(0)),w((o|0)==(s|0)?n:e);if(r)o=l&8388607|8388608;else{if(r=l<<9,(r|0)>-1){o=r,r=0;do r=r+-1|0,o=o<<1;while((o|0)>-1)}else r=0;o=l<<1-r}if(d)_=_&8388607|8388608;else{if(l=_<<9,(l|0)>-1){s=0;do s=s+-1|0,l=l<<1;while((l|0)>-1)}else s=0;d=s,_=_<<1-s}s=o-_|0,l=(s|0)>-1;t:do if((r|0)>(d|0)){for(;;){if(l)if(s)o=s;else break;if(o=o<<1,r=r+-1|0,s=o-_|0,l=(s|0)>-1,(r|0)<=(d|0))break t}n=w(e*w(0));break e}while(0);if(l)if(s)o=s;else{n=w(e*w(0));break}if(o>>>0<8388608)do o=o<<1,r=r+-1|0;while(o>>>0<8388608);(r|0)>0?r=o+-8388608|r<<23:r=o>>>(1-r|0),n=(t[j>>2]=r|y,w(D[j>>2]))}else k=3;while(0);return(k|0)==3&&(n=w(e*n),n=w(n/n)),w(n)}function kL(e){return e=w(e),D[j>>2]=e,t[j>>2]|0|0}function AL(e,n){return e=e|0,n=n|0,q8(t[582]|0,e,n)|0}function $n(e){e=e|0,_n()}function da(e){e=e|0}function OL(e,n){return e=e|0,n=n|0,0}function IL(e){return e=e|0,($8(e+4|0)|0)==-1?(Nl[t[(t[e>>2]|0)+8>>2]&127](e),e=1):e=0,e|0}function $8(e){e=e|0;var n=0;return n=t[e>>2]|0,t[e>>2]=n+-1,n+-1|0}function Tf(e){e=e|0,IL(e)|0&&PL(e)}function PL(e){e=e|0;var n=0;n=e+8|0,((t[n>>2]|0)!=0?($8(n)|0)!=-1:0)||Nl[t[(t[e>>2]|0)+16>>2]&127](e)}function Tt(e){e=e|0;var n=0;for(n=(e|0)==0?1:e;e=uh(n)|0,!(e|0);){if(e=FL()|0,!e){e=0;break}fD[e&0]()}return e|0}function K8(e){return e=e|0,Tt(e)|0}function Ve(e){e=e|0,sh(e)}function ML(e){e=e|0,(c[e+11>>0]|0)<0&&Ve(t[e>>2]|0)}function FL(){var e=0;return e=t[2923]|0,t[2923]=e+0,e|0}function LL(){}function fh(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,o=n-o-(r>>>0>e>>>0|0)>>>0,be=o,e-r>>>0|0|0}function Y4(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,r=e+r>>>0,be=n+o+(r>>>0>>0|0)>>>0,r|0|0}function pa(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0,d=0;if(l=e+r|0,n=n&255,(r|0)>=67){for(;e&3;)c[e>>0]=n,e=e+1|0;for(o=l&-4|0,s=o-64|0,d=n|n<<8|n<<16|n<<24;(e|0)<=(s|0);)t[e>>2]=d,t[e+4>>2]=d,t[e+8>>2]=d,t[e+12>>2]=d,t[e+16>>2]=d,t[e+20>>2]=d,t[e+24>>2]=d,t[e+28>>2]=d,t[e+32>>2]=d,t[e+36>>2]=d,t[e+40>>2]=d,t[e+44>>2]=d,t[e+48>>2]=d,t[e+52>>2]=d,t[e+56>>2]=d,t[e+60>>2]=d,e=e+64|0;for(;(e|0)<(o|0);)t[e>>2]=d,e=e+4|0}for(;(e|0)<(l|0);)c[e>>0]=n,e=e+1|0;return l-r|0}function X8(e,n,r){return e=e|0,n=n|0,r=r|0,(r|0)<32?(be=n<>>32-r,e<>>r,e>>>r|(n&(1<>>r-32|0)}function vn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,s=0,l=0;if((r|0)>=8192)return wo(e|0,n|0,r|0)|0;if(l=e|0,s=e+r|0,(e&3)==(n&3)){for(;e&3;){if(!r)return l|0;c[e>>0]=c[n>>0]|0,e=e+1|0,n=n+1|0,r=r-1|0}for(r=s&-4|0,o=r-64|0;(e|0)<=(o|0);)t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2],t[e+16>>2]=t[n+16>>2],t[e+20>>2]=t[n+20>>2],t[e+24>>2]=t[n+24>>2],t[e+28>>2]=t[n+28>>2],t[e+32>>2]=t[n+32>>2],t[e+36>>2]=t[n+36>>2],t[e+40>>2]=t[n+40>>2],t[e+44>>2]=t[n+44>>2],t[e+48>>2]=t[n+48>>2],t[e+52>>2]=t[n+52>>2],t[e+56>>2]=t[n+56>>2],t[e+60>>2]=t[n+60>>2],e=e+64|0,n=n+64|0;for(;(e|0)<(r|0);)t[e>>2]=t[n>>2],e=e+4|0,n=n+4|0}else for(r=s-4|0;(e|0)<(r|0);)c[e>>0]=c[n>>0]|0,c[e+1>>0]=c[n+1>>0]|0,c[e+2>>0]=c[n+2>>0]|0,c[e+3>>0]=c[n+3>>0]|0,e=e+4|0,n=n+4|0;for(;(e|0)<(s|0);)c[e>>0]=c[n>>0]|0,e=e+1|0,n=n+1|0;return l|0}function J8(e){e=e|0;var n=0;return n=c[ce+(e&255)>>0]|0,(n|0)<8?n|0:(n=c[ce+(e>>8&255)>>0]|0,(n|0)<8?n+8|0:(n=c[ce+(e>>16&255)>>0]|0,(n|0)<8?n+16|0:(c[ce+(e>>>24)>>0]|0)+24|0))}function Q8(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0;var l=0,d=0,_=0,y=0,k=0,T=0,P=0,q=0,we=0,le=0;if(T=e,y=n,k=y,d=r,q=o,_=q,!k)return l=(s|0)!=0,_?l?(t[s>>2]=e|0,t[s+4>>2]=n&0,q=0,s=0,be=q,s|0):(q=0,s=0,be=q,s|0):(l&&(t[s>>2]=(T>>>0)%(d>>>0),t[s+4>>2]=0),q=0,s=(T>>>0)/(d>>>0)>>>0,be=q,s|0);l=(_|0)==0;do if(d){if(!l){if(l=(cr(_|0)|0)-(cr(k|0)|0)|0,l>>>0<=31){P=l+1|0,_=31-l|0,n=l-31>>31,d=P,e=T>>>(P>>>0)&n|k<<_,n=k>>>(P>>>0)&n,l=0,_=T<<_;break}return s?(t[s>>2]=e|0,t[s+4>>2]=y|n&0,q=0,s=0,be=q,s|0):(q=0,s=0,be=q,s|0)}if(l=d-1|0,l&d|0){_=(cr(d|0)|0)+33-(cr(k|0)|0)|0,le=64-_|0,P=32-_|0,y=P>>31,we=_-32|0,n=we>>31,d=_,e=P-1>>31&k>>>(we>>>0)|(k<>>(_>>>0))&n,n=n&k>>>(_>>>0),l=T<>>(we>>>0))&y|T<>31;break}return s|0&&(t[s>>2]=l&T,t[s+4>>2]=0),(d|0)==1?(we=y|n&0,le=e|0|0,be=we,le|0):(le=J8(d|0)|0,we=k>>>(le>>>0)|0,le=k<<32-le|T>>>(le>>>0)|0,be=we,le|0)}else{if(l)return s|0&&(t[s>>2]=(k>>>0)%(d>>>0),t[s+4>>2]=0),we=0,le=(k>>>0)/(d>>>0)>>>0,be=we,le|0;if(!T)return s|0&&(t[s>>2]=0,t[s+4>>2]=(k>>>0)%(_>>>0)),we=0,le=(k>>>0)/(_>>>0)>>>0,be=we,le|0;if(l=_-1|0,!(l&_))return s|0&&(t[s>>2]=e|0,t[s+4>>2]=l&k|n&0),we=0,le=k>>>((J8(_|0)|0)>>>0),be=we,le|0;if(l=(cr(_|0)|0)-(cr(k|0)|0)|0,l>>>0<=30){n=l+1|0,_=31-l|0,d=n,e=k<<_|T>>>(n>>>0),n=k>>>(n>>>0),l=0,_=T<<_;break}return s?(t[s>>2]=e|0,t[s+4>>2]=y|n&0,we=0,le=0,be=we,le|0):(we=0,le=0,be=we,le|0)}while(0);if(!d)k=_,y=0,_=0;else{P=r|0|0,T=q|o&0,k=Y4(P|0,T|0,-1,-1)|0,r=be,y=_,_=0;do o=y,y=l>>>31|y<<1,l=_|l<<1,o=e<<1|o>>>31|0,q=e>>>31|n<<1|0,fh(k|0,r|0,o|0,q|0)|0,le=be,we=le>>31|((le|0)<0?-1:0)<<1,_=we&1,e=fh(o|0,q|0,we&P|0,(((le|0)<0?-1:0)>>31|((le|0)<0?-1:0)<<1)&T|0)|0,n=be,d=d-1|0;while((d|0)!=0);k=y,y=0}return d=0,s|0&&(t[s>>2]=e,t[s+4>>2]=n),we=(l|0)>>>31|(k|d)<<1|(d<<1|l>>>31)&0|y,le=(l<<1|0>>>31)&-2|_,be=we,le|0}function $4(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,Q8(e,n,r,o,0)|0}function xf(e){e=e|0;var n=0,r=0;return r=e+15&-16|0,n=t[N>>2]|0,e=n+r|0,(r|0)>0&(e|0)<(n|0)|(e|0)<0?(vr()|0,Os(12),-1):(t[N>>2]=e,((e|0)>(Xn()|0)?(Bn()|0)==0:0)?(t[N>>2]=n,Os(12),-1):n|0)}function Y1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;if((n|0)<(e|0)&(e|0)<(n+r|0)){for(o=e,n=n+r|0,e=e+r|0;(r|0)>0;)e=e-1|0,n=n-1|0,r=r-1|0,c[e>>0]=c[n>>0]|0;e=o}else vn(e,n,r)|0;return e|0}function K4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var s=0,l=0;return l=h,h=h+16|0,s=l|0,Q8(e,n,r,o,s)|0,h=l,be=t[s+4>>2]|0,t[s>>2]|0|0}function Z8(e){return e=e|0,(e&255)<<24|(e>>8&255)<<16|(e>>16&255)<<8|e>>>24|0}function RL(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,eD[e&1](n|0,r|0,o|0,s|0,l|0)}function NL(e,n,r){e=e|0,n=n|0,r=w(r),tD[e&1](n|0,w(r))}function BL(e,n,r){e=e|0,n=n|0,r=+r,nD[e&31](n|0,+r)}function jL(e,n,r,o){return e=e|0,n=n|0,r=w(r),o=w(o),w(rD[e&0](n|0,w(r),w(o)))}function UL(e,n){e=e|0,n=n|0,Nl[e&127](n|0)}function qL(e,n,r){e=e|0,n=n|0,r=r|0,Bl[e&31](n|0,r|0)}function zL(e,n){return e=e|0,n=n|0,dc[e&31](n|0)|0}function WL(e,n,r,o,s){e=e|0,n=n|0,r=+r,o=+o,s=s|0,iD[e&1](n|0,+r,+o,s|0)}function HL(e,n,r,o){e=e|0,n=n|0,r=+r,o=+o,CR[e&1](n|0,+r,+o)}function bL(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,dh[e&7](n|0,r|0,o|0)|0}function VL(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,+TR[e&1](n|0,r|0,o|0)}function YL(e,n){return e=e|0,n=n|0,+oD[e&15](n|0)}function $L(e,n,r){return e=e|0,n=n|0,r=+r,xR[e&1](n|0,+r)|0}function KL(e,n,r){return e=e|0,n=n|0,r=r|0,J4[e&15](n|0,r|0)|0}function XL(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=+o,s=+s,l=l|0,kR[e&1](n|0,r|0,+o,+s,l|0)}function JL(e,n,r,o,s,l,d){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,d=d|0,AR[e&1](n|0,r|0,o|0,s|0,l|0,d|0)}function QL(e,n,r){return e=e|0,n=n|0,r=r|0,+uD[e&7](n|0,r|0)}function ZL(e){return e=e|0,ph[e&7]()|0}function eR(e,n,r,o,s,l){return e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,sD[e&1](n|0,r|0,o|0,s|0,l|0)|0}function tR(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=+s,OR[e&1](n|0,r|0,o|0,+s)}function nR(e,n,r,o,s,l,d){e=e|0,n=n|0,r=r|0,o=w(o),s=s|0,l=w(l),d=d|0,lD[e&1](n|0,r|0,w(o),s|0,w(l),d|0)}function rR(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,X1[e&15](n|0,r|0,o|0)}function iR(e){e=e|0,fD[e&0]()}function oR(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o,cD[e&15](n|0,r|0,+o)}function uR(e,n,r){return e=e|0,n=+n,r=+r,IR[e&1](+n,+r)|0}function sR(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,Q4[e&15](n|0,r|0,o|0,s|0)}function lR(e,n,r,o,s){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,pt(0)}function fR(e,n){e=e|0,n=w(n),pt(1)}function Lo(e,n){e=e|0,n=+n,pt(2)}function cR(e,n,r){return e=e|0,n=w(n),r=w(r),pt(3),tt}function tn(e){e=e|0,pt(4)}function $1(e,n){e=e|0,n=n|0,pt(5)}function tu(e){return e=e|0,pt(6),0}function aR(e,n,r,o){e=e|0,n=+n,r=+r,o=o|0,pt(7)}function dR(e,n,r){e=e|0,n=+n,r=+r,pt(8)}function pR(e,n,r){return e=e|0,n=n|0,r=r|0,pt(9),0}function hR(e,n,r){return e=e|0,n=n|0,r=r|0,pt(10),0}function ac(e){return e=e|0,pt(11),0}function mR(e,n){return e=e|0,n=+n,pt(12),0}function K1(e,n){return e=e|0,n=n|0,pt(13),0}function vR(e,n,r,o,s){e=e|0,n=n|0,r=+r,o=+o,s=s|0,pt(14)}function gR(e,n,r,o,s,l){e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,l=l|0,pt(15)}function X4(e,n){return e=e|0,n=n|0,pt(16),0}function _R(){return pt(17),0}function yR(e,n,r,o,s){return e=e|0,n=n|0,r=r|0,o=o|0,s=s|0,pt(18),0}function wR(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o,pt(19)}function DR(e,n,r,o,s,l){e=e|0,n=n|0,r=w(r),o=o|0,s=w(s),l=l|0,pt(20)}function ah(e,n,r){e=e|0,n=n|0,r=r|0,pt(21)}function ER(){pt(22)}function ha(e,n,r){e=e|0,n=n|0,r=+r,pt(23)}function SR(e,n){return e=+e,n=+n,pt(24),0}function ma(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,pt(25)}var eD=[lR,_I],tD=[fR,x0],nD=[Lo,Kf,Tl,xl,hf,xo,mf,Wa,Hs,mi,Xf,Rc,Jf,ao,$o,kl,Nc,Al,vf,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo,Lo],rD=[cR],Nl=[tn,da,Km,Xm,es,a_,d_,p_,YA,$A,KA,oI,uI,sI,kF,AF,OF,Sn,Oc,pf,ti,vi,Nm,Uc,r1,Hd,Pl,mv,Av,Kc,Jc,yp,Eg,na,Ug,Yg,u_,k_,q_,J_,a4,Ct,w9,U9,ex,hx,Ix,_0,s7,S7,W7,uk,Dk,Wk,Qk,tA,_A,DA,jA,JA,eO,gO,RO,d1,vP,YP,lM,SM,GM,uF,gF,wF,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn,tn],Bl=[$1,ja,Ua,$f,gu,co,qa,Ws,za,Mc,Fc,Lc,po,Ce,ze,Et,on,sr,mn,Zf,gd,xd,H9,rx,ck,yP,HO,C8,$1,$1,$1,$1],dc=[tu,iL,Ba,m,b,ee,Ye,Ze,ut,In,jr,gi,Pm,Ha,Ya,Fx,Tk,wO,SP,Qo,tu,tu,tu,tu,tu,tu,tu,tu,tu,tu,tu,tu],iD=[aR,Sd],CR=[dR,zA],dh=[pR,j8,oL,lL,Gv,P_,a7,kM],TR=[hR,Op],oD=[ac,_i,Re,pr,Cd,ho,bs,$a,Td,qc,ac,ac,ac,ac,ac,ac],xR=[mR,Kk],J4=[K1,OL,vd,Vc,_v,ig,pg,f_,H_,_x,Xu,dM,K1,K1,K1,K1],kR=[vR,iv],AR=[gR,KM],uD=[X4,Hr,Ka,kd,Xa,Jg,X4,X4],ph=[_R,Ja,Z0,g0,oA,TA,iO,CF],sD=[yR,or],OR=[wR,m4],lD=[DR,Bc],X1=[ah,S,A0,Vn,ni,Mv,Tg,dn,C9,fo,zI,JP,cF,ah,ah,ah],fD=[ER],cD=[ha,Ic,vu,Pc,Qu,Qf,k0,v,W1,k7,Gk,ha,ha,ha,ha,ha],IR=[SR,GA],Q4=[ma,Fg,zx,V7,Lk,aA,PA,aO,qO,OP,RF,ma,ma,ma,ma,ma];return{_llvm_bswap_i32:Z8,dynCall_idd:uR,dynCall_i:ZL,_i64Subtract:fh,___udivdi3:$4,dynCall_vif:NL,setThrew:vl,dynCall_viii:rR,_bitshift64Lshr:ch,_bitshift64Shl:X8,dynCall_vi:UL,dynCall_viiddi:XL,dynCall_diii:VL,dynCall_iii:KL,_memset:pa,_sbrk:xf,_memcpy:vn,__GLOBAL__sub_I_Yoga_cpp:t0,dynCall_vii:qL,___uremdi3:K4,dynCall_vid:BL,stackAlloc:zi,_nbind_init:VF,getTempRet0:fu,dynCall_di:YL,dynCall_iid:$L,setTempRet0:gl,_i64Add:Y4,dynCall_fiff:jL,dynCall_iiii:bL,_emscripten_get_global_libc:rL,dynCall_viid:oR,dynCall_viiid:tR,dynCall_viififi:nR,dynCall_ii:zL,__GLOBAL__sub_I_Binding_cc:lP,dynCall_viiii:sR,dynCall_iiiiii:eR,stackSave:lu,dynCall_viiiii:RL,__GLOBAL__sub_I_nbind_cc:Gs,dynCall_vidd:HL,_free:sh,runPostSets:LL,dynCall_viiiiii:JL,establishStackSpace:O0,_memmove:Y1,stackRestore:Ho,_malloc:uh,__GLOBAL__sub_I_common_cc:AO,dynCall_viddi:WL,dynCall_dii:QL,dynCall_v:iR}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(i){this.name="ExitStatus",this.message="Program terminated with exit("+i+")",this.status=i}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function i(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=i)},Module.callMain=Module.callMain=function(u){u=u||[],ensureInitRuntime();var f=u.length+1;function c(){for(var x=0;x<4-1;x++)g.push(0)}var g=[allocate(intArrayFromString(Module.thisProgram),"i8",ALLOC_NORMAL)];c();for(var t=0;t0||(preRun(),runDependencies>0)||Module.calledRun)return;function u(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(i),postRun()))}Module.setStatus?(Module.setStatus("Running..."),setTimeout(function(){setTimeout(function(){Module.setStatus("")},1),u()},1)):u()}Module.run=Module.run=run;function exit(i,u){u&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=i,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(i)),ENVIRONMENT_IS_NODE&&process.exit(i),Module.quit(i,new ExitStatus(i)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(i){Module.onAbort&&Module.onAbort(i),i!==void 0?(Module.print(i),Module.printErr(i),i=JSON.stringify(i)):i="",ABORT=!0,EXITSTATUS=1;var u=` + If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,f="abort("+i+") at "+stackTrace()+u;throw abortDecorators&&abortDecorators.forEach(function(c){f=c(f,i)}),f}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var hc=Me((hb,vE)=>{"use strict";var wN=hE(),DN=mE(),Py=!1,My=null;DN({},function(i,u){if(!Py){if(Py=!0,i)throw i;My=u}});if(!Py)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");vE.exports=wN(My.bind,My.lib)});var _E=Me((mb,gE)=>{"use strict";gE.exports=({onlyFirst:i=!1}={})=>{let u=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(u,i?void 0:"g")}});var Fy=Me((vb,yE)=>{"use strict";var EN=_E();yE.exports=i=>typeof i=="string"?i.replace(EN(),""):i});var Ry=Me((gb,Ly)=>{"use strict";var wE=i=>Number.isNaN(i)?!1:i>=4352&&(i<=4447||i===9001||i===9002||11904<=i&&i<=12871&&i!==12351||12880<=i&&i<=19903||19968<=i&&i<=42182||43360<=i&&i<=43388||44032<=i&&i<=55203||63744<=i&&i<=64255||65040<=i&&i<=65049||65072<=i&&i<=65131||65281<=i&&i<=65376||65504<=i&&i<=65510||110592<=i&&i<=110593||127488<=i&&i<=127569||131072<=i&&i<=262141);Ly.exports=wE;Ly.exports.default=wE});var EE=Me((_b,DE)=>{"use strict";DE.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var Mh=Me((yb,Ny)=>{"use strict";var SN=Fy(),CN=Ry(),TN=EE(),SE=i=>{if(i=i.replace(TN()," "),typeof i!="string"||i.length===0)return 0;i=SN(i);let u=0;for(let f=0;f=127&&c<=159||c>=768&&c<=879||(c>65535&&f++,u+=CN(c)?2:1)}return u};Ny.exports=SE;Ny.exports.default=SE});var jy=Me((wb,By)=>{"use strict";var xN=Mh(),CE=i=>{let u=0;for(let f of i.split(` + `))u=Math.max(u,xN(f));return u};By.exports=CE;By.exports.default=CE});var TE=Me(a2=>{"use strict";var kN=a2&&a2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(a2,"__esModule",{value:!0});var AN=kN(jy()),Uy={};a2.default=i=>{if(i.length===0)return{width:0,height:0};if(Uy[i])return Uy[i];let u=AN.default(i),f=i.split(` + `).length;return Uy[i]={width:u,height:f},{width:u,height:f}}});var xE=Me(d2=>{"use strict";var ON=d2&&d2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(d2,"__esModule",{value:!0});var hr=ON(hc()),IN=(i,u)=>{"position"in u&&i.setPositionType(u.position==="absolute"?hr.default.POSITION_TYPE_ABSOLUTE:hr.default.POSITION_TYPE_RELATIVE)},PN=(i,u)=>{"marginLeft"in u&&i.setMargin(hr.default.EDGE_START,u.marginLeft||0),"marginRight"in u&&i.setMargin(hr.default.EDGE_END,u.marginRight||0),"marginTop"in u&&i.setMargin(hr.default.EDGE_TOP,u.marginTop||0),"marginBottom"in u&&i.setMargin(hr.default.EDGE_BOTTOM,u.marginBottom||0)},MN=(i,u)=>{"paddingLeft"in u&&i.setPadding(hr.default.EDGE_LEFT,u.paddingLeft||0),"paddingRight"in u&&i.setPadding(hr.default.EDGE_RIGHT,u.paddingRight||0),"paddingTop"in u&&i.setPadding(hr.default.EDGE_TOP,u.paddingTop||0),"paddingBottom"in u&&i.setPadding(hr.default.EDGE_BOTTOM,u.paddingBottom||0)},FN=(i,u)=>{var f;"flexGrow"in u&&i.setFlexGrow((f=u.flexGrow)!==null&&f!==void 0?f:0),"flexShrink"in u&&i.setFlexShrink(typeof u.flexShrink=="number"?u.flexShrink:1),"flexDirection"in u&&(u.flexDirection==="row"&&i.setFlexDirection(hr.default.FLEX_DIRECTION_ROW),u.flexDirection==="row-reverse"&&i.setFlexDirection(hr.default.FLEX_DIRECTION_ROW_REVERSE),u.flexDirection==="column"&&i.setFlexDirection(hr.default.FLEX_DIRECTION_COLUMN),u.flexDirection==="column-reverse"&&i.setFlexDirection(hr.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in u&&(typeof u.flexBasis=="number"?i.setFlexBasis(u.flexBasis):typeof u.flexBasis=="string"?i.setFlexBasisPercent(Number.parseInt(u.flexBasis,10)):i.setFlexBasis(NaN)),"alignItems"in u&&((u.alignItems==="stretch"||!u.alignItems)&&i.setAlignItems(hr.default.ALIGN_STRETCH),u.alignItems==="flex-start"&&i.setAlignItems(hr.default.ALIGN_FLEX_START),u.alignItems==="center"&&i.setAlignItems(hr.default.ALIGN_CENTER),u.alignItems==="flex-end"&&i.setAlignItems(hr.default.ALIGN_FLEX_END)),"alignSelf"in u&&((u.alignSelf==="auto"||!u.alignSelf)&&i.setAlignSelf(hr.default.ALIGN_AUTO),u.alignSelf==="flex-start"&&i.setAlignSelf(hr.default.ALIGN_FLEX_START),u.alignSelf==="center"&&i.setAlignSelf(hr.default.ALIGN_CENTER),u.alignSelf==="flex-end"&&i.setAlignSelf(hr.default.ALIGN_FLEX_END)),"justifyContent"in u&&((u.justifyContent==="flex-start"||!u.justifyContent)&&i.setJustifyContent(hr.default.JUSTIFY_FLEX_START),u.justifyContent==="center"&&i.setJustifyContent(hr.default.JUSTIFY_CENTER),u.justifyContent==="flex-end"&&i.setJustifyContent(hr.default.JUSTIFY_FLEX_END),u.justifyContent==="space-between"&&i.setJustifyContent(hr.default.JUSTIFY_SPACE_BETWEEN),u.justifyContent==="space-around"&&i.setJustifyContent(hr.default.JUSTIFY_SPACE_AROUND))},LN=(i,u)=>{var f,c;"width"in u&&(typeof u.width=="number"?i.setWidth(u.width):typeof u.width=="string"?i.setWidthPercent(Number.parseInt(u.width,10)):i.setWidthAuto()),"height"in u&&(typeof u.height=="number"?i.setHeight(u.height):typeof u.height=="string"?i.setHeightPercent(Number.parseInt(u.height,10)):i.setHeightAuto()),"minWidth"in u&&(typeof u.minWidth=="string"?i.setMinWidthPercent(Number.parseInt(u.minWidth,10)):i.setMinWidth((f=u.minWidth)!==null&&f!==void 0?f:0)),"minHeight"in u&&(typeof u.minHeight=="string"?i.setMinHeightPercent(Number.parseInt(u.minHeight,10)):i.setMinHeight((c=u.minHeight)!==null&&c!==void 0?c:0))},RN=(i,u)=>{"display"in u&&i.setDisplay(u.display==="flex"?hr.default.DISPLAY_FLEX:hr.default.DISPLAY_NONE)},NN=(i,u)=>{if("borderStyle"in u){let f=typeof u.borderStyle=="string"?1:0;i.setBorder(hr.default.EDGE_TOP,f),i.setBorder(hr.default.EDGE_BOTTOM,f),i.setBorder(hr.default.EDGE_LEFT,f),i.setBorder(hr.default.EDGE_RIGHT,f)}};d2.default=(i,u={})=>{IN(i,u),PN(i,u),MN(i,u),FN(i,u),LN(i,u),RN(i,u),NN(i,u)}});var AE=Me((Sb,kE)=>{"use strict";kE.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var qy=Me((Cb,OE)=>{var p2=AE(),IE={};for(let i of Object.keys(p2))IE[p2[i]]=i;var Xt={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};OE.exports=Xt;for(let i of Object.keys(Xt)){if(!("channels"in Xt[i]))throw new Error("missing channels property: "+i);if(!("labels"in Xt[i]))throw new Error("missing channel labels property: "+i);if(Xt[i].labels.length!==Xt[i].channels)throw new Error("channel and label counts mismatch: "+i);let{channels:u,labels:f}=Xt[i];delete Xt[i].channels,delete Xt[i].labels,Object.defineProperty(Xt[i],"channels",{value:u}),Object.defineProperty(Xt[i],"labels",{value:f})}Xt.rgb.hsl=function(i){let u=i[0]/255,f=i[1]/255,c=i[2]/255,g=Math.min(u,f,c),t=Math.max(u,f,c),C=t-g,A,x;t===g?A=0:u===t?A=(f-c)/C:f===t?A=2+(c-u)/C:c===t&&(A=4+(u-f)/C),A=Math.min(A*60,360),A<0&&(A+=360);let D=(g+t)/2;return t===g?x=0:D<=.5?x=C/(t+g):x=C/(2-t-g),[A,x*100,D*100]};Xt.rgb.hsv=function(i){let u,f,c,g,t,C=i[0]/255,A=i[1]/255,x=i[2]/255,D=Math.max(C,A,x),L=D-Math.min(C,A,x),N=function(j){return(D-j)/6/L+1/2};return L===0?(g=0,t=0):(t=L/D,u=N(C),f=N(A),c=N(x),C===D?g=c-f:A===D?g=1/3+u-c:x===D&&(g=2/3+f-u),g<0?g+=1:g>1&&(g-=1)),[g*360,t*100,D*100]};Xt.rgb.hwb=function(i){let u=i[0],f=i[1],c=i[2],g=Xt.rgb.hsl(i)[0],t=1/255*Math.min(u,Math.min(f,c));return c=1-1/255*Math.max(u,Math.max(f,c)),[g,t*100,c*100]};Xt.rgb.cmyk=function(i){let u=i[0]/255,f=i[1]/255,c=i[2]/255,g=Math.min(1-u,1-f,1-c),t=(1-u-g)/(1-g)||0,C=(1-f-g)/(1-g)||0,A=(1-c-g)/(1-g)||0;return[t*100,C*100,A*100,g*100]};function BN(i,u){return(i[0]-u[0])**2+(i[1]-u[1])**2+(i[2]-u[2])**2}Xt.rgb.keyword=function(i){let u=IE[i];if(u)return u;let f=Infinity,c;for(let g of Object.keys(p2)){let t=p2[g],C=BN(i,t);C.04045?((u+.055)/1.055)**2.4:u/12.92,f=f>.04045?((f+.055)/1.055)**2.4:f/12.92,c=c>.04045?((c+.055)/1.055)**2.4:c/12.92;let g=u*.4124+f*.3576+c*.1805,t=u*.2126+f*.7152+c*.0722,C=u*.0193+f*.1192+c*.9505;return[g*100,t*100,C*100]};Xt.rgb.lab=function(i){let u=Xt.rgb.xyz(i),f=u[0],c=u[1],g=u[2];f/=95.047,c/=100,g/=108.883,f=f>.008856?f**(1/3):7.787*f+16/116,c=c>.008856?c**(1/3):7.787*c+16/116,g=g>.008856?g**(1/3):7.787*g+16/116;let t=116*c-16,C=500*(f-c),A=200*(c-g);return[t,C,A]};Xt.hsl.rgb=function(i){let u=i[0]/360,f=i[1]/100,c=i[2]/100,g,t,C;if(f===0)return C=c*255,[C,C,C];c<.5?g=c*(1+f):g=c+f-c*f;let A=2*c-g,x=[0,0,0];for(let D=0;D<3;D++)t=u+1/3*-(D-1),t<0&&t++,t>1&&t--,6*t<1?C=A+(g-A)*6*t:2*t<1?C=g:3*t<2?C=A+(g-A)*(2/3-t)*6:C=A,x[D]=C*255;return x};Xt.hsl.hsv=function(i){let u=i[0],f=i[1]/100,c=i[2]/100,g=f,t=Math.max(c,.01);c*=2,f*=c<=1?c:2-c,g*=t<=1?t:2-t;let C=(c+f)/2,A=c===0?2*g/(t+g):2*f/(c+f);return[u,A*100,C*100]};Xt.hsv.rgb=function(i){let u=i[0]/60,f=i[1]/100,c=i[2]/100,g=Math.floor(u)%6,t=u-Math.floor(u),C=255*c*(1-f),A=255*c*(1-f*t),x=255*c*(1-f*(1-t));switch(c*=255,g){case 0:return[c,x,C];case 1:return[A,c,C];case 2:return[C,c,x];case 3:return[C,A,c];case 4:return[x,C,c];case 5:return[c,C,A]}};Xt.hsv.hsl=function(i){let u=i[0],f=i[1]/100,c=i[2]/100,g=Math.max(c,.01),t,C;C=(2-f)*c;let A=(2-f)*g;return t=f*g,t/=A<=1?A:2-A,t=t||0,C/=2,[u,t*100,C*100]};Xt.hwb.rgb=function(i){let u=i[0]/360,f=i[1]/100,c=i[2]/100,g=f+c,t;g>1&&(f/=g,c/=g);let C=Math.floor(6*u),A=1-c;t=6*u-C,(C&1)!=0&&(t=1-t);let x=f+t*(A-f),D,L,N;switch(C){default:case 6:case 0:D=A,L=x,N=f;break;case 1:D=x,L=A,N=f;break;case 2:D=f,L=A,N=x;break;case 3:D=f,L=x,N=A;break;case 4:D=x,L=f,N=A;break;case 5:D=A,L=f,N=x;break}return[D*255,L*255,N*255]};Xt.cmyk.rgb=function(i){let u=i[0]/100,f=i[1]/100,c=i[2]/100,g=i[3]/100,t=1-Math.min(1,u*(1-g)+g),C=1-Math.min(1,f*(1-g)+g),A=1-Math.min(1,c*(1-g)+g);return[t*255,C*255,A*255]};Xt.xyz.rgb=function(i){let u=i[0]/100,f=i[1]/100,c=i[2]/100,g,t,C;return g=u*3.2406+f*-1.5372+c*-.4986,t=u*-.9689+f*1.8758+c*.0415,C=u*.0557+f*-.204+c*1.057,g=g>.0031308?1.055*g**(1/2.4)-.055:g*12.92,t=t>.0031308?1.055*t**(1/2.4)-.055:t*12.92,C=C>.0031308?1.055*C**(1/2.4)-.055:C*12.92,g=Math.min(Math.max(0,g),1),t=Math.min(Math.max(0,t),1),C=Math.min(Math.max(0,C),1),[g*255,t*255,C*255]};Xt.xyz.lab=function(i){let u=i[0],f=i[1],c=i[2];u/=95.047,f/=100,c/=108.883,u=u>.008856?u**(1/3):7.787*u+16/116,f=f>.008856?f**(1/3):7.787*f+16/116,c=c>.008856?c**(1/3):7.787*c+16/116;let g=116*f-16,t=500*(u-f),C=200*(f-c);return[g,t,C]};Xt.lab.xyz=function(i){let u=i[0],f=i[1],c=i[2],g,t,C;t=(u+16)/116,g=f/500+t,C=t-c/200;let A=t**3,x=g**3,D=C**3;return t=A>.008856?A:(t-16/116)/7.787,g=x>.008856?x:(g-16/116)/7.787,C=D>.008856?D:(C-16/116)/7.787,g*=95.047,t*=100,C*=108.883,[g,t,C]};Xt.lab.lch=function(i){let u=i[0],f=i[1],c=i[2],g;g=Math.atan2(c,f)*360/2/Math.PI,g<0&&(g+=360);let C=Math.sqrt(f*f+c*c);return[u,C,g]};Xt.lch.lab=function(i){let u=i[0],f=i[1],g=i[2]/360*2*Math.PI,t=f*Math.cos(g),C=f*Math.sin(g);return[u,t,C]};Xt.rgb.ansi16=function(i,u=null){let[f,c,g]=i,t=u===null?Xt.rgb.hsv(i)[2]:u;if(t=Math.round(t/50),t===0)return 30;let C=30+(Math.round(g/255)<<2|Math.round(c/255)<<1|Math.round(f/255));return t===2&&(C+=60),C};Xt.hsv.ansi16=function(i){return Xt.rgb.ansi16(Xt.hsv.rgb(i),i[2])};Xt.rgb.ansi256=function(i){let u=i[0],f=i[1],c=i[2];return u===f&&f===c?u<8?16:u>248?231:Math.round((u-8)/247*24)+232:16+36*Math.round(u/255*5)+6*Math.round(f/255*5)+Math.round(c/255*5)};Xt.ansi16.rgb=function(i){let u=i%10;if(u===0||u===7)return i>50&&(u+=3.5),u=u/10.5*255,[u,u,u];let f=(~~(i>50)+1)*.5,c=(u&1)*f*255,g=(u>>1&1)*f*255,t=(u>>2&1)*f*255;return[c,g,t]};Xt.ansi256.rgb=function(i){if(i>=232){let t=(i-232)*10+8;return[t,t,t]}i-=16;let u,f=Math.floor(i/36)/5*255,c=Math.floor((u=i%36)/6)/5*255,g=u%6/5*255;return[f,c,g]};Xt.rgb.hex=function(i){let f=(((Math.round(i[0])&255)<<16)+((Math.round(i[1])&255)<<8)+(Math.round(i[2])&255)).toString(16).toUpperCase();return"000000".substring(f.length)+f};Xt.hex.rgb=function(i){let u=i.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!u)return[0,0,0];let f=u[0];u[0].length===3&&(f=f.split("").map(A=>A+A).join(""));let c=parseInt(f,16),g=c>>16&255,t=c>>8&255,C=c&255;return[g,t,C]};Xt.rgb.hcg=function(i){let u=i[0]/255,f=i[1]/255,c=i[2]/255,g=Math.max(Math.max(u,f),c),t=Math.min(Math.min(u,f),c),C=g-t,A,x;return C<1?A=t/(1-C):A=0,C<=0?x=0:g===u?x=(f-c)/C%6:g===f?x=2+(c-u)/C:x=4+(u-f)/C,x/=6,x%=1,[x*360,C*100,A*100]};Xt.hsl.hcg=function(i){let u=i[1]/100,f=i[2]/100,c=f<.5?2*u*f:2*u*(1-f),g=0;return c<1&&(g=(f-.5*c)/(1-c)),[i[0],c*100,g*100]};Xt.hsv.hcg=function(i){let u=i[1]/100,f=i[2]/100,c=u*f,g=0;return c<1&&(g=(f-c)/(1-c)),[i[0],c*100,g*100]};Xt.hcg.rgb=function(i){let u=i[0]/360,f=i[1]/100,c=i[2]/100;if(f===0)return[c*255,c*255,c*255];let g=[0,0,0],t=u%1*6,C=t%1,A=1-C,x=0;switch(Math.floor(t)){case 0:g[0]=1,g[1]=C,g[2]=0;break;case 1:g[0]=A,g[1]=1,g[2]=0;break;case 2:g[0]=0,g[1]=1,g[2]=C;break;case 3:g[0]=0,g[1]=A,g[2]=1;break;case 4:g[0]=C,g[1]=0,g[2]=1;break;default:g[0]=1,g[1]=0,g[2]=A}return x=(1-f)*c,[(f*g[0]+x)*255,(f*g[1]+x)*255,(f*g[2]+x)*255]};Xt.hcg.hsv=function(i){let u=i[1]/100,f=i[2]/100,c=u+f*(1-u),g=0;return c>0&&(g=u/c),[i[0],g*100,c*100]};Xt.hcg.hsl=function(i){let u=i[1]/100,c=i[2]/100*(1-u)+.5*u,g=0;return c>0&&c<.5?g=u/(2*c):c>=.5&&c<1&&(g=u/(2*(1-c))),[i[0],g*100,c*100]};Xt.hcg.hwb=function(i){let u=i[1]/100,f=i[2]/100,c=u+f*(1-u);return[i[0],(c-u)*100,(1-c)*100]};Xt.hwb.hcg=function(i){let u=i[1]/100,f=i[2]/100,c=1-f,g=c-u,t=0;return g<1&&(t=(c-g)/(1-g)),[i[0],g*100,t*100]};Xt.apple.rgb=function(i){return[i[0]/65535*255,i[1]/65535*255,i[2]/65535*255]};Xt.rgb.apple=function(i){return[i[0]/255*65535,i[1]/255*65535,i[2]/255*65535]};Xt.gray.rgb=function(i){return[i[0]/100*255,i[0]/100*255,i[0]/100*255]};Xt.gray.hsl=function(i){return[0,0,i[0]]};Xt.gray.hsv=Xt.gray.hsl;Xt.gray.hwb=function(i){return[0,100,i[0]]};Xt.gray.cmyk=function(i){return[0,0,0,i[0]]};Xt.gray.lab=function(i){return[i[0],0,0]};Xt.gray.hex=function(i){let u=Math.round(i[0]/100*255)&255,c=((u<<16)+(u<<8)+u).toString(16).toUpperCase();return"000000".substring(c.length)+c};Xt.rgb.gray=function(i){return[(i[0]+i[1]+i[2])/3/255*100]}});var ME=Me((Tb,PE)=>{var Fh=qy();function jN(){let i={},u=Object.keys(Fh);for(let f=u.length,c=0;c{var zy=qy(),WN=ME(),Ca={},HN=Object.keys(zy);function bN(i){let u=function(...f){let c=f[0];return c==null?c:(c.length>1&&(f=c),i(f))};return"conversion"in i&&(u.conversion=i.conversion),u}function GN(i){let u=function(...f){let c=f[0];if(c==null)return c;c.length>1&&(f=c);let g=i(f);if(typeof g=="object")for(let t=g.length,C=0;C{Ca[i]={},Object.defineProperty(Ca[i],"channels",{value:zy[i].channels}),Object.defineProperty(Ca[i],"labels",{value:zy[i].labels});let u=WN(i);Object.keys(u).forEach(c=>{let g=u[c];Ca[i][c]=GN(g),Ca[i][c].raw=bN(g)})});FE.exports=Ca});var Rh=Me((kb,RE)=>{"use strict";var NE=(i,u)=>(...f)=>`[${i(...f)+u}m`,BE=(i,u)=>(...f)=>{let c=i(...f);return`[${38+u};5;${c}m`},jE=(i,u)=>(...f)=>{let c=i(...f);return`[${38+u};2;${c[0]};${c[1]};${c[2]}m`},Lh=i=>i,UE=(i,u,f)=>[i,u,f],Ta=(i,u,f)=>{Object.defineProperty(i,u,{get:()=>{let c=f();return Object.defineProperty(i,u,{value:c,enumerable:!0,configurable:!0}),c},enumerable:!0,configurable:!0})},Wy,xa=(i,u,f,c)=>{Wy===void 0&&(Wy=LE());let g=c?10:0,t={};for(let[C,A]of Object.entries(Wy)){let x=C==="ansi16"?"ansi":C;C===u?t[x]=i(f,g):typeof A=="object"&&(t[x]=i(A[u],g))}return t};function VN(){let i=new Map,u={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};u.color.gray=u.color.blackBright,u.bgColor.bgGray=u.bgColor.bgBlackBright,u.color.grey=u.color.blackBright,u.bgColor.bgGrey=u.bgColor.bgBlackBright;for(let[f,c]of Object.entries(u)){for(let[g,t]of Object.entries(c))u[g]={open:`[${t[0]}m`,close:`[${t[1]}m`},c[g]=u[g],i.set(t[0],t[1]);Object.defineProperty(u,f,{value:c,enumerable:!1})}return Object.defineProperty(u,"codes",{value:i,enumerable:!1}),u.color.close="",u.bgColor.close="",Ta(u.color,"ansi",()=>xa(NE,"ansi16",Lh,!1)),Ta(u.color,"ansi256",()=>xa(BE,"ansi256",Lh,!1)),Ta(u.color,"ansi16m",()=>xa(jE,"rgb",UE,!1)),Ta(u.bgColor,"ansi",()=>xa(NE,"ansi16",Lh,!0)),Ta(u.bgColor,"ansi256",()=>xa(BE,"ansi256",Lh,!0)),Ta(u.bgColor,"ansi16m",()=>xa(jE,"rgb",UE,!0)),u}Object.defineProperty(RE,"exports",{enumerable:!0,get:VN})});var WE=Me((Ab,qE)=>{"use strict";var h2=Mh(),YN=Fy(),$N=Rh(),Hy=new Set(["","\x9B"]),KN=39,zE=i=>`${Hy.values().next().value}[${i}m`,XN=i=>i.split(" ").map(u=>h2(u)),by=(i,u,f)=>{let c=[...u],g=!1,t=h2(YN(i[i.length-1]));for(let[C,A]of c.entries()){let x=h2(A);if(t+x<=f?i[i.length-1]+=A:(i.push(A),t=0),Hy.has(A))g=!0;else if(g&&A==="m"){g=!1;continue}g||(t+=x,t===f&&C0&&i.length>1&&(i[i.length-2]+=i.pop())},JN=i=>{let u=i.split(" "),f=u.length;for(;f>0&&!(h2(u[f-1])>0);)f--;return f===u.length?i:u.slice(0,f).join(" ")+u.slice(f).join("")},QN=(i,u,f={})=>{if(f.trim!==!1&&i.trim()==="")return"";let c="",g="",t,C=XN(i),A=[""];for(let[x,D]of i.split(" ").entries()){f.trim!==!1&&(A[A.length-1]=A[A.length-1].trimLeft());let L=h2(A[A.length-1]);if(x!==0&&(L>=u&&(f.wordWrap===!1||f.trim===!1)&&(A.push(""),L=0),(L>0||f.trim===!1)&&(A[A.length-1]+=" ",L++)),f.hard&&C[x]>u){let N=u-L,j=1+Math.floor((C[x]-N-1)/u);Math.floor((C[x]-1)/u)u&&L>0&&C[x]>0){if(f.wordWrap===!1&&Lu&&f.wordWrap===!1){by(A,D,u);continue}A[A.length-1]+=D}f.trim!==!1&&(A=A.map(JN)),c=A.join(` + `);for(let[x,D]of[...c].entries()){if(g+=D,Hy.has(D)){let N=parseFloat(/\d[^m]*/.exec(c.slice(x,x+4)));t=N===KN?null:N}let L=$N.codes.get(Number(t));t&&L&&(c[x+1]===` + `?g+=zE(L):D===` + `&&(g+=zE(t)))}return g};qE.exports=(i,u,f)=>String(i).normalize().replace(/\r\n/g,` + `).split(` + `).map(c=>QN(c,u,f)).join(` + `)});var GE=Me((Ob,HE)=>{"use strict";var bE="[\uD800-\uDBFF][\uDC00-\uDFFF]",ZN=i=>i&&i.exact?new RegExp(`^${bE}$`):new RegExp(bE,"g");HE.exports=ZN});var Gy=Me((Ib,VE)=>{"use strict";var eB=Ry(),tB=GE(),YE=Rh(),$E=["","\x9B"],Nh=i=>`${$E[0]}[${i}m`,KE=(i,u,f)=>{let c=[];i=[...i];for(let g of i){let t=g;g.match(";")&&(g=g.split(";")[0][0]+"0");let C=YE.codes.get(parseInt(g,10));if(C){let A=i.indexOf(C.toString());A>=0?i.splice(A,1):c.push(Nh(u?C:t))}else if(u){c.push(Nh(0));break}else c.push(Nh(t))}if(u&&(c=c.filter((g,t)=>c.indexOf(g)===t),f!==void 0)){let g=Nh(YE.codes.get(parseInt(f,10)));c=c.reduce((t,C)=>C===g?[C,...t]:[...t,C],[])}return c.join("")};VE.exports=(i,u,f)=>{let c=[...i.normalize()],g=[];f=typeof f=="number"?f:c.length;let t=!1,C,A=0,x="";for(let[D,L]of c.entries()){let N=!1;if($E.includes(L)){let j=/\d[^m]*/.exec(i.slice(D,D+18));C=j&&j.length>0?j[0]:void 0,Au&&A<=f)x+=L;else if(A===u&&!t&&C!==void 0)x=KE(g);else if(A>=f){x+=KE(g,!0,C);break}}return x}});var JE=Me((Pb,XE)=>{"use strict";var Bf=Gy(),nB=Mh();function Bh(i,u,f){if(i.charAt(u)===" ")return u;for(let c=1;c<=3;c++)if(f){if(i.charAt(u+c)===" ")return u+c}else if(i.charAt(u-c)===" ")return u-c;return u}XE.exports=(i,u,f)=>{f=dt({position:"end",preferTruncationOnSpace:!1},f);let{position:c,space:g,preferTruncationOnSpace:t}=f,C="\u2026",A=1;if(typeof i!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof i}`);if(typeof u!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof u}`);if(u<1)return"";if(u===1)return C;let x=nB(i);if(x<=u)return i;if(c==="start"){if(t){let D=Bh(i,x-u+1,!0);return C+Bf(i,D,x).trim()}return g===!0&&(C+=" ",A=2),C+Bf(i,x-u+A,x)}if(c==="middle"){g===!0&&(C=" "+C+" ",A=3);let D=Math.floor(u/2);if(t){let L=Bh(i,D),N=Bh(i,x-(u-D)+1,!0);return Bf(i,0,L)+C+Bf(i,N,x).trim()}return Bf(i,0,D)+C+Bf(i,x-(u-D)+A,x)}if(c==="end"){if(t){let D=Bh(i,u-1);return Bf(i,0,D)+C}return g===!0&&(C=" "+C,A=2),Bf(i,0,u-A)+C}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${c}`)}});var Yy=Me(m2=>{"use strict";var QE=m2&&m2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(m2,"__esModule",{value:!0});var rB=QE(WE()),iB=QE(JE()),Vy={};m2.default=(i,u,f)=>{let c=i+String(u)+String(f);if(Vy[c])return Vy[c];let g=i;if(f==="wrap"&&(g=rB.default(i,u,{trim:!1,hard:!0})),f.startsWith("truncate")){let t="end";f==="truncate-middle"&&(t="middle"),f==="truncate-start"&&(t="start"),g=iB.default(i,u,{position:t})}return Vy[c]=g,g}});var Ky=Me($y=>{"use strict";Object.defineProperty($y,"__esModule",{value:!0});var ZE=i=>{let u="";if(i.childNodes.length>0)for(let f of i.childNodes){let c="";f.nodeName==="#text"?c=f.nodeValue:((f.nodeName==="ink-text"||f.nodeName==="ink-virtual-text")&&(c=ZE(f)),c.length>0&&typeof f.internal_transform=="function"&&(c=f.internal_transform(c))),u+=c}return u};$y.default=ZE});var Xy=Me(Zr=>{"use strict";var v2=Zr&&Zr.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(Zr,"__esModule",{value:!0});Zr.setTextNodeValue=Zr.createTextNode=Zr.setStyle=Zr.setAttribute=Zr.removeChildNode=Zr.insertBeforeNode=Zr.appendChildNode=Zr.createNode=Zr.TEXT_NAME=void 0;var oB=v2(hc()),e6=v2(TE()),uB=v2(xE()),sB=v2(Yy()),lB=v2(Ky());Zr.TEXT_NAME="#text";Zr.createNode=i=>{var u;let f={nodeName:i,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:i==="ink-virtual-text"?void 0:oB.default.Node.create()};return i==="ink-text"&&((u=f.yogaNode)===null||u===void 0||u.setMeasureFunc(fB.bind(null,f))),f};Zr.appendChildNode=(i,u)=>{var f;u.parentNode&&Zr.removeChildNode(u.parentNode,u),u.parentNode=i,i.childNodes.push(u),u.yogaNode&&((f=i.yogaNode)===null||f===void 0||f.insertChild(u.yogaNode,i.yogaNode.getChildCount())),(i.nodeName==="ink-text"||i.nodeName==="ink-virtual-text")&&jh(i)};Zr.insertBeforeNode=(i,u,f)=>{var c,g;u.parentNode&&Zr.removeChildNode(u.parentNode,u),u.parentNode=i;let t=i.childNodes.indexOf(f);if(t>=0){i.childNodes.splice(t,0,u),u.yogaNode&&((c=i.yogaNode)===null||c===void 0||c.insertChild(u.yogaNode,t));return}i.childNodes.push(u),u.yogaNode&&((g=i.yogaNode)===null||g===void 0||g.insertChild(u.yogaNode,i.yogaNode.getChildCount())),(i.nodeName==="ink-text"||i.nodeName==="ink-virtual-text")&&jh(i)};Zr.removeChildNode=(i,u)=>{var f,c;u.yogaNode&&((c=(f=u.parentNode)===null||f===void 0?void 0:f.yogaNode)===null||c===void 0||c.removeChild(u.yogaNode)),u.parentNode=null;let g=i.childNodes.indexOf(u);g>=0&&i.childNodes.splice(g,1),(i.nodeName==="ink-text"||i.nodeName==="ink-virtual-text")&&jh(i)};Zr.setAttribute=(i,u,f)=>{i.attributes[u]=f};Zr.setStyle=(i,u)=>{i.style=u,i.yogaNode&&uB.default(i.yogaNode,u)};Zr.createTextNode=i=>{let u={nodeName:"#text",nodeValue:i,yogaNode:void 0,parentNode:null,style:{}};return Zr.setTextNodeValue(u,i),u};var fB=function(i,u){var f,c;let g=i.nodeName==="#text"?i.nodeValue:lB.default(i),t=e6.default(g);if(t.width<=u||t.width>=1&&u>0&&u<1)return t;let C=(c=(f=i.style)===null||f===void 0?void 0:f.textWrap)!==null&&c!==void 0?c:"wrap",A=sB.default(g,u,C);return e6.default(A)},t6=i=>{var u;if(!(!i||!i.parentNode))return(u=i.yogaNode)!==null&&u!==void 0?u:t6(i.parentNode)},jh=i=>{let u=t6(i);u==null||u.markDirty()};Zr.setTextNodeValue=(i,u)=>{typeof u!="string"&&(u=String(u)),i.nodeValue=u,jh(i)}});var mc=Me((Rb,n6)=>{"use strict";n6.exports={BINARY_TYPES:["nodebuffer","arraybuffer","fragments"],GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),EMPTY_BUFFER:Buffer.alloc(0),NOOP:()=>{}}});var g2=Me((Nb,Jy)=>{"use strict";var{EMPTY_BUFFER:cB}=mc();function r6(i,u){if(i.length===0)return cB;if(i.length===1)return i[0];let f=Buffer.allocUnsafe(u),c=0;for(let g=0;g{"use strict";var l6=Symbol("kDone"),Qy=Symbol("kRun"),f6=class{constructor(u){this[l6]=()=>{this.pending--,this[Qy]()},this.concurrency=u||Infinity,this.jobs=[],this.pending=0}add(u){this.jobs.push(u),this[Qy]()}[Qy](){if(this.pending!==this.concurrency&&this.jobs.length){let u=this.jobs.shift();this.pending++,u(this[l6])}}};s6.exports=f6});var w2=Me((jb,a6)=>{"use strict";var _2=require("zlib"),d6=g2(),aB=c6(),{kStatusCode:p6,NOOP:dB}=mc(),pB=Buffer.from([0,0,255,255]),qh=Symbol("permessage-deflate"),Xl=Symbol("total-length"),y2=Symbol("callback"),jf=Symbol("buffers"),Zy=Symbol("error"),zh,h6=class{constructor(u,f,c){if(this._maxPayload=c|0,this._options=u||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._isServer=!!f,this._deflate=null,this._inflate=null,this.params=null,!zh){let g=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;zh=new aB(g)}}static get extensionName(){return"permessage-deflate"}offer(){let u={};return this._options.serverNoContextTakeover&&(u.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(u.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(u.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?u.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(u.client_max_window_bits=!0),u}accept(u){return u=this.normalizeParams(u),this.params=this._isServer?this.acceptAsServer(u):this.acceptAsClient(u),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let u=this._deflate[y2];this._deflate.close(),this._deflate=null,u&&u(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(u){let f=this._options,c=u.find(g=>!(f.serverNoContextTakeover===!1&&g.server_no_context_takeover||g.server_max_window_bits&&(f.serverMaxWindowBits===!1||typeof f.serverMaxWindowBits=="number"&&f.serverMaxWindowBits>g.server_max_window_bits)||typeof f.clientMaxWindowBits=="number"&&!g.client_max_window_bits));if(!c)throw new Error("None of the extension offers can be accepted");return f.serverNoContextTakeover&&(c.server_no_context_takeover=!0),f.clientNoContextTakeover&&(c.client_no_context_takeover=!0),typeof f.serverMaxWindowBits=="number"&&(c.server_max_window_bits=f.serverMaxWindowBits),typeof f.clientMaxWindowBits=="number"?c.client_max_window_bits=f.clientMaxWindowBits:(c.client_max_window_bits===!0||f.clientMaxWindowBits===!1)&&delete c.client_max_window_bits,c}acceptAsClient(u){let f=u[0];if(this._options.clientNoContextTakeover===!1&&f.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!f.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(f.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&f.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return f}normalizeParams(u){return u.forEach(f=>{Object.keys(f).forEach(c=>{let g=f[c];if(g.length>1)throw new Error(`Parameter "${c}" must have only a single value`);if(g=g[0],c==="client_max_window_bits"){if(g!==!0){let t=+g;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${c}": ${g}`);g=t}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${c}": ${g}`)}else if(c==="server_max_window_bits"){let t=+g;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${c}": ${g}`);g=t}else if(c==="client_no_context_takeover"||c==="server_no_context_takeover"){if(g!==!0)throw new TypeError(`Invalid value for parameter "${c}": ${g}`)}else throw new Error(`Unknown parameter "${c}"`);f[c]=g})}),u}decompress(u,f,c){zh.add(g=>{this._decompress(u,f,(t,C)=>{g(),c(t,C)})})}compress(u,f,c){zh.add(g=>{this._compress(u,f,(t,C)=>{g(),c(t,C)})})}_decompress(u,f,c){let g=this._isServer?"client":"server";if(!this._inflate){let t=`${g}_max_window_bits`,C=typeof this.params[t]!="number"?_2.Z_DEFAULT_WINDOWBITS:this.params[t];this._inflate=_2.createInflateRaw(zn(dt({},this._options.zlibInflateOptions),{windowBits:C})),this._inflate[qh]=this,this._inflate[Xl]=0,this._inflate[jf]=[],this._inflate.on("error",mB),this._inflate.on("data",m6)}this._inflate[y2]=c,this._inflate.write(u),f&&this._inflate.write(pB),this._inflate.flush(()=>{let t=this._inflate[Zy];if(t){this._inflate.close(),this._inflate=null,c(t);return}let C=d6.concat(this._inflate[jf],this._inflate[Xl]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[Xl]=0,this._inflate[jf]=[],f&&this.params[`${g}_no_context_takeover`]&&this._inflate.reset()),c(null,C)})}_compress(u,f,c){let g=this._isServer?"server":"client";if(!this._deflate){let t=`${g}_max_window_bits`,C=typeof this.params[t]!="number"?_2.Z_DEFAULT_WINDOWBITS:this.params[t];this._deflate=_2.createDeflateRaw(zn(dt({},this._options.zlibDeflateOptions),{windowBits:C})),this._deflate[Xl]=0,this._deflate[jf]=[],this._deflate.on("error",dB),this._deflate.on("data",hB)}this._deflate[y2]=c,this._deflate.write(u),this._deflate.flush(_2.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let t=d6.concat(this._deflate[jf],this._deflate[Xl]);f&&(t=t.slice(0,t.length-4)),this._deflate[y2]=null,this._deflate[Xl]=0,this._deflate[jf]=[],f&&this.params[`${g}_no_context_takeover`]&&this._deflate.reset(),c(null,t)})}};a6.exports=h6;function hB(i){this[jf].push(i),this[Xl]+=i.length}function m6(i){if(this[Xl]+=i.length,this[qh]._maxPayload<1||this[Xl]<=this[qh]._maxPayload){this[jf].push(i);return}this[Zy]=new RangeError("Max payload size exceeded"),this[Zy][p6]=1009,this.removeListener("data",m6),this.reset()}function mB(i){this[qh]._inflate=null,i[p6]=1007,this[y2](i)}});var t3=Me((Ub,e3)=>{"use strict";function v6(i){return i>=1e3&&i<=1014&&i!==1004&&i!==1005&&i!==1006||i>=3e3&&i<=4999}function g6(i){let u=i.length,f=0;for(;f=u||(i[f+1]&192)!=128||(i[f+2]&192)!=128||i[f]===224&&(i[f+1]&224)==128||i[f]===237&&(i[f+1]&224)==160)return!1;f+=3}else if((i[f]&248)==240){if(f+3>=u||(i[f+1]&192)!=128||(i[f+2]&192)!=128||(i[f+3]&192)!=128||i[f]===240&&(i[f+1]&240)==128||i[f]===244&&i[f+1]>143||i[f]>244)return!1;f+=4}else return!1;return!0}try{let i=require("utf-8-validate");typeof i=="object"&&(i=i.Validation.isValidUTF8),e3.exports={isValidStatusCode:v6,isValidUTF8(u){return u.length<150?g6(u):i(u)}}}catch(i){e3.exports={isValidStatusCode:v6,isValidUTF8:g6}}});var i3=Me((qb,_6)=>{"use strict";var{Writable:vB}=require("stream"),y6=w2(),{BINARY_TYPES:gB,EMPTY_BUFFER:_B,kStatusCode:yB,kWebSocket:wB}=mc(),{concat:n3,toArrayBuffer:DB,unmask:EB}=g2(),{isValidStatusCode:SB,isValidUTF8:w6}=t3(),D2=0,D6=1,E6=2,S6=3,r3=4,CB=5,C6=class extends vB{constructor(u,f,c,g){super();this._binaryType=u||gB[0],this[wB]=void 0,this._extensions=f||{},this._isServer=!!c,this._maxPayload=g|0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._state=D2,this._loop=!1}_write(u,f,c){if(this._opcode===8&&this._state==D2)return c();this._bufferedBytes+=u.length,this._buffers.push(u),this.startLoop(c)}consume(u){if(this._bufferedBytes-=u,u===this._buffers[0].length)return this._buffers.shift();if(u=c.length?f.set(this._buffers.shift(),g):(f.set(new Uint8Array(c.buffer,c.byteOffset,u),g),this._buffers[0]=c.slice(u)),u-=c.length}while(u>0);return f}startLoop(u){let f;this._loop=!0;do switch(this._state){case D2:f=this.getInfo();break;case D6:f=this.getPayloadLength16();break;case E6:f=this.getPayloadLength64();break;case S6:this.getMask();break;case r3:f=this.getData(u);break;default:this._loop=!1;return}while(this._loop);u(f)}getInfo(){if(this._bufferedBytes<2){this._loop=!1;return}let u=this.consume(2);if((u[0]&48)!=0)return this._loop=!1,ii(RangeError,"RSV2 and RSV3 must be clear",!0,1002);let f=(u[0]&64)==64;if(f&&!this._extensions[y6.extensionName])return this._loop=!1,ii(RangeError,"RSV1 must be clear",!0,1002);if(this._fin=(u[0]&128)==128,this._opcode=u[0]&15,this._payloadLength=u[1]&127,this._opcode===0){if(f)return this._loop=!1,ii(RangeError,"RSV1 must be clear",!0,1002);if(!this._fragmented)return this._loop=!1,ii(RangeError,"invalid opcode 0",!0,1002);this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented)return this._loop=!1,ii(RangeError,`invalid opcode ${this._opcode}`,!0,1002);this._compressed=f}else if(this._opcode>7&&this._opcode<11){if(!this._fin)return this._loop=!1,ii(RangeError,"FIN must be set",!0,1002);if(f)return this._loop=!1,ii(RangeError,"RSV1 must be clear",!0,1002);if(this._payloadLength>125)return this._loop=!1,ii(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002)}else return this._loop=!1,ii(RangeError,`invalid opcode ${this._opcode}`,!0,1002);if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(u[1]&128)==128,this._isServer){if(!this._masked)return this._loop=!1,ii(RangeError,"MASK must be set",!0,1002)}else if(this._masked)return this._loop=!1,ii(RangeError,"MASK must be clear",!0,1002);if(this._payloadLength===126)this._state=D6;else if(this._payloadLength===127)this._state=E6;else return this.haveLength()}getPayloadLength16(){if(this._bufferedBytes<2){this._loop=!1;return}return this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength()}getPayloadLength64(){if(this._bufferedBytes<8){this._loop=!1;return}let u=this.consume(8),f=u.readUInt32BE(0);return f>Math.pow(2,53-32)-1?(this._loop=!1,ii(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009)):(this._payloadLength=f*Math.pow(2,32)+u.readUInt32BE(4),this.haveLength())}haveLength(){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0))return this._loop=!1,ii(RangeError,"Max payload size exceeded",!1,1009);this._masked?this._state=S6:this._state=r3}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=r3}getData(u){let f=_B;if(this._payloadLength){if(this._bufferedBytes7)return this.controlMessage(f);if(this._compressed){this._state=CB,this.decompress(f,u);return}return f.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(f)),this.dataMessage()}decompress(u,f){this._extensions[y6.extensionName].decompress(u,this._fin,(g,t)=>{if(g)return f(g);if(t.length){if(this._messageLength+=t.length,this._messageLength>this._maxPayload&&this._maxPayload>0)return f(ii(RangeError,"Max payload size exceeded",!1,1009));this._fragments.push(t)}let C=this.dataMessage();if(C)return f(C);this.startLoop(f)})}dataMessage(){if(this._fin){let u=this._messageLength,f=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let c;this._binaryType==="nodebuffer"?c=n3(f,u):this._binaryType==="arraybuffer"?c=DB(n3(f,u)):c=f,this.emit("message",c)}else{let c=n3(f,u);if(!w6(c))return this._loop=!1,ii(Error,"invalid UTF-8 sequence",!0,1007);this.emit("message",c.toString())}}this._state=D2}controlMessage(u){if(this._opcode===8)if(this._loop=!1,u.length===0)this.emit("conclude",1005,""),this.end();else{if(u.length===1)return ii(RangeError,"invalid payload length 1",!0,1002);{let f=u.readUInt16BE(0);if(!SB(f))return ii(RangeError,`invalid status code ${f}`,!0,1002);let c=u.slice(2);if(!w6(c))return ii(Error,"invalid UTF-8 sequence",!0,1007);this.emit("conclude",f,c.toString()),this.end()}}else this._opcode===9?this.emit("ping",u):this.emit("pong",u);this._state=D2}};_6.exports=C6;function ii(i,u,f,c){let g=new i(f?`Invalid WebSocket frame: ${u}`:u);return Error.captureStackTrace(g,ii),g[yB]=c,g}});var o3=Me((zb,T6)=>{"use strict";var{randomFillSync:TB}=require("crypto"),x6=w2(),{EMPTY_BUFFER:xB}=mc(),{isValidStatusCode:kB}=t3(),{mask:k6,toBuffer:Jl}=g2(),vc=Buffer.alloc(4),Ql=class{constructor(u,f){this._extensions=f||{},this._socket=u,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._deflating=!1,this._queue=[]}static frame(u,f){let c=f.mask&&f.readOnly,g=f.mask?6:2,t=u.length;u.length>=65536?(g+=8,t=127):u.length>125&&(g+=2,t=126);let C=Buffer.allocUnsafe(c?u.length+g:g);return C[0]=f.fin?f.opcode|128:f.opcode,f.rsv1&&(C[0]|=64),C[1]=t,t===126?C.writeUInt16BE(u.length,2):t===127&&(C.writeUInt32BE(0,2),C.writeUInt32BE(u.length,6)),f.mask?(TB(vc,0,4),C[1]|=128,C[g-4]=vc[0],C[g-3]=vc[1],C[g-2]=vc[2],C[g-1]=vc[3],c?(k6(u,vc,C,g,u.length),[C]):(k6(u,vc,u,0,u.length),[C,u])):[C,u]}close(u,f,c,g){let t;if(u===void 0)t=xB;else{if(typeof u!="number"||!kB(u))throw new TypeError("First argument must be a valid error code number");if(f===void 0||f==="")t=Buffer.allocUnsafe(2),t.writeUInt16BE(u,0);else{let C=Buffer.byteLength(f);if(C>123)throw new RangeError("The message must not be greater than 123 bytes");t=Buffer.allocUnsafe(2+C),t.writeUInt16BE(u,0),t.write(f,2)}}this._deflating?this.enqueue([this.doClose,t,c,g]):this.doClose(t,c,g)}doClose(u,f,c){this.sendFrame(Ql.frame(u,{fin:!0,rsv1:!1,opcode:8,mask:f,readOnly:!1}),c)}ping(u,f,c){let g=Jl(u);if(g.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPing,g,f,Jl.readOnly,c]):this.doPing(g,f,Jl.readOnly,c)}doPing(u,f,c,g){this.sendFrame(Ql.frame(u,{fin:!0,rsv1:!1,opcode:9,mask:f,readOnly:c}),g)}pong(u,f,c){let g=Jl(u);if(g.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPong,g,f,Jl.readOnly,c]):this.doPong(g,f,Jl.readOnly,c)}doPong(u,f,c,g){this.sendFrame(Ql.frame(u,{fin:!0,rsv1:!1,opcode:10,mask:f,readOnly:c}),g)}send(u,f,c){let g=Jl(u),t=this._extensions[x6.extensionName],C=f.binary?2:1,A=f.compress;if(this._firstFragment?(this._firstFragment=!1,A&&t&&(A=g.length>=t._threshold),this._compress=A):(A=!1,C=0),f.fin&&(this._firstFragment=!0),t){let x={fin:f.fin,rsv1:A,opcode:C,mask:f.mask,readOnly:Jl.readOnly};this._deflating?this.enqueue([this.dispatch,g,this._compress,x,c]):this.dispatch(g,this._compress,x,c)}else this.sendFrame(Ql.frame(g,{fin:f.fin,rsv1:!1,opcode:C,mask:f.mask,readOnly:Jl.readOnly}),c)}dispatch(u,f,c,g){if(!f){this.sendFrame(Ql.frame(u,c),g);return}let t=this._extensions[x6.extensionName];this._bufferedBytes+=u.length,this._deflating=!0,t.compress(u,c.fin,(C,A)=>{if(this._socket.destroyed){let x=new Error("The socket was closed while data was being compressed");typeof g=="function"&&g(x);for(let D=0;D{"use strict";var E2=class{constructor(u,f){this.target=f,this.type=u}},O6=class extends E2{constructor(u,f){super("message",f);this.data=u}},I6=class extends E2{constructor(u,f,c){super("close",c);this.wasClean=c._closeFrameReceived&&c._closeFrameSent,this.reason=f,this.code=u}},P6=class extends E2{constructor(u){super("open",u)}},M6=class extends E2{constructor(u,f){super("error",f);this.message=u.message,this.error=u}},AB={addEventListener(i,u,f){if(typeof u!="function")return;function c(x){u.call(this,new O6(x,this))}function g(x,D){u.call(this,new I6(x,D,this))}function t(x){u.call(this,new M6(x,this))}function C(){u.call(this,new P6(this))}let A=f&&f.once?"once":"on";i==="message"?(c._listener=u,this[A](i,c)):i==="close"?(g._listener=u,this[A](i,g)):i==="error"?(t._listener=u,this[A](i,t)):i==="open"?(C._listener=u,this[A](i,C)):this[A](i,u)},removeEventListener(i,u){let f=this.listeners(i);for(let c=0;c{"use strict";var S2=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function rl(i,u,f){i[u]===void 0?i[u]=[f]:i[u].push(f)}function OB(i){let u=Object.create(null);if(i===void 0||i==="")return u;let f=Object.create(null),c=!1,g=!1,t=!1,C,A,x=-1,D=-1,L=0;for(;L{let f=i[u];return Array.isArray(f)||(f=[f]),f.map(c=>[u].concat(Object.keys(c).map(g=>{let t=c[g];return Array.isArray(t)||(t=[t]),t.map(C=>C===!0?g:`${g}=${C}`).join("; ")})).join("; ")).join(", ")}).join(", ")}L6.exports={format:IB,parse:OB}});var a3=Me((bb,R6)=>{"use strict";var PB=require("events"),MB=require("https"),FB=require("http"),N6=require("net"),LB=require("tls"),{randomBytes:RB,createHash:NB}=require("crypto"),{URL:s3}=require("url"),Uf=w2(),BB=i3(),jB=o3(),{BINARY_TYPES:B6,EMPTY_BUFFER:l3,GUID:UB,kStatusCode:qB,kWebSocket:No,NOOP:j6}=mc(),{addEventListener:zB,removeEventListener:WB}=F6(),{format:HB,parse:bB}=u3(),{toBuffer:GB}=g2(),U6=["CONNECTING","OPEN","CLOSING","CLOSED"],f3=[8,13],VB=30*1e3,mr=class extends PB{constructor(u,f,c){super();this._binaryType=B6[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage="",this._closeTimer=null,this._extensions={},this._protocol="",this._readyState=mr.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,u!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,Array.isArray(f)?f=f.join(", "):typeof f=="object"&&f!==null&&(c=f,f=void 0),q6(this,u,f,c)):this._isServer=!0}get binaryType(){return this._binaryType}set binaryType(u){!B6.includes(u)||(this._binaryType=u,this._receiver&&(this._receiver._binaryType=u))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(u,f,c){let g=new BB(this.binaryType,this._extensions,this._isServer,c);this._sender=new jB(u,this._extensions),this._receiver=g,this._socket=u,g[No]=this,u[No]=this,g.on("conclude",YB),g.on("drain",$B),g.on("error",KB),g.on("message",XB),g.on("ping",JB),g.on("pong",QB),u.setTimeout(0),u.setNoDelay(),f.length>0&&u.unshift(f),u.on("close",z6),u.on("data",Wh),u.on("end",W6),u.on("error",H6),this._readyState=mr.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=mr.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[Uf.extensionName]&&this._extensions[Uf.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=mr.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(u,f){if(this.readyState!==mr.CLOSED){if(this.readyState===mr.CONNECTING){let c="WebSocket was closed before the connection was established";return Zl(this,this._req,c)}if(this.readyState===mr.CLOSING){this._closeFrameSent&&this._closeFrameReceived&&this._socket.end();return}this._readyState=mr.CLOSING,this._sender.close(u,f,!this._isServer,c=>{c||(this._closeFrameSent=!0,this._closeFrameReceived&&this._socket.end())}),this._closeTimer=setTimeout(this._socket.destroy.bind(this._socket),VB)}}ping(u,f,c){if(this.readyState===mr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof u=="function"?(c=u,u=f=void 0):typeof f=="function"&&(c=f,f=void 0),typeof u=="number"&&(u=u.toString()),this.readyState!==mr.OPEN){c3(this,u,c);return}f===void 0&&(f=!this._isServer),this._sender.ping(u||l3,f,c)}pong(u,f,c){if(this.readyState===mr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof u=="function"?(c=u,u=f=void 0):typeof f=="function"&&(c=f,f=void 0),typeof u=="number"&&(u=u.toString()),this.readyState!==mr.OPEN){c3(this,u,c);return}f===void 0&&(f=!this._isServer),this._sender.pong(u||l3,f,c)}send(u,f,c){if(this.readyState===mr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof f=="function"&&(c=f,f={}),typeof u=="number"&&(u=u.toString()),this.readyState!==mr.OPEN){c3(this,u,c);return}let g=dt({binary:typeof u!="string",mask:!this._isServer,compress:!0,fin:!0},f);this._extensions[Uf.extensionName]||(g.compress=!1),this._sender.send(u||l3,g,c)}terminate(){if(this.readyState!==mr.CLOSED){if(this.readyState===mr.CONNECTING){let u="WebSocket was closed before the connection was established";return Zl(this,this._req,u)}this._socket&&(this._readyState=mr.CLOSING,this._socket.destroy())}}};U6.forEach((i,u)=>{let f={enumerable:!0,value:u};Object.defineProperty(mr.prototype,i,f),Object.defineProperty(mr,i,f)});["binaryType","bufferedAmount","extensions","protocol","readyState","url"].forEach(i=>{Object.defineProperty(mr.prototype,i,{enumerable:!0})});["open","error","close","message"].forEach(i=>{Object.defineProperty(mr.prototype,`on${i}`,{configurable:!0,enumerable:!0,get(){let u=this.listeners(i);for(let f=0;f{Zl(i,j,"Opening handshake has timed out")}),j.on("error",$=>{j===null||j.aborted||(j=i._req=null,i._readyState=mr.CLOSING,i.emit("error",$),i.emitClose())}),j.on("response",$=>{let h=$.headers.location,re=$.statusCode;if(h&&g.followRedirects&&re>=300&&re<400){if(++i._redirects>g.maxRedirects){Zl(i,j,"Maximum redirects exceeded");return}j.abort();let ce=new s3(h,u);q6(i,ce,f,c)}else i.emit("unexpected-response",j,$)||Zl(i,j,`Unexpected server response: ${$.statusCode}`)}),j.on("upgrade",($,h,re)=>{if(i.emit("upgrade",$),i.readyState!==mr.CONNECTING)return;j=i._req=null;let ce=NB("sha1").update(D+UB).digest("base64");if($.headers["sec-websocket-accept"]!==ce){Zl(i,h,"Invalid Sec-WebSocket-Accept header");return}let Q=$.headers["sec-websocket-protocol"],oe=(f||"").split(/, */),Se;if(!f&&Q?Se="Server sent a subprotocol but none was requested":f&&!Q?Se="Server sent no subprotocol":Q&&!oe.includes(Q)&&(Se="Server sent an invalid subprotocol"),Se){Zl(i,h,Se);return}if(Q&&(i._protocol=Q),N)try{let me=bB($.headers["sec-websocket-extensions"]);me[Uf.extensionName]&&(N.accept(me[Uf.extensionName]),i._extensions[Uf.extensionName]=N)}catch(me){Zl(i,h,"Invalid Sec-WebSocket-Extensions header");return}i.setSocket(h,re,g.maxPayload)})}function ZB(i){return i.path=i.socketPath,N6.connect(i)}function ej(i){return i.path=void 0,!i.servername&&i.servername!==""&&(i.servername=N6.isIP(i.host)?"":i.host),LB.connect(i)}function Zl(i,u,f){i._readyState=mr.CLOSING;let c=new Error(f);Error.captureStackTrace(c,Zl),u.setHeader?(u.abort(),u.socket&&!u.socket.destroyed&&u.socket.destroy(),u.once("abort",i.emitClose.bind(i)),i.emit("error",c)):(u.destroy(c),u.once("error",i.emit.bind(i,"error")),u.once("close",i.emitClose.bind(i)))}function c3(i,u,f){if(u){let c=GB(u).length;i._socket?i._sender._bufferedBytes+=c:i._bufferedAmount+=c}if(f){let c=new Error(`WebSocket is not open: readyState ${i.readyState} (${U6[i.readyState]})`);f(c)}}function YB(i,u){let f=this[No];f._socket.removeListener("data",Wh),f._socket.resume(),f._closeFrameReceived=!0,f._closeMessage=u,f._closeCode=i,i===1005?f.close():f.close(i,u)}function $B(){this[No]._socket.resume()}function KB(i){let u=this[No];u._socket.removeListener("data",Wh),u._readyState=mr.CLOSING,u._closeCode=i[qB],u.emit("error",i),u._socket.destroy()}function b6(){this[No].emitClose()}function XB(i){this[No].emit("message",i)}function JB(i){let u=this[No];u.pong(i,!u._isServer,j6),u.emit("ping",i)}function QB(i){this[No].emit("pong",i)}function z6(){let i=this[No];this.removeListener("close",z6),this.removeListener("end",W6),i._readyState=mr.CLOSING,i._socket.read(),i._receiver.end(),this.removeListener("data",Wh),this[No]=void 0,clearTimeout(i._closeTimer),i._receiver._writableState.finished||i._receiver._writableState.errorEmitted?i.emitClose():(i._receiver.on("error",b6),i._receiver.on("finish",b6))}function Wh(i){this[No]._receiver.write(i)||this.pause()}function W6(){let i=this[No];i._readyState=mr.CLOSING,i._receiver.end(),this.end()}function H6(){let i=this[No];this.removeListener("error",H6),this.on("error",j6),i&&(i._readyState=mr.CLOSING,this.destroy())}});var $6=Me((Gb,G6)=>{"use strict";var{Duplex:tj}=require("stream");function V6(i){i.emit("close")}function nj(){!this.destroyed&&this._writableState.finished&&this.destroy()}function Y6(i){this.removeListener("error",Y6),this.destroy(),this.listenerCount("error")===0&&this.emit("error",i)}function rj(i,u){let f=!0;function c(){f&&i._socket.resume()}i.readyState===i.CONNECTING?i.once("open",function(){i._receiver.removeAllListeners("drain"),i._receiver.on("drain",c)}):(i._receiver.removeAllListeners("drain"),i._receiver.on("drain",c));let g=new tj(zn(dt({},u),{autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1}));return i.on("message",function(C){g.push(C)||(f=!1,i._socket.pause())}),i.once("error",function(C){g.destroyed||g.destroy(C)}),i.once("close",function(){g.destroyed||g.push(null)}),g._destroy=function(t,C){if(i.readyState===i.CLOSED){C(t),process.nextTick(V6,g);return}let A=!1;i.once("error",function(D){A=!0,C(D)}),i.once("close",function(){A||C(t),process.nextTick(V6,g)}),i.terminate()},g._final=function(t){if(i.readyState===i.CONNECTING){i.once("open",function(){g._final(t)});return}i._socket!==null&&(i._socket._writableState.finished?(t(),g._readableState.endEmitted&&g.destroy()):(i._socket.once("finish",function(){t()}),i.close()))},g._read=function(){i.readyState===i.OPEN&&!f&&(f=!0,i._receiver._writableState.needDrain||i._socket.resume())},g._write=function(t,C,A){if(i.readyState===i.CONNECTING){i.once("open",function(){g._write(t,C,A)});return}i.send(t,A)},g.on("end",nj),g.on("error",Y6),g}G6.exports=rj});var J6=Me((Vb,K6)=>{"use strict";var ij=require("events"),{createHash:oj}=require("crypto"),{createServer:uj,STATUS_CODES:d3}=require("http"),gc=w2(),sj=a3(),{format:lj,parse:fj}=u3(),{GUID:cj,kWebSocket:aj}=mc(),dj=/^[+/0-9A-Za-z]{22}==$/,X6=class extends ij{constructor(u,f){super();if(u=dt({maxPayload:100*1024*1024,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null},u),u.port==null&&!u.server&&!u.noServer)throw new TypeError('One of the "port", "server", or "noServer" options must be specified');if(u.port!=null?(this._server=uj((c,g)=>{let t=d3[426];g.writeHead(426,{"Content-Length":t.length,"Content-Type":"text/plain"}),g.end(t)}),this._server.listen(u.port,u.host,u.backlog,f)):u.server&&(this._server=u.server),this._server){let c=this.emit.bind(this,"connection");this._removeListeners=pj(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(g,t,C)=>{this.handleUpgrade(g,t,C,c)}})}u.perMessageDeflate===!0&&(u.perMessageDeflate={}),u.clientTracking&&(this.clients=new Set),this.options=u}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(u){if(u&&this.once("close",u),this.clients)for(let c of this.clients)c.terminate();let f=this._server;if(f&&(this._removeListeners(),this._removeListeners=this._server=null,this.options.port!=null)){f.close(()=>this.emit("close"));return}process.nextTick(hj,this)}shouldHandle(u){if(this.options.path){let f=u.url.indexOf("?");if((f!==-1?u.url.slice(0,f):u.url)!==this.options.path)return!1}return!0}handleUpgrade(u,f,c,g){f.on("error",p3);let t=u.headers["sec-websocket-key"]!==void 0?u.headers["sec-websocket-key"].trim():!1,C=+u.headers["sec-websocket-version"],A={};if(u.method!=="GET"||u.headers.upgrade.toLowerCase()!=="websocket"||!t||!dj.test(t)||C!==8&&C!==13||!this.shouldHandle(u))return Hh(f,400);if(this.options.perMessageDeflate){let x=new gc(this.options.perMessageDeflate,!0,this.options.maxPayload);try{let D=fj(u.headers["sec-websocket-extensions"]);D[gc.extensionName]&&(x.accept(D[gc.extensionName]),A[gc.extensionName]=x)}catch(D){return Hh(f,400)}}if(this.options.verifyClient){let x={origin:u.headers[`${C===8?"sec-websocket-origin":"origin"}`],secure:!!(u.socket.authorized||u.socket.encrypted),req:u};if(this.options.verifyClient.length===2){this.options.verifyClient(x,(D,L,N,j)=>{if(!D)return Hh(f,L||401,N,j);this.completeUpgrade(t,A,u,f,c,g)});return}if(!this.options.verifyClient(x))return Hh(f,401)}this.completeUpgrade(t,A,u,f,c,g)}completeUpgrade(u,f,c,g,t,C){if(!g.readable||!g.writable)return g.destroy();if(g[aj])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");let A=oj("sha1").update(u+cj).digest("base64"),x=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${A}`],D=new sj(null),L=c.headers["sec-websocket-protocol"];if(L&&(L=L.split(",").map(mj),this.options.handleProtocols?L=this.options.handleProtocols(L,c):L=L[0],L&&(x.push(`Sec-WebSocket-Protocol: ${L}`),D._protocol=L)),f[gc.extensionName]){let N=f[gc.extensionName].params,j=lj({[gc.extensionName]:[N]});x.push(`Sec-WebSocket-Extensions: ${j}`),D._extensions=f}this.emit("headers",x,c),g.write(x.concat(`\r + `).join(`\r + `)),g.removeListener("error",p3),D.setSocket(g,t,this.options.maxPayload),this.clients&&(this.clients.add(D),D.on("close",()=>this.clients.delete(D))),C(D,c)}};K6.exports=X6;function pj(i,u){for(let f of Object.keys(u))i.on(f,u[f]);return function(){for(let c of Object.keys(u))i.removeListener(c,u[c])}}function hj(i){i.emit("close")}function p3(){this.destroy()}function Hh(i,u,f,c){i.writable&&(f=f||d3[u],c=dt({Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(f)},c),i.write(`HTTP/1.1 ${u} ${d3[u]}\r + `+Object.keys(c).map(g=>`${g}: ${c[g]}`).join(`\r + `)+`\r + \r + `+f)),i.removeListener("error",p3),i.destroy()}function mj(i){return i.trim()}});var Z6=Me((Yb,Q6)=>{"use strict";var C2=a3();C2.createWebSocketStream=$6();C2.Server=J6();C2.Receiver=i3();C2.Sender=o3();Q6.exports=C2});var eS=Me(bh=>{"use strict";var vj=bh&&bh.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(bh,"__esModule",{value:!0});var gj=vj(Z6()),T2=global;T2.WebSocket||(T2.WebSocket=gj.default);T2.window||(T2.window=global);T2.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__=[{type:1,value:7,isEnabled:!0},{type:2,value:"InternalApp",isEnabled:!0,isValid:!0},{type:2,value:"InternalAppContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdoutContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStderrContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdinContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalFocusContext",isEnabled:!0,isValid:!0}]});var tS=Me((Gh,h3)=>{(function(i,u){typeof Gh=="object"&&typeof h3=="object"?h3.exports=u():typeof define=="function"&&define.amd?define([],u):typeof Gh=="object"?Gh.ReactDevToolsBackend=u():i.ReactDevToolsBackend=u()})(window,function(){return function(i){var u={};function f(c){if(u[c])return u[c].exports;var g=u[c]={i:c,l:!1,exports:{}};return i[c].call(g.exports,g,g.exports,f),g.l=!0,g.exports}return f.m=i,f.c=u,f.d=function(c,g,t){f.o(c,g)||Object.defineProperty(c,g,{enumerable:!0,get:t})},f.r=function(c){typeof Symbol!="undefined"&&Symbol.toStringTag&&Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(c,"__esModule",{value:!0})},f.t=function(c,g){if(1&g&&(c=f(c)),8&g||4&g&&typeof c=="object"&&c&&c.__esModule)return c;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:c}),2&g&&typeof c!="string")for(var C in c)f.d(t,C,function(A){return c[A]}.bind(null,C));return t},f.n=function(c){var g=c&&c.__esModule?function(){return c.default}:function(){return c};return f.d(g,"a",g),g},f.o=function(c,g){return Object.prototype.hasOwnProperty.call(c,g)},f.p="",f(f.s=20)}([function(i,u,f){"use strict";i.exports=f(12)},function(i,u,f){"use strict";var c=Object.getOwnPropertySymbols,g=Object.prototype.hasOwnProperty,t=Object.prototype.propertyIsEnumerable;function C(A){if(A==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(A)}i.exports=function(){try{if(!Object.assign)return!1;var A=new String("abc");if(A[5]="de",Object.getOwnPropertyNames(A)[0]==="5")return!1;for(var x={},D=0;D<10;D++)x["_"+String.fromCharCode(D)]=D;if(Object.getOwnPropertyNames(x).map(function(N){return x[N]}).join("")!=="0123456789")return!1;var L={};return"abcdefghijklmnopqrst".split("").forEach(function(N){L[N]=N}),Object.keys(Object.assign({},L)).join("")==="abcdefghijklmnopqrst"}catch(N){return!1}}()?Object.assign:function(A,x){for(var D,L,N=C(A),j=1;j=J||Ft<0||Nt&&it-At>=ot}function Z(){var it=ce();if(ge(it))return Ae(it);Ue=setTimeout(Z,function(Ft){var jt=J-(Ft-be);return Nt?re(jt,ot-(Ft-At)):jt}(it))}function Ae(it){return Ue=void 0,Je&&Oe?V(it):(Oe=Le=void 0,ct)}function at(){var it=ce(),Ft=ge(it);if(Oe=arguments,Le=this,be=it,Ft){if(Ue===void 0)return ne(be);if(Nt)return Ue=setTimeout(Z,J),V(be)}return Ue===void 0&&(Ue=setTimeout(Z,J)),ct}return J=me(J)||0,oe(Te)&&(Ot=!!Te.leading,ot=(Nt="maxWait"in Te)?h(me(Te.maxWait)||0,J):ot,Je="trailing"in Te?!!Te.trailing:Je),at.cancel=function(){Ue!==void 0&&clearTimeout(Ue),At=0,Oe=be=Le=Ue=void 0},at.flush=function(){return Ue===void 0?ct:Ae(ce())},at}function oe(De){var J=g(De);return!!De&&(J=="object"||J=="function")}function Se(De){return g(De)=="symbol"||function(J){return!!J&&g(J)=="object"}(De)&&$.call(De)=="[object Symbol]"}function me(De){if(typeof De=="number")return De;if(Se(De))return NaN;if(oe(De)){var J=typeof De.valueOf=="function"?De.valueOf():De;De=oe(J)?J+"":J}if(typeof De!="string")return De===0?De:+De;De=De.replace(t,"");var Te=A.test(De);return Te||x.test(De)?D(De.slice(2),Te?2:8):C.test(De)?NaN:+De}i.exports=function(De,J,Te){var Oe=!0,Le=!0;if(typeof De!="function")throw new TypeError("Expected a function");return oe(Te)&&(Oe="leading"in Te?!!Te.leading:Oe,Le="trailing"in Te?!!Te.trailing:Le),Q(De,J,{leading:Oe,maxWait:J,trailing:Le})}}).call(this,f(4))},function(i,u,f){(function(c){function g(V){return(g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(ne){return typeof ne}:function(ne){return ne&&typeof Symbol=="function"&&ne.constructor===Symbol&&ne!==Symbol.prototype?"symbol":typeof ne})(V)}var t;u=i.exports=h,t=(c===void 0?"undefined":g(c))==="object"&&c.env&&c.env.NODE_DEBUG&&/\bsemver\b/i.test(c.env.NODE_DEBUG)?function(){var V=Array.prototype.slice.call(arguments,0);V.unshift("SEMVER"),console.log.apply(console,V)}:function(){},u.SEMVER_SPEC_VERSION="2.0.0";var C=Number.MAX_SAFE_INTEGER||9007199254740991,A=u.re=[],x=u.src=[],D=u.tokens={},L=0;function N(V){D[V]=L++}N("NUMERICIDENTIFIER"),x[D.NUMERICIDENTIFIER]="0|[1-9]\\d*",N("NUMERICIDENTIFIERLOOSE"),x[D.NUMERICIDENTIFIERLOOSE]="[0-9]+",N("NONNUMERICIDENTIFIER"),x[D.NONNUMERICIDENTIFIER]="\\d*[a-zA-Z-][a-zA-Z0-9-]*",N("MAINVERSION"),x[D.MAINVERSION]="("+x[D.NUMERICIDENTIFIER]+")\\.("+x[D.NUMERICIDENTIFIER]+")\\.("+x[D.NUMERICIDENTIFIER]+")",N("MAINVERSIONLOOSE"),x[D.MAINVERSIONLOOSE]="("+x[D.NUMERICIDENTIFIERLOOSE]+")\\.("+x[D.NUMERICIDENTIFIERLOOSE]+")\\.("+x[D.NUMERICIDENTIFIERLOOSE]+")",N("PRERELEASEIDENTIFIER"),x[D.PRERELEASEIDENTIFIER]="(?:"+x[D.NUMERICIDENTIFIER]+"|"+x[D.NONNUMERICIDENTIFIER]+")",N("PRERELEASEIDENTIFIERLOOSE"),x[D.PRERELEASEIDENTIFIERLOOSE]="(?:"+x[D.NUMERICIDENTIFIERLOOSE]+"|"+x[D.NONNUMERICIDENTIFIER]+")",N("PRERELEASE"),x[D.PRERELEASE]="(?:-("+x[D.PRERELEASEIDENTIFIER]+"(?:\\."+x[D.PRERELEASEIDENTIFIER]+")*))",N("PRERELEASELOOSE"),x[D.PRERELEASELOOSE]="(?:-?("+x[D.PRERELEASEIDENTIFIERLOOSE]+"(?:\\."+x[D.PRERELEASEIDENTIFIERLOOSE]+")*))",N("BUILDIDENTIFIER"),x[D.BUILDIDENTIFIER]="[0-9A-Za-z-]+",N("BUILD"),x[D.BUILD]="(?:\\+("+x[D.BUILDIDENTIFIER]+"(?:\\."+x[D.BUILDIDENTIFIER]+")*))",N("FULL"),N("FULLPLAIN"),x[D.FULLPLAIN]="v?"+x[D.MAINVERSION]+x[D.PRERELEASE]+"?"+x[D.BUILD]+"?",x[D.FULL]="^"+x[D.FULLPLAIN]+"$",N("LOOSEPLAIN"),x[D.LOOSEPLAIN]="[v=\\s]*"+x[D.MAINVERSIONLOOSE]+x[D.PRERELEASELOOSE]+"?"+x[D.BUILD]+"?",N("LOOSE"),x[D.LOOSE]="^"+x[D.LOOSEPLAIN]+"$",N("GTLT"),x[D.GTLT]="((?:<|>)?=?)",N("XRANGEIDENTIFIERLOOSE"),x[D.XRANGEIDENTIFIERLOOSE]=x[D.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*",N("XRANGEIDENTIFIER"),x[D.XRANGEIDENTIFIER]=x[D.NUMERICIDENTIFIER]+"|x|X|\\*",N("XRANGEPLAIN"),x[D.XRANGEPLAIN]="[v=\\s]*("+x[D.XRANGEIDENTIFIER]+")(?:\\.("+x[D.XRANGEIDENTIFIER]+")(?:\\.("+x[D.XRANGEIDENTIFIER]+")(?:"+x[D.PRERELEASE]+")?"+x[D.BUILD]+"?)?)?",N("XRANGEPLAINLOOSE"),x[D.XRANGEPLAINLOOSE]="[v=\\s]*("+x[D.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+x[D.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+x[D.XRANGEIDENTIFIERLOOSE]+")(?:"+x[D.PRERELEASELOOSE]+")?"+x[D.BUILD]+"?)?)?",N("XRANGE"),x[D.XRANGE]="^"+x[D.GTLT]+"\\s*"+x[D.XRANGEPLAIN]+"$",N("XRANGELOOSE"),x[D.XRANGELOOSE]="^"+x[D.GTLT]+"\\s*"+x[D.XRANGEPLAINLOOSE]+"$",N("COERCE"),x[D.COERCE]="(^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])",N("COERCERTL"),A[D.COERCERTL]=new RegExp(x[D.COERCE],"g"),N("LONETILDE"),x[D.LONETILDE]="(?:~>?)",N("TILDETRIM"),x[D.TILDETRIM]="(\\s*)"+x[D.LONETILDE]+"\\s+",A[D.TILDETRIM]=new RegExp(x[D.TILDETRIM],"g"),N("TILDE"),x[D.TILDE]="^"+x[D.LONETILDE]+x[D.XRANGEPLAIN]+"$",N("TILDELOOSE"),x[D.TILDELOOSE]="^"+x[D.LONETILDE]+x[D.XRANGEPLAINLOOSE]+"$",N("LONECARET"),x[D.LONECARET]="(?:\\^)",N("CARETTRIM"),x[D.CARETTRIM]="(\\s*)"+x[D.LONECARET]+"\\s+",A[D.CARETTRIM]=new RegExp(x[D.CARETTRIM],"g"),N("CARET"),x[D.CARET]="^"+x[D.LONECARET]+x[D.XRANGEPLAIN]+"$",N("CARETLOOSE"),x[D.CARETLOOSE]="^"+x[D.LONECARET]+x[D.XRANGEPLAINLOOSE]+"$",N("COMPARATORLOOSE"),x[D.COMPARATORLOOSE]="^"+x[D.GTLT]+"\\s*("+x[D.LOOSEPLAIN]+")$|^$",N("COMPARATOR"),x[D.COMPARATOR]="^"+x[D.GTLT]+"\\s*("+x[D.FULLPLAIN]+")$|^$",N("COMPARATORTRIM"),x[D.COMPARATORTRIM]="(\\s*)"+x[D.GTLT]+"\\s*("+x[D.LOOSEPLAIN]+"|"+x[D.XRANGEPLAIN]+")",A[D.COMPARATORTRIM]=new RegExp(x[D.COMPARATORTRIM],"g"),N("HYPHENRANGE"),x[D.HYPHENRANGE]="^\\s*("+x[D.XRANGEPLAIN]+")\\s+-\\s+("+x[D.XRANGEPLAIN]+")\\s*$",N("HYPHENRANGELOOSE"),x[D.HYPHENRANGELOOSE]="^\\s*("+x[D.XRANGEPLAINLOOSE]+")\\s+-\\s+("+x[D.XRANGEPLAINLOOSE]+")\\s*$",N("STAR"),x[D.STAR]="(<|>)?=?\\s*\\*";for(var j=0;j256||!(ne.loose?A[D.LOOSE]:A[D.FULL]).test(V))return null;try{return new h(V,ne)}catch(ge){return null}}function h(V,ne){if(ne&&g(ne)==="object"||(ne={loose:!!ne,includePrerelease:!1}),V instanceof h){if(V.loose===ne.loose)return V;V=V.version}else if(typeof V!="string")throw new TypeError("Invalid Version: "+V);if(V.length>256)throw new TypeError("version is longer than 256 characters");if(!(this instanceof h))return new h(V,ne);t("SemVer",V,ne),this.options=ne,this.loose=!!ne.loose;var ge=V.trim().match(ne.loose?A[D.LOOSE]:A[D.FULL]);if(!ge)throw new TypeError("Invalid Version: "+V);if(this.raw=V,this.major=+ge[1],this.minor=+ge[2],this.patch=+ge[3],this.major>C||this.major<0)throw new TypeError("Invalid major version");if(this.minor>C||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>C||this.patch<0)throw new TypeError("Invalid patch version");ge[4]?this.prerelease=ge[4].split(".").map(function(Z){if(/^[0-9]+$/.test(Z)){var Ae=+Z;if(Ae>=0&&Ae=0;)typeof this.prerelease[ge]=="number"&&(this.prerelease[ge]++,ge=-2);ge===-1&&this.prerelease.push(0)}ne&&(this.prerelease[0]===ne?isNaN(this.prerelease[1])&&(this.prerelease=[ne,0]):this.prerelease=[ne,0]);break;default:throw new Error("invalid increment argument: "+V)}return this.format(),this.raw=this.version,this},u.inc=function(V,ne,ge,Z){typeof ge=="string"&&(Z=ge,ge=void 0);try{return new h(V,ge).inc(ne,Z).version}catch(Ae){return null}},u.diff=function(V,ne){if(me(V,ne))return null;var ge=$(V),Z=$(ne),Ae="";if(ge.prerelease.length||Z.prerelease.length){Ae="pre";var at="prerelease"}for(var it in ge)if((it==="major"||it==="minor"||it==="patch")&&ge[it]!==Z[it])return Ae+it;return at},u.compareIdentifiers=ce;var re=/^[0-9]+$/;function ce(V,ne){var ge=re.test(V),Z=re.test(ne);return ge&&Z&&(V=+V,ne=+ne),V===ne?0:ge&&!Z?-1:Z&&!ge?1:V0}function Se(V,ne,ge){return Q(V,ne,ge)<0}function me(V,ne,ge){return Q(V,ne,ge)===0}function De(V,ne,ge){return Q(V,ne,ge)!==0}function J(V,ne,ge){return Q(V,ne,ge)>=0}function Te(V,ne,ge){return Q(V,ne,ge)<=0}function Oe(V,ne,ge,Z){switch(ne){case"===":return g(V)==="object"&&(V=V.version),g(ge)==="object"&&(ge=ge.version),V===ge;case"!==":return g(V)==="object"&&(V=V.version),g(ge)==="object"&&(ge=ge.version),V!==ge;case"":case"=":case"==":return me(V,ge,Z);case"!=":return De(V,ge,Z);case">":return oe(V,ge,Z);case">=":return J(V,ge,Z);case"<":return Se(V,ge,Z);case"<=":return Te(V,ge,Z);default:throw new TypeError("Invalid operator: "+ne)}}function Le(V,ne){if(ne&&g(ne)==="object"||(ne={loose:!!ne,includePrerelease:!1}),V instanceof Le){if(V.loose===!!ne.loose)return V;V=V.value}if(!(this instanceof Le))return new Le(V,ne);t("comparator",V,ne),this.options=ne,this.loose=!!ne.loose,this.parse(V),this.semver===ot?this.value="":this.value=this.operator+this.semver.version,t("comp",this)}u.rcompareIdentifiers=function(V,ne){return ce(ne,V)},u.major=function(V,ne){return new h(V,ne).major},u.minor=function(V,ne){return new h(V,ne).minor},u.patch=function(V,ne){return new h(V,ne).patch},u.compare=Q,u.compareLoose=function(V,ne){return Q(V,ne,!0)},u.compareBuild=function(V,ne,ge){var Z=new h(V,ge),Ae=new h(ne,ge);return Z.compare(Ae)||Z.compareBuild(Ae)},u.rcompare=function(V,ne,ge){return Q(ne,V,ge)},u.sort=function(V,ne){return V.sort(function(ge,Z){return u.compareBuild(ge,Z,ne)})},u.rsort=function(V,ne){return V.sort(function(ge,Z){return u.compareBuild(Z,ge,ne)})},u.gt=oe,u.lt=Se,u.eq=me,u.neq=De,u.gte=J,u.lte=Te,u.cmp=Oe,u.Comparator=Le;var ot={};function ct(V,ne){if(ne&&g(ne)==="object"||(ne={loose:!!ne,includePrerelease:!1}),V instanceof ct)return V.loose===!!ne.loose&&V.includePrerelease===!!ne.includePrerelease?V:new ct(V.raw,ne);if(V instanceof Le)return new ct(V.value,ne);if(!(this instanceof ct))return new ct(V,ne);if(this.options=ne,this.loose=!!ne.loose,this.includePrerelease=!!ne.includePrerelease,this.raw=V,this.set=V.split(/\s*\|\|\s*/).map(function(ge){return this.parseRange(ge.trim())},this).filter(function(ge){return ge.length}),!this.set.length)throw new TypeError("Invalid SemVer Range: "+V);this.format()}function Ue(V,ne){for(var ge=!0,Z=V.slice(),Ae=Z.pop();ge&&Z.length;)ge=Z.every(function(at){return Ae.intersects(at,ne)}),Ae=Z.pop();return ge}function be(V){return!V||V.toLowerCase()==="x"||V==="*"}function At(V,ne,ge,Z,Ae,at,it,Ft,jt,hn,Un,Jt,Yt){return((ne=be(ge)?"":be(Z)?">="+ge+".0.0":be(Ae)?">="+ge+"."+Z+".0":">="+ne)+" "+(Ft=be(jt)?"":be(hn)?"<"+(+jt+1)+".0.0":be(Un)?"<"+jt+"."+(+hn+1)+".0":Jt?"<="+jt+"."+hn+"."+Un+"-"+Jt:"<="+Ft)).trim()}function Ot(V,ne,ge){for(var Z=0;Z0){var Ae=V[Z].semver;if(Ae.major===ne.major&&Ae.minor===ne.minor&&Ae.patch===ne.patch)return!0}return!1}return!0}function Nt(V,ne,ge){try{ne=new ct(ne,ge)}catch(Z){return!1}return ne.test(V)}function Je(V,ne,ge,Z){var Ae,at,it,Ft,jt;switch(V=new h(V,Z),ne=new ct(ne,Z),ge){case">":Ae=oe,at=Te,it=Se,Ft=">",jt=">=";break;case"<":Ae=Se,at=J,it=oe,Ft="<",jt="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(Nt(V,ne,Z))return!1;for(var hn=0;hn=0.0.0")),Jt=Jt||cr,Yt=Yt||cr,Ae(cr.semver,Jt.semver,Z)?Jt=cr:it(cr.semver,Yt.semver,Z)&&(Yt=cr)}),Jt.operator===Ft||Jt.operator===jt||(!Yt.operator||Yt.operator===Ft)&&at(V,Yt.semver)||Yt.operator===jt&&it(V,Yt.semver))return!1}return!0}Le.prototype.parse=function(V){var ne=this.options.loose?A[D.COMPARATORLOOSE]:A[D.COMPARATOR],ge=V.match(ne);if(!ge)throw new TypeError("Invalid comparator: "+V);this.operator=ge[1]!==void 0?ge[1]:"",this.operator==="="&&(this.operator=""),ge[2]?this.semver=new h(ge[2],this.options.loose):this.semver=ot},Le.prototype.toString=function(){return this.value},Le.prototype.test=function(V){if(t("Comparator.test",V,this.options.loose),this.semver===ot||V===ot)return!0;if(typeof V=="string")try{V=new h(V,this.options)}catch(ne){return!1}return Oe(V,this.operator,this.semver,this.options)},Le.prototype.intersects=function(V,ne){if(!(V instanceof Le))throw new TypeError("a Comparator is required");var ge;if(ne&&g(ne)==="object"||(ne={loose:!!ne,includePrerelease:!1}),this.operator==="")return this.value===""||(ge=new ct(V.value,ne),Nt(this.value,ge,ne));if(V.operator==="")return V.value===""||(ge=new ct(this.value,ne),Nt(V.semver,ge,ne));var Z=!(this.operator!==">="&&this.operator!==">"||V.operator!==">="&&V.operator!==">"),Ae=!(this.operator!=="<="&&this.operator!=="<"||V.operator!=="<="&&V.operator!=="<"),at=this.semver.version===V.semver.version,it=!(this.operator!==">="&&this.operator!=="<="||V.operator!==">="&&V.operator!=="<="),Ft=Oe(this.semver,"<",V.semver,ne)&&(this.operator===">="||this.operator===">")&&(V.operator==="<="||V.operator==="<"),jt=Oe(this.semver,">",V.semver,ne)&&(this.operator==="<="||this.operator==="<")&&(V.operator===">="||V.operator===">");return Z||Ae||at&&it||Ft||jt},u.Range=ct,ct.prototype.format=function(){return this.range=this.set.map(function(V){return V.join(" ").trim()}).join("||").trim(),this.range},ct.prototype.toString=function(){return this.range},ct.prototype.parseRange=function(V){var ne=this.options.loose;V=V.trim();var ge=ne?A[D.HYPHENRANGELOOSE]:A[D.HYPHENRANGE];V=V.replace(ge,At),t("hyphen replace",V),V=V.replace(A[D.COMPARATORTRIM],"$1$2$3"),t("comparator trim",V,A[D.COMPARATORTRIM]),V=(V=(V=V.replace(A[D.TILDETRIM],"$1~")).replace(A[D.CARETTRIM],"$1^")).split(/\s+/).join(" ");var Z=ne?A[D.COMPARATORLOOSE]:A[D.COMPARATOR],Ae=V.split(" ").map(function(at){return function(it,Ft){return t("comp",it,Ft),it=function(jt,hn){return jt.trim().split(/\s+/).map(function(Un){return function(Jt,Yt){t("caret",Jt,Yt);var cr=Yt.loose?A[D.CARETLOOSE]:A[D.CARET];return Jt.replace(cr,function(w,pt,Mn,Bn,Xn){var vr;return t("caret",Jt,w,pt,Mn,Bn,Xn),be(pt)?vr="":be(Mn)?vr=">="+pt+".0.0 <"+(+pt+1)+".0.0":be(Bn)?vr=pt==="0"?">="+pt+"."+Mn+".0 <"+pt+"."+(+Mn+1)+".0":">="+pt+"."+Mn+".0 <"+(+pt+1)+".0.0":Xn?(t("replaceCaret pr",Xn),vr=pt==="0"?Mn==="0"?">="+pt+"."+Mn+"."+Bn+"-"+Xn+" <"+pt+"."+Mn+"."+(+Bn+1):">="+pt+"."+Mn+"."+Bn+"-"+Xn+" <"+pt+"."+(+Mn+1)+".0":">="+pt+"."+Mn+"."+Bn+"-"+Xn+" <"+(+pt+1)+".0.0"):(t("no pr"),vr=pt==="0"?Mn==="0"?">="+pt+"."+Mn+"."+Bn+" <"+pt+"."+Mn+"."+(+Bn+1):">="+pt+"."+Mn+"."+Bn+" <"+pt+"."+(+Mn+1)+".0":">="+pt+"."+Mn+"."+Bn+" <"+(+pt+1)+".0.0"),t("caret return",vr),vr})}(Un,hn)}).join(" ")}(it,Ft),t("caret",it),it=function(jt,hn){return jt.trim().split(/\s+/).map(function(Un){return function(Jt,Yt){var cr=Yt.loose?A[D.TILDELOOSE]:A[D.TILDE];return Jt.replace(cr,function(w,pt,Mn,Bn,Xn){var vr;return t("tilde",Jt,w,pt,Mn,Bn,Xn),be(pt)?vr="":be(Mn)?vr=">="+pt+".0.0 <"+(+pt+1)+".0.0":be(Bn)?vr=">="+pt+"."+Mn+".0 <"+pt+"."+(+Mn+1)+".0":Xn?(t("replaceTilde pr",Xn),vr=">="+pt+"."+Mn+"."+Bn+"-"+Xn+" <"+pt+"."+(+Mn+1)+".0"):vr=">="+pt+"."+Mn+"."+Bn+" <"+pt+"."+(+Mn+1)+".0",t("tilde return",vr),vr})}(Un,hn)}).join(" ")}(it,Ft),t("tildes",it),it=function(jt,hn){return t("replaceXRanges",jt,hn),jt.split(/\s+/).map(function(Un){return function(Jt,Yt){Jt=Jt.trim();var cr=Yt.loose?A[D.XRANGELOOSE]:A[D.XRANGE];return Jt.replace(cr,function(w,pt,Mn,Bn,Xn,vr){t("xRange",Jt,w,pt,Mn,Bn,Xn,vr);var gr=be(Mn),r0=gr||be(Bn),Ci=r0||be(Xn),yo=Ci;return pt==="="&&yo&&(pt=""),vr=Yt.includePrerelease?"-0":"",gr?w=pt===">"||pt==="<"?"<0.0.0-0":"*":pt&&yo?(r0&&(Bn=0),Xn=0,pt===">"?(pt=">=",r0?(Mn=+Mn+1,Bn=0,Xn=0):(Bn=+Bn+1,Xn=0)):pt==="<="&&(pt="<",r0?Mn=+Mn+1:Bn=+Bn+1),w=pt+Mn+"."+Bn+"."+Xn+vr):r0?w=">="+Mn+".0.0"+vr+" <"+(+Mn+1)+".0.0"+vr:Ci&&(w=">="+Mn+"."+Bn+".0"+vr+" <"+Mn+"."+(+Bn+1)+".0"+vr),t("xRange return",w),w})}(Un,hn)}).join(" ")}(it,Ft),t("xrange",it),it=function(jt,hn){return t("replaceStars",jt,hn),jt.trim().replace(A[D.STAR],"")}(it,Ft),t("stars",it),it}(at,this.options)},this).join(" ").split(/\s+/);return this.options.loose&&(Ae=Ae.filter(function(at){return!!at.match(Z)})),Ae=Ae.map(function(at){return new Le(at,this.options)},this)},ct.prototype.intersects=function(V,ne){if(!(V instanceof ct))throw new TypeError("a Range is required");return this.set.some(function(ge){return Ue(ge,ne)&&V.set.some(function(Z){return Ue(Z,ne)&&ge.every(function(Ae){return Z.every(function(at){return Ae.intersects(at,ne)})})})})},u.toComparators=function(V,ne){return new ct(V,ne).set.map(function(ge){return ge.map(function(Z){return Z.value}).join(" ").trim().split(" ")})},ct.prototype.test=function(V){if(!V)return!1;if(typeof V=="string")try{V=new h(V,this.options)}catch(ge){return!1}for(var ne=0;ne":at.prerelease.length===0?at.patch++:at.prerelease.push(0),at.raw=at.format();case"":case">=":ge&&!oe(ge,at)||(ge=at);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+Ae.operator)}});return ge&&V.test(ge)?ge:null},u.validRange=function(V,ne){try{return new ct(V,ne).range||"*"}catch(ge){return null}},u.ltr=function(V,ne,ge){return Je(V,ne,"<",ge)},u.gtr=function(V,ne,ge){return Je(V,ne,">",ge)},u.outside=Je,u.prerelease=function(V,ne){var ge=$(V,ne);return ge&&ge.prerelease.length?ge.prerelease:null},u.intersects=function(V,ne,ge){return V=new ct(V,ge),ne=new ct(ne,ge),V.intersects(ne)},u.coerce=function(V,ne){if(V instanceof h)return V;if(typeof V=="number"&&(V=String(V)),typeof V!="string")return null;var ge=null;if((ne=ne||{}).rtl){for(var Z;(Z=A[D.COERCERTL].exec(V))&&(!ge||ge.index+ge[0].length!==V.length);)ge&&Z.index+Z[0].length===ge.index+ge[0].length||(ge=Z),A[D.COERCERTL].lastIndex=Z.index+Z[1].length+Z[2].length;A[D.COERCERTL].lastIndex=-1}else ge=V.match(A[D.COERCE]);return ge===null?null:$(ge[2]+"."+(ge[3]||"0")+"."+(ge[4]||"0"),ne)}}).call(this,f(5))},function(i,u){function f(g){return(f=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(g)}var c;c=function(){return this}();try{c=c||new Function("return this")()}catch(g){(typeof window=="undefined"?"undefined":f(window))==="object"&&(c=window)}i.exports=c},function(i,u){var f,c,g=i.exports={};function t(){throw new Error("setTimeout has not been defined")}function C(){throw new Error("clearTimeout has not been defined")}function A(ce){if(f===setTimeout)return setTimeout(ce,0);if((f===t||!f)&&setTimeout)return f=setTimeout,setTimeout(ce,0);try{return f(ce,0)}catch(Q){try{return f.call(null,ce,0)}catch(oe){return f.call(this,ce,0)}}}(function(){try{f=typeof setTimeout=="function"?setTimeout:t}catch(ce){f=t}try{c=typeof clearTimeout=="function"?clearTimeout:C}catch(ce){c=C}})();var x,D=[],L=!1,N=-1;function j(){L&&x&&(L=!1,x.length?D=x.concat(D):N=-1,D.length&&$())}function $(){if(!L){var ce=A(j);L=!0;for(var Q=D.length;Q;){for(x=D,D=[];++N1)for(var oe=1;oethis[C])return De(this,this[h].get(Ue)),!1;var Je=this[h].get(Ue).value;return this[N]&&(this[j]||this[N](Ue,Je.value)),Je.now=Ot,Je.maxAge=At,Je.value=be,this[A]+=Nt-Je.length,Je.length=Nt,this.get(Ue),me(this),!0}var V=new J(Ue,be,Nt,Ot,At);return V.length>this[C]?(this[N]&&this[N](Ue,be),!1):(this[A]+=V.length,this[$].unshift(V),this[h].set(Ue,this[$].head),me(this),!0)}},{key:"has",value:function(Ue){if(!this[h].has(Ue))return!1;var be=this[h].get(Ue).value;return!Se(this,be)}},{key:"get",value:function(Ue){return oe(this,Ue,!0)}},{key:"peek",value:function(Ue){return oe(this,Ue,!1)}},{key:"pop",value:function(){var Ue=this[$].tail;return Ue?(De(this,Ue),Ue.value):null}},{key:"del",value:function(Ue){De(this,this[h].get(Ue))}},{key:"load",value:function(Ue){this.reset();for(var be=Date.now(),At=Ue.length-1;At>=0;At--){var Ot=Ue[At],Nt=Ot.e||0;if(Nt===0)this.set(Ot.k,Ot.v);else{var Je=Nt-be;Je>0&&this.set(Ot.k,Ot.v,Je)}}}},{key:"prune",value:function(){var Ue=this;this[h].forEach(function(be,At){return oe(Ue,At,!1)})}},{key:"max",set:function(Ue){if(typeof Ue!="number"||Ue<0)throw new TypeError("max must be a non-negative number");this[C]=Ue||1/0,me(this)},get:function(){return this[C]}},{key:"allowStale",set:function(Ue){this[D]=!!Ue},get:function(){return this[D]}},{key:"maxAge",set:function(Ue){if(typeof Ue!="number")throw new TypeError("maxAge must be a non-negative number");this[L]=Ue,me(this)},get:function(){return this[L]}},{key:"lengthCalculator",set:function(Ue){var be=this;typeof Ue!="function"&&(Ue=ce),Ue!==this[x]&&(this[x]=Ue,this[A]=0,this[$].forEach(function(At){At.length=be[x](At.value,At.key),be[A]+=At.length})),me(this)},get:function(){return this[x]}},{key:"length",get:function(){return this[A]}},{key:"itemCount",get:function(){return this[$].length}}])&&g(Le.prototype,ot),ct&&g(Le,ct),Oe}(),oe=function(Oe,Le,ot){var ct=Oe[h].get(Le);if(ct){var Ue=ct.value;if(Se(Oe,Ue)){if(De(Oe,ct),!Oe[D])return}else ot&&(Oe[re]&&(ct.value.now=Date.now()),Oe[$].unshiftNode(ct));return Ue.value}},Se=function(Oe,Le){if(!Le||!Le.maxAge&&!Oe[L])return!1;var ot=Date.now()-Le.now;return Le.maxAge?ot>Le.maxAge:Oe[L]&&ot>Oe[L]},me=function(Oe){if(Oe[A]>Oe[C])for(var Le=Oe[$].tail;Oe[A]>Oe[C]&&Le!==null;){var ot=Le.prev;De(Oe,Le),Le=ot}},De=function(Oe,Le){if(Le){var ot=Le.value;Oe[N]&&Oe[N](ot.key,ot.value),Oe[A]-=ot.length,Oe[h].delete(ot.key),Oe[$].removeNode(Le)}},J=function Oe(Le,ot,ct,Ue,be){c(this,Oe),this.key=Le,this.value=ot,this.length=ct,this.now=Ue,this.maxAge=be||0},Te=function(Oe,Le,ot,ct){var Ue=ot.value;Se(Oe,Ue)&&(De(Oe,ot),Oe[D]||(Ue=void 0)),Ue&&Le.call(ct,Ue.value,Ue.key,Oe)};i.exports=Q},function(i,u,f){(function(c){function g(t){return(g=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(C){return typeof C}:function(C){return C&&typeof Symbol=="function"&&C.constructor===Symbol&&C!==Symbol.prototype?"symbol":typeof C})(t)}i.exports=function(){if(typeof document=="undefined"||!document.addEventListener)return null;var t,C,A,x={};return x.copy=function(){var D=!1,L=null,N=!1;function j(){D=!1,L=null,N&&window.getSelection().removeAllRanges(),N=!1}return document.addEventListener("copy",function($){if(D){for(var h in L)$.clipboardData.setData(h,L[h]);$.preventDefault()}}),function($){return new Promise(function(h,re){D=!0,typeof $=="string"?L={"text/plain":$}:$ instanceof Node?L={"text/html":new XMLSerializer().serializeToString($)}:$ instanceof Object?L=$:re("Invalid data type. Must be string, DOM node, or an object mapping MIME types to strings."),function ce(Q){try{if(document.execCommand("copy"))j(),h();else{if(Q)throw j(),new Error("Unable to copy. Perhaps it's not available in your browser?");(function(){var oe=document.getSelection();if(!document.queryCommandEnabled("copy")&&oe.isCollapsed){var Se=document.createRange();Se.selectNodeContents(document.body),oe.removeAllRanges(),oe.addRange(Se),N=!0}})(),ce(!0)}}catch(oe){j(),re(oe)}}(!1)})}}(),x.paste=(A=!1,document.addEventListener("paste",function(D){if(A){A=!1,D.preventDefault();var L=t;t=null,L(D.clipboardData.getData(C))}}),function(D){return new Promise(function(L,N){A=!0,t=L,C=D||"text/plain";try{document.execCommand("paste")||(A=!1,N(new Error("Unable to paste. Pasting only works in Internet Explorer at the moment.")))}catch(j){A=!1,N(new Error(j))}})}),typeof ClipboardEvent=="undefined"&&window.clipboardData!==void 0&&window.clipboardData.setData!==void 0&&(function(D){function L(me,De){return function(){me.apply(De,arguments)}}function N(me){if(g(this)!="object")throw new TypeError("Promises must be constructed via new");if(typeof me!="function")throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],Q(me,L($,this),L(h,this))}function j(me){var De=this;return this._state===null?void this._deferreds.push(me):void oe(function(){var J=De._state?me.onFulfilled:me.onRejected;if(J!==null){var Te;try{Te=J(De._value)}catch(Oe){return void me.reject(Oe)}me.resolve(Te)}else(De._state?me.resolve:me.reject)(De._value)})}function $(me){try{if(me===this)throw new TypeError("A promise cannot be resolved with itself.");if(me&&(g(me)=="object"||typeof me=="function")){var De=me.then;if(typeof De=="function")return void Q(L(De,me),L($,this),L(h,this))}this._state=!0,this._value=me,re.call(this)}catch(J){h.call(this,J)}}function h(me){this._state=!1,this._value=me,re.call(this)}function re(){for(var me=0,De=this._deferreds.length;De>me;me++)j.call(this,this._deferreds[me]);this._deferreds=null}function ce(me,De,J,Te){this.onFulfilled=typeof me=="function"?me:null,this.onRejected=typeof De=="function"?De:null,this.resolve=J,this.reject=Te}function Q(me,De,J){var Te=!1;try{me(function(Oe){Te||(Te=!0,De(Oe))},function(Oe){Te||(Te=!0,J(Oe))})}catch(Oe){if(Te)return;Te=!0,J(Oe)}}var oe=N.immediateFn||typeof c=="function"&&c||function(me){setTimeout(me,1)},Se=Array.isArray||function(me){return Object.prototype.toString.call(me)==="[object Array]"};N.prototype.catch=function(me){return this.then(null,me)},N.prototype.then=function(me,De){var J=this;return new N(function(Te,Oe){j.call(J,new ce(me,De,Te,Oe))})},N.all=function(){var me=Array.prototype.slice.call(arguments.length===1&&Se(arguments[0])?arguments[0]:arguments);return new N(function(De,J){function Te(ot,ct){try{if(ct&&(g(ct)=="object"||typeof ct=="function")){var Ue=ct.then;if(typeof Ue=="function")return void Ue.call(ct,function(be){Te(ot,be)},J)}me[ot]=ct,--Oe==0&&De(me)}catch(be){J(be)}}if(me.length===0)return De([]);for(var Oe=me.length,Le=0;LeTe;Te++)me[Te].then(De,J)})},i.exports?i.exports=N:D.Promise||(D.Promise=N)}(this),x.copy=function(D){return new Promise(function(L,N){if(typeof D!="string"&&!("text/plain"in D))throw new Error("You must provide a text/plain type.");var j=typeof D=="string"?D:D["text/plain"];window.clipboardData.setData("Text",j)?L():N(new Error("Copying was rejected."))})},x.paste=function(){return new Promise(function(D,L){var N=window.clipboardData.getData("Text");N?D(N):L(new Error("Pasting was rejected."))})}),x}()}).call(this,f(13).setImmediate)},function(i,u,f){"use strict";i.exports=f(15)},function(i,u,f){"use strict";f.r(u),u.default=`:root { + /** + * IMPORTANT: When new theme variables are added below\u2013 also add them to SettingsContext updateThemeVariables() + */ + + /* Light theme */ + --light-color-attribute-name: #ef6632; + --light-color-attribute-name-not-editable: #23272f; + --light-color-attribute-name-inverted: rgba(255, 255, 255, 0.7); + --light-color-attribute-value: #1a1aa6; + --light-color-attribute-value-inverted: #ffffff; + --light-color-attribute-editable-value: #1a1aa6; + --light-color-background: #ffffff; + --light-color-background-hover: rgba(0, 136, 250, 0.1); + --light-color-background-inactive: #e5e5e5; + --light-color-background-invalid: #fff0f0; + --light-color-background-selected: #0088fa; + --light-color-button-background: #ffffff; + --light-color-button-background-focus: #ededed; + --light-color-button: #5f6673; + --light-color-button-disabled: #cfd1d5; + --light-color-button-active: #0088fa; + --light-color-button-focus: #23272f; + --light-color-button-hover: #23272f; + --light-color-border: #eeeeee; + --light-color-commit-did-not-render-fill: #cfd1d5; + --light-color-commit-did-not-render-fill-text: #000000; + --light-color-commit-did-not-render-pattern: #cfd1d5; + --light-color-commit-did-not-render-pattern-text: #333333; + --light-color-commit-gradient-0: #37afa9; + --light-color-commit-gradient-1: #63b19e; + --light-color-commit-gradient-2: #80b393; + --light-color-commit-gradient-3: #97b488; + --light-color-commit-gradient-4: #abb67d; + --light-color-commit-gradient-5: #beb771; + --light-color-commit-gradient-6: #cfb965; + --light-color-commit-gradient-7: #dfba57; + --light-color-commit-gradient-8: #efbb49; + --light-color-commit-gradient-9: #febc38; + --light-color-commit-gradient-text: #000000; + --light-color-component-name: #6a51b2; + --light-color-component-name-inverted: #ffffff; + --light-color-component-badge-background: rgba(0, 0, 0, 0.1); + --light-color-component-badge-background-inverted: rgba(255, 255, 255, 0.25); + --light-color-component-badge-count: #777d88; + --light-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --light-color-context-background: rgba(0,0,0,.9); + --light-color-context-background-hover: rgba(255, 255, 255, 0.1); + --light-color-context-background-selected: #178fb9; + --light-color-context-border: #3d424a; + --light-color-context-text: #ffffff; + --light-color-context-text-selected: #ffffff; + --light-color-dim: #777d88; + --light-color-dimmer: #cfd1d5; + --light-color-dimmest: #eff0f1; + --light-color-error-background: hsl(0, 100%, 97%); + --light-color-error-border: hsl(0, 100%, 92%); + --light-color-error-text: #ff0000; + --light-color-expand-collapse-toggle: #777d88; + --light-color-link: #0000ff; + --light-color-modal-background: rgba(255, 255, 255, 0.75); + --light-color-record-active: #fc3a4b; + --light-color-record-hover: #3578e5; + --light-color-record-inactive: #0088fa; + --light-color-scroll-thumb: #c2c2c2; + --light-color-scroll-track: #fafafa; + --light-color-search-match: yellow; + --light-color-search-match-current: #f7923b; + --light-color-selected-tree-highlight-active: rgba(0, 136, 250, 0.1); + --light-color-selected-tree-highlight-inactive: rgba(0, 0, 0, 0.05); + --light-color-shadow: rgba(0, 0, 0, 0.25); + --light-color-tab-selected-border: #0088fa; + --light-color-text: #000000; + --light-color-text-invalid: #ff0000; + --light-color-text-selected: #ffffff; + --light-color-toggle-background-invalid: #fc3a4b; + --light-color-toggle-background-on: #0088fa; + --light-color-toggle-background-off: #cfd1d5; + --light-color-toggle-text: #ffffff; + --light-color-tooltip-background: rgba(0, 0, 0, 0.9); + --light-color-tooltip-text: #ffffff; + + /* Dark theme */ + --dark-color-attribute-name: #9d87d2; + --dark-color-attribute-name-not-editable: #ededed; + --dark-color-attribute-name-inverted: #282828; + --dark-color-attribute-value: #cedae0; + --dark-color-attribute-value-inverted: #ffffff; + --dark-color-attribute-editable-value: yellow; + --dark-color-background: #282c34; + --dark-color-background-hover: rgba(255, 255, 255, 0.1); + --dark-color-background-inactive: #3d424a; + --dark-color-background-invalid: #5c0000; + --dark-color-background-selected: #178fb9; + --dark-color-button-background: #282c34; + --dark-color-button-background-focus: #3d424a; + --dark-color-button: #afb3b9; + --dark-color-button-active: #61dafb; + --dark-color-button-disabled: #4f5766; + --dark-color-button-focus: #a2e9fc; + --dark-color-button-hover: #ededed; + --dark-color-border: #3d424a; + --dark-color-commit-did-not-render-fill: #777d88; + --dark-color-commit-did-not-render-fill-text: #000000; + --dark-color-commit-did-not-render-pattern: #666c77; + --dark-color-commit-did-not-render-pattern-text: #ffffff; + --dark-color-commit-gradient-0: #37afa9; + --dark-color-commit-gradient-1: #63b19e; + --dark-color-commit-gradient-2: #80b393; + --dark-color-commit-gradient-3: #97b488; + --dark-color-commit-gradient-4: #abb67d; + --dark-color-commit-gradient-5: #beb771; + --dark-color-commit-gradient-6: #cfb965; + --dark-color-commit-gradient-7: #dfba57; + --dark-color-commit-gradient-8: #efbb49; + --dark-color-commit-gradient-9: #febc38; + --dark-color-commit-gradient-text: #000000; + --dark-color-component-name: #61dafb; + --dark-color-component-name-inverted: #282828; + --dark-color-component-badge-background: rgba(255, 255, 255, 0.25); + --dark-color-component-badge-background-inverted: rgba(0, 0, 0, 0.25); + --dark-color-component-badge-count: #8f949d; + --dark-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --dark-color-context-background: rgba(255,255,255,.9); + --dark-color-context-background-hover: rgba(0, 136, 250, 0.1); + --dark-color-context-background-selected: #0088fa; + --dark-color-context-border: #eeeeee; + --dark-color-context-text: #000000; + --dark-color-context-text-selected: #ffffff; + --dark-color-dim: #8f949d; + --dark-color-dimmer: #777d88; + --dark-color-dimmest: #4f5766; + --dark-color-error-background: #200; + --dark-color-error-border: #900; + --dark-color-error-text: #f55; + --dark-color-expand-collapse-toggle: #8f949d; + --dark-color-link: #61dafb; + --dark-color-modal-background: rgba(0, 0, 0, 0.75); + --dark-color-record-active: #fc3a4b; + --dark-color-record-hover: #a2e9fc; + --dark-color-record-inactive: #61dafb; + --dark-color-scroll-thumb: #afb3b9; + --dark-color-scroll-track: #313640; + --dark-color-search-match: yellow; + --dark-color-search-match-current: #f7923b; + --dark-color-selected-tree-highlight-active: rgba(23, 143, 185, 0.15); + --dark-color-selected-tree-highlight-inactive: rgba(255, 255, 255, 0.05); + --dark-color-shadow: rgba(0, 0, 0, 0.5); + --dark-color-tab-selected-border: #178fb9; + --dark-color-text: #ffffff; + --dark-color-text-invalid: #ff8080; + --dark-color-text-selected: #ffffff; + --dark-color-toggle-background-invalid: #fc3a4b; + --dark-color-toggle-background-on: #178fb9; + --dark-color-toggle-background-off: #777d88; + --dark-color-toggle-text: #ffffff; + --dark-color-tooltip-background: rgba(255, 255, 255, 0.9); + --dark-color-tooltip-text: #000000; + + /* Font smoothing */ + --light-font-smoothing: auto; + --dark-font-smoothing: antialiased; + --font-smoothing: auto; + + /* Compact density */ + --compact-font-size-monospace-small: 9px; + --compact-font-size-monospace-normal: 11px; + --compact-font-size-monospace-large: 15px; + --compact-font-size-sans-small: 10px; + --compact-font-size-sans-normal: 12px; + --compact-font-size-sans-large: 14px; + --compact-line-height-data: 18px; + --compact-root-font-size: 16px; + + /* Comfortable density */ + --comfortable-font-size-monospace-small: 10px; + --comfortable-font-size-monospace-normal: 13px; + --comfortable-font-size-monospace-large: 17px; + --comfortable-font-size-sans-small: 12px; + --comfortable-font-size-sans-normal: 14px; + --comfortable-font-size-sans-large: 16px; + --comfortable-line-height-data: 22px; + --comfortable-root-font-size: 20px; + + /* GitHub.com system fonts */ + --font-family-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, + Courier, monospace; + --font-family-sans: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, + Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + + /* Constant values shared between JS and CSS */ + --interaction-commit-size: 10px; + --interaction-label-width: 200px; + } + `},function(i,u,f){"use strict";function c(x){var D=this;if(D instanceof c||(D=new c),D.tail=null,D.head=null,D.length=0,x&&typeof x.forEach=="function")x.forEach(function(j){D.push(j)});else if(arguments.length>0)for(var L=0,N=arguments.length;L1)L=D;else{if(!this.head)throw new TypeError("Reduce of empty list with no initial value");N=this.head.next,L=this.head.value}for(var j=0;N!==null;j++)L=x(L,N.value,j),N=N.next;return L},c.prototype.reduceReverse=function(x,D){var L,N=this.tail;if(arguments.length>1)L=D;else{if(!this.tail)throw new TypeError("Reduce of empty list with no initial value");N=this.tail.prev,L=this.tail.value}for(var j=this.length-1;N!==null;j--)L=x(L,N.value,j),N=N.prev;return L},c.prototype.toArray=function(){for(var x=new Array(this.length),D=0,L=this.head;L!==null;D++)x[D]=L.value,L=L.next;return x},c.prototype.toArrayReverse=function(){for(var x=new Array(this.length),D=0,L=this.tail;L!==null;D++)x[D]=L.value,L=L.prev;return x},c.prototype.slice=function(x,D){(D=D||this.length)<0&&(D+=this.length),(x=x||0)<0&&(x+=this.length);var L=new c;if(Dthis.length&&(D=this.length);for(var N=0,j=this.head;j!==null&&Nthis.length&&(D=this.length);for(var N=this.length,j=this.tail;j!==null&&N>D;N--)j=j.prev;for(;j!==null&&N>x;N--,j=j.prev)L.push(j.value);return L},c.prototype.splice=function(x,D){x>this.length&&(x=this.length-1),x<0&&(x=this.length+x);for(var L=0,N=this.head;N!==null&&L=0&&(A._idleTimeoutId=setTimeout(function(){A._onTimeout&&A._onTimeout()},x))},f(14),u.setImmediate=typeof self!="undefined"&&self.setImmediate||c!==void 0&&c.setImmediate||this&&this.setImmediate,u.clearImmediate=typeof self!="undefined"&&self.clearImmediate||c!==void 0&&c.clearImmediate||this&&this.clearImmediate}).call(this,f(4))},function(i,u,f){(function(c,g){(function(t,C){"use strict";if(!t.setImmediate){var A,x,D,L,N,j=1,$={},h=!1,re=t.document,ce=Object.getPrototypeOf&&Object.getPrototypeOf(t);ce=ce&&ce.setTimeout?ce:t,{}.toString.call(t.process)==="[object process]"?A=function(Se){g.nextTick(function(){oe(Se)})}:function(){if(t.postMessage&&!t.importScripts){var Se=!0,me=t.onmessage;return t.onmessage=function(){Se=!1},t.postMessage("","*"),t.onmessage=me,Se}}()?(L="setImmediate$"+Math.random()+"$",N=function(Se){Se.source===t&&typeof Se.data=="string"&&Se.data.indexOf(L)===0&&oe(+Se.data.slice(L.length))},t.addEventListener?t.addEventListener("message",N,!1):t.attachEvent("onmessage",N),A=function(Se){t.postMessage(L+Se,"*")}):t.MessageChannel?((D=new MessageChannel).port1.onmessage=function(Se){oe(Se.data)},A=function(Se){D.port2.postMessage(Se)}):re&&"onreadystatechange"in re.createElement("script")?(x=re.documentElement,A=function(Se){var me=re.createElement("script");me.onreadystatechange=function(){oe(Se),me.onreadystatechange=null,x.removeChild(me),me=null},x.appendChild(me)}):A=function(Se){setTimeout(oe,0,Se)},ce.setImmediate=function(Se){typeof Se!="function"&&(Se=new Function(""+Se));for(var me=new Array(arguments.length-1),De=0;Dene;ne++)if((V=Q(Je,Ot,ne))!==-1){ce=ne,Ot=V;break e}Ot=-1}}e:{if(Je=Nt,(V=j().get(At.primitive))!==void 0){for(ne=0;neOt-Je?null:Nt.slice(Je,Ot-1))!==null){if(Ot=0,Le!==null){for(;OtOt;Le--)ot=Ue.pop()}for(Le=Nt.length-Ot-1;1<=Le;Le--)Ot=[],ot.push({id:null,isStateEditable:!1,name:Se(Nt[Le-1].functionName),value:void 0,subHooks:Ot}),Ue.push(ot),ot=Ot;Le=Nt}Ot=(Nt=At.primitive)==="Context"||Nt==="DebugValue"?null:ct++,ot.push({id:Ot,isStateEditable:Nt==="Reducer"||Nt==="State",name:Nt,value:At.value,subHooks:[]})}return function ge(Z,Ae){for(var at=[],it=0;it-1&&($=$.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(\),.*$)/g,""));var h=$.replace(/^\s+/,"").replace(/\(eval code/g,"("),re=h.match(/ (\((.+):(\d+):(\d+)\)$)/),ce=(h=re?h.replace(re[0],""):h).split(/\s+/).slice(1),Q=this.extractLocation(re?re[1]:ce.pop()),oe=ce.join(" ")||void 0,Se=["eval",""].indexOf(Q[0])>-1?void 0:Q[0];return new x({functionName:oe,fileName:Se,lineNumber:Q[1],columnNumber:Q[2],source:$})},this)},parseFFOrSafari:function(j){return j.stack.split(` + `).filter(function($){return!$.match(N)},this).map(function($){if($.indexOf(" > eval")>-1&&($=$.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),$.indexOf("@")===-1&&$.indexOf(":")===-1)return new x({functionName:$});var h=/((.*".+"[^@]*)?[^@]*)(?:@)/,re=$.match(h),ce=re&&re[1]?re[1]:void 0,Q=this.extractLocation($.replace(h,""));return new x({functionName:ce,fileName:Q[0],lineNumber:Q[1],columnNumber:Q[2],source:$})},this)},parseOpera:function(j){return!j.stacktrace||j.message.indexOf(` + `)>-1&&j.message.split(` + `).length>j.stacktrace.split(` + `).length?this.parseOpera9(j):j.stack?this.parseOpera11(j):this.parseOpera10(j)},parseOpera9:function(j){for(var $=/Line (\d+).*script (?:in )?(\S+)/i,h=j.message.split(` + `),re=[],ce=2,Q=h.length;ce/,"$2").replace(/\([^)]*\)/g,"")||void 0;Q.match(/\(([^)]*)\)/)&&(h=Q.replace(/^[^(]+\(([^)]*)\)$/,"$1"));var Se=h===void 0||h==="[arguments not available]"?void 0:h.split(",");return new x({functionName:oe,args:Se,fileName:ce[0],lineNumber:ce[1],columnNumber:ce[2],source:$})},this)}}})=="function"?c.apply(u,g):c)===void 0||(i.exports=t)})()},function(i,u,f){var c,g,t;(function(C,A){"use strict";g=[],(t=typeof(c=function(){function x(oe){return oe.charAt(0).toUpperCase()+oe.substring(1)}function D(oe){return function(){return this[oe]}}var L=["isConstructor","isEval","isNative","isToplevel"],N=["columnNumber","lineNumber"],j=["fileName","functionName","source"],$=L.concat(N,j,["args"]);function h(oe){if(oe)for(var Se=0;Se<$.length;Se++)oe[$[Se]]!==void 0&&this["set"+x($[Se])](oe[$[Se]])}h.prototype={getArgs:function(){return this.args},setArgs:function(oe){if(Object.prototype.toString.call(oe)!=="[object Array]")throw new TypeError("Args must be an Array");this.args=oe},getEvalOrigin:function(){return this.evalOrigin},setEvalOrigin:function(oe){if(oe instanceof h)this.evalOrigin=oe;else{if(!(oe instanceof Object))throw new TypeError("Eval Origin must be an Object or StackFrame");this.evalOrigin=new h(oe)}},toString:function(){var oe=this.getFileName()||"",Se=this.getLineNumber()||"",me=this.getColumnNumber()||"",De=this.getFunctionName()||"";return this.getIsEval()?oe?"[eval] ("+oe+":"+Se+":"+me+")":"[eval]:"+Se+":"+me:De?De+" ("+oe+":"+Se+":"+me+")":oe+":"+Se+":"+me}},h.fromString=function(oe){var Se=oe.indexOf("("),me=oe.lastIndexOf(")"),De=oe.substring(0,Se),J=oe.substring(Se+1,me).split(","),Te=oe.substring(me+1);if(Te.indexOf("@")===0)var Oe=/@(.+?)(?::(\d+))?(?::(\d+))?$/.exec(Te,""),Le=Oe[1],ot=Oe[2],ct=Oe[3];return new h({functionName:De,args:J||void 0,fileName:Le,lineNumber:ot||void 0,columnNumber:ct||void 0})};for(var re=0;re1?de-1:0),ve=1;ve=0&&de.splice(W,1)}}}])&&c(R.prototype,U),H&&c(R,H),F}(),t=f(2),C=f.n(t);try{var A=f(9).default,x=function(F){var R=new RegExp("".concat(F,": ([0-9]+)")),U=A.match(R);return parseInt(U[1],10)};x("comfortable-line-height-data"),x("compact-line-height-data")}catch(F){}function D(F){try{return sessionStorage.getItem(F)}catch(R){return null}}function L(F){try{sessionStorage.removeItem(F)}catch(R){}}function N(F,R){try{return sessionStorage.setItem(F,R)}catch(U){}}var j=function(F,R){return F===R},$=f(1),h=f.n($);function re(F){return F.ownerDocument?F.ownerDocument.defaultView:null}function ce(F){var R=re(F);return R?R.frameElement:null}function Q(F){var R=me(F);return oe([F.getBoundingClientRect(),{top:R.borderTop,left:R.borderLeft,bottom:R.borderBottom,right:R.borderRight,width:0,height:0}])}function oe(F){return F.reduce(function(R,U){return R==null?U:{top:R.top+U.top,left:R.left+U.left,width:R.width,height:R.height,bottom:R.bottom+U.bottom,right:R.right+U.right}})}function Se(F,R){var U=ce(F);if(U&&U!==R){for(var H=[F.getBoundingClientRect()],fe=U,ue=!1;fe;){var de=Q(fe);if(H.push(de),fe=ce(fe),ue)break;fe&&re(fe)===R&&(ue=!0)}return oe(H)}return F.getBoundingClientRect()}function me(F){var R=window.getComputedStyle(F);return{borderLeft:parseInt(R.borderLeftWidth,10),borderRight:parseInt(R.borderRightWidth,10),borderTop:parseInt(R.borderTopWidth,10),borderBottom:parseInt(R.borderBottomWidth,10),marginLeft:parseInt(R.marginLeft,10),marginRight:parseInt(R.marginRight,10),marginTop:parseInt(R.marginTop,10),marginBottom:parseInt(R.marginBottom,10),paddingLeft:parseInt(R.paddingLeft,10),paddingRight:parseInt(R.paddingRight,10),paddingTop:parseInt(R.paddingTop,10),paddingBottom:parseInt(R.paddingBottom,10)}}function De(F,R){var U;if(typeof Symbol=="undefined"||F[Symbol.iterator]==null){if(Array.isArray(F)||(U=function(ve,Fe){if(!!ve){if(typeof ve=="string")return J(ve,Fe);var Ge=Object.prototype.toString.call(ve).slice(8,-1);if(Ge==="Object"&&ve.constructor&&(Ge=ve.constructor.name),Ge==="Map"||Ge==="Set")return Array.from(ve);if(Ge==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(Ge))return J(ve,Fe)}}(F))||R&&F&&typeof F.length=="number"){U&&(F=U);var H=0,fe=function(){};return{s:fe,n:function(){return H>=F.length?{done:!0}:{done:!1,value:F[H++]}},e:function(ve){throw ve},f:fe}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. + In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var ue,de=!0,W=!1;return{s:function(){U=F[Symbol.iterator]()},n:function(){var ve=U.next();return de=ve.done,ve},e:function(ve){W=!0,ue=ve},f:function(){try{de||U.return==null||U.return()}finally{if(W)throw ue}}}}function J(F,R){(R==null||R>F.length)&&(R=F.length);for(var U=0,H=new Array(R);Ude.left+de.width&&(K=de.left+de.width-Ge-5),{style:{top:ve+="px",left:K+="px"}}}(R,U,{width:H.width,height:H.height});h()(this.tip.style,fe.style)}}]),F}(),Ue=function(){function F(){Te(this,F);var R=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.window=R;var U=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.tipBoundsWindow=U;var H=R.document;this.container=H.createElement("div"),this.container.style.zIndex="10000000",this.tip=new ct(H,this.container),this.rects=[],H.body.appendChild(this.container)}return Le(F,[{key:"remove",value:function(){this.tip.remove(),this.rects.forEach(function(R){R.remove()}),this.rects.length=0,this.container.parentNode&&this.container.parentNode.removeChild(this.container)}},{key:"inspect",value:function(R,U){for(var H=this,fe=R.filter(function(Xe){return Xe.nodeType===Node.ELEMENT_NODE});this.rects.length>fe.length;)this.rects.pop().remove();if(fe.length!==0){for(;this.rects.length1&&arguments[1]!==void 0?arguments[1]:j,je=void 0,Xe=[],rt=void 0,st=!1,xt=function(lt,Rt){return xe(lt,Xe[Rt])},wt=function(){for(var lt=arguments.length,Rt=Array(lt),yn=0;yn5&&arguments[5]!==void 0?arguments[5]:0,W=cl(F);switch(W){case"html_element":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:F.tagName,type:W};case"function":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:typeof F.name!="function"&&F.name?F.name:"function",type:W};case"string":return F.length<=500?F:F.slice(0,500)+"...";case"bigint":case"symbol":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:F.toString(),type:W};case"react_element":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:al(F)||"Unknown",type:W};case"array_buffer":case"data_view":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:W==="data_view"?"DataView":"ArrayBuffer",size:F.byteLength,type:W};case"array":return ue=fe(H),de>=2&&!ue?yo(W,!0,F,R,H):F.map(function(Ge,K){return Ds(Ge,R,U,H.concat([K]),fe,ue?1:de+1)});case"html_all_collection":case"typed_array":case"iterator":if(ue=fe(H),de>=2&&!ue)return yo(W,!0,F,R,H);var ve={unserializable:!0,type:W,readonly:!0,size:W==="typed_array"?F.length:void 0,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:F.constructor&&F.constructor.name!=="Object"?F.constructor.name:""};return r0(F[Symbol.iterator])&&Array.from(F).forEach(function(Ge,K){return ve[K]=Ds(Ge,R,U,H.concat([K]),fe,ue?1:de+1)}),U.push(H),ve;case"opaque_iterator":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:F[Symbol.toStringTag],type:W};case"date":case"regexp":return R.push(H),{inspectable:!1,preview_short:Mr(F,!1),preview_long:Mr(F,!0),name:F.toString(),type:W};case"object":if(ue=fe(H),de>=2&&!ue)return yo(W,!0,F,R,H);var Fe={};return Es(F).forEach(function(Ge){var K=Ge.toString();Fe[K]=Ds(F[Ge],R,U,H.concat([K]),fe,ue?1:de+1)}),Fe;case"infinity":case"nan":case"undefined":return R.push(H),{type:W};default:return F}}function Mu(F){return(Mu=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(R){return typeof R}:function(R){return R&&typeof Symbol=="function"&&R.constructor===Symbol&&R!==Symbol.prototype?"symbol":typeof R})(F)}function Gf(F){return function(R){if(Array.isArray(R))return iu(R)}(F)||function(R){if(typeof Symbol!="undefined"&&Symbol.iterator in Object(R))return Array.from(R)}(F)||function(R,U){if(!!R){if(typeof R=="string")return iu(R,U);var H=Object.prototype.toString.call(R).slice(8,-1);if(H==="Object"&&R.constructor&&(H=R.constructor.name),H==="Map"||H==="Set")return Array.from(R);if(H==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(H))return iu(R,U)}}(F)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. + In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function iu(F,R){(R==null||R>F.length)&&(R=F.length);for(var U=0,H=new Array(R);UR.toString()?1:R.toString()>F.toString()?-1:0}function Es(F){for(var R=[],U=F,H=function(){var fe=[].concat(Gf(Object.keys(U)),Gf(Object.getOwnPropertySymbols(U))),ue=Object.getOwnPropertyDescriptors(U);fe.forEach(function(de){ue[de].enumerable&&R.push(de)}),U=Object.getPrototypeOf(U)};U!=null;)H();return R}function Uo(F){var R=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"Anonymous",U=ou.get(F);if(U!=null)return U;var H=R;return typeof F.displayName=="string"?H=F.displayName:typeof F.name=="string"&&F.name!==""&&(H=F.name),ou.set(F,H),H}var sl=0;function Ss(){return++sl}function Cs(F){var R=ol.get(F);if(R!==void 0)return R;for(var U=new Array(F.length),H=0;H1&&arguments[1]!==void 0?arguments[1]:50;return F.length>R?F.substr(0,R)+"\u2026":F}function Mr(F,R){if(F!=null&&hasOwnProperty.call(F,Ci.type))return R?F[Ci.preview_long]:F[Ci.preview_short];switch(cl(F)){case"html_element":return"<".concat(Ui(F.tagName.toLowerCase())," />");case"function":return Ui("\u0192 ".concat(typeof F.name=="function"?"":F.name,"() {}"));case"string":return'"'.concat(F,'"');case"bigint":return Ui(F.toString()+"n");case"regexp":case"symbol":return Ui(F.toString());case"react_element":return"<".concat(Ui(al(F)||"Unknown")," />");case"array_buffer":return"ArrayBuffer(".concat(F.byteLength,")");case"data_view":return"DataView(".concat(F.buffer.byteLength,")");case"array":if(R){for(var U="",H=0;H0&&(U+=", "),!((U+=Mr(F[H],!1)).length>50));H++);return"[".concat(Ui(U),"]")}var fe=hasOwnProperty.call(F,Ci.size)?F[Ci.size]:F.length;return"Array(".concat(fe,")");case"typed_array":var ue="".concat(F.constructor.name,"(").concat(F.length,")");if(R){for(var de="",W=0;W0&&(de+=", "),!((de+=F[W]).length>50));W++);return"".concat(ue," [").concat(Ui(de),"]")}return ue;case"iterator":var ve=F.constructor.name;if(R){for(var Fe=Array.from(F),Ge="",K=0;K0&&(Ge+=", "),Array.isArray(xe)){var je=Mr(xe[0],!0),Xe=Mr(xe[1],!1);Ge+="".concat(je," => ").concat(Xe)}else Ge+=Mr(xe,!1);if(Ge.length>50)break}return"".concat(ve,"(").concat(F.size,") {").concat(Ui(Ge),"}")}return"".concat(ve,"(").concat(F.size,")");case"opaque_iterator":return F[Symbol.toStringTag];case"date":return F.toString();case"object":if(R){for(var rt=Es(F).sort(ul),st="",xt=0;xt0&&(st+=", "),(st+="".concat(wt.toString(),": ").concat(Mr(F[wt],!1))).length>50)break}return"{".concat(Ui(st),"}")}return"{\u2026}";case"boolean":case"number":case"infinity":case"nan":case"null":case"undefined":return F;default:try{return Ui(""+F)}catch(lt){return"unserializable"}}}var Ac=f(7);function of(F){return(of=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(R){return typeof R}:function(R){return R&&typeof Symbol=="function"&&R.constructor===Symbol&&R!==Symbol.prototype?"symbol":typeof R})(F)}function Ts(F,R){var U=Object.keys(F);if(Object.getOwnPropertySymbols){var H=Object.getOwnPropertySymbols(F);R&&(H=H.filter(function(fe){return Object.getOwnPropertyDescriptor(F,fe).enumerable})),U.push.apply(U,H)}return U}function xs(F){for(var R=1;R2&&arguments[2]!==void 0?arguments[2]:[];if(F!==null){var H=[],fe=[],ue=Ds(F,H,fe,U,R);return{data:ue,cleaned:H,unserializable:fe}}return null}function qo(F){var R,U,H=(R=F,U=new Set,JSON.stringify(R,function(de,W){if(of(W)==="object"&&W!==null){if(U.has(W))return;U.add(W)}return typeof W=="bigint"?W.toString()+"n":W})),fe=H===void 0?"undefined":H,ue=window.__REACT_DEVTOOLS_GLOBAL_HOOK__.clipboardCopyText;typeof ue=="function"?ue(fe).catch(function(de){}):Object(Ac.copy)(fe)}function kr(F,R){var U=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,H=R[U],fe=Array.isArray(F)?F.slice():xs({},F);return U+1===R.length?Array.isArray(fe)?fe.splice(H,1):delete fe[H]:fe[H]=kr(F[H],R,U+1),fe}function Fr(F,R,U){var H=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,fe=R[H],ue=Array.isArray(F)?F.slice():xs({},F);if(H+1===R.length){var de=U[H];ue[de]=ue[fe],Array.isArray(ue)?ue.splice(fe,1):delete ue[fe]}else ue[fe]=Fr(F[fe],R,U,H+1);return ue}function si(F,R,U){var H=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0;if(H>=R.length)return U;var fe=R[H],ue=Array.isArray(F)?F.slice():xs({},F);return ue[fe]=si(F[fe],R,U,H+1),ue}var H0=f(8);function b0(F,R){var U=Object.keys(F);if(Object.getOwnPropertySymbols){var H=Object.getOwnPropertySymbols(F);R&&(H=H.filter(function(fe){return Object.getOwnPropertyDescriptor(F,fe).enumerable})),U.push.apply(U,H)}return U}function Bt(F){for(var R=1;R=F.length?{done:!0}:{done:!1,value:F[H++]}},e:function(ve){throw ve},f:fe}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. + In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var ue,de=!0,W=!1;return{s:function(){U=F[Symbol.iterator]()},n:function(){var ve=U.next();return de=ve.done,ve},e:function(ve){W=!0,ue=ve},f:function(){try{de||U.return==null||U.return()}finally{if(W)throw ue}}}}function As(F,R){if(F){if(typeof F=="string")return uu(F,R);var U=Object.prototype.toString.call(F).slice(8,-1);return U==="Object"&&F.constructor&&(U=F.constructor.name),U==="Map"||U==="Set"?Array.from(F):U==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(U)?uu(F,R):void 0}}function uu(F,R){(R==null||R>F.length)&&(R=F.length);for(var U=0,H=new Array(R);U0){var et=ue(X);if(et!=null){var Dt,bt=ks(du);try{for(bt.s();!(Dt=bt.n()).done;)if(Dt.value.test(et))return!0}catch(fn){bt.e(fn)}finally{bt.f()}}}if(Y!=null&&Yu.size>0){var Zt,qt=Y.fileName,Ut=ks(Yu);try{for(Ut.s();!(Zt=Ut.n()).done;)if(Zt.value.test(qt))return!0}catch(fn){Ut.e(fn)}finally{Ut.f()}}return!1}function Gr(X){var Y=X.type;switch(X.tag){case Xe:case ar:return 1;case je:case rn:return 5;case wt:return 6;case lt:return 11;case yn:return 7;case Rt:case sn:case xt:return 9;case Hn:case Cr:return 8;case He:return 12;case Qe:return 13;default:switch(de(Y)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":return 9;case 60109:case"Symbol(react.provider)":return 2;case 60110:case"Symbol(react.context)":return 2;case 60108:case"Symbol(react.strict_mode)":return 9;case 60114:case"Symbol(react.profiler)":return 10;default:return 9}}}function ir(X){if(Co.has(X))return X;var Y=X.alternate;return Y!=null&&Co.has(Y)?Y:(Co.add(X),X)}window.__REACT_DEVTOOLS_COMPONENT_FILTERS__!=null?qs(window.__REACT_DEVTOOLS_COMPONENT_FILTERS__):qs([{type:1,value:7,isEnabled:!0}]);var L0=new Map,Y0=new Map,Co=new Set,$u=new Map,Vo=new Map,Rr=-1;function Jn(X){if(!L0.has(X)){var Y=Ss();L0.set(X,Y),Y0.set(Y,X)}return L0.get(X)}function ai(X){switch(Gr(X)){case 1:if(N0!==null){var Y=Jn(ir(X)),ye=Vr(X);ye!==null&&N0.set(Y,ye)}}}var o0={};function Vr(X){switch(Gr(X)){case 1:var Y=X.stateNode,ye=o0,he=o0;return Y!=null&&(Y.constructor&&Y.constructor.contextType!=null?he=Y.context:(ye=Y.context)&&Object.keys(ye).length===0&&(ye=o0)),[ye,he];default:return null}}function ff(X){switch(Gr(X)){case 1:if(N0!==null){var Y=Jn(ir(X)),ye=N0.has(Y)?N0.get(Y):null,he=Vr(X);if(ye==null||he==null)return null;var We=Ru(ye,2),et=We[0],Dt=We[1],bt=Ru(he,2),Zt=bt[0],qt=bt[1];if(Zt!==o0)return $0(et,Zt);if(qt!==o0)return Dt!==qt}}return null}function cf(X,Y){if(X==null||Y==null)return!1;if(Y.hasOwnProperty("baseState")&&Y.hasOwnProperty("memoizedState")&&Y.hasOwnProperty("next")&&Y.hasOwnProperty("queue"))for(;Y!==null;){if(Y.memoizedState!==X.memoizedState)return!0;Y=Y.next,X=X.next}return!1}function $0(X,Y){if(X==null||Y==null||Y.hasOwnProperty("baseState")&&Y.hasOwnProperty("memoizedState")&&Y.hasOwnProperty("next")&&Y.hasOwnProperty("queue"))return null;var ye,he=[],We=ks(new Set([].concat(c0(Object.keys(X)),c0(Object.keys(Y)))));try{for(We.s();!(ye=We.n()).done;){var et=ye.value;X[et]!==Y[et]&&he.push(et)}}catch(Dt){We.e(Dt)}finally{We.f()}return he}function K0(X,Y){switch(Y.tag){case Xe:case je:case rt:case Hn:case Cr:return(zo(Y)&K)===K;default:return X.memoizedProps!==Y.memoizedProps||X.memoizedState!==Y.memoizedState||X.ref!==Y.ref}}var ae=[],Be=[],Ie=[],ht=[],mt=new Map,wn=0,Gn=null;function $t(X){ae.push(X)}function X0(X){if(ae.length!==0||Be.length!==0||Ie.length!==0||Gn!==null||u0){var Y=Be.length+Ie.length+(Gn===null?0:1),ye=new Array(3+wn+(Y>0?2+Y:0)+ae.length),he=0;if(ye[he++]=R,ye[he++]=Rr,ye[he++]=wn,mt.forEach(function(bt,Zt){ye[he++]=Zt.length;for(var qt=Cs(Zt),Ut=0;Ut0){ye[he++]=2,ye[he++]=Y;for(var We=Be.length-1;We>=0;We--)ye[he++]=Be[We];for(var et=0;et0?X.forEach(function(Y){F.emit("operations",Y)}):(Fn!==null&&(zr=!0),F.getFiberRoots(R).forEach(function(Y){T0(Rr=Jn(ir(Y.current)),Y.current),u0&&Y.memoizedInteractions!=null&&(uo={changeDescriptions:To?new Map:null,durations:[],commitTime:Os()-v0,interactions:Array.from(Y.memoizedInteractions).map(function(ye){return Bt(Bt({},ye),{},{timestamp:ye.timestamp-v0})}),maxActualDuration:0,priorityLevel:null}),$r(Y.current,null,!1,!1),X0(),Rr=-1}))},getBestMatchForTrackedPath:function(){if(Fn===null||pi===null)return null;for(var X=pi;X!==null&&F0(X);)X=X.return;return X===null?null:{id:Jn(ir(X)),isFullMatch:Br===Fn.length-1}},getDisplayNameForFiberID:function(X){var Y=Y0.get(X);return Y!=null?ue(Y):null},getFiberIDForNative:function(X){var Y=arguments.length>1&&arguments[1]!==void 0&&arguments[1],ye=U.findFiberByHostInstance(X);if(ye!=null){if(Y)for(;ye!==null&&F0(ye);)ye=ye.return;return Jn(ir(ye))}return null},getInstanceAndStyle:function(X){var Y=null,ye=null,he=J0(X);return he!==null&&(Y=he.stateNode,he.memoizedProps!==null&&(ye=he.memoizedProps.style)),{instance:Y,style:ye}},getOwnersList:function(X){var Y=J0(X);if(Y==null)return null;var ye=Y._debugOwner,he=[{displayName:ue(Y)||"Anonymous",id:X,type:Gr(Y)}];if(ye)for(var We=ye;We!==null;)he.unshift({displayName:ue(We)||"Anonymous",id:Jn(ir(We)),type:Gr(We)}),We=We._debugOwner||null;return he},getPathForElement:function(X){var Y=Y0.get(X);if(Y==null)return null;for(var ye=[];Y!==null;)ye.push(Ai(Y)),Y=Y.return;return ye.reverse(),ye},getProfilingData:function(){var X=[];if(pu===null)throw Error("getProfilingData() called before any profiling data was recorded");return pu.forEach(function(Y,ye){var he=[],We=[],et=new Map,Dt=new Map,bt=so!==null&&so.get(ye)||"Unknown";C0!=null&&C0.forEach(function(Zt,qt){di!=null&&di.get(qt)===ye&&We.push([qt,Zt])}),Y.forEach(function(Zt,qt){var Ut=Zt.changeDescriptions,fn=Zt.durations,_t=Zt.interactions,_r=Zt.maxActualDuration,Wr=Zt.priorityLevel,Ar=Zt.commitTime,z=[];_t.forEach(function(s0){et.has(s0.id)||et.set(s0.id,s0),z.push(s0.id);var t0=Dt.get(s0.id);t0!=null?t0.push(qt):Dt.set(s0.id,[qt])});for(var dr=[],Or=[],Qn=0;Qn1?kn.set(Ut,fn-1):kn.delete(Ut),wr.delete(Zt)}(Rr),Yr(ye,!1))}else T0(Rr,ye),$r(ye,null,!1,!1);if(u0&&We){var bt=pu.get(Rr);bt!=null?bt.push(uo):pu.set(Rr,[uo])}X0(),oo&&F.emit("traceUpdates",Hi),Rr=-1},handleCommitFiberUnmount:function(X){Yr(X,!1)},inspectElement:function(X,Y){if(Tr(X)){if(Y!=null){R0(Y);var ye=null;return Y[0]==="hooks"&&(ye="hooks"),{id:X,type:"hydrated-path",path:Y,value:qi(Ti(S0,Y),Nr(null,ye),Y)}}return{id:X,type:"no-change"}}if(El=!1,S0!==null&&S0.id===X||(Q0={}),(S0=af(X))===null)return{id:X,type:"not-found"};Y!=null&&R0(Y),function(We){var et=We.hooks,Dt=We.id,bt=We.props,Zt=Y0.get(Dt);if(Zt!=null){var qt=Zt.elementType,Ut=Zt.stateNode,fn=Zt.tag,_t=Zt.type;switch(fn){case Xe:case ar:case rn:H.$r=Ut;break;case je:H.$r={hooks:et,props:bt,type:_t};break;case wt:H.$r={props:bt,type:_t.render};break;case Hn:case Cr:H.$r={props:bt,type:qt!=null&&qt.type!=null?qt.type:_t};break;default:H.$r=null}}else console.warn('Could not find Fiber with id "'.concat(Dt,'"'))}(S0);var he=Bt({},S0);return he.context=qi(he.context,Nr("context",null)),he.hooks=qi(he.hooks,Nr("hooks","hooks")),he.props=qi(he.props,Nr("props",null)),he.state=qi(he.state,Nr("state",null)),{id:X,type:"full-data",value:he}},logElementToConsole:function(X){var Y=Tr(X)?S0:af(X);if(Y!==null){var ye=typeof console.groupCollapsed=="function";ye&&console.groupCollapsed("[Click to expand] %c<".concat(Y.displayName||"Component"," />"),"color: var(--dom-tag-name-color); font-weight: normal;"),Y.props!==null&&console.log("Props:",Y.props),Y.state!==null&&console.log("State:",Y.state),Y.hooks!==null&&console.log("Hooks:",Y.hooks);var he=zs(X);he!==null&&console.log("Nodes:",he),Y.source!==null&&console.log("Location:",Y.source),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),ye&&console.groupEnd()}else console.warn('Could not find Fiber with id "'.concat(X,'"'))},prepareViewAttributeSource:function(X,Y){Tr(X)&&(window.$attribute=Ti(S0,Y))},prepareViewElementSource:function(X){var Y=Y0.get(X);if(Y!=null){var ye=Y.elementType,he=Y.tag,We=Y.type;switch(he){case Xe:case ar:case rn:case je:H.$type=We;break;case wt:H.$type=We.render;break;case Hn:case Cr:H.$type=ye!=null&&ye.type!=null?ye.type:We;break;default:H.$type=null}}else console.warn('Could not find Fiber with id "'.concat(X,'"'))},overrideSuspense:function(X,Y){if(typeof Eo!="function"||typeof So!="function")throw new Error("Expected overrideSuspense() to not get called for earlier React versions.");Y?(B0.add(X),B0.size===1&&Eo(hu)):(B0.delete(X),B0.size===0&&Eo(Cl));var ye=Y0.get(X);ye!=null&&So(ye)},overrideValueAtPath:function(X,Y,ye,he,We){var et=J0(Y);if(et!==null){var Dt=et.stateNode;switch(X){case"context":switch(he=he.slice(1),et.tag){case Xe:he.length===0?Dt.context=We:fl(Dt.context,he,We),Dt.forceUpdate()}break;case"hooks":typeof p0=="function"&&p0(et,ye,he,We);break;case"props":switch(et.tag){case Xe:et.pendingProps=si(Dt.props,he,We),Dt.forceUpdate();break;default:typeof xi=="function"&&xi(et,he,We)}break;case"state":switch(et.tag){case Xe:fl(Dt.state,he,We),Dt.forceUpdate()}}}},renamePath:function(X,Y,ye,he,We){var et=J0(Y);if(et!==null){var Dt=et.stateNode;switch(X){case"context":switch(he=he.slice(1),We=We.slice(1),et.tag){case Xe:he.length===0||ll(Dt.context,he,We),Dt.forceUpdate()}break;case"hooks":typeof ci=="function"&&ci(et,ye,he,We);break;case"props":Dt===null?typeof qr=="function"&&qr(et,he,We):(et.pendingProps=Fr(Dt.props,he,We),Dt.forceUpdate());break;case"state":ll(Dt.state,he,We),Dt.forceUpdate()}}},renderer:U,setTraceUpdatesEnabled:function(X){oo=X},setTrackedPath:lo,startProfiling:Sl,stopProfiling:function(){u0=!1,To=!1},storeAsGlobal:function(X,Y,ye){if(Tr(X)){var he=Ti(S0,Y),We="$reactTemp".concat(ye);window[We]=he,console.log(We),console.log(he)}},updateComponentFilters:function(X){if(u0)throw Error("Cannot modify filter preferences while profiling");F.getFiberRoots(R).forEach(function(Y){Rr=Jn(ir(Y.current)),m0(Y.current),Yr(Y.current,!1),Rr=-1}),qs(X),kn.clear(),F.getFiberRoots(R).forEach(function(Y){T0(Rr=Jn(ir(Y.current)),Y.current),$r(Y.current,null,!1,!1),X0(Y),Rr=-1})}}}var _n;function Nu(F){return(Nu=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(R){return typeof R}:function(R){return R&&typeof Symbol=="function"&&R.constructor===Symbol&&R!==Symbol.prototype?"symbol":typeof R})(F)}function Wo(F,R,U){if(_n===void 0)try{throw Error()}catch(fe){var H=fe.stack.trim().match(/\n( *(at )?)/);_n=H&&H[1]||""}return` + `+_n+F}var su=!1;function Ps(F,R,U){if(!F||su)return"";var H,fe=Error.prepareStackTrace;Error.prepareStackTrace=void 0,su=!0;var ue=U.current;U.current=null;try{if(R){var de=function(){throw Error()};if(Object.defineProperty(de.prototype,"props",{set:function(){throw Error()}}),(typeof Reflect=="undefined"?"undefined":Nu(Reflect))==="object"&&Reflect.construct){try{Reflect.construct(de,[])}catch(xe){H=xe}Reflect.construct(F,[],de)}else{try{de.call()}catch(xe){H=xe}F.call(de.prototype)}}else{try{throw Error()}catch(xe){H=xe}F()}}catch(xe){if(xe&&H&&typeof xe.stack=="string"){for(var W=xe.stack.split(` + `),ve=H.stack.split(` + `),Fe=W.length-1,Ge=ve.length-1;Fe>=1&&Ge>=0&&W[Fe]!==ve[Ge];)Ge--;for(;Fe>=1&&Ge>=0;Fe--,Ge--)if(W[Fe]!==ve[Ge]){if(Fe!==1||Ge!==1)do if(Fe--,--Ge<0||W[Fe]!==ve[Ge])return` + `+W[Fe].replace(" at new "," at ");while(Fe>=1&&Ge>=0);break}}}finally{su=!1,Error.prepareStackTrace=fe,U.current=ue}var K=F?F.displayName||F.name:"";return K?Wo(K):""}function pl(F,R,U,H){return Ps(F,!1,H)}function Vf(F,R,U){var H=F.HostComponent,fe=F.LazyComponent,ue=F.SuspenseComponent,de=F.SuspenseListComponent,W=F.FunctionComponent,ve=F.IndeterminateComponent,Fe=F.SimpleMemoComponent,Ge=F.ForwardRef,K=F.Block,xe=F.ClassComponent;switch(R.tag){case H:return Wo(R.type);case fe:return Wo("Lazy");case ue:return Wo("Suspense");case de:return Wo("SuspenseList");case W:case ve:case Fe:return pl(R.type,0,0,U);case Ge:return pl(R.type.render,0,0,U);case K:return pl(R.type._render,0,0,U);case xe:return function(je,Xe,rt,st){return Ps(je,!0,st)}(R.type,0,0,U);default:return""}}function hl(F,R,U){try{var H="",fe=R;do H+=Vf(F,fe,U),fe=fe.return;while(fe);return H}catch(ue){return` + Error generating stack: `+ue.message+` + `+ue.stack}}function Bu(F,R){var U;if(typeof Symbol=="undefined"||F[Symbol.iterator]==null){if(Array.isArray(F)||(U=function(ve,Fe){if(!!ve){if(typeof ve=="string")return ju(ve,Fe);var Ge=Object.prototype.toString.call(ve).slice(8,-1);if(Ge==="Object"&&ve.constructor&&(Ge=ve.constructor.name),Ge==="Map"||Ge==="Set")return Array.from(ve);if(Ge==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(Ge))return ju(ve,Fe)}}(F))||R&&F&&typeof F.length=="number"){U&&(F=U);var H=0,fe=function(){};return{s:fe,n:function(){return H>=F.length?{done:!0}:{done:!1,value:F[H++]}},e:function(ve){throw ve},f:fe}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. + In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var ue,de=!0,W=!1;return{s:function(){U=F[Symbol.iterator]()},n:function(){var ve=U.next();return de=ve.done,ve},e:function(ve){W=!0,ue=ve},f:function(){try{de||U.return==null||U.return()}finally{if(W)throw ue}}}}function ju(F,R){(R==null||R>F.length)&&(R=F.length);for(var U=0,H=new Array(R);U0?Fe[Fe.length-1]:null,xe=K!==null&&(ro.test(K)||Ms.test(K));if(!xe){var je,Xe=Bu(ml.values());try{for(Xe.s();!(je=Xe.n()).done;){var rt=je.value,st=rt.currentDispatcherRef,xt=rt.getCurrentFiber,wt=rt.workTagMap,lt=xt();if(lt!=null){var Rt=hl(wt,lt,st);Rt!==""&&Fe.push(Rt);break}}}catch(yn){Xe.e(yn)}finally{Xe.f()}}}catch(yn){}ue.apply(void 0,Fe)};de.__REACT_DEVTOOLS_ORIGINAL_METHOD__=ue,Uu[fe]=de}catch(W){}})}}function O0(F){return(O0=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(R){return typeof R}:function(R){return R&&typeof Symbol=="function"&&R.constructor===Symbol&&R!==Symbol.prototype?"symbol":typeof R})(F)}function vl(F,R){for(var U=0;UF.length)&&(R=F.length);for(var U=0,H=new Array(R);U1?W-1:0),Fe=1;Fe0?K[K.length-1]:0),K.push(St),W.set(Ne,Fe(ft._topLevelWrapper));try{var Qt=He.apply(this,Qe);return K.pop(),Qt}catch(bn){throw K=[],bn}finally{if(K.length===0){var Cn=W.get(Ne);if(Cn===void 0)throw new Error("Expected to find root ID.");yn(Cn)}}},performUpdateIfNecessary:function(He,Qe){var Ne=Qe[0];if(P0(Ne)===9)return He.apply(this,Qe);var ft=Fe(Ne);K.push(ft);var St=ln(Ne);try{var Qt=He.apply(this,Qe),Cn=ln(Ne);return Ge(St,Cn)||Xe(Ne,ft,Cn),K.pop(),Qt}catch(p0){throw K=[],p0}finally{if(K.length===0){var bn=W.get(Ne);if(bn===void 0)throw new Error("Expected to find root ID.");yn(bn)}}},receiveComponent:function(He,Qe){var Ne=Qe[0];if(P0(Ne)===9)return He.apply(this,Qe);var ft=Fe(Ne);K.push(ft);var St=ln(Ne);try{var Qt=He.apply(this,Qe),Cn=ln(Ne);return Ge(St,Cn)||Xe(Ne,ft,Cn),K.pop(),Qt}catch(p0){throw K=[],p0}finally{if(K.length===0){var bn=W.get(Ne);if(bn===void 0)throw new Error("Expected to find root ID.");yn(bn)}}},unmountComponent:function(He,Qe){var Ne=Qe[0];if(P0(Ne)===9)return He.apply(this,Qe);var ft=Fe(Ne);K.push(ft);try{var St=He.apply(this,Qe);return K.pop(),function(Cn,bn){wt.push(bn),ue.delete(bn)}(0,ft),St}catch(Cn){throw K=[],Cn}finally{if(K.length===0){var Qt=W.get(Ne);if(Qt===void 0)throw new Error("Expected to find root ID.");yn(Qt)}}}}));var st=[],xt=new Map,wt=[],lt=0,Rt=null;function yn(He){if(st.length!==0||wt.length!==0||Rt!==null){var Qe=wt.length+(Rt===null?0:1),Ne=new Array(3+lt+(Qe>0?2+Qe:0)+st.length),ft=0;if(Ne[ft++]=R,Ne[ft++]=He,Ne[ft++]=lt,xt.forEach(function(Cn,bn){Ne[ft++]=bn.length;for(var p0=Cs(bn),h0=0;h00){Ne[ft++]=2,Ne[ft++]=Qe;for(var St=0;St"),"color: var(--dom-tag-name-color); font-weight: normal;"),Qe.props!==null&&console.log("Props:",Qe.props),Qe.state!==null&&console.log("State:",Qe.state),Qe.context!==null&&console.log("Context:",Qe.context);var ft=fe(He);ft!==null&&console.log("Node:",ft),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),Ne&&console.groupEnd()}else console.warn('Could not find element with id "'.concat(He,'"'))},overrideSuspense:function(){throw new Error("overrideSuspense not supported by this renderer")},overrideValueAtPath:function(He,Qe,Ne,ft,St){var Qt=ue.get(Qe);if(Qt!=null){var Cn=Qt._instance;if(Cn!=null)switch(He){case"context":fl(Cn.context,ft,St),a0(Cn);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var bn=Qt._currentElement;Qt._currentElement=V0(V0({},bn),{},{props:si(bn.props,ft,St)}),a0(Cn);break;case"state":fl(Cn.state,ft,St),a0(Cn)}}},renamePath:function(He,Qe,Ne,ft,St){var Qt=ue.get(Qe);if(Qt!=null){var Cn=Qt._instance;if(Cn!=null)switch(He){case"context":ll(Cn.context,ft,St),a0(Cn);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var bn=Qt._currentElement;Qt._currentElement=V0(V0({},bn),{},{props:Fr(bn.props,ft,St)}),a0(Cn);break;case"state":ll(Cn.state,ft,St),a0(Cn)}}},prepareViewAttributeSource:function(He,Qe){var Ne=Cr(He);Ne!==null&&(window.$attribute=Ti(Ne,Qe))},prepareViewElementSource:function(He){var Qe=ue.get(He);if(Qe!=null){var Ne=Qe._currentElement;Ne!=null?H.$type=Ne.type:console.warn('Could not find element with id "'.concat(He,'"'))}else console.warn('Could not find instance with id "'.concat(He,'"'))},renderer:U,setTraceUpdatesEnabled:function(He){},setTrackedPath:function(He){},startProfiling:function(){},stopProfiling:function(){},storeAsGlobal:function(He,Qe,Ne){var ft=Cr(He);if(ft!==null){var St=Ti(ft,Qe),Qt="$reactTemp".concat(Ne);window[Qt]=St,console.log(Qt),console.log(St)}},updateComponentFilters:function(He){}}}function nr(F,R){var U=!1,H={bottom:0,left:0,right:0,top:0},fe=R[F];if(fe!=null){for(var ue=0,de=Object.keys(H);ue0?"development":"production";var st=Function.prototype.toString;if(rt.Mount&&rt.Mount._renderNewRootComponent){var xt=st.call(rt.Mount._renderNewRootComponent);return xt.indexOf("function")!==0?"production":xt.indexOf("storedMeasure")!==-1?"development":xt.indexOf("should be a pure function")!==-1?xt.indexOf("NODE_ENV")!==-1||xt.indexOf("development")!==-1||xt.indexOf("true")!==-1?"development":xt.indexOf("nextElement")!==-1||xt.indexOf("nextComponent")!==-1?"unminified":"development":xt.indexOf("nextElement")!==-1||xt.indexOf("nextComponent")!==-1?"unminified":"outdated"}}catch(wt){}return"production"}(ve);try{var K=window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__!==!1,xe=window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__===!0;(K||xe)&&(zi(ve),Ho({appendComponentStack:K,breakOnConsoleErrors:xe}))}catch(rt){}var je=F.__REACT_DEVTOOLS_ATTACH__;if(typeof je=="function"){var Xe=je(W,Fe,ve,F);W.rendererInterfaces.set(Fe,Xe)}return W.emit("renderer",{id:Fe,renderer:ve,reactBuildType:Ge}),Fe},on:function(ve,Fe){ue[ve]||(ue[ve]=[]),ue[ve].push(Fe)},off:function(ve,Fe){if(ue[ve]){var Ge=ue[ve].indexOf(Fe);Ge!==-1&&ue[ve].splice(Ge,1),ue[ve].length||delete ue[ve]}},sub:function(ve,Fe){return W.on(ve,Fe),function(){return W.off(ve,Fe)}},supportsFiber:!0,checkDCE:function(ve){try{Function.prototype.toString.call(ve).indexOf("^_^")>-1&&(U=!0,setTimeout(function(){throw new Error("React is running in production mode, but dead code elimination has not been applied. Read how to correctly configure React for production: https://reactjs.org/link/perf-use-production-build")}))}catch(Fe){}},onCommitFiberUnmount:function(ve,Fe){var Ge=fe.get(ve);Ge!=null&&Ge.handleCommitFiberUnmount(Fe)},onCommitFiberRoot:function(ve,Fe,Ge){var K=W.getFiberRoots(ve),xe=Fe.current,je=K.has(Fe),Xe=xe.memoizedState==null||xe.memoizedState.element==null;je||Xe?je&&Xe&&K.delete(Fe):K.add(Fe);var rt=fe.get(ve);rt!=null&&rt.handleCommitFiberRoot(Fe,Ge)}};Object.defineProperty(F,"__REACT_DEVTOOLS_GLOBAL_HOOK__",{configurable:!1,enumerable:!1,get:function(){return W}})})(window);var M0=window.__REACT_DEVTOOLS_GLOBAL_HOOK__,au=[{type:1,value:7,isEnabled:!0}];function Lr(F){if(M0!=null){var R=F||{},U=R.host,H=U===void 0?"localhost":U,fe=R.nativeStyleEditorValidAttributes,ue=R.useHttps,de=ue!==void 0&&ue,W=R.port,ve=W===void 0?8097:W,Fe=R.websocket,Ge=R.resolveRNStyle,K=Ge===void 0?null:Ge,xe=R.isAppActive,je=de?"wss":"ws",Xe=null;if((xe===void 0?function(){return!0}:xe)()){var rt=null,st=[],xt=je+"://"+H+":"+ve,wt=Fe||new window.WebSocket(xt);wt.onclose=function(){rt!==null&&rt.emit("shutdown"),lt()},wt.onerror=function(){lt()},wt.onmessage=function(Rt){var yn;try{if(typeof Rt.data!="string")throw Error();yn=JSON.parse(Rt.data)}catch(sn){return void console.error("[React DevTools] Failed to parse JSON: "+Rt.data)}st.forEach(function(sn){try{sn(yn)}catch(ar){throw console.log("[React DevTools] Error calling listener",yn),console.log("error:",ar),ar}})},wt.onopen=function(){(rt=new Do({listen:function(rn){return st.push(rn),function(){var Hn=st.indexOf(rn);Hn>=0&&st.splice(Hn,1)}},send:function(rn,Hn,d0){wt.readyState===wt.OPEN?wt.send(JSON.stringify({event:rn,payload:Hn})):(rt!==null&&rt.shutdown(),lt())}})).addListener("inspectElement",function(rn){var Hn=rn.id,d0=rn.rendererID,Cr=Rt.rendererInterfaces[d0];if(Cr!=null){var He=Cr.findNativeNodesForFiberID(Hn);He!=null&&He[0]!=null&&Rt.emit("showNativeHighlight",He[0])}}),rt.addListener("updateComponentFilters",function(rn){au=rn}),window.__REACT_DEVTOOLS_COMPONENT_FILTERS__==null&&rt.send("overrideComponentFilters",au);var Rt=new I0(rt);if(Rt.addListener("shutdown",function(){M0.emit("shutdown")}),function(rn,Hn,d0){if(rn==null)return function(){};var Cr=[rn.sub("renderer-attached",function(Ne){var ft=Ne.id,St=(Ne.renderer,Ne.rendererInterface);Hn.setRendererInterface(ft,St),St.flushInitialOperations()}),rn.sub("unsupported-renderer-version",function(Ne){Hn.onUnsupportedRenderer(Ne)}),rn.sub("operations",Hn.onHookOperations),rn.sub("traceUpdates",Hn.onTraceUpdates)],He=function(Ne,ft){var St=rn.rendererInterfaces.get(Ne);St==null&&(typeof ft.findFiberByHostInstance=="function"?St=uf(rn,Ne,ft,d0):ft.ComponentTree&&(St=lf(rn,Ne,ft,d0)),St!=null&&rn.rendererInterfaces.set(Ne,St)),St!=null?rn.emit("renderer-attached",{id:Ne,renderer:ft,rendererInterface:St}):rn.emit("unsupported-renderer-version",Ne)};rn.renderers.forEach(function(Ne,ft){He(ft,Ne)}),Cr.push(rn.sub("renderer",function(Ne){var ft=Ne.id,St=Ne.renderer;He(ft,St)})),rn.emit("react-devtools",Hn),rn.reactDevtoolsAgent=Hn;var Qe=function(){Cr.forEach(function(Ne){return Ne()}),rn.rendererInterfaces.forEach(function(Ne){Ne.cleanup()}),rn.reactDevtoolsAgent=null};Hn.addListener("shutdown",Qe),Cr.push(function(){Hn.removeListener("shutdown",Qe)})}(M0,Rt,window),K!=null||M0.resolveRNStyle!=null)Gu(rt,Rt,K||M0.resolveRNStyle,fe||M0.nativeStyleEditorValidAttributes||null);else{var yn,sn,ar=function(){rt!==null&&Gu(rt,Rt,yn,sn)};M0.hasOwnProperty("resolveRNStyle")||Object.defineProperty(M0,"resolveRNStyle",{enumerable:!1,get:function(){return yn},set:function(rn){yn=rn,ar()}}),M0.hasOwnProperty("nativeStyleEditorValidAttributes")||Object.defineProperty(M0,"nativeStyleEditorValidAttributes",{enumerable:!1,get:function(){return sn},set:function(rn){sn=rn,ar()}})}}}else lt()}function lt(){Xe===null&&(Xe=setTimeout(function(){return Lr(F)},2e3))}}}])})});var rS=Me(nS=>{"use strict";Object.defineProperty(nS,"__esModule",{value:!0});eS();var _j=tS();_j.connectToDevTools()});var lS=Me(x2=>{"use strict";var iS=x2&&x2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(x2,"__esModule",{value:!0});var oS=Ay(),yj=iS(lE()),uS=iS(hc()),no=Xy();process.env.DEV==="true"&&rS();var sS=i=>{i==null||i.unsetMeasureFunc(),i==null||i.freeRecursive()};x2.default=yj.default({schedulePassiveEffects:oS.unstable_scheduleCallback,cancelPassiveEffects:oS.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>{},resetAfterCommit:i=>{if(i.isStaticDirty){i.isStaticDirty=!1,typeof i.onImmediateRender=="function"&&i.onImmediateRender();return}typeof i.onRender=="function"&&i.onRender()},getChildHostContext:(i,u)=>{let f=i.isInsideText,c=u==="ink-text"||u==="ink-virtual-text";return f===c?i:{isInsideText:c}},shouldSetTextContent:()=>!1,createInstance:(i,u,f,c)=>{if(c.isInsideText&&i==="ink-box")throw new Error(" can\u2019t be nested inside component");let g=i==="ink-text"&&c.isInsideText?"ink-virtual-text":i,t=no.createNode(g);for(let[C,A]of Object.entries(u))C!=="children"&&(C==="style"?no.setStyle(t,A):C==="internal_transform"?t.internal_transform=A:C==="internal_static"?t.internal_static=!0:no.setAttribute(t,C,A));return t},createTextInstance:(i,u,f)=>{if(!f.isInsideText)throw new Error(`Text string "${i}" must be rendered inside component`);return no.createTextNode(i)},resetTextContent:()=>{},hideTextInstance:i=>{no.setTextNodeValue(i,"")},unhideTextInstance:(i,u)=>{no.setTextNodeValue(i,u)},getPublicInstance:i=>i,hideInstance:i=>{var u;(u=i.yogaNode)===null||u===void 0||u.setDisplay(uS.default.DISPLAY_NONE)},unhideInstance:i=>{var u;(u=i.yogaNode)===null||u===void 0||u.setDisplay(uS.default.DISPLAY_FLEX)},appendInitialChild:no.appendChildNode,appendChild:no.appendChildNode,insertBefore:no.insertBeforeNode,finalizeInitialChildren:(i,u,f,c)=>(i.internal_static&&(c.isStaticDirty=!0,c.staticNode=i),!1),supportsMutation:!0,appendChildToContainer:no.appendChildNode,insertInContainerBefore:no.insertBeforeNode,removeChildFromContainer:(i,u)=>{no.removeChildNode(i,u),sS(u.yogaNode)},prepareUpdate:(i,u,f,c,g)=>{i.internal_static&&(g.isStaticDirty=!0);let t={},C=Object.keys(c);for(let A of C)if(c[A]!==f[A]){if(A==="style"&&typeof c.style=="object"&&typeof f.style=="object"){let D=c.style,L=f.style,N=Object.keys(D);for(let j of N){if(j==="borderStyle"||j==="borderColor"){if(typeof t.style!="object"){let $={};t.style=$}t.style.borderStyle=D.borderStyle,t.style.borderColor=D.borderColor}if(D[j]!==L[j]){if(typeof t.style!="object"){let $={};t.style=$}t.style[j]=D[j]}}continue}t[A]=c[A]}return t},commitUpdate:(i,u)=>{for(let[f,c]of Object.entries(u))f!=="children"&&(f==="style"?no.setStyle(i,c):f==="internal_transform"?i.internal_transform=c:f==="internal_static"?i.internal_static=!0:no.setAttribute(i,f,c))},commitTextUpdate:(i,u,f)=>{no.setTextNodeValue(i,f)},removeChild:(i,u)=>{no.removeChildNode(i,u),sS(u.yogaNode)}})});var cS=Me((Jb,fS)=>{"use strict";fS.exports=(i,u=1,f)=>{if(f=dt({indent:" ",includeEmptyLines:!1},f),typeof i!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof i}\``);if(typeof u!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof u}\``);if(typeof f.indent!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof f.indent}\``);if(u===0)return i;let c=f.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return i.replace(c,f.indent.repeat(u))}});var aS=Me(k2=>{"use strict";var wj=k2&&k2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(k2,"__esModule",{value:!0});var Vh=wj(hc());k2.default=i=>i.getComputedWidth()-i.getComputedPadding(Vh.default.EDGE_LEFT)-i.getComputedPadding(Vh.default.EDGE_RIGHT)-i.getComputedBorder(Vh.default.EDGE_LEFT)-i.getComputedBorder(Vh.default.EDGE_RIGHT)});var pS=Me((Zb,dS)=>{dS.exports={single:{topLeft:"\u250C",topRight:"\u2510",bottomRight:"\u2518",bottomLeft:"\u2514",vertical:"\u2502",horizontal:"\u2500"},double:{topLeft:"\u2554",topRight:"\u2557",bottomRight:"\u255D",bottomLeft:"\u255A",vertical:"\u2551",horizontal:"\u2550"},round:{topLeft:"\u256D",topRight:"\u256E",bottomRight:"\u256F",bottomLeft:"\u2570",vertical:"\u2502",horizontal:"\u2500"},bold:{topLeft:"\u250F",topRight:"\u2513",bottomRight:"\u251B",bottomLeft:"\u2517",vertical:"\u2503",horizontal:"\u2501"},singleDouble:{topLeft:"\u2553",topRight:"\u2556",bottomRight:"\u255C",bottomLeft:"\u2559",vertical:"\u2551",horizontal:"\u2500"},doubleSingle:{topLeft:"\u2552",topRight:"\u2555",bottomRight:"\u255B",bottomLeft:"\u2558",vertical:"\u2502",horizontal:"\u2550"},classic:{topLeft:"+",topRight:"+",bottomRight:"+",bottomLeft:"+",vertical:"|",horizontal:"-"}}});var mS=Me((eG,m3)=>{"use strict";var hS=pS();m3.exports=hS;m3.exports.default=hS});var gS=Me((tG,vS)=>{"use strict";vS.exports=(i,u=process.argv)=>{let f=i.startsWith("-")?"":i.length===1?"-":"--",c=u.indexOf(f+i),g=u.indexOf("--");return c!==-1&&(g===-1||c{"use strict";var Dj=require("os"),yS=require("tty"),Pu=gS(),{env:oi}=process,qf;Pu("no-color")||Pu("no-colors")||Pu("color=false")||Pu("color=never")?qf=0:(Pu("color")||Pu("colors")||Pu("color=true")||Pu("color=always"))&&(qf=1);"FORCE_COLOR"in oi&&(oi.FORCE_COLOR==="true"?qf=1:oi.FORCE_COLOR==="false"?qf=0:qf=oi.FORCE_COLOR.length===0?1:Math.min(parseInt(oi.FORCE_COLOR,10),3));function v3(i){return i===0?!1:{level:i,hasBasic:!0,has256:i>=2,has16m:i>=3}}function g3(i,u){if(qf===0)return 0;if(Pu("color=16m")||Pu("color=full")||Pu("color=truecolor"))return 3;if(Pu("color=256"))return 2;if(i&&!u&&qf===void 0)return 0;let f=qf||0;if(oi.TERM==="dumb")return f;if(process.platform==="win32"){let c=Dj.release().split(".");return Number(c[0])>=10&&Number(c[2])>=10586?Number(c[2])>=14931?3:2:1}if("CI"in oi)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(c=>c in oi)||oi.CI_NAME==="codeship"?1:f;if("TEAMCITY_VERSION"in oi)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(oi.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in oi)return 1;if(oi.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in oi){let c=parseInt((oi.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(oi.TERM_PROGRAM){case"iTerm.app":return c>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(oi.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(oi.TERM)||"COLORTERM"in oi?1:f}function Ej(i){let u=g3(i,i&&i.isTTY);return v3(u)}_S.exports={supportsColor:Ej,stdout:v3(g3(!0,yS.isatty(1))),stderr:v3(g3(!0,yS.isatty(2)))}});var ES=Me((rG,DS)=>{"use strict";var Sj=(i,u,f)=>{let c=i.indexOf(u);if(c===-1)return i;let g=u.length,t=0,C="";do C+=i.substr(t,c-t)+u+f,t=c+g,c=i.indexOf(u,t);while(c!==-1);return C+=i.substr(t),C},Cj=(i,u,f,c)=>{let g=0,t="";do{let C=i[c-1]==="\r";t+=i.substr(g,(C?c-1:c)-g)+u+(C?`\r + `:` + `)+f,g=c+1,c=i.indexOf(` + `,g)}while(c!==-1);return t+=i.substr(g),t};DS.exports={stringReplaceAll:Sj,stringEncaseCRLFWithFirstIndex:Cj}});var kS=Me((iG,SS)=>{"use strict";var Tj=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,CS=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,xj=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,kj=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,Aj=new Map([["n",` + `],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e",""],["a","\x07"]]);function TS(i){let u=i[0]==="u",f=i[1]==="{";return u&&!f&&i.length===5||i[0]==="x"&&i.length===3?String.fromCharCode(parseInt(i.slice(1),16)):u&&f?String.fromCodePoint(parseInt(i.slice(2,-1),16)):Aj.get(i)||i}function Oj(i,u){let f=[],c=u.trim().split(/\s*,\s*/g),g;for(let t of c){let C=Number(t);if(!Number.isNaN(C))f.push(C);else if(g=t.match(xj))f.push(g[2].replace(kj,(A,x,D)=>x?TS(x):D));else throw new Error(`Invalid Chalk template style argument: ${t} (in style '${i}')`)}return f}function Ij(i){CS.lastIndex=0;let u=[],f;for(;(f=CS.exec(i))!==null;){let c=f[1];if(f[2]){let g=Oj(c,f[2]);u.push([c].concat(g))}else u.push([c])}return u}function xS(i,u){let f={};for(let g of u)for(let t of g.styles)f[t[0]]=g.inverse?null:t.slice(1);let c=i;for(let[g,t]of Object.entries(f))if(!!Array.isArray(t)){if(!(g in c))throw new Error(`Unknown Chalk style: ${g}`);c=t.length>0?c[g](...t):c[g]}return c}SS.exports=(i,u)=>{let f=[],c=[],g=[];if(u.replace(Tj,(t,C,A,x,D,L)=>{if(C)g.push(TS(C));else if(x){let N=g.join("");g=[],c.push(f.length===0?N:xS(i,f)(N)),f.push({inverse:A,styles:Ij(x)})}else if(D){if(f.length===0)throw new Error("Found extraneous } in Chalk template literal");c.push(xS(i,f)(g.join(""))),g=[],f.pop()}else g.push(L)}),c.push(g.join("")),f.length>0){let t=`Chalk template literal is missing ${f.length} closing bracket${f.length===1?"":"s"} (\`}\`)`;throw new Error(t)}return c.join("")}});var Jh=Me((oG,AS)=>{"use strict";var A2=Rh(),{stdout:_3,stderr:y3}=wS(),{stringReplaceAll:Pj,stringEncaseCRLFWithFirstIndex:Mj}=ES(),{isArray:Yh}=Array,OS=["ansi","ansi","ansi256","ansi16m"],ka=Object.create(null),Fj=(i,u={})=>{if(u.level&&!(Number.isInteger(u.level)&&u.level>=0&&u.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let f=_3?_3.level:0;i.level=u.level===void 0?f:u.level},IS=class{constructor(u){return PS(u)}},PS=i=>{let u={};return Fj(u,i),u.template=(...f)=>MS(u.template,...f),Object.setPrototypeOf(u,$h.prototype),Object.setPrototypeOf(u.template,u),u.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},u.template.Instance=IS,u.template};function $h(i){return PS(i)}for(let[i,u]of Object.entries(A2))ka[i]={get(){let f=Kh(this,w3(u.open,u.close,this._styler),this._isEmpty);return Object.defineProperty(this,i,{value:f}),f}};ka.visible={get(){let i=Kh(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:i}),i}};var LS=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let i of LS)ka[i]={get(){let{level:u}=this;return function(...f){let c=w3(A2.color[OS[u]][i](...f),A2.color.close,this._styler);return Kh(this,c,this._isEmpty)}}};for(let i of LS){let u="bg"+i[0].toUpperCase()+i.slice(1);ka[u]={get(){let{level:f}=this;return function(...c){let g=w3(A2.bgColor[OS[f]][i](...c),A2.bgColor.close,this._styler);return Kh(this,g,this._isEmpty)}}}}var Lj=Object.defineProperties(()=>{},zn(dt({},ka),{level:{enumerable:!0,get(){return this._generator.level},set(i){this._generator.level=i}}})),w3=(i,u,f)=>{let c,g;return f===void 0?(c=i,g=u):(c=f.openAll+i,g=u+f.closeAll),{open:i,close:u,openAll:c,closeAll:g,parent:f}},Kh=(i,u,f)=>{let c=(...g)=>Yh(g[0])&&Yh(g[0].raw)?RS(c,MS(c,...g)):RS(c,g.length===1?""+g[0]:g.join(" "));return Object.setPrototypeOf(c,Lj),c._generator=i,c._styler=u,c._isEmpty=f,c},RS=(i,u)=>{if(i.level<=0||!u)return i._isEmpty?"":u;let f=i._styler;if(f===void 0)return u;let{openAll:c,closeAll:g}=f;if(u.indexOf("")!==-1)for(;f!==void 0;)u=Pj(u,f.close,f.open),f=f.parent;let t=u.indexOf(` + `);return t!==-1&&(u=Mj(u,g,c,t)),c+u+g},D3,MS=(i,...u)=>{let[f]=u;if(!Yh(f)||!Yh(f.raw))return u.join(" ");let c=u.slice(1),g=[f.raw[0]];for(let t=1;t{"use strict";var Rj=O2&&O2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(O2,"__esModule",{value:!0});var I2=Rj(Jh()),Nj=/^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/,Bj=/^(ansi|ansi256)\(\s?(\d+)\s?\)$/,Qh=(i,u)=>u==="foreground"?i:"bg"+i[0].toUpperCase()+i.slice(1);O2.default=(i,u,f)=>{if(!u)return i;if(u in I2.default){let g=Qh(u,f);return I2.default[g](i)}if(u.startsWith("#")){let g=Qh("hex",f);return I2.default[g](u)(i)}if(u.startsWith("ansi")){let g=Bj.exec(u);if(!g)return i;let t=Qh(g[1],f),C=Number(g[2]);return I2.default[t](C)(i)}if(u.startsWith("rgb")||u.startsWith("hsl")||u.startsWith("hsv")||u.startsWith("hwb")){let g=Nj.exec(u);if(!g)return i;let t=Qh(g[1],f),C=Number(g[2]),A=Number(g[3]),x=Number(g[4]);return I2.default[t](C,A,x)(i)}return i}});var BS=Me(P2=>{"use strict";var NS=P2&&P2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(P2,"__esModule",{value:!0});var jj=NS(mS()),S3=NS(E3());P2.default=(i,u,f,c)=>{if(typeof f.style.borderStyle=="string"){let g=f.yogaNode.getComputedWidth(),t=f.yogaNode.getComputedHeight(),C=f.style.borderColor,A=jj.default[f.style.borderStyle],x=S3.default(A.topLeft+A.horizontal.repeat(g-2)+A.topRight,C,"foreground"),D=(S3.default(A.vertical,C,"foreground")+` + `).repeat(t-2),L=S3.default(A.bottomLeft+A.horizontal.repeat(g-2)+A.bottomRight,C,"foreground");c.write(i,u,x,{transformers:[]}),c.write(i,u+1,D,{transformers:[]}),c.write(i+g-1,u+1,D,{transformers:[]}),c.write(i,u+t-1,L,{transformers:[]})}}});var US=Me(M2=>{"use strict";var _c=M2&&M2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(M2,"__esModule",{value:!0});var Uj=_c(hc()),qj=_c(jy()),zj=_c(cS()),Wj=_c(Yy()),Hj=_c(aS()),bj=_c(Ky()),Gj=_c(BS()),Vj=(i,u)=>{var f;let c=(f=i.childNodes[0])===null||f===void 0?void 0:f.yogaNode;if(c){let g=c.getComputedLeft(),t=c.getComputedTop();u=` + `.repeat(t)+zj.default(u,g)}return u},jS=(i,u,f)=>{var c;let{offsetX:g=0,offsetY:t=0,transformers:C=[],skipStaticElements:A}=f;if(A&&i.internal_static)return;let{yogaNode:x}=i;if(x){if(x.getDisplay()===Uj.default.DISPLAY_NONE)return;let D=g+x.getComputedLeft(),L=t+x.getComputedTop(),N=C;if(typeof i.internal_transform=="function"&&(N=[i.internal_transform,...C]),i.nodeName==="ink-text"){let j=bj.default(i);if(j.length>0){let $=qj.default(j),h=Hj.default(x);if($>h){let re=(c=i.style.textWrap)!==null&&c!==void 0?c:"wrap";j=Wj.default(j,h,re)}j=Vj(i,j),u.write(D,L,j,{transformers:N})}return}if(i.nodeName==="ink-box"&&Gj.default(D,L,i,u),i.nodeName==="ink-root"||i.nodeName==="ink-box")for(let j of i.childNodes)jS(j,u,{offsetX:D,offsetY:L,transformers:N,skipStaticElements:A})}};M2.default=jS});var zS=Me((fG,qS)=>{"use strict";qS.exports=i=>{i=Object.assign({onlyFirst:!1},i);let u=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(u,i.onlyFirst?void 0:"g")}});var HS=Me((cG,C3)=>{"use strict";var Yj=zS(),WS=i=>typeof i=="string"?i.replace(Yj(),""):i;C3.exports=WS;C3.exports.default=WS});var VS=Me((aG,bS)=>{"use strict";var GS="[\uD800-\uDBFF][\uDC00-\uDFFF]";bS.exports=i=>i&&i.exact?new RegExp(`^${GS}$`):new RegExp(GS,"g")});var $S=Me((dG,T3)=>{"use strict";var $j=HS(),Kj=VS(),YS=i=>$j(i).replace(Kj()," ").length;T3.exports=YS;T3.exports.default=YS});var QS=Me(F2=>{"use strict";var KS=F2&&F2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(F2,"__esModule",{value:!0});var XS=KS(Gy()),Xj=KS($S()),JS=class{constructor(u){this.writes=[];let{width:f,height:c}=u;this.width=f,this.height=c}write(u,f,c,g){let{transformers:t}=g;!c||this.writes.push({x:u,y:f,text:c,transformers:t})}get(){let u=[];for(let c=0;cc.trimRight()).join(` + `),height:u.length}}};F2.default=JS});var t5=Me(L2=>{"use strict";var x3=L2&&L2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(L2,"__esModule",{value:!0});var Jj=x3(hc()),ZS=x3(US()),e5=x3(QS());L2.default=(i,u)=>{var f;if(i.yogaNode.setWidth(u),i.yogaNode){i.yogaNode.calculateLayout(void 0,void 0,Jj.default.DIRECTION_LTR);let c=new e5.default({width:i.yogaNode.getComputedWidth(),height:i.yogaNode.getComputedHeight()});ZS.default(i,c,{skipStaticElements:!0});let g;((f=i.staticNode)===null||f===void 0?void 0:f.yogaNode)&&(g=new e5.default({width:i.staticNode.yogaNode.getComputedWidth(),height:i.staticNode.yogaNode.getComputedHeight()}),ZS.default(i.staticNode,g,{skipStaticElements:!1}));let{output:t,height:C}=c.get();return{output:t,outputHeight:C,staticOutput:g?`${g.get().output} + `:""}}return{output:"",outputHeight:0,staticOutput:""}}});var o5=Me((mG,n5)=>{"use strict";var r5=require("stream"),i5=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],k3={},Qj=i=>{let u=new r5.PassThrough,f=new r5.PassThrough;u.write=g=>i("stdout",g),f.write=g=>i("stderr",g);let c=new console.Console(u,f);for(let g of i5)k3[g]=console[g],console[g]=c[g];return()=>{for(let g of i5)console[g]=k3[g];k3={}}};n5.exports=Qj});var O3=Me(A3=>{"use strict";Object.defineProperty(A3,"__esModule",{value:!0});A3.default=new WeakMap});var P3=Me(I3=>{"use strict";Object.defineProperty(I3,"__esModule",{value:!0});var Zj=lr(),u5=Zj.createContext({exit:()=>{}});u5.displayName="InternalAppContext";I3.default=u5});var F3=Me(M3=>{"use strict";Object.defineProperty(M3,"__esModule",{value:!0});var eU=lr(),s5=eU.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});s5.displayName="InternalStdinContext";M3.default=s5});var R3=Me(L3=>{"use strict";Object.defineProperty(L3,"__esModule",{value:!0});var tU=lr(),l5=tU.createContext({stdout:void 0,write:()=>{}});l5.displayName="InternalStdoutContext";L3.default=l5});var B3=Me(N3=>{"use strict";Object.defineProperty(N3,"__esModule",{value:!0});var nU=lr(),f5=nU.createContext({stderr:void 0,write:()=>{}});f5.displayName="InternalStderrContext";N3.default=f5});var Zh=Me(j3=>{"use strict";Object.defineProperty(j3,"__esModule",{value:!0});var rU=lr(),c5=rU.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{}});c5.displayName="InternalFocusContext";j3.default=c5});var d5=Me((EG,a5)=>{"use strict";var iU=/[|\\{}()[\]^$+*?.-]/g;a5.exports=i=>{if(typeof i!="string")throw new TypeError("Expected a string");return i.replace(iU,"\\$&")}});var v5=Me((SG,p5)=>{"use strict";var oU=d5(),h5=[].concat(require("module").builtinModules,"bootstrap_node","node").map(i=>new RegExp(`(?:\\(${i}\\.js:\\d+:\\d+\\)$|^\\s*at ${i}\\.js:\\d+:\\d+$)`));h5.push(/\(internal\/[^:]+:\d+:\d+\)$/,/\s*at internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var em=class{constructor(u){u=dt({ignoredPackages:[]},u),"internals"in u||(u.internals=em.nodeInternals()),"cwd"in u||(u.cwd=process.cwd()),this._cwd=u.cwd.replace(/\\/g,"/"),this._internals=[].concat(u.internals,uU(u.ignoredPackages)),this._wrapCallSite=u.wrapCallSite||!1}static nodeInternals(){return[...h5]}clean(u,f=0){f=" ".repeat(f),Array.isArray(u)||(u=u.split(` + `)),!/^\s*at /.test(u[0])&&/^\s*at /.test(u[1])&&(u=u.slice(1));let c=!1,g=null,t=[];return u.forEach(C=>{if(C=C.replace(/\\/g,"/"),this._internals.some(x=>x.test(C)))return;let A=/^\s*at /.test(C);c?C=C.trimEnd().replace(/^(\s+)at /,"$1"):(C=C.trim(),A&&(C=C.slice(3))),C=C.replace(`${this._cwd}/`,""),C&&(A?(g&&(t.push(g),g=null),t.push(C)):(c=!0,g=C))}),t.map(C=>`${f}${C} + `).join("")}captureString(u,f=this.captureString){typeof u=="function"&&(f=u,u=Infinity);let{stackTraceLimit:c}=Error;u&&(Error.stackTraceLimit=u);let g={};Error.captureStackTrace(g,f);let{stack:t}=g;return Error.stackTraceLimit=c,this.clean(t)}capture(u,f=this.capture){typeof u=="function"&&(f=u,u=Infinity);let{prepareStackTrace:c,stackTraceLimit:g}=Error;Error.prepareStackTrace=(A,x)=>this._wrapCallSite?x.map(this._wrapCallSite):x,u&&(Error.stackTraceLimit=u);let t={};Error.captureStackTrace(t,f);let{stack:C}=t;return Object.assign(Error,{prepareStackTrace:c,stackTraceLimit:g}),C}at(u=this.at){let[f]=this.capture(1,u);if(!f)return{};let c={line:f.getLineNumber(),column:f.getColumnNumber()};m5(c,f.getFileName(),this._cwd),f.isConstructor()&&(c.constructor=!0),f.isEval()&&(c.evalOrigin=f.getEvalOrigin()),f.isNative()&&(c.native=!0);let g;try{g=f.getTypeName()}catch(A){}g&&g!=="Object"&&g!=="[object Object]"&&(c.type=g);let t=f.getFunctionName();t&&(c.function=t);let C=f.getMethodName();return C&&t!==C&&(c.method=C),c}parseLine(u){let f=u&&u.match(sU);if(!f)return null;let c=f[1]==="new",g=f[2],t=f[3],C=f[4],A=Number(f[5]),x=Number(f[6]),D=f[7],L=f[8],N=f[9],j=f[10]==="native",$=f[11]===")",h,re={};if(L&&(re.line=Number(L)),N&&(re.column=Number(N)),$&&D){let ce=0;for(let Q=D.length-1;Q>0;Q--)if(D.charAt(Q)===")")ce++;else if(D.charAt(Q)==="("&&D.charAt(Q-1)===" "&&(ce--,ce===-1&&D.charAt(Q-1)===" ")){let oe=D.slice(0,Q-1);D=D.slice(Q+1),g+=` (${oe}`;break}}if(g){let ce=g.match(lU);ce&&(g=ce[1],h=ce[2])}return m5(re,D,this._cwd),c&&(re.constructor=!0),t&&(re.evalOrigin=t,re.evalLine=A,re.evalColumn=x,re.evalFile=C&&C.replace(/\\/g,"/")),j&&(re.native=!0),g&&(re.function=g),h&&g!==h&&(re.method=h),re}};function m5(i,u,f){u&&(u=u.replace(/\\/g,"/"),u.startsWith(`${f}/`)&&(u=u.slice(f.length+1)),i.file=u)}function uU(i){if(i.length===0)return[];let u=i.map(f=>oU(f));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${u.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var sU=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),lU=/^(.*?) \[as (.*?)\]$/;p5.exports=em});var _5=Me((CG,g5)=>{"use strict";g5.exports=(i,u)=>i.replace(/^\t+/gm,f=>" ".repeat(f.length*(u||2)))});var w5=Me((TG,y5)=>{"use strict";var fU=_5(),cU=(i,u)=>{let f=[],c=i-u,g=i+u;for(let t=c;t<=g;t++)f.push(t);return f};y5.exports=(i,u,f)=>{if(typeof i!="string")throw new TypeError("Source code is missing.");if(!u||u<1)throw new TypeError("Line number must start from `1`.");if(i=fU(i).split(/\r?\n/),!(u>i.length))return f=dt({around:3},f),cU(u,f.around).filter(c=>i[c-1]!==void 0).map(c=>({line:c,value:i[c-1]}))}});var tm=Me(hs=>{"use strict";var aU=hs&&hs.__createBinding||(Object.create?function(i,u,f,c){c===void 0&&(c=f),Object.defineProperty(i,c,{enumerable:!0,get:function(){return u[f]}})}:function(i,u,f,c){c===void 0&&(c=f),i[c]=u[f]}),dU=hs&&hs.__setModuleDefault||(Object.create?function(i,u){Object.defineProperty(i,"default",{enumerable:!0,value:u})}:function(i,u){i.default=u}),pU=hs&&hs.__importStar||function(i){if(i&&i.__esModule)return i;var u={};if(i!=null)for(var f in i)f!=="default"&&Object.hasOwnProperty.call(i,f)&&aU(u,i,f);return dU(u,i),u},hU=hs&&hs.__rest||function(i,u){var f={};for(var c in i)Object.prototype.hasOwnProperty.call(i,c)&&u.indexOf(c)<0&&(f[c]=i[c]);if(i!=null&&typeof Object.getOwnPropertySymbols=="function")for(var g=0,c=Object.getOwnPropertySymbols(i);g{var{children:f}=i,c=hU(i,["children"]);let g=Object.assign(Object.assign({},c),{marginLeft:c.marginLeft||c.marginX||c.margin||0,marginRight:c.marginRight||c.marginX||c.margin||0,marginTop:c.marginTop||c.marginY||c.margin||0,marginBottom:c.marginBottom||c.marginY||c.margin||0,paddingLeft:c.paddingLeft||c.paddingX||c.padding||0,paddingRight:c.paddingRight||c.paddingX||c.padding||0,paddingTop:c.paddingTop||c.paddingY||c.padding||0,paddingBottom:c.paddingBottom||c.paddingY||c.padding||0});return D5.default.createElement("ink-box",{ref:u,style:g},f)});U3.displayName="Box";U3.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};hs.default=U3});var W3=Me(R2=>{"use strict";var q3=R2&&R2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(R2,"__esModule",{value:!0});var mU=q3(lr()),Aa=q3(Jh()),E5=q3(E3()),z3=({color:i,backgroundColor:u,dimColor:f,bold:c,italic:g,underline:t,strikethrough:C,inverse:A,wrap:x,children:D})=>{if(D==null)return null;let L=N=>(f&&(N=Aa.default.dim(N)),i&&(N=E5.default(N,i,"foreground")),u&&(N=E5.default(N,u,"background")),c&&(N=Aa.default.bold(N)),g&&(N=Aa.default.italic(N)),t&&(N=Aa.default.underline(N)),C&&(N=Aa.default.strikethrough(N)),A&&(N=Aa.default.inverse(N)),N);return mU.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row",textWrap:x},internal_transform:L},D)};z3.displayName="Text";z3.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:"wrap"};R2.default=z3});var x5=Me(ms=>{"use strict";var vU=ms&&ms.__createBinding||(Object.create?function(i,u,f,c){c===void 0&&(c=f),Object.defineProperty(i,c,{enumerable:!0,get:function(){return u[f]}})}:function(i,u,f,c){c===void 0&&(c=f),i[c]=u[f]}),gU=ms&&ms.__setModuleDefault||(Object.create?function(i,u){Object.defineProperty(i,"default",{enumerable:!0,value:u})}:function(i,u){i.default=u}),_U=ms&&ms.__importStar||function(i){if(i&&i.__esModule)return i;var u={};if(i!=null)for(var f in i)f!=="default"&&Object.hasOwnProperty.call(i,f)&&vU(u,i,f);return gU(u,i),u},N2=ms&&ms.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(ms,"__esModule",{value:!0});var S5=_U(require("fs")),ui=N2(lr()),C5=N2(v5()),yU=N2(w5()),ef=N2(tm()),il=N2(W3()),T5=new C5.default({cwd:process.cwd(),internals:C5.default.nodeInternals()}),wU=({error:i})=>{let u=i.stack?i.stack.split(` + `).slice(1):void 0,f=u?T5.parseLine(u[0]):void 0,c,g=0;if((f==null?void 0:f.file)&&(f==null?void 0:f.line)&&S5.existsSync(f.file)){let t=S5.readFileSync(f.file,"utf8");if(c=yU.default(t,f.line),c)for(let{line:C}of c)g=Math.max(g,String(C).length)}return ui.default.createElement(ef.default,{flexDirection:"column",padding:1},ui.default.createElement(ef.default,null,ui.default.createElement(il.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),ui.default.createElement(il.default,null," ",i.message)),f&&ui.default.createElement(ef.default,{marginTop:1},ui.default.createElement(il.default,{dimColor:!0},f.file,":",f.line,":",f.column)),f&&c&&ui.default.createElement(ef.default,{marginTop:1,flexDirection:"column"},c.map(({line:t,value:C})=>ui.default.createElement(ef.default,{key:t},ui.default.createElement(ef.default,{width:g+1},ui.default.createElement(il.default,{dimColor:t!==f.line,backgroundColor:t===f.line?"red":void 0,color:t===f.line?"white":void 0},String(t).padStart(g," "),":")),ui.default.createElement(il.default,{key:t,backgroundColor:t===f.line?"red":void 0,color:t===f.line?"white":void 0}," "+C)))),i.stack&&ui.default.createElement(ef.default,{marginTop:1,flexDirection:"column"},i.stack.split(` + `).slice(1).map(t=>{let C=T5.parseLine(t);return C?ui.default.createElement(ef.default,{key:t},ui.default.createElement(il.default,{dimColor:!0},"- "),ui.default.createElement(il.default,{dimColor:!0,bold:!0},C.function),ui.default.createElement(il.default,{dimColor:!0,color:"gray"}," ","(",C.file,":",C.line,":",C.column,")")):ui.default.createElement(ef.default,{key:t},ui.default.createElement(il.default,{dimColor:!0},"- "),ui.default.createElement(il.default,{dimColor:!0,bold:!0},t))})))};ms.default=wU});var A5=Me(vs=>{"use strict";var DU=vs&&vs.__createBinding||(Object.create?function(i,u,f,c){c===void 0&&(c=f),Object.defineProperty(i,c,{enumerable:!0,get:function(){return u[f]}})}:function(i,u,f,c){c===void 0&&(c=f),i[c]=u[f]}),EU=vs&&vs.__setModuleDefault||(Object.create?function(i,u){Object.defineProperty(i,"default",{enumerable:!0,value:u})}:function(i,u){i.default=u}),SU=vs&&vs.__importStar||function(i){if(i&&i.__esModule)return i;var u={};if(i!=null)for(var f in i)f!=="default"&&Object.hasOwnProperty.call(i,f)&&DU(u,i,f);return EU(u,i),u},yc=vs&&vs.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(vs,"__esModule",{value:!0});var wc=SU(lr()),k5=yc(gy()),CU=yc(P3()),TU=yc(F3()),xU=yc(R3()),kU=yc(B3()),AU=yc(Zh()),OU=yc(x5()),IU=" ",PU="",MU="",H3=class extends wc.PureComponent{constructor(){super(...arguments);this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=u=>{let{stdin:f}=this.props;if(!this.isRawModeSupported())throw f===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default. + Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink. + Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(f.setEncoding("utf8"),u){this.rawModeEnabledCount===0&&(f.addListener("data",this.handleInput),f.resume(),f.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount==0&&(f.setRawMode(!1),f.removeListener("data",this.handleInput),f.pause())},this.handleInput=u=>{u===""&&this.props.exitOnCtrlC&&this.handleExit(),u===MU&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(u===IU&&this.focusNext(),u===PU&&this.focusPrevious())},this.handleExit=u=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(u)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focusNext=()=>{this.setState(u=>{let f=u.focusables[0].id;return{activeFocusId:this.findNextFocusable(u)||f}})},this.focusPrevious=()=>{this.setState(u=>{let f=u.focusables[u.focusables.length-1].id;return{activeFocusId:this.findPreviousFocusable(u)||f}})},this.addFocusable=(u,{autoFocus:f})=>{this.setState(c=>{let g=c.activeFocusId;return!g&&f&&(g=u),{activeFocusId:g,focusables:[...c.focusables,{id:u,isActive:!0}]}})},this.removeFocusable=u=>{this.setState(f=>({activeFocusId:f.activeFocusId===u?void 0:f.activeFocusId,focusables:f.focusables.filter(c=>c.id!==u)}))},this.activateFocusable=u=>{this.setState(f=>({focusables:f.focusables.map(c=>c.id!==u?c:{id:u,isActive:!0})}))},this.deactivateFocusable=u=>{this.setState(f=>({activeFocusId:f.activeFocusId===u?void 0:f.activeFocusId,focusables:f.focusables.map(c=>c.id!==u?c:{id:u,isActive:!1})}))},this.findNextFocusable=u=>{let f=u.focusables.findIndex(c=>c.id===u.activeFocusId);for(let c=f+1;c{let f=u.focusables.findIndex(c=>c.id===u.activeFocusId);for(let c=f-1;c>=0;c--)if(u.focusables[c].isActive)return u.focusables[c].id}}static getDerivedStateFromError(u){return{error:u}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return wc.default.createElement(CU.default.Provider,{value:{exit:this.handleExit}},wc.default.createElement(TU.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},wc.default.createElement(xU.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},wc.default.createElement(kU.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},wc.default.createElement(AU.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious}},this.state.error?wc.default.createElement(OU.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){k5.default.hide(this.props.stdout)}componentWillUnmount(){k5.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(u){this.handleExit(u)}};vs.default=H3;H3.displayName="InternalApp"});var M5=Me(gs=>{"use strict";var FU=gs&&gs.__createBinding||(Object.create?function(i,u,f,c){c===void 0&&(c=f),Object.defineProperty(i,c,{enumerable:!0,get:function(){return u[f]}})}:function(i,u,f,c){c===void 0&&(c=f),i[c]=u[f]}),LU=gs&&gs.__setModuleDefault||(Object.create?function(i,u){Object.defineProperty(i,"default",{enumerable:!0,value:u})}:function(i,u){i.default=u}),RU=gs&&gs.__importStar||function(i){if(i&&i.__esModule)return i;var u={};if(i!=null)for(var f in i)f!=="default"&&Object.hasOwnProperty.call(i,f)&&FU(u,i,f);return LU(u,i),u},_s=gs&&gs.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(gs,"__esModule",{value:!0});var NU=_s(lr()),O5=AD(),BU=_s(WD()),jU=_s(ay()),UU=_s(KD()),qU=_s(JD()),nm=_s(lS()),zU=_s(t5()),WU=_s(vy()),HU=_s(o5()),bU=RU(Xy()),GU=_s(O3()),VU=_s(A5()),Oa=process.env.CI==="false"?!1:UU.default,I5=()=>{},P5=class{constructor(u){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:f,outputHeight:c,staticOutput:g}=zU.default(this.rootNode,this.options.stdout.columns||80),t=g&&g!==` + `;if(this.options.debug){t&&(this.fullStaticOutput+=g),this.options.stdout.write(this.fullStaticOutput+f);return}if(Oa){t&&this.options.stdout.write(g),this.lastOutput=f;return}if(t&&(this.fullStaticOutput+=g),c>=this.options.stdout.rows){this.options.stdout.write(jU.default.clearTerminal+this.fullStaticOutput+f),this.lastOutput=f;return}t&&(this.log.clear(),this.options.stdout.write(g),this.log(f)),!t&&f!==this.lastOutput&&this.throttledLog(f),this.lastOutput=f},qU.default(this),this.options=u,this.rootNode=bU.createNode("ink-root"),this.rootNode.onRender=u.debug?this.onRender:O5.throttle(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=BU.default.create(u.stdout),this.throttledLog=u.debug?this.log:O5.throttle(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=nm.default.createContainer(this.rootNode,!1,!1),this.unsubscribeExit=WU.default(this.unmount,{alwaysLast:!1}),process.env.DEV==="true"&&nm.default.injectIntoDevTools({bundleType:0,version:"16.13.1",rendererPackageName:"ink"}),u.patchConsole&&this.patchConsole(),Oa||(u.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{u.stdout.off("resize",this.onRender)})}render(u){let f=NU.default.createElement(VU.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},u);nm.default.updateContainer(f,this.container,null,I5)}writeToStdout(u){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(u+this.fullStaticOutput+this.lastOutput);return}if(Oa){this.options.stdout.write(u);return}this.log.clear(),this.options.stdout.write(u),this.log(this.lastOutput)}}writeToStderr(u){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(u),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(Oa){this.options.stderr.write(u);return}this.log.clear(),this.options.stderr.write(u),this.log(this.lastOutput)}}unmount(u){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),Oa?this.options.stdout.write(this.lastOutput+` + `):this.options.debug||this.log.done(),this.isUnmounted=!0,nm.default.updateContainer(null,this.container,null,I5),GU.default.delete(this.options.stdout),u instanceof Error?this.rejectExitPromise(u):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((u,f)=>{this.resolveExitPromise=u,this.rejectExitPromise=f})),this.exitPromise}clear(){!Oa&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=HU.default((u,f)=>{u==="stdout"&&this.writeToStdout(f),u==="stderr"&&(f.startsWith("The above error occurred")||this.writeToStderr(f))}))}};gs.default=P5});var L5=Me(B2=>{"use strict";var F5=B2&&B2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(B2,"__esModule",{value:!0});var YU=F5(M5()),rm=F5(O3()),$U=require("stream"),JU=(i,u)=>{let f=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},KU(u)),c=XU(f.stdout,()=>new YU.default(f));return c.render(i),{rerender:c.render,unmount:()=>c.unmount(),waitUntilExit:c.waitUntilExit,cleanup:()=>rm.default.delete(f.stdout),clear:c.clear}};B2.default=JU;var KU=(i={})=>i instanceof $U.Stream?{stdout:i,stdin:process.stdin}:i,XU=(i,u)=>{let f;return rm.default.has(i)?f=rm.default.get(i):(f=u(),rm.default.set(i,f)),f}});var N5=Me(tf=>{"use strict";var QU=tf&&tf.__createBinding||(Object.create?function(i,u,f,c){c===void 0&&(c=f),Object.defineProperty(i,c,{enumerable:!0,get:function(){return u[f]}})}:function(i,u,f,c){c===void 0&&(c=f),i[c]=u[f]}),ZU=tf&&tf.__setModuleDefault||(Object.create?function(i,u){Object.defineProperty(i,"default",{enumerable:!0,value:u})}:function(i,u){i.default=u}),eq=tf&&tf.__importStar||function(i){if(i&&i.__esModule)return i;var u={};if(i!=null)for(var f in i)f!=="default"&&Object.hasOwnProperty.call(i,f)&&QU(u,i,f);return ZU(u,i),u};Object.defineProperty(tf,"__esModule",{value:!0});var j2=eq(lr()),R5=i=>{let{items:u,children:f,style:c}=i,[g,t]=j2.useState(0),C=j2.useMemo(()=>u.slice(g),[u,g]);j2.useLayoutEffect(()=>{t(u.length)},[u.length]);let A=C.map((D,L)=>f(D,g+L)),x=j2.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},c),[c]);return j2.default.createElement("ink-box",{internal_static:!0,style:x},A)};R5.displayName="Static";tf.default=R5});var j5=Me(U2=>{"use strict";var tq=U2&&U2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(U2,"__esModule",{value:!0});var nq=tq(lr()),B5=({children:i,transform:u})=>i==null?null:nq.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:u},i);B5.displayName="Transform";U2.default=B5});var q5=Me(q2=>{"use strict";var rq=q2&&q2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(q2,"__esModule",{value:!0});var iq=rq(lr()),U5=({count:i=1})=>iq.default.createElement("ink-text",null,` + `.repeat(i));U5.displayName="Newline";q2.default=U5});var H5=Me(z2=>{"use strict";var z5=z2&&z2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(z2,"__esModule",{value:!0});var oq=z5(lr()),uq=z5(tm()),W5=()=>oq.default.createElement(uq.default,{flexGrow:1});W5.displayName="Spacer";z2.default=W5});var im=Me(W2=>{"use strict";var sq=W2&&W2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(W2,"__esModule",{value:!0});var lq=lr(),fq=sq(F3()),cq=()=>lq.useContext(fq.default);W2.default=cq});var G5=Me(H2=>{"use strict";var aq=H2&&H2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(H2,"__esModule",{value:!0});var b5=lr(),dq=aq(im()),pq=(i,u={})=>{let{stdin:f,setRawMode:c,internal_exitOnCtrlC:g}=dq.default();b5.useEffect(()=>{if(u.isActive!==!1)return c(!0),()=>{c(!1)}},[u.isActive,c]),b5.useEffect(()=>{if(u.isActive===!1)return;let t=C=>{let A=String(C),x={upArrow:A==="",downArrow:A==="",leftArrow:A==="",rightArrow:A==="",pageDown:A==="[6~",pageUp:A==="[5~",return:A==="\r",escape:A==="",ctrl:!1,shift:!1,tab:A===" "||A==="",backspace:A==="\b",delete:A==="\x7F"||A==="[3~",meta:!1};A<=""&&!x.return&&(A=String.fromCharCode(A.charCodeAt(0)+"a".charCodeAt(0)-1),x.ctrl=!0),A.startsWith("")&&(A=A.slice(1),x.meta=!0);let D=A>="A"&&A<="Z",L=A>="\u0410"&&A<="\u042F";A.length===1&&(D||L)&&(x.shift=!0),x.tab&&A==="[Z"&&(x.shift=!0),(x.tab||x.backspace||x.delete)&&(A=""),(!(A==="c"&&x.ctrl)||!g)&&i(A,x)};return f==null||f.on("data",t),()=>{f==null||f.off("data",t)}},[u.isActive,f,g,i])};H2.default=pq});var V5=Me(b2=>{"use strict";var hq=b2&&b2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(b2,"__esModule",{value:!0});var mq=lr(),vq=hq(P3()),gq=()=>mq.useContext(vq.default);b2.default=gq});var Y5=Me(G2=>{"use strict";var _q=G2&&G2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(G2,"__esModule",{value:!0});var yq=lr(),wq=_q(R3()),Dq=()=>yq.useContext(wq.default);G2.default=Dq});var $5=Me(V2=>{"use strict";var Eq=V2&&V2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(V2,"__esModule",{value:!0});var Sq=lr(),Cq=Eq(B3()),Tq=()=>Sq.useContext(Cq.default);V2.default=Tq});var X5=Me(Y2=>{"use strict";var K5=Y2&&Y2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(Y2,"__esModule",{value:!0});var $2=lr(),xq=K5(Zh()),kq=K5(im()),Aq=({isActive:i=!0,autoFocus:u=!1}={})=>{let{isRawModeSupported:f,setRawMode:c}=kq.default(),{activeId:g,add:t,remove:C,activate:A,deactivate:x}=$2.useContext(xq.default),D=$2.useMemo(()=>Math.random().toString().slice(2,7),[]);return $2.useEffect(()=>(t(D,{autoFocus:u}),()=>{C(D)}),[D,u]),$2.useEffect(()=>{i?A(D):x(D)},[i,D]),$2.useEffect(()=>{if(!(!f||!i))return c(!0),()=>{c(!1)}},[i]),{isFocused:Boolean(D)&&g===D}};Y2.default=Aq});var J5=Me(K2=>{"use strict";var Oq=K2&&K2.__importDefault||function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(K2,"__esModule",{value:!0});var Iq=lr(),Pq=Oq(Zh()),Mq=()=>{let i=Iq.useContext(Pq.default);return{enableFocus:i.enableFocus,disableFocus:i.disableFocus,focusNext:i.focusNext,focusPrevious:i.focusPrevious}};K2.default=Mq});var Q5=Me(b3=>{"use strict";Object.defineProperty(b3,"__esModule",{value:!0});b3.default=i=>{var u,f,c,g;return{width:(f=(u=i.yogaNode)===null||u===void 0?void 0:u.getComputedWidth())!==null&&f!==void 0?f:0,height:(g=(c=i.yogaNode)===null||c===void 0?void 0:c.getComputedHeight())!==null&&g!==void 0?g:0}}});var ys=Me(ji=>{"use strict";Object.defineProperty(ji,"__esModule",{value:!0});var Fq=L5();Object.defineProperty(ji,"render",{enumerable:!0,get:function(){return Fq.default}});var Lq=tm();Object.defineProperty(ji,"Box",{enumerable:!0,get:function(){return Lq.default}});var Rq=W3();Object.defineProperty(ji,"Text",{enumerable:!0,get:function(){return Rq.default}});var Nq=N5();Object.defineProperty(ji,"Static",{enumerable:!0,get:function(){return Nq.default}});var Bq=j5();Object.defineProperty(ji,"Transform",{enumerable:!0,get:function(){return Bq.default}});var jq=q5();Object.defineProperty(ji,"Newline",{enumerable:!0,get:function(){return jq.default}});var Uq=H5();Object.defineProperty(ji,"Spacer",{enumerable:!0,get:function(){return Uq.default}});var qq=G5();Object.defineProperty(ji,"useInput",{enumerable:!0,get:function(){return qq.default}});var zq=V5();Object.defineProperty(ji,"useApp",{enumerable:!0,get:function(){return zq.default}});var Wq=im();Object.defineProperty(ji,"useStdin",{enumerable:!0,get:function(){return Wq.default}});var Hq=Y5();Object.defineProperty(ji,"useStdout",{enumerable:!0,get:function(){return Hq.default}});var bq=$5();Object.defineProperty(ji,"useStderr",{enumerable:!0,get:function(){return bq.default}});var Gq=X5();Object.defineProperty(ji,"useFocus",{enumerable:!0,get:function(){return Gq.default}});var Vq=J5();Object.defineProperty(ji,"useFocusManager",{enumerable:!0,get:function(){return Vq.default}});var Yq=Q5();Object.defineProperty(ji,"measureElement",{enumerable:!0,get:function(){return Yq.default}})});var lC=Me(X2=>{"use strict";Object.defineProperty(X2,"__esModule",{value:!0});X2.UncontrolledTextInput=void 0;var oC=lr(),Y3=lr(),uC=ys(),Sc=Jh(),sC=({value:i,placeholder:u="",focus:f=!0,mask:c,highlightPastedText:g=!1,showCursor:t=!0,onChange:C,onSubmit:A})=>{let[{cursorOffset:x,cursorWidth:D},L]=Y3.useState({cursorOffset:(i||"").length,cursorWidth:0});Y3.useEffect(()=>{L(re=>{if(!f||!t)return re;let ce=i||"";return re.cursorOffset>ce.length-1?{cursorOffset:ce.length,cursorWidth:0}:re})},[i,f,t]);let N=g?D:0,j=c?c.repeat(i.length):i,$=j,h=u?Sc.grey(u):void 0;if(t&&f){h=u.length>0?Sc.inverse(u[0])+Sc.grey(u.slice(1)):Sc.inverse(" "),$=j.length>0?"":Sc.inverse(" ");let re=0;for(let ce of j)re>=x-N&&re<=x?$+=Sc.inverse(ce):$+=ce,re++;j.length>0&&x===j.length&&($+=Sc.inverse(" "))}return uC.useInput((re,ce)=>{if(ce.upArrow||ce.downArrow||ce.ctrl&&re==="c"||ce.tab||ce.shift&&ce.tab)return;if(ce.return){A&&A(i);return}let Q=x,oe=i,Se=0;ce.leftArrow?t&&Q--:ce.rightArrow?t&&Q++:ce.backspace||ce.delete?x>0&&(oe=i.slice(0,x-1)+i.slice(x,i.length),Q--):(oe=i.slice(0,x)+re+i.slice(x,i.length),Q+=re.length,re.length>1&&(Se=re.length)),x<0&&(Q=0),x>i.length&&(Q=i.length),L({cursorOffset:Q,cursorWidth:Se}),oe!==i&&C(oe)},{isActive:f}),oC.createElement(uC.Text,null,u?j.length>0?$:h:$)};X2.default=sC;X2.UncontrolledTextInput=i=>{let[u,f]=Y3.useState("");return oC.createElement(sC,Object.assign({},i,{value:u,onChange:f}))}});var cC=Me(pm=>{"use strict";Object.defineProperty(pm,"__esModule",{value:!0});function J2(i){let u=[...i.caches],f=u.shift();return f===void 0?fC():{get(c,g,t={miss:()=>Promise.resolve()}){return f.get(c,g,t).catch(()=>J2({caches:u}).get(c,g,t))},set(c,g){return f.set(c,g).catch(()=>J2({caches:u}).set(c,g))},delete(c){return f.delete(c).catch(()=>J2({caches:u}).delete(c))},clear(){return f.clear().catch(()=>J2({caches:u}).clear())}}}function fC(){return{get(i,u,f={miss:()=>Promise.resolve()}){return u().then(g=>Promise.all([g,f.miss(g)])).then(([g])=>g)},set(i,u){return Promise.resolve(u)},delete(i){return Promise.resolve()},clear(){return Promise.resolve()}}}pm.createFallbackableCache=J2;pm.createNullCache=fC});var dC=Me((fV,aC)=>{aC.exports=cC()});var pC=Me($3=>{"use strict";Object.defineProperty($3,"__esModule",{value:!0});function $q(i={serializable:!0}){let u={};return{get(f,c,g={miss:()=>Promise.resolve()}){let t=JSON.stringify(f);if(t in u)return Promise.resolve(i.serializable?JSON.parse(u[t]):u[t]);let C=c(),A=g&&g.miss||(()=>Promise.resolve());return C.then(x=>A(x)).then(()=>C)},set(f,c){return u[JSON.stringify(f)]=i.serializable?JSON.stringify(c):c,Promise.resolve(c)},delete(f){return delete u[JSON.stringify(f)],Promise.resolve()},clear(){return u={},Promise.resolve()}}}$3.createInMemoryCache=$q});var mC=Me((aV,hC)=>{hC.exports=pC()});var gC=Me(ws=>{"use strict";Object.defineProperty(ws,"__esModule",{value:!0});function Kq(i,u,f){let c={"x-algolia-api-key":f,"x-algolia-application-id":u};return{headers(){return i===K3.WithinHeaders?c:{}},queryParameters(){return i===K3.WithinQueryParameters?c:{}}}}function Xq(i){let u=0,f=()=>(u++,new Promise(c=>{setTimeout(()=>{c(i(f))},Math.min(100*u,1e3))}));return i(f)}function vC(i,u=(f,c)=>Promise.resolve()){return Object.assign(i,{wait(f){return vC(i.then(c=>Promise.all([u(c,f),c])).then(c=>c[1]))}})}function Jq(i){let u=i.length-1;for(u;u>0;u--){let f=Math.floor(Math.random()*(u+1)),c=i[u];i[u]=i[f],i[f]=c}return i}function Qq(i,u){return Object.keys(u!==void 0?u:{}).forEach(f=>{i[f]=u[f](i)}),i}function Zq(i,...u){let f=0;return i.replace(/%s/g,()=>encodeURIComponent(u[f++]))}var ez="4.2.0",tz=i=>()=>i.transporter.requester.destroy(),K3={WithinQueryParameters:0,WithinHeaders:1};ws.AuthMode=K3;ws.addMethods=Qq;ws.createAuth=Kq;ws.createRetryablePromise=Xq;ws.createWaitablePromise=vC;ws.destroy=tz;ws.encode=Zq;ws.shuffle=Jq;ws.version=ez});var Q2=Me((pV,_C)=>{_C.exports=gC()});var yC=Me(X3=>{"use strict";Object.defineProperty(X3,"__esModule",{value:!0});var nz={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};X3.MethodEnum=nz});var Z2=Me((mV,wC)=>{wC.exports=yC()});var RC=Me(y0=>{"use strict";Object.defineProperty(y0,"__esModule",{value:!0});var DC=Z2();function J3(i,u){let f=i||{},c=f.data||{};return Object.keys(f).forEach(g=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(g)===-1&&(c[g]=f[g])}),{data:Object.entries(c).length>0?c:void 0,timeout:f.timeout||u,headers:f.headers||{},queryParameters:f.queryParameters||{},cacheable:f.cacheable}}var hm={Read:1,Write:2,Any:3},Ia={Up:1,Down:2,Timeouted:3},EC=2*60*1e3;function Q3(i,u=Ia.Up){return zn(dt({},i),{status:u,lastUpdate:Date.now()})}function SC(i){return i.status===Ia.Up||Date.now()-i.lastUpdate>EC}function CC(i){return i.status===Ia.Timeouted&&Date.now()-i.lastUpdate<=EC}function Z3(i){return{protocol:i.protocol||"https",url:i.url,accept:i.accept||hm.Any}}function rz(i,u){return Promise.all(u.map(f=>i.get(f,()=>Promise.resolve(Q3(f))))).then(f=>{let c=f.filter(A=>SC(A)),g=f.filter(A=>CC(A)),t=[...c,...g],C=t.length>0?t.map(A=>Z3(A)):u;return{getTimeout(A,x){return(g.length===0&&A===0?1:g.length+3+A)*x},statelessHosts:C}})}var iz=({isTimedOut:i,status:u})=>!i&&~~u==0,oz=i=>{let u=i.status;return i.isTimedOut||iz(i)||~~(u/100)!=2&&~~(u/100)!=4},uz=({status:i})=>~~(i/100)==2,sz=(i,u)=>oz(i)?u.onRetry(i):uz(i)?u.onSucess(i):u.onFail(i);function PC(i,u,f,c){let g=[],t=AC(f,c),C=OC(i,c),A=f.method,x=f.method!==DC.MethodEnum.Get?{}:dt(dt({},f.data),c.data),D=dt(dt(dt({"x-algolia-agent":i.userAgent.value},i.queryParameters),x),c.queryParameters),L=0,N=(j,$)=>{let h=j.pop();if(h===void 0)throw IC(ew(g));let re={data:t,headers:C,method:A,url:kC(h,f.path,D),connectTimeout:$(L,i.timeouts.connect),responseTimeout:$(L,c.timeout)},ce=oe=>{let Se={request:re,response:oe,host:h,triesLeft:j.length};return g.push(Se),Se},Q={onSucess:oe=>TC(oe),onRetry(oe){let Se=ce(oe);return oe.isTimedOut&&L++,Promise.all([i.logger.info("Retryable failure",tw(Se)),i.hostsCache.set(h,Q3(h,oe.isTimedOut?Ia.Timeouted:Ia.Down))]).then(()=>N(j,$))},onFail(oe){throw ce(oe),xC(oe,ew(g))}};return i.requester.send(re).then(oe=>sz(oe,Q))};return rz(i.hostsCache,u).then(j=>N([...j.statelessHosts].reverse(),j.getTimeout))}function lz(i){let{hostsCache:u,logger:f,requester:c,requestsCache:g,responsesCache:t,timeouts:C,userAgent:A,hosts:x,queryParameters:D,headers:L}=i,N={hostsCache:u,logger:f,requester:c,requestsCache:g,responsesCache:t,timeouts:C,userAgent:A,headers:L,queryParameters:D,hosts:x.map(j=>Z3(j)),read(j,$){let h=J3($,N.timeouts.read),re=()=>PC(N,N.hosts.filter(oe=>(oe.accept&hm.Read)!=0),j,h);if((h.cacheable!==void 0?h.cacheable:j.cacheable)!==!0)return re();let Q={request:j,mappedRequestOptions:h,transporter:{queryParameters:N.queryParameters,headers:N.headers}};return N.responsesCache.get(Q,()=>N.requestsCache.get(Q,()=>N.requestsCache.set(Q,re()).then(oe=>Promise.all([N.requestsCache.delete(Q),oe]),oe=>Promise.all([N.requestsCache.delete(Q),Promise.reject(oe)])).then(([oe,Se])=>Se)),{miss:oe=>N.responsesCache.set(Q,oe)})},write(j,$){return PC(N,N.hosts.filter(h=>(h.accept&hm.Write)!=0),j,J3($,N.timeouts.write))}};return N}function fz(i){let u={value:`Algolia for JavaScript (${i})`,add(f){let c=`; ${f.segment}${f.version!==void 0?` (${f.version})`:""}`;return u.value.indexOf(c)===-1&&(u.value=`${u.value}${c}`),u}};return u}function TC(i){try{return JSON.parse(i.content)}catch(u){throw MC(u.message,i)}}function xC({content:i,status:u},f){let c=i;try{c=JSON.parse(i).message}catch(g){}return FC(c,u,f)}function cz(i,...u){let f=0;return i.replace(/%s/g,()=>encodeURIComponent(u[f++]))}function kC(i,u,f){let c=LC(f),g=`${i.protocol}://${i.url}/${u.charAt(0)==="/"?u.substr(1):u}`;return c.length&&(g+=`?${c}`),g}function LC(i){let u=f=>Object.prototype.toString.call(f)==="[object Object]"||Object.prototype.toString.call(f)==="[object Array]";return Object.keys(i).map(f=>cz("%s=%s",f,u(i[f])?JSON.stringify(i[f]):i[f])).join("&")}function AC(i,u){if(i.method===DC.MethodEnum.Get||i.data===void 0&&u.data===void 0)return;let f=Array.isArray(i.data)?i.data:dt(dt({},i.data),u.data);return JSON.stringify(f)}function OC(i,u){let f=dt(dt({},i.headers),u.headers),c={};return Object.keys(f).forEach(g=>{let t=f[g];c[g.toLowerCase()]=t}),c}function ew(i){return i.map(u=>tw(u))}function tw(i){let u=i.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return zn(dt({},i),{request:zn(dt({},i.request),{headers:dt(dt({},i.request.headers),u)})})}function FC(i,u,f){return{name:"ApiError",message:i,status:u,transporterStackTrace:f}}function MC(i,u){return{name:"DeserializationError",message:i,response:u}}function IC(i){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:i}}y0.CallEnum=hm;y0.HostStatusEnum=Ia;y0.createApiError=FC;y0.createDeserializationError=MC;y0.createMappedRequestOptions=J3;y0.createRetryError=IC;y0.createStatefulHost=Q3;y0.createStatelessHost=Z3;y0.createTransporter=lz;y0.createUserAgent=fz;y0.deserializeFailure=xC;y0.deserializeSuccess=TC;y0.isStatefulHostTimeouted=CC;y0.isStatefulHostUp=SC;y0.serializeData=AC;y0.serializeHeaders=OC;y0.serializeQueryParameters=LC;y0.serializeUrl=kC;y0.stackFrameWithoutCredentials=tw;y0.stackTraceWithoutCredentials=ew});var ed=Me((gV,NC)=>{NC.exports=RC()});var BC=Me(Hf=>{"use strict";Object.defineProperty(Hf,"__esModule",{value:!0});var Pa=Q2(),az=ed(),td=Z2(),dz=i=>{let u=i.region||"us",f=Pa.createAuth(Pa.AuthMode.WithinHeaders,i.appId,i.apiKey),c=az.createTransporter(zn(dt({hosts:[{url:`analytics.${u}.algolia.com`}]},i),{headers:dt(zn(dt({},f.headers()),{"content-type":"application/json"}),i.headers),queryParameters:dt(dt({},f.queryParameters()),i.queryParameters)})),g=i.appId;return Pa.addMethods({appId:g,transporter:c},i.methods)},pz=i=>(u,f)=>i.transporter.write({method:td.MethodEnum.Post,path:"2/abtests",data:u},f),hz=i=>(u,f)=>i.transporter.write({method:td.MethodEnum.Delete,path:Pa.encode("2/abtests/%s",u)},f),mz=i=>(u,f)=>i.transporter.read({method:td.MethodEnum.Get,path:Pa.encode("2/abtests/%s",u)},f),vz=i=>u=>i.transporter.read({method:td.MethodEnum.Get,path:"2/abtests"},u),gz=i=>(u,f)=>i.transporter.write({method:td.MethodEnum.Post,path:Pa.encode("2/abtests/%s/stop",u)},f);Hf.addABTest=pz;Hf.createAnalyticsClient=dz;Hf.deleteABTest=hz;Hf.getABTest=mz;Hf.getABTests=vz;Hf.stopABTest=gz});var UC=Me((yV,jC)=>{jC.exports=BC()});var zC=Me(nd=>{"use strict";Object.defineProperty(nd,"__esModule",{value:!0});var nw=Q2(),_z=ed(),qC=Z2(),yz=i=>{let u=i.region||"us",f=nw.createAuth(nw.AuthMode.WithinHeaders,i.appId,i.apiKey),c=_z.createTransporter(zn(dt({hosts:[{url:`recommendation.${u}.algolia.com`}]},i),{headers:dt(zn(dt({},f.headers()),{"content-type":"application/json"}),i.headers),queryParameters:dt(dt({},f.queryParameters()),i.queryParameters)}));return nw.addMethods({appId:i.appId,transporter:c},i.methods)},wz=i=>u=>i.transporter.read({method:qC.MethodEnum.Get,path:"1/strategies/personalization"},u),Dz=i=>(u,f)=>i.transporter.write({method:qC.MethodEnum.Post,path:"1/strategies/personalization",data:u},f);nd.createRecommendationClient=yz;nd.getPersonalizationStrategy=wz;nd.setPersonalizationStrategy=Dz});var HC=Me((DV,WC)=>{WC.exports=zC()});var nT=Me(yt=>{"use strict";Object.defineProperty(yt,"__esModule",{value:!0});var Wt=Q2(),jo=ed(),Rn=Z2(),Ez=require("crypto");function mm(i){let u=f=>i.request(f).then(c=>{if(i.batch!==void 0&&i.batch(c.hits),!i.shouldStop(c))return c.cursor?u({cursor:c.cursor}):u({page:(f.page||0)+1})});return u({})}var Sz=i=>{let u=i.appId,f=Wt.createAuth(i.authMode!==void 0?i.authMode:Wt.AuthMode.WithinHeaders,u,i.apiKey),c=jo.createTransporter(zn(dt({hosts:[{url:`${u}-dsn.algolia.net`,accept:jo.CallEnum.Read},{url:`${u}.algolia.net`,accept:jo.CallEnum.Write}].concat(Wt.shuffle([{url:`${u}-1.algolianet.com`},{url:`${u}-2.algolianet.com`},{url:`${u}-3.algolianet.com`}]))},i),{headers:dt(zn(dt({},f.headers()),{"content-type":"application/x-www-form-urlencoded"}),i.headers),queryParameters:dt(dt({},f.queryParameters()),i.queryParameters)})),g={transporter:c,appId:u,addAlgoliaAgent(t,C){c.userAgent.add({segment:t,version:C})},clearCache(){return Promise.all([c.requestsCache.clear(),c.responsesCache.clear()]).then(()=>{})}};return Wt.addMethods(g,i.methods)};function bC(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function GC(){return{name:"ObjectNotFoundError",message:"Object not found."}}function VC(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Cz=i=>(u,f)=>{let A=f||{},{queryParameters:c}=A,g=Si(A,["queryParameters"]),t=dt({acl:u},c!==void 0?{queryParameters:c}:{}),C=(x,D)=>Wt.createRetryablePromise(L=>rd(i)(x.key,D).catch(N=>{if(N.status!==404)throw N;return L()}));return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:"1/keys",data:t},g),C)},Tz=i=>(u,f,c)=>{let g=jo.createMappedRequestOptions(c);return g.queryParameters["X-Algolia-User-ID"]=u,i.transporter.write({method:Rn.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:f}},g)},xz=i=>(u,f,c)=>i.transporter.write({method:Rn.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:u,cluster:f}},c),vm=i=>(u,f,c)=>{let g=(t,C)=>id(i)(u,{methods:{waitTask:z0}}).waitTask(t.taskID,C);return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/operation",u),data:{operation:"copy",destination:f}},c),g)},kz=i=>(u,f,c)=>vm(i)(u,f,zn(dt({},c),{scope:[gm.Rules]})),Az=i=>(u,f,c)=>vm(i)(u,f,zn(dt({},c),{scope:[gm.Settings]})),Oz=i=>(u,f,c)=>vm(i)(u,f,zn(dt({},c),{scope:[gm.Synonyms]})),Iz=i=>(u,f)=>{let c=(g,t)=>Wt.createRetryablePromise(C=>rd(i)(u,t).then(C).catch(A=>{if(A.status!==404)throw A}));return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Delete,path:Wt.encode("1/keys/%s",u)},f),c)},Pz=()=>(i,u)=>{let f=jo.serializeQueryParameters(u),c=Ez.createHmac("sha256",i).update(f).digest("hex");return Buffer.from(c+f).toString("base64")},rd=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/keys/%s",u)},f),Mz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/logs"},u),Fz=()=>i=>{let u=Buffer.from(i,"base64").toString("ascii"),f=/validUntil=(\d+)/,c=u.match(f);if(c===null)throw VC();return parseInt(c[1],10)-Math.round(new Date().getTime()/1e3)},Lz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/clusters/mapping/top"},u),Rz=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/clusters/mapping/%s",u)},f),Nz=i=>u=>{let g=u||{},{retrieveMappings:f}=g,c=Si(g,["retrieveMappings"]);return f===!0&&(c.getClusters=!0),i.transporter.read({method:Rn.MethodEnum.Get,path:"1/clusters/mapping/pending"},c)},id=i=>(u,f={})=>{let c={transporter:i.transporter,appId:i.appId,indexName:u};return Wt.addMethods(c,f.methods)},Bz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/keys"},u),jz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/clusters"},u),Uz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/indexes"},u),qz=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:"1/clusters/mapping"},u),zz=i=>(u,f,c)=>{let g=(t,C)=>id(i)(u,{methods:{waitTask:z0}}).waitTask(t.taskID,C);return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/operation",u),data:{operation:"move",destination:f}},c),g)},Wz=i=>(u,f)=>{let c=(g,t)=>Promise.all(Object.keys(g.taskID).map(C=>id(i)(C,{methods:{waitTask:z0}}).waitTask(g.taskID[C],t)));return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:u}},f),c)},Hz=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:u}},f),bz=i=>(u,f)=>{let c=u.map(g=>zn(dt({},g),{params:jo.serializeQueryParameters(g.params||{})}));return i.transporter.read({method:Rn.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:c},cacheable:!0},f)},Gz=i=>(u,f)=>Promise.all(u.map(c=>{let A=c.params,{facetName:g,facetQuery:t}=A,C=Si(A,["facetName","facetQuery"]);return id(i)(c.indexName,{methods:{searchForFacetValues:YC}}).searchForFacetValues(g,t,dt(dt({},f),C))})),Vz=i=>(u,f)=>{let c=jo.createMappedRequestOptions(f);return c.queryParameters["X-Algolia-User-ID"]=u,i.transporter.write({method:Rn.MethodEnum.Delete,path:"1/clusters/mapping"},c)},Yz=i=>(u,f)=>{let c=(g,t)=>Wt.createRetryablePromise(C=>rd(i)(u,t).catch(A=>{if(A.status!==404)throw A;return C()}));return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/keys/%s/restore",u)},f),c)},$z=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:u}},f),Kz=i=>(u,f)=>{let c=Object.assign({},f),L=f||{},{queryParameters:g}=L,t=Si(L,["queryParameters"]),C=g?{queryParameters:g}:{},A=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],x=N=>Object.keys(c).filter(j=>A.indexOf(j)!==-1).every(j=>N[j]===c[j]),D=(N,j)=>Wt.createRetryablePromise($=>rd(i)(u,j).then(h=>x(h)?Promise.resolve():$()));return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Put,path:Wt.encode("1/keys/%s",u),data:C},t),D)},$C=i=>(u,f)=>{let c=(g,t)=>z0(i)(g.taskID,t);return Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/batch",i.indexName),data:{requests:u}},f),c)},Xz=i=>u=>mm(zn(dt({},u),{shouldStop:f=>f.cursor===void 0,request:f=>i.transporter.read({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/browse",i.indexName),data:f},u)})),Jz=i=>u=>{let f=dt({hitsPerPage:1e3},u);return mm(zn(dt({},f),{shouldStop:c=>c.hits.lengthzn(dt({},g),{hits:g.hits.map(t=>(delete t._highlightResult,t))}))}}))},Qz=i=>u=>{let f=dt({hitsPerPage:1e3},u);return mm(zn(dt({},f),{shouldStop:c=>c.hits.lengthzn(dt({},g),{hits:g.hits.map(t=>(delete t._highlightResult,t))}))}}))},_m=i=>(u,f,c)=>{let x=c||{},{batchSize:g}=x,t=Si(x,["batchSize"]),C={taskIDs:[],objectIDs:[]},A=(D=0)=>{let L=[],N;for(N=D;N({action:f,body:j})),t).then(j=>(C.objectIDs=C.objectIDs.concat(j.objectIDs),C.taskIDs.push(j.taskID),N++,A(N)))};return Wt.createWaitablePromise(A(),(D,L)=>Promise.all(D.taskIDs.map(N=>z0(i)(N,L))))},Zz=i=>u=>Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/clear",i.indexName)},u),(f,c)=>z0(i)(f.taskID,c)),eW=i=>u=>{let t=u||{},{forwardToReplicas:f}=t,c=Si(t,["forwardToReplicas"]),g=jo.createMappedRequestOptions(c);return f&&(g.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/rules/clear",i.indexName)},g),(C,A)=>z0(i)(C.taskID,A))},tW=i=>u=>{let t=u||{},{forwardToReplicas:f}=t,c=Si(t,["forwardToReplicas"]),g=jo.createMappedRequestOptions(c);return f&&(g.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/synonyms/clear",i.indexName)},g),(C,A)=>z0(i)(C.taskID,A))},nW=i=>(u,f)=>Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/deleteByQuery",i.indexName),data:u},f),(c,g)=>z0(i)(c.taskID,g)),rW=i=>u=>Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Delete,path:Wt.encode("1/indexes/%s",i.indexName)},u),(f,c)=>z0(i)(f.taskID,c)),iW=i=>(u,f)=>Wt.createWaitablePromise(JC(i)([u],f).then(c=>({taskID:c.taskIDs[0]})),(c,g)=>z0(i)(c.taskID,g)),JC=i=>(u,f)=>{let c=u.map(g=>({objectID:g}));return _m(i)(c,Cc.DeleteObject,f)},oW=i=>(u,f)=>{let C=f||{},{forwardToReplicas:c}=C,g=Si(C,["forwardToReplicas"]),t=jo.createMappedRequestOptions(g);return c&&(t.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Delete,path:Wt.encode("1/indexes/%s/rules/%s",i.indexName,u)},t),(A,x)=>z0(i)(A.taskID,x))},uW=i=>(u,f)=>{let C=f||{},{forwardToReplicas:c}=C,g=Si(C,["forwardToReplicas"]),t=jo.createMappedRequestOptions(g);return c&&(t.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Delete,path:Wt.encode("1/indexes/%s/synonyms/%s",i.indexName,u)},t),(A,x)=>z0(i)(A.taskID,x))},sW=i=>u=>QC(i)(u).then(()=>!0).catch(f=>{if(f.status!==404)throw f;return!1}),lW=i=>(u,f)=>{let x=f||{},{query:c,paginate:g}=x,t=Si(x,["query","paginate"]),C=0,A=()=>ZC(i)(c||"",zn(dt({},t),{page:C})).then(D=>{for(let[L,N]of Object.entries(D.hits))if(u(N))return{object:N,position:parseInt(L,10),page:C};if(C++,g===!1||C>=D.nbPages)throw GC();return A()});return A()},fW=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/indexes/%s/%s",i.indexName,u)},f),cW=()=>(i,u)=>{for(let[f,c]of Object.entries(i.hits))if(c.objectID===u)return parseInt(f,10);return-1},aW=i=>(u,f)=>{let C=f||{},{attributesToRetrieve:c}=C,g=Si(C,["attributesToRetrieve"]),t=u.map(A=>dt({indexName:i.indexName,objectID:A},c?{attributesToRetrieve:c}:{}));return i.transporter.read({method:Rn.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},g)},dW=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/indexes/%s/rules/%s",i.indexName,u)},f),QC=i=>u=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/indexes/%s/settings",i.indexName),data:{getVersion:2}},u),pW=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/indexes/%s/synonyms/%s",i.indexName,u)},f),eT=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Get,path:Wt.encode("1/indexes/%s/task/%s",i.indexName,u.toString())},f),hW=i=>(u,f)=>Wt.createWaitablePromise(tT(i)([u],f).then(c=>({objectID:c.objectIDs[0],taskID:c.taskIDs[0]})),(c,g)=>z0(i)(c.taskID,g)),tT=i=>(u,f)=>{let C=f||{},{createIfNotExists:c}=C,g=Si(C,["createIfNotExists"]),t=c?Cc.PartialUpdateObject:Cc.PartialUpdateObjectNoCreate;return _m(i)(u,t,g)},mW=i=>(u,f)=>{let h=f||{},{safe:c,autoGenerateObjectIDIfNotExist:g,batchSize:t}=h,C=Si(h,["safe","autoGenerateObjectIDIfNotExist","batchSize"]),A=(re,ce,Q,oe)=>Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/operation",re),data:{operation:Q,destination:ce}},oe),(Se,me)=>z0(i)(Se.taskID,me)),x=Math.random().toString(36).substring(7),D=`${i.indexName}_tmp_${x}`,L=rw({appId:i.appId,transporter:i.transporter,indexName:D}),N=[],j=A(i.indexName,D,"copy",zn(dt({},C),{scope:["settings","synonyms","rules"]}));N.push(j);let $=(c?j.wait(C):j).then(()=>{let re=L(u,zn(dt({},C),{autoGenerateObjectIDIfNotExist:g,batchSize:t}));return N.push(re),c?re.wait(C):re}).then(()=>{let re=A(D,i.indexName,"move",C);return N.push(re),c?re.wait(C):re}).then(()=>Promise.all(N)).then(([re,ce,Q])=>({objectIDs:ce.objectIDs,taskIDs:[re.taskID,...ce.taskIDs,Q.taskID]}));return Wt.createWaitablePromise($,(re,ce)=>Promise.all(N.map(Q=>Q.wait(ce))))},vW=i=>(u,f)=>iw(i)(u,zn(dt({},f),{clearExistingRules:!0})),gW=i=>(u,f)=>ow(i)(u,zn(dt({},f),{replaceExistingSynonyms:!0})),_W=i=>(u,f)=>Wt.createWaitablePromise(rw(i)([u],f).then(c=>({objectID:c.objectIDs[0],taskID:c.taskIDs[0]})),(c,g)=>z0(i)(c.taskID,g)),rw=i=>(u,f)=>{let C=f||{},{autoGenerateObjectIDIfNotExist:c}=C,g=Si(C,["autoGenerateObjectIDIfNotExist"]),t=c?Cc.AddObject:Cc.UpdateObject;if(t===Cc.UpdateObject){for(let A of u)if(A.objectID===void 0)return Wt.createWaitablePromise(Promise.reject(bC()))}return _m(i)(u,t,g)},yW=i=>(u,f)=>iw(i)([u],f),iw=i=>(u,f)=>{let A=f||{},{forwardToReplicas:c,clearExistingRules:g}=A,t=Si(A,["forwardToReplicas","clearExistingRules"]),C=jo.createMappedRequestOptions(t);return c&&(C.queryParameters.forwardToReplicas=1),g&&(C.queryParameters.clearExistingRules=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/rules/batch",i.indexName),data:u},C),(x,D)=>z0(i)(x.taskID,D))},wW=i=>(u,f)=>ow(i)([u],f),ow=i=>(u,f)=>{let A=f||{},{forwardToReplicas:c,replaceExistingSynonyms:g}=A,t=Si(A,["forwardToReplicas","replaceExistingSynonyms"]),C=jo.createMappedRequestOptions(t);return c&&(C.queryParameters.forwardToReplicas=1),g&&(C.queryParameters.replaceExistingSynonyms=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/synonyms/batch",i.indexName),data:u},C),(x,D)=>z0(i)(x.taskID,D))},ZC=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/query",i.indexName),data:{query:u},cacheable:!0},f),YC=i=>(u,f,c)=>i.transporter.read({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/facets/%s/query",i.indexName,u),data:{facetQuery:f},cacheable:!0},c),KC=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/rules/search",i.indexName),data:{query:u}},f),XC=i=>(u,f)=>i.transporter.read({method:Rn.MethodEnum.Post,path:Wt.encode("1/indexes/%s/synonyms/search",i.indexName),data:{query:u}},f),DW=i=>(u,f)=>{let C=f||{},{forwardToReplicas:c}=C,g=Si(C,["forwardToReplicas"]),t=jo.createMappedRequestOptions(g);return c&&(t.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(i.transporter.write({method:Rn.MethodEnum.Put,path:Wt.encode("1/indexes/%s/settings",i.indexName),data:u},t),(A,x)=>z0(i)(A.taskID,x))},z0=i=>(u,f)=>Wt.createRetryablePromise(c=>eT(i)(u,f).then(g=>g.status!=="published"?c():void 0)),EW={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",ListIndexes:"listIndexes",Logs:"logs",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},Cc={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},gm={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},SW={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},CW={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};yt.ApiKeyACLEnum=EW;yt.BatchActionEnum=Cc;yt.ScopeEnum=gm;yt.StrategyEnum=SW;yt.SynonymEnum=CW;yt.addApiKey=Cz;yt.assignUserID=Tz;yt.assignUserIDs=xz;yt.batch=$C;yt.browseObjects=Xz;yt.browseRules=Jz;yt.browseSynonyms=Qz;yt.chunkedBatch=_m;yt.clearObjects=Zz;yt.clearRules=eW;yt.clearSynonyms=tW;yt.copyIndex=vm;yt.copyRules=kz;yt.copySettings=Az;yt.copySynonyms=Oz;yt.createBrowsablePromise=mm;yt.createMissingObjectIDError=bC;yt.createObjectNotFoundError=GC;yt.createSearchClient=Sz;yt.createValidUntilNotFoundError=VC;yt.deleteApiKey=Iz;yt.deleteBy=nW;yt.deleteIndex=rW;yt.deleteObject=iW;yt.deleteObjects=JC;yt.deleteRule=oW;yt.deleteSynonym=uW;yt.exists=sW;yt.findObject=lW;yt.generateSecuredApiKey=Pz;yt.getApiKey=rd;yt.getLogs=Mz;yt.getObject=fW;yt.getObjectPosition=cW;yt.getObjects=aW;yt.getRule=dW;yt.getSecuredApiKeyRemainingValidity=Fz;yt.getSettings=QC;yt.getSynonym=pW;yt.getTask=eT;yt.getTopUserIDs=Lz;yt.getUserID=Rz;yt.hasPendingMappings=Nz;yt.initIndex=id;yt.listApiKeys=Bz;yt.listClusters=jz;yt.listIndices=Uz;yt.listUserIDs=qz;yt.moveIndex=zz;yt.multipleBatch=Wz;yt.multipleGetObjects=Hz;yt.multipleQueries=bz;yt.multipleSearchForFacetValues=Gz;yt.partialUpdateObject=hW;yt.partialUpdateObjects=tT;yt.removeUserID=Vz;yt.replaceAllObjects=mW;yt.replaceAllRules=vW;yt.replaceAllSynonyms=gW;yt.restoreApiKey=Yz;yt.saveObject=_W;yt.saveObjects=rw;yt.saveRule=yW;yt.saveRules=iw;yt.saveSynonym=wW;yt.saveSynonyms=ow;yt.search=ZC;yt.searchForFacetValues=YC;yt.searchRules=KC;yt.searchSynonyms=XC;yt.searchUserIDs=$z;yt.setSettings=DW;yt.updateApiKey=Kz;yt.waitTask=z0});var iT=Me((SV,rT)=>{rT.exports=nT()});var oT=Me(ym=>{"use strict";Object.defineProperty(ym,"__esModule",{value:!0});function TW(){return{debug(i,u){return Promise.resolve()},info(i,u){return Promise.resolve()},error(i,u){return Promise.resolve()}}}var xW={Debug:1,Info:2,Error:3};ym.LogLevelEnum=xW;ym.createNullLogger=TW});var sT=Me((TV,uT)=>{uT.exports=oT()});var cT=Me(uw=>{"use strict";Object.defineProperty(uw,"__esModule",{value:!0});var lT=require("http"),fT=require("https"),kW=require("url");function AW(){let i={keepAlive:!0},u=new lT.Agent(i),f=new fT.Agent(i);return{send(c){return new Promise(g=>{let t=kW.parse(c.url),C=t.query===null?t.pathname:`${t.pathname}?${t.query}`,A=dt({agent:t.protocol==="https:"?f:u,hostname:t.hostname,path:C,method:c.method,headers:c.headers},t.port!==void 0?{port:t.port||""}:{}),x=(t.protocol==="https:"?fT:lT).request(A,j=>{let $="";j.on("data",h=>$+=h),j.on("end",()=>{clearTimeout(L),clearTimeout(N),g({status:j.statusCode||0,content:$,isTimedOut:!1})})}),D=(j,$)=>setTimeout(()=>{x.abort(),g({status:0,content:$,isTimedOut:!0})},j*1e3),L=D(c.connectTimeout,"Connection timeout"),N;x.on("error",j=>{clearTimeout(L),clearTimeout(N),g({status:0,content:j.message,isTimedOut:!1})}),x.once("response",()=>{clearTimeout(L),N=D(c.responseTimeout,"Socket timeout")}),c.data!==void 0&&x.write(c.data),x.end()})},destroy(){return u.destroy(),f.destroy(),Promise.resolve()}}}uw.createNodeHttpRequester=AW});var dT=Me((kV,aT)=>{aT.exports=cT()});var vT=Me((AV,pT)=>{"use strict";var hT=dC(),OW=mC(),Ma=UC(),sw=Q2(),lw=HC(),Mt=iT(),IW=sT(),PW=dT(),MW=ed();function mT(i,u,f){let c={appId:i,apiKey:u,timeouts:{connect:2,read:5,write:30},requester:PW.createNodeHttpRequester(),logger:IW.createNullLogger(),responsesCache:hT.createNullCache(),requestsCache:hT.createNullCache(),hostsCache:OW.createInMemoryCache(),userAgent:MW.createUserAgent(sw.version).add({segment:"Node.js",version:process.versions.node})};return Mt.createSearchClient(zn(dt(dt({},c),f),{methods:{search:Mt.multipleQueries,searchForFacetValues:Mt.multipleSearchForFacetValues,multipleBatch:Mt.multipleBatch,multipleGetObjects:Mt.multipleGetObjects,multipleQueries:Mt.multipleQueries,copyIndex:Mt.copyIndex,copySettings:Mt.copySettings,copyRules:Mt.copyRules,copySynonyms:Mt.copySynonyms,moveIndex:Mt.moveIndex,listIndices:Mt.listIndices,getLogs:Mt.getLogs,listClusters:Mt.listClusters,multipleSearchForFacetValues:Mt.multipleSearchForFacetValues,getApiKey:Mt.getApiKey,addApiKey:Mt.addApiKey,listApiKeys:Mt.listApiKeys,updateApiKey:Mt.updateApiKey,deleteApiKey:Mt.deleteApiKey,restoreApiKey:Mt.restoreApiKey,assignUserID:Mt.assignUserID,assignUserIDs:Mt.assignUserIDs,getUserID:Mt.getUserID,searchUserIDs:Mt.searchUserIDs,listUserIDs:Mt.listUserIDs,getTopUserIDs:Mt.getTopUserIDs,removeUserID:Mt.removeUserID,hasPendingMappings:Mt.hasPendingMappings,generateSecuredApiKey:Mt.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:Mt.getSecuredApiKeyRemainingValidity,destroy:sw.destroy,initIndex:g=>t=>Mt.initIndex(g)(t,{methods:{batch:Mt.batch,delete:Mt.deleteIndex,getObject:Mt.getObject,getObjects:Mt.getObjects,saveObject:Mt.saveObject,saveObjects:Mt.saveObjects,search:Mt.search,searchForFacetValues:Mt.searchForFacetValues,waitTask:Mt.waitTask,setSettings:Mt.setSettings,getSettings:Mt.getSettings,partialUpdateObject:Mt.partialUpdateObject,partialUpdateObjects:Mt.partialUpdateObjects,deleteObject:Mt.deleteObject,deleteObjects:Mt.deleteObjects,deleteBy:Mt.deleteBy,clearObjects:Mt.clearObjects,browseObjects:Mt.browseObjects,getObjectPosition:Mt.getObjectPosition,findObject:Mt.findObject,exists:Mt.exists,saveSynonym:Mt.saveSynonym,saveSynonyms:Mt.saveSynonyms,getSynonym:Mt.getSynonym,searchSynonyms:Mt.searchSynonyms,browseSynonyms:Mt.browseSynonyms,deleteSynonym:Mt.deleteSynonym,clearSynonyms:Mt.clearSynonyms,replaceAllObjects:Mt.replaceAllObjects,replaceAllSynonyms:Mt.replaceAllSynonyms,searchRules:Mt.searchRules,getRule:Mt.getRule,deleteRule:Mt.deleteRule,saveRule:Mt.saveRule,saveRules:Mt.saveRules,replaceAllRules:Mt.replaceAllRules,browseRules:Mt.browseRules,clearRules:Mt.clearRules}}),initAnalytics:()=>g=>Ma.createAnalyticsClient(zn(dt(dt({},c),g),{methods:{addABTest:Ma.addABTest,getABTest:Ma.getABTest,getABTests:Ma.getABTests,stopABTest:Ma.stopABTest,deleteABTest:Ma.deleteABTest}})),initRecommendation:()=>g=>lw.createRecommendationClient(zn(dt(dt({},c),g),{methods:{getPersonalizationStrategy:lw.getPersonalizationStrategy,setPersonalizationStrategy:lw.setPersonalizationStrategy}}))}}))}mT.version=sw.version;pT.exports=mT});var _T=Me((OV,fw)=>{var gT=vT();fw.exports=gT;fw.exports.default=gT});var rf=Me(dw=>{"use strict";Object.defineProperty(dw,"__esModule",{value:!0});dw.default=kT;function kT(){}kT.prototype={diff:function(u,f){var c=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},g=c.callback;typeof c=="function"&&(g=c,c={}),this.options=c;var t=this;function C(re){return g?(setTimeout(function(){g(void 0,re)},0),!0):re}u=this.castInput(u),f=this.castInput(f),u=this.removeEmpty(this.tokenize(u)),f=this.removeEmpty(this.tokenize(f));var A=f.length,x=u.length,D=1,L=A+x,N=[{newPos:-1,components:[]}],j=this.extractCommon(N[0],f,u,0);if(N[0].newPos+1>=A&&j+1>=x)return C([{value:this.join(f),count:f.length}]);function $(){for(var re=-1*D;re<=D;re+=2){var ce=void 0,Q=N[re-1],oe=N[re+1],Se=(oe?oe.newPos:0)-re;Q&&(N[re-1]=void 0);var me=Q&&Q.newPos+1=A&&Se+1>=x)return C(LW(t,ce.components,f,u,t.useLongestToken));N[re]=ce}D++}if(g)(function re(){setTimeout(function(){if(D>L)return g();$()||re()},0)})();else for(;D<=L;){var h=$();if(h)return h}},pushComponent:function(u,f,c){var g=u[u.length-1];g&&g.added===f&&g.removed===c?u[u.length-1]={count:g.count+1,added:f,removed:c}:u.push({count:1,added:f,removed:c})},extractCommon:function(u,f,c,g){for(var t=f.length,C=c.length,A=u.newPos,x=A-g,D=0;A+1$.length?re:$}),D.value=i.join(L)}else D.value=i.join(f.slice(A,A+D.count));A+=D.count,D.added||(x+=D.count)}}var j=u[C-1];return C>1&&typeof j.value=="string"&&(j.added||j.removed)&&i.equals("",j.value)&&(u[C-2].value+=j.value,u.pop()),u}function RW(i){return{newPos:i.newPos,components:i.components.slice(0)}}});var OT=Me(ld=>{"use strict";Object.defineProperty(ld,"__esModule",{value:!0});ld.diffChars=NW;ld.characterDiff=void 0;var jW=BW(rf());function BW(i){return i&&i.__esModule?i:{default:i}}var AT=new jW.default;ld.characterDiff=AT;function NW(i,u,f){return AT.diff(i,u,f)}});var hw=Me(pw=>{"use strict";Object.defineProperty(pw,"__esModule",{value:!0});pw.generateOptions=UW;function UW(i,u){if(typeof i=="function")u.callback=i;else if(i)for(var f in i)i.hasOwnProperty(f)&&(u[f]=i[f]);return u}});var MT=Me(Fa=>{"use strict";Object.defineProperty(Fa,"__esModule",{value:!0});Fa.diffWords=qW;Fa.diffWordsWithSpace=zW;Fa.wordDiff=void 0;var HW=WW(rf()),bW=hw();function WW(i){return i&&i.__esModule?i:{default:i}}var IT=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,PT=/\S/,fd=new HW.default;Fa.wordDiff=fd;fd.equals=function(i,u){return this.options.ignoreCase&&(i=i.toLowerCase(),u=u.toLowerCase()),i===u||this.options.ignoreWhitespace&&!PT.test(i)&&!PT.test(u)};fd.tokenize=function(i){for(var u=i.split(/(\s+|[()[\]{}'"]|\b)/),f=0;f{"use strict";Object.defineProperty(La,"__esModule",{value:!0});La.diffLines=GW;La.diffTrimmedLines=VW;La.lineDiff=void 0;var $W=YW(rf()),KW=hw();function YW(i){return i&&i.__esModule?i:{default:i}}var Dm=new $W.default;La.lineDiff=Dm;Dm.tokenize=function(i){var u=[],f=i.split(/(\n|\r\n)/);f[f.length-1]||f.pop();for(var c=0;c{"use strict";Object.defineProperty(cd,"__esModule",{value:!0});cd.diffSentences=XW;cd.sentenceDiff=void 0;var QW=JW(rf());function JW(i){return i&&i.__esModule?i:{default:i}}var mw=new QW.default;cd.sentenceDiff=mw;mw.tokenize=function(i){return i.split(/(\S.+?[.!?])(?=\s+|$)/)};function XW(i,u,f){return mw.diff(i,u,f)}});var LT=Me(ad=>{"use strict";Object.defineProperty(ad,"__esModule",{value:!0});ad.diffCss=ZW;ad.cssDiff=void 0;var tH=eH(rf());function eH(i){return i&&i.__esModule?i:{default:i}}var vw=new tH.default;ad.cssDiff=vw;vw.tokenize=function(i){return i.split(/([{}:;,]|\s+)/)};function ZW(i,u,f){return vw.diff(i,u,f)}});var NT=Me(Ra=>{"use strict";Object.defineProperty(Ra,"__esModule",{value:!0});Ra.diffJson=nH;Ra.canonicalize=Sm;Ra.jsonDiff=void 0;var RT=rH(rf()),iH=Em();function rH(i){return i&&i.__esModule?i:{default:i}}function Cm(i){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Cm=function(f){return typeof f}:Cm=function(f){return f&&typeof Symbol=="function"&&f.constructor===Symbol&&f!==Symbol.prototype?"symbol":typeof f},Cm(i)}var oH=Object.prototype.toString,xc=new RT.default;Ra.jsonDiff=xc;xc.useLongestToken=!0;xc.tokenize=iH.lineDiff.tokenize;xc.castInput=function(i){var u=this.options,f=u.undefinedReplacement,c=u.stringifyReplacer,g=c===void 0?function(t,C){return typeof C=="undefined"?f:C}:c;return typeof i=="string"?i:JSON.stringify(Sm(i,null,null,g),g," ")};xc.equals=function(i,u){return RT.default.prototype.equals.call(xc,i.replace(/,([\r\n])/g,"$1"),u.replace(/,([\r\n])/g,"$1"))};function nH(i,u,f){return xc.diff(i,u,f)}function Sm(i,u,f,c,g){u=u||[],f=f||[],c&&(i=c(g,i));var t;for(t=0;t{"use strict";Object.defineProperty(dd,"__esModule",{value:!0});dd.diffArrays=uH;dd.arrayDiff=void 0;var lH=sH(rf());function sH(i){return i&&i.__esModule?i:{default:i}}var pd=new lH.default;dd.arrayDiff=pd;pd.tokenize=function(i){return i.slice()};pd.join=pd.removeEmpty=function(i){return i};function uH(i,u,f){return pd.diff(i,u,f)}});var Tm=Me(gw=>{"use strict";Object.defineProperty(gw,"__esModule",{value:!0});gw.parsePatch=fH;function fH(i){var u=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},f=i.split(/\r\n|[\n\v\f\r\x85]/),c=i.match(/\r\n|[\n\v\f\r\x85]/g)||[],g=[],t=0;function C(){var D={};for(g.push(D);t{"use strict";Object.defineProperty(_w,"__esModule",{value:!0});_w.default=cH;function cH(i,u,f){var c=!0,g=!1,t=!1,C=1;return function A(){if(c&&!t){if(g?C++:c=!1,i+C<=f)return C;t=!0}if(!g)return t||(c=!0),u<=i-C?-C++:(g=!0,A())}}});var zT=Me(xm=>{"use strict";Object.defineProperty(xm,"__esModule",{value:!0});xm.applyPatch=UT;xm.applyPatches=aH;var qT=Tm(),pH=dH(jT());function dH(i){return i&&i.__esModule?i:{default:i}}function UT(i,u){var f=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};if(typeof u=="string"&&(u=(0,qT.parsePatch)(u)),Array.isArray(u)){if(u.length>1)throw new Error("applyPatch only works with a single input.");u=u[0]}var c=i.split(/\r\n|[\n\v\f\r\x85]/),g=i.match(/\r\n|[\n\v\f\r\x85]/g)||[],t=u.hunks,C=f.compareLine||function(Ot,Nt,Je,V){return Nt===V},A=0,x=f.fuzzFactor||0,D=0,L=0,N,j;function $(Ot,Nt){for(var Je=0;Je0?V[0]:" ",ge=V.length>0?V.substr(1):V;if(ne===" "||ne==="-"){if(!C(Nt+1,c[Nt],ne,ge)&&(A++,A>x))return!1;Nt++}}return!0}for(var h=0;h0?Le[0]:" ",ct=Le.length>0?Le.substr(1):Le,Ue=J.linedelimiters[Oe];if(ot===" ")Te++;else if(ot==="-")c.splice(Te,1),g.splice(Te,1);else if(ot==="+")c.splice(Te,0,ct),g.splice(Te,0,Ue),Te++;else if(ot==="\\"){var be=J.lines[Oe-1]?J.lines[Oe-1][0]:null;be==="+"?N=!0:be==="-"&&(j=!0)}}}if(N)for(;!c[c.length-1];)c.pop(),g.pop();else j&&(c.push(""),g.push(` + `));for(var At=0;At{"use strict";Object.defineProperty(hd,"__esModule",{value:!0});hd.structuredPatch=WT;hd.createTwoFilesPatch=HT;hd.createPatch=hH;var mH=Em();function yw(i){return _H(i)||gH(i)||vH()}function vH(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function gH(i){if(Symbol.iterator in Object(i)||Object.prototype.toString.call(i)==="[object Arguments]")return Array.from(i)}function _H(i){if(Array.isArray(i)){for(var u=0,f=new Array(i.length);u0?x(J.lines.slice(-C.context)):[],L-=j.length,N-=j.length)}(De=j).push.apply(De,yw(me.map(function(At){return(Se.added?"+":"-")+At}))),Se.added?h+=me.length:$+=me.length}else{if(L)if(me.length<=C.context*2&&oe=A.length-2&&me.length<=C.context){var ct=/\n$/.test(f),Ue=/\n$/.test(c),be=me.length==0&&j.length>ot.oldLines;!ct&&be&&j.splice(ot.oldLines,0,"\\ No newline at end of file"),(!ct&&!be||!Ue)&&j.push("\\ No newline at end of file")}D.push(ot),L=0,N=0,j=[]}$+=me.length,h+=me.length}},ce=0;ce{"use strict";Object.defineProperty(km,"__esModule",{value:!0});km.arrayEqual=yH;km.arrayStartsWith=bT;function yH(i,u){return i.length!==u.length?!1:bT(i,u)}function bT(i,u){if(u.length>i.length)return!1;for(var f=0;f{"use strict";Object.defineProperty(Am,"__esModule",{value:!0});Am.calcLineCount=VT;Am.merge=wH;var DH=ww(),EH=Tm(),Dw=GT();function Na(i){return TH(i)||CH(i)||SH()}function SH(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function CH(i){if(Symbol.iterator in Object(i)||Object.prototype.toString.call(i)==="[object Arguments]")return Array.from(i)}function TH(i){if(Array.isArray(i)){for(var u=0,f=new Array(i.length);u{"use strict";Object.defineProperty(Cw,"__esModule",{value:!0});Cw.convertChangesToDMP=OH;function OH(i){for(var u=[],f,c,g=0;g{"use strict";Object.defineProperty(Tw,"__esModule",{value:!0});Tw.convertChangesToXML=IH;function IH(i){for(var u=[],f=0;f"):c.removed&&u.push(""),u.push(PH(c.value)),c.added?u.push(""):c.removed&&u.push("")}return u.join("")}function PH(i){var u=i;return u=u.replace(/&/g,"&"),u=u.replace(//g,">"),u=u.replace(/"/g,"""),u}});var f9=Me(w0=>{"use strict";Object.defineProperty(w0,"__esModule",{value:!0});Object.defineProperty(w0,"Diff",{enumerable:!0,get:function(){return MH.default}});Object.defineProperty(w0,"diffChars",{enumerable:!0,get:function(){return FH.diffChars}});Object.defineProperty(w0,"diffWords",{enumerable:!0,get:function(){return o9.diffWords}});Object.defineProperty(w0,"diffWordsWithSpace",{enumerable:!0,get:function(){return o9.diffWordsWithSpace}});Object.defineProperty(w0,"diffLines",{enumerable:!0,get:function(){return u9.diffLines}});Object.defineProperty(w0,"diffTrimmedLines",{enumerable:!0,get:function(){return u9.diffTrimmedLines}});Object.defineProperty(w0,"diffSentences",{enumerable:!0,get:function(){return LH.diffSentences}});Object.defineProperty(w0,"diffCss",{enumerable:!0,get:function(){return RH.diffCss}});Object.defineProperty(w0,"diffJson",{enumerable:!0,get:function(){return s9.diffJson}});Object.defineProperty(w0,"canonicalize",{enumerable:!0,get:function(){return s9.canonicalize}});Object.defineProperty(w0,"diffArrays",{enumerable:!0,get:function(){return NH.diffArrays}});Object.defineProperty(w0,"applyPatch",{enumerable:!0,get:function(){return l9.applyPatch}});Object.defineProperty(w0,"applyPatches",{enumerable:!0,get:function(){return l9.applyPatches}});Object.defineProperty(w0,"parsePatch",{enumerable:!0,get:function(){return BH.parsePatch}});Object.defineProperty(w0,"merge",{enumerable:!0,get:function(){return jH.merge}});Object.defineProperty(w0,"structuredPatch",{enumerable:!0,get:function(){return xw.structuredPatch}});Object.defineProperty(w0,"createTwoFilesPatch",{enumerable:!0,get:function(){return xw.createTwoFilesPatch}});Object.defineProperty(w0,"createPatch",{enumerable:!0,get:function(){return xw.createPatch}});Object.defineProperty(w0,"convertChangesToDMP",{enumerable:!0,get:function(){return UH.convertChangesToDMP}});Object.defineProperty(w0,"convertChangesToXML",{enumerable:!0,get:function(){return qH.convertChangesToXML}});var MH=zH(rf()),FH=OT(),o9=MT(),u9=Em(),LH=FT(),RH=LT(),s9=NT(),NH=BT(),l9=zT(),BH=Tm(),jH=n9(),xw=ww(),UH=r9(),qH=i9();function zH(i){return i&&i.__esModule?i:{default:i}}});var HH={};jR(HH,{default:()=>GH});var wT=Er(require("@yarnpkg/cli")),Tc=Er(require("@yarnpkg/core"));var Z5=Er(ys()),Dc=Er(lr()),om=(0,Dc.memo)(({active:i})=>{let u=(0,Dc.useMemo)(()=>i?"\u25C9":"\u25EF",[i]),f=(0,Dc.useMemo)(()=>i?"green":"yellow",[i]);return Dc.default.createElement(Z5.Text,{color:f},u)});var Wf=Er(ys()),Bo=Er(lr());var eC=Er(ys()),um=Er(lr());function zf({active:i},u,f){let{stdin:c}=(0,eC.useStdin)(),g=(0,um.useCallback)((t,C)=>u(t,C),f);(0,um.useEffect)(()=>{if(!(!i||!c))return c.on("keypress",g),()=>{c.off("keypress",g)}},[i,g,c])}var sm;(function(f){f.BEFORE="before",f.AFTER="after"})(sm||(sm={}));var tC=function({active:i},u,f){zf({active:i},(c,g)=>{g.name==="tab"&&(g.shift?u(sm.BEFORE):u(sm.AFTER))},f)};var lm=function(i,u,{active:f,minus:c,plus:g,set:t,loop:C=!0}){zf({active:f},(A,x)=>{let D=u.indexOf(i);switch(x.name){case c:{let L=D-1;if(C){t(u[(u.length+L)%u.length]);return}if(L<0)return;t(u[L])}break;case g:{let L=D+1;if(C){t(u[L%u.length]);return}if(L>=u.length)return;t(u[L])}break}},[u,i,g,t,C])};var fm=({active:i=!0,children:u=[],radius:f=10,size:c=1,loop:g=!0,onFocusRequest:t,willReachEnd:C})=>{let A=ce=>{if(ce.key===null)throw new Error("Expected all children to have a key");return ce.key},x=Bo.default.Children.map(u,ce=>A(ce)),D=x[0],[L,N]=(0,Bo.useState)(D),j=x.indexOf(L);(0,Bo.useEffect)(()=>{x.includes(L)||N(D)},[u]),(0,Bo.useEffect)(()=>{C&&j>=x.length-2&&C()},[j]),tC({active:i&&!!t},ce=>{t==null||t(ce)},[t]),lm(L,x,{active:i,minus:"up",plus:"down",set:N,loop:g});let $=j-f,h=j+f;h>x.length&&($-=h-x.length,h=x.length),$<0&&(h+=-$,$=0),h>=x.length&&(h=x.length-1);let re=[];for(let ce=$;ce<=h;++ce){let Q=x[ce],oe=i&&Q===L;re.push(Bo.default.createElement(Wf.Box,{key:Q,height:c},Bo.default.createElement(Wf.Box,{marginLeft:1,marginRight:1},Bo.default.createElement(Wf.Text,null,oe?Bo.default.createElement(Wf.Text,{color:"cyan",bold:!0},">"):" ")),Bo.default.createElement(Wf.Box,null,Bo.default.cloneElement(u[ce],{active:oe}))))}return Bo.default.createElement(Wf.Box,{flexDirection:"column",width:"100%"},re)};var cm=Er(lr());var nC=Er(ys()),nf=Er(lr()),rC=Er(require("readline")),G3=nf.default.createContext(null),iC=({children:i})=>{let{stdin:u,setRawMode:f}=(0,nC.useStdin)();(0,nf.useEffect)(()=>{f&&f(!0),u&&(0,rC.emitKeypressEvents)(u)},[u,f]);let[c,g]=(0,nf.useState)(new Map),t=(0,nf.useMemo)(()=>({getAll:()=>c,get:C=>c.get(C),set:(C,A)=>g(new Map([...c,[C,A]]))}),[c,g]);return nf.default.createElement(G3.Provider,{value:t,children:i})};function Ec(i,u){let f=(0,cm.useContext)(G3);if(f===null)throw new Error("Expected this hook to run with a ministore context attached");if(typeof i=="undefined")return f.getAll();let c=(0,cm.useCallback)(t=>{f.set(i,t)},[i,f.set]),g=f.get(i);return typeof g=="undefined"&&(g=u),[g,c]}var am=Er(ys()),V3=Er(lr());async function dm(i,u){let f,c=t=>{let{exit:C}=(0,am.useApp)();zf({active:!0},(A,x)=>{x.name==="return"&&(f=t,C())},[C,t])},{waitUntilExit:g}=(0,am.render)(V3.default.createElement(iC,null,V3.default.createElement(i,zn(dt({},u),{useSubmit:c}))));return await g(),f}var DT=Er(require("clipanion")),ET=Er(lC()),un=Er(ys()),Pt=Er(lr());var yT=Er(_T()),cw={appId:"OFCNCOG2CU",apiKey:"6fe4476ee5a1832882e326b506d14126",indexName:"npm-search"},FW=(0,yT.default)(cw.appId,cw.apiKey).initIndex(cw.indexName),aw=async(i,u=0)=>await FW.search(i,{analyticsTags:["yarn-plugin-interactive-tools"],attributesToRetrieve:["name","version","owner","repository","humanDownloadsLast30Days"],page:u,hitsPerPage:10});var od=["regular","dev","peer"],ud=class extends wT.BaseCommand{async execute(){let u=await Tc.Configuration.find(this.context.cwd,this.context.plugins),f=()=>Pt.default.createElement(un.Box,{flexDirection:"row"},Pt.default.createElement(un.Box,{flexDirection:"column",width:48},Pt.default.createElement(un.Box,null,Pt.default.createElement(un.Text,null,"Press ",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},""),"/",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},"")," to move between packages.")),Pt.default.createElement(un.Box,null,Pt.default.createElement(un.Text,null,"Press ",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},"")," to select a package.")),Pt.default.createElement(un.Box,null,Pt.default.createElement(un.Text,null,"Press ",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},"")," again to change the target."))),Pt.default.createElement(un.Box,{flexDirection:"column"},Pt.default.createElement(un.Box,{marginLeft:1},Pt.default.createElement(un.Text,null,"Press ",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},"")," to install the selected packages.")),Pt.default.createElement(un.Box,{marginLeft:1},Pt.default.createElement(un.Text,null,"Press ",Pt.default.createElement(un.Text,{bold:!0,color:"cyanBright"},"")," to abort.")))),c=()=>Pt.default.createElement(Pt.default.Fragment,null,Pt.default.createElement(un.Box,{width:15},Pt.default.createElement(un.Text,{bold:!0,underline:!0,color:"gray"},"Owner")),Pt.default.createElement(un.Box,{width:11},Pt.default.createElement(un.Text,{bold:!0,underline:!0,color:"gray"},"Version")),Pt.default.createElement(un.Box,{width:10},Pt.default.createElement(un.Text,{bold:!0,underline:!0,color:"gray"},"Downloads"))),g=()=>Pt.default.createElement(un.Box,{width:17},Pt.default.createElement(un.Text,{bold:!0,underline:!0,color:"gray"},"Target")),t=({hit:$,active:h})=>{let[re,ce]=Ec($.name,null);zf({active:h},(Se,me)=>{if(me.name!=="space")return;if(!re){ce(od[0]);return}let De=od.indexOf(re)+1;De===od.length?ce(null):ce(od[De])},[re,ce]);let Q=Tc.structUtils.parseIdent($.name),oe=Tc.structUtils.prettyIdent(u,Q);return Pt.default.createElement(un.Box,null,Pt.default.createElement(un.Box,{width:45},Pt.default.createElement(un.Text,{bold:!0,wrap:"wrap"},oe)),Pt.default.createElement(un.Box,{width:14,marginLeft:1},Pt.default.createElement(un.Text,{bold:!0,wrap:"truncate"},$.owner.name)),Pt.default.createElement(un.Box,{width:10,marginLeft:1},Pt.default.createElement(un.Text,{italic:!0,wrap:"truncate"},$.version)),Pt.default.createElement(un.Box,{width:16,marginLeft:1},Pt.default.createElement(un.Text,null,$.humanDownloadsLast30Days)))},C=({name:$,active:h})=>{let[re]=Ec($,null),ce=Tc.structUtils.parseIdent($);return Pt.default.createElement(un.Box,null,Pt.default.createElement(un.Box,{width:47},Pt.default.createElement(un.Text,{bold:!0}," - ",Tc.structUtils.prettyIdent(u,ce))),od.map(Q=>Pt.default.createElement(un.Box,{key:Q,width:14,marginLeft:1},Pt.default.createElement(un.Text,null," ",Pt.default.createElement(om,{active:re===Q})," ",Pt.default.createElement(un.Text,{bold:!0},Q)))))},A=()=>Pt.default.createElement(un.Box,{marginTop:1},Pt.default.createElement(un.Text,null,"Powered by Algolia.")),D=await dm(({useSubmit:$})=>{let h=Ec();$(h);let re=Array.from(h.keys()).filter(Le=>h.get(Le)!==null),[ce,Q]=(0,Pt.useState)(""),[oe,Se]=(0,Pt.useState)(0),[me,De]=(0,Pt.useState)([]),J=Le=>{Le.match(/\t| /)||Q(Le)},Te=async()=>{Se(0);let Le=await aw(ce);Le.query===ce&&De(Le.hits)},Oe=async()=>{let Le=await aw(ce,oe+1);Le.query===ce&&Le.page-1===oe&&(Se(Le.page),De([...me,...Le.hits]))};return(0,Pt.useEffect)(()=>{ce?Te():De([])},[ce]),Pt.default.createElement(un.Box,{flexDirection:"column"},Pt.default.createElement(f,null),Pt.default.createElement(un.Box,{flexDirection:"row",marginTop:1},Pt.default.createElement(un.Text,{bold:!0},"Search: "),Pt.default.createElement(un.Box,{width:41},Pt.default.createElement(ET.default,{value:ce,onChange:J,placeholder:"i.e. babel, webpack, react...",showCursor:!1})),Pt.default.createElement(c,null)),me.length?Pt.default.createElement(fm,{radius:2,loop:!1,children:me.map(Le=>Pt.default.createElement(t,{key:Le.name,hit:Le,active:!1})),willReachEnd:Oe}):Pt.default.createElement(un.Text,{color:"gray"},"Start typing..."),Pt.default.createElement(un.Box,{flexDirection:"row",marginTop:1},Pt.default.createElement(un.Box,{width:49},Pt.default.createElement(un.Text,{bold:!0},"Selected:")),Pt.default.createElement(g,null)),re.length?re.map(Le=>Pt.default.createElement(C,{key:Le,name:Le,active:!1})):Pt.default.createElement(un.Text,{color:"gray"},"No selected packages..."),Pt.default.createElement(A,null))},{});if(typeof D=="undefined")return 1;let L=Array.from(D.keys()).filter($=>D.get($)==="regular"),N=Array.from(D.keys()).filter($=>D.get($)==="dev"),j=Array.from(D.keys()).filter($=>D.get($)==="peer");return L.length&&await this.cli.run(["add",...L]),N.length&&await this.cli.run(["add","--dev",...N]),j&&await this.cli.run(["add","--peer",...j]),0}};ud.paths=[["search"]],ud.usage=DT.Command.Usage({category:"Interactive commands",description:"open the search interface",details:` + This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry. + `,examples:[["Open the search window","yarn search"]]});var ST=ud;var Im=Er(require("@yarnpkg/cli")),W0=Er(require("@yarnpkg/core"));var sd=Er(ys()),bf=Er(lr());var CT=Er(ys()),TT=Er(lr()),wm=({length:i,active:u})=>{if(i===0)return null;let f=i>1?` ${"-".repeat(i-1)}`:" ";return TT.default.createElement(CT.Text,{dimColor:!u},f)};var xT=function({active:i,skewer:u,options:f,value:c,onChange:g,sizes:t=[]}){let C=f.filter(({label:x})=>!!x).map(({value:x})=>x),A=f.findIndex(x=>x.value===c&&x.label!="");return lm(c,C,{active:i,minus:"left",plus:"right",set:g}),bf.default.createElement(bf.default.Fragment,null,f.map(({label:x},D)=>{let L=D===A,N=t[D]-1||0,j=x.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),$=Math.max(0,N-j.length-2);return x?bf.default.createElement(sd.Box,{key:x,width:N,marginLeft:1},bf.default.createElement(sd.Text,{wrap:"truncate"},bf.default.createElement(om,{active:L})," ",x),u?bf.default.createElement(wm,{active:i,length:$}):null):bf.default.createElement(sd.Box,{key:`spacer-${D}`,width:N,marginLeft:1})}))};var c9=Er(require("@yarnpkg/plugin-essentials")),a9=Er(require("clipanion")),d9=Er(f9()),tr=Er(ys()),pn=Er(lr()),p9=Er(require("semver")),h9=/^((?:[\^~]|>=?)?)([0-9]+)(\.[0-9]+)(\.[0-9]+)((?:-\S+)?)$/,WH=10,md=class extends Im.BaseCommand{async execute(){let u=await W0.Configuration.find(this.context.cwd,this.context.plugins),{project:f,workspace:c}=await W0.Project.find(u,this.context.cwd),g=await W0.Cache.find(u);if(!c)throw new Im.WorkspaceRequiredError(f.cwd,this.context.cwd);await f.restoreInstallState({restoreResolutions:!1});let t=(Q,oe)=>{let Se=(0,d9.diffWords)(Q,oe),me="";for(let De of Se)De.added?me+=W0.formatUtils.pretty(u,De.value,"green"):De.removed||(me+=De.value);return me},C=(Q,oe)=>{if(Q===oe)return oe;let Se=W0.structUtils.parseRange(Q),me=W0.structUtils.parseRange(oe),De=Se.selector.match(h9),J=me.selector.match(h9);if(!De||!J)return t(Q,oe);let Te=["gray","red","yellow","green","magenta"],Oe=null,Le="";for(let ot=1;ot{let me=await c9.suggestUtils.fetchDescriptorFrom(Q,Se,{project:f,cache:g,preserveModifier:oe,workspace:c});return me!==null?me.range:Q.range},x=async Q=>{let oe=p9.default.valid(Q.range)?`^${Q.range}`:Q.range,[Se,me]=await Promise.all([A(Q,Q.range,oe).catch(()=>null),A(Q,Q.range,"latest").catch(()=>null)]),De=[{value:null,label:Q.range}];return Se&&Se!==Q.range?De.push({value:Se,label:C(Q.range,Se)}):De.push({value:null,label:""}),me&&me!==Se&&me!==Q.range?De.push({value:me,label:C(Q.range,me)}):De.push({value:null,label:""}),De},D=()=>pn.default.createElement(tr.Box,{flexDirection:"row"},pn.default.createElement(tr.Box,{flexDirection:"column",width:49},pn.default.createElement(tr.Box,{marginLeft:1},pn.default.createElement(tr.Text,null,"Press ",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},""),"/",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},"")," to select packages.")),pn.default.createElement(tr.Box,{marginLeft:1},pn.default.createElement(tr.Text,null,"Press ",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},""),"/",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},"")," to select versions."))),pn.default.createElement(tr.Box,{flexDirection:"column"},pn.default.createElement(tr.Box,{marginLeft:1},pn.default.createElement(tr.Text,null,"Press ",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},"")," to install.")),pn.default.createElement(tr.Box,{marginLeft:1},pn.default.createElement(tr.Text,null,"Press ",pn.default.createElement(tr.Text,{bold:!0,color:"cyanBright"},"")," to abort.")))),L=()=>pn.default.createElement(tr.Box,{flexDirection:"row",paddingTop:1,paddingBottom:1},pn.default.createElement(tr.Box,{width:50},pn.default.createElement(tr.Text,{bold:!0},pn.default.createElement(tr.Text,{color:"greenBright"},"?")," Pick the packages you want to upgrade.")),pn.default.createElement(tr.Box,{width:17},pn.default.createElement(tr.Text,{bold:!0,underline:!0,color:"gray"},"Current")),pn.default.createElement(tr.Box,{width:17},pn.default.createElement(tr.Text,{bold:!0,underline:!0,color:"gray"},"Range")),pn.default.createElement(tr.Box,{width:17},pn.default.createElement(tr.Text,{bold:!0,underline:!0,color:"gray"},"Latest"))),N=({active:Q,descriptor:oe,suggestions:Se})=>{let[me,De]=Ec(oe.descriptorHash,null),J=W0.structUtils.stringifyIdent(oe),Te=Math.max(0,45-J.length);return pn.default.createElement(pn.default.Fragment,null,pn.default.createElement(tr.Box,null,pn.default.createElement(tr.Box,{width:45},pn.default.createElement(tr.Text,{bold:!0},W0.structUtils.prettyIdent(u,oe)),pn.default.createElement(wm,{active:Q,length:Te})),Se!==null?pn.default.createElement(xT,{active:Q,options:Se,value:me,skewer:!0,onChange:De,sizes:[17,17,17]}):pn.default.createElement(tr.Box,{marginLeft:2},pn.default.createElement(tr.Text,{color:"gray"},"Fetching suggestions..."))))},j=({dependencies:Q})=>{let[oe,Se]=(0,pn.useState)(null),me=(0,pn.useRef)(!0);return(0,pn.useEffect)(()=>()=>{me.current=!1}),(0,pn.useEffect)(()=>{Promise.all(Q.map(De=>x(De))).then(De=>{let J=Q.map((Te,Oe)=>{let Le=De[Oe];return[Te,Le]}).filter(([Te,Oe])=>Oe.filter(Le=>Le.label!=="").length>1);me.current&&Se(J)})},[]),oe?oe.length?pn.default.createElement(fm,{radius:WH,children:oe.map(([De,J])=>pn.default.createElement(N,{key:De.descriptorHash,active:!1,descriptor:De,suggestions:J}))}):pn.default.createElement(tr.Text,null,"No upgrades found"):pn.default.createElement(tr.Text,null,"Fetching suggestions...")},h=await dm(({useSubmit:Q})=>{Q(Ec());let oe=new Map;for(let me of f.workspaces)for(let De of["dependencies","devDependencies"])for(let J of me.manifest[De].values())f.tryWorkspaceByDescriptor(J)===null&&oe.set(J.descriptorHash,J);let Se=W0.miscUtils.sortMap(oe.values(),me=>W0.structUtils.stringifyDescriptor(me));return pn.default.createElement(tr.Box,{flexDirection:"column"},pn.default.createElement(D,null),pn.default.createElement(L,null),pn.default.createElement(j,{dependencies:Se}))},{});if(typeof h=="undefined")return 1;let re=!1;for(let Q of f.workspaces)for(let oe of["dependencies","devDependencies"]){let Se=Q.manifest[oe];for(let me of Se.values()){let De=h.get(me.descriptorHash);typeof De!="undefined"&&De!==null&&(Se.set(me.identHash,W0.structUtils.makeDescriptor(me,De)),re=!0)}}return re?(await W0.StreamReport.start({configuration:u,stdout:this.context.stdout,includeLogs:!this.context.quiet},async Q=>{await f.install({cache:g,report:Q})})).exitCode():0}};md.paths=[["upgrade-interactive"]],md.usage=a9.Command.Usage({category:"Interactive commands",description:"open the upgrade interface",details:` + This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade. + `,examples:[["Open the upgrade window","yarn upgrade-interactive"]]});var m9=md;var bH={commands:[ST,m9]},GH=bH;return HH;})(); + /* + object-assign + (c) Sindre Sorhus + @license MIT + */ + /** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + /** @license React v0.0.0-experimental-51a3aa6af + * react-debug-tools.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v0.0.0-experimental-51a3aa6af + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v0.0.0-experimental-51a3aa6af + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v0.18.0 + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v0.24.0 + * react-reconciler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v16.13.1 + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + return plugin; + } + }; + \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/.yarn/releases/yarn-4.5.1.cjs b/src/apps/Altinn.AccessManagement/test/K6/.yarn/releases/yarn-4.5.1.cjs new file mode 100755 index 00000000..2a9a9203 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.yarn/releases/yarn-4.5.1.cjs @@ -0,0 +1,934 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var j3e=Object.create;var gT=Object.defineProperty;var G3e=Object.getOwnPropertyDescriptor;var Y3e=Object.getOwnPropertyNames;var W3e=Object.getPrototypeOf,K3e=Object.prototype.hasOwnProperty;var ve=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var wt=(t,e)=>()=>(t&&(e=t(t=0)),e);var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Kt=(t,e)=>{for(var r in e)gT(t,r,{get:e[r],enumerable:!0})},V3e=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of Y3e(e))!K3e.call(t,a)&&a!==r&&gT(t,a,{get:()=>e[a],enumerable:!(o=G3e(e,a))||o.enumerable});return t};var et=(t,e,r)=>(r=t!=null?j3e(W3e(t)):{},V3e(e||!t||!t.__esModule?gT(r,"default",{value:t,enumerable:!0}):r,t));var Pi={};Kt(Pi,{SAFE_TIME:()=>cY,S_IFDIR:()=>VD,S_IFLNK:()=>zD,S_IFMT:()=>Hu,S_IFREG:()=>oI});var Hu,VD,oI,zD,cY,uY=wt(()=>{Hu=61440,VD=16384,oI=32768,zD=40960,cY=456789e3});var sr={};Kt(sr,{EBADF:()=>ho,EBUSY:()=>z3e,EEXIST:()=>t_e,EINVAL:()=>X3e,EISDIR:()=>e_e,ENOENT:()=>Z3e,ENOSYS:()=>J3e,ENOTDIR:()=>$3e,ENOTEMPTY:()=>n_e,EOPNOTSUPP:()=>i_e,EROFS:()=>r_e,ERR_DIR_CLOSED:()=>dT});function Ll(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}function z3e(t){return Ll("EBUSY",t)}function J3e(t,e){return Ll("ENOSYS",`${t}, ${e}`)}function X3e(t){return Ll("EINVAL",`invalid argument, ${t}`)}function ho(t){return Ll("EBADF",`bad file descriptor, ${t}`)}function Z3e(t){return Ll("ENOENT",`no such file or directory, ${t}`)}function $3e(t){return Ll("ENOTDIR",`not a directory, ${t}`)}function e_e(t){return Ll("EISDIR",`illegal operation on a directory, ${t}`)}function t_e(t){return Ll("EEXIST",`file already exists, ${t}`)}function r_e(t){return Ll("EROFS",`read-only filesystem, ${t}`)}function n_e(t){return Ll("ENOTEMPTY",`directory not empty, ${t}`)}function i_e(t){return Ll("EOPNOTSUPP",`operation not supported, ${t}`)}function dT(){return Ll("ERR_DIR_CLOSED","Directory handle was closed")}var JD=wt(()=>{});var Ia={};Kt(Ia,{BigIntStatsEntry:()=>cm,DEFAULT_MODE:()=>ET,DirEntry:()=>mT,StatEntry:()=>lm,areStatsEqual:()=>CT,clearStats:()=>XD,convertToBigIntStats:()=>o_e,makeDefaultStats:()=>AY,makeEmptyStats:()=>s_e});function AY(){return new lm}function s_e(){return XD(AY())}function XD(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r=="number"?t[e]=0:typeof r=="bigint"?t[e]=BigInt(0):yT.types.isDate(r)&&(t[e]=new Date(0))}return t}function o_e(t){let e=new cm;for(let r in t)if(Object.hasOwn(t,r)){let o=t[r];typeof o=="number"?e[r]=BigInt(o):yT.types.isDate(o)&&(e[r]=new Date(o))}return e.atimeNs=e.atimeMs*BigInt(1e6),e.mtimeNs=e.mtimeMs*BigInt(1e6),e.ctimeNs=e.ctimeMs*BigInt(1e6),e.birthtimeNs=e.birthtimeMs*BigInt(1e6),e}function CT(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs||t.blksize!==e.blksize||t.blocks!==e.blocks||t.ctimeMs!==e.ctimeMs||t.dev!==e.dev||t.gid!==e.gid||t.ino!==e.ino||t.isBlockDevice()!==e.isBlockDevice()||t.isCharacterDevice()!==e.isCharacterDevice()||t.isDirectory()!==e.isDirectory()||t.isFIFO()!==e.isFIFO()||t.isFile()!==e.isFile()||t.isSocket()!==e.isSocket()||t.isSymbolicLink()!==e.isSymbolicLink()||t.mode!==e.mode||t.mtimeMs!==e.mtimeMs||t.nlink!==e.nlink||t.rdev!==e.rdev||t.size!==e.size||t.uid!==e.uid)return!1;let r=t,o=e;return!(r.atimeNs!==o.atimeNs||r.mtimeNs!==o.mtimeNs||r.ctimeNs!==o.ctimeNs||r.birthtimeNs!==o.birthtimeNs)}var yT,ET,mT,lm,cm,wT=wt(()=>{yT=et(ve("util")),ET=33188,mT=class{constructor(){this.name="";this.path="";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},lm=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=ET;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},cm=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=BigInt(0);this.ino=BigInt(0);this.mode=BigInt(ET);this.nlink=BigInt(1);this.rdev=BigInt(0);this.blocks=BigInt(1)}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}isFIFO(){return!1}isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}isSocket(){return!1}isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}}});function A_e(t){let e,r;if(e=t.match(c_e))t=e[1];else if(r=t.match(u_e))t=`\\\\${r[1]?".\\":""}${r[2]}`;else return t;return t.replace(/\//g,"\\")}function f_e(t){t=t.replace(/\\/g,"/");let e,r;return(e=t.match(a_e))?t=`/${e[1]}`:(r=t.match(l_e))&&(t=`/unc/${r[1]?".dot/":""}${r[2]}`),t}function ZD(t,e){return t===Ae?pY(e):IT(e)}var aI,Bt,mr,Ae,K,fY,a_e,l_e,c_e,u_e,IT,pY,Ba=wt(()=>{aI=et(ve("path")),Bt={root:"/",dot:".",parent:".."},mr={home:"~",nodeModules:"node_modules",manifest:"package.json",lockfile:"yarn.lock",virtual:"__virtual__",pnpJs:".pnp.js",pnpCjs:".pnp.cjs",pnpData:".pnp.data.json",pnpEsmLoader:".pnp.loader.mjs",rc:".yarnrc.yml",env:".env"},Ae=Object.create(aI.default),K=Object.create(aI.default.posix);Ae.cwd=()=>process.cwd();K.cwd=process.platform==="win32"?()=>IT(process.cwd()):process.cwd;process.platform==="win32"&&(K.resolve=(...t)=>t.length>0&&K.isAbsolute(t[0])?aI.default.posix.resolve(...t):aI.default.posix.resolve(K.cwd(),...t));fY=function(t,e,r){return e=t.normalize(e),r=t.normalize(r),e===r?".":(e.endsWith(t.sep)||(e=e+t.sep),r.startsWith(e)?r.slice(e.length):null)};Ae.contains=(t,e)=>fY(Ae,t,e);K.contains=(t,e)=>fY(K,t,e);a_e=/^([a-zA-Z]:.*)$/,l_e=/^\/\/(\.\/)?(.*)$/,c_e=/^\/([a-zA-Z]:.*)$/,u_e=/^\/unc\/(\.dot\/)?(.*)$/;IT=process.platform==="win32"?f_e:t=>t,pY=process.platform==="win32"?A_e:t=>t;Ae.fromPortablePath=pY;Ae.toPortablePath=IT});async function $D(t,e){let r="0123456789abcdef";await t.mkdirPromise(e.indexPath,{recursive:!0});let o=[];for(let a of r)for(let n of r)o.push(t.mkdirPromise(t.pathUtils.join(e.indexPath,`${a}${n}`),{recursive:!0}));return await Promise.all(o),e.indexPath}async function hY(t,e,r,o,a){let n=t.pathUtils.normalize(e),u=r.pathUtils.normalize(o),A=[],p=[],{atime:h,mtime:E}=a.stableTime?{atime:H0,mtime:H0}:await r.lstatPromise(u);await t.mkdirpPromise(t.pathUtils.dirname(e),{utimes:[h,E]}),await BT(A,p,t,n,r,u,{...a,didParentExist:!0});for(let I of A)await I();await Promise.all(p.map(I=>I()))}async function BT(t,e,r,o,a,n,u){let A=u.didParentExist?await gY(r,o):null,p=await a.lstatPromise(n),{atime:h,mtime:E}=u.stableTime?{atime:H0,mtime:H0}:p,I;switch(!0){case p.isDirectory():I=await h_e(t,e,r,o,A,a,n,p,u);break;case p.isFile():I=await m_e(t,e,r,o,A,a,n,p,u);break;case p.isSymbolicLink():I=await y_e(t,e,r,o,A,a,n,p,u);break;default:throw new Error(`Unsupported file type (${p.mode})`)}return(u.linkStrategy?.type!=="HardlinkFromIndex"||!p.isFile())&&((I||A?.mtime?.getTime()!==E.getTime()||A?.atime?.getTime()!==h.getTime())&&(e.push(()=>r.lutimesPromise(o,h,E)),I=!0),(A===null||(A.mode&511)!==(p.mode&511))&&(e.push(()=>r.chmodPromise(o,p.mode&511)),I=!0)),I}async function gY(t,e){try{return await t.lstatPromise(e)}catch{return null}}async function h_e(t,e,r,o,a,n,u,A,p){if(a!==null&&!a.isDirectory())if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;let h=!1;a===null&&(t.push(async()=>{try{await r.mkdirPromise(o,{mode:A.mode})}catch(D){if(D.code!=="EEXIST")throw D}}),h=!0);let E=await n.readdirPromise(u),I=p.didParentExist&&!a?{...p,didParentExist:!1}:p;if(p.stableSort)for(let D of E.sort())await BT(t,e,r,r.pathUtils.join(o,D),n,n.pathUtils.join(u,D),I)&&(h=!0);else(await Promise.all(E.map(async x=>{await BT(t,e,r,r.pathUtils.join(o,x),n,n.pathUtils.join(u,x),I)}))).some(x=>x)&&(h=!0);return h}async function g_e(t,e,r,o,a,n,u,A,p,h){let E=await n.checksumFilePromise(u,{algorithm:"sha1"}),I=420,D=A.mode&511,x=`${E}${D!==I?D.toString(8):""}`,C=r.pathUtils.join(h.indexPath,E.slice(0,2),`${x}.dat`),T;(ue=>(ue[ue.Lock=0]="Lock",ue[ue.Rename=1]="Rename"))(T||={});let L=1,U=await gY(r,C);if(a){let le=U&&a.dev===U.dev&&a.ino===U.ino,ce=U?.mtimeMs!==p_e;if(le&&ce&&h.autoRepair&&(L=0,U=null),!le)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1}let z=!U&&L===1?`${C}.${Math.floor(Math.random()*4294967296).toString(16).padStart(8,"0")}`:null,te=!1;return t.push(async()=>{if(!U&&(L===0&&await r.lockPromise(C,async()=>{let le=await n.readFilePromise(u);await r.writeFilePromise(C,le)}),L===1&&z)){let le=await n.readFilePromise(u);await r.writeFilePromise(z,le);try{await r.linkPromise(z,C)}catch(ce){if(ce.code==="EEXIST")te=!0,await r.unlinkPromise(z);else throw ce}}a||await r.linkPromise(C,o)}),e.push(async()=>{U||(await r.lutimesPromise(C,H0,H0),D!==I&&await r.chmodPromise(C,D)),z&&!te&&await r.unlinkPromise(z)}),!1}async function d_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{let h=await n.readFilePromise(u);await r.writeFilePromise(o,h)}),!0}async function m_e(t,e,r,o,a,n,u,A,p){return p.linkStrategy?.type==="HardlinkFromIndex"?g_e(t,e,r,o,a,n,u,A,p,p.linkStrategy):d_e(t,e,r,o,a,n,u,A,p)}async function y_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{await r.symlinkPromise(ZD(r.pathUtils,await n.readlinkPromise(u)),o)}),!0}var H0,p_e,vT=wt(()=>{Ba();H0=new Date(456789e3*1e3),p_e=H0.getTime()});function eP(t,e,r,o){let a=()=>{let n=r.shift();if(typeof n>"u")return null;let u=t.pathUtils.join(e,n);return Object.assign(t.statSync(u),{name:n,path:void 0})};return new lI(e,a,o)}var lI,dY=wt(()=>{JD();lI=class{constructor(e,r,o={}){this.path=e;this.nextDirent=r;this.opts=o;this.closed=!1}throwIfClosed(){if(this.closed)throw dT()}async*[Symbol.asyncIterator](){try{let e;for(;(e=await this.read())!==null;)yield e}finally{await this.close()}}read(e){let r=this.readSync();return typeof e<"u"?e(null,r):Promise.resolve(r)}readSync(){return this.throwIfClosed(),this.nextDirent()}close(e){return this.closeSync(),typeof e<"u"?e(null):Promise.resolve()}closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}}});function mY(t,e){if(t!==e)throw new Error(`Invalid StatWatcher status: expected '${e}', got '${t}'`)}var yY,tP,EY=wt(()=>{yY=ve("events");wT();tP=class t extends yY.EventEmitter{constructor(r,o,{bigint:a=!1}={}){super();this.status="ready";this.changeListeners=new Map;this.startTimeout=null;this.fakeFs=r,this.path=o,this.bigint=a,this.lastStats=this.stat()}static create(r,o,a){let n=new t(r,o,a);return n.start(),n}start(){mY(this.status,"ready"),this.status="running",this.startTimeout=setTimeout(()=>{this.startTimeout=null,this.fakeFs.existsSync(this.path)||this.emit("change",this.lastStats,this.lastStats)},3)}stop(){mY(this.status,"running"),this.status="stopped",this.startTimeout!==null&&(clearTimeout(this.startTimeout),this.startTimeout=null),this.emit("stop")}stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}catch{let o=this.bigint?new cm:new lm;return XD(o)}}makeInterval(r){let o=setInterval(()=>{let a=this.stat(),n=this.lastStats;CT(a,n)||(this.lastStats=a,this.emit("change",a,n))},r.interval);return r.persistent?o:o.unref()}registerChangeListener(r,o){this.addListener("change",r),this.changeListeners.set(r,this.makeInterval(o))}unregisterChangeListener(r){this.removeListener("change",r);let o=this.changeListeners.get(r);typeof o<"u"&&clearInterval(o),this.changeListeners.delete(r)}unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())this.unregisterChangeListener(r)}hasChangeListeners(){return this.changeListeners.size>0}ref(){for(let r of this.changeListeners.values())r.ref();return this}unref(){for(let r of this.changeListeners.values())r.unref();return this}}});function um(t,e,r,o){let a,n,u,A;switch(typeof r){case"function":a=!1,n=!0,u=5007,A=r;break;default:({bigint:a=!1,persistent:n=!0,interval:u=5007}=r),A=o;break}let p=rP.get(t);typeof p>"u"&&rP.set(t,p=new Map);let h=p.get(e);return typeof h>"u"&&(h=tP.create(t,e,{bigint:a}),p.set(e,h)),h.registerChangeListener(A,{persistent:n,interval:u}),h}function q0(t,e,r){let o=rP.get(t);if(typeof o>"u")return;let a=o.get(e);typeof a>"u"||(typeof r>"u"?a.unregisterAllChangeListeners():a.unregisterChangeListener(r),a.hasChangeListeners()||(a.stop(),o.delete(e)))}function j0(t){let e=rP.get(t);if(!(typeof e>"u"))for(let r of e.keys())q0(t,r)}var rP,DT=wt(()=>{EY();rP=new WeakMap});function E_e(t){let e=t.match(/\r?\n/g);if(e===null)return wY.EOL;let r=e.filter(a=>a===`\r +`).length,o=e.length-r;return r>o?`\r +`:` +`}function G0(t,e){return e.replace(/\r?\n/g,E_e(t))}var CY,wY,hf,qu,Y0=wt(()=>{CY=ve("crypto"),wY=ve("os");vT();Ba();hf=class{constructor(e){this.pathUtils=e}async*genTraversePromise(e,{stableSort:r=!1}={}){let o=[e];for(;o.length>0;){let a=o.shift();if((await this.lstatPromise(a)).isDirectory()){let u=await this.readdirPromise(a);if(r)for(let A of u.sort())o.push(this.pathUtils.join(a,A));else throw new Error("Not supported")}else yield a}}async checksumFilePromise(e,{algorithm:r="sha512"}={}){let o=await this.openPromise(e,"r");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,CY.createHash)(r),A=0;for(;(A=await this.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest("hex")}finally{await this.closePromise(o)}}async removePromise(e,{recursive:r=!0,maxRetries:o=5}={}){let a;try{a=await this.lstatPromise(e)}catch(n){if(n.code==="ENOENT")return;throw n}if(a.isDirectory()){if(r){let n=await this.readdirPromise(e);await Promise.all(n.map(u=>this.removePromise(this.pathUtils.resolve(e,u))))}for(let n=0;n<=o;n++)try{await this.rmdirPromise(e);break}catch(u){if(u.code!=="EBUSY"&&u.code!=="ENOTEMPTY")throw u;nsetTimeout(A,n*100))}}else await this.unlinkPromise(e)}removeSync(e,{recursive:r=!0}={}){let o;try{o=this.lstatSync(e)}catch(a){if(a.code==="ENOENT")return;throw a}if(o.isDirectory()){if(r)for(let a of this.readdirSync(e))this.removeSync(this.pathUtils.resolve(e,a));this.rmdirSync(e)}else this.unlinkSync(e)}async mkdirpPromise(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{await this.mkdirPromise(A)}catch(p){if(p.code==="EEXIST")continue;throw p}if(n??=A,r!=null&&await this.chmodPromise(A,r),o!=null)await this.utimesPromise(A,o[0],o[1]);else{let p=await this.statPromise(this.pathUtils.dirname(A));await this.utimesPromise(A,p.atime,p.mtime)}}}return n}mkdirpSync(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{this.mkdirSync(A)}catch(p){if(p.code==="EEXIST")continue;throw p}if(n??=A,r!=null&&this.chmodSync(A,r),o!=null)this.utimesSync(A,o[0],o[1]);else{let p=this.statSync(this.pathUtils.dirname(A));this.utimesSync(A,p.atime,p.mtime)}}}return n}async copyPromise(e,r,{baseFs:o=this,overwrite:a=!0,stableSort:n=!1,stableTime:u=!1,linkStrategy:A=null}={}){return await hY(this,e,o,r,{overwrite:a,stableSort:n,stableTime:u,linkStrategy:A})}copySync(e,r,{baseFs:o=this,overwrite:a=!0}={}){let n=o.lstatSync(r),u=this.existsSync(e);if(n.isDirectory()){this.mkdirpSync(e);let p=o.readdirSync(r);for(let h of p)this.copySync(this.pathUtils.join(e,h),o.pathUtils.join(r,h),{baseFs:o,overwrite:a})}else if(n.isFile()){if(!u||a){u&&this.removeSync(e);let p=o.readFileSync(r);this.writeFileSync(e,p)}}else if(n.isSymbolicLink()){if(!u||a){u&&this.removeSync(e);let p=o.readlinkSync(r);this.symlinkSync(ZD(this.pathUtils,p),e)}}else throw new Error(`Unsupported file type (file: ${r}, mode: 0o${n.mode.toString(8).padStart(6,"0")})`);let A=n.mode&511;this.chmodSync(e,A)}async changeFilePromise(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferPromise(e,r,o):this.changeFileTextPromise(e,r,o)}async changeFileBufferPromise(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=await this.readFilePromise(e)}catch{}Buffer.compare(a,r)!==0&&await this.writeFilePromise(e,r,{mode:o})}async changeFileTextPromise(e,r,{automaticNewlines:o,mode:a}={}){let n="";try{n=await this.readFilePromise(e,"utf8")}catch{}let u=o?G0(n,r):r;n!==u&&await this.writeFilePromise(e,u,{mode:a})}changeFileSync(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferSync(e,r,o):this.changeFileTextSync(e,r,o)}changeFileBufferSync(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=this.readFileSync(e)}catch{}Buffer.compare(a,r)!==0&&this.writeFileSync(e,r,{mode:o})}changeFileTextSync(e,r,{automaticNewlines:o=!1,mode:a}={}){let n="";try{n=this.readFileSync(e,"utf8")}catch{}let u=o?G0(n,r):r;n!==u&&this.writeFileSync(e,u,{mode:a})}async movePromise(e,r){try{await this.renamePromise(e,r)}catch(o){if(o.code==="EXDEV")await this.copyPromise(r,e),await this.removePromise(e);else throw o}}moveSync(e,r){try{this.renameSync(e,r)}catch(o){if(o.code==="EXDEV")this.copySync(r,e),this.removeSync(e);else throw o}}async lockPromise(e,r){let o=`${e}.flock`,a=1e3/60,n=Date.now(),u=null,A=async()=>{let p;try{[p]=await this.readJsonPromise(o)}catch{return Date.now()-n<500}try{return process.kill(p,0),!0}catch{return!1}};for(;u===null;)try{u=await this.openPromise(o,"wx")}catch(p){if(p.code==="EEXIST"){if(!await A())try{await this.unlinkPromise(o);continue}catch{}if(Date.now()-n<60*1e3)await new Promise(h=>setTimeout(h,a));else throw new Error(`Couldn't acquire a lock in a reasonable time (via ${o})`)}else throw p}await this.writePromise(u,JSON.stringify([process.pid]));try{return await r()}finally{try{await this.closePromise(u),await this.unlinkPromise(o)}catch{}}}async readJsonPromise(e){let r=await this.readFilePromise(e,"utf8");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}readJsonSync(e){let r=this.readFileSync(e,"utf8");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}async writeJsonPromise(e,r,{compact:o=!1}={}){let a=o?0:2;return await this.writeFilePromise(e,`${JSON.stringify(r,null,a)} +`)}writeJsonSync(e,r,{compact:o=!1}={}){let a=o?0:2;return this.writeFileSync(e,`${JSON.stringify(r,null,a)} +`)}async preserveTimePromise(e,r){let o=await this.lstatPromise(e),a=await r();typeof a<"u"&&(e=a),await this.lutimesPromise(e,o.atime,o.mtime)}async preserveTimeSync(e,r){let o=this.lstatSync(e),a=r();typeof a<"u"&&(e=a),this.lutimesSync(e,o.atime,o.mtime)}},qu=class extends hf{constructor(){super(K)}}});var Is,gf=wt(()=>{Y0();Is=class extends hf{getExtractHint(e){return this.baseFs.getExtractHint(e)}resolve(e){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(e)))}getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}async openPromise(e,r,o){return this.baseFs.openPromise(this.mapToBase(e),r,o)}openSync(e,r,o){return this.baseFs.openSync(this.mapToBase(e),r,o)}async opendirPromise(e,r){return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(e),r),{path:e})}opendirSync(e,r){return Object.assign(this.baseFs.opendirSync(this.mapToBase(e),r),{path:e})}async readPromise(e,r,o,a,n){return await this.baseFs.readPromise(e,r,o,a,n)}readSync(e,r,o,a,n){return this.baseFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return typeof r=="string"?await this.baseFs.writePromise(e,r,o):await this.baseFs.writePromise(e,r,o,a,n)}writeSync(e,r,o,a,n){return typeof r=="string"?this.baseFs.writeSync(e,r,o):this.baseFs.writeSync(e,r,o,a,n)}async closePromise(e){return this.baseFs.closePromise(e)}closeSync(e){this.baseFs.closeSync(e)}createReadStream(e,r){return this.baseFs.createReadStream(e!==null?this.mapToBase(e):e,r)}createWriteStream(e,r){return this.baseFs.createWriteStream(e!==null?this.mapToBase(e):e,r)}async realpathPromise(e){return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(e)))}realpathSync(e){return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(e)))}async existsPromise(e){return this.baseFs.existsPromise(this.mapToBase(e))}existsSync(e){return this.baseFs.existsSync(this.mapToBase(e))}accessSync(e,r){return this.baseFs.accessSync(this.mapToBase(e),r)}async accessPromise(e,r){return this.baseFs.accessPromise(this.mapToBase(e),r)}async statPromise(e,r){return this.baseFs.statPromise(this.mapToBase(e),r)}statSync(e,r){return this.baseFs.statSync(this.mapToBase(e),r)}async fstatPromise(e,r){return this.baseFs.fstatPromise(e,r)}fstatSync(e,r){return this.baseFs.fstatSync(e,r)}lstatPromise(e,r){return this.baseFs.lstatPromise(this.mapToBase(e),r)}lstatSync(e,r){return this.baseFs.lstatSync(this.mapToBase(e),r)}async fchmodPromise(e,r){return this.baseFs.fchmodPromise(e,r)}fchmodSync(e,r){return this.baseFs.fchmodSync(e,r)}async chmodPromise(e,r){return this.baseFs.chmodPromise(this.mapToBase(e),r)}chmodSync(e,r){return this.baseFs.chmodSync(this.mapToBase(e),r)}async fchownPromise(e,r,o){return this.baseFs.fchownPromise(e,r,o)}fchownSync(e,r,o){return this.baseFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return this.baseFs.chownPromise(this.mapToBase(e),r,o)}chownSync(e,r,o){return this.baseFs.chownSync(this.mapToBase(e),r,o)}async renamePromise(e,r){return this.baseFs.renamePromise(this.mapToBase(e),this.mapToBase(r))}renameSync(e,r){return this.baseFs.renameSync(this.mapToBase(e),this.mapToBase(r))}async copyFilePromise(e,r,o=0){return this.baseFs.copyFilePromise(this.mapToBase(e),this.mapToBase(r),o)}copyFileSync(e,r,o=0){return this.baseFs.copyFileSync(this.mapToBase(e),this.mapToBase(r),o)}async appendFilePromise(e,r,o){return this.baseFs.appendFilePromise(this.fsMapToBase(e),r,o)}appendFileSync(e,r,o){return this.baseFs.appendFileSync(this.fsMapToBase(e),r,o)}async writeFilePromise(e,r,o){return this.baseFs.writeFilePromise(this.fsMapToBase(e),r,o)}writeFileSync(e,r,o){return this.baseFs.writeFileSync(this.fsMapToBase(e),r,o)}async unlinkPromise(e){return this.baseFs.unlinkPromise(this.mapToBase(e))}unlinkSync(e){return this.baseFs.unlinkSync(this.mapToBase(e))}async utimesPromise(e,r,o){return this.baseFs.utimesPromise(this.mapToBase(e),r,o)}utimesSync(e,r,o){return this.baseFs.utimesSync(this.mapToBase(e),r,o)}async lutimesPromise(e,r,o){return this.baseFs.lutimesPromise(this.mapToBase(e),r,o)}lutimesSync(e,r,o){return this.baseFs.lutimesSync(this.mapToBase(e),r,o)}async mkdirPromise(e,r){return this.baseFs.mkdirPromise(this.mapToBase(e),r)}mkdirSync(e,r){return this.baseFs.mkdirSync(this.mapToBase(e),r)}async rmdirPromise(e,r){return this.baseFs.rmdirPromise(this.mapToBase(e),r)}rmdirSync(e,r){return this.baseFs.rmdirSync(this.mapToBase(e),r)}async rmPromise(e,r){return this.baseFs.rmPromise(this.mapToBase(e),r)}rmSync(e,r){return this.baseFs.rmSync(this.mapToBase(e),r)}async linkPromise(e,r){return this.baseFs.linkPromise(this.mapToBase(e),this.mapToBase(r))}linkSync(e,r){return this.baseFs.linkSync(this.mapToBase(e),this.mapToBase(r))}async symlinkPromise(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkPromise(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkPromise(u,a,o)}symlinkSync(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkSync(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkSync(u,a,o)}async readFilePromise(e,r){return this.baseFs.readFilePromise(this.fsMapToBase(e),r)}readFileSync(e,r){return this.baseFs.readFileSync(this.fsMapToBase(e),r)}readdirPromise(e,r){return this.baseFs.readdirPromise(this.mapToBase(e),r)}readdirSync(e,r){return this.baseFs.readdirSync(this.mapToBase(e),r)}async readlinkPromise(e){return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(e)))}readlinkSync(e){return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(e)))}async truncatePromise(e,r){return this.baseFs.truncatePromise(this.mapToBase(e),r)}truncateSync(e,r){return this.baseFs.truncateSync(this.mapToBase(e),r)}async ftruncatePromise(e,r){return this.baseFs.ftruncatePromise(e,r)}ftruncateSync(e,r){return this.baseFs.ftruncateSync(e,r)}watch(e,r,o){return this.baseFs.watch(this.mapToBase(e),r,o)}watchFile(e,r,o){return this.baseFs.watchFile(this.mapToBase(e),r,o)}unwatchFile(e,r){return this.baseFs.unwatchFile(this.mapToBase(e),r)}fsMapToBase(e){return typeof e=="number"?e:this.mapToBase(e)}}});var ju,IY=wt(()=>{gf();ju=class extends Is{constructor(e,{baseFs:r,pathUtils:o}){super(o),this.target=e,this.baseFs=r}getRealPath(){return this.target}getBaseFs(){return this.baseFs}mapFromBase(e){return e}mapToBase(e){return e}}});function BY(t){let e=t;return typeof t.path=="string"&&(e.path=Ae.toPortablePath(t.path)),e}var vY,_n,W0=wt(()=>{vY=et(ve("fs"));Y0();Ba();_n=class extends qu{constructor(e=vY.default){super(),this.realFs=e}getExtractHint(){return!1}getRealPath(){return Bt.root}resolve(e){return K.resolve(e)}async openPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.open(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}openSync(e,r,o){return this.realFs.openSync(Ae.fromPortablePath(e),r,o)}async opendirPromise(e,r){return await new Promise((o,a)=>{typeof r<"u"?this.realFs.opendir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.opendir(Ae.fromPortablePath(e),this.makeCallback(o,a))}).then(o=>{let a=o;return Object.defineProperty(a,"path",{value:e,configurable:!0,writable:!0}),a})}opendirSync(e,r){let a=typeof r<"u"?this.realFs.opendirSync(Ae.fromPortablePath(e),r):this.realFs.opendirSync(Ae.fromPortablePath(e));return Object.defineProperty(a,"path",{value:e,configurable:!0,writable:!0}),a}async readPromise(e,r,o=0,a=0,n=-1){return await new Promise((u,A)=>{this.realFs.read(e,r,o,a,n,(p,h)=>{p?A(p):u(h)})})}readSync(e,r,o,a,n){return this.realFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return await new Promise((u,A)=>typeof r=="string"?this.realFs.write(e,r,o,this.makeCallback(u,A)):this.realFs.write(e,r,o,a,n,this.makeCallback(u,A)))}writeSync(e,r,o,a,n){return typeof r=="string"?this.realFs.writeSync(e,r,o):this.realFs.writeSync(e,r,o,a,n)}async closePromise(e){await new Promise((r,o)=>{this.realFs.close(e,this.makeCallback(r,o))})}closeSync(e){this.realFs.closeSync(e)}createReadStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return this.realFs.createReadStream(o,r)}createWriteStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return this.realFs.createWriteStream(o,r)}async realpathPromise(e){return await new Promise((r,o)=>{this.realFs.realpath(Ae.fromPortablePath(e),{},this.makeCallback(r,o))}).then(r=>Ae.toPortablePath(r))}realpathSync(e){return Ae.toPortablePath(this.realFs.realpathSync(Ae.fromPortablePath(e),{}))}async existsPromise(e){return await new Promise(r=>{this.realFs.exists(Ae.fromPortablePath(e),r)})}accessSync(e,r){return this.realFs.accessSync(Ae.fromPortablePath(e),r)}async accessPromise(e,r){return await new Promise((o,a)=>{this.realFs.access(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}existsSync(e){return this.realFs.existsSync(Ae.fromPortablePath(e))}async statPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.stat(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.stat(Ae.fromPortablePath(e),this.makeCallback(o,a))})}statSync(e,r){return r?this.realFs.statSync(Ae.fromPortablePath(e),r):this.realFs.statSync(Ae.fromPortablePath(e))}async fstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.fstat(e,r,this.makeCallback(o,a)):this.realFs.fstat(e,this.makeCallback(o,a))})}fstatSync(e,r){return r?this.realFs.fstatSync(e,r):this.realFs.fstatSync(e)}async lstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.lstat(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.lstat(Ae.fromPortablePath(e),this.makeCallback(o,a))})}lstatSync(e,r){return r?this.realFs.lstatSync(Ae.fromPortablePath(e),r):this.realFs.lstatSync(Ae.fromPortablePath(e))}async fchmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.fchmod(e,r,this.makeCallback(o,a))})}fchmodSync(e,r){return this.realFs.fchmodSync(e,r)}async chmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.chmod(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}chmodSync(e,r){return this.realFs.chmodSync(Ae.fromPortablePath(e),r)}async fchownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.fchown(e,r,o,this.makeCallback(a,n))})}fchownSync(e,r,o){return this.realFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.chown(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}chownSync(e,r,o){return this.realFs.chownSync(Ae.fromPortablePath(e),r,o)}async renamePromise(e,r){return await new Promise((o,a)=>{this.realFs.rename(Ae.fromPortablePath(e),Ae.fromPortablePath(r),this.makeCallback(o,a))})}renameSync(e,r){return this.realFs.renameSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r))}async copyFilePromise(e,r,o=0){return await new Promise((a,n)=>{this.realFs.copyFile(Ae.fromPortablePath(e),Ae.fromPortablePath(r),o,this.makeCallback(a,n))})}copyFileSync(e,r,o=0){return this.realFs.copyFileSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r),o)}async appendFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e=="string"?Ae.fromPortablePath(e):e;o?this.realFs.appendFile(u,r,o,this.makeCallback(a,n)):this.realFs.appendFile(u,r,this.makeCallback(a,n))})}appendFileSync(e,r,o){let a=typeof e=="string"?Ae.fromPortablePath(e):e;o?this.realFs.appendFileSync(a,r,o):this.realFs.appendFileSync(a,r)}async writeFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e=="string"?Ae.fromPortablePath(e):e;o?this.realFs.writeFile(u,r,o,this.makeCallback(a,n)):this.realFs.writeFile(u,r,this.makeCallback(a,n))})}writeFileSync(e,r,o){let a=typeof e=="string"?Ae.fromPortablePath(e):e;o?this.realFs.writeFileSync(a,r,o):this.realFs.writeFileSync(a,r)}async unlinkPromise(e){return await new Promise((r,o)=>{this.realFs.unlink(Ae.fromPortablePath(e),this.makeCallback(r,o))})}unlinkSync(e){return this.realFs.unlinkSync(Ae.fromPortablePath(e))}async utimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.utimes(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}utimesSync(e,r,o){this.realFs.utimesSync(Ae.fromPortablePath(e),r,o)}async lutimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.lutimes(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}lutimesSync(e,r,o){this.realFs.lutimesSync(Ae.fromPortablePath(e),r,o)}async mkdirPromise(e,r){return await new Promise((o,a)=>{this.realFs.mkdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}mkdirSync(e,r){return this.realFs.mkdirSync(Ae.fromPortablePath(e),r)}async rmdirPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rmdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rmdir(Ae.fromPortablePath(e),this.makeCallback(o,a))})}rmdirSync(e,r){return this.realFs.rmdirSync(Ae.fromPortablePath(e),r)}async rmPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rm(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rm(Ae.fromPortablePath(e),this.makeCallback(o,a))})}rmSync(e,r){return this.realFs.rmSync(Ae.fromPortablePath(e),r)}async linkPromise(e,r){return await new Promise((o,a)=>{this.realFs.link(Ae.fromPortablePath(e),Ae.fromPortablePath(r),this.makeCallback(o,a))})}linkSync(e,r){return this.realFs.linkSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r))}async symlinkPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.symlink(Ae.fromPortablePath(e.replace(/\/+$/,"")),Ae.fromPortablePath(r),o,this.makeCallback(a,n))})}symlinkSync(e,r,o){return this.realFs.symlinkSync(Ae.fromPortablePath(e.replace(/\/+$/,"")),Ae.fromPortablePath(r),o)}async readFilePromise(e,r){return await new Promise((o,a)=>{let n=typeof e=="string"?Ae.fromPortablePath(e):e;this.realFs.readFile(n,r,this.makeCallback(o,a))})}readFileSync(e,r){let o=typeof e=="string"?Ae.fromPortablePath(e):e;return this.realFs.readFileSync(o,r)}async readdirPromise(e,r){return await new Promise((o,a)=>{r?r.recursive&&process.platform==="win32"?r.withFileTypes?this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(BY)),a)):this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(Ae.toPortablePath)),a)):this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.readdir(Ae.fromPortablePath(e),this.makeCallback(o,a))})}readdirSync(e,r){return r?r.recursive&&process.platform==="win32"?r.withFileTypes?this.realFs.readdirSync(Ae.fromPortablePath(e),r).map(BY):this.realFs.readdirSync(Ae.fromPortablePath(e),r).map(Ae.toPortablePath):this.realFs.readdirSync(Ae.fromPortablePath(e),r):this.realFs.readdirSync(Ae.fromPortablePath(e))}async readlinkPromise(e){return await new Promise((r,o)=>{this.realFs.readlink(Ae.fromPortablePath(e),this.makeCallback(r,o))}).then(r=>Ae.toPortablePath(r))}readlinkSync(e){return Ae.toPortablePath(this.realFs.readlinkSync(Ae.fromPortablePath(e)))}async truncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.truncate(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}truncateSync(e,r){return this.realFs.truncateSync(Ae.fromPortablePath(e),r)}async ftruncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.ftruncate(e,r,this.makeCallback(o,a))})}ftruncateSync(e,r){return this.realFs.ftruncateSync(e,r)}watch(e,r,o){return this.realFs.watch(Ae.fromPortablePath(e),r,o)}watchFile(e,r,o){return this.realFs.watchFile(Ae.fromPortablePath(e),r,o)}unwatchFile(e,r){return this.realFs.unwatchFile(Ae.fromPortablePath(e),r)}makeCallback(e,r){return(o,a)=>{o?r(o):e(a)}}}});var En,DY=wt(()=>{W0();gf();Ba();En=class extends Is{constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils.normalize(e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.target)}resolve(e){return this.pathUtils.isAbsolute(e)?K.normalize(e):this.baseFs.resolve(K.join(this.target,e))}mapFromBase(e){return e}mapToBase(e){return this.pathUtils.isAbsolute(e)?e:this.pathUtils.join(this.target,e)}}});var PY,Gu,SY=wt(()=>{W0();gf();Ba();PY=Bt.root,Gu=class extends Is{constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils.resolve(Bt.root,e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.pathUtils.relative(Bt.root,this.target))}getTarget(){return this.target}getBaseFs(){return this.baseFs}mapToBase(e){let r=this.pathUtils.normalize(e);if(this.pathUtils.isAbsolute(e))return this.pathUtils.resolve(this.target,this.pathUtils.relative(PY,e));if(r.match(/^\.\.\/?/))throw new Error(`Resolving this path (${e}) would escape the jail`);return this.pathUtils.resolve(this.target,e)}mapFromBase(e){return this.pathUtils.resolve(PY,this.pathUtils.relative(this.target,e))}}});var Am,bY=wt(()=>{gf();Am=class extends Is{constructor(r,o){super(o);this.instance=null;this.factory=r}get baseFs(){return this.instance||(this.instance=this.factory()),this.instance}set baseFs(r){this.instance=r}mapFromBase(r){return r}mapToBase(r){return r}}});var K0,va,Gp,xY=wt(()=>{K0=ve("fs");Y0();W0();DT();JD();Ba();va=4278190080,Gp=class extends qu{constructor({baseFs:r=new _n,filter:o=null,magicByte:a=42,maxOpenFiles:n=1/0,useCache:u=!0,maxAge:A=5e3,typeCheck:p=K0.constants.S_IFREG,getMountPoint:h,factoryPromise:E,factorySync:I}){if(Math.floor(a)!==a||!(a>1&&a<=127))throw new Error("The magic byte must be set to a round value between 1 and 127 included");super();this.fdMap=new Map;this.nextFd=3;this.isMount=new Set;this.notMount=new Set;this.realPaths=new Map;this.limitOpenFilesTimeout=null;this.baseFs=r,this.mountInstances=u?new Map:null,this.factoryPromise=E,this.factorySync=I,this.filter=o,this.getMountPoint=h,this.magic=a<<24,this.maxAge=A,this.maxOpenFiles=n,this.typeCheck=p}getExtractHint(r){return this.baseFs.getExtractHint(r)}getRealPath(){return this.baseFs.getRealPath()}saveAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.saveAndClose?.(),this.mountInstances.delete(r)}discardAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.discardAndClose?.(),this.mountInstances.delete(r)}resolve(r){return this.baseFs.resolve(r)}remapFd(r,o){let a=this.nextFd++|this.magic;return this.fdMap.set(a,[r,o]),a}async openPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.openPromise(r,o,a),async(n,{subPath:u})=>this.remapFd(n,await n.openPromise(u,o,a)))}openSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.openSync(r,o,a),(n,{subPath:u})=>this.remapFd(n,n.openSync(u,o,a)))}async opendirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.opendirPromise(r,o),async(a,{subPath:n})=>await a.opendirPromise(n,o),{requireSubpath:!1})}opendirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.opendirSync(r,o),(a,{subPath:n})=>a.opendirSync(n,o),{requireSubpath:!1})}async readPromise(r,o,a,n,u){if((r&va)!==this.magic)return await this.baseFs.readPromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw ho("read");let[p,h]=A;return await p.readPromise(h,o,a,n,u)}readSync(r,o,a,n,u){if((r&va)!==this.magic)return this.baseFs.readSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw ho("readSync");let[p,h]=A;return p.readSync(h,o,a,n,u)}async writePromise(r,o,a,n,u){if((r&va)!==this.magic)return typeof o=="string"?await this.baseFs.writePromise(r,o,a):await this.baseFs.writePromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw ho("write");let[p,h]=A;return typeof o=="string"?await p.writePromise(h,o,a):await p.writePromise(h,o,a,n,u)}writeSync(r,o,a,n,u){if((r&va)!==this.magic)return typeof o=="string"?this.baseFs.writeSync(r,o,a):this.baseFs.writeSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw ho("writeSync");let[p,h]=A;return typeof o=="string"?p.writeSync(h,o,a):p.writeSync(h,o,a,n,u)}async closePromise(r){if((r&va)!==this.magic)return await this.baseFs.closePromise(r);let o=this.fdMap.get(r);if(typeof o>"u")throw ho("close");this.fdMap.delete(r);let[a,n]=o;return await a.closePromise(n)}closeSync(r){if((r&va)!==this.magic)return this.baseFs.closeSync(r);let o=this.fdMap.get(r);if(typeof o>"u")throw ho("closeSync");this.fdMap.delete(r);let[a,n]=o;return a.closeSync(n)}createReadStream(r,o){return r===null?this.baseFs.createReadStream(r,o):this.makeCallSync(r,()=>this.baseFs.createReadStream(r,o),(a,{archivePath:n,subPath:u})=>{let A=a.createReadStream(u,o);return A.path=Ae.fromPortablePath(this.pathUtils.join(n,u)),A})}createWriteStream(r,o){return r===null?this.baseFs.createWriteStream(r,o):this.makeCallSync(r,()=>this.baseFs.createWriteStream(r,o),(a,{subPath:n})=>a.createWriteStream(n,o))}async realpathPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.realpathPromise(r),async(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>"u"&&(u=await this.baseFs.realpathPromise(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(Bt.root,await o.realpathPromise(n)))})}realpathSync(r){return this.makeCallSync(r,()=>this.baseFs.realpathSync(r),(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>"u"&&(u=this.baseFs.realpathSync(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(Bt.root,o.realpathSync(n)))})}async existsPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.existsPromise(r),async(o,{subPath:a})=>await o.existsPromise(a))}existsSync(r){return this.makeCallSync(r,()=>this.baseFs.existsSync(r),(o,{subPath:a})=>o.existsSync(a))}async accessPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.accessPromise(r,o),async(a,{subPath:n})=>await a.accessPromise(n,o))}accessSync(r,o){return this.makeCallSync(r,()=>this.baseFs.accessSync(r,o),(a,{subPath:n})=>a.accessSync(n,o))}async statPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.statPromise(r,o),async(a,{subPath:n})=>await a.statPromise(n,o))}statSync(r,o){return this.makeCallSync(r,()=>this.baseFs.statSync(r,o),(a,{subPath:n})=>a.statSync(n,o))}async fstatPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fstatPromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("fstat");let[n,u]=a;return n.fstatPromise(u,o)}fstatSync(r,o){if((r&va)!==this.magic)return this.baseFs.fstatSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("fstatSync");let[n,u]=a;return n.fstatSync(u,o)}async lstatPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.lstatPromise(r,o),async(a,{subPath:n})=>await a.lstatPromise(n,o))}lstatSync(r,o){return this.makeCallSync(r,()=>this.baseFs.lstatSync(r,o),(a,{subPath:n})=>a.lstatSync(n,o))}async fchmodPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fchmodPromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("fchmod");let[n,u]=a;return n.fchmodPromise(u,o)}fchmodSync(r,o){if((r&va)!==this.magic)return this.baseFs.fchmodSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("fchmodSync");let[n,u]=a;return n.fchmodSync(u,o)}async chmodPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.chmodPromise(r,o),async(a,{subPath:n})=>await a.chmodPromise(n,o))}chmodSync(r,o){return this.makeCallSync(r,()=>this.baseFs.chmodSync(r,o),(a,{subPath:n})=>a.chmodSync(n,o))}async fchownPromise(r,o,a){if((r&va)!==this.magic)return this.baseFs.fchownPromise(r,o,a);let n=this.fdMap.get(r);if(typeof n>"u")throw ho("fchown");let[u,A]=n;return u.fchownPromise(A,o,a)}fchownSync(r,o,a){if((r&va)!==this.magic)return this.baseFs.fchownSync(r,o,a);let n=this.fdMap.get(r);if(typeof n>"u")throw ho("fchownSync");let[u,A]=n;return u.fchownSync(A,o,a)}async chownPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.chownPromise(r,o,a),async(n,{subPath:u})=>await n.chownPromise(u,o,a))}chownSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.chownSync(r,o,a),(n,{subPath:u})=>n.chownSync(u,o,a))}async renamePromise(r,o){return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.renamePromise(r,o),async()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})}),async(a,{subPath:n})=>await this.makeCallPromise(o,async()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})},async(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"});return await a.renamePromise(n,A)}))}renameSync(r,o){return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.renameSync(r,o),()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})}),(a,{subPath:n})=>this.makeCallSync(o,()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})},(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"});return a.renameSync(n,A)}))}async copyFilePromise(r,o,a=0){let n=async(u,A,p,h)=>{if(a&K0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:"EXDEV"});if(a&K0.constants.COPYFILE_EXCL&&await this.existsPromise(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:"EEXIST"});let E;try{E=await u.readFilePromise(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:"EINVAL"})}await p.writeFilePromise(h,E)};return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.copyFilePromise(r,o,a),async(u,{subPath:A})=>await n(this.baseFs,r,u,A)),async(u,{subPath:A})=>await this.makeCallPromise(o,async()=>await n(u,A,this.baseFs,o),async(p,{subPath:h})=>u!==p?await n(u,A,p,h):await u.copyFilePromise(A,h,a)))}copyFileSync(r,o,a=0){let n=(u,A,p,h)=>{if(a&K0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:"EXDEV"});if(a&K0.constants.COPYFILE_EXCL&&this.existsSync(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:"EEXIST"});let E;try{E=u.readFileSync(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:"EINVAL"})}p.writeFileSync(h,E)};return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.copyFileSync(r,o,a),(u,{subPath:A})=>n(this.baseFs,r,u,A)),(u,{subPath:A})=>this.makeCallSync(o,()=>n(u,A,this.baseFs,o),(p,{subPath:h})=>u!==p?n(u,A,p,h):u.copyFileSync(A,h,a)))}async appendFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.appendFilePromise(r,o,a),async(n,{subPath:u})=>await n.appendFilePromise(u,o,a))}appendFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.appendFileSync(r,o,a),(n,{subPath:u})=>n.appendFileSync(u,o,a))}async writeFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.writeFilePromise(r,o,a),async(n,{subPath:u})=>await n.writeFilePromise(u,o,a))}writeFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.writeFileSync(r,o,a),(n,{subPath:u})=>n.writeFileSync(u,o,a))}async unlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.unlinkPromise(r),async(o,{subPath:a})=>await o.unlinkPromise(a))}unlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.unlinkSync(r),(o,{subPath:a})=>o.unlinkSync(a))}async utimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.utimesPromise(r,o,a),async(n,{subPath:u})=>await n.utimesPromise(u,o,a))}utimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.utimesSync(r,o,a),(n,{subPath:u})=>n.utimesSync(u,o,a))}async lutimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.lutimesPromise(r,o,a),async(n,{subPath:u})=>await n.lutimesPromise(u,o,a))}lutimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.lutimesSync(r,o,a),(n,{subPath:u})=>n.lutimesSync(u,o,a))}async mkdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.mkdirPromise(r,o),async(a,{subPath:n})=>await a.mkdirPromise(n,o))}mkdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.mkdirSync(r,o),(a,{subPath:n})=>a.mkdirSync(n,o))}async rmdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmdirPromise(r,o),async(a,{subPath:n})=>await a.rmdirPromise(n,o))}rmdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmdirSync(r,o),(a,{subPath:n})=>a.rmdirSync(n,o))}async rmPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmPromise(r,o),async(a,{subPath:n})=>await a.rmPromise(n,o))}rmSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmSync(r,o),(a,{subPath:n})=>a.rmSync(n,o))}async linkPromise(r,o){return await this.makeCallPromise(o,async()=>await this.baseFs.linkPromise(r,o),async(a,{subPath:n})=>await a.linkPromise(r,n))}linkSync(r,o){return this.makeCallSync(o,()=>this.baseFs.linkSync(r,o),(a,{subPath:n})=>a.linkSync(r,n))}async symlinkPromise(r,o,a){return await this.makeCallPromise(o,async()=>await this.baseFs.symlinkPromise(r,o,a),async(n,{subPath:u})=>await n.symlinkPromise(r,u))}symlinkSync(r,o,a){return this.makeCallSync(o,()=>this.baseFs.symlinkSync(r,o,a),(n,{subPath:u})=>n.symlinkSync(r,u))}async readFilePromise(r,o){return this.makeCallPromise(r,async()=>await this.baseFs.readFilePromise(r,o),async(a,{subPath:n})=>await a.readFilePromise(n,o))}readFileSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readFileSync(r,o),(a,{subPath:n})=>a.readFileSync(n,o))}async readdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.readdirPromise(r,o),async(a,{subPath:n})=>await a.readdirPromise(n,o),{requireSubpath:!1})}readdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readdirSync(r,o),(a,{subPath:n})=>a.readdirSync(n,o),{requireSubpath:!1})}async readlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.readlinkPromise(r),async(o,{subPath:a})=>await o.readlinkPromise(a))}readlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.readlinkSync(r),(o,{subPath:a})=>o.readlinkSync(a))}async truncatePromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.truncatePromise(r,o),async(a,{subPath:n})=>await a.truncatePromise(n,o))}truncateSync(r,o){return this.makeCallSync(r,()=>this.baseFs.truncateSync(r,o),(a,{subPath:n})=>a.truncateSync(n,o))}async ftruncatePromise(r,o){if((r&va)!==this.magic)return this.baseFs.ftruncatePromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("ftruncate");let[n,u]=a;return n.ftruncatePromise(u,o)}ftruncateSync(r,o){if((r&va)!==this.magic)return this.baseFs.ftruncateSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw ho("ftruncateSync");let[n,u]=a;return n.ftruncateSync(u,o)}watch(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watch(r,o,a),(n,{subPath:u})=>n.watch(u,o,a))}watchFile(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watchFile(r,o,a),()=>um(this,r,o,a))}unwatchFile(r,o){return this.makeCallSync(r,()=>this.baseFs.unwatchFile(r,o),()=>q0(this,r,o))}async makeCallPromise(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="string")return await o();let u=this.resolve(r),A=this.findMount(u);return A?n&&A.subPath==="/"?await o():await this.getMountPromise(A.archivePath,async p=>await a(p,A)):await o()}makeCallSync(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="string")return o();let u=this.resolve(r),A=this.findMount(u);return!A||n&&A.subPath==="/"?o():this.getMountSync(A.archivePath,p=>a(p,A))}findMount(r){if(this.filter&&!this.filter.test(r))return null;let o="";for(;;){let a=r.substring(o.length),n=this.getMountPoint(a,o);if(!n)return null;if(o=this.pathUtils.join(o,n),!this.isMount.has(o)){if(this.notMount.has(o))continue;try{if(this.typeCheck!==null&&(this.baseFs.lstatSync(o).mode&K0.constants.S_IFMT)!==this.typeCheck){this.notMount.add(o);continue}}catch{return null}this.isMount.add(o)}return{archivePath:o,subPath:this.pathUtils.join(Bt.root,r.substring(o.length))}}}limitOpenFiles(r){if(this.mountInstances===null)return;let o=Date.now(),a=o+this.maxAge,n=r===null?0:this.mountInstances.size-r;for(let[u,{childFs:A,expiresAt:p,refCount:h}]of this.mountInstances.entries())if(!(h!==0||A.hasOpenFileHandles?.())){if(o>=p){A.saveAndClose?.(),this.mountInstances.delete(u),n-=1;continue}else if(r===null||n<=0){a=p;break}A.saveAndClose?.(),this.mountInstances.delete(u),n-=1}this.limitOpenFilesTimeout===null&&(r===null&&this.mountInstances.size>0||r!==null)&&isFinite(a)&&(this.limitOpenFilesTimeout=setTimeout(()=>{this.limitOpenFilesTimeout=null,this.limitOpenFiles(null)},a-o).unref())}async getMountPromise(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);if(!a){let n=await this.factoryPromise(this.baseFs,r);a=this.mountInstances.get(r),a||(a={childFs:n(),expiresAt:0,refCount:0})}this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,a.refCount+=1;try{return await o(a.childFs)}finally{a.refCount-=1}}else{let a=(await this.factoryPromise(this.baseFs,r))();try{return await o(a)}finally{a.saveAndClose?.()}}}getMountSync(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);return a||(a={childFs:this.factorySync(this.baseFs,r),expiresAt:0,refCount:0}),this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,o(a.childFs)}else{let a=this.factorySync(this.baseFs,r);try{return o(a)}finally{a.saveAndClose?.()}}}}});var $t,nP,kY=wt(()=>{Y0();Ba();$t=()=>Object.assign(new Error("ENOSYS: unsupported filesystem access"),{code:"ENOSYS"}),nP=class t extends hf{static{this.instance=new t}constructor(){super(K)}getExtractHint(){throw $t()}getRealPath(){throw $t()}resolve(){throw $t()}async openPromise(){throw $t()}openSync(){throw $t()}async opendirPromise(){throw $t()}opendirSync(){throw $t()}async readPromise(){throw $t()}readSync(){throw $t()}async writePromise(){throw $t()}writeSync(){throw $t()}async closePromise(){throw $t()}closeSync(){throw $t()}createWriteStream(){throw $t()}createReadStream(){throw $t()}async realpathPromise(){throw $t()}realpathSync(){throw $t()}async readdirPromise(){throw $t()}readdirSync(){throw $t()}async existsPromise(e){throw $t()}existsSync(e){throw $t()}async accessPromise(){throw $t()}accessSync(){throw $t()}async statPromise(){throw $t()}statSync(){throw $t()}async fstatPromise(e){throw $t()}fstatSync(e){throw $t()}async lstatPromise(e){throw $t()}lstatSync(e){throw $t()}async fchmodPromise(){throw $t()}fchmodSync(){throw $t()}async chmodPromise(){throw $t()}chmodSync(){throw $t()}async fchownPromise(){throw $t()}fchownSync(){throw $t()}async chownPromise(){throw $t()}chownSync(){throw $t()}async mkdirPromise(){throw $t()}mkdirSync(){throw $t()}async rmdirPromise(){throw $t()}rmdirSync(){throw $t()}async rmPromise(){throw $t()}rmSync(){throw $t()}async linkPromise(){throw $t()}linkSync(){throw $t()}async symlinkPromise(){throw $t()}symlinkSync(){throw $t()}async renamePromise(){throw $t()}renameSync(){throw $t()}async copyFilePromise(){throw $t()}copyFileSync(){throw $t()}async appendFilePromise(){throw $t()}appendFileSync(){throw $t()}async writeFilePromise(){throw $t()}writeFileSync(){throw $t()}async unlinkPromise(){throw $t()}unlinkSync(){throw $t()}async utimesPromise(){throw $t()}utimesSync(){throw $t()}async lutimesPromise(){throw $t()}lutimesSync(){throw $t()}async readFilePromise(){throw $t()}readFileSync(){throw $t()}async readlinkPromise(){throw $t()}readlinkSync(){throw $t()}async truncatePromise(){throw $t()}truncateSync(){throw $t()}async ftruncatePromise(e,r){throw $t()}ftruncateSync(e,r){throw $t()}watch(){throw $t()}watchFile(){throw $t()}unwatchFile(){throw $t()}}});var Yp,QY=wt(()=>{gf();Ba();Yp=class extends Is{constructor(e){super(Ae),this.baseFs=e}mapFromBase(e){return Ae.fromPortablePath(e)}mapToBase(e){return Ae.toPortablePath(e)}}});var C_e,PT,w_e,qs,FY=wt(()=>{W0();gf();Ba();C_e=/^[0-9]+$/,PT=/^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/,w_e=/^([^/]+-)?[a-f0-9]+$/,qs=class t extends Is{static makeVirtualPath(e,r,o){if(K.basename(e)!=="__virtual__")throw new Error('Assertion failed: Virtual folders must be named "__virtual__"');if(!K.basename(r).match(w_e))throw new Error("Assertion failed: Virtual components must be ended by an hexadecimal hash");let n=K.relative(K.dirname(e),o).split("/"),u=0;for(;u{ST=et(ve("buffer")),RY=ve("url"),TY=ve("util");gf();Ba();iP=class extends Is{constructor(e){super(Ae),this.baseFs=e}mapFromBase(e){return e}mapToBase(e){if(typeof e=="string")return e;if(e instanceof URL)return(0,RY.fileURLToPath)(e);if(Buffer.isBuffer(e)){let r=e.toString();if(!I_e(e,r))throw new Error("Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942");return r}throw new Error(`Unsupported path type: ${(0,TY.inspect)(e)}`)}}});var _Y,go,df,Wp,sP,oP,fm,_c,Hc,LY,MY,OY,UY,cI,HY=wt(()=>{_Y=ve("readline"),go=Symbol("kBaseFs"),df=Symbol("kFd"),Wp=Symbol("kClosePromise"),sP=Symbol("kCloseResolve"),oP=Symbol("kCloseReject"),fm=Symbol("kRefs"),_c=Symbol("kRef"),Hc=Symbol("kUnref"),cI=class{constructor(e,r){this[UY]=1;this[OY]=void 0;this[MY]=void 0;this[LY]=void 0;this[go]=r,this[df]=e}get fd(){return this[df]}async appendFile(e,r){try{this[_c](this.appendFile);let o=(typeof r=="string"?r:r?.encoding)??void 0;return await this[go].appendFilePromise(this.fd,e,o?{encoding:o}:void 0)}finally{this[Hc]()}}async chown(e,r){try{return this[_c](this.chown),await this[go].fchownPromise(this.fd,e,r)}finally{this[Hc]()}}async chmod(e){try{return this[_c](this.chmod),await this[go].fchmodPromise(this.fd,e)}finally{this[Hc]()}}createReadStream(e){return this[go].createReadStream(null,{...e,fd:this.fd})}createWriteStream(e){return this[go].createWriteStream(null,{...e,fd:this.fd})}datasync(){throw new Error("Method not implemented.")}sync(){throw new Error("Method not implemented.")}async read(e,r,o,a){try{this[_c](this.read);let n;return Buffer.isBuffer(e)?n=e:(e??={},n=e.buffer??Buffer.alloc(16384),r=e.offset||0,o=e.length??n.byteLength,a=e.position??null),r??=0,o??=0,o===0?{bytesRead:o,buffer:n}:{bytesRead:await this[go].readPromise(this.fd,n,r,o,a),buffer:n}}finally{this[Hc]()}}async readFile(e){try{this[_c](this.readFile);let r=(typeof e=="string"?e:e?.encoding)??void 0;return await this[go].readFilePromise(this.fd,r)}finally{this[Hc]()}}readLines(e){return(0,_Y.createInterface)({input:this.createReadStream(e),crlfDelay:1/0})}async stat(e){try{return this[_c](this.stat),await this[go].fstatPromise(this.fd,e)}finally{this[Hc]()}}async truncate(e){try{return this[_c](this.truncate),await this[go].ftruncatePromise(this.fd,e)}finally{this[Hc]()}}utimes(e,r){throw new Error("Method not implemented.")}async writeFile(e,r){try{this[_c](this.writeFile);let o=(typeof r=="string"?r:r?.encoding)??void 0;await this[go].writeFilePromise(this.fd,e,o)}finally{this[Hc]()}}async write(...e){try{if(this[_c](this.write),ArrayBuffer.isView(e[0])){let[r,o,a,n]=e;return{bytesWritten:await this[go].writePromise(this.fd,r,o??void 0,a??void 0,n??void 0),buffer:r}}else{let[r,o,a]=e;return{bytesWritten:await this[go].writePromise(this.fd,r,o,a),buffer:r}}}finally{this[Hc]()}}async writev(e,r){try{this[_c](this.writev);let o=0;if(typeof r<"u")for(let a of e){let n=await this.write(a,void 0,void 0,r);o+=n.bytesWritten,r+=n.bytesWritten}else for(let a of e){let n=await this.write(a);o+=n.bytesWritten}return{buffers:e,bytesWritten:o}}finally{this[Hc]()}}readv(e,r){throw new Error("Method not implemented.")}close(){if(this[df]===-1)return Promise.resolve();if(this[Wp])return this[Wp];if(this[fm]--,this[fm]===0){let e=this[df];this[df]=-1,this[Wp]=this[go].closePromise(e).finally(()=>{this[Wp]=void 0})}else this[Wp]=new Promise((e,r)=>{this[sP]=e,this[oP]=r}).finally(()=>{this[Wp]=void 0,this[oP]=void 0,this[sP]=void 0});return this[Wp]}[(go,df,UY=fm,OY=Wp,MY=sP,LY=oP,_c)](e){if(this[df]===-1){let r=new Error("file closed");throw r.code="EBADF",r.syscall=e.name,r}this[fm]++}[Hc](){if(this[fm]--,this[fm]===0){let e=this[df];this[df]=-1,this[go].closePromise(e).then(this[sP],this[oP])}}}});function uI(t,e){e=new iP(e);let r=(o,a,n)=>{let u=o[a];o[a]=n,typeof u?.[pm.promisify.custom]<"u"&&(n[pm.promisify.custom]=u[pm.promisify.custom])};{r(t,"exists",(o,...a)=>{let u=typeof a[a.length-1]=="function"?a.pop():()=>{};process.nextTick(()=>{e.existsPromise(o).then(A=>{u(A)},()=>{u(!1)})})}),r(t,"read",(...o)=>{let[a,n,u,A,p,h]=o;if(o.length<=3){let E={};o.length<3?h=o[1]:(E=o[1],h=o[2]),{buffer:n=Buffer.alloc(16384),offset:u=0,length:A=n.byteLength,position:p}=E}if(u==null&&(u=0),A|=0,A===0){process.nextTick(()=>{h(null,0,n)});return}p==null&&(p=-1),process.nextTick(()=>{e.readPromise(a,n,u,A,p).then(E=>{h(null,E,n)},E=>{h(E,0,n)})})});for(let o of qY){let a=o.replace(/Promise$/,"");if(typeof t[a]>"u")continue;let n=e[o];if(typeof n>"u")continue;r(t,a,(...A)=>{let h=typeof A[A.length-1]=="function"?A.pop():()=>{};process.nextTick(()=>{n.apply(e,A).then(E=>{h(null,E)},E=>{h(E)})})})}t.realpath.native=t.realpath}{r(t,"existsSync",o=>{try{return e.existsSync(o)}catch{return!1}}),r(t,"readSync",(...o)=>{let[a,n,u,A,p]=o;return o.length<=3&&({offset:u=0,length:A=n.byteLength,position:p}=o[2]||{}),u==null&&(u=0),A|=0,A===0?0:(p==null&&(p=-1),e.readSync(a,n,u,A,p))});for(let o of B_e){let a=o;if(typeof t[a]>"u")continue;let n=e[o];typeof n>"u"||r(t,a,n.bind(e))}t.realpathSync.native=t.realpathSync}{let o=t.promises;for(let a of qY){let n=a.replace(/Promise$/,"");if(typeof o[n]>"u")continue;let u=e[a];typeof u>"u"||a!=="open"&&r(o,n,(A,...p)=>A instanceof cI?A[n].apply(A,p):u.call(e,A,...p))}r(o,"open",async(...a)=>{let n=await e.openPromise(...a);return new cI(n,e)})}t.read[pm.promisify.custom]=async(o,a,...n)=>({bytesRead:await e.readPromise(o,a,...n),buffer:a}),t.write[pm.promisify.custom]=async(o,a,...n)=>({bytesWritten:await e.writePromise(o,a,...n),buffer:a})}function aP(t,e){let r=Object.create(t);return uI(r,e),r}var pm,B_e,qY,jY=wt(()=>{pm=ve("util");NY();HY();B_e=new Set(["accessSync","appendFileSync","createReadStream","createWriteStream","chmodSync","fchmodSync","chownSync","fchownSync","closeSync","copyFileSync","linkSync","lstatSync","fstatSync","lutimesSync","mkdirSync","openSync","opendirSync","readlinkSync","readFileSync","readdirSync","readlinkSync","realpathSync","renameSync","rmdirSync","rmSync","statSync","symlinkSync","truncateSync","ftruncateSync","unlinkSync","unwatchFile","utimesSync","watch","watchFile","writeFileSync","writeSync"]),qY=new Set(["accessPromise","appendFilePromise","fchmodPromise","chmodPromise","fchownPromise","chownPromise","closePromise","copyFilePromise","linkPromise","fstatPromise","lstatPromise","lutimesPromise","mkdirPromise","openPromise","opendirPromise","readdirPromise","realpathPromise","readFilePromise","readdirPromise","readlinkPromise","renamePromise","rmdirPromise","rmPromise","statPromise","symlinkPromise","truncatePromise","ftruncatePromise","unlinkPromise","utimesPromise","writeFilePromise","writeSync"])});function GY(t){let e=Math.ceil(Math.random()*4294967296).toString(16).padStart(8,"0");return`${t}${e}`}function YY(){if(bT)return bT;let t=Ae.toPortablePath(WY.default.tmpdir()),e=ae.realpathSync(t);return process.once("exit",()=>{ae.rmtempSync()}),bT={tmpdir:t,realTmpdir:e}}var WY,qc,bT,ae,KY=wt(()=>{WY=et(ve("os"));W0();Ba();qc=new Set,bT=null;ae=Object.assign(new _n,{detachTemp(t){qc.delete(t)},mktempSync(t){let{tmpdir:e,realTmpdir:r}=YY();for(;;){let o=GY("xfs-");try{this.mkdirSync(K.join(e,o))}catch(n){if(n.code==="EEXIST")continue;throw n}let a=K.join(r,o);if(qc.add(a),typeof t>"u")return a;try{return t(a)}finally{if(qc.has(a)){qc.delete(a);try{this.removeSync(a)}catch{}}}}},async mktempPromise(t){let{tmpdir:e,realTmpdir:r}=YY();for(;;){let o=GY("xfs-");try{await this.mkdirPromise(K.join(e,o))}catch(n){if(n.code==="EEXIST")continue;throw n}let a=K.join(r,o);if(qc.add(a),typeof t>"u")return a;try{return await t(a)}finally{if(qc.has(a)){qc.delete(a);try{await this.removePromise(a)}catch{}}}}},async rmtempPromise(){await Promise.all(Array.from(qc.values()).map(async t=>{try{await ae.removePromise(t,{maxRetries:0}),qc.delete(t)}catch{}}))},rmtempSync(){for(let t of qc)try{ae.removeSync(t),qc.delete(t)}catch{}}})});var AI={};Kt(AI,{AliasFS:()=>ju,BasePortableFakeFS:()=>qu,CustomDir:()=>lI,CwdFS:()=>En,FakeFS:()=>hf,Filename:()=>mr,JailFS:()=>Gu,LazyFS:()=>Am,MountFS:()=>Gp,NoFS:()=>nP,NodeFS:()=>_n,PortablePath:()=>Bt,PosixFS:()=>Yp,ProxiedFS:()=>Is,VirtualFS:()=>qs,constants:()=>Pi,errors:()=>sr,extendFs:()=>aP,normalizeLineEndings:()=>G0,npath:()=>Ae,opendir:()=>eP,patchFs:()=>uI,ppath:()=>K,setupCopyIndex:()=>$D,statUtils:()=>Ia,unwatchAllFiles:()=>j0,unwatchFile:()=>q0,watchFile:()=>um,xfs:()=>ae});var Pt=wt(()=>{uY();JD();wT();vT();dY();DT();Y0();Ba();Ba();IY();Y0();DY();SY();bY();xY();kY();W0();QY();gf();FY();jY();KY()});var ZY=_((qSt,XY)=>{XY.exports=JY;JY.sync=D_e;var VY=ve("fs");function v_e(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!r||(r=r.split(";"),r.indexOf("")!==-1))return!0;for(var o=0;o{rW.exports=eW;eW.sync=P_e;var $Y=ve("fs");function eW(t,e,r){$Y.stat(t,function(o,a){r(o,o?!1:tW(a,e))})}function P_e(t,e){return tW($Y.statSync(t),e)}function tW(t,e){return t.isFile()&&S_e(t,e)}function S_e(t,e){var r=t.mode,o=t.uid,a=t.gid,n=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),u=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),A=parseInt("100",8),p=parseInt("010",8),h=parseInt("001",8),E=A|p,I=r&h||r&p&&a===u||r&A&&o===n||r&E&&n===0;return I}});var sW=_((YSt,iW)=>{var GSt=ve("fs"),lP;process.platform==="win32"||global.TESTING_WINDOWS?lP=ZY():lP=nW();iW.exports=xT;xT.sync=b_e;function xT(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(o,a){xT(t,e||{},function(n,u){n?a(n):o(u)})})}lP(t,e||{},function(o,a){o&&(o.code==="EACCES"||e&&e.ignoreErrors)&&(o=null,a=!1),r(o,a)})}function b_e(t,e){try{return lP.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}});var fW=_((WSt,AW)=>{var hm=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",oW=ve("path"),x_e=hm?";":":",aW=sW(),lW=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),cW=(t,e)=>{let r=e.colon||x_e,o=t.match(/\//)||hm&&t.match(/\\/)?[""]:[...hm?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],a=hm?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",n=hm?a.split(r):[""];return hm&&t.indexOf(".")!==-1&&n[0]!==""&&n.unshift(""),{pathEnv:o,pathExt:n,pathExtExe:a}},uW=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});let{pathEnv:o,pathExt:a,pathExtExe:n}=cW(t,e),u=[],A=h=>new Promise((E,I)=>{if(h===o.length)return e.all&&u.length?E(u):I(lW(t));let D=o[h],x=/^".*"$/.test(D)?D.slice(1,-1):D,C=oW.join(x,t),T=!x&&/^\.[\\\/]/.test(t)?t.slice(0,2)+C:C;E(p(T,h,0))}),p=(h,E,I)=>new Promise((D,x)=>{if(I===a.length)return D(A(E+1));let C=a[I];aW(h+C,{pathExt:n},(T,L)=>{if(!T&&L)if(e.all)u.push(h+C);else return D(h+C);return D(p(h,E,I+1))})});return r?A(0).then(h=>r(null,h),r):A(0)},k_e=(t,e)=>{e=e||{};let{pathEnv:r,pathExt:o,pathExtExe:a}=cW(t,e),n=[];for(let u=0;u{"use strict";var pW=(t={})=>{let e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(o=>o.toUpperCase()==="PATH")||"Path"};kT.exports=pW;kT.exports.default=pW});var yW=_((VSt,mW)=>{"use strict";var gW=ve("path"),Q_e=fW(),F_e=hW();function dW(t,e){let r=t.options.env||process.env,o=process.cwd(),a=t.options.cwd!=null,n=a&&process.chdir!==void 0&&!process.chdir.disabled;if(n)try{process.chdir(t.options.cwd)}catch{}let u;try{u=Q_e.sync(t.command,{path:r[F_e({env:r})],pathExt:e?gW.delimiter:void 0})}catch{}finally{n&&process.chdir(o)}return u&&(u=gW.resolve(a?t.options.cwd:"",u)),u}function R_e(t){return dW(t)||dW(t,!0)}mW.exports=R_e});var EW=_((zSt,FT)=>{"use strict";var QT=/([()\][%!^"`<>&|;, *?])/g;function T_e(t){return t=t.replace(QT,"^$1"),t}function N_e(t,e){return t=`${t}`,t=t.replace(/(\\*)"/g,'$1$1\\"'),t=t.replace(/(\\*)$/,"$1$1"),t=`"${t}"`,t=t.replace(QT,"^$1"),e&&(t=t.replace(QT,"^$1")),t}FT.exports.command=T_e;FT.exports.argument=N_e});var wW=_((JSt,CW)=>{"use strict";CW.exports=/^#!(.*)/});var BW=_((XSt,IW)=>{"use strict";var L_e=wW();IW.exports=(t="")=>{let e=t.match(L_e);if(!e)return null;let[r,o]=e[0].replace(/#! ?/,"").split(" "),a=r.split("/").pop();return a==="env"?o:o?`${a} ${o}`:a}});var DW=_((ZSt,vW)=>{"use strict";var RT=ve("fs"),M_e=BW();function O_e(t){let r=Buffer.alloc(150),o;try{o=RT.openSync(t,"r"),RT.readSync(o,r,0,150,0),RT.closeSync(o)}catch{}return M_e(r.toString())}vW.exports=O_e});var xW=_(($St,bW)=>{"use strict";var U_e=ve("path"),PW=yW(),SW=EW(),__e=DW(),H_e=process.platform==="win32",q_e=/\.(?:com|exe)$/i,j_e=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function G_e(t){t.file=PW(t);let e=t.file&&__e(t.file);return e?(t.args.unshift(t.file),t.command=e,PW(t)):t.file}function Y_e(t){if(!H_e)return t;let e=G_e(t),r=!q_e.test(e);if(t.options.forceShell||r){let o=j_e.test(e);t.command=U_e.normalize(t.command),t.command=SW.command(t.command),t.args=t.args.map(n=>SW.argument(n,o));let a=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${a}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function W_e(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);let o={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?o:Y_e(o)}bW.exports=W_e});var FW=_((ebt,QW)=>{"use strict";var TT=process.platform==="win32";function NT(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function K_e(t,e){if(!TT)return;let r=t.emit;t.emit=function(o,a){if(o==="exit"){let n=kW(a,e,"spawn");if(n)return r.call(t,"error",n)}return r.apply(t,arguments)}}function kW(t,e){return TT&&t===1&&!e.file?NT(e.original,"spawn"):null}function V_e(t,e){return TT&&t===1&&!e.file?NT(e.original,"spawnSync"):null}QW.exports={hookChildProcess:K_e,verifyENOENT:kW,verifyENOENTSync:V_e,notFoundError:NT}});var OT=_((tbt,gm)=>{"use strict";var RW=ve("child_process"),LT=xW(),MT=FW();function TW(t,e,r){let o=LT(t,e,r),a=RW.spawn(o.command,o.args,o.options);return MT.hookChildProcess(a,o),a}function z_e(t,e,r){let o=LT(t,e,r),a=RW.spawnSync(o.command,o.args,o.options);return a.error=a.error||MT.verifyENOENTSync(a.status,o),a}gm.exports=TW;gm.exports.spawn=TW;gm.exports.sync=z_e;gm.exports._parse=LT;gm.exports._enoent=MT});var LW=_((rbt,NW)=>{"use strict";function J_e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function V0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,V0)}J_e(V0,Error);V0.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I0){for(I=1,D=1;I>",S=cr(">>",!1),y=">&",R=cr(">&",!1),J=">",X=cr(">",!1),$="<<<",se=cr("<<<",!1),be="<&",Fe=cr("<&",!1),lt="<",Et=cr("<",!1),qt=function(N){return{type:"argument",segments:[].concat(...N)}},nr=function(N){return N},St="$'",cn=cr("$'",!1),Pr="'",yr=cr("'",!1),Rr=function(N){return[{type:"text",text:N}]},Xr='""',$n=cr('""',!1),Xs=function(){return{type:"text",text:""}},Hi='"',Qs=cr('"',!1),Zs=function(N){return N},xi=function(N){return{type:"arithmetic",arithmetic:N,quoted:!0}},Fs=function(N){return{type:"shell",shell:N,quoted:!0}},$s=function(N){return{type:"variable",...N,quoted:!0}},SA=function(N){return{type:"text",text:N}},gu=function(N){return{type:"arithmetic",arithmetic:N,quoted:!1}},op=function(N){return{type:"shell",shell:N,quoted:!1}},ap=function(N){return{type:"variable",...N,quoted:!1}},Rs=function(N){return{type:"glob",pattern:N}},Ln=/^[^']/,hs=Li(["'"],!0,!1),Ts=function(N){return N.join("")},pc=/^[^$"]/,hc=Li(["$",'"'],!0,!1),gc=`\\ +`,bA=cr(`\\ +`,!1),xA=function(){return""},Ro="\\",To=cr("\\",!1),kA=/^[\\$"`]/,pr=Li(["\\","$",'"',"`"],!1,!1),Oe=function(N){return N},ia="\\a",dc=cr("\\a",!1),Er=function(){return"a"},du="\\b",QA=cr("\\b",!1),FA=function(){return"\b"},mc=/^[Ee]/,yc=Li(["E","e"],!1,!1),wl=function(){return"\x1B"},Ie="\\f",Tt=cr("\\f",!1),Il=function(){return"\f"},Bi="\\n",Ns=cr("\\n",!1),Ft=function(){return` +`},Bn="\\r",No=cr("\\r",!1),ki=function(){return"\r"},vi="\\t",sa=cr("\\t",!1),un=function(){return" "},qn="\\v",Ec=cr("\\v",!1),lp=function(){return"\v"},oa=/^[\\'"?]/,aa=Li(["\\","'",'"',"?"],!1,!1),la=function(N){return String.fromCharCode(parseInt(N,16))},Ze="\\x",ca=cr("\\x",!1),mu="\\u",Bl=cr("\\u",!1),dn="\\U",Lo=cr("\\U",!1),RA=function(N){return String.fromCodePoint(parseInt(N,16))},TA=/^[0-7]/,Mo=Li([["0","7"]],!1,!1),qa=/^[0-9a-fA-f]/,Mt=Li([["0","9"],["a","f"],["A","f"]],!1,!1),vn=wu(),Oo="{}",ua=cr("{}",!1),qi=function(){return"{}"},vl="-",Cc=cr("-",!1),Dl="+",Aa=cr("+",!1),Di=".",rs=cr(".",!1),ja=function(N,V,re){return{type:"number",value:(N==="-"?-1:1)*parseFloat(V.join("")+"."+re.join(""))}},yu=function(N,V){return{type:"number",value:(N==="-"?-1:1)*parseInt(V.join(""))}},Pl=function(N){return{type:"variable",...N}},pi=function(N){return{type:"variable",name:N}},Dn=function(N){return N},Sl="*",ze=cr("*",!1),it="/",vt=cr("/",!1),ar=function(N,V,re){return{type:V==="*"?"multiplication":"division",right:re}},ee=function(N,V){return V.reduce((re,ge)=>({left:re,...ge}),N)},ye=function(N,V,re){return{type:V==="+"?"addition":"subtraction",right:re}},Le="$((",ht=cr("$((",!1),mt="))",Dt=cr("))",!1),er=function(N){return N},sn="$(",ei=cr("$(",!1),Qi=function(N){return N},Pn="${",fa=cr("${",!1),Id=":-",Bw=cr(":-",!1),eo=function(N,V){return{name:N,defaultValue:V}},Bd=":-}",cp=cr(":-}",!1),vw=function(N){return{name:N,defaultValue:[]}},to=":+",up=cr(":+",!1),Ap=function(N,V){return{name:N,alternativeValue:V}},wc=":+}",fp=cr(":+}",!1),s0=function(N){return{name:N,alternativeValue:[]}},o0=function(N){return{name:N}},a0="$",vd=cr("$",!1),Eu=function(N){return e.isGlobPattern(N)},ro=function(N){return N},Ga=/^[a-zA-Z0-9_]/,pp=Li([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),l0=function(){return bd()},Ya=/^[$@*?#a-zA-Z0-9_\-]/,Wa=Li(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),Dd=/^[()}<>$|&; \t"']/,NA=Li(["(",")","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),Pd=/^[<>&; \t"']/,Sd=Li(["<",">","&",";"," "," ",'"',"'"],!1,!1),LA=/^[ \t]/,MA=Li([" "," "],!1,!1),Y=0,bt=0,OA=[{line:1,column:1}],no=0,Cu=[],dt=0,Ic;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function bd(){return t.substring(bt,Y)}function c0(){return Iu(bt,Y)}function Dw(N,V){throw V=V!==void 0?V:Iu(bt,Y),UA([u0(N)],t.substring(bt,Y),V)}function hp(N,V){throw V=V!==void 0?V:Iu(bt,Y),oi(N,V)}function cr(N,V){return{type:"literal",text:N,ignoreCase:V}}function Li(N,V,re){return{type:"class",parts:N,inverted:V,ignoreCase:re}}function wu(){return{type:"any"}}function pa(){return{type:"end"}}function u0(N){return{type:"other",description:N}}function Bc(N){var V=OA[N],re;if(V)return V;for(re=N-1;!OA[re];)re--;for(V=OA[re],V={line:V.line,column:V.column};reno&&(no=Y,Cu=[]),Cu.push(N))}function oi(N,V){return new V0(N,null,null,V)}function UA(N,V,re){return new V0(V0.buildMessage(N,V),N,V,re)}function ha(){var N,V,re;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();return V!==r?(re=Uo(),re===r&&(re=null),re!==r?(bt=N,V=n(re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function Uo(){var N,V,re,ge,We;if(N=Y,V=gp(),V!==r){for(re=[],ge=xt();ge!==r;)re.push(ge),ge=xt();re!==r?(ge=A0(),ge!==r?(We=ga(),We===r&&(We=null),We!==r?(bt=N,V=u(V,ge,We),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;if(N===r)if(N=Y,V=gp(),V!==r){for(re=[],ge=xt();ge!==r;)re.push(ge),ge=xt();re!==r?(ge=A0(),ge===r&&(ge=null),ge!==r?(bt=N,V=A(V,ge),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;return N}function ga(){var N,V,re,ge,We;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r)if(re=Uo(),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();ge!==r?(bt=N,V=p(re),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;return N}function A0(){var N;return t.charCodeAt(Y)===59?(N=h,Y++):(N=r,dt===0&&It(E)),N===r&&(t.charCodeAt(Y)===38?(N=I,Y++):(N=r,dt===0&&It(D))),N}function gp(){var N,V,re;return N=Y,V=_A(),V!==r?(re=f0(),re===r&&(re=null),re!==r?(bt=N,V=x(V,re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function f0(){var N,V,re,ge,We,At,hr;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r)if(re=xd(),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();if(ge!==r)if(We=gp(),We!==r){for(At=[],hr=xt();hr!==r;)At.push(hr),hr=xt();At!==r?(bt=N,V=C(re,We),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;return N}function xd(){var N;return t.substr(Y,2)===T?(N=T,Y+=2):(N=r,dt===0&&It(L)),N===r&&(t.substr(Y,2)===U?(N=U,Y+=2):(N=r,dt===0&&It(z))),N}function _A(){var N,V,re;return N=Y,V=Bu(),V!==r?(re=p0(),re===r&&(re=null),re!==r?(bt=N,V=te(V,re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function p0(){var N,V,re,ge,We,At,hr;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r)if(re=vc(),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();if(ge!==r)if(We=_A(),We!==r){for(At=[],hr=xt();hr!==r;)At.push(hr),hr=xt();At!==r?(bt=N,V=le(re,We),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;return N}function vc(){var N;return t.substr(Y,2)===ce?(N=ce,Y+=2):(N=r,dt===0&&It(ue)),N===r&&(t.charCodeAt(Y)===124?(N=Ce,Y++):(N=r,dt===0&&It(he))),N}function Dc(){var N,V,re,ge,We,At;if(N=Y,V=yp(),V!==r)if(t.charCodeAt(Y)===61?(re=De,Y++):(re=r,dt===0&&It(Ee)),re!==r)if(ge=HA(),ge!==r){for(We=[],At=xt();At!==r;)We.push(At),At=xt();We!==r?(bt=N,V=g(V,ge),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;else Y=N,N=r;if(N===r)if(N=Y,V=yp(),V!==r)if(t.charCodeAt(Y)===61?(re=De,Y++):(re=r,dt===0&&It(Ee)),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();ge!==r?(bt=N,V=me(V),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;return N}function Bu(){var N,V,re,ge,We,At,hr,wr,Rn,ai,ns;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r)if(t.charCodeAt(Y)===40?(re=we,Y++):(re=r,dt===0&&It(fe)),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();if(ge!==r)if(We=Uo(),We!==r){for(At=[],hr=xt();hr!==r;)At.push(hr),hr=xt();if(At!==r)if(t.charCodeAt(Y)===41?(hr=ie,Y++):(hr=r,dt===0&&It(Z)),hr!==r){for(wr=[],Rn=xt();Rn!==r;)wr.push(Rn),Rn=xt();if(wr!==r){for(Rn=[],ai=Mn();ai!==r;)Rn.push(ai),ai=Mn();if(Rn!==r){for(ai=[],ns=xt();ns!==r;)ai.push(ns),ns=xt();ai!==r?(bt=N,V=xe(We,Rn),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;if(N===r){for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r)if(t.charCodeAt(Y)===123?(re=Re,Y++):(re=r,dt===0&&It(gt)),re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();if(ge!==r)if(We=Uo(),We!==r){for(At=[],hr=xt();hr!==r;)At.push(hr),hr=xt();if(At!==r)if(t.charCodeAt(Y)===125?(hr=q,Y++):(hr=r,dt===0&&It(nt)),hr!==r){for(wr=[],Rn=xt();Rn!==r;)wr.push(Rn),Rn=xt();if(wr!==r){for(Rn=[],ai=Mn();ai!==r;)Rn.push(ai),ai=Mn();if(Rn!==r){for(ai=[],ns=xt();ns!==r;)ai.push(ns),ns=xt();ai!==r?(bt=N,V=Ne(We,Rn),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;if(N===r){for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r){for(re=[],ge=Dc();ge!==r;)re.push(ge),ge=Dc();if(re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();if(ge!==r){if(We=[],At=Pc(),At!==r)for(;At!==r;)We.push(At),At=Pc();else We=r;if(We!==r){for(At=[],hr=xt();hr!==r;)At.push(hr),hr=xt();At!==r?(bt=N,V=Te(re,We),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;if(N===r){for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r){if(re=[],ge=Dc(),ge!==r)for(;ge!==r;)re.push(ge),ge=Dc();else re=r;if(re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();ge!==r?(bt=N,V=ke(re),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}}}return N}function gs(){var N,V,re,ge,We;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r){if(re=[],ge=Ci(),ge!==r)for(;ge!==r;)re.push(ge),ge=Ci();else re=r;if(re!==r){for(ge=[],We=xt();We!==r;)ge.push(We),We=xt();ge!==r?(bt=N,V=Ve(re),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r;return N}function Pc(){var N,V,re;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();if(V!==r?(re=Mn(),re!==r?(bt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r){for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();V!==r?(re=Ci(),re!==r?(bt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r)}return N}function Mn(){var N,V,re,ge,We;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();return V!==r?(tt.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(He)),re===r&&(re=null),re!==r?(ge=ji(),ge!==r?(We=Ci(),We!==r?(bt=N,V=b(re,ge,We),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function ji(){var N;return t.substr(Y,2)===w?(N=w,Y+=2):(N=r,dt===0&&It(S)),N===r&&(t.substr(Y,2)===y?(N=y,Y+=2):(N=r,dt===0&&It(R)),N===r&&(t.charCodeAt(Y)===62?(N=J,Y++):(N=r,dt===0&&It(X)),N===r&&(t.substr(Y,3)===$?(N=$,Y+=3):(N=r,dt===0&&It(se)),N===r&&(t.substr(Y,2)===be?(N=be,Y+=2):(N=r,dt===0&&It(Fe)),N===r&&(t.charCodeAt(Y)===60?(N=lt,Y++):(N=r,dt===0&&It(Et))))))),N}function Ci(){var N,V,re;for(N=Y,V=[],re=xt();re!==r;)V.push(re),re=xt();return V!==r?(re=HA(),re!==r?(bt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function HA(){var N,V,re;if(N=Y,V=[],re=vu(),re!==r)for(;re!==r;)V.push(re),re=vu();else V=r;return V!==r&&(bt=N,V=qt(V)),N=V,N}function vu(){var N,V;return N=Y,V=An(),V!==r&&(bt=N,V=nr(V)),N=V,N===r&&(N=Y,V=h0(),V!==r&&(bt=N,V=nr(V)),N=V,N===r&&(N=Y,V=g0(),V!==r&&(bt=N,V=nr(V)),N=V,N===r&&(N=Y,V=Gi(),V!==r&&(bt=N,V=nr(V)),N=V))),N}function An(){var N,V,re,ge;return N=Y,t.substr(Y,2)===St?(V=St,Y+=2):(V=r,dt===0&&It(cn)),V!==r?(re=fn(),re!==r?(t.charCodeAt(Y)===39?(ge=Pr,Y++):(ge=r,dt===0&&It(yr)),ge!==r?(bt=N,V=Rr(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function h0(){var N,V,re,ge;return N=Y,t.charCodeAt(Y)===39?(V=Pr,Y++):(V=r,dt===0&&It(yr)),V!==r?(re=Du(),re!==r?(t.charCodeAt(Y)===39?(ge=Pr,Y++):(ge=r,dt===0&&It(yr)),ge!==r?(bt=N,V=Rr(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function g0(){var N,V,re,ge;if(N=Y,t.substr(Y,2)===Xr?(V=Xr,Y+=2):(V=r,dt===0&&It($n)),V!==r&&(bt=N,V=Xs()),N=V,N===r)if(N=Y,t.charCodeAt(Y)===34?(V=Hi,Y++):(V=r,dt===0&&It(Qs)),V!==r){for(re=[],ge=Ka();ge!==r;)re.push(ge),ge=Ka();re!==r?(t.charCodeAt(Y)===34?(ge=Hi,Y++):(ge=r,dt===0&&It(Qs)),ge!==r?(bt=N,V=Zs(re),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;return N}function Gi(){var N,V,re;if(N=Y,V=[],re=io(),re!==r)for(;re!==r;)V.push(re),re=io();else V=r;return V!==r&&(bt=N,V=Zs(V)),N=V,N}function Ka(){var N,V;return N=Y,V=Kr(),V!==r&&(bt=N,V=xi(V)),N=V,N===r&&(N=Y,V=mp(),V!==r&&(bt=N,V=Fs(V)),N=V,N===r&&(N=Y,V=jA(),V!==r&&(bt=N,V=$s(V)),N=V,N===r&&(N=Y,V=Pu(),V!==r&&(bt=N,V=SA(V)),N=V))),N}function io(){var N,V;return N=Y,V=Kr(),V!==r&&(bt=N,V=gu(V)),N=V,N===r&&(N=Y,V=mp(),V!==r&&(bt=N,V=op(V)),N=V,N===r&&(N=Y,V=jA(),V!==r&&(bt=N,V=ap(V)),N=V,N===r&&(N=Y,V=kd(),V!==r&&(bt=N,V=Rs(V)),N=V,N===r&&(N=Y,V=dp(),V!==r&&(bt=N,V=SA(V)),N=V)))),N}function Du(){var N,V,re;for(N=Y,V=[],Ln.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hs));re!==r;)V.push(re),Ln.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hs));return V!==r&&(bt=N,V=Ts(V)),N=V,N}function Pu(){var N,V,re;if(N=Y,V=[],re=Va(),re===r&&(pc.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hc))),re!==r)for(;re!==r;)V.push(re),re=Va(),re===r&&(pc.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hc)));else V=r;return V!==r&&(bt=N,V=Ts(V)),N=V,N}function Va(){var N,V,re;return N=Y,t.substr(Y,2)===gc?(V=gc,Y+=2):(V=r,dt===0&&It(bA)),V!==r&&(bt=N,V=xA()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ro,Y++):(V=r,dt===0&&It(To)),V!==r?(kA.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(pr)),re!==r?(bt=N,V=Oe(re),N=V):(Y=N,N=r)):(Y=N,N=r)),N}function fn(){var N,V,re;for(N=Y,V=[],re=so(),re===r&&(Ln.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hs)));re!==r;)V.push(re),re=so(),re===r&&(Ln.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(hs)));return V!==r&&(bt=N,V=Ts(V)),N=V,N}function so(){var N,V,re;return N=Y,t.substr(Y,2)===ia?(V=ia,Y+=2):(V=r,dt===0&&It(dc)),V!==r&&(bt=N,V=Er()),N=V,N===r&&(N=Y,t.substr(Y,2)===du?(V=du,Y+=2):(V=r,dt===0&&It(QA)),V!==r&&(bt=N,V=FA()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ro,Y++):(V=r,dt===0&&It(To)),V!==r?(mc.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(yc)),re!==r?(bt=N,V=wl(),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Ie?(V=Ie,Y+=2):(V=r,dt===0&&It(Tt)),V!==r&&(bt=N,V=Il()),N=V,N===r&&(N=Y,t.substr(Y,2)===Bi?(V=Bi,Y+=2):(V=r,dt===0&&It(Ns)),V!==r&&(bt=N,V=Ft()),N=V,N===r&&(N=Y,t.substr(Y,2)===Bn?(V=Bn,Y+=2):(V=r,dt===0&&It(No)),V!==r&&(bt=N,V=ki()),N=V,N===r&&(N=Y,t.substr(Y,2)===vi?(V=vi,Y+=2):(V=r,dt===0&&It(sa)),V!==r&&(bt=N,V=un()),N=V,N===r&&(N=Y,t.substr(Y,2)===qn?(V=qn,Y+=2):(V=r,dt===0&&It(Ec)),V!==r&&(bt=N,V=lp()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ro,Y++):(V=r,dt===0&&It(To)),V!==r?(oa.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(aa)),re!==r?(bt=N,V=Oe(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Sc()))))))))),N}function Sc(){var N,V,re,ge,We,At,hr,wr,Rn,ai,ns,GA;return N=Y,t.charCodeAt(Y)===92?(V=Ro,Y++):(V=r,dt===0&&It(To)),V!==r?(re=_o(),re!==r?(bt=N,V=la(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Ze?(V=Ze,Y+=2):(V=r,dt===0&&It(ca)),V!==r?(re=Y,ge=Y,We=_o(),We!==r?(At=ds(),At!==r?(We=[We,At],ge=We):(Y=ge,ge=r)):(Y=ge,ge=r),ge===r&&(ge=_o()),ge!==r?re=t.substring(re,Y):re=ge,re!==r?(bt=N,V=la(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===mu?(V=mu,Y+=2):(V=r,dt===0&&It(Bl)),V!==r?(re=Y,ge=Y,We=ds(),We!==r?(At=ds(),At!==r?(hr=ds(),hr!==r?(wr=ds(),wr!==r?(We=[We,At,hr,wr],ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r),ge!==r?re=t.substring(re,Y):re=ge,re!==r?(bt=N,V=la(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===dn?(V=dn,Y+=2):(V=r,dt===0&&It(Lo)),V!==r?(re=Y,ge=Y,We=ds(),We!==r?(At=ds(),At!==r?(hr=ds(),hr!==r?(wr=ds(),wr!==r?(Rn=ds(),Rn!==r?(ai=ds(),ai!==r?(ns=ds(),ns!==r?(GA=ds(),GA!==r?(We=[We,At,hr,wr,Rn,ai,ns,GA],ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r)):(Y=ge,ge=r),ge!==r?re=t.substring(re,Y):re=ge,re!==r?(bt=N,V=RA(re),N=V):(Y=N,N=r)):(Y=N,N=r)))),N}function _o(){var N;return TA.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,dt===0&&It(Mo)),N}function ds(){var N;return qa.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,dt===0&&It(Mt)),N}function dp(){var N,V,re,ge,We;if(N=Y,V=[],re=Y,t.charCodeAt(Y)===92?(ge=Ro,Y++):(ge=r,dt===0&&It(To)),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r),re===r&&(re=Y,t.substr(Y,2)===Oo?(ge=Oo,Y+=2):(ge=r,dt===0&&It(ua)),ge!==r&&(bt=re,ge=qi()),re=ge,re===r&&(re=Y,ge=Y,dt++,We=Qd(),dt--,We===r?ge=void 0:(Y=ge,ge=r),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r))),re!==r)for(;re!==r;)V.push(re),re=Y,t.charCodeAt(Y)===92?(ge=Ro,Y++):(ge=r,dt===0&&It(To)),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r),re===r&&(re=Y,t.substr(Y,2)===Oo?(ge=Oo,Y+=2):(ge=r,dt===0&&It(ua)),ge!==r&&(bt=re,ge=qi()),re=ge,re===r&&(re=Y,ge=Y,dt++,We=Qd(),dt--,We===r?ge=void 0:(Y=ge,ge=r),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r)));else V=r;return V!==r&&(bt=N,V=Ts(V)),N=V,N}function qA(){var N,V,re,ge,We,At;if(N=Y,t.charCodeAt(Y)===45?(V=vl,Y++):(V=r,dt===0&&It(Cc)),V===r&&(t.charCodeAt(Y)===43?(V=Dl,Y++):(V=r,dt===0&&It(Aa))),V===r&&(V=null),V!==r){if(re=[],tt.test(t.charAt(Y))?(ge=t.charAt(Y),Y++):(ge=r,dt===0&&It(He)),ge!==r)for(;ge!==r;)re.push(ge),tt.test(t.charAt(Y))?(ge=t.charAt(Y),Y++):(ge=r,dt===0&&It(He));else re=r;if(re!==r)if(t.charCodeAt(Y)===46?(ge=Di,Y++):(ge=r,dt===0&&It(rs)),ge!==r){if(We=[],tt.test(t.charAt(Y))?(At=t.charAt(Y),Y++):(At=r,dt===0&&It(He)),At!==r)for(;At!==r;)We.push(At),tt.test(t.charAt(Y))?(At=t.charAt(Y),Y++):(At=r,dt===0&&It(He));else We=r;We!==r?(bt=N,V=ja(V,re,We),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;if(N===r){if(N=Y,t.charCodeAt(Y)===45?(V=vl,Y++):(V=r,dt===0&&It(Cc)),V===r&&(t.charCodeAt(Y)===43?(V=Dl,Y++):(V=r,dt===0&&It(Aa))),V===r&&(V=null),V!==r){if(re=[],tt.test(t.charAt(Y))?(ge=t.charAt(Y),Y++):(ge=r,dt===0&&It(He)),ge!==r)for(;ge!==r;)re.push(ge),tt.test(t.charAt(Y))?(ge=t.charAt(Y),Y++):(ge=r,dt===0&&It(He));else re=r;re!==r?(bt=N,V=yu(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;if(N===r&&(N=Y,V=jA(),V!==r&&(bt=N,V=Pl(V)),N=V,N===r&&(N=Y,V=bl(),V!==r&&(bt=N,V=pi(V)),N=V,N===r)))if(N=Y,t.charCodeAt(Y)===40?(V=we,Y++):(V=r,dt===0&&It(fe)),V!==r){for(re=[],ge=xt();ge!==r;)re.push(ge),ge=xt();if(re!==r)if(ge=Ls(),ge!==r){for(We=[],At=xt();At!==r;)We.push(At),At=xt();We!==r?(t.charCodeAt(Y)===41?(At=ie,Y++):(At=r,dt===0&&It(Z)),At!==r?(bt=N,V=Dn(ge),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r}return N}function Su(){var N,V,re,ge,We,At,hr,wr;if(N=Y,V=qA(),V!==r){for(re=[],ge=Y,We=[],At=xt();At!==r;)We.push(At),At=xt();if(We!==r)if(t.charCodeAt(Y)===42?(At=Sl,Y++):(At=r,dt===0&&It(ze)),At===r&&(t.charCodeAt(Y)===47?(At=it,Y++):(At=r,dt===0&&It(vt))),At!==r){for(hr=[],wr=xt();wr!==r;)hr.push(wr),wr=xt();hr!==r?(wr=qA(),wr!==r?(bt=ge,We=ar(V,At,wr),ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)}else Y=ge,ge=r;else Y=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=Y,We=[],At=xt();At!==r;)We.push(At),At=xt();if(We!==r)if(t.charCodeAt(Y)===42?(At=Sl,Y++):(At=r,dt===0&&It(ze)),At===r&&(t.charCodeAt(Y)===47?(At=it,Y++):(At=r,dt===0&&It(vt))),At!==r){for(hr=[],wr=xt();wr!==r;)hr.push(wr),wr=xt();hr!==r?(wr=qA(),wr!==r?(bt=ge,We=ar(V,At,wr),ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)}else Y=ge,ge=r;else Y=ge,ge=r}re!==r?(bt=N,V=ee(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;return N}function Ls(){var N,V,re,ge,We,At,hr,wr;if(N=Y,V=Su(),V!==r){for(re=[],ge=Y,We=[],At=xt();At!==r;)We.push(At),At=xt();if(We!==r)if(t.charCodeAt(Y)===43?(At=Dl,Y++):(At=r,dt===0&&It(Aa)),At===r&&(t.charCodeAt(Y)===45?(At=vl,Y++):(At=r,dt===0&&It(Cc))),At!==r){for(hr=[],wr=xt();wr!==r;)hr.push(wr),wr=xt();hr!==r?(wr=Su(),wr!==r?(bt=ge,We=ye(V,At,wr),ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)}else Y=ge,ge=r;else Y=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=Y,We=[],At=xt();At!==r;)We.push(At),At=xt();if(We!==r)if(t.charCodeAt(Y)===43?(At=Dl,Y++):(At=r,dt===0&&It(Aa)),At===r&&(t.charCodeAt(Y)===45?(At=vl,Y++):(At=r,dt===0&&It(Cc))),At!==r){for(hr=[],wr=xt();wr!==r;)hr.push(wr),wr=xt();hr!==r?(wr=Su(),wr!==r?(bt=ge,We=ye(V,At,wr),ge=We):(Y=ge,ge=r)):(Y=ge,ge=r)}else Y=ge,ge=r;else Y=ge,ge=r}re!==r?(bt=N,V=ee(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;return N}function Kr(){var N,V,re,ge,We,At;if(N=Y,t.substr(Y,3)===Le?(V=Le,Y+=3):(V=r,dt===0&&It(ht)),V!==r){for(re=[],ge=xt();ge!==r;)re.push(ge),ge=xt();if(re!==r)if(ge=Ls(),ge!==r){for(We=[],At=xt();At!==r;)We.push(At),At=xt();We!==r?(t.substr(Y,2)===mt?(At=mt,Y+=2):(At=r,dt===0&&It(Dt)),At!==r?(bt=N,V=er(ge),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;return N}function mp(){var N,V,re,ge;return N=Y,t.substr(Y,2)===sn?(V=sn,Y+=2):(V=r,dt===0&&It(ei)),V!==r?(re=Uo(),re!==r?(t.charCodeAt(Y)===41?(ge=ie,Y++):(ge=r,dt===0&&It(Z)),ge!==r?(bt=N,V=Qi(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function jA(){var N,V,re,ge,We,At;return N=Y,t.substr(Y,2)===Pn?(V=Pn,Y+=2):(V=r,dt===0&&It(fa)),V!==r?(re=bl(),re!==r?(t.substr(Y,2)===Id?(ge=Id,Y+=2):(ge=r,dt===0&&It(Bw)),ge!==r?(We=gs(),We!==r?(t.charCodeAt(Y)===125?(At=q,Y++):(At=r,dt===0&&It(nt)),At!==r?(bt=N,V=eo(re,We),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Pn?(V=Pn,Y+=2):(V=r,dt===0&&It(fa)),V!==r?(re=bl(),re!==r?(t.substr(Y,3)===Bd?(ge=Bd,Y+=3):(ge=r,dt===0&&It(cp)),ge!==r?(bt=N,V=vw(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Pn?(V=Pn,Y+=2):(V=r,dt===0&&It(fa)),V!==r?(re=bl(),re!==r?(t.substr(Y,2)===to?(ge=to,Y+=2):(ge=r,dt===0&&It(up)),ge!==r?(We=gs(),We!==r?(t.charCodeAt(Y)===125?(At=q,Y++):(At=r,dt===0&&It(nt)),At!==r?(bt=N,V=Ap(re,We),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Pn?(V=Pn,Y+=2):(V=r,dt===0&&It(fa)),V!==r?(re=bl(),re!==r?(t.substr(Y,3)===wc?(ge=wc,Y+=3):(ge=r,dt===0&&It(fp)),ge!==r?(bt=N,V=s0(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Pn?(V=Pn,Y+=2):(V=r,dt===0&&It(fa)),V!==r?(re=bl(),re!==r?(t.charCodeAt(Y)===125?(ge=q,Y++):(ge=r,dt===0&&It(nt)),ge!==r?(bt=N,V=o0(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.charCodeAt(Y)===36?(V=a0,Y++):(V=r,dt===0&&It(vd)),V!==r?(re=bl(),re!==r?(bt=N,V=o0(re),N=V):(Y=N,N=r)):(Y=N,N=r)))))),N}function kd(){var N,V,re;return N=Y,V=d0(),V!==r?(bt=Y,re=Eu(V),re?re=void 0:re=r,re!==r?(bt=N,V=ro(V),N=V):(Y=N,N=r)):(Y=N,N=r),N}function d0(){var N,V,re,ge,We;if(N=Y,V=[],re=Y,ge=Y,dt++,We=Ep(),dt--,We===r?ge=void 0:(Y=ge,ge=r),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r),re!==r)for(;re!==r;)V.push(re),re=Y,ge=Y,dt++,We=Ep(),dt--,We===r?ge=void 0:(Y=ge,ge=r),ge!==r?(t.length>Y?(We=t.charAt(Y),Y++):(We=r,dt===0&&It(vn)),We!==r?(bt=re,ge=Oe(We),re=ge):(Y=re,re=r)):(Y=re,re=r);else V=r;return V!==r&&(bt=N,V=Ts(V)),N=V,N}function yp(){var N,V,re;if(N=Y,V=[],Ga.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(pp)),re!==r)for(;re!==r;)V.push(re),Ga.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(pp));else V=r;return V!==r&&(bt=N,V=l0()),N=V,N}function bl(){var N,V,re;if(N=Y,V=[],Ya.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(Wa)),re!==r)for(;re!==r;)V.push(re),Ya.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,dt===0&&It(Wa));else V=r;return V!==r&&(bt=N,V=l0()),N=V,N}function Qd(){var N;return Dd.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,dt===0&&It(NA)),N}function Ep(){var N;return Pd.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,dt===0&&It(Sd)),N}function xt(){var N,V;if(N=[],LA.test(t.charAt(Y))?(V=t.charAt(Y),Y++):(V=r,dt===0&&It(MA)),V!==r)for(;V!==r;)N.push(V),LA.test(t.charAt(Y))?(V=t.charAt(Y),Y++):(V=r,dt===0&&It(MA));else N=r;return N}if(Ic=a(),Ic!==r&&Y===t.length)return Ic;throw Ic!==r&&Y!1}){try{return(0,MW.parse)(t,e)}catch(r){throw r.location&&(r.message=r.message.replace(/(\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function dm(t,{endSemicolon:e=!1}={}){return t.map(({command:r,type:o},a)=>`${AP(r)}${o===";"?a!==t.length-1||e?";":"":" &"}`).join(" ")}function AP(t){return`${mm(t.chain)}${t.then?` ${UT(t.then)}`:""}`}function UT(t){return`${t.type} ${AP(t.line)}`}function mm(t){return`${HT(t)}${t.then?` ${_T(t.then)}`:""}`}function _T(t){return`${t.type} ${mm(t.chain)}`}function HT(t){switch(t.type){case"command":return`${t.envs.length>0?`${t.envs.map(e=>cP(e)).join(" ")} `:""}${t.args.map(e=>qT(e)).join(" ")}`;case"subshell":return`(${dm(t.subshell)})${t.args.length>0?` ${t.args.map(e=>fI(e)).join(" ")}`:""}`;case"group":return`{ ${dm(t.group,{endSemicolon:!0})} }${t.args.length>0?` ${t.args.map(e=>fI(e)).join(" ")}`:""}`;case"envs":return t.envs.map(e=>cP(e)).join(" ");default:throw new Error(`Unsupported command type: "${t.type}"`)}}function cP(t){return`${t.name}=${t.args[0]?z0(t.args[0]):""}`}function qT(t){switch(t.type){case"redirection":return fI(t);case"argument":return z0(t);default:throw new Error(`Unsupported argument type: "${t.type}"`)}}function fI(t){return`${t.subtype} ${t.args.map(e=>z0(e)).join(" ")}`}function z0(t){return t.segments.map(e=>jT(e)).join("")}function jT(t){let e=(o,a)=>a?`"${o}"`:o,r=o=>o===""?"''":o.match(/[()}<>$|&;"'\n\t ]/)?o.match(/['\t\p{C}]/u)?o.match(/'/)?`"${o.replace(/["$\t\p{C}]/u,$_e)}"`:`$'${o.replace(/[\t\p{C}]/u,UW)}'`:`'${o}'`:o;switch(t.type){case"text":return r(t.text);case"glob":return t.pattern;case"shell":return e(`$(${dm(t.shell)})`,t.quoted);case"variable":return e(typeof t.defaultValue>"u"?typeof t.alternativeValue>"u"?`\${${t.name}}`:t.alternativeValue.length===0?`\${${t.name}:+}`:`\${${t.name}:+${t.alternativeValue.map(o=>z0(o)).join(" ")}}`:t.defaultValue.length===0?`\${${t.name}:-}`:`\${${t.name}:-${t.defaultValue.map(o=>z0(o)).join(" ")}}`,t.quoted);case"arithmetic":return`$(( ${fP(t.arithmetic)} ))`;default:throw new Error(`Unsupported argument segment type: "${t.type}"`)}}function fP(t){let e=a=>{switch(a){case"addition":return"+";case"subtraction":return"-";case"multiplication":return"*";case"division":return"/";default:throw new Error(`Can't extract operator from arithmetic expression of type "${a}"`)}},r=(a,n)=>n?`( ${a} )`:a,o=a=>r(fP(a),!["number","variable"].includes(a.type));switch(t.type){case"number":return String(t.value);case"variable":return t.name;default:return`${o(t.left)} ${e(t.type)} ${o(t.right)}`}}var MW,OW,Z_e,UW,$_e,_W=wt(()=>{MW=et(LW());OW=new Map([["\f","\\f"],[` +`,"\\n"],["\r","\\r"],[" ","\\t"],["\v","\\v"],["\0","\\0"]]),Z_e=new Map([["\\","\\\\"],["$","\\$"],['"','\\"'],...Array.from(OW,([t,e])=>[t,`"$'${e}'"`])]),UW=t=>OW.get(t)??`\\x${t.charCodeAt(0).toString(16).padStart(2,"0")}`,$_e=t=>Z_e.get(t)??`"$'${UW(t)}'"`});var qW=_((dbt,HW)=>{"use strict";function e8e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function J0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,J0)}e8e(J0,Error);J0.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I0){for(I=1,D=1;Ice&&(ce=z,ue=[]),ue.push(He))}function nt(He,b){return new J0(He,null,null,b)}function Ne(He,b,w){return new J0(J0.buildMessage(He,b),He,b,w)}function Te(){var He,b,w,S;return He=z,b=ke(),b!==r?(t.charCodeAt(z)===47?(w=n,z++):(w=r,Ce===0&&q(u)),w!==r?(S=ke(),S!==r?(te=He,b=A(b,S),He=b):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,b=ke(),b!==r&&(te=He,b=p(b)),He=b),He}function ke(){var He,b,w,S;return He=z,b=Ve(),b!==r?(t.charCodeAt(z)===64?(w=h,z++):(w=r,Ce===0&&q(E)),w!==r?(S=tt(),S!==r?(te=He,b=I(b,S),He=b):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,b=Ve(),b!==r&&(te=He,b=D(b)),He=b),He}function Ve(){var He,b,w,S,y;return He=z,t.charCodeAt(z)===64?(b=h,z++):(b=r,Ce===0&&q(E)),b!==r?(w=Se(),w!==r?(t.charCodeAt(z)===47?(S=n,z++):(S=r,Ce===0&&q(u)),S!==r?(y=Se(),y!==r?(te=He,b=x(),He=b):(z=He,He=r)):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,b=Se(),b!==r&&(te=He,b=x()),He=b),He}function Se(){var He,b,w;if(He=z,b=[],C.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&q(T)),w!==r)for(;w!==r;)b.push(w),C.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&q(T));else b=r;return b!==r&&(te=He,b=x()),He=b,He}function tt(){var He,b,w;if(He=z,b=[],L.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&q(U)),w!==r)for(;w!==r;)b.push(w),L.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&q(U));else b=r;return b!==r&&(te=He,b=x()),He=b,He}if(he=a(),he!==r&&z===t.length)return he;throw he!==r&&z{jW=et(qW())});var Z0=_((ybt,X0)=>{"use strict";function YW(t){return typeof t>"u"||t===null}function r8e(t){return typeof t=="object"&&t!==null}function n8e(t){return Array.isArray(t)?t:YW(t)?[]:[t]}function i8e(t,e){var r,o,a,n;if(e)for(n=Object.keys(e),r=0,o=n.length;r{"use strict";function pI(t,e){Error.call(this),this.name="YAMLException",this.reason=t,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}pI.prototype=Object.create(Error.prototype);pI.prototype.constructor=pI;pI.prototype.toString=function(e){var r=this.name+": ";return r+=this.reason||"(unknown reason)",!e&&this.mark&&(r+=" "+this.mark.toString()),r};WW.exports=pI});var zW=_((Cbt,VW)=>{"use strict";var KW=Z0();function GT(t,e,r,o,a){this.name=t,this.buffer=e,this.position=r,this.line=o,this.column=a}GT.prototype.getSnippet=function(e,r){var o,a,n,u,A;if(!this.buffer)return null;for(e=e||4,r=r||75,o="",a=this.position;a>0&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(a-1))===-1;)if(a-=1,this.position-a>r/2-1){o=" ... ",a+=5;break}for(n="",u=this.position;ur/2-1){n=" ... ",u-=5;break}return A=this.buffer.slice(a,u),KW.repeat(" ",e)+o+A+n+` +`+KW.repeat(" ",e+this.position-a+o.length)+"^"};GT.prototype.toString=function(e){var r,o="";return this.name&&(o+='in "'+this.name+'" '),o+="at line "+(this.line+1)+", column "+(this.column+1),e||(r=this.getSnippet(),r&&(o+=`: +`+r)),o};VW.exports=GT});var as=_((wbt,XW)=>{"use strict";var JW=ym(),a8e=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],l8e=["scalar","sequence","mapping"];function c8e(t){var e={};return t!==null&&Object.keys(t).forEach(function(r){t[r].forEach(function(o){e[String(o)]=r})}),e}function u8e(t,e){if(e=e||{},Object.keys(e).forEach(function(r){if(a8e.indexOf(r)===-1)throw new JW('Unknown option "'+r+'" is met in definition of "'+t+'" YAML type.')}),this.tag=t,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(r){return r},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=c8e(e.styleAliases||null),l8e.indexOf(this.kind)===-1)throw new JW('Unknown kind "'+this.kind+'" is specified for "'+t+'" YAML type.')}XW.exports=u8e});var $0=_((Ibt,$W)=>{"use strict";var ZW=Z0(),gP=ym(),A8e=as();function YT(t,e,r){var o=[];return t.include.forEach(function(a){r=YT(a,e,r)}),t[e].forEach(function(a){r.forEach(function(n,u){n.tag===a.tag&&n.kind===a.kind&&o.push(u)}),r.push(a)}),r.filter(function(a,n){return o.indexOf(n)===-1})}function f8e(){var t={scalar:{},sequence:{},mapping:{},fallback:{}},e,r;function o(a){t[a.kind][a.tag]=t.fallback[a.tag]=a}for(e=0,r=arguments.length;e{"use strict";var p8e=as();eK.exports=new p8e("tag:yaml.org,2002:str",{kind:"scalar",construct:function(t){return t!==null?t:""}})});var nK=_((vbt,rK)=>{"use strict";var h8e=as();rK.exports=new h8e("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(t){return t!==null?t:[]}})});var sK=_((Dbt,iK)=>{"use strict";var g8e=as();iK.exports=new g8e("tag:yaml.org,2002:map",{kind:"mapping",construct:function(t){return t!==null?t:{}}})});var dP=_((Pbt,oK)=>{"use strict";var d8e=$0();oK.exports=new d8e({explicit:[tK(),nK(),sK()]})});var lK=_((Sbt,aK)=>{"use strict";var m8e=as();function y8e(t){if(t===null)return!0;var e=t.length;return e===1&&t==="~"||e===4&&(t==="null"||t==="Null"||t==="NULL")}function E8e(){return null}function C8e(t){return t===null}aK.exports=new m8e("tag:yaml.org,2002:null",{kind:"scalar",resolve:y8e,construct:E8e,predicate:C8e,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var uK=_((bbt,cK)=>{"use strict";var w8e=as();function I8e(t){if(t===null)return!1;var e=t.length;return e===4&&(t==="true"||t==="True"||t==="TRUE")||e===5&&(t==="false"||t==="False"||t==="FALSE")}function B8e(t){return t==="true"||t==="True"||t==="TRUE"}function v8e(t){return Object.prototype.toString.call(t)==="[object Boolean]"}cK.exports=new w8e("tag:yaml.org,2002:bool",{kind:"scalar",resolve:I8e,construct:B8e,predicate:v8e,represent:{lowercase:function(t){return t?"true":"false"},uppercase:function(t){return t?"TRUE":"FALSE"},camelcase:function(t){return t?"True":"False"}},defaultStyle:"lowercase"})});var fK=_((xbt,AK)=>{"use strict";var D8e=Z0(),P8e=as();function S8e(t){return 48<=t&&t<=57||65<=t&&t<=70||97<=t&&t<=102}function b8e(t){return 48<=t&&t<=55}function x8e(t){return 48<=t&&t<=57}function k8e(t){if(t===null)return!1;var e=t.length,r=0,o=!1,a;if(!e)return!1;if(a=t[r],(a==="-"||a==="+")&&(a=t[++r]),a==="0"){if(r+1===e)return!0;if(a=t[++r],a==="b"){for(r++;r=0?"0b"+t.toString(2):"-0b"+t.toString(2).slice(1)},octal:function(t){return t>=0?"0"+t.toString(8):"-0"+t.toString(8).slice(1)},decimal:function(t){return t.toString(10)},hexadecimal:function(t){return t>=0?"0x"+t.toString(16).toUpperCase():"-0x"+t.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})});var gK=_((kbt,hK)=>{"use strict";var pK=Z0(),R8e=as(),T8e=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function N8e(t){return!(t===null||!T8e.test(t)||t[t.length-1]==="_")}function L8e(t){var e,r,o,a;return e=t.replace(/_/g,"").toLowerCase(),r=e[0]==="-"?-1:1,a=[],"+-".indexOf(e[0])>=0&&(e=e.slice(1)),e===".inf"?r===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===".nan"?NaN:e.indexOf(":")>=0?(e.split(":").forEach(function(n){a.unshift(parseFloat(n,10))}),e=0,o=1,a.forEach(function(n){e+=n*o,o*=60}),r*e):r*parseFloat(e,10)}var M8e=/^[-+]?[0-9]+e/;function O8e(t,e){var r;if(isNaN(t))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===t)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===t)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(pK.isNegativeZero(t))return"-0.0";return r=t.toString(10),M8e.test(r)?r.replace("e",".e"):r}function U8e(t){return Object.prototype.toString.call(t)==="[object Number]"&&(t%1!==0||pK.isNegativeZero(t))}hK.exports=new R8e("tag:yaml.org,2002:float",{kind:"scalar",resolve:N8e,construct:L8e,predicate:U8e,represent:O8e,defaultStyle:"lowercase"})});var WT=_((Qbt,dK)=>{"use strict";var _8e=$0();dK.exports=new _8e({include:[dP()],implicit:[lK(),uK(),fK(),gK()]})});var KT=_((Fbt,mK)=>{"use strict";var H8e=$0();mK.exports=new H8e({include:[WT()]})});var wK=_((Rbt,CK)=>{"use strict";var q8e=as(),yK=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),EK=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function j8e(t){return t===null?!1:yK.exec(t)!==null||EK.exec(t)!==null}function G8e(t){var e,r,o,a,n,u,A,p=0,h=null,E,I,D;if(e=yK.exec(t),e===null&&(e=EK.exec(t)),e===null)throw new Error("Date resolve error");if(r=+e[1],o=+e[2]-1,a=+e[3],!e[4])return new Date(Date.UTC(r,o,a));if(n=+e[4],u=+e[5],A=+e[6],e[7]){for(p=e[7].slice(0,3);p.length<3;)p+="0";p=+p}return e[9]&&(E=+e[10],I=+(e[11]||0),h=(E*60+I)*6e4,e[9]==="-"&&(h=-h)),D=new Date(Date.UTC(r,o,a,n,u,A,p)),h&&D.setTime(D.getTime()-h),D}function Y8e(t){return t.toISOString()}CK.exports=new q8e("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:j8e,construct:G8e,instanceOf:Date,represent:Y8e})});var BK=_((Tbt,IK)=>{"use strict";var W8e=as();function K8e(t){return t==="<<"||t===null}IK.exports=new W8e("tag:yaml.org,2002:merge",{kind:"scalar",resolve:K8e})});var PK=_((Nbt,DK)=>{"use strict";var eg;try{vK=ve,eg=vK("buffer").Buffer}catch{}var vK,V8e=as(),VT=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function z8e(t){if(t===null)return!1;var e,r,o=0,a=t.length,n=VT;for(r=0;r64)){if(e<0)return!1;o+=6}return o%8===0}function J8e(t){var e,r,o=t.replace(/[\r\n=]/g,""),a=o.length,n=VT,u=0,A=[];for(e=0;e>16&255),A.push(u>>8&255),A.push(u&255)),u=u<<6|n.indexOf(o.charAt(e));return r=a%4*6,r===0?(A.push(u>>16&255),A.push(u>>8&255),A.push(u&255)):r===18?(A.push(u>>10&255),A.push(u>>2&255)):r===12&&A.push(u>>4&255),eg?eg.from?eg.from(A):new eg(A):A}function X8e(t){var e="",r=0,o,a,n=t.length,u=VT;for(o=0;o>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]),r=(r<<8)+t[o];return a=n%3,a===0?(e+=u[r>>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]):a===2?(e+=u[r>>10&63],e+=u[r>>4&63],e+=u[r<<2&63],e+=u[64]):a===1&&(e+=u[r>>2&63],e+=u[r<<4&63],e+=u[64],e+=u[64]),e}function Z8e(t){return eg&&eg.isBuffer(t)}DK.exports=new V8e("tag:yaml.org,2002:binary",{kind:"scalar",resolve:z8e,construct:J8e,predicate:Z8e,represent:X8e})});var bK=_((Mbt,SK)=>{"use strict";var $8e=as(),eHe=Object.prototype.hasOwnProperty,tHe=Object.prototype.toString;function rHe(t){if(t===null)return!0;var e=[],r,o,a,n,u,A=t;for(r=0,o=A.length;r{"use strict";var iHe=as(),sHe=Object.prototype.toString;function oHe(t){if(t===null)return!0;var e,r,o,a,n,u=t;for(n=new Array(u.length),e=0,r=u.length;e{"use strict";var lHe=as(),cHe=Object.prototype.hasOwnProperty;function uHe(t){if(t===null)return!0;var e,r=t;for(e in r)if(cHe.call(r,e)&&r[e]!==null)return!1;return!0}function AHe(t){return t!==null?t:{}}QK.exports=new lHe("tag:yaml.org,2002:set",{kind:"mapping",resolve:uHe,construct:AHe})});var Cm=_((_bt,RK)=>{"use strict";var fHe=$0();RK.exports=new fHe({include:[KT()],implicit:[wK(),BK()],explicit:[PK(),bK(),kK(),FK()]})});var NK=_((Hbt,TK)=>{"use strict";var pHe=as();function hHe(){return!0}function gHe(){}function dHe(){return""}function mHe(t){return typeof t>"u"}TK.exports=new pHe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:hHe,construct:gHe,predicate:mHe,represent:dHe})});var MK=_((qbt,LK)=>{"use strict";var yHe=as();function EHe(t){if(t===null||t.length===0)return!1;var e=t,r=/\/([gim]*)$/.exec(t),o="";return!(e[0]==="/"&&(r&&(o=r[1]),o.length>3||e[e.length-o.length-1]!=="/"))}function CHe(t){var e=t,r=/\/([gim]*)$/.exec(t),o="";return e[0]==="/"&&(r&&(o=r[1]),e=e.slice(1,e.length-o.length-1)),new RegExp(e,o)}function wHe(t){var e="/"+t.source+"/";return t.global&&(e+="g"),t.multiline&&(e+="m"),t.ignoreCase&&(e+="i"),e}function IHe(t){return Object.prototype.toString.call(t)==="[object RegExp]"}LK.exports=new yHe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:EHe,construct:CHe,predicate:IHe,represent:wHe})});var _K=_((jbt,UK)=>{"use strict";var mP;try{OK=ve,mP=OK("esprima")}catch{typeof window<"u"&&(mP=window.esprima)}var OK,BHe=as();function vHe(t){if(t===null)return!1;try{var e="("+t+")",r=mP.parse(e,{range:!0});return!(r.type!=="Program"||r.body.length!==1||r.body[0].type!=="ExpressionStatement"||r.body[0].expression.type!=="ArrowFunctionExpression"&&r.body[0].expression.type!=="FunctionExpression")}catch{return!1}}function DHe(t){var e="("+t+")",r=mP.parse(e,{range:!0}),o=[],a;if(r.type!=="Program"||r.body.length!==1||r.body[0].type!=="ExpressionStatement"||r.body[0].expression.type!=="ArrowFunctionExpression"&&r.body[0].expression.type!=="FunctionExpression")throw new Error("Failed to resolve function");return r.body[0].expression.params.forEach(function(n){o.push(n.name)}),a=r.body[0].expression.body.range,r.body[0].expression.body.type==="BlockStatement"?new Function(o,e.slice(a[0]+1,a[1]-1)):new Function(o,"return "+e.slice(a[0],a[1]))}function PHe(t){return t.toString()}function SHe(t){return Object.prototype.toString.call(t)==="[object Function]"}UK.exports=new BHe("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:vHe,construct:DHe,predicate:SHe,represent:PHe})});var hI=_((Ybt,qK)=>{"use strict";var HK=$0();qK.exports=HK.DEFAULT=new HK({include:[Cm()],explicit:[NK(),MK(),_K()]})});var aV=_((Wbt,gI)=>{"use strict";var mf=Z0(),zK=ym(),bHe=zW(),JK=Cm(),xHe=hI(),Vp=Object.prototype.hasOwnProperty,yP=1,XK=2,ZK=3,EP=4,zT=1,kHe=2,jK=3,QHe=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,FHe=/[\x85\u2028\u2029]/,RHe=/[,\[\]\{\}]/,$K=/^(?:!|!!|![a-z\-]+!)$/i,eV=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function GK(t){return Object.prototype.toString.call(t)}function Yu(t){return t===10||t===13}function rg(t){return t===9||t===32}function Da(t){return t===9||t===32||t===10||t===13}function wm(t){return t===44||t===91||t===93||t===123||t===125}function THe(t){var e;return 48<=t&&t<=57?t-48:(e=t|32,97<=e&&e<=102?e-97+10:-1)}function NHe(t){return t===120?2:t===117?4:t===85?8:0}function LHe(t){return 48<=t&&t<=57?t-48:-1}function YK(t){return t===48?"\0":t===97?"\x07":t===98?"\b":t===116||t===9?" ":t===110?` +`:t===118?"\v":t===102?"\f":t===114?"\r":t===101?"\x1B":t===32?" ":t===34?'"':t===47?"/":t===92?"\\":t===78?"\x85":t===95?"\xA0":t===76?"\u2028":t===80?"\u2029":""}function MHe(t){return t<=65535?String.fromCharCode(t):String.fromCharCode((t-65536>>10)+55296,(t-65536&1023)+56320)}var tV=new Array(256),rV=new Array(256);for(tg=0;tg<256;tg++)tV[tg]=YK(tg)?1:0,rV[tg]=YK(tg);var tg;function OHe(t,e){this.input=t,this.filename=e.filename||null,this.schema=e.schema||xHe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=t.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function nV(t,e){return new zK(e,new bHe(t.filename,t.input,t.position,t.line,t.position-t.lineStart))}function Qr(t,e){throw nV(t,e)}function CP(t,e){t.onWarning&&t.onWarning.call(null,nV(t,e))}var WK={YAML:function(e,r,o){var a,n,u;e.version!==null&&Qr(e,"duplication of %YAML directive"),o.length!==1&&Qr(e,"YAML directive accepts exactly one argument"),a=/^([0-9]+)\.([0-9]+)$/.exec(o[0]),a===null&&Qr(e,"ill-formed argument of the YAML directive"),n=parseInt(a[1],10),u=parseInt(a[2],10),n!==1&&Qr(e,"unacceptable YAML version of the document"),e.version=o[0],e.checkLineBreaks=u<2,u!==1&&u!==2&&CP(e,"unsupported YAML version of the document")},TAG:function(e,r,o){var a,n;o.length!==2&&Qr(e,"TAG directive accepts exactly two arguments"),a=o[0],n=o[1],$K.test(a)||Qr(e,"ill-formed tag handle (first argument) of the TAG directive"),Vp.call(e.tagMap,a)&&Qr(e,'there is a previously declared suffix for "'+a+'" tag handle'),eV.test(n)||Qr(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[a]=n}};function Kp(t,e,r,o){var a,n,u,A;if(e1&&(t.result+=mf.repeat(` +`,e-1))}function UHe(t,e,r){var o,a,n,u,A,p,h,E,I=t.kind,D=t.result,x;if(x=t.input.charCodeAt(t.position),Da(x)||wm(x)||x===35||x===38||x===42||x===33||x===124||x===62||x===39||x===34||x===37||x===64||x===96||(x===63||x===45)&&(a=t.input.charCodeAt(t.position+1),Da(a)||r&&wm(a)))return!1;for(t.kind="scalar",t.result="",n=u=t.position,A=!1;x!==0;){if(x===58){if(a=t.input.charCodeAt(t.position+1),Da(a)||r&&wm(a))break}else if(x===35){if(o=t.input.charCodeAt(t.position-1),Da(o))break}else{if(t.position===t.lineStart&&wP(t)||r&&wm(x))break;if(Yu(x))if(p=t.line,h=t.lineStart,E=t.lineIndent,Wi(t,!1,-1),t.lineIndent>=e){A=!0,x=t.input.charCodeAt(t.position);continue}else{t.position=u,t.line=p,t.lineStart=h,t.lineIndent=E;break}}A&&(Kp(t,n,u,!1),XT(t,t.line-p),n=u=t.position,A=!1),rg(x)||(u=t.position+1),x=t.input.charCodeAt(++t.position)}return Kp(t,n,u,!1),t.result?!0:(t.kind=I,t.result=D,!1)}function _He(t,e){var r,o,a;if(r=t.input.charCodeAt(t.position),r!==39)return!1;for(t.kind="scalar",t.result="",t.position++,o=a=t.position;(r=t.input.charCodeAt(t.position))!==0;)if(r===39)if(Kp(t,o,t.position,!0),r=t.input.charCodeAt(++t.position),r===39)o=t.position,t.position++,a=t.position;else return!0;else Yu(r)?(Kp(t,o,a,!0),XT(t,Wi(t,!1,e)),o=a=t.position):t.position===t.lineStart&&wP(t)?Qr(t,"unexpected end of the document within a single quoted scalar"):(t.position++,a=t.position);Qr(t,"unexpected end of the stream within a single quoted scalar")}function HHe(t,e){var r,o,a,n,u,A;if(A=t.input.charCodeAt(t.position),A!==34)return!1;for(t.kind="scalar",t.result="",t.position++,r=o=t.position;(A=t.input.charCodeAt(t.position))!==0;){if(A===34)return Kp(t,r,t.position,!0),t.position++,!0;if(A===92){if(Kp(t,r,t.position,!0),A=t.input.charCodeAt(++t.position),Yu(A))Wi(t,!1,e);else if(A<256&&tV[A])t.result+=rV[A],t.position++;else if((u=NHe(A))>0){for(a=u,n=0;a>0;a--)A=t.input.charCodeAt(++t.position),(u=THe(A))>=0?n=(n<<4)+u:Qr(t,"expected hexadecimal character");t.result+=MHe(n),t.position++}else Qr(t,"unknown escape sequence");r=o=t.position}else Yu(A)?(Kp(t,r,o,!0),XT(t,Wi(t,!1,e)),r=o=t.position):t.position===t.lineStart&&wP(t)?Qr(t,"unexpected end of the document within a double quoted scalar"):(t.position++,o=t.position)}Qr(t,"unexpected end of the stream within a double quoted scalar")}function qHe(t,e){var r=!0,o,a=t.tag,n,u=t.anchor,A,p,h,E,I,D={},x,C,T,L;if(L=t.input.charCodeAt(t.position),L===91)p=93,I=!1,n=[];else if(L===123)p=125,I=!0,n={};else return!1;for(t.anchor!==null&&(t.anchorMap[t.anchor]=n),L=t.input.charCodeAt(++t.position);L!==0;){if(Wi(t,!0,e),L=t.input.charCodeAt(t.position),L===p)return t.position++,t.tag=a,t.anchor=u,t.kind=I?"mapping":"sequence",t.result=n,!0;r||Qr(t,"missed comma between flow collection entries"),C=x=T=null,h=E=!1,L===63&&(A=t.input.charCodeAt(t.position+1),Da(A)&&(h=E=!0,t.position++,Wi(t,!0,e))),o=t.line,Bm(t,e,yP,!1,!0),C=t.tag,x=t.result,Wi(t,!0,e),L=t.input.charCodeAt(t.position),(E||t.line===o)&&L===58&&(h=!0,L=t.input.charCodeAt(++t.position),Wi(t,!0,e),Bm(t,e,yP,!1,!0),T=t.result),I?Im(t,n,D,C,x,T):h?n.push(Im(t,null,D,C,x,T)):n.push(x),Wi(t,!0,e),L=t.input.charCodeAt(t.position),L===44?(r=!0,L=t.input.charCodeAt(++t.position)):r=!1}Qr(t,"unexpected end of the stream within a flow collection")}function jHe(t,e){var r,o,a=zT,n=!1,u=!1,A=e,p=0,h=!1,E,I;if(I=t.input.charCodeAt(t.position),I===124)o=!1;else if(I===62)o=!0;else return!1;for(t.kind="scalar",t.result="";I!==0;)if(I=t.input.charCodeAt(++t.position),I===43||I===45)zT===a?a=I===43?jK:kHe:Qr(t,"repeat of a chomping mode identifier");else if((E=LHe(I))>=0)E===0?Qr(t,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?Qr(t,"repeat of an indentation width identifier"):(A=e+E-1,u=!0);else break;if(rg(I)){do I=t.input.charCodeAt(++t.position);while(rg(I));if(I===35)do I=t.input.charCodeAt(++t.position);while(!Yu(I)&&I!==0)}for(;I!==0;){for(JT(t),t.lineIndent=0,I=t.input.charCodeAt(t.position);(!u||t.lineIndentA&&(A=t.lineIndent),Yu(I)){p++;continue}if(t.lineIndente)&&p!==0)Qr(t,"bad indentation of a sequence entry");else if(t.lineIndente)&&(Bm(t,e,EP,!0,a)&&(C?D=t.result:x=t.result),C||(Im(t,h,E,I,D,x,n,u),I=D=x=null),Wi(t,!0,-1),L=t.input.charCodeAt(t.position)),t.lineIndent>e&&L!==0)Qr(t,"bad indentation of a mapping entry");else if(t.lineIndente?p=1:t.lineIndent===e?p=0:t.lineIndente?p=1:t.lineIndent===e?p=0:t.lineIndent tag; it should be "scalar", not "'+t.kind+'"'),I=0,D=t.implicitTypes.length;I tag; it should be "'+x.kind+'", not "'+t.kind+'"'),x.resolve(t.result)?(t.result=x.construct(t.result),t.anchor!==null&&(t.anchorMap[t.anchor]=t.result)):Qr(t,"cannot resolve a node with !<"+t.tag+"> explicit tag")):Qr(t,"unknown tag !<"+t.tag+">");return t.listener!==null&&t.listener("close",t),t.tag!==null||t.anchor!==null||E}function VHe(t){var e=t.position,r,o,a,n=!1,u;for(t.version=null,t.checkLineBreaks=t.legacy,t.tagMap={},t.anchorMap={};(u=t.input.charCodeAt(t.position))!==0&&(Wi(t,!0,-1),u=t.input.charCodeAt(t.position),!(t.lineIndent>0||u!==37));){for(n=!0,u=t.input.charCodeAt(++t.position),r=t.position;u!==0&&!Da(u);)u=t.input.charCodeAt(++t.position);for(o=t.input.slice(r,t.position),a=[],o.length<1&&Qr(t,"directive name must not be less than one character in length");u!==0;){for(;rg(u);)u=t.input.charCodeAt(++t.position);if(u===35){do u=t.input.charCodeAt(++t.position);while(u!==0&&!Yu(u));break}if(Yu(u))break;for(r=t.position;u!==0&&!Da(u);)u=t.input.charCodeAt(++t.position);a.push(t.input.slice(r,t.position))}u!==0&&JT(t),Vp.call(WK,o)?WK[o](t,o,a):CP(t,'unknown document directive "'+o+'"')}if(Wi(t,!0,-1),t.lineIndent===0&&t.input.charCodeAt(t.position)===45&&t.input.charCodeAt(t.position+1)===45&&t.input.charCodeAt(t.position+2)===45?(t.position+=3,Wi(t,!0,-1)):n&&Qr(t,"directives end mark is expected"),Bm(t,t.lineIndent-1,EP,!1,!0),Wi(t,!0,-1),t.checkLineBreaks&&FHe.test(t.input.slice(e,t.position))&&CP(t,"non-ASCII line breaks are interpreted as content"),t.documents.push(t.result),t.position===t.lineStart&&wP(t)){t.input.charCodeAt(t.position)===46&&(t.position+=3,Wi(t,!0,-1));return}if(t.position"u"&&(r=e,e=null);var o=iV(t,r);if(typeof e!="function")return o;for(var a=0,n=o.length;a"u"&&(r=e,e=null),sV(t,e,mf.extend({schema:JK},r))}function JHe(t,e){return oV(t,mf.extend({schema:JK},e))}gI.exports.loadAll=sV;gI.exports.load=oV;gI.exports.safeLoadAll=zHe;gI.exports.safeLoad=JHe});var kV=_((Kbt,tN)=>{"use strict";var mI=Z0(),yI=ym(),XHe=hI(),ZHe=Cm(),gV=Object.prototype.toString,dV=Object.prototype.hasOwnProperty,$He=9,dI=10,e6e=13,t6e=32,r6e=33,n6e=34,mV=35,i6e=37,s6e=38,o6e=39,a6e=42,yV=44,l6e=45,EV=58,c6e=61,u6e=62,A6e=63,f6e=64,CV=91,wV=93,p6e=96,IV=123,h6e=124,BV=125,mo={};mo[0]="\\0";mo[7]="\\a";mo[8]="\\b";mo[9]="\\t";mo[10]="\\n";mo[11]="\\v";mo[12]="\\f";mo[13]="\\r";mo[27]="\\e";mo[34]='\\"';mo[92]="\\\\";mo[133]="\\N";mo[160]="\\_";mo[8232]="\\L";mo[8233]="\\P";var g6e=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function d6e(t,e){var r,o,a,n,u,A,p;if(e===null)return{};for(r={},o=Object.keys(e),a=0,n=o.length;a0?t.charCodeAt(n-1):null,D=D&&uV(u,A)}else{for(n=0;no&&t[I+1]!==" ",I=n);else if(!vm(u))return IP;A=n>0?t.charCodeAt(n-1):null,D=D&&uV(u,A)}h=h||E&&n-I-1>o&&t[I+1]!==" "}return!p&&!h?D&&!a(t)?DV:PV:r>9&&vV(t)?IP:h?bV:SV}function I6e(t,e,r,o){t.dump=function(){if(e.length===0)return"''";if(!t.noCompatMode&&g6e.indexOf(e)!==-1)return"'"+e+"'";var a=t.indent*Math.max(1,r),n=t.lineWidth===-1?-1:Math.max(Math.min(t.lineWidth,40),t.lineWidth-a),u=o||t.flowLevel>-1&&r>=t.flowLevel;function A(p){return y6e(t,p)}switch(w6e(e,u,t.indent,n,A)){case DV:return e;case PV:return"'"+e.replace(/'/g,"''")+"'";case SV:return"|"+AV(e,t.indent)+fV(cV(e,a));case bV:return">"+AV(e,t.indent)+fV(cV(B6e(e,n),a));case IP:return'"'+v6e(e,n)+'"';default:throw new yI("impossible error: invalid scalar style")}}()}function AV(t,e){var r=vV(t)?String(e):"",o=t[t.length-1]===` +`,a=o&&(t[t.length-2]===` +`||t===` +`),n=a?"+":o?"":"-";return r+n+` +`}function fV(t){return t[t.length-1]===` +`?t.slice(0,-1):t}function B6e(t,e){for(var r=/(\n+)([^\n]*)/g,o=function(){var h=t.indexOf(` +`);return h=h!==-1?h:t.length,r.lastIndex=h,pV(t.slice(0,h),e)}(),a=t[0]===` +`||t[0]===" ",n,u;u=r.exec(t);){var A=u[1],p=u[2];n=p[0]===" ",o+=A+(!a&&!n&&p!==""?` +`:"")+pV(p,e),a=n}return o}function pV(t,e){if(t===""||t[0]===" ")return t;for(var r=/ [^ ]/g,o,a=0,n,u=0,A=0,p="";o=r.exec(t);)A=o.index,A-a>e&&(n=u>a?u:A,p+=` +`+t.slice(a,n),a=n+1),u=A;return p+=` +`,t.length-a>e&&u>a?p+=t.slice(a,u)+` +`+t.slice(u+1):p+=t.slice(a),p.slice(1)}function v6e(t){for(var e="",r,o,a,n=0;n=55296&&r<=56319&&(o=t.charCodeAt(n+1),o>=56320&&o<=57343)){e+=lV((r-55296)*1024+o-56320+65536),n++;continue}a=mo[r],e+=!a&&vm(r)?t[n]:a||lV(r)}return e}function D6e(t,e,r){var o="",a=t.tag,n,u;for(n=0,u=r.length;n1024&&(E+="? "),E+=t.dump+(t.condenseFlow?'"':"")+":"+(t.condenseFlow?"":" "),ng(t,e,h,!1,!1)&&(E+=t.dump,o+=E));t.tag=a,t.dump="{"+o+"}"}function b6e(t,e,r,o){var a="",n=t.tag,u=Object.keys(r),A,p,h,E,I,D;if(t.sortKeys===!0)u.sort();else if(typeof t.sortKeys=="function")u.sort(t.sortKeys);else if(t.sortKeys)throw new yI("sortKeys must be a boolean or a function");for(A=0,p=u.length;A1024,I&&(t.dump&&dI===t.dump.charCodeAt(0)?D+="?":D+="? "),D+=t.dump,I&&(D+=ZT(t,e)),ng(t,e+1,E,!0,I)&&(t.dump&&dI===t.dump.charCodeAt(0)?D+=":":D+=": ",D+=t.dump,a+=D));t.tag=n,t.dump=a||"{}"}function hV(t,e,r){var o,a,n,u,A,p;for(a=r?t.explicitTypes:t.implicitTypes,n=0,u=a.length;n tag resolver accepts not "'+p+'" style');t.dump=o}return!0}return!1}function ng(t,e,r,o,a,n){t.tag=null,t.dump=r,hV(t,r,!1)||hV(t,r,!0);var u=gV.call(t.dump);o&&(o=t.flowLevel<0||t.flowLevel>e);var A=u==="[object Object]"||u==="[object Array]",p,h;if(A&&(p=t.duplicates.indexOf(r),h=p!==-1),(t.tag!==null&&t.tag!=="?"||h||t.indent!==2&&e>0)&&(a=!1),h&&t.usedDuplicates[p])t.dump="*ref_"+p;else{if(A&&h&&!t.usedDuplicates[p]&&(t.usedDuplicates[p]=!0),u==="[object Object]")o&&Object.keys(t.dump).length!==0?(b6e(t,e,t.dump,a),h&&(t.dump="&ref_"+p+t.dump)):(S6e(t,e,t.dump),h&&(t.dump="&ref_"+p+" "+t.dump));else if(u==="[object Array]"){var E=t.noArrayIndent&&e>0?e-1:e;o&&t.dump.length!==0?(P6e(t,E,t.dump,a),h&&(t.dump="&ref_"+p+t.dump)):(D6e(t,E,t.dump),h&&(t.dump="&ref_"+p+" "+t.dump))}else if(u==="[object String]")t.tag!=="?"&&I6e(t,t.dump,e,n);else{if(t.skipInvalid)return!1;throw new yI("unacceptable kind of an object to dump "+u)}t.tag!==null&&t.tag!=="?"&&(t.dump="!<"+t.tag+"> "+t.dump)}return!0}function x6e(t,e){var r=[],o=[],a,n;for($T(t,r,o),a=0,n=o.length;a{"use strict";var BP=aV(),QV=kV();function vP(t){return function(){throw new Error("Function "+t+" is deprecated and cannot be used.")}}Fi.exports.Type=as();Fi.exports.Schema=$0();Fi.exports.FAILSAFE_SCHEMA=dP();Fi.exports.JSON_SCHEMA=WT();Fi.exports.CORE_SCHEMA=KT();Fi.exports.DEFAULT_SAFE_SCHEMA=Cm();Fi.exports.DEFAULT_FULL_SCHEMA=hI();Fi.exports.load=BP.load;Fi.exports.loadAll=BP.loadAll;Fi.exports.safeLoad=BP.safeLoad;Fi.exports.safeLoadAll=BP.safeLoadAll;Fi.exports.dump=QV.dump;Fi.exports.safeDump=QV.safeDump;Fi.exports.YAMLException=ym();Fi.exports.MINIMAL_SCHEMA=dP();Fi.exports.SAFE_SCHEMA=Cm();Fi.exports.DEFAULT_SCHEMA=hI();Fi.exports.scan=vP("scan");Fi.exports.parse=vP("parse");Fi.exports.compose=vP("compose");Fi.exports.addConstructor=vP("addConstructor")});var TV=_((zbt,RV)=>{"use strict";var Q6e=FV();RV.exports=Q6e});var LV=_((Jbt,NV)=>{"use strict";function F6e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function ig(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,ig)}F6e(ig,Error);ig.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I0){for(I=1,D=1;I({[ht]:Le})))},ce=function(ee){return ee},ue=function(ee){return ee},Ce=oa("correct indentation"),he=" ",De=un(" ",!1),Ee=function(ee){return ee.length===ar*vt},g=function(ee){return ee.length===(ar+1)*vt},me=function(){return ar++,!0},we=function(){return ar--,!0},fe=function(){return No()},ie=oa("pseudostring"),Z=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,xe=qn(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),Re=/^[^\r\n\t ,\][{}:#"']/,gt=qn(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),q=function(){return No().replace(/^ *| *$/g,"")},nt="--",Ne=un("--",!1),Te=/^[a-zA-Z\/0-9]/,ke=qn([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),Ve=/^[^\r\n\t :,]/,Se=qn(["\r",` +`," "," ",":",","],!0,!1),tt="null",He=un("null",!1),b=function(){return null},w="true",S=un("true",!1),y=function(){return!0},R="false",J=un("false",!1),X=function(){return!1},$=oa("string"),se='"',be=un('"',!1),Fe=function(){return""},lt=function(ee){return ee},Et=function(ee){return ee.join("")},qt=/^[^"\\\0-\x1F\x7F]/,nr=qn(['"',"\\",["\0",""],"\x7F"],!0,!1),St='\\"',cn=un('\\"',!1),Pr=function(){return'"'},yr="\\\\",Rr=un("\\\\",!1),Xr=function(){return"\\"},$n="\\/",Xs=un("\\/",!1),Hi=function(){return"/"},Qs="\\b",Zs=un("\\b",!1),xi=function(){return"\b"},Fs="\\f",$s=un("\\f",!1),SA=function(){return"\f"},gu="\\n",op=un("\\n",!1),ap=function(){return` +`},Rs="\\r",Ln=un("\\r",!1),hs=function(){return"\r"},Ts="\\t",pc=un("\\t",!1),hc=function(){return" "},gc="\\u",bA=un("\\u",!1),xA=function(ee,ye,Le,ht){return String.fromCharCode(parseInt(`0x${ee}${ye}${Le}${ht}`))},Ro=/^[0-9a-fA-F]/,To=qn([["0","9"],["a","f"],["A","F"]],!1,!1),kA=oa("blank space"),pr=/^[ \t]/,Oe=qn([" "," "],!1,!1),ia=oa("white space"),dc=/^[ \t\n\r]/,Er=qn([" "," ",` +`,"\r"],!1,!1),du=`\r +`,QA=un(`\r +`,!1),FA=` +`,mc=un(` +`,!1),yc="\r",wl=un("\r",!1),Ie=0,Tt=0,Il=[{line:1,column:1}],Bi=0,Ns=[],Ft=0,Bn;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function No(){return t.substring(Tt,Ie)}function ki(){return la(Tt,Ie)}function vi(ee,ye){throw ye=ye!==void 0?ye:la(Tt,Ie),mu([oa(ee)],t.substring(Tt,Ie),ye)}function sa(ee,ye){throw ye=ye!==void 0?ye:la(Tt,Ie),ca(ee,ye)}function un(ee,ye){return{type:"literal",text:ee,ignoreCase:ye}}function qn(ee,ye,Le){return{type:"class",parts:ee,inverted:ye,ignoreCase:Le}}function Ec(){return{type:"any"}}function lp(){return{type:"end"}}function oa(ee){return{type:"other",description:ee}}function aa(ee){var ye=Il[ee],Le;if(ye)return ye;for(Le=ee-1;!Il[Le];)Le--;for(ye=Il[Le],ye={line:ye.line,column:ye.column};LeBi&&(Bi=Ie,Ns=[]),Ns.push(ee))}function ca(ee,ye){return new ig(ee,null,null,ye)}function mu(ee,ye,Le){return new ig(ig.buildMessage(ee,ye),ee,ye,Le)}function Bl(){var ee;return ee=RA(),ee}function dn(){var ee,ye,Le;for(ee=Ie,ye=[],Le=Lo();Le!==r;)ye.push(Le),Le=Lo();return ye!==r&&(Tt=ee,ye=n(ye)),ee=ye,ee}function Lo(){var ee,ye,Le,ht,mt;return ee=Ie,ye=qa(),ye!==r?(t.charCodeAt(Ie)===45?(Le=u,Ie++):(Le=r,Ft===0&&Ze(A)),Le!==r?(ht=Dn(),ht!==r?(mt=Mo(),mt!==r?(Tt=ee,ye=p(mt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee}function RA(){var ee,ye,Le;for(ee=Ie,ye=[],Le=TA();Le!==r;)ye.push(Le),Le=TA();return ye!==r&&(Tt=ee,ye=h(ye)),ee=ye,ee}function TA(){var ee,ye,Le,ht,mt,Dt,er,sn,ei;if(ee=Ie,ye=Dn(),ye===r&&(ye=null),ye!==r){if(Le=Ie,t.charCodeAt(Ie)===35?(ht=E,Ie++):(ht=r,Ft===0&&Ze(I)),ht!==r){if(mt=[],Dt=Ie,er=Ie,Ft++,sn=it(),Ft--,sn===r?er=void 0:(Ie=er,er=r),er!==r?(t.length>Ie?(sn=t.charAt(Ie),Ie++):(sn=r,Ft===0&&Ze(D)),sn!==r?(er=[er,sn],Dt=er):(Ie=Dt,Dt=r)):(Ie=Dt,Dt=r),Dt!==r)for(;Dt!==r;)mt.push(Dt),Dt=Ie,er=Ie,Ft++,sn=it(),Ft--,sn===r?er=void 0:(Ie=er,er=r),er!==r?(t.length>Ie?(sn=t.charAt(Ie),Ie++):(sn=r,Ft===0&&Ze(D)),sn!==r?(er=[er,sn],Dt=er):(Ie=Dt,Dt=r)):(Ie=Dt,Dt=r);else mt=r;mt!==r?(ht=[ht,mt],Le=ht):(Ie=Le,Le=r)}else Ie=Le,Le=r;if(Le===r&&(Le=null),Le!==r){if(ht=[],mt=ze(),mt!==r)for(;mt!==r;)ht.push(mt),mt=ze();else ht=r;ht!==r?(Tt=ee,ye=x(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r}else Ie=ee,ee=r;if(ee===r&&(ee=Ie,ye=qa(),ye!==r?(Le=ua(),Le!==r?(ht=Dn(),ht===r&&(ht=null),ht!==r?(t.charCodeAt(Ie)===58?(mt=C,Ie++):(mt=r,Ft===0&&Ze(T)),mt!==r?(Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(er=Mo(),er!==r?(Tt=ee,ye=L(Le,er),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,ye=qa(),ye!==r?(Le=qi(),Le!==r?(ht=Dn(),ht===r&&(ht=null),ht!==r?(t.charCodeAt(Ie)===58?(mt=C,Ie++):(mt=r,Ft===0&&Ze(T)),mt!==r?(Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(er=Mo(),er!==r?(Tt=ee,ye=L(Le,er),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r))){if(ee=Ie,ye=qa(),ye!==r)if(Le=qi(),Le!==r)if(ht=Dn(),ht!==r)if(mt=Cc(),mt!==r){if(Dt=[],er=ze(),er!==r)for(;er!==r;)Dt.push(er),er=ze();else Dt=r;Dt!==r?(Tt=ee,ye=L(Le,mt),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r;else Ie=ee,ee=r;else Ie=ee,ee=r;if(ee===r)if(ee=Ie,ye=qa(),ye!==r)if(Le=qi(),Le!==r){if(ht=[],mt=Ie,Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(t.charCodeAt(Ie)===44?(er=U,Ie++):(er=r,Ft===0&&Ze(z)),er!==r?(sn=Dn(),sn===r&&(sn=null),sn!==r?(ei=qi(),ei!==r?(Tt=mt,Dt=te(Le,ei),mt=Dt):(Ie=mt,mt=r)):(Ie=mt,mt=r)):(Ie=mt,mt=r)):(Ie=mt,mt=r),mt!==r)for(;mt!==r;)ht.push(mt),mt=Ie,Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(t.charCodeAt(Ie)===44?(er=U,Ie++):(er=r,Ft===0&&Ze(z)),er!==r?(sn=Dn(),sn===r&&(sn=null),sn!==r?(ei=qi(),ei!==r?(Tt=mt,Dt=te(Le,ei),mt=Dt):(Ie=mt,mt=r)):(Ie=mt,mt=r)):(Ie=mt,mt=r)):(Ie=mt,mt=r);else ht=r;ht!==r?(mt=Dn(),mt===r&&(mt=null),mt!==r?(t.charCodeAt(Ie)===58?(Dt=C,Ie++):(Dt=r,Ft===0&&Ze(T)),Dt!==r?(er=Dn(),er===r&&(er=null),er!==r?(sn=Mo(),sn!==r?(Tt=ee,ye=le(Le,ht,sn),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r}return ee}function Mo(){var ee,ye,Le,ht,mt,Dt,er;if(ee=Ie,ye=Ie,Ft++,Le=Ie,ht=it(),ht!==r?(mt=Mt(),mt!==r?(t.charCodeAt(Ie)===45?(Dt=u,Ie++):(Dt=r,Ft===0&&Ze(A)),Dt!==r?(er=Dn(),er!==r?(ht=[ht,mt,Dt,er],Le=ht):(Ie=Le,Le=r)):(Ie=Le,Le=r)):(Ie=Le,Le=r)):(Ie=Le,Le=r),Ft--,Le!==r?(Ie=ye,ye=void 0):ye=r,ye!==r?(Le=ze(),Le!==r?(ht=vn(),ht!==r?(mt=dn(),mt!==r?(Dt=Oo(),Dt!==r?(Tt=ee,ye=ce(mt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,ye=it(),ye!==r?(Le=vn(),Le!==r?(ht=RA(),ht!==r?(mt=Oo(),mt!==r?(Tt=ee,ye=ce(ht),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r))if(ee=Ie,ye=vl(),ye!==r){if(Le=[],ht=ze(),ht!==r)for(;ht!==r;)Le.push(ht),ht=ze();else Le=r;Le!==r?(Tt=ee,ye=ue(ye),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return ee}function qa(){var ee,ye,Le;for(Ft++,ee=Ie,ye=[],t.charCodeAt(Ie)===32?(Le=he,Ie++):(Le=r,Ft===0&&Ze(De));Le!==r;)ye.push(Le),t.charCodeAt(Ie)===32?(Le=he,Ie++):(Le=r,Ft===0&&Ze(De));return ye!==r?(Tt=Ie,Le=Ee(ye),Le?Le=void 0:Le=r,Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),Ft--,ee===r&&(ye=r,Ft===0&&Ze(Ce)),ee}function Mt(){var ee,ye,Le;for(ee=Ie,ye=[],t.charCodeAt(Ie)===32?(Le=he,Ie++):(Le=r,Ft===0&&Ze(De));Le!==r;)ye.push(Le),t.charCodeAt(Ie)===32?(Le=he,Ie++):(Le=r,Ft===0&&Ze(De));return ye!==r?(Tt=Ie,Le=g(ye),Le?Le=void 0:Le=r,Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee}function vn(){var ee;return Tt=Ie,ee=me(),ee?ee=void 0:ee=r,ee}function Oo(){var ee;return Tt=Ie,ee=we(),ee?ee=void 0:ee=r,ee}function ua(){var ee;return ee=ja(),ee===r&&(ee=Dl()),ee}function qi(){var ee,ye,Le;if(ee=ja(),ee===r){if(ee=Ie,ye=[],Le=Aa(),Le!==r)for(;Le!==r;)ye.push(Le),Le=Aa();else ye=r;ye!==r&&(Tt=ee,ye=fe()),ee=ye}return ee}function vl(){var ee;return ee=Di(),ee===r&&(ee=rs(),ee===r&&(ee=ja(),ee===r&&(ee=Dl()))),ee}function Cc(){var ee;return ee=Di(),ee===r&&(ee=ja(),ee===r&&(ee=Aa())),ee}function Dl(){var ee,ye,Le,ht,mt,Dt;if(Ft++,ee=Ie,Z.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Ft===0&&Ze(xe)),ye!==r){for(Le=[],ht=Ie,mt=Dn(),mt===r&&(mt=null),mt!==r?(Re.test(t.charAt(Ie))?(Dt=t.charAt(Ie),Ie++):(Dt=r,Ft===0&&Ze(gt)),Dt!==r?(mt=[mt,Dt],ht=mt):(Ie=ht,ht=r)):(Ie=ht,ht=r);ht!==r;)Le.push(ht),ht=Ie,mt=Dn(),mt===r&&(mt=null),mt!==r?(Re.test(t.charAt(Ie))?(Dt=t.charAt(Ie),Ie++):(Dt=r,Ft===0&&Ze(gt)),Dt!==r?(mt=[mt,Dt],ht=mt):(Ie=ht,ht=r)):(Ie=ht,ht=r);Le!==r?(Tt=ee,ye=q(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(ie)),ee}function Aa(){var ee,ye,Le,ht,mt;if(ee=Ie,t.substr(Ie,2)===nt?(ye=nt,Ie+=2):(ye=r,Ft===0&&Ze(Ne)),ye===r&&(ye=null),ye!==r)if(Te.test(t.charAt(Ie))?(Le=t.charAt(Ie),Ie++):(Le=r,Ft===0&&Ze(ke)),Le!==r){for(ht=[],Ve.test(t.charAt(Ie))?(mt=t.charAt(Ie),Ie++):(mt=r,Ft===0&&Ze(Se));mt!==r;)ht.push(mt),Ve.test(t.charAt(Ie))?(mt=t.charAt(Ie),Ie++):(mt=r,Ft===0&&Ze(Se));ht!==r?(Tt=ee,ye=q(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r;return ee}function Di(){var ee,ye;return ee=Ie,t.substr(Ie,4)===tt?(ye=tt,Ie+=4):(ye=r,Ft===0&&Ze(He)),ye!==r&&(Tt=ee,ye=b()),ee=ye,ee}function rs(){var ee,ye;return ee=Ie,t.substr(Ie,4)===w?(ye=w,Ie+=4):(ye=r,Ft===0&&Ze(S)),ye!==r&&(Tt=ee,ye=y()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,5)===R?(ye=R,Ie+=5):(ye=r,Ft===0&&Ze(J)),ye!==r&&(Tt=ee,ye=X()),ee=ye),ee}function ja(){var ee,ye,Le,ht;return Ft++,ee=Ie,t.charCodeAt(Ie)===34?(ye=se,Ie++):(ye=r,Ft===0&&Ze(be)),ye!==r?(t.charCodeAt(Ie)===34?(Le=se,Ie++):(Le=r,Ft===0&&Ze(be)),Le!==r?(Tt=ee,ye=Fe(),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,t.charCodeAt(Ie)===34?(ye=se,Ie++):(ye=r,Ft===0&&Ze(be)),ye!==r?(Le=yu(),Le!==r?(t.charCodeAt(Ie)===34?(ht=se,Ie++):(ht=r,Ft===0&&Ze(be)),ht!==r?(Tt=ee,ye=lt(Le),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)),Ft--,ee===r&&(ye=r,Ft===0&&Ze($)),ee}function yu(){var ee,ye,Le;if(ee=Ie,ye=[],Le=Pl(),Le!==r)for(;Le!==r;)ye.push(Le),Le=Pl();else ye=r;return ye!==r&&(Tt=ee,ye=Et(ye)),ee=ye,ee}function Pl(){var ee,ye,Le,ht,mt,Dt;return qt.test(t.charAt(Ie))?(ee=t.charAt(Ie),Ie++):(ee=r,Ft===0&&Ze(nr)),ee===r&&(ee=Ie,t.substr(Ie,2)===St?(ye=St,Ie+=2):(ye=r,Ft===0&&Ze(cn)),ye!==r&&(Tt=ee,ye=Pr()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===yr?(ye=yr,Ie+=2):(ye=r,Ft===0&&Ze(Rr)),ye!==r&&(Tt=ee,ye=Xr()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===$n?(ye=$n,Ie+=2):(ye=r,Ft===0&&Ze(Xs)),ye!==r&&(Tt=ee,ye=Hi()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Qs?(ye=Qs,Ie+=2):(ye=r,Ft===0&&Ze(Zs)),ye!==r&&(Tt=ee,ye=xi()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Fs?(ye=Fs,Ie+=2):(ye=r,Ft===0&&Ze($s)),ye!==r&&(Tt=ee,ye=SA()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===gu?(ye=gu,Ie+=2):(ye=r,Ft===0&&Ze(op)),ye!==r&&(Tt=ee,ye=ap()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Rs?(ye=Rs,Ie+=2):(ye=r,Ft===0&&Ze(Ln)),ye!==r&&(Tt=ee,ye=hs()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Ts?(ye=Ts,Ie+=2):(ye=r,Ft===0&&Ze(pc)),ye!==r&&(Tt=ee,ye=hc()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===gc?(ye=gc,Ie+=2):(ye=r,Ft===0&&Ze(bA)),ye!==r?(Le=pi(),Le!==r?(ht=pi(),ht!==r?(mt=pi(),mt!==r?(Dt=pi(),Dt!==r?(Tt=ee,ye=xA(Le,ht,mt,Dt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)))))))))),ee}function pi(){var ee;return Ro.test(t.charAt(Ie))?(ee=t.charAt(Ie),Ie++):(ee=r,Ft===0&&Ze(To)),ee}function Dn(){var ee,ye;if(Ft++,ee=[],pr.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Ft===0&&Ze(Oe)),ye!==r)for(;ye!==r;)ee.push(ye),pr.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Ft===0&&Ze(Oe));else ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(kA)),ee}function Sl(){var ee,ye;if(Ft++,ee=[],dc.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Ft===0&&Ze(Er)),ye!==r)for(;ye!==r;)ee.push(ye),dc.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Ft===0&&Ze(Er));else ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(ia)),ee}function ze(){var ee,ye,Le,ht,mt,Dt;if(ee=Ie,ye=it(),ye!==r){for(Le=[],ht=Ie,mt=Dn(),mt===r&&(mt=null),mt!==r?(Dt=it(),Dt!==r?(mt=[mt,Dt],ht=mt):(Ie=ht,ht=r)):(Ie=ht,ht=r);ht!==r;)Le.push(ht),ht=Ie,mt=Dn(),mt===r&&(mt=null),mt!==r?(Dt=it(),Dt!==r?(mt=[mt,Dt],ht=mt):(Ie=ht,ht=r)):(Ie=ht,ht=r);Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return ee}function it(){var ee;return t.substr(Ie,2)===du?(ee=du,Ie+=2):(ee=r,Ft===0&&Ze(QA)),ee===r&&(t.charCodeAt(Ie)===10?(ee=FA,Ie++):(ee=r,Ft===0&&Ze(mc)),ee===r&&(t.charCodeAt(Ie)===13?(ee=yc,Ie++):(ee=r,Ft===0&&Ze(wl)))),ee}let vt=2,ar=0;if(Bn=a(),Bn!==r&&Ie===t.length)return Bn;throw Bn!==r&&Ie"u"?!0:typeof t=="object"&&t!==null&&!Array.isArray(t)?Object.keys(t).every(e=>_V(t[e])):!1}function rN(t,e,r){if(t===null)return`null +`;if(typeof t=="number"||typeof t=="boolean")return`${t.toString()} +`;if(typeof t=="string")return`${OV(t)} +`;if(Array.isArray(t)){if(t.length===0)return`[] +`;let o=" ".repeat(e);return` +${t.map(n=>`${o}- ${rN(n,e+1,!1)}`).join("")}`}if(typeof t=="object"&&t){let[o,a]=t instanceof DP?[t.data,!1]:[t,!0],n=" ".repeat(e),u=Object.keys(o);a&&u.sort((p,h)=>{let E=MV.indexOf(p),I=MV.indexOf(h);return E===-1&&I===-1?ph?1:0:E!==-1&&I===-1?-1:E===-1&&I!==-1?1:E-I});let A=u.filter(p=>!_V(o[p])).map((p,h)=>{let E=o[p],I=OV(p),D=rN(E,e+1,!0),x=h>0||r?n:"",C=I.length>1024?`? ${I} +${x}:`:`${I}:`,T=D.startsWith(` +`)?D:` ${D}`;return`${x}${C}${T}`}).join(e===0?` +`:"")||` +`;return r?` +${A}`:`${A}`}throw new Error(`Unsupported value type (${t})`)}function Pa(t){try{let e=rN(t,0,!1);return e!==` +`?e:""}catch(e){throw e.location&&(e.message=e.message.replace(/(\.)?$/,` (line ${e.location.start.line}, column ${e.location.start.column})$1`)),e}}function N6e(t){return t.endsWith(` +`)||(t+=` +`),(0,UV.parse)(t)}function M6e(t){if(L6e.test(t))return N6e(t);let e=(0,PP.safeLoad)(t,{schema:PP.FAILSAFE_SCHEMA,json:!0});if(e==null)return{};if(typeof e!="object")throw new Error(`Expected an indexed object, got a ${typeof e} instead. Does your file follow Yaml's rules?`);if(Array.isArray(e))throw new Error("Expected an indexed object, got an array instead. Does your file follow Yaml's rules?");return e}function Ki(t){return M6e(t)}var PP,UV,T6e,MV,DP,L6e,HV=wt(()=>{PP=et(TV()),UV=et(LV()),T6e=/^(?![-?:,\][{}#&*!|>'"%@` \t\r\n]).([ \t]*(?![,\][{}:# \t\r\n]).)*$/,MV=["__metadata","version","resolution","dependencies","peerDependencies","dependenciesMeta","peerDependenciesMeta","binaries"],DP=class{constructor(e){this.data=e}};Pa.PreserveOrdering=DP;L6e=/^(#.*(\r?\n))*?#\s+yarn\s+lockfile\s+v1\r?\n/i});var EI={};Kt(EI,{parseResolution:()=>pP,parseShell:()=>uP,parseSyml:()=>Ki,stringifyArgument:()=>qT,stringifyArgumentSegment:()=>jT,stringifyArithmeticExpression:()=>fP,stringifyCommand:()=>HT,stringifyCommandChain:()=>mm,stringifyCommandChainThen:()=>_T,stringifyCommandLine:()=>AP,stringifyCommandLineThen:()=>UT,stringifyEnvSegment:()=>cP,stringifyRedirectArgument:()=>fI,stringifyResolution:()=>hP,stringifyShell:()=>dm,stringifyShellLine:()=>dm,stringifySyml:()=>Pa,stringifyValueArgument:()=>z0});var Ml=wt(()=>{_W();GW();HV()});var jV=_((txt,nN)=>{"use strict";var O6e=t=>{let e=!1,r=!1,o=!1;for(let a=0;a{if(!(typeof t=="string"||Array.isArray(t)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let r=a=>e.pascalCase?a.charAt(0).toUpperCase()+a.slice(1):a;return Array.isArray(t)?t=t.map(a=>a.trim()).filter(a=>a.length).join("-"):t=t.trim(),t.length===0?"":t.length===1?e.pascalCase?t.toUpperCase():t.toLowerCase():(t!==t.toLowerCase()&&(t=O6e(t)),t=t.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(a,n)=>n.toUpperCase()).replace(/\d+(\w|$)/g,a=>a.toUpperCase()),r(t))};nN.exports=qV;nN.exports.default=qV});var GV=_((rxt,U6e)=>{U6e.exports=[{name:"Agola CI",constant:"AGOLA",env:"AGOLA_GIT_REF",pr:"AGOLA_PULL_REQUEST_ID"},{name:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"TF_BUILD",pr:{BUILD_REASON:"PullRequest"}},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{name:"Codemagic",constant:"CODEMAGIC",env:"CM_BUILD_ID",pr:"CM_PULL_REQUEST"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"Earthly",constant:"EARTHLY",env:"EARTHLY_CI"},{name:"Expo Application Services",constant:"EAS",env:"EAS_BUILD"},{name:"Gerrit",constant:"GERRIT",env:"GERRIT_PROJECT"},{name:"Gitea Actions",constant:"GITEA_ACTIONS",env:"GITEA_ACTIONS"},{name:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Google Cloud Build",constant:"GOOGLE_CLOUD_BUILD",env:"BUILDER_OUTPUT"},{name:"Harness CI",constant:"HARNESS",env:"HARNESS_BUILD_ID"},{name:"Heroku",constant:"HEROKU",env:{env:"NODE",includes:"/app/.heroku/node/bin/node"}},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Prow",constant:"PROW",env:"PROW_JOB_ID"},{name:"ReleaseHub",constant:"RELEASEHUB",env:"RELEASE_BUILD_ID"},{name:"Render",constant:"RENDER",env:"RENDER",pr:{IS_PULL_REQUEST:"true"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Screwdriver",constant:"SCREWDRIVER",env:"SCREWDRIVER",pr:{env:"SD_PULL_REQUEST",ne:"false"}},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Sourcehut",constant:"SOURCEHUT",env:{CI_NAME:"sourcehut"}},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}},{name:"Vela",constant:"VELA",env:"VELA",pr:{VELA_PULL_REQUEST:"1"}},{name:"Vercel",constant:"VERCEL",env:{any:["NOW_BUILDER","VERCEL"]},pr:"VERCEL_GIT_PULL_REQUEST_ID"},{name:"Visual Studio App Center",constant:"APPCENTER",env:"APPCENTER_BUILD_ID"},{name:"Woodpecker",constant:"WOODPECKER",env:{CI:"woodpecker"},pr:{CI_BUILD_EVENT:"pull_request"}},{name:"Xcode Cloud",constant:"XCODE_CLOUD",env:"CI_XCODE_PROJECT",pr:"CI_PULL_REQUEST_NUMBER"},{name:"Xcode Server",constant:"XCODE_SERVER",env:"XCS"}]});var sg=_(nl=>{"use strict";var WV=GV(),ls=process.env;Object.defineProperty(nl,"_vendors",{value:WV.map(function(t){return t.constant})});nl.name=null;nl.isPR=null;WV.forEach(function(t){let r=(Array.isArray(t.env)?t.env:[t.env]).every(function(o){return YV(o)});if(nl[t.constant]=r,!!r)switch(nl.name=t.name,typeof t.pr){case"string":nl.isPR=!!ls[t.pr];break;case"object":"env"in t.pr?nl.isPR=t.pr.env in ls&&ls[t.pr.env]!==t.pr.ne:"any"in t.pr?nl.isPR=t.pr.any.some(function(o){return!!ls[o]}):nl.isPR=YV(t.pr);break;default:nl.isPR=null}});nl.isCI=!!(ls.CI!=="false"&&(ls.BUILD_ID||ls.BUILD_NUMBER||ls.CI||ls.CI_APP_ID||ls.CI_BUILD_ID||ls.CI_BUILD_NUMBER||ls.CI_NAME||ls.CONTINUOUS_INTEGRATION||ls.RUN_ID||nl.name));function YV(t){return typeof t=="string"?!!ls[t]:"env"in t?ls[t.env]&&ls[t.env].includes(t.includes):"any"in t?t.any.some(function(e){return!!ls[e]}):Object.keys(t).every(function(e){return ls[e]===t[e]})}});var Kn,pn,og,iN,SP,KV,sN,oN,bP=wt(()=>{(function(t){t.StartOfInput="\0",t.EndOfInput="",t.EndOfPartialInput=""})(Kn||(Kn={}));(function(t){t[t.InitialNode=0]="InitialNode",t[t.SuccessNode=1]="SuccessNode",t[t.ErrorNode=2]="ErrorNode",t[t.CustomNode=3]="CustomNode"})(pn||(pn={}));og=-1,iN=/^(-h|--help)(?:=([0-9]+))?$/,SP=/^(--[a-z]+(?:-[a-z]+)*|-[a-zA-Z]+)$/,KV=/^-[a-zA-Z]{2,}$/,sN=/^([^=]+)=([\s\S]*)$/,oN=process.env.DEBUG_CLI==="1"});var ot,Dm,xP,aN,kP=wt(()=>{bP();ot=class extends Error{constructor(e){super(e),this.clipanion={type:"usage"},this.name="UsageError"}},Dm=class extends Error{constructor(e,r){if(super(),this.input=e,this.candidates=r,this.clipanion={type:"none"},this.name="UnknownSyntaxError",this.candidates.length===0)this.message="Command not found, but we're not sure what's the alternative.";else if(this.candidates.every(o=>o.reason!==null&&o.reason===r[0].reason)){let[{reason:o}]=this.candidates;this.message=`${o} + +${this.candidates.map(({usage:a})=>`$ ${a}`).join(` +`)}`}else if(this.candidates.length===1){let[{usage:o}]=this.candidates;this.message=`Command not found; did you mean: + +$ ${o} +${aN(e)}`}else this.message=`Command not found; did you mean one of: + +${this.candidates.map(({usage:o},a)=>`${`${a}.`.padStart(4)} ${o}`).join(` +`)} + +${aN(e)}`}},xP=class extends Error{constructor(e,r){super(),this.input=e,this.usages=r,this.clipanion={type:"none"},this.name="AmbiguousSyntaxError",this.message=`Cannot find which to pick amongst the following alternatives: + +${this.usages.map((o,a)=>`${`${a}.`.padStart(4)} ${o}`).join(` +`)} + +${aN(e)}`}},aN=t=>`While running ${t.filter(e=>e!==Kn.EndOfInput&&e!==Kn.EndOfPartialInput).map(e=>{let r=JSON.stringify(e);return e.match(/\s/)||e.length===0||r!==`"${e}"`?r:e}).join(" ")}`});function _6e(t){let e=t.split(` +`),r=e.filter(a=>a.match(/\S/)),o=r.length>0?r.reduce((a,n)=>Math.min(a,n.length-n.trimStart().length),Number.MAX_VALUE):0;return e.map(a=>a.slice(o).trimRight()).join(` +`)}function yo(t,{format:e,paragraphs:r}){return t=t.replace(/\r\n?/g,` +`),t=_6e(t),t=t.replace(/^\n+|\n+$/g,""),t=t.replace(/^(\s*)-([^\n]*?)\n+/gm,`$1-$2 + +`),t=t.replace(/\n(\n)?\n*/g,(o,a)=>a||" "),r&&(t=t.split(/\n/).map(o=>{let a=o.match(/^\s*[*-][\t ]+(.*)/);if(!a)return o.match(/(.{1,80})(?: |$)/g).join(` +`);let n=o.length-o.trimStart().length;return a[1].match(new RegExp(`(.{1,${78-n}})(?: |$)`,"g")).map((u,A)=>" ".repeat(n)+(A===0?"- ":" ")+u).join(` +`)}).join(` + +`)),t=t.replace(/(`+)((?:.|[\n])*?)\1/g,(o,a,n)=>e.code(a+n+a)),t=t.replace(/(\*\*)((?:.|[\n])*?)\1/g,(o,a,n)=>e.bold(a+n+a)),t?`${t} +`:""}var lN,VV,zV,cN=wt(()=>{lN=Array(80).fill("\u2501");for(let t=0;t<=24;++t)lN[lN.length-t]=`\x1B[38;5;${232+t}m\u2501`;VV={header:t=>`\x1B[1m\u2501\u2501\u2501 ${t}${t.length<75?` ${lN.slice(t.length+5).join("")}`:":"}\x1B[0m`,bold:t=>`\x1B[1m${t}\x1B[22m`,error:t=>`\x1B[31m\x1B[1m${t}\x1B[22m\x1B[39m`,code:t=>`\x1B[36m${t}\x1B[39m`},zV={header:t=>t,bold:t=>t,error:t=>t,code:t=>t}});function Yo(t){return{...t,[CI]:!0}}function Wu(t,e){return typeof t>"u"?[t,e]:typeof t=="object"&&t!==null&&!Array.isArray(t)?[void 0,t]:[t,e]}function QP(t,{mergeName:e=!1}={}){let r=t.match(/^([^:]+): (.*)$/m);if(!r)return"validation failed";let[,o,a]=r;return e&&(a=a[0].toLowerCase()+a.slice(1)),a=o!=="."||!e?`${o.replace(/^\.(\[|$)/,"$1")}: ${a}`:`: ${a}`,a}function wI(t,e){return e.length===1?new ot(`${t}${QP(e[0],{mergeName:!0})}`):new ot(`${t}: +${e.map(r=>` +- ${QP(r)}`).join("")}`)}function ag(t,e,r){if(typeof r>"u")return e;let o=[],a=[],n=A=>{let p=e;return e=A,n.bind(null,p)};if(!r(e,{errors:o,coercions:a,coercion:n}))throw wI(`Invalid value for ${t}`,o);for(let[,A]of a)A();return e}var CI,yf=wt(()=>{kP();CI=Symbol("clipanion/isOption")});var Wo={};Kt(Wo,{KeyRelationship:()=>Ku,TypeAssertionError:()=>Jp,applyCascade:()=>vI,as:()=>sqe,assert:()=>rqe,assertWithErrors:()=>nqe,cascade:()=>NP,fn:()=>oqe,hasAtLeastOneKey:()=>dN,hasExactLength:()=>ez,hasForbiddenKeys:()=>Dqe,hasKeyRelationship:()=>PI,hasMaxLength:()=>lqe,hasMinLength:()=>aqe,hasMutuallyExclusiveKeys:()=>Pqe,hasRequiredKeys:()=>vqe,hasUniqueItems:()=>cqe,isArray:()=>FP,isAtLeast:()=>hN,isAtMost:()=>fqe,isBase64:()=>Cqe,isBoolean:()=>V6e,isDate:()=>J6e,isDict:()=>$6e,isEnum:()=>js,isHexColor:()=>Eqe,isISO8601:()=>yqe,isInExclusiveRange:()=>hqe,isInInclusiveRange:()=>pqe,isInstanceOf:()=>tqe,isInteger:()=>gN,isJSON:()=>wqe,isLiteral:()=>XV,isLowerCase:()=>gqe,isMap:()=>Z6e,isNegative:()=>uqe,isNullable:()=>Bqe,isNumber:()=>fN,isObject:()=>ZV,isOneOf:()=>pN,isOptional:()=>Iqe,isPartial:()=>eqe,isPayload:()=>z6e,isPositive:()=>Aqe,isRecord:()=>TP,isSet:()=>X6e,isString:()=>Sm,isTuple:()=>RP,isUUID4:()=>mqe,isUnknown:()=>AN,isUpperCase:()=>dqe,makeTrait:()=>$V,makeValidator:()=>qr,matchesRegExp:()=>BI,softAssert:()=>iqe});function Vn(t){return t===null?"null":t===void 0?"undefined":t===""?"an empty string":typeof t=="symbol"?`<${t.toString()}>`:Array.isArray(t)?"an array":JSON.stringify(t)}function Pm(t,e){if(t.length===0)return"nothing";if(t.length===1)return Vn(t[0]);let r=t.slice(0,-1),o=t[t.length-1],a=t.length>2?`, ${e} `:` ${e} `;return`${r.map(n=>Vn(n)).join(", ")}${a}${Vn(o)}`}function zp(t,e){var r,o,a;return typeof e=="number"?`${(r=t?.p)!==null&&r!==void 0?r:"."}[${e}]`:H6e.test(e)?`${(o=t?.p)!==null&&o!==void 0?o:""}.${e}`:`${(a=t?.p)!==null&&a!==void 0?a:"."}[${JSON.stringify(e)}]`}function uN(t,e,r){return t===1?e:r}function gr({errors:t,p:e}={},r){return t?.push(`${e??"."}: ${r}`),!1}function W6e(t,e){return r=>{t[e]=r}}function Vu(t,e){return r=>{let o=t[e];return t[e]=r,Vu(t,e).bind(null,o)}}function II(t,e,r){let o=()=>(t(r()),a),a=()=>(t(e),o);return o}function AN(){return qr({test:(t,e)=>!0})}function XV(t){return qr({test:(e,r)=>e!==t?gr(r,`Expected ${Vn(t)} (got ${Vn(e)})`):!0})}function Sm(){return qr({test:(t,e)=>typeof t!="string"?gr(e,`Expected a string (got ${Vn(t)})`):!0})}function js(t){let e=Array.isArray(t)?t:Object.values(t),r=e.every(a=>typeof a=="string"||typeof a=="number"),o=new Set(e);return o.size===1?XV([...o][0]):qr({test:(a,n)=>o.has(a)?!0:r?gr(n,`Expected one of ${Pm(e,"or")} (got ${Vn(a)})`):gr(n,`Expected a valid enumeration value (got ${Vn(a)})`)})}function V6e(){return qr({test:(t,e)=>{var r;if(typeof t!="boolean"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return gr(e,"Unbound coercion result");let o=K6e.get(t);if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a boolean (got ${Vn(t)})`)}return!0}})}function fN(){return qr({test:(t,e)=>{var r;if(typeof t!="number"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return gr(e,"Unbound coercion result");let o;if(typeof t=="string"){let a;try{a=JSON.parse(t)}catch{}if(typeof a=="number")if(JSON.stringify(a)===t)o=a;else return gr(e,`Received a number that can't be safely represented by the runtime (${t})`)}if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a number (got ${Vn(t)})`)}return!0}})}function z6e(t){return qr({test:(e,r)=>{var o;if(typeof r?.coercions>"u")return gr(r,"The isPayload predicate can only be used with coercion enabled");if(typeof r.coercion>"u")return gr(r,"Unbound coercion result");if(typeof e!="string")return gr(r,`Expected a string (got ${Vn(e)})`);let a;try{a=JSON.parse(e)}catch{return gr(r,`Expected a JSON string (got ${Vn(e)})`)}let n={value:a};return t(a,Object.assign(Object.assign({},r),{coercion:Vu(n,"value")}))?(r.coercions.push([(o=r.p)!==null&&o!==void 0?o:".",r.coercion.bind(null,n.value)]),!0):!1}})}function J6e(){return qr({test:(t,e)=>{var r;if(!(t instanceof Date)){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return gr(e,"Unbound coercion result");let o;if(typeof t=="string"&&JV.test(t))o=new Date(t);else{let a;if(typeof t=="string"){let n;try{n=JSON.parse(t)}catch{}typeof n=="number"&&(a=n)}else typeof t=="number"&&(a=t);if(typeof a<"u")if(Number.isSafeInteger(a)||!Number.isSafeInteger(a*1e3))o=new Date(a*1e3);else return gr(e,`Received a timestamp that can't be safely represented by the runtime (${t})`)}if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a date (got ${Vn(t)})`)}return!0}})}function FP(t,{delimiter:e}={}){return qr({test:(r,o)=>{var a;let n=r;if(typeof r=="string"&&typeof e<"u"&&typeof o?.coercions<"u"){if(typeof o?.coercion>"u")return gr(o,"Unbound coercion result");r=r.split(e)}if(!Array.isArray(r))return gr(o,`Expected an array (got ${Vn(r)})`);let u=!0;for(let A=0,p=r.length;A{var n,u;if(Object.getPrototypeOf(o).toString()==="[object Set]")if(typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return gr(a,"Unbound coercion result");let A=[...o],p=[...o];if(!r(p,Object.assign(Object.assign({},a),{coercion:void 0})))return!1;let h=()=>p.some((E,I)=>E!==A[I])?new Set(p):o;return a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",II(a.coercion,o,h)]),!0}else{let A=!0;for(let p of o)if(A=t(p,Object.assign({},a))&&A,!A&&a?.errors==null)break;return A}if(typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return gr(a,"Unbound coercion result");let A={value:o};return r(o,Object.assign(Object.assign({},a),{coercion:Vu(A,"value")}))?(a.coercions.push([(u=a.p)!==null&&u!==void 0?u:".",II(a.coercion,o,()=>new Set(A.value))]),!0):!1}return gr(a,`Expected a set (got ${Vn(o)})`)}})}function Z6e(t,e){let r=FP(RP([t,e])),o=TP(e,{keys:t});return qr({test:(a,n)=>{var u,A,p;if(Object.getPrototypeOf(a).toString()==="[object Map]")if(typeof n?.coercions<"u"){if(typeof n?.coercion>"u")return gr(n,"Unbound coercion result");let h=[...a],E=[...a];if(!r(E,Object.assign(Object.assign({},n),{coercion:void 0})))return!1;let I=()=>E.some((D,x)=>D[0]!==h[x][0]||D[1]!==h[x][1])?new Map(E):a;return n.coercions.push([(u=n.p)!==null&&u!==void 0?u:".",II(n.coercion,a,I)]),!0}else{let h=!0;for(let[E,I]of a)if(h=t(E,Object.assign({},n))&&h,!h&&n?.errors==null||(h=e(I,Object.assign(Object.assign({},n),{p:zp(n,E)}))&&h,!h&&n?.errors==null))break;return h}if(typeof n?.coercions<"u"){if(typeof n?.coercion>"u")return gr(n,"Unbound coercion result");let h={value:a};return Array.isArray(a)?r(a,Object.assign(Object.assign({},n),{coercion:void 0}))?(n.coercions.push([(A=n.p)!==null&&A!==void 0?A:".",II(n.coercion,a,()=>new Map(h.value))]),!0):!1:o(a,Object.assign(Object.assign({},n),{coercion:Vu(h,"value")}))?(n.coercions.push([(p=n.p)!==null&&p!==void 0?p:".",II(n.coercion,a,()=>new Map(Object.entries(h.value)))]),!0):!1}return gr(n,`Expected a map (got ${Vn(a)})`)}})}function RP(t,{delimiter:e}={}){let r=ez(t.length);return qr({test:(o,a)=>{var n;if(typeof o=="string"&&typeof e<"u"&&typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return gr(a,"Unbound coercion result");o=o.split(e),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,o)])}if(!Array.isArray(o))return gr(a,`Expected a tuple (got ${Vn(o)})`);let u=r(o,Object.assign({},a));for(let A=0,p=o.length;A{var n;if(Array.isArray(o)&&typeof a?.coercions<"u")return typeof a?.coercion>"u"?gr(a,"Unbound coercion result"):r(o,Object.assign(Object.assign({},a),{coercion:void 0}))?(o=Object.fromEntries(o),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,o)]),!0):!1;if(typeof o!="object"||o===null)return gr(a,`Expected an object (got ${Vn(o)})`);let u=Object.keys(o),A=!0;for(let p=0,h=u.length;p{if(typeof a!="object"||a===null)return gr(n,`Expected an object (got ${Vn(a)})`);let u=new Set([...r,...Object.keys(a)]),A={},p=!0;for(let h of u){if(h==="constructor"||h==="__proto__")p=gr(Object.assign(Object.assign({},n),{p:zp(n,h)}),"Unsafe property name");else{let E=Object.prototype.hasOwnProperty.call(t,h)?t[h]:void 0,I=Object.prototype.hasOwnProperty.call(a,h)?a[h]:void 0;typeof E<"u"?p=E(I,Object.assign(Object.assign({},n),{p:zp(n,h),coercion:Vu(a,h)}))&&p:e===null?p=gr(Object.assign(Object.assign({},n),{p:zp(n,h)}),`Extraneous property (got ${Vn(I)})`):Object.defineProperty(A,h,{enumerable:!0,get:()=>I,set:W6e(a,h)})}if(!p&&n?.errors==null)break}return e!==null&&(p||n?.errors!=null)&&(p=e(A,n)&&p),p}});return Object.assign(o,{properties:t})}function eqe(t){return ZV(t,{extra:TP(AN())})}function $V(t){return()=>t}function qr({test:t}){return $V(t)()}function rqe(t,e){if(!e(t))throw new Jp}function nqe(t,e){let r=[];if(!e(t,{errors:r}))throw new Jp({errors:r})}function iqe(t,e){}function sqe(t,e,{coerce:r=!1,errors:o,throw:a}={}){let n=o?[]:void 0;if(!r){if(e(t,{errors:n}))return a?t:{value:t,errors:void 0};if(a)throw new Jp({errors:n});return{value:void 0,errors:n??!0}}let u={value:t},A=Vu(u,"value"),p=[];if(!e(t,{errors:n,coercion:A,coercions:p})){if(a)throw new Jp({errors:n});return{value:void 0,errors:n??!0}}for(let[,h]of p)h();return a?u.value:{value:u.value,errors:void 0}}function oqe(t,e){let r=RP(t);return(...o)=>{if(!r(o))throw new Jp;return e(...o)}}function aqe(t){return qr({test:(e,r)=>e.length>=t?!0:gr(r,`Expected to have a length of at least ${t} elements (got ${e.length})`)})}function lqe(t){return qr({test:(e,r)=>e.length<=t?!0:gr(r,`Expected to have a length of at most ${t} elements (got ${e.length})`)})}function ez(t){return qr({test:(e,r)=>e.length!==t?gr(r,`Expected to have a length of exactly ${t} elements (got ${e.length})`):!0})}function cqe({map:t}={}){return qr({test:(e,r)=>{let o=new Set,a=new Set;for(let n=0,u=e.length;nt<=0?!0:gr(e,`Expected to be negative (got ${t})`)})}function Aqe(){return qr({test:(t,e)=>t>=0?!0:gr(e,`Expected to be positive (got ${t})`)})}function hN(t){return qr({test:(e,r)=>e>=t?!0:gr(r,`Expected to be at least ${t} (got ${e})`)})}function fqe(t){return qr({test:(e,r)=>e<=t?!0:gr(r,`Expected to be at most ${t} (got ${e})`)})}function pqe(t,e){return qr({test:(r,o)=>r>=t&&r<=e?!0:gr(o,`Expected to be in the [${t}; ${e}] range (got ${r})`)})}function hqe(t,e){return qr({test:(r,o)=>r>=t&&re!==Math.round(e)?gr(r,`Expected to be an integer (got ${e})`):!t&&!Number.isSafeInteger(e)?gr(r,`Expected to be a safe integer (got ${e})`):!0})}function BI(t){return qr({test:(e,r)=>t.test(e)?!0:gr(r,`Expected to match the pattern ${t.toString()} (got ${Vn(e)})`)})}function gqe(){return qr({test:(t,e)=>t!==t.toLowerCase()?gr(e,`Expected to be all-lowercase (got ${t})`):!0})}function dqe(){return qr({test:(t,e)=>t!==t.toUpperCase()?gr(e,`Expected to be all-uppercase (got ${t})`):!0})}function mqe(){return qr({test:(t,e)=>Y6e.test(t)?!0:gr(e,`Expected to be a valid UUID v4 (got ${Vn(t)})`)})}function yqe(){return qr({test:(t,e)=>JV.test(t)?!0:gr(e,`Expected to be a valid ISO 8601 date string (got ${Vn(t)})`)})}function Eqe({alpha:t=!1}){return qr({test:(e,r)=>(t?q6e.test(e):j6e.test(e))?!0:gr(r,`Expected to be a valid hexadecimal color string (got ${Vn(e)})`)})}function Cqe(){return qr({test:(t,e)=>G6e.test(t)?!0:gr(e,`Expected to be a valid base 64 string (got ${Vn(t)})`)})}function wqe(t=AN()){return qr({test:(e,r)=>{let o;try{o=JSON.parse(e)}catch{return gr(r,`Expected to be a valid JSON string (got ${Vn(e)})`)}return t(o,r)}})}function NP(t,...e){let r=Array.isArray(e[0])?e[0]:e;return qr({test:(o,a)=>{var n,u;let A={value:o},p=typeof a?.coercions<"u"?Vu(A,"value"):void 0,h=typeof a?.coercions<"u"?[]:void 0;if(!t(o,Object.assign(Object.assign({},a),{coercion:p,coercions:h})))return!1;let E=[];if(typeof h<"u")for(let[,I]of h)E.push(I());try{if(typeof a?.coercions<"u"){if(A.value!==o){if(typeof a?.coercion>"u")return gr(a,"Unbound coercion result");a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,A.value)])}(u=a?.coercions)===null||u===void 0||u.push(...h)}return r.every(I=>I(A.value,a))}finally{for(let I of E)I()}}})}function vI(t,...e){let r=Array.isArray(e[0])?e[0]:e;return NP(t,r)}function Iqe(t){return qr({test:(e,r)=>typeof e>"u"?!0:t(e,r)})}function Bqe(t){return qr({test:(e,r)=>e===null?!0:t(e,r)})}function vqe(t,e){var r;let o=new Set(t),a=DI[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)||p.push(h);return p.length>0?gr(u,`Missing required ${uN(p.length,"property","properties")} ${Pm(p,"and")}`):!0}})}function dN(t,e){var r;let o=new Set(t),a=DI[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return qr({test:(n,u)=>Object.keys(n).some(h=>a(o,h,n))?!0:gr(u,`Missing at least one property from ${Pm(Array.from(o),"or")}`)})}function Dqe(t,e){var r;let o=new Set(t),a=DI[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>0?gr(u,`Forbidden ${uN(p.length,"property","properties")} ${Pm(p,"and")}`):!0}})}function Pqe(t,e){var r;let o=new Set(t),a=DI[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>1?gr(u,`Mutually exclusive properties ${Pm(p,"and")}`):!0}})}function PI(t,e,r,o){var a,n;let u=new Set((a=o?.ignore)!==null&&a!==void 0?a:[]),A=DI[(n=o?.missingIf)!==null&&n!==void 0?n:"missing"],p=new Set(r),h=Sqe[e],E=e===Ku.Forbids?"or":"and";return qr({test:(I,D)=>{let x=new Set(Object.keys(I));if(!A(x,t,I)||u.has(I[t]))return!0;let C=[];for(let T of p)(A(x,T,I)&&!u.has(I[T]))!==h.expect&&C.push(T);return C.length>=1?gr(D,`Property "${t}" ${h.message} ${uN(C.length,"property","properties")} ${Pm(C,E)}`):!0}})}var H6e,q6e,j6e,G6e,Y6e,JV,K6e,tqe,pN,Jp,DI,Ku,Sqe,il=wt(()=>{H6e=/^[a-zA-Z_][a-zA-Z0-9_]*$/;q6e=/^#[0-9a-f]{6}$/i,j6e=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,G6e=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,Y6e=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,JV=/^(?:[1-9]\d{3}(-?)(?:(?:0[1-9]|1[0-2])\1(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])\1(?:29|30)|(?:0[13578]|1[02])(?:\1)31|00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[0-5]))|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\2)29|-?366))T(?:[01]\d|2[0-3])(:?)[0-5]\d(?:\3[0-5]\d)?(?:Z|[+-][01]\d(?:\3[0-5]\d)?)$/;K6e=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]);tqe=t=>qr({test:(e,r)=>e instanceof t?!0:gr(r,`Expected an instance of ${t.name} (got ${Vn(e)})`)}),pN=(t,{exclusive:e=!1}={})=>qr({test:(r,o)=>{var a,n,u;let A=[],p=typeof o?.errors<"u"?[]:void 0;for(let h=0,E=t.length;h1?gr(o,`Expected to match exactly a single predicate (matched ${A.join(", ")})`):(u=o?.errors)===null||u===void 0||u.push(...p),!1}});Jp=class extends Error{constructor({errors:e}={}){let r="Type mismatch";if(e&&e.length>0){r+=` +`;for(let o of e)r+=` +- ${o}`}super(r)}};DI={missing:(t,e)=>t.has(e),undefined:(t,e,r)=>t.has(e)&&typeof r[e]<"u",nil:(t,e,r)=>t.has(e)&&r[e]!=null,falsy:(t,e,r)=>t.has(e)&&!!r[e]};(function(t){t.Forbids="Forbids",t.Requires="Requires"})(Ku||(Ku={}));Sqe={[Ku.Forbids]:{expect:!1,message:"forbids using"},[Ku.Requires]:{expect:!0,message:"requires using"}}});var st,Xp=wt(()=>{yf();st=class{constructor(){this.help=!1}static Usage(e){return e}async catch(e){throw e}async validateAndExecute(){let r=this.constructor.schema;if(Array.isArray(r)){let{isDict:a,isUnknown:n,applyCascade:u}=await Promise.resolve().then(()=>(il(),Wo)),A=u(a(n()),r),p=[],h=[];if(!A(this,{errors:p,coercions:h}))throw wI("Invalid option schema",p);for(let[,I]of h)I()}else if(r!=null)throw new Error("Invalid command schema");let o=await this.execute();return typeof o<"u"?o:0}};st.isOption=CI;st.Default=[]});function Sa(t){oN&&console.log(t)}function rz(){let t={nodes:[]};for(let e=0;e{if(e.has(o))return;e.add(o);let a=t.nodes[o];for(let u of Object.values(a.statics))for(let{to:A}of u)r(A);for(let[,{to:u}]of a.dynamics)r(u);for(let{to:u}of a.shortcuts)r(u);let n=new Set(a.shortcuts.map(({to:u})=>u));for(;a.shortcuts.length>0;){let{to:u}=a.shortcuts.shift(),A=t.nodes[u];for(let[p,h]of Object.entries(A.statics)){let E=Object.prototype.hasOwnProperty.call(a.statics,p)?a.statics[p]:a.statics[p]=[];for(let I of h)E.some(({to:D})=>I.to===D)||E.push(I)}for(let[p,h]of A.dynamics)a.dynamics.some(([E,{to:I}])=>p===E&&h.to===I)||a.dynamics.push([p,h]);for(let p of A.shortcuts)n.has(p.to)||(a.shortcuts.push(p),n.add(p.to))}};r(pn.InitialNode)}function kqe(t,{prefix:e=""}={}){if(oN){Sa(`${e}Nodes are:`);for(let r=0;rE!==pn.ErrorNode).map(({state:E})=>({usage:E.candidateUsage,reason:null})));if(h.every(({node:E})=>E===pn.ErrorNode))throw new Dm(e,h.map(({state:E})=>({usage:E.candidateUsage,reason:E.errorMessage})));o=Rqe(h)}if(o.length>0){Sa(" Results:");for(let n of o)Sa(` - ${n.node} -> ${JSON.stringify(n.state)}`)}else Sa(" No results");return o}function Fqe(t,e,{endToken:r=Kn.EndOfInput}={}){let o=Qqe(t,[...e,r]);return Tqe(e,o.map(({state:a})=>a))}function Rqe(t){let e=0;for(let{state:r}of t)r.path.length>e&&(e=r.path.length);return t.filter(({state:r})=>r.path.length===e)}function Tqe(t,e){let r=e.filter(D=>D.selectedIndex!==null),o=r.filter(D=>!D.partial);if(o.length>0&&(r=o),r.length===0)throw new Error;let a=r.filter(D=>D.selectedIndex===og||D.requiredOptions.every(x=>x.some(C=>D.options.find(T=>T.name===C))));if(a.length===0)throw new Dm(t,r.map(D=>({usage:D.candidateUsage,reason:null})));let n=0;for(let D of a)D.path.length>n&&(n=D.path.length);let u=a.filter(D=>D.path.length===n),A=D=>D.positionals.filter(({extra:x})=>!x).length+D.options.length,p=u.map(D=>({state:D,positionalCount:A(D)})),h=0;for(let{positionalCount:D}of p)D>h&&(h=D);let E=p.filter(({positionalCount:D})=>D===h).map(({state:D})=>D),I=Nqe(E);if(I.length>1)throw new xP(t,I.map(D=>D.candidateUsage));return I[0]}function Nqe(t){let e=[],r=[];for(let o of t)o.selectedIndex===og?r.push(o):e.push(o);return r.length>0&&e.push({...tz,path:nz(...r.map(o=>o.path)),options:r.reduce((o,a)=>o.concat(a.options),[])}),e}function nz(t,e,...r){return e===void 0?Array.from(t):nz(t.filter((o,a)=>o===e[a]),...r)}function sl(){return{dynamics:[],shortcuts:[],statics:{}}}function iz(t){return t===pn.SuccessNode||t===pn.ErrorNode}function mN(t,e=0){return{to:iz(t.to)?t.to:t.to>=pn.CustomNode?t.to+e-pn.CustomNode+1:t.to+e,reducer:t.reducer}}function Lqe(t,e=0){let r=sl();for(let[o,a]of t.dynamics)r.dynamics.push([o,mN(a,e)]);for(let o of t.shortcuts)r.shortcuts.push(mN(o,e));for(let[o,a]of Object.entries(t.statics))r.statics[o]=a.map(n=>mN(n,e));return r}function Bs(t,e,r,o,a){t.nodes[e].dynamics.push([r,{to:o,reducer:a}])}function bm(t,e,r,o){t.nodes[e].shortcuts.push({to:r,reducer:o})}function Ko(t,e,r,o,a){(Object.prototype.hasOwnProperty.call(t.nodes[e].statics,r)?t.nodes[e].statics[r]:t.nodes[e].statics[r]=[]).push({to:o,reducer:a})}function LP(t,e,r,o,a){if(Array.isArray(e)){let[n,...u]=e;return t[n](r,o,a,...u)}else return t[e](r,o,a)}var tz,Mqe,yN,ol,EN,MP,OP=wt(()=>{bP();kP();tz={candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,path:[],positionals:[],options:[],remainder:null,selectedIndex:og,partial:!1,tokens:[]};Mqe={always:()=>!0,isOptionLike:(t,e)=>!t.ignoreOptions&&e!=="-"&&e.startsWith("-"),isNotOptionLike:(t,e)=>t.ignoreOptions||e==="-"||!e.startsWith("-"),isOption:(t,e,r,o)=>!t.ignoreOptions&&e===o,isBatchOption:(t,e,r,o)=>!t.ignoreOptions&&KV.test(e)&&[...e.slice(1)].every(a=>o.has(`-${a}`)),isBoundOption:(t,e,r,o,a)=>{let n=e.match(sN);return!t.ignoreOptions&&!!n&&SP.test(n[1])&&o.has(n[1])&&a.filter(u=>u.nameSet.includes(n[1])).every(u=>u.allowBinding)},isNegatedOption:(t,e,r,o)=>!t.ignoreOptions&&e===`--no-${o.slice(2)}`,isHelp:(t,e)=>!t.ignoreOptions&&iN.test(e),isUnsupportedOption:(t,e,r,o)=>!t.ignoreOptions&&e.startsWith("-")&&SP.test(e)&&!o.has(e),isInvalidOption:(t,e)=>!t.ignoreOptions&&e.startsWith("-")&&!SP.test(e)},yN={setCandidateState:(t,e,r,o)=>({...t,...o}),setSelectedIndex:(t,e,r,o)=>({...t,selectedIndex:o}),setPartialIndex:(t,e,r,o)=>({...t,selectedIndex:o,partial:!0}),pushBatch:(t,e,r,o)=>{let a=t.options.slice(),n=t.tokens.slice();for(let u=1;u{let[,o,a]=e.match(sN),n=t.options.concat({name:o,value:a}),u=t.tokens.concat([{segmentIndex:r,type:"option",slice:[0,o.length],option:o},{segmentIndex:r,type:"assign",slice:[o.length,o.length+1]},{segmentIndex:r,type:"value",slice:[o.length+1,o.length+a.length+1]}]);return{...t,options:n,tokens:u}},pushPath:(t,e,r)=>{let o=t.path.concat(e),a=t.tokens.concat({segmentIndex:r,type:"path"});return{...t,path:o,tokens:a}},pushPositional:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!1}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushExtra:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!0}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushExtraNoLimits:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:ol}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushTrue:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!0}),n=t.tokens.concat({segmentIndex:r,type:"option",option:o});return{...t,options:a,tokens:n}},pushFalse:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!1}),n=t.tokens.concat({segmentIndex:r,type:"option",option:o});return{...t,options:a,tokens:n}},pushUndefined:(t,e,r,o)=>{let a=t.options.concat({name:e,value:void 0}),n=t.tokens.concat({segmentIndex:r,type:"option",option:e});return{...t,options:a,tokens:n}},pushStringValue:(t,e,r)=>{var o;let a=t.options[t.options.length-1],n=t.options.slice(),u=t.tokens.concat({segmentIndex:r,type:"value"});return a.value=((o=a.value)!==null&&o!==void 0?o:[]).concat([e]),{...t,options:n,tokens:u}},setStringValue:(t,e,r)=>{let o=t.options[t.options.length-1],a=t.options.slice(),n=t.tokens.concat({segmentIndex:r,type:"value"});return o.value=e,{...t,options:a,tokens:n}},inhibateOptions:t=>({...t,ignoreOptions:!0}),useHelp:(t,e,r,o)=>{let[,,a]=e.match(iN);return typeof a<"u"?{...t,options:[{name:"-c",value:String(o)},{name:"-i",value:a}]}:{...t,options:[{name:"-c",value:String(o)}]}},setError:(t,e,r,o)=>e===Kn.EndOfInput||e===Kn.EndOfPartialInput?{...t,errorMessage:`${o}.`}:{...t,errorMessage:`${o} ("${e}").`},setOptionArityError:(t,e)=>{let r=t.options[t.options.length-1];return{...t,errorMessage:`Not enough arguments to option ${r.name}.`}}},ol=Symbol(),EN=class{constructor(e,r){this.allOptionNames=new Map,this.arity={leading:[],trailing:[],extra:[],proxy:!1},this.options=[],this.paths=[],this.cliIndex=e,this.cliOpts=r}addPath(e){this.paths.push(e)}setArity({leading:e=this.arity.leading,trailing:r=this.arity.trailing,extra:o=this.arity.extra,proxy:a=this.arity.proxy}){Object.assign(this.arity,{leading:e,trailing:r,extra:o,proxy:a})}addPositional({name:e="arg",required:r=!0}={}){if(!r&&this.arity.extra===ol)throw new Error("Optional parameters cannot be declared when using .rest() or .proxy()");if(!r&&this.arity.trailing.length>0)throw new Error("Optional parameters cannot be declared after the required trailing positional arguments");!r&&this.arity.extra!==ol?this.arity.extra.push(e):this.arity.extra!==ol&&this.arity.extra.length===0?this.arity.leading.push(e):this.arity.trailing.push(e)}addRest({name:e="arg",required:r=0}={}){if(this.arity.extra===ol)throw new Error("Infinite lists cannot be declared multiple times in the same command");if(this.arity.trailing.length>0)throw new Error("Infinite lists cannot be declared after the required trailing positional arguments");for(let o=0;o1)throw new Error("The arity cannot be higher than 1 when the option only supports the --arg=value syntax");if(!Number.isInteger(o))throw new Error(`The arity must be an integer, got ${o}`);if(o<0)throw new Error(`The arity must be positive, got ${o}`);let A=e.reduce((p,h)=>h.length>p.length?h:p,"");for(let p of e)this.allOptionNames.set(p,A);this.options.push({preferredName:A,nameSet:e,description:r,arity:o,hidden:a,required:n,allowBinding:u})}setContext(e){this.context=e}usage({detailed:e=!0,inlineOptions:r=!0}={}){let o=[this.cliOpts.binaryName],a=[];if(this.paths.length>0&&o.push(...this.paths[0]),e){for(let{preferredName:u,nameSet:A,arity:p,hidden:h,description:E,required:I}of this.options){if(h)continue;let D=[];for(let C=0;C`:`[${x}]`)}o.push(...this.arity.leading.map(u=>`<${u}>`)),this.arity.extra===ol?o.push("..."):o.push(...this.arity.extra.map(u=>`[${u}]`)),o.push(...this.arity.trailing.map(u=>`<${u}>`))}return{usage:o.join(" "),options:a}}compile(){if(typeof this.context>"u")throw new Error("Assertion failed: No context attached");let e=rz(),r=pn.InitialNode,o=this.usage().usage,a=this.options.filter(A=>A.required).map(A=>A.nameSet);r=jc(e,sl()),Ko(e,pn.InitialNode,Kn.StartOfInput,r,["setCandidateState",{candidateUsage:o,requiredOptions:a}]);let n=this.arity.proxy?"always":"isNotOptionLike",u=this.paths.length>0?this.paths:[[]];for(let A of u){let p=r;if(A.length>0){let D=jc(e,sl());bm(e,p,D),this.registerOptions(e,D),p=D}for(let D=0;D0||!this.arity.proxy){let D=jc(e,sl());Bs(e,p,"isHelp",D,["useHelp",this.cliIndex]),Bs(e,D,"always",D,"pushExtra"),Ko(e,D,Kn.EndOfInput,pn.SuccessNode,["setSelectedIndex",og]),this.registerOptions(e,p)}this.arity.leading.length>0&&(Ko(e,p,Kn.EndOfInput,pn.ErrorNode,["setError","Not enough positional arguments"]),Ko(e,p,Kn.EndOfPartialInput,pn.SuccessNode,["setPartialIndex",this.cliIndex]));let h=p;for(let D=0;D0||D+1!==this.arity.leading.length)&&(Ko(e,x,Kn.EndOfInput,pn.ErrorNode,["setError","Not enough positional arguments"]),Ko(e,x,Kn.EndOfPartialInput,pn.SuccessNode,["setPartialIndex",this.cliIndex])),Bs(e,h,"isNotOptionLike",x,"pushPositional"),h=x}let E=h;if(this.arity.extra===ol||this.arity.extra.length>0){let D=jc(e,sl());if(bm(e,h,D),this.arity.extra===ol){let x=jc(e,sl());this.arity.proxy||this.registerOptions(e,x),Bs(e,h,n,x,"pushExtraNoLimits"),Bs(e,x,n,x,"pushExtraNoLimits"),bm(e,x,D)}else for(let x=0;x0)&&this.registerOptions(e,C),Bs(e,E,n,C,"pushExtra"),bm(e,C,D),E=C}E=D}this.arity.trailing.length>0&&(Ko(e,E,Kn.EndOfInput,pn.ErrorNode,["setError","Not enough positional arguments"]),Ko(e,E,Kn.EndOfPartialInput,pn.SuccessNode,["setPartialIndex",this.cliIndex]));let I=E;for(let D=0;D=0&&e{let u=n?Kn.EndOfPartialInput:Kn.EndOfInput;return Fqe(o,a,{endToken:u})}}}}});function oz(){return UP.default&&"getColorDepth"in UP.default.WriteStream.prototype?UP.default.WriteStream.prototype.getColorDepth():process.env.FORCE_COLOR==="0"?1:process.env.FORCE_COLOR==="1"||typeof process.stdout<"u"&&process.stdout.isTTY?8:1}function az(t){let e=sz;if(typeof e>"u"){if(t.stdout===process.stdout&&t.stderr===process.stderr)return null;let{AsyncLocalStorage:r}=ve("async_hooks");e=sz=new r;let o=process.stdout._write;process.stdout._write=function(n,u,A){let p=e.getStore();return typeof p>"u"?o.call(this,n,u,A):p.stdout.write(n,u,A)};let a=process.stderr._write;process.stderr._write=function(n,u,A){let p=e.getStore();return typeof p>"u"?a.call(this,n,u,A):p.stderr.write(n,u,A)}}return r=>e.run(t,r)}var UP,sz,lz=wt(()=>{UP=et(ve("tty"),1)});var _P,cz=wt(()=>{Xp();_P=class t extends st{constructor(e){super(),this.contexts=e,this.commands=[]}static from(e,r){let o=new t(r);o.path=e.path;for(let a of e.options)switch(a.name){case"-c":o.commands.push(Number(a.value));break;case"-i":o.index=Number(a.value);break}return o}async execute(){let e=this.commands;if(typeof this.index<"u"&&this.index>=0&&this.index1){this.context.stdout.write(`Multiple commands match your selection: +`),this.context.stdout.write(` +`);let r=0;for(let o of this.commands)this.context.stdout.write(this.cli.usage(this.contexts[o].commandClass,{prefix:`${r++}. `.padStart(5)}));this.context.stdout.write(` +`),this.context.stdout.write(`Run again with -h= to see the longer details of any of those commands. +`)}}}});async function fz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=hz(t);return Vo.from(r,e).runExit(o,a)}async function pz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=hz(t);return Vo.from(r,e).run(o,a)}function hz(t){let e,r,o,a;switch(typeof process<"u"&&typeof process.argv<"u"&&(o=process.argv.slice(2)),t.length){case 1:r=t[0];break;case 2:t[0]&&t[0].prototype instanceof st||Array.isArray(t[0])?(r=t[0],Array.isArray(t[1])?o=t[1]:a=t[1]):(e=t[0],r=t[1]);break;case 3:Array.isArray(t[2])?(e=t[0],r=t[1],o=t[2]):t[0]&&t[0].prototype instanceof st||Array.isArray(t[0])?(r=t[0],o=t[1],a=t[2]):(e=t[0],r=t[1],a=t[2]);break;default:e=t[0],r=t[1],o=t[2],a=t[3];break}if(typeof o>"u")throw new Error("The argv parameter must be provided when running Clipanion outside of a Node context");return{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}}function Az(t){return t()}var uz,Vo,gz=wt(()=>{bP();OP();cN();lz();Xp();cz();uz=Symbol("clipanion/errorCommand");Vo=class t{constructor({binaryLabel:e,binaryName:r="...",binaryVersion:o,enableCapture:a=!1,enableColors:n}={}){this.registrations=new Map,this.builder=new MP({binaryName:r}),this.binaryLabel=e,this.binaryName=r,this.binaryVersion=o,this.enableCapture=a,this.enableColors=n}static from(e,r={}){let o=new t(r),a=Array.isArray(e)?e:[e];for(let n of a)o.register(n);return o}register(e){var r;let o=new Map,a=new e;for(let p in a){let h=a[p];typeof h=="object"&&h!==null&&h[st.isOption]&&o.set(p,h)}let n=this.builder.command(),u=n.cliIndex,A=(r=e.paths)!==null&&r!==void 0?r:a.paths;if(typeof A<"u")for(let p of A)n.addPath(p);this.registrations.set(e,{specs:o,builder:n,index:u});for(let[p,{definition:h}]of o.entries())h(n,p);n.setContext({commandClass:e})}process(e,r){let{input:o,context:a,partial:n}=typeof e=="object"&&Array.isArray(e)?{input:e,context:r}:e,{contexts:u,process:A}=this.builder.compile(),p=A(o,{partial:n}),h={...t.defaultContext,...a};switch(p.selectedIndex){case og:{let E=_P.from(p,u);return E.context=h,E.tokens=p.tokens,E}default:{let{commandClass:E}=u[p.selectedIndex],I=this.registrations.get(E);if(typeof I>"u")throw new Error("Assertion failed: Expected the command class to have been registered.");let D=new E;D.context=h,D.tokens=p.tokens,D.path=p.path;try{for(let[x,{transformer:C}]of I.specs.entries())D[x]=C(I.builder,x,p,h);return D}catch(x){throw x[uz]=D,x}}break}}async run(e,r){var o,a;let n,u={...t.defaultContext,...r},A=(o=this.enableColors)!==null&&o!==void 0?o:u.colorDepth>1;if(!Array.isArray(e))n=e;else try{n=this.process(e,u)}catch(E){return u.stdout.write(this.error(E,{colored:A})),1}if(n.help)return u.stdout.write(this.usage(n,{colored:A,detailed:!0})),0;n.context=u,n.cli={binaryLabel:this.binaryLabel,binaryName:this.binaryName,binaryVersion:this.binaryVersion,enableCapture:this.enableCapture,enableColors:this.enableColors,definitions:()=>this.definitions(),definition:E=>this.definition(E),error:(E,I)=>this.error(E,I),format:E=>this.format(E),process:(E,I)=>this.process(E,{...u,...I}),run:(E,I)=>this.run(E,{...u,...I}),usage:(E,I)=>this.usage(E,I)};let p=this.enableCapture&&(a=az(u))!==null&&a!==void 0?a:Az,h;try{h=await p(()=>n.validateAndExecute().catch(E=>n.catch(E).then(()=>0)))}catch(E){return u.stdout.write(this.error(E,{colored:A,command:n})),1}return h}async runExit(e,r){process.exitCode=await this.run(e,r)}definition(e,{colored:r=!1}={}){if(!e.usage)return null;let{usage:o}=this.getUsageByRegistration(e,{detailed:!1}),{usage:a,options:n}=this.getUsageByRegistration(e,{detailed:!0,inlineOptions:!1}),u=typeof e.usage.category<"u"?yo(e.usage.category,{format:this.format(r),paragraphs:!1}):void 0,A=typeof e.usage.description<"u"?yo(e.usage.description,{format:this.format(r),paragraphs:!1}):void 0,p=typeof e.usage.details<"u"?yo(e.usage.details,{format:this.format(r),paragraphs:!0}):void 0,h=typeof e.usage.examples<"u"?e.usage.examples.map(([E,I])=>[yo(E,{format:this.format(r),paragraphs:!1}),I.replace(/\$0/g,this.binaryName)]):void 0;return{path:o,usage:a,category:u,description:A,details:p,examples:h,options:n}}definitions({colored:e=!1}={}){let r=[];for(let o of this.registrations.keys()){let a=this.definition(o,{colored:e});a&&r.push(a)}return r}usage(e=null,{colored:r,detailed:o=!1,prefix:a="$ "}={}){var n;if(e===null){for(let p of this.registrations.keys()){let h=p.paths,E=typeof p.usage<"u";if(!h||h.length===0||h.length===1&&h[0].length===0||((n=h?.some(x=>x.length===0))!==null&&n!==void 0?n:!1))if(e){e=null;break}else e=p;else if(E){e=null;continue}}e&&(o=!0)}let u=e!==null&&e instanceof st?e.constructor:e,A="";if(u)if(o){let{description:p="",details:h="",examples:E=[]}=u.usage||{};p!==""&&(A+=yo(p,{format:this.format(r),paragraphs:!1}).replace(/^./,x=>x.toUpperCase()),A+=` +`),(h!==""||E.length>0)&&(A+=`${this.format(r).header("Usage")} +`,A+=` +`);let{usage:I,options:D}=this.getUsageByRegistration(u,{inlineOptions:!1});if(A+=`${this.format(r).bold(a)}${I} +`,D.length>0){A+=` +`,A+=`${this.format(r).header("Options")} +`;let x=D.reduce((C,T)=>Math.max(C,T.definition.length),0);A+=` +`;for(let{definition:C,description:T}of D)A+=` ${this.format(r).bold(C.padEnd(x))} ${yo(T,{format:this.format(r),paragraphs:!1})}`}if(h!==""&&(A+=` +`,A+=`${this.format(r).header("Details")} +`,A+=` +`,A+=yo(h,{format:this.format(r),paragraphs:!0})),E.length>0){A+=` +`,A+=`${this.format(r).header("Examples")} +`;for(let[x,C]of E)A+=` +`,A+=yo(x,{format:this.format(r),paragraphs:!1}),A+=`${C.replace(/^/m,` ${this.format(r).bold(a)}`).replace(/\$0/g,this.binaryName)} +`}}else{let{usage:p}=this.getUsageByRegistration(u);A+=`${this.format(r).bold(a)}${p} +`}else{let p=new Map;for(let[D,{index:x}]of this.registrations.entries()){if(typeof D.usage>"u")continue;let C=typeof D.usage.category<"u"?yo(D.usage.category,{format:this.format(r),paragraphs:!1}):null,T=p.get(C);typeof T>"u"&&p.set(C,T=[]);let{usage:L}=this.getUsageByIndex(x);T.push({commandClass:D,usage:L})}let h=Array.from(p.keys()).sort((D,x)=>D===null?-1:x===null?1:D.localeCompare(x,"en",{usage:"sort",caseFirst:"upper"})),E=typeof this.binaryLabel<"u",I=typeof this.binaryVersion<"u";E||I?(E&&I?A+=`${this.format(r).header(`${this.binaryLabel} - ${this.binaryVersion}`)} + +`:E?A+=`${this.format(r).header(`${this.binaryLabel}`)} +`:A+=`${this.format(r).header(`${this.binaryVersion}`)} +`,A+=` ${this.format(r).bold(a)}${this.binaryName} +`):A+=`${this.format(r).bold(a)}${this.binaryName} +`;for(let D of h){let x=p.get(D).slice().sort((T,L)=>T.usage.localeCompare(L.usage,"en",{usage:"sort",caseFirst:"upper"})),C=D!==null?D.trim():"General commands";A+=` +`,A+=`${this.format(r).header(`${C}`)} +`;for(let{commandClass:T,usage:L}of x){let U=T.usage.description||"undocumented";A+=` +`,A+=` ${this.format(r).bold(L)} +`,A+=` ${yo(U,{format:this.format(r),paragraphs:!1})}`}}A+=` +`,A+=yo("You can also print more details about any of these commands by calling them with the `-h,--help` flag right after the command name.",{format:this.format(r),paragraphs:!0})}return A}error(e,r){var o,{colored:a,command:n=(o=e[uz])!==null&&o!==void 0?o:null}=r===void 0?{}:r;(!e||typeof e!="object"||!("stack"in e))&&(e=new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(e)})`));let u="",A=e.name.replace(/([a-z])([A-Z])/g,"$1 $2");A==="Error"&&(A="Internal Error"),u+=`${this.format(a).error(A)}: ${e.message} +`;let p=e.clipanion;return typeof p<"u"?p.type==="usage"&&(u+=` +`,u+=this.usage(n)):e.stack&&(u+=`${e.stack.replace(/^.*\n/,"")} +`),u}format(e){var r;return((r=e??this.enableColors)!==null&&r!==void 0?r:t.defaultContext.colorDepth>1)?VV:zV}getUsageByRegistration(e,r){let o=this.registrations.get(e);if(typeof o>"u")throw new Error("Assertion failed: Unregistered command");return this.getUsageByIndex(o.index,r)}getUsageByIndex(e,r){return this.builder.getBuilderByIndex(e).usage(r)}};Vo.defaultContext={env:process.env,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr,colorDepth:oz()}});var SI,dz=wt(()=>{Xp();SI=class extends st{async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.definitions(),null,2)} +`)}};SI.paths=[["--clipanion=definitions"]]});var bI,mz=wt(()=>{Xp();bI=class extends st{async execute(){this.context.stdout.write(this.cli.usage())}};bI.paths=[["-h"],["--help"]]});function HP(t={}){return Yo({definition(e,r){var o;e.addProxy({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){return o.positionals.map(({value:a})=>a)}})}var CN=wt(()=>{yf()});var xI,yz=wt(()=>{Xp();CN();xI=class extends st{constructor(){super(...arguments),this.args=HP()}async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.process(this.args).tokens,null,2)} +`)}};xI.paths=[["--clipanion=tokens"]]});var kI,Ez=wt(()=>{Xp();kI=class extends st{async execute(){var e;this.context.stdout.write(`${(e=this.cli.binaryVersion)!==null&&e!==void 0?e:""} +`)}};kI.paths=[["-v"],["--version"]]});var wN={};Kt(wN,{DefinitionsCommand:()=>SI,HelpCommand:()=>bI,TokensCommand:()=>xI,VersionCommand:()=>kI});var Cz=wt(()=>{dz();mz();yz();Ez()});function wz(t,e,r){let[o,a]=Wu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=new Set(u);return Yo({definition(p){p.addOption({names:u,arity:n,hidden:a?.hidden,description:a?.description,required:a.required})},transformer(p,h,E){let I,D=typeof o<"u"?[...o]:void 0;for(let{name:x,value:C}of E.options)A.has(x)&&(I=x,D=D??[],D.push(C));return typeof D<"u"?ag(I??h,D,a.validator):D}})}var Iz=wt(()=>{yf()});function Bz(t,e,r){let[o,a]=Wu(e,r??{}),n=t.split(","),u=new Set(n);return Yo({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:I,value:D}of h.options)u.has(I)&&(E=D);return E}})}var vz=wt(()=>{yf()});function Dz(t,e,r){let[o,a]=Wu(e,r??{}),n=t.split(","),u=new Set(n);return Yo({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:I,value:D}of h.options)u.has(I)&&(E??(E=0),D?E+=1:E=0);return E}})}var Pz=wt(()=>{yf()});function Sz(t={}){return Yo({definition(e,r){var o;e.addRest({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){let a=u=>{let A=o.positionals[u];return A.extra===ol||A.extra===!1&&uu)}})}var bz=wt(()=>{OP();yf()});function Oqe(t,e,r){let[o,a]=Wu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=new Set(u);return Yo({definition(p){p.addOption({names:u,arity:a.tolerateBoolean?0:n,hidden:a.hidden,description:a.description,required:a.required})},transformer(p,h,E,I){let D,x=o;typeof a.env<"u"&&I.env[a.env]&&(D=a.env,x=I.env[a.env]);for(let{name:C,value:T}of E.options)A.has(C)&&(D=C,x=T);return typeof x=="string"?ag(D??h,x,a.validator):x}})}function Uqe(t={}){let{required:e=!0}=t;return Yo({definition(r,o){var a;r.addPositional({name:(a=t.name)!==null&&a!==void 0?a:o,required:t.required})},transformer(r,o,a){var n;for(let u=0;u{OP();yf()});var de={};Kt(de,{Array:()=>wz,Boolean:()=>Bz,Counter:()=>Dz,Proxy:()=>HP,Rest:()=>Sz,String:()=>xz,applyValidator:()=>ag,cleanValidationError:()=>QP,formatError:()=>wI,isOptionSymbol:()=>CI,makeCommandOption:()=>Yo,rerouteArguments:()=>Wu});var Qz=wt(()=>{yf();CN();Iz();vz();Pz();bz();kz()});var QI={};Kt(QI,{Builtins:()=>wN,Cli:()=>Vo,Command:()=>st,Option:()=>de,UsageError:()=>ot,formatMarkdownish:()=>yo,run:()=>pz,runExit:()=>fz});var Gt=wt(()=>{kP();cN();Xp();gz();Cz();Qz()});var Fz=_((ckt,_qe)=>{_qe.exports={name:"dotenv",version:"16.3.1",description:"Loads environment variables from .env file",main:"lib/main.js",types:"lib/main.d.ts",exports:{".":{types:"./lib/main.d.ts",require:"./lib/main.js",default:"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},scripts:{"dts-check":"tsc --project tests/types/tsconfig.json",lint:"standard","lint-readme":"standard-markdown",pretest:"npm run lint && npm run dts-check",test:"tap tests/*.js --100 -Rspec",prerelease:"npm test",release:"standard-version"},repository:{type:"git",url:"git://github.com/motdotla/dotenv.git"},funding:"https://github.com/motdotla/dotenv?sponsor=1",keywords:["dotenv","env",".env","environment","variables","config","settings"],readmeFilename:"README.md",license:"BSD-2-Clause",devDependencies:{"@definitelytyped/dtslint":"^0.0.133","@types/node":"^18.11.3",decache:"^4.6.1",sinon:"^14.0.1",standard:"^17.0.0","standard-markdown":"^7.1.0","standard-version":"^9.5.0",tap:"^16.3.0",tar:"^6.1.11",typescript:"^4.8.4"},engines:{node:">=12"},browser:{fs:!1}}});var Lz=_((ukt,Ef)=>{var Rz=ve("fs"),BN=ve("path"),Hqe=ve("os"),qqe=ve("crypto"),jqe=Fz(),vN=jqe.version,Gqe=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;function Yqe(t){let e={},r=t.toString();r=r.replace(/\r\n?/mg,` +`);let o;for(;(o=Gqe.exec(r))!=null;){let a=o[1],n=o[2]||"";n=n.trim();let u=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/mg,"$2"),u==='"'&&(n=n.replace(/\\n/g,` +`),n=n.replace(/\\r/g,"\r")),e[a]=n}return e}function Wqe(t){let e=Nz(t),r=vs.configDotenv({path:e});if(!r.parsed)throw new Error(`MISSING_DATA: Cannot parse ${e} for an unknown reason`);let o=Tz(t).split(","),a=o.length,n;for(let u=0;u=a)throw A}return vs.parse(n)}function Kqe(t){console.log(`[dotenv@${vN}][INFO] ${t}`)}function Vqe(t){console.log(`[dotenv@${vN}][WARN] ${t}`)}function IN(t){console.log(`[dotenv@${vN}][DEBUG] ${t}`)}function Tz(t){return t&&t.DOTENV_KEY&&t.DOTENV_KEY.length>0?t.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function zqe(t,e){let r;try{r=new URL(e)}catch(A){throw A.code==="ERR_INVALID_URL"?new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development"):A}let o=r.password;if(!o)throw new Error("INVALID_DOTENV_KEY: Missing key part");let a=r.searchParams.get("environment");if(!a)throw new Error("INVALID_DOTENV_KEY: Missing environment part");let n=`DOTENV_VAULT_${a.toUpperCase()}`,u=t.parsed[n];if(!u)throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);return{ciphertext:u,key:o}}function Nz(t){let e=BN.resolve(process.cwd(),".env");return t&&t.path&&t.path.length>0&&(e=t.path),e.endsWith(".vault")?e:`${e}.vault`}function Jqe(t){return t[0]==="~"?BN.join(Hqe.homedir(),t.slice(1)):t}function Xqe(t){Kqe("Loading env from encrypted .env.vault");let e=vs._parseVault(t),r=process.env;return t&&t.processEnv!=null&&(r=t.processEnv),vs.populate(r,e,t),{parsed:e}}function Zqe(t){let e=BN.resolve(process.cwd(),".env"),r="utf8",o=!!(t&&t.debug);t&&(t.path!=null&&(e=Jqe(t.path)),t.encoding!=null&&(r=t.encoding));try{let a=vs.parse(Rz.readFileSync(e,{encoding:r})),n=process.env;return t&&t.processEnv!=null&&(n=t.processEnv),vs.populate(n,a,t),{parsed:a}}catch(a){return o&&IN(`Failed to load ${e} ${a.message}`),{error:a}}}function $qe(t){let e=Nz(t);return Tz(t).length===0?vs.configDotenv(t):Rz.existsSync(e)?vs._configVault(t):(Vqe(`You set DOTENV_KEY but you are missing a .env.vault file at ${e}. Did you forget to build it?`),vs.configDotenv(t))}function eje(t,e){let r=Buffer.from(e.slice(-64),"hex"),o=Buffer.from(t,"base64"),a=o.slice(0,12),n=o.slice(-16);o=o.slice(12,-16);try{let u=qqe.createDecipheriv("aes-256-gcm",r,a);return u.setAuthTag(n),`${u.update(o)}${u.final()}`}catch(u){let A=u instanceof RangeError,p=u.message==="Invalid key length",h=u.message==="Unsupported state or unable to authenticate data";if(A||p){let E="INVALID_DOTENV_KEY: It must be 64 characters long (or more)";throw new Error(E)}else if(h){let E="DECRYPTION_FAILED: Please check your DOTENV_KEY";throw new Error(E)}else throw console.error("Error: ",u.code),console.error("Error: ",u.message),u}}function tje(t,e,r={}){let o=!!(r&&r.debug),a=!!(r&&r.override);if(typeof e!="object")throw new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");for(let n of Object.keys(e))Object.prototype.hasOwnProperty.call(t,n)?(a===!0&&(t[n]=e[n]),o&&IN(a===!0?`"${n}" is already defined and WAS overwritten`:`"${n}" is already defined and was NOT overwritten`)):t[n]=e[n]}var vs={configDotenv:Zqe,_configVault:Xqe,_parseVault:Wqe,config:$qe,decrypt:eje,parse:Yqe,populate:tje};Ef.exports.configDotenv=vs.configDotenv;Ef.exports._configVault=vs._configVault;Ef.exports._parseVault=vs._parseVault;Ef.exports.config=vs.config;Ef.exports.decrypt=vs.decrypt;Ef.exports.parse=vs.parse;Ef.exports.populate=vs.populate;Ef.exports=vs});var Oz=_((Akt,Mz)=>{"use strict";Mz.exports=(t,...e)=>new Promise(r=>{r(t(...e))})});var lg=_((fkt,DN)=>{"use strict";var rje=Oz(),Uz=t=>{if(t<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],r=0,o=()=>{r--,e.length>0&&e.shift()()},a=(A,p,...h)=>{r++;let E=rje(A,...h);p(E),E.then(o,o)},n=(A,p,...h)=>{rnew Promise(h=>n(A,h,...p));return Object.defineProperties(u,{activeCount:{get:()=>r},pendingCount:{get:()=>e.length}}),u};DN.exports=Uz;DN.exports.default=Uz});function zu(t){return`YN${t.toString(10).padStart(4,"0")}`}function qP(t){let e=Number(t.slice(2));if(typeof vr[e]>"u")throw new Error(`Unknown message name: "${t}"`);return e}var vr,jP=wt(()=>{vr=(Oe=>(Oe[Oe.UNNAMED=0]="UNNAMED",Oe[Oe.EXCEPTION=1]="EXCEPTION",Oe[Oe.MISSING_PEER_DEPENDENCY=2]="MISSING_PEER_DEPENDENCY",Oe[Oe.CYCLIC_DEPENDENCIES=3]="CYCLIC_DEPENDENCIES",Oe[Oe.DISABLED_BUILD_SCRIPTS=4]="DISABLED_BUILD_SCRIPTS",Oe[Oe.BUILD_DISABLED=5]="BUILD_DISABLED",Oe[Oe.SOFT_LINK_BUILD=6]="SOFT_LINK_BUILD",Oe[Oe.MUST_BUILD=7]="MUST_BUILD",Oe[Oe.MUST_REBUILD=8]="MUST_REBUILD",Oe[Oe.BUILD_FAILED=9]="BUILD_FAILED",Oe[Oe.RESOLVER_NOT_FOUND=10]="RESOLVER_NOT_FOUND",Oe[Oe.FETCHER_NOT_FOUND=11]="FETCHER_NOT_FOUND",Oe[Oe.LINKER_NOT_FOUND=12]="LINKER_NOT_FOUND",Oe[Oe.FETCH_NOT_CACHED=13]="FETCH_NOT_CACHED",Oe[Oe.YARN_IMPORT_FAILED=14]="YARN_IMPORT_FAILED",Oe[Oe.REMOTE_INVALID=15]="REMOTE_INVALID",Oe[Oe.REMOTE_NOT_FOUND=16]="REMOTE_NOT_FOUND",Oe[Oe.RESOLUTION_PACK=17]="RESOLUTION_PACK",Oe[Oe.CACHE_CHECKSUM_MISMATCH=18]="CACHE_CHECKSUM_MISMATCH",Oe[Oe.UNUSED_CACHE_ENTRY=19]="UNUSED_CACHE_ENTRY",Oe[Oe.MISSING_LOCKFILE_ENTRY=20]="MISSING_LOCKFILE_ENTRY",Oe[Oe.WORKSPACE_NOT_FOUND=21]="WORKSPACE_NOT_FOUND",Oe[Oe.TOO_MANY_MATCHING_WORKSPACES=22]="TOO_MANY_MATCHING_WORKSPACES",Oe[Oe.CONSTRAINTS_MISSING_DEPENDENCY=23]="CONSTRAINTS_MISSING_DEPENDENCY",Oe[Oe.CONSTRAINTS_INCOMPATIBLE_DEPENDENCY=24]="CONSTRAINTS_INCOMPATIBLE_DEPENDENCY",Oe[Oe.CONSTRAINTS_EXTRANEOUS_DEPENDENCY=25]="CONSTRAINTS_EXTRANEOUS_DEPENDENCY",Oe[Oe.CONSTRAINTS_INVALID_DEPENDENCY=26]="CONSTRAINTS_INVALID_DEPENDENCY",Oe[Oe.CANT_SUGGEST_RESOLUTIONS=27]="CANT_SUGGEST_RESOLUTIONS",Oe[Oe.FROZEN_LOCKFILE_EXCEPTION=28]="FROZEN_LOCKFILE_EXCEPTION",Oe[Oe.CROSS_DRIVE_VIRTUAL_LOCAL=29]="CROSS_DRIVE_VIRTUAL_LOCAL",Oe[Oe.FETCH_FAILED=30]="FETCH_FAILED",Oe[Oe.DANGEROUS_NODE_MODULES=31]="DANGEROUS_NODE_MODULES",Oe[Oe.NODE_GYP_INJECTED=32]="NODE_GYP_INJECTED",Oe[Oe.AUTHENTICATION_NOT_FOUND=33]="AUTHENTICATION_NOT_FOUND",Oe[Oe.INVALID_CONFIGURATION_KEY=34]="INVALID_CONFIGURATION_KEY",Oe[Oe.NETWORK_ERROR=35]="NETWORK_ERROR",Oe[Oe.LIFECYCLE_SCRIPT=36]="LIFECYCLE_SCRIPT",Oe[Oe.CONSTRAINTS_MISSING_FIELD=37]="CONSTRAINTS_MISSING_FIELD",Oe[Oe.CONSTRAINTS_INCOMPATIBLE_FIELD=38]="CONSTRAINTS_INCOMPATIBLE_FIELD",Oe[Oe.CONSTRAINTS_EXTRANEOUS_FIELD=39]="CONSTRAINTS_EXTRANEOUS_FIELD",Oe[Oe.CONSTRAINTS_INVALID_FIELD=40]="CONSTRAINTS_INVALID_FIELD",Oe[Oe.AUTHENTICATION_INVALID=41]="AUTHENTICATION_INVALID",Oe[Oe.PROLOG_UNKNOWN_ERROR=42]="PROLOG_UNKNOWN_ERROR",Oe[Oe.PROLOG_SYNTAX_ERROR=43]="PROLOG_SYNTAX_ERROR",Oe[Oe.PROLOG_EXISTENCE_ERROR=44]="PROLOG_EXISTENCE_ERROR",Oe[Oe.STACK_OVERFLOW_RESOLUTION=45]="STACK_OVERFLOW_RESOLUTION",Oe[Oe.AUTOMERGE_FAILED_TO_PARSE=46]="AUTOMERGE_FAILED_TO_PARSE",Oe[Oe.AUTOMERGE_IMMUTABLE=47]="AUTOMERGE_IMMUTABLE",Oe[Oe.AUTOMERGE_SUCCESS=48]="AUTOMERGE_SUCCESS",Oe[Oe.AUTOMERGE_REQUIRED=49]="AUTOMERGE_REQUIRED",Oe[Oe.DEPRECATED_CLI_SETTINGS=50]="DEPRECATED_CLI_SETTINGS",Oe[Oe.PLUGIN_NAME_NOT_FOUND=51]="PLUGIN_NAME_NOT_FOUND",Oe[Oe.INVALID_PLUGIN_REFERENCE=52]="INVALID_PLUGIN_REFERENCE",Oe[Oe.CONSTRAINTS_AMBIGUITY=53]="CONSTRAINTS_AMBIGUITY",Oe[Oe.CACHE_OUTSIDE_PROJECT=54]="CACHE_OUTSIDE_PROJECT",Oe[Oe.IMMUTABLE_INSTALL=55]="IMMUTABLE_INSTALL",Oe[Oe.IMMUTABLE_CACHE=56]="IMMUTABLE_CACHE",Oe[Oe.INVALID_MANIFEST=57]="INVALID_MANIFEST",Oe[Oe.PACKAGE_PREPARATION_FAILED=58]="PACKAGE_PREPARATION_FAILED",Oe[Oe.INVALID_RANGE_PEER_DEPENDENCY=59]="INVALID_RANGE_PEER_DEPENDENCY",Oe[Oe.INCOMPATIBLE_PEER_DEPENDENCY=60]="INCOMPATIBLE_PEER_DEPENDENCY",Oe[Oe.DEPRECATED_PACKAGE=61]="DEPRECATED_PACKAGE",Oe[Oe.INCOMPATIBLE_OS=62]="INCOMPATIBLE_OS",Oe[Oe.INCOMPATIBLE_CPU=63]="INCOMPATIBLE_CPU",Oe[Oe.FROZEN_ARTIFACT_EXCEPTION=64]="FROZEN_ARTIFACT_EXCEPTION",Oe[Oe.TELEMETRY_NOTICE=65]="TELEMETRY_NOTICE",Oe[Oe.PATCH_HUNK_FAILED=66]="PATCH_HUNK_FAILED",Oe[Oe.INVALID_CONFIGURATION_VALUE=67]="INVALID_CONFIGURATION_VALUE",Oe[Oe.UNUSED_PACKAGE_EXTENSION=68]="UNUSED_PACKAGE_EXTENSION",Oe[Oe.REDUNDANT_PACKAGE_EXTENSION=69]="REDUNDANT_PACKAGE_EXTENSION",Oe[Oe.AUTO_NM_SUCCESS=70]="AUTO_NM_SUCCESS",Oe[Oe.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK=71]="NM_CANT_INSTALL_EXTERNAL_SOFT_LINK",Oe[Oe.NM_PRESERVE_SYMLINKS_REQUIRED=72]="NM_PRESERVE_SYMLINKS_REQUIRED",Oe[Oe.UPDATE_LOCKFILE_ONLY_SKIP_LINK=73]="UPDATE_LOCKFILE_ONLY_SKIP_LINK",Oe[Oe.NM_HARDLINKS_MODE_DOWNGRADED=74]="NM_HARDLINKS_MODE_DOWNGRADED",Oe[Oe.PROLOG_INSTANTIATION_ERROR=75]="PROLOG_INSTANTIATION_ERROR",Oe[Oe.INCOMPATIBLE_ARCHITECTURE=76]="INCOMPATIBLE_ARCHITECTURE",Oe[Oe.GHOST_ARCHITECTURE=77]="GHOST_ARCHITECTURE",Oe[Oe.RESOLUTION_MISMATCH=78]="RESOLUTION_MISMATCH",Oe[Oe.PROLOG_LIMIT_EXCEEDED=79]="PROLOG_LIMIT_EXCEEDED",Oe[Oe.NETWORK_DISABLED=80]="NETWORK_DISABLED",Oe[Oe.NETWORK_UNSAFE_HTTP=81]="NETWORK_UNSAFE_HTTP",Oe[Oe.RESOLUTION_FAILED=82]="RESOLUTION_FAILED",Oe[Oe.AUTOMERGE_GIT_ERROR=83]="AUTOMERGE_GIT_ERROR",Oe[Oe.CONSTRAINTS_CHECK_FAILED=84]="CONSTRAINTS_CHECK_FAILED",Oe[Oe.UPDATED_RESOLUTION_RECORD=85]="UPDATED_RESOLUTION_RECORD",Oe[Oe.EXPLAIN_PEER_DEPENDENCIES_CTA=86]="EXPLAIN_PEER_DEPENDENCIES_CTA",Oe[Oe.MIGRATION_SUCCESS=87]="MIGRATION_SUCCESS",Oe[Oe.VERSION_NOTICE=88]="VERSION_NOTICE",Oe[Oe.TIPS_NOTICE=89]="TIPS_NOTICE",Oe[Oe.OFFLINE_MODE_ENABLED=90]="OFFLINE_MODE_ENABLED",Oe))(vr||{})});var FI=_((hkt,_z)=>{var nje="2.0.0",ije=Number.MAX_SAFE_INTEGER||9007199254740991,sje=16,oje=250,aje=["major","premajor","minor","preminor","patch","prepatch","prerelease"];_z.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:sje,MAX_SAFE_BUILD_LENGTH:oje,MAX_SAFE_INTEGER:ije,RELEASE_TYPES:aje,SEMVER_SPEC_VERSION:nje,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}});var RI=_((gkt,Hz)=>{var lje=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...t)=>console.error("SEMVER",...t):()=>{};Hz.exports=lje});var xm=_((Cf,qz)=>{var{MAX_SAFE_COMPONENT_LENGTH:PN,MAX_SAFE_BUILD_LENGTH:cje,MAX_LENGTH:uje}=FI(),Aje=RI();Cf=qz.exports={};var fje=Cf.re=[],pje=Cf.safeRe=[],tr=Cf.src=[],rr=Cf.t={},hje=0,SN="[a-zA-Z0-9-]",gje=[["\\s",1],["\\d",uje],[SN,cje]],dje=t=>{for(let[e,r]of gje)t=t.split(`${e}*`).join(`${e}{0,${r}}`).split(`${e}+`).join(`${e}{1,${r}}`);return t},Gr=(t,e,r)=>{let o=dje(e),a=hje++;Aje(t,a,e),rr[t]=a,tr[a]=e,fje[a]=new RegExp(e,r?"g":void 0),pje[a]=new RegExp(o,r?"g":void 0)};Gr("NUMERICIDENTIFIER","0|[1-9]\\d*");Gr("NUMERICIDENTIFIERLOOSE","\\d+");Gr("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${SN}*`);Gr("MAINVERSION",`(${tr[rr.NUMERICIDENTIFIER]})\\.(${tr[rr.NUMERICIDENTIFIER]})\\.(${tr[rr.NUMERICIDENTIFIER]})`);Gr("MAINVERSIONLOOSE",`(${tr[rr.NUMERICIDENTIFIERLOOSE]})\\.(${tr[rr.NUMERICIDENTIFIERLOOSE]})\\.(${tr[rr.NUMERICIDENTIFIERLOOSE]})`);Gr("PRERELEASEIDENTIFIER",`(?:${tr[rr.NUMERICIDENTIFIER]}|${tr[rr.NONNUMERICIDENTIFIER]})`);Gr("PRERELEASEIDENTIFIERLOOSE",`(?:${tr[rr.NUMERICIDENTIFIERLOOSE]}|${tr[rr.NONNUMERICIDENTIFIER]})`);Gr("PRERELEASE",`(?:-(${tr[rr.PRERELEASEIDENTIFIER]}(?:\\.${tr[rr.PRERELEASEIDENTIFIER]})*))`);Gr("PRERELEASELOOSE",`(?:-?(${tr[rr.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${tr[rr.PRERELEASEIDENTIFIERLOOSE]})*))`);Gr("BUILDIDENTIFIER",`${SN}+`);Gr("BUILD",`(?:\\+(${tr[rr.BUILDIDENTIFIER]}(?:\\.${tr[rr.BUILDIDENTIFIER]})*))`);Gr("FULLPLAIN",`v?${tr[rr.MAINVERSION]}${tr[rr.PRERELEASE]}?${tr[rr.BUILD]}?`);Gr("FULL",`^${tr[rr.FULLPLAIN]}$`);Gr("LOOSEPLAIN",`[v=\\s]*${tr[rr.MAINVERSIONLOOSE]}${tr[rr.PRERELEASELOOSE]}?${tr[rr.BUILD]}?`);Gr("LOOSE",`^${tr[rr.LOOSEPLAIN]}$`);Gr("GTLT","((?:<|>)?=?)");Gr("XRANGEIDENTIFIERLOOSE",`${tr[rr.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);Gr("XRANGEIDENTIFIER",`${tr[rr.NUMERICIDENTIFIER]}|x|X|\\*`);Gr("XRANGEPLAIN",`[v=\\s]*(${tr[rr.XRANGEIDENTIFIER]})(?:\\.(${tr[rr.XRANGEIDENTIFIER]})(?:\\.(${tr[rr.XRANGEIDENTIFIER]})(?:${tr[rr.PRERELEASE]})?${tr[rr.BUILD]}?)?)?`);Gr("XRANGEPLAINLOOSE",`[v=\\s]*(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:\\.(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:\\.(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:${tr[rr.PRERELEASELOOSE]})?${tr[rr.BUILD]}?)?)?`);Gr("XRANGE",`^${tr[rr.GTLT]}\\s*${tr[rr.XRANGEPLAIN]}$`);Gr("XRANGELOOSE",`^${tr[rr.GTLT]}\\s*${tr[rr.XRANGEPLAINLOOSE]}$`);Gr("COERCEPLAIN",`(^|[^\\d])(\\d{1,${PN}})(?:\\.(\\d{1,${PN}}))?(?:\\.(\\d{1,${PN}}))?`);Gr("COERCE",`${tr[rr.COERCEPLAIN]}(?:$|[^\\d])`);Gr("COERCEFULL",tr[rr.COERCEPLAIN]+`(?:${tr[rr.PRERELEASE]})?(?:${tr[rr.BUILD]})?(?:$|[^\\d])`);Gr("COERCERTL",tr[rr.COERCE],!0);Gr("COERCERTLFULL",tr[rr.COERCEFULL],!0);Gr("LONETILDE","(?:~>?)");Gr("TILDETRIM",`(\\s*)${tr[rr.LONETILDE]}\\s+`,!0);Cf.tildeTrimReplace="$1~";Gr("TILDE",`^${tr[rr.LONETILDE]}${tr[rr.XRANGEPLAIN]}$`);Gr("TILDELOOSE",`^${tr[rr.LONETILDE]}${tr[rr.XRANGEPLAINLOOSE]}$`);Gr("LONECARET","(?:\\^)");Gr("CARETTRIM",`(\\s*)${tr[rr.LONECARET]}\\s+`,!0);Cf.caretTrimReplace="$1^";Gr("CARET",`^${tr[rr.LONECARET]}${tr[rr.XRANGEPLAIN]}$`);Gr("CARETLOOSE",`^${tr[rr.LONECARET]}${tr[rr.XRANGEPLAINLOOSE]}$`);Gr("COMPARATORLOOSE",`^${tr[rr.GTLT]}\\s*(${tr[rr.LOOSEPLAIN]})$|^$`);Gr("COMPARATOR",`^${tr[rr.GTLT]}\\s*(${tr[rr.FULLPLAIN]})$|^$`);Gr("COMPARATORTRIM",`(\\s*)${tr[rr.GTLT]}\\s*(${tr[rr.LOOSEPLAIN]}|${tr[rr.XRANGEPLAIN]})`,!0);Cf.comparatorTrimReplace="$1$2$3";Gr("HYPHENRANGE",`^\\s*(${tr[rr.XRANGEPLAIN]})\\s+-\\s+(${tr[rr.XRANGEPLAIN]})\\s*$`);Gr("HYPHENRANGELOOSE",`^\\s*(${tr[rr.XRANGEPLAINLOOSE]})\\s+-\\s+(${tr[rr.XRANGEPLAINLOOSE]})\\s*$`);Gr("STAR","(<|>)?=?\\s*\\*");Gr("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$");Gr("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")});var GP=_((dkt,jz)=>{var mje=Object.freeze({loose:!0}),yje=Object.freeze({}),Eje=t=>t?typeof t!="object"?mje:t:yje;jz.exports=Eje});var bN=_((mkt,Wz)=>{var Gz=/^[0-9]+$/,Yz=(t,e)=>{let r=Gz.test(t),o=Gz.test(e);return r&&o&&(t=+t,e=+e),t===e?0:r&&!o?-1:o&&!r?1:tYz(e,t);Wz.exports={compareIdentifiers:Yz,rcompareIdentifiers:Cje}});var Eo=_((ykt,Jz)=>{var YP=RI(),{MAX_LENGTH:Kz,MAX_SAFE_INTEGER:WP}=FI(),{safeRe:Vz,t:zz}=xm(),wje=GP(),{compareIdentifiers:km}=bN(),xN=class t{constructor(e,r){if(r=wje(r),e instanceof t){if(e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>Kz)throw new TypeError(`version is longer than ${Kz} characters`);YP("SemVer",e,r),this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease;let o=e.trim().match(r.loose?Vz[zz.LOOSE]:Vz[zz.FULL]);if(!o)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+o[1],this.minor=+o[2],this.patch=+o[3],this.major>WP||this.major<0)throw new TypeError("Invalid major version");if(this.minor>WP||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>WP||this.patch<0)throw new TypeError("Invalid patch version");o[4]?this.prerelease=o[4].split(".").map(a=>{if(/^[0-9]+$/.test(a)){let n=+a;if(n>=0&&n=0;)typeof this.prerelease[n]=="number"&&(this.prerelease[n]++,n=-2);if(n===-1){if(r===this.prerelease.join(".")&&o===!1)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(a)}}if(r){let n=[r,a];o===!1&&(n=[r]),km(this.prerelease[0],r)===0?isNaN(this.prerelease[1])&&(this.prerelease=n):this.prerelease=n}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}};Jz.exports=xN});var cg=_((Ekt,Zz)=>{var Xz=Eo(),Ije=(t,e,r=!1)=>{if(t instanceof Xz)return t;try{return new Xz(t,e)}catch(o){if(!r)return null;throw o}};Zz.exports=Ije});var eJ=_((Ckt,$z)=>{var Bje=cg(),vje=(t,e)=>{let r=Bje(t,e);return r?r.version:null};$z.exports=vje});var rJ=_((wkt,tJ)=>{var Dje=cg(),Pje=(t,e)=>{let r=Dje(t.trim().replace(/^[=v]+/,""),e);return r?r.version:null};tJ.exports=Pje});var sJ=_((Ikt,iJ)=>{var nJ=Eo(),Sje=(t,e,r,o,a)=>{typeof r=="string"&&(a=o,o=r,r=void 0);try{return new nJ(t instanceof nJ?t.version:t,r).inc(e,o,a).version}catch{return null}};iJ.exports=Sje});var lJ=_((Bkt,aJ)=>{var oJ=cg(),bje=(t,e)=>{let r=oJ(t,null,!0),o=oJ(e,null,!0),a=r.compare(o);if(a===0)return null;let n=a>0,u=n?r:o,A=n?o:r,p=!!u.prerelease.length;if(!!A.prerelease.length&&!p)return!A.patch&&!A.minor?"major":u.patch?"patch":u.minor?"minor":"major";let E=p?"pre":"";return r.major!==o.major?E+"major":r.minor!==o.minor?E+"minor":r.patch!==o.patch?E+"patch":"prerelease"};aJ.exports=bje});var uJ=_((vkt,cJ)=>{var xje=Eo(),kje=(t,e)=>new xje(t,e).major;cJ.exports=kje});var fJ=_((Dkt,AJ)=>{var Qje=Eo(),Fje=(t,e)=>new Qje(t,e).minor;AJ.exports=Fje});var hJ=_((Pkt,pJ)=>{var Rje=Eo(),Tje=(t,e)=>new Rje(t,e).patch;pJ.exports=Tje});var dJ=_((Skt,gJ)=>{var Nje=cg(),Lje=(t,e)=>{let r=Nje(t,e);return r&&r.prerelease.length?r.prerelease:null};gJ.exports=Lje});var Ol=_((bkt,yJ)=>{var mJ=Eo(),Mje=(t,e,r)=>new mJ(t,r).compare(new mJ(e,r));yJ.exports=Mje});var CJ=_((xkt,EJ)=>{var Oje=Ol(),Uje=(t,e,r)=>Oje(e,t,r);EJ.exports=Uje});var IJ=_((kkt,wJ)=>{var _je=Ol(),Hje=(t,e)=>_je(t,e,!0);wJ.exports=Hje});var KP=_((Qkt,vJ)=>{var BJ=Eo(),qje=(t,e,r)=>{let o=new BJ(t,r),a=new BJ(e,r);return o.compare(a)||o.compareBuild(a)};vJ.exports=qje});var PJ=_((Fkt,DJ)=>{var jje=KP(),Gje=(t,e)=>t.sort((r,o)=>jje(r,o,e));DJ.exports=Gje});var bJ=_((Rkt,SJ)=>{var Yje=KP(),Wje=(t,e)=>t.sort((r,o)=>Yje(o,r,e));SJ.exports=Wje});var TI=_((Tkt,xJ)=>{var Kje=Ol(),Vje=(t,e,r)=>Kje(t,e,r)>0;xJ.exports=Vje});var VP=_((Nkt,kJ)=>{var zje=Ol(),Jje=(t,e,r)=>zje(t,e,r)<0;kJ.exports=Jje});var kN=_((Lkt,QJ)=>{var Xje=Ol(),Zje=(t,e,r)=>Xje(t,e,r)===0;QJ.exports=Zje});var QN=_((Mkt,FJ)=>{var $je=Ol(),e5e=(t,e,r)=>$je(t,e,r)!==0;FJ.exports=e5e});var zP=_((Okt,RJ)=>{var t5e=Ol(),r5e=(t,e,r)=>t5e(t,e,r)>=0;RJ.exports=r5e});var JP=_((Ukt,TJ)=>{var n5e=Ol(),i5e=(t,e,r)=>n5e(t,e,r)<=0;TJ.exports=i5e});var FN=_((_kt,NJ)=>{var s5e=kN(),o5e=QN(),a5e=TI(),l5e=zP(),c5e=VP(),u5e=JP(),A5e=(t,e,r,o)=>{switch(e){case"===":return typeof t=="object"&&(t=t.version),typeof r=="object"&&(r=r.version),t===r;case"!==":return typeof t=="object"&&(t=t.version),typeof r=="object"&&(r=r.version),t!==r;case"":case"=":case"==":return s5e(t,r,o);case"!=":return o5e(t,r,o);case">":return a5e(t,r,o);case">=":return l5e(t,r,o);case"<":return c5e(t,r,o);case"<=":return u5e(t,r,o);default:throw new TypeError(`Invalid operator: ${e}`)}};NJ.exports=A5e});var MJ=_((Hkt,LJ)=>{var f5e=Eo(),p5e=cg(),{safeRe:XP,t:ZP}=xm(),h5e=(t,e)=>{if(t instanceof f5e)return t;if(typeof t=="number"&&(t=String(t)),typeof t!="string")return null;e=e||{};let r=null;if(!e.rtl)r=t.match(e.includePrerelease?XP[ZP.COERCEFULL]:XP[ZP.COERCE]);else{let p=e.includePrerelease?XP[ZP.COERCERTLFULL]:XP[ZP.COERCERTL],h;for(;(h=p.exec(t))&&(!r||r.index+r[0].length!==t.length);)(!r||h.index+h[0].length!==r.index+r[0].length)&&(r=h),p.lastIndex=h.index+h[1].length+h[2].length;p.lastIndex=-1}if(r===null)return null;let o=r[2],a=r[3]||"0",n=r[4]||"0",u=e.includePrerelease&&r[5]?`-${r[5]}`:"",A=e.includePrerelease&&r[6]?`+${r[6]}`:"";return p5e(`${o}.${a}.${n}${u}${A}`,e)};LJ.exports=h5e});var UJ=_((qkt,OJ)=>{"use strict";OJ.exports=function(t){t.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var $P=_((jkt,_J)=>{"use strict";_J.exports=bn;bn.Node=ug;bn.create=bn;function bn(t){var e=this;if(e instanceof bn||(e=new bn),e.tail=null,e.head=null,e.length=0,t&&typeof t.forEach=="function")t.forEach(function(a){e.push(a)});else if(arguments.length>0)for(var r=0,o=arguments.length;r1)r=e;else if(this.head)o=this.head.next,r=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var a=0;o!==null;a++)r=t(r,o.value,a),o=o.next;return r};bn.prototype.reduceReverse=function(t,e){var r,o=this.tail;if(arguments.length>1)r=e;else if(this.tail)o=this.tail.prev,r=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var a=this.length-1;o!==null;a--)r=t(r,o.value,a),o=o.prev;return r};bn.prototype.toArray=function(){for(var t=new Array(this.length),e=0,r=this.head;r!==null;e++)t[e]=r.value,r=r.next;return t};bn.prototype.toArrayReverse=function(){for(var t=new Array(this.length),e=0,r=this.tail;r!==null;e++)t[e]=r.value,r=r.prev;return t};bn.prototype.slice=function(t,e){e=e||this.length,e<0&&(e+=this.length),t=t||0,t<0&&(t+=this.length);var r=new bn;if(ethis.length&&(e=this.length);for(var o=0,a=this.head;a!==null&&othis.length&&(e=this.length);for(var o=this.length,a=this.tail;a!==null&&o>e;o--)a=a.prev;for(;a!==null&&o>t;o--,a=a.prev)r.push(a.value);return r};bn.prototype.splice=function(t,e,...r){t>this.length&&(t=this.length-1),t<0&&(t=this.length+t);for(var o=0,a=this.head;a!==null&&o{"use strict";var y5e=$P(),Ag=Symbol("max"),If=Symbol("length"),Qm=Symbol("lengthCalculator"),LI=Symbol("allowStale"),fg=Symbol("maxAge"),wf=Symbol("dispose"),HJ=Symbol("noDisposeOnSet"),Ds=Symbol("lruList"),Gc=Symbol("cache"),jJ=Symbol("updateAgeOnGet"),RN=()=>1,NN=class{constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!="number"||e.max<0))throw new TypeError("max must be a non-negative number");let r=this[Ag]=e.max||1/0,o=e.length||RN;if(this[Qm]=typeof o!="function"?RN:o,this[LI]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[fg]=e.maxAge||0,this[wf]=e.dispose,this[HJ]=e.noDisposeOnSet||!1,this[jJ]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a non-negative number");this[Ag]=e||1/0,NI(this)}get max(){return this[Ag]}set allowStale(e){this[LI]=!!e}get allowStale(){return this[LI]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[fg]=e,NI(this)}get maxAge(){return this[fg]}set lengthCalculator(e){typeof e!="function"&&(e=RN),e!==this[Qm]&&(this[Qm]=e,this[If]=0,this[Ds].forEach(r=>{r.length=this[Qm](r.value,r.key),this[If]+=r.length})),NI(this)}get lengthCalculator(){return this[Qm]}get length(){return this[If]}get itemCount(){return this[Ds].length}rforEach(e,r){r=r||this;for(let o=this[Ds].tail;o!==null;){let a=o.prev;qJ(this,e,o,r),o=a}}forEach(e,r){r=r||this;for(let o=this[Ds].head;o!==null;){let a=o.next;qJ(this,e,o,r),o=a}}keys(){return this[Ds].toArray().map(e=>e.key)}values(){return this[Ds].toArray().map(e=>e.value)}reset(){this[wf]&&this[Ds]&&this[Ds].length&&this[Ds].forEach(e=>this[wf](e.key,e.value)),this[Gc]=new Map,this[Ds]=new y5e,this[If]=0}dump(){return this[Ds].map(e=>eS(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[Ds]}set(e,r,o){if(o=o||this[fg],o&&typeof o!="number")throw new TypeError("maxAge must be a number");let a=o?Date.now():0,n=this[Qm](r,e);if(this[Gc].has(e)){if(n>this[Ag])return Fm(this,this[Gc].get(e)),!1;let p=this[Gc].get(e).value;return this[wf]&&(this[HJ]||this[wf](e,p.value)),p.now=a,p.maxAge=o,p.value=r,this[If]+=n-p.length,p.length=n,this.get(e),NI(this),!0}let u=new LN(e,r,n,a,o);return u.length>this[Ag]?(this[wf]&&this[wf](e,r),!1):(this[If]+=u.length,this[Ds].unshift(u),this[Gc].set(e,this[Ds].head),NI(this),!0)}has(e){if(!this[Gc].has(e))return!1;let r=this[Gc].get(e).value;return!eS(this,r)}get(e){return TN(this,e,!0)}peek(e){return TN(this,e,!1)}pop(){let e=this[Ds].tail;return e?(Fm(this,e),e.value):null}del(e){Fm(this,this[Gc].get(e))}load(e){this.reset();let r=Date.now();for(let o=e.length-1;o>=0;o--){let a=e[o],n=a.e||0;if(n===0)this.set(a.k,a.v);else{let u=n-r;u>0&&this.set(a.k,a.v,u)}}}prune(){this[Gc].forEach((e,r)=>TN(this,r,!1))}},TN=(t,e,r)=>{let o=t[Gc].get(e);if(o){let a=o.value;if(eS(t,a)){if(Fm(t,o),!t[LI])return}else r&&(t[jJ]&&(o.value.now=Date.now()),t[Ds].unshiftNode(o));return a.value}},eS=(t,e)=>{if(!e||!e.maxAge&&!t[fg])return!1;let r=Date.now()-e.now;return e.maxAge?r>e.maxAge:t[fg]&&r>t[fg]},NI=t=>{if(t[If]>t[Ag])for(let e=t[Ds].tail;t[If]>t[Ag]&&e!==null;){let r=e.prev;Fm(t,e),e=r}},Fm=(t,e)=>{if(e){let r=e.value;t[wf]&&t[wf](r.key,r.value),t[If]-=r.length,t[Gc].delete(r.key),t[Ds].removeNode(e)}},LN=class{constructor(e,r,o,a,n){this.key=e,this.value=r,this.length=o,this.now=a,this.maxAge=n||0}},qJ=(t,e,r,o)=>{let a=r.value;eS(t,a)&&(Fm(t,r),t[LI]||(a=void 0)),a&&e.call(o,a.value,a.key,t)};GJ.exports=NN});var Ul=_((Ykt,zJ)=>{var MN=class t{constructor(e,r){if(r=C5e(r),e instanceof t)return e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease?e:new t(e.raw,r);if(e instanceof ON)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease,this.raw=e.trim().split(/\s+/).join(" "),this.set=this.raw.split("||").map(o=>this.parseRange(o.trim())).filter(o=>o.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){let o=this.set[0];if(this.set=this.set.filter(a=>!KJ(a[0])),this.set.length===0)this.set=[o];else if(this.set.length>1){for(let a of this.set)if(a.length===1&&S5e(a[0])){this.set=[a];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){let o=((this.options.includePrerelease&&D5e)|(this.options.loose&&P5e))+":"+e,a=WJ.get(o);if(a)return a;let n=this.options.loose,u=n?ba[zo.HYPHENRANGELOOSE]:ba[zo.HYPHENRANGE];e=e.replace(u,M5e(this.options.includePrerelease)),gi("hyphen replace",e),e=e.replace(ba[zo.COMPARATORTRIM],I5e),gi("comparator trim",e),e=e.replace(ba[zo.TILDETRIM],B5e),gi("tilde trim",e),e=e.replace(ba[zo.CARETTRIM],v5e),gi("caret trim",e);let A=e.split(" ").map(I=>b5e(I,this.options)).join(" ").split(/\s+/).map(I=>L5e(I,this.options));n&&(A=A.filter(I=>(gi("loose invalid filter",I,this.options),!!I.match(ba[zo.COMPARATORLOOSE])))),gi("range list",A);let p=new Map,h=A.map(I=>new ON(I,this.options));for(let I of h){if(KJ(I))return[I];p.set(I.value,I)}p.size>1&&p.has("")&&p.delete("");let E=[...p.values()];return WJ.set(o,E),E}intersects(e,r){if(!(e instanceof t))throw new TypeError("a Range is required");return this.set.some(o=>VJ(o,r)&&e.set.some(a=>VJ(a,r)&&o.every(n=>a.every(u=>n.intersects(u,r)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new w5e(e,this.options)}catch{return!1}for(let r=0;rt.value==="<0.0.0-0",S5e=t=>t.value==="",VJ=(t,e)=>{let r=!0,o=t.slice(),a=o.pop();for(;r&&o.length;)r=o.every(n=>a.intersects(n,e)),a=o.pop();return r},b5e=(t,e)=>(gi("comp",t,e),t=Q5e(t,e),gi("caret",t),t=x5e(t,e),gi("tildes",t),t=R5e(t,e),gi("xrange",t),t=N5e(t,e),gi("stars",t),t),Jo=t=>!t||t.toLowerCase()==="x"||t==="*",x5e=(t,e)=>t.trim().split(/\s+/).map(r=>k5e(r,e)).join(" "),k5e=(t,e)=>{let r=e.loose?ba[zo.TILDELOOSE]:ba[zo.TILDE];return t.replace(r,(o,a,n,u,A)=>{gi("tilde",t,o,a,n,u,A);let p;return Jo(a)?p="":Jo(n)?p=`>=${a}.0.0 <${+a+1}.0.0-0`:Jo(u)?p=`>=${a}.${n}.0 <${a}.${+n+1}.0-0`:A?(gi("replaceTilde pr",A),p=`>=${a}.${n}.${u}-${A} <${a}.${+n+1}.0-0`):p=`>=${a}.${n}.${u} <${a}.${+n+1}.0-0`,gi("tilde return",p),p})},Q5e=(t,e)=>t.trim().split(/\s+/).map(r=>F5e(r,e)).join(" "),F5e=(t,e)=>{gi("caret",t,e);let r=e.loose?ba[zo.CARETLOOSE]:ba[zo.CARET],o=e.includePrerelease?"-0":"";return t.replace(r,(a,n,u,A,p)=>{gi("caret",t,a,n,u,A,p);let h;return Jo(n)?h="":Jo(u)?h=`>=${n}.0.0${o} <${+n+1}.0.0-0`:Jo(A)?n==="0"?h=`>=${n}.${u}.0${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.0${o} <${+n+1}.0.0-0`:p?(gi("replaceCaret pr",p),n==="0"?u==="0"?h=`>=${n}.${u}.${A}-${p} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}-${p} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A}-${p} <${+n+1}.0.0-0`):(gi("no pr"),n==="0"?u==="0"?h=`>=${n}.${u}.${A}${o} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A} <${+n+1}.0.0-0`),gi("caret return",h),h})},R5e=(t,e)=>(gi("replaceXRanges",t,e),t.split(/\s+/).map(r=>T5e(r,e)).join(" ")),T5e=(t,e)=>{t=t.trim();let r=e.loose?ba[zo.XRANGELOOSE]:ba[zo.XRANGE];return t.replace(r,(o,a,n,u,A,p)=>{gi("xRange",t,o,a,n,u,A,p);let h=Jo(n),E=h||Jo(u),I=E||Jo(A),D=I;return a==="="&&D&&(a=""),p=e.includePrerelease?"-0":"",h?a===">"||a==="<"?o="<0.0.0-0":o="*":a&&D?(E&&(u=0),A=0,a===">"?(a=">=",E?(n=+n+1,u=0,A=0):(u=+u+1,A=0)):a==="<="&&(a="<",E?n=+n+1:u=+u+1),a==="<"&&(p="-0"),o=`${a+n}.${u}.${A}${p}`):E?o=`>=${n}.0.0${p} <${+n+1}.0.0-0`:I&&(o=`>=${n}.${u}.0${p} <${n}.${+u+1}.0-0`),gi("xRange return",o),o})},N5e=(t,e)=>(gi("replaceStars",t,e),t.trim().replace(ba[zo.STAR],"")),L5e=(t,e)=>(gi("replaceGTE0",t,e),t.trim().replace(ba[e.includePrerelease?zo.GTE0PRE:zo.GTE0],"")),M5e=t=>(e,r,o,a,n,u,A,p,h,E,I,D,x)=>(Jo(o)?r="":Jo(a)?r=`>=${o}.0.0${t?"-0":""}`:Jo(n)?r=`>=${o}.${a}.0${t?"-0":""}`:u?r=`>=${r}`:r=`>=${r}${t?"-0":""}`,Jo(h)?p="":Jo(E)?p=`<${+h+1}.0.0-0`:Jo(I)?p=`<${h}.${+E+1}.0-0`:D?p=`<=${h}.${E}.${I}-${D}`:t?p=`<${h}.${E}.${+I+1}-0`:p=`<=${p}`,`${r} ${p}`.trim()),O5e=(t,e,r)=>{for(let o=0;o0){let a=t[o].semver;if(a.major===e.major&&a.minor===e.minor&&a.patch===e.patch)return!0}return!1}return!0}});var MI=_((Wkt,tX)=>{var OI=Symbol("SemVer ANY"),HN=class t{static get ANY(){return OI}constructor(e,r){if(r=JJ(r),e instanceof t){if(e.loose===!!r.loose)return e;e=e.value}e=e.trim().split(/\s+/).join(" "),_N("comparator",e,r),this.options=r,this.loose=!!r.loose,this.parse(e),this.semver===OI?this.value="":this.value=this.operator+this.semver.version,_N("comp",this)}parse(e){let r=this.options.loose?XJ[ZJ.COMPARATORLOOSE]:XJ[ZJ.COMPARATOR],o=e.match(r);if(!o)throw new TypeError(`Invalid comparator: ${e}`);this.operator=o[1]!==void 0?o[1]:"",this.operator==="="&&(this.operator=""),o[2]?this.semver=new $J(o[2],this.options.loose):this.semver=OI}toString(){return this.value}test(e){if(_N("Comparator.test",e,this.options.loose),this.semver===OI||e===OI)return!0;if(typeof e=="string")try{e=new $J(e,this.options)}catch{return!1}return UN(e,this.operator,this.semver,this.options)}intersects(e,r){if(!(e instanceof t))throw new TypeError("a Comparator is required");return this.operator===""?this.value===""?!0:new eX(e.value,r).test(this.value):e.operator===""?e.value===""?!0:new eX(this.value,r).test(e.semver):(r=JJ(r),r.includePrerelease&&(this.value==="<0.0.0-0"||e.value==="<0.0.0-0")||!r.includePrerelease&&(this.value.startsWith("<0.0.0")||e.value.startsWith("<0.0.0"))?!1:!!(this.operator.startsWith(">")&&e.operator.startsWith(">")||this.operator.startsWith("<")&&e.operator.startsWith("<")||this.semver.version===e.semver.version&&this.operator.includes("=")&&e.operator.includes("=")||UN(this.semver,"<",e.semver,r)&&this.operator.startsWith(">")&&e.operator.startsWith("<")||UN(this.semver,">",e.semver,r)&&this.operator.startsWith("<")&&e.operator.startsWith(">")))}};tX.exports=HN;var JJ=GP(),{safeRe:XJ,t:ZJ}=xm(),UN=FN(),_N=RI(),$J=Eo(),eX=Ul()});var UI=_((Kkt,rX)=>{var U5e=Ul(),_5e=(t,e,r)=>{try{e=new U5e(e,r)}catch{return!1}return e.test(t)};rX.exports=_5e});var iX=_((Vkt,nX)=>{var H5e=Ul(),q5e=(t,e)=>new H5e(t,e).set.map(r=>r.map(o=>o.value).join(" ").trim().split(" "));nX.exports=q5e});var oX=_((zkt,sX)=>{var j5e=Eo(),G5e=Ul(),Y5e=(t,e,r)=>{let o=null,a=null,n=null;try{n=new G5e(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===-1)&&(o=u,a=new j5e(o,r))}),o};sX.exports=Y5e});var lX=_((Jkt,aX)=>{var W5e=Eo(),K5e=Ul(),V5e=(t,e,r)=>{let o=null,a=null,n=null;try{n=new K5e(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===1)&&(o=u,a=new W5e(o,r))}),o};aX.exports=V5e});var AX=_((Xkt,uX)=>{var qN=Eo(),z5e=Ul(),cX=TI(),J5e=(t,e)=>{t=new z5e(t,e);let r=new qN("0.0.0");if(t.test(r)||(r=new qN("0.0.0-0"),t.test(r)))return r;r=null;for(let o=0;o{let A=new qN(u.semver.version);switch(u.operator){case">":A.prerelease.length===0?A.patch++:A.prerelease.push(0),A.raw=A.format();case"":case">=":(!n||cX(A,n))&&(n=A);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${u.operator}`)}}),n&&(!r||cX(r,n))&&(r=n)}return r&&t.test(r)?r:null};uX.exports=J5e});var pX=_((Zkt,fX)=>{var X5e=Ul(),Z5e=(t,e)=>{try{return new X5e(t,e).range||"*"}catch{return null}};fX.exports=Z5e});var tS=_(($kt,mX)=>{var $5e=Eo(),dX=MI(),{ANY:eGe}=dX,tGe=Ul(),rGe=UI(),hX=TI(),gX=VP(),nGe=JP(),iGe=zP(),sGe=(t,e,r,o)=>{t=new $5e(t,o),e=new tGe(e,o);let a,n,u,A,p;switch(r){case">":a=hX,n=nGe,u=gX,A=">",p=">=";break;case"<":a=gX,n=iGe,u=hX,A="<",p="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(rGe(t,e,o))return!1;for(let h=0;h{x.semver===eGe&&(x=new dX(">=0.0.0")),I=I||x,D=D||x,a(x.semver,I.semver,o)?I=x:u(x.semver,D.semver,o)&&(D=x)}),I.operator===A||I.operator===p||(!D.operator||D.operator===A)&&n(t,D.semver))return!1;if(D.operator===p&&u(t,D.semver))return!1}return!0};mX.exports=sGe});var EX=_((eQt,yX)=>{var oGe=tS(),aGe=(t,e,r)=>oGe(t,e,">",r);yX.exports=aGe});var wX=_((tQt,CX)=>{var lGe=tS(),cGe=(t,e,r)=>lGe(t,e,"<",r);CX.exports=cGe});var vX=_((rQt,BX)=>{var IX=Ul(),uGe=(t,e,r)=>(t=new IX(t,r),e=new IX(e,r),t.intersects(e,r));BX.exports=uGe});var PX=_((nQt,DX)=>{var AGe=UI(),fGe=Ol();DX.exports=(t,e,r)=>{let o=[],a=null,n=null,u=t.sort((E,I)=>fGe(E,I,r));for(let E of u)AGe(E,e,r)?(n=E,a||(a=E)):(n&&o.push([a,n]),n=null,a=null);a&&o.push([a,null]);let A=[];for(let[E,I]of o)E===I?A.push(E):!I&&E===u[0]?A.push("*"):I?E===u[0]?A.push(`<=${I}`):A.push(`${E} - ${I}`):A.push(`>=${E}`);let p=A.join(" || "),h=typeof e.raw=="string"?e.raw:String(e);return p.length{var SX=Ul(),GN=MI(),{ANY:jN}=GN,_I=UI(),YN=Ol(),pGe=(t,e,r={})=>{if(t===e)return!0;t=new SX(t,r),e=new SX(e,r);let o=!1;e:for(let a of t.set){for(let n of e.set){let u=gGe(a,n,r);if(o=o||u!==null,u)continue e}if(o)return!1}return!0},hGe=[new GN(">=0.0.0-0")],bX=[new GN(">=0.0.0")],gGe=(t,e,r)=>{if(t===e)return!0;if(t.length===1&&t[0].semver===jN){if(e.length===1&&e[0].semver===jN)return!0;r.includePrerelease?t=hGe:t=bX}if(e.length===1&&e[0].semver===jN){if(r.includePrerelease)return!0;e=bX}let o=new Set,a,n;for(let x of t)x.operator===">"||x.operator===">="?a=xX(a,x,r):x.operator==="<"||x.operator==="<="?n=kX(n,x,r):o.add(x.semver);if(o.size>1)return null;let u;if(a&&n){if(u=YN(a.semver,n.semver,r),u>0)return null;if(u===0&&(a.operator!==">="||n.operator!=="<="))return null}for(let x of o){if(a&&!_I(x,String(a),r)||n&&!_I(x,String(n),r))return null;for(let C of e)if(!_I(x,String(C),r))return!1;return!0}let A,p,h,E,I=n&&!r.includePrerelease&&n.semver.prerelease.length?n.semver:!1,D=a&&!r.includePrerelease&&a.semver.prerelease.length?a.semver:!1;I&&I.prerelease.length===1&&n.operator==="<"&&I.prerelease[0]===0&&(I=!1);for(let x of e){if(E=E||x.operator===">"||x.operator===">=",h=h||x.operator==="<"||x.operator==="<=",a){if(D&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===D.major&&x.semver.minor===D.minor&&x.semver.patch===D.patch&&(D=!1),x.operator===">"||x.operator===">="){if(A=xX(a,x,r),A===x&&A!==a)return!1}else if(a.operator===">="&&!_I(a.semver,String(x),r))return!1}if(n){if(I&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===I.major&&x.semver.minor===I.minor&&x.semver.patch===I.patch&&(I=!1),x.operator==="<"||x.operator==="<="){if(p=kX(n,x,r),p===x&&p!==n)return!1}else if(n.operator==="<="&&!_I(n.semver,String(x),r))return!1}if(!x.operator&&(n||a)&&u!==0)return!1}return!(a&&h&&!n&&u!==0||n&&E&&!a&&u!==0||D||I)},xX=(t,e,r)=>{if(!t)return e;let o=YN(t.semver,e.semver,r);return o>0?t:o<0||e.operator===">"&&t.operator===">="?e:t},kX=(t,e,r)=>{if(!t)return e;let o=YN(t.semver,e.semver,r);return o<0?t:o>0||e.operator==="<"&&t.operator==="<="?e:t};QX.exports=pGe});var ni=_((sQt,NX)=>{var WN=xm(),RX=FI(),dGe=Eo(),TX=bN(),mGe=cg(),yGe=eJ(),EGe=rJ(),CGe=sJ(),wGe=lJ(),IGe=uJ(),BGe=fJ(),vGe=hJ(),DGe=dJ(),PGe=Ol(),SGe=CJ(),bGe=IJ(),xGe=KP(),kGe=PJ(),QGe=bJ(),FGe=TI(),RGe=VP(),TGe=kN(),NGe=QN(),LGe=zP(),MGe=JP(),OGe=FN(),UGe=MJ(),_Ge=MI(),HGe=Ul(),qGe=UI(),jGe=iX(),GGe=oX(),YGe=lX(),WGe=AX(),KGe=pX(),VGe=tS(),zGe=EX(),JGe=wX(),XGe=vX(),ZGe=PX(),$Ge=FX();NX.exports={parse:mGe,valid:yGe,clean:EGe,inc:CGe,diff:wGe,major:IGe,minor:BGe,patch:vGe,prerelease:DGe,compare:PGe,rcompare:SGe,compareLoose:bGe,compareBuild:xGe,sort:kGe,rsort:QGe,gt:FGe,lt:RGe,eq:TGe,neq:NGe,gte:LGe,lte:MGe,cmp:OGe,coerce:UGe,Comparator:_Ge,Range:HGe,satisfies:qGe,toComparators:jGe,maxSatisfying:GGe,minSatisfying:YGe,minVersion:WGe,validRange:KGe,outside:VGe,gtr:zGe,ltr:JGe,intersects:XGe,simplifyRange:ZGe,subset:$Ge,SemVer:dGe,re:WN.re,src:WN.src,tokens:WN.t,SEMVER_SPEC_VERSION:RX.SEMVER_SPEC_VERSION,RELEASE_TYPES:RX.RELEASE_TYPES,compareIdentifiers:TX.compareIdentifiers,rcompareIdentifiers:TX.rcompareIdentifiers}});var MX=_((oQt,LX)=>{"use strict";function e9e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function pg(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,pg)}e9e(pg,Error);pg.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I0){for(I=1,D=1;I{switch(Fe[1]){case"|":return be|Fe[3];case"&":return be&Fe[3];case"^":return be^Fe[3]}},$)},D="!",x=Ne("!",!1),C=function($){return!$},T="(",L=Ne("(",!1),U=")",z=Ne(")",!1),te=function($){return $},le=/^[^ \t\n\r()!|&\^]/,ce=Te([" "," ",` +`,"\r","(",")","!","|","&","^"],!0,!1),ue=function($){return e.queryPattern.test($)},Ce=function($){return e.checkFn($)},he=Se("whitespace"),De=/^[ \t\n\r]/,Ee=Te([" "," ",` +`,"\r"],!1,!1),g=0,me=0,we=[{line:1,column:1}],fe=0,ie=[],Z=0,xe;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function Re(){return t.substring(me,g)}function gt(){return He(me,g)}function q($,se){throw se=se!==void 0?se:He(me,g),S([Se($)],t.substring(me,g),se)}function nt($,se){throw se=se!==void 0?se:He(me,g),w($,se)}function Ne($,se){return{type:"literal",text:$,ignoreCase:se}}function Te($,se,be){return{type:"class",parts:$,inverted:se,ignoreCase:be}}function ke(){return{type:"any"}}function Ve(){return{type:"end"}}function Se($){return{type:"other",description:$}}function tt($){var se=we[$],be;if(se)return se;for(be=$-1;!we[be];)be--;for(se=we[be],se={line:se.line,column:se.column};be<$;)t.charCodeAt(be)===10?(se.line++,se.column=1):se.column++,be++;return we[$]=se,se}function He($,se){var be=tt($),Fe=tt(se);return{start:{offset:$,line:be.line,column:be.column},end:{offset:se,line:Fe.line,column:Fe.column}}}function b($){gfe&&(fe=g,ie=[]),ie.push($))}function w($,se){return new pg($,null,null,se)}function S($,se,be){return new pg(pg.buildMessage($,se),$,se,be)}function y(){var $,se,be,Fe,lt,Et,qt,nr;if($=g,se=R(),se!==r){for(be=[],Fe=g,lt=X(),lt!==r?(t.charCodeAt(g)===124?(Et=n,g++):(Et=r,Z===0&&b(u)),Et===r&&(t.charCodeAt(g)===38?(Et=A,g++):(Et=r,Z===0&&b(p)),Et===r&&(t.charCodeAt(g)===94?(Et=h,g++):(Et=r,Z===0&&b(E)))),Et!==r?(qt=X(),qt!==r?(nr=R(),nr!==r?(lt=[lt,Et,qt,nr],Fe=lt):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);Fe!==r;)be.push(Fe),Fe=g,lt=X(),lt!==r?(t.charCodeAt(g)===124?(Et=n,g++):(Et=r,Z===0&&b(u)),Et===r&&(t.charCodeAt(g)===38?(Et=A,g++):(Et=r,Z===0&&b(p)),Et===r&&(t.charCodeAt(g)===94?(Et=h,g++):(Et=r,Z===0&&b(E)))),Et!==r?(qt=X(),qt!==r?(nr=R(),nr!==r?(lt=[lt,Et,qt,nr],Fe=lt):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);be!==r?(me=$,se=I(se,be),$=se):(g=$,$=r)}else g=$,$=r;return $}function R(){var $,se,be,Fe,lt,Et;return $=g,t.charCodeAt(g)===33?(se=D,g++):(se=r,Z===0&&b(x)),se!==r?(be=R(),be!==r?(me=$,se=C(be),$=se):(g=$,$=r)):(g=$,$=r),$===r&&($=g,t.charCodeAt(g)===40?(se=T,g++):(se=r,Z===0&&b(L)),se!==r?(be=X(),be!==r?(Fe=y(),Fe!==r?(lt=X(),lt!==r?(t.charCodeAt(g)===41?(Et=U,g++):(Et=r,Z===0&&b(z)),Et!==r?(me=$,se=te(Fe),$=se):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r),$===r&&($=J())),$}function J(){var $,se,be,Fe,lt;if($=g,se=X(),se!==r){if(be=g,Fe=[],le.test(t.charAt(g))?(lt=t.charAt(g),g++):(lt=r,Z===0&&b(ce)),lt!==r)for(;lt!==r;)Fe.push(lt),le.test(t.charAt(g))?(lt=t.charAt(g),g++):(lt=r,Z===0&&b(ce));else Fe=r;Fe!==r?be=t.substring(be,g):be=Fe,be!==r?(me=g,Fe=ue(be),Fe?Fe=void 0:Fe=r,Fe!==r?(me=$,se=Ce(be),$=se):(g=$,$=r)):(g=$,$=r)}else g=$,$=r;return $}function X(){var $,se;for(Z++,$=[],De.test(t.charAt(g))?(se=t.charAt(g),g++):(se=r,Z===0&&b(Ee));se!==r;)$.push(se),De.test(t.charAt(g))?(se=t.charAt(g),g++):(se=r,Z===0&&b(Ee));return Z--,$===r&&(se=r,Z===0&&b(he)),$}if(xe=a(),xe!==r&&g===t.length)return xe;throw xe!==r&&g{var{parse:r9e}=MX();rS.makeParser=(t=/[a-z]+/)=>(e,r)=>r9e(e,{queryPattern:t,checkFn:r});rS.parse=rS.makeParser()});var _X=_((lQt,UX)=>{"use strict";UX.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var KN=_((cQt,qX)=>{var HI=_X(),HX={};for(let t of Object.keys(HI))HX[HI[t]]=t;var fr={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};qX.exports=fr;for(let t of Object.keys(fr)){if(!("channels"in fr[t]))throw new Error("missing channels property: "+t);if(!("labels"in fr[t]))throw new Error("missing channel labels property: "+t);if(fr[t].labels.length!==fr[t].channels)throw new Error("channel and label counts mismatch: "+t);let{channels:e,labels:r}=fr[t];delete fr[t].channels,delete fr[t].labels,Object.defineProperty(fr[t],"channels",{value:e}),Object.defineProperty(fr[t],"labels",{value:r})}fr.rgb.hsl=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(e,r,o),n=Math.max(e,r,o),u=n-a,A,p;n===a?A=0:e===n?A=(r-o)/u:r===n?A=2+(o-e)/u:o===n&&(A=4+(e-r)/u),A=Math.min(A*60,360),A<0&&(A+=360);let h=(a+n)/2;return n===a?p=0:h<=.5?p=u/(n+a):p=u/(2-n-a),[A,p*100,h*100]};fr.rgb.hsv=function(t){let e,r,o,a,n,u=t[0]/255,A=t[1]/255,p=t[2]/255,h=Math.max(u,A,p),E=h-Math.min(u,A,p),I=function(D){return(h-D)/6/E+1/2};return E===0?(a=0,n=0):(n=E/h,e=I(u),r=I(A),o=I(p),u===h?a=o-r:A===h?a=1/3+e-o:p===h&&(a=2/3+r-e),a<0?a+=1:a>1&&(a-=1)),[a*360,n*100,h*100]};fr.rgb.hwb=function(t){let e=t[0],r=t[1],o=t[2],a=fr.rgb.hsl(t)[0],n=1/255*Math.min(e,Math.min(r,o));return o=1-1/255*Math.max(e,Math.max(r,o)),[a,n*100,o*100]};fr.rgb.cmyk=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(1-e,1-r,1-o),n=(1-e-a)/(1-a)||0,u=(1-r-a)/(1-a)||0,A=(1-o-a)/(1-a)||0;return[n*100,u*100,A*100,a*100]};function n9e(t,e){return(t[0]-e[0])**2+(t[1]-e[1])**2+(t[2]-e[2])**2}fr.rgb.keyword=function(t){let e=HX[t];if(e)return e;let r=1/0,o;for(let a of Object.keys(HI)){let n=HI[a],u=n9e(t,n);u.04045?((e+.055)/1.055)**2.4:e/12.92,r=r>.04045?((r+.055)/1.055)**2.4:r/12.92,o=o>.04045?((o+.055)/1.055)**2.4:o/12.92;let a=e*.4124+r*.3576+o*.1805,n=e*.2126+r*.7152+o*.0722,u=e*.0193+r*.1192+o*.9505;return[a*100,n*100,u*100]};fr.rgb.lab=function(t){let e=fr.rgb.xyz(t),r=e[0],o=e[1],a=e[2];r/=95.047,o/=100,a/=108.883,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116,a=a>.008856?a**(1/3):7.787*a+16/116;let n=116*o-16,u=500*(r-o),A=200*(o-a);return[n,u,A]};fr.hsl.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a,n,u;if(r===0)return u=o*255,[u,u,u];o<.5?a=o*(1+r):a=o+r-o*r;let A=2*o-a,p=[0,0,0];for(let h=0;h<3;h++)n=e+1/3*-(h-1),n<0&&n++,n>1&&n--,6*n<1?u=A+(a-A)*6*n:2*n<1?u=a:3*n<2?u=A+(a-A)*(2/3-n)*6:u=A,p[h]=u*255;return p};fr.hsl.hsv=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=r,n=Math.max(o,.01);o*=2,r*=o<=1?o:2-o,a*=n<=1?n:2-n;let u=(o+r)/2,A=o===0?2*a/(n+a):2*r/(o+r);return[e,A*100,u*100]};fr.hsv.rgb=function(t){let e=t[0]/60,r=t[1]/100,o=t[2]/100,a=Math.floor(e)%6,n=e-Math.floor(e),u=255*o*(1-r),A=255*o*(1-r*n),p=255*o*(1-r*(1-n));switch(o*=255,a){case 0:return[o,p,u];case 1:return[A,o,u];case 2:return[u,o,p];case 3:return[u,A,o];case 4:return[p,u,o];case 5:return[o,u,A]}};fr.hsv.hsl=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=Math.max(o,.01),n,u;u=(2-r)*o;let A=(2-r)*a;return n=r*a,n/=A<=1?A:2-A,n=n||0,u/=2,[e,n*100,u*100]};fr.hwb.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a=r+o,n;a>1&&(r/=a,o/=a);let u=Math.floor(6*e),A=1-o;n=6*e-u,u&1&&(n=1-n);let p=r+n*(A-r),h,E,I;switch(u){default:case 6:case 0:h=A,E=p,I=r;break;case 1:h=p,E=A,I=r;break;case 2:h=r,E=A,I=p;break;case 3:h=r,E=p,I=A;break;case 4:h=p,E=r,I=A;break;case 5:h=A,E=r,I=p;break}return[h*255,E*255,I*255]};fr.cmyk.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a=t[3]/100,n=1-Math.min(1,e*(1-a)+a),u=1-Math.min(1,r*(1-a)+a),A=1-Math.min(1,o*(1-a)+a);return[n*255,u*255,A*255]};fr.xyz.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a,n,u;return a=e*3.2406+r*-1.5372+o*-.4986,n=e*-.9689+r*1.8758+o*.0415,u=e*.0557+r*-.204+o*1.057,a=a>.0031308?1.055*a**(1/2.4)-.055:a*12.92,n=n>.0031308?1.055*n**(1/2.4)-.055:n*12.92,u=u>.0031308?1.055*u**(1/2.4)-.055:u*12.92,a=Math.min(Math.max(0,a),1),n=Math.min(Math.max(0,n),1),u=Math.min(Math.max(0,u),1),[a*255,n*255,u*255]};fr.xyz.lab=function(t){let e=t[0],r=t[1],o=t[2];e/=95.047,r/=100,o/=108.883,e=e>.008856?e**(1/3):7.787*e+16/116,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116;let a=116*r-16,n=500*(e-r),u=200*(r-o);return[a,n,u]};fr.lab.xyz=function(t){let e=t[0],r=t[1],o=t[2],a,n,u;n=(e+16)/116,a=r/500+n,u=n-o/200;let A=n**3,p=a**3,h=u**3;return n=A>.008856?A:(n-16/116)/7.787,a=p>.008856?p:(a-16/116)/7.787,u=h>.008856?h:(u-16/116)/7.787,a*=95.047,n*=100,u*=108.883,[a,n,u]};fr.lab.lch=function(t){let e=t[0],r=t[1],o=t[2],a;a=Math.atan2(o,r)*360/2/Math.PI,a<0&&(a+=360);let u=Math.sqrt(r*r+o*o);return[e,u,a]};fr.lch.lab=function(t){let e=t[0],r=t[1],a=t[2]/360*2*Math.PI,n=r*Math.cos(a),u=r*Math.sin(a);return[e,n,u]};fr.rgb.ansi16=function(t,e=null){let[r,o,a]=t,n=e===null?fr.rgb.hsv(t)[2]:e;if(n=Math.round(n/50),n===0)return 30;let u=30+(Math.round(a/255)<<2|Math.round(o/255)<<1|Math.round(r/255));return n===2&&(u+=60),u};fr.hsv.ansi16=function(t){return fr.rgb.ansi16(fr.hsv.rgb(t),t[2])};fr.rgb.ansi256=function(t){let e=t[0],r=t[1],o=t[2];return e===r&&r===o?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(r/255*5)+Math.round(o/255*5)};fr.ansi16.rgb=function(t){let e=t%10;if(e===0||e===7)return t>50&&(e+=3.5),e=e/10.5*255,[e,e,e];let r=(~~(t>50)+1)*.5,o=(e&1)*r*255,a=(e>>1&1)*r*255,n=(e>>2&1)*r*255;return[o,a,n]};fr.ansi256.rgb=function(t){if(t>=232){let n=(t-232)*10+8;return[n,n,n]}t-=16;let e,r=Math.floor(t/36)/5*255,o=Math.floor((e=t%36)/6)/5*255,a=e%6/5*255;return[r,o,a]};fr.rgb.hex=function(t){let r=(((Math.round(t[0])&255)<<16)+((Math.round(t[1])&255)<<8)+(Math.round(t[2])&255)).toString(16).toUpperCase();return"000000".substring(r.length)+r};fr.hex.rgb=function(t){let e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];let r=e[0];e[0].length===3&&(r=r.split("").map(A=>A+A).join(""));let o=parseInt(r,16),a=o>>16&255,n=o>>8&255,u=o&255;return[a,n,u]};fr.rgb.hcg=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.max(Math.max(e,r),o),n=Math.min(Math.min(e,r),o),u=a-n,A,p;return u<1?A=n/(1-u):A=0,u<=0?p=0:a===e?p=(r-o)/u%6:a===r?p=2+(o-e)/u:p=4+(e-r)/u,p/=6,p%=1,[p*360,u*100,A*100]};fr.hsl.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=r<.5?2*e*r:2*e*(1-r),a=0;return o<1&&(a=(r-.5*o)/(1-o)),[t[0],o*100,a*100]};fr.hsv.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=e*r,a=0;return o<1&&(a=(r-o)/(1-o)),[t[0],o*100,a*100]};fr.hcg.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100;if(r===0)return[o*255,o*255,o*255];let a=[0,0,0],n=e%1*6,u=n%1,A=1-u,p=0;switch(Math.floor(n)){case 0:a[0]=1,a[1]=u,a[2]=0;break;case 1:a[0]=A,a[1]=1,a[2]=0;break;case 2:a[0]=0,a[1]=1,a[2]=u;break;case 3:a[0]=0,a[1]=A,a[2]=1;break;case 4:a[0]=u,a[1]=0,a[2]=1;break;default:a[0]=1,a[1]=0,a[2]=A}return p=(1-r)*o,[(r*a[0]+p)*255,(r*a[1]+p)*255,(r*a[2]+p)*255]};fr.hcg.hsv=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e),a=0;return o>0&&(a=e/o),[t[0],a*100,o*100]};fr.hcg.hsl=function(t){let e=t[1]/100,o=t[2]/100*(1-e)+.5*e,a=0;return o>0&&o<.5?a=e/(2*o):o>=.5&&o<1&&(a=e/(2*(1-o))),[t[0],a*100,o*100]};fr.hcg.hwb=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e);return[t[0],(o-e)*100,(1-o)*100]};fr.hwb.hcg=function(t){let e=t[1]/100,o=1-t[2]/100,a=o-e,n=0;return a<1&&(n=(o-a)/(1-a)),[t[0],a*100,n*100]};fr.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]};fr.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]};fr.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]};fr.gray.hsl=function(t){return[0,0,t[0]]};fr.gray.hsv=fr.gray.hsl;fr.gray.hwb=function(t){return[0,100,t[0]]};fr.gray.cmyk=function(t){return[0,0,0,t[0]]};fr.gray.lab=function(t){return[t[0],0,0]};fr.gray.hex=function(t){let e=Math.round(t[0]/100*255)&255,o=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(o.length)+o};fr.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}});var GX=_((uQt,jX)=>{var nS=KN();function i9e(){let t={},e=Object.keys(nS);for(let r=e.length,o=0;o{var VN=KN(),l9e=GX(),Rm={},c9e=Object.keys(VN);function u9e(t){let e=function(...r){let o=r[0];return o==null?o:(o.length>1&&(r=o),t(r))};return"conversion"in t&&(e.conversion=t.conversion),e}function A9e(t){let e=function(...r){let o=r[0];if(o==null)return o;o.length>1&&(r=o);let a=t(r);if(typeof a=="object")for(let n=a.length,u=0;u{Rm[t]={},Object.defineProperty(Rm[t],"channels",{value:VN[t].channels}),Object.defineProperty(Rm[t],"labels",{value:VN[t].labels});let e=l9e(t);Object.keys(e).forEach(o=>{let a=e[o];Rm[t][o]=A9e(a),Rm[t][o].raw=u9e(a)})});YX.exports=Rm});var qI=_((fQt,XX)=>{"use strict";var KX=(t,e)=>(...r)=>`\x1B[${t(...r)+e}m`,VX=(t,e)=>(...r)=>{let o=t(...r);return`\x1B[${38+e};5;${o}m`},zX=(t,e)=>(...r)=>{let o=t(...r);return`\x1B[${38+e};2;${o[0]};${o[1]};${o[2]}m`},iS=t=>t,JX=(t,e,r)=>[t,e,r],Tm=(t,e,r)=>{Object.defineProperty(t,e,{get:()=>{let o=r();return Object.defineProperty(t,e,{value:o,enumerable:!0,configurable:!0}),o},enumerable:!0,configurable:!0})},zN,Nm=(t,e,r,o)=>{zN===void 0&&(zN=WX());let a=o?10:0,n={};for(let[u,A]of Object.entries(zN)){let p=u==="ansi16"?"ansi":u;u===e?n[p]=t(r,a):typeof A=="object"&&(n[p]=t(A[e],a))}return n};function f9e(){let t=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.gray=e.color.blackBright,e.bgColor.bgGray=e.bgColor.bgBlackBright,e.color.grey=e.color.blackBright,e.bgColor.bgGrey=e.bgColor.bgBlackBright;for(let[r,o]of Object.entries(e)){for(let[a,n]of Object.entries(o))e[a]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},o[a]=e[a],t.set(n[0],n[1]);Object.defineProperty(e,r,{value:o,enumerable:!1})}return Object.defineProperty(e,"codes",{value:t,enumerable:!1}),e.color.close="\x1B[39m",e.bgColor.close="\x1B[49m",Tm(e.color,"ansi",()=>Nm(KX,"ansi16",iS,!1)),Tm(e.color,"ansi256",()=>Nm(VX,"ansi256",iS,!1)),Tm(e.color,"ansi16m",()=>Nm(zX,"rgb",JX,!1)),Tm(e.bgColor,"ansi",()=>Nm(KX,"ansi16",iS,!0)),Tm(e.bgColor,"ansi256",()=>Nm(VX,"ansi256",iS,!0)),Tm(e.bgColor,"ansi16m",()=>Nm(zX,"rgb",JX,!0)),e}Object.defineProperty(XX,"exports",{enumerable:!0,get:f9e})});var $X=_((pQt,ZX)=>{"use strict";ZX.exports=(t,e=process.argv)=>{let r=t.startsWith("-")?"":t.length===1?"-":"--",o=e.indexOf(r+t),a=e.indexOf("--");return o!==-1&&(a===-1||o{"use strict";var p9e=ve("os"),eZ=ve("tty"),_l=$X(),{env:cs}=process,Zp;_l("no-color")||_l("no-colors")||_l("color=false")||_l("color=never")?Zp=0:(_l("color")||_l("colors")||_l("color=true")||_l("color=always"))&&(Zp=1);"FORCE_COLOR"in cs&&(cs.FORCE_COLOR==="true"?Zp=1:cs.FORCE_COLOR==="false"?Zp=0:Zp=cs.FORCE_COLOR.length===0?1:Math.min(parseInt(cs.FORCE_COLOR,10),3));function JN(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function XN(t,e){if(Zp===0)return 0;if(_l("color=16m")||_l("color=full")||_l("color=truecolor"))return 3;if(_l("color=256"))return 2;if(t&&!e&&Zp===void 0)return 0;let r=Zp||0;if(cs.TERM==="dumb")return r;if(process.platform==="win32"){let o=p9e.release().split(".");return Number(o[0])>=10&&Number(o[2])>=10586?Number(o[2])>=14931?3:2:1}if("CI"in cs)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(o=>o in cs)||cs.CI_NAME==="codeship"?1:r;if("TEAMCITY_VERSION"in cs)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(cs.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in cs)return 1;if(cs.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in cs){let o=parseInt((cs.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(cs.TERM_PROGRAM){case"iTerm.app":return o>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(cs.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(cs.TERM)||"COLORTERM"in cs?1:r}function h9e(t){let e=XN(t,t&&t.isTTY);return JN(e)}tZ.exports={supportsColor:h9e,stdout:JN(XN(!0,eZ.isatty(1))),stderr:JN(XN(!0,eZ.isatty(2)))}});var nZ=_((gQt,rZ)=>{"use strict";var g9e=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u="";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},d9e=(t,e,r,o)=>{let a=0,n="";do{let u=t[o-1]==="\r";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\r +`:` +`)+r,a=o+1,o=t.indexOf(` +`,a)}while(o!==-1);return n+=t.substr(a),n};rZ.exports={stringReplaceAll:g9e,stringEncaseCRLFWithFirstIndex:d9e}});var lZ=_((dQt,aZ)=>{"use strict";var m9e=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,iZ=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,y9e=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,E9e=/\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi,C9e=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function oZ(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5||t[0]==="x"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):C9e.get(t)||t}function w9e(t,e){let r=[],o=e.trim().split(/\s*,\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(y9e))r.push(a[2].replace(E9e,(A,p,h)=>p?oZ(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function I9e(t){iZ.lastIndex=0;let e=[],r;for(;(r=iZ.exec(t))!==null;){let o=r[1];if(r[2]){let a=w9e(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function sZ(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}aZ.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(m9e,(n,u,A,p,h,E)=>{if(u)a.push(oZ(u));else if(p){let I=a.join("");a=[],o.push(r.length===0?I:sZ(t,r)(I)),r.push({inverse:A,styles:I9e(p)})}else if(h){if(r.length===0)throw new Error("Found extraneous } in Chalk template literal");o.push(sZ(t,r)(a.join(""))),a=[],r.pop()}else a.push(E)}),o.push(a.join("")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?"":"s"} (\`}\`)`;throw new Error(n)}return o.join("")}});var iL=_((mQt,fZ)=>{"use strict";var jI=qI(),{stdout:eL,stderr:tL}=ZN(),{stringReplaceAll:B9e,stringEncaseCRLFWithFirstIndex:v9e}=nZ(),cZ=["ansi","ansi","ansi256","ansi16m"],Lm=Object.create(null),D9e=(t,e={})=>{if(e.level>3||e.level<0)throw new Error("The `level` option should be an integer from 0 to 3");let r=eL?eL.level:0;t.level=e.level===void 0?r:e.level},rL=class{constructor(e){return uZ(e)}},uZ=t=>{let e={};return D9e(e,t),e.template=(...r)=>b9e(e.template,...r),Object.setPrototypeOf(e,sS.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=rL,e.template};function sS(t){return uZ(t)}for(let[t,e]of Object.entries(jI))Lm[t]={get(){let r=oS(this,nL(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};Lm.visible={get(){let t=oS(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:t}),t}};var AZ=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let t of AZ)Lm[t]={get(){let{level:e}=this;return function(...r){let o=nL(jI.color[cZ[e]][t](...r),jI.color.close,this._styler);return oS(this,o,this._isEmpty)}}};for(let t of AZ){let e="bg"+t[0].toUpperCase()+t.slice(1);Lm[e]={get(){let{level:r}=this;return function(...o){let a=nL(jI.bgColor[cZ[r]][t](...o),jI.bgColor.close,this._styler);return oS(this,a,this._isEmpty)}}}}var P9e=Object.defineProperties(()=>{},{...Lm,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),nL=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},oS=(t,e,r)=>{let o=(...a)=>S9e(o,a.length===1?""+a[0]:a.join(" "));return o.__proto__=P9e,o._generator=t,o._styler=e,o._isEmpty=r,o},S9e=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?"":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf("\x1B")!==-1)for(;r!==void 0;)e=B9e(e,r.close,r.open),r=r.parent;let n=e.indexOf(` +`);return n!==-1&&(e=v9e(e,a,o,n)),o+e+a},$N,b9e=(t,...e)=>{let[r]=e;if(!Array.isArray(r))return e.join(" ");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n{"use strict";Hl.isInteger=t=>typeof t=="number"?Number.isInteger(t):typeof t=="string"&&t.trim()!==""?Number.isInteger(Number(t)):!1;Hl.find=(t,e)=>t.nodes.find(r=>r.type===e);Hl.exceedsLimit=(t,e,r=1,o)=>o===!1||!Hl.isInteger(t)||!Hl.isInteger(e)?!1:(Number(e)-Number(t))/Number(r)>=o;Hl.escapeNode=(t,e=0,r)=>{let o=t.nodes[e];o&&(r&&o.type===r||o.type==="open"||o.type==="close")&&o.escaped!==!0&&(o.value="\\"+o.value,o.escaped=!0)};Hl.encloseBrace=t=>t.type!=="brace"||t.commas>>0+t.ranges>>0?!1:(t.invalid=!0,!0);Hl.isInvalidBrace=t=>t.type!=="brace"?!1:t.invalid===!0||t.dollar?!0:!(t.commas>>0+t.ranges>>0)||t.open!==!0||t.close!==!0?(t.invalid=!0,!0):!1;Hl.isOpenOrClose=t=>t.type==="open"||t.type==="close"?!0:t.open===!0||t.close===!0;Hl.reduce=t=>t.reduce((e,r)=>(r.type==="text"&&e.push(r.value),r.type==="range"&&(r.type="text"),e),[]);Hl.flatten=(...t)=>{let e=[],r=o=>{for(let a=0;a{"use strict";var pZ=aS();hZ.exports=(t,e={})=>{let r=(o,a={})=>{let n=e.escapeInvalid&&pZ.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A="";if(o.value)return(n||u)&&pZ.isOpenOrClose(o)?"\\"+o.value:o.value;if(o.value)return o.value;if(o.nodes)for(let p of o.nodes)A+=r(p);return A};return r(t)}});var dZ=_((CQt,gZ)=>{"use strict";gZ.exports=function(t){return typeof t=="number"?t-t===0:typeof t=="string"&&t.trim()!==""?Number.isFinite?Number.isFinite(+t):isFinite(+t):!1}});var DZ=_((wQt,vZ)=>{"use strict";var mZ=dZ(),hg=(t,e,r)=>{if(mZ(t)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(e===void 0||t===e)return String(t);if(mZ(e)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let o={relaxZeros:!0,...r};typeof o.strictZeros=="boolean"&&(o.relaxZeros=o.strictZeros===!1);let a=String(o.relaxZeros),n=String(o.shorthand),u=String(o.capture),A=String(o.wrap),p=t+":"+e+"="+a+n+u+A;if(hg.cache.hasOwnProperty(p))return hg.cache[p].result;let h=Math.min(t,e),E=Math.max(t,e);if(Math.abs(h-E)===1){let T=t+"|"+e;return o.capture?`(${T})`:o.wrap===!1?T:`(?:${T})`}let I=BZ(t)||BZ(e),D={min:t,max:e,a:h,b:E},x=[],C=[];if(I&&(D.isPadded=I,D.maxLen=String(D.max).length),h<0){let T=E<0?Math.abs(E):1;C=yZ(T,Math.abs(h),D,o),h=D.a=0}return E>=0&&(x=yZ(h,E,D,o)),D.negatives=C,D.positives=x,D.result=x9e(C,x,o),o.capture===!0?D.result=`(${D.result})`:o.wrap!==!1&&x.length+C.length>1&&(D.result=`(?:${D.result})`),hg.cache[p]=D,D.result};function x9e(t,e,r){let o=sL(t,e,"-",!1,r)||[],a=sL(e,t,"",!1,r)||[],n=sL(t,e,"-?",!0,r)||[];return o.concat(n).concat(a).join("|")}function k9e(t,e){let r=1,o=1,a=CZ(t,r),n=new Set([e]);for(;t<=a&&a<=e;)n.add(a),r+=1,a=CZ(t,r);for(a=wZ(e+1,o)-1;t1&&A.count.pop(),A.count.push(E.count[0]),A.string=A.pattern+IZ(A.count),u=h+1;continue}r.isPadded&&(I=N9e(h,r,o)),E.string=I+E.pattern+IZ(E.count),n.push(E),u=h+1,A=E}return n}function sL(t,e,r,o,a){let n=[];for(let u of t){let{string:A}=u;!o&&!EZ(e,"string",A)&&n.push(r+A),o&&EZ(e,"string",A)&&n.push(r+A)}return n}function F9e(t,e){let r=[];for(let o=0;oe?1:e>t?-1:0}function EZ(t,e,r){return t.some(o=>o[e]===r)}function CZ(t,e){return Number(String(t).slice(0,-e)+"9".repeat(e))}function wZ(t,e){return t-t%Math.pow(10,e)}function IZ(t){let[e=0,r=""]=t;return r||e>1?`{${e+(r?","+r:"")}}`:""}function T9e(t,e,r){return`[${t}${e-t===1?"":"-"}${e}]`}function BZ(t){return/^-?(0+)\d/.test(t)}function N9e(t,e,r){if(!e.isPadded)return t;let o=Math.abs(e.maxLen-String(t).length),a=r.relaxZeros!==!1;switch(o){case 0:return"";case 1:return a?"0?":"0";case 2:return a?"0{0,2}":"00";default:return a?`0{0,${o}}`:`0{${o}}`}}hg.cache={};hg.clearCache=()=>hg.cache={};vZ.exports=hg});var lL=_((IQt,RZ)=>{"use strict";var L9e=ve("util"),bZ=DZ(),PZ=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),M9e=t=>e=>t===!0?Number(e):String(e),oL=t=>typeof t=="number"||typeof t=="string"&&t!=="",YI=t=>Number.isInteger(+t),aL=t=>{let e=`${t}`,r=-1;if(e[0]==="-"&&(e=e.slice(1)),e==="0")return!1;for(;e[++r]==="0";);return r>0},O9e=(t,e,r)=>typeof t=="string"||typeof e=="string"?!0:r.stringify===!0,U9e=(t,e,r)=>{if(e>0){let o=t[0]==="-"?"-":"";o&&(t=t.slice(1)),t=o+t.padStart(o?e-1:e,"0")}return r===!1?String(t):t},SZ=(t,e)=>{let r=t[0]==="-"?"-":"";for(r&&(t=t.slice(1),e--);t.length{t.negatives.sort((u,A)=>uA?1:0),t.positives.sort((u,A)=>uA?1:0);let r=e.capture?"":"?:",o="",a="",n;return t.positives.length&&(o=t.positives.join("|")),t.negatives.length&&(a=`-(${r}${t.negatives.join("|")})`),o&&a?n=`${o}|${a}`:n=o||a,e.wrap?`(${r}${n})`:n},xZ=(t,e,r,o)=>{if(r)return bZ(t,e,{wrap:!1,...o});let a=String.fromCharCode(t);if(t===e)return a;let n=String.fromCharCode(e);return`[${a}-${n}]`},kZ=(t,e,r)=>{if(Array.isArray(t)){let o=r.wrap===!0,a=r.capture?"":"?:";return o?`(${a}${t.join("|")})`:t.join("|")}return bZ(t,e,r)},QZ=(...t)=>new RangeError("Invalid range arguments: "+L9e.inspect(...t)),FZ=(t,e,r)=>{if(r.strictRanges===!0)throw QZ([t,e]);return[]},H9e=(t,e)=>{if(e.strictRanges===!0)throw new TypeError(`Expected step "${t}" to be a number`);return[]},q9e=(t,e,r=1,o={})=>{let a=Number(t),n=Number(e);if(!Number.isInteger(a)||!Number.isInteger(n)){if(o.strictRanges===!0)throw QZ([t,e]);return[]}a===0&&(a=0),n===0&&(n=0);let u=a>n,A=String(t),p=String(e),h=String(r);r=Math.max(Math.abs(r),1);let E=aL(A)||aL(p)||aL(h),I=E?Math.max(A.length,p.length,h.length):0,D=E===!1&&O9e(t,e,o)===!1,x=o.transform||M9e(D);if(o.toRegex&&r===1)return xZ(SZ(t,I),SZ(e,I),!0,o);let C={negatives:[],positives:[]},T=z=>C[z<0?"negatives":"positives"].push(Math.abs(z)),L=[],U=0;for(;u?a>=n:a<=n;)o.toRegex===!0&&r>1?T(a):L.push(U9e(x(a,U),I,D)),a=u?a-r:a+r,U++;return o.toRegex===!0?r>1?_9e(C,o):kZ(L,null,{wrap:!1,...o}):L},j9e=(t,e,r=1,o={})=>{if(!YI(t)&&t.length>1||!YI(e)&&e.length>1)return FZ(t,e,o);let a=o.transform||(D=>String.fromCharCode(D)),n=`${t}`.charCodeAt(0),u=`${e}`.charCodeAt(0),A=n>u,p=Math.min(n,u),h=Math.max(n,u);if(o.toRegex&&r===1)return xZ(p,h,!1,o);let E=[],I=0;for(;A?n>=u:n<=u;)E.push(a(n,I)),n=A?n-r:n+r,I++;return o.toRegex===!0?kZ(E,null,{wrap:!1,options:o}):E},cS=(t,e,r,o={})=>{if(e==null&&oL(t))return[t];if(!oL(t)||!oL(e))return FZ(t,e,o);if(typeof r=="function")return cS(t,e,1,{transform:r});if(PZ(r))return cS(t,e,0,r);let a={...o};return a.capture===!0&&(a.wrap=!0),r=r||a.step||1,YI(r)?YI(t)&&YI(e)?q9e(t,e,r,a):j9e(t,e,Math.max(Math.abs(r),1),a):r!=null&&!PZ(r)?H9e(r,a):cS(t,e,1,r)};RZ.exports=cS});var LZ=_((BQt,NZ)=>{"use strict";var G9e=lL(),TZ=aS(),Y9e=(t,e={})=>{let r=(o,a={})=>{let n=TZ.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A=n===!0||u===!0,p=e.escapeInvalid===!0?"\\":"",h="";if(o.isOpen===!0||o.isClose===!0)return p+o.value;if(o.type==="open")return A?p+o.value:"(";if(o.type==="close")return A?p+o.value:")";if(o.type==="comma")return o.prev.type==="comma"?"":A?o.value:"|";if(o.value)return o.value;if(o.nodes&&o.ranges>0){let E=TZ.reduce(o.nodes),I=G9e(...E,{...e,wrap:!1,toRegex:!0});if(I.length!==0)return E.length>1&&I.length>1?`(${I})`:I}if(o.nodes)for(let E of o.nodes)h+=r(E,o);return h};return r(t)};NZ.exports=Y9e});var UZ=_((vQt,OZ)=>{"use strict";var W9e=lL(),MZ=lS(),Mm=aS(),gg=(t="",e="",r=!1)=>{let o=[];if(t=[].concat(t),e=[].concat(e),!e.length)return t;if(!t.length)return r?Mm.flatten(e).map(a=>`{${a}}`):e;for(let a of t)if(Array.isArray(a))for(let n of a)o.push(gg(n,e,r));else for(let n of e)r===!0&&typeof n=="string"&&(n=`{${n}}`),o.push(Array.isArray(n)?gg(a,n,r):a+n);return Mm.flatten(o)},K9e=(t,e={})=>{let r=e.rangeLimit===void 0?1e3:e.rangeLimit,o=(a,n={})=>{a.queue=[];let u=n,A=n.queue;for(;u.type!=="brace"&&u.type!=="root"&&u.parent;)u=u.parent,A=u.queue;if(a.invalid||a.dollar){A.push(gg(A.pop(),MZ(a,e)));return}if(a.type==="brace"&&a.invalid!==!0&&a.nodes.length===2){A.push(gg(A.pop(),["{}"]));return}if(a.nodes&&a.ranges>0){let I=Mm.reduce(a.nodes);if(Mm.exceedsLimit(...I,e.step,r))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let D=W9e(...I,e);D.length===0&&(D=MZ(a,e)),A.push(gg(A.pop(),D)),a.nodes=[];return}let p=Mm.encloseBrace(a),h=a.queue,E=a;for(;E.type!=="brace"&&E.type!=="root"&&E.parent;)E=E.parent,h=E.queue;for(let I=0;I{"use strict";_Z.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` +`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var WZ=_((PQt,YZ)=>{"use strict";var V9e=lS(),{MAX_LENGTH:qZ,CHAR_BACKSLASH:cL,CHAR_BACKTICK:z9e,CHAR_COMMA:J9e,CHAR_DOT:X9e,CHAR_LEFT_PARENTHESES:Z9e,CHAR_RIGHT_PARENTHESES:$9e,CHAR_LEFT_CURLY_BRACE:e7e,CHAR_RIGHT_CURLY_BRACE:t7e,CHAR_LEFT_SQUARE_BRACKET:jZ,CHAR_RIGHT_SQUARE_BRACKET:GZ,CHAR_DOUBLE_QUOTE:r7e,CHAR_SINGLE_QUOTE:n7e,CHAR_NO_BREAK_SPACE:i7e,CHAR_ZERO_WIDTH_NOBREAK_SPACE:s7e}=HZ(),o7e=(t,e={})=>{if(typeof t!="string")throw new TypeError("Expected a string");let r=e||{},o=typeof r.maxLength=="number"?Math.min(qZ,r.maxLength):qZ;if(t.length>o)throw new SyntaxError(`Input length (${t.length}), exceeds max characters (${o})`);let a={type:"root",input:t,nodes:[]},n=[a],u=a,A=a,p=0,h=t.length,E=0,I=0,D,x={},C=()=>t[E++],T=L=>{if(L.type==="text"&&A.type==="dot"&&(A.type="text"),A&&A.type==="text"&&L.type==="text"){A.value+=L.value;return}return u.nodes.push(L),L.parent=u,L.prev=A,A=L,L};for(T({type:"bos"});E0){if(u.ranges>0){u.ranges=0;let L=u.nodes.shift();u.nodes=[L,{type:"text",value:V9e(u)}]}T({type:"comma",value:D}),u.commas++;continue}if(D===X9e&&I>0&&u.commas===0){let L=u.nodes;if(I===0||L.length===0){T({type:"text",value:D});continue}if(A.type==="dot"){if(u.range=[],A.value+=D,A.type="range",u.nodes.length!==3&&u.nodes.length!==5){u.invalid=!0,u.ranges=0,A.type="text";continue}u.ranges++,u.args=[];continue}if(A.type==="range"){L.pop();let U=L[L.length-1];U.value+=A.value+D,A=U,u.ranges--;continue}T({type:"dot",value:D});continue}T({type:"text",value:D})}do if(u=n.pop(),u.type!=="root"){u.nodes.forEach(z=>{z.nodes||(z.type==="open"&&(z.isOpen=!0),z.type==="close"&&(z.isClose=!0),z.nodes||(z.type="text"),z.invalid=!0)});let L=n[n.length-1],U=L.nodes.indexOf(u);L.nodes.splice(U,1,...u.nodes)}while(n.length>0);return T({type:"eos"}),a};YZ.exports=o7e});var zZ=_((SQt,VZ)=>{"use strict";var KZ=lS(),a7e=LZ(),l7e=UZ(),c7e=WZ(),al=(t,e={})=>{let r=[];if(Array.isArray(t))for(let o of t){let a=al.create(o,e);Array.isArray(a)?r.push(...a):r.push(a)}else r=[].concat(al.create(t,e));return e&&e.expand===!0&&e.nodupes===!0&&(r=[...new Set(r)]),r};al.parse=(t,e={})=>c7e(t,e);al.stringify=(t,e={})=>KZ(typeof t=="string"?al.parse(t,e):t,e);al.compile=(t,e={})=>(typeof t=="string"&&(t=al.parse(t,e)),a7e(t,e));al.expand=(t,e={})=>{typeof t=="string"&&(t=al.parse(t,e));let r=l7e(t,e);return e.noempty===!0&&(r=r.filter(Boolean)),e.nodupes===!0&&(r=[...new Set(r)]),r};al.create=(t,e={})=>t===""||t.length<3?[t]:e.expand!==!0?al.compile(t,e):al.expand(t,e);VZ.exports=al});var WI=_((bQt,e$)=>{"use strict";var u7e=ve("path"),Ju="\\\\/",JZ=`[^${Ju}]`,Bf="\\.",A7e="\\+",f7e="\\?",uS="\\/",p7e="(?=.)",XZ="[^/]",uL=`(?:${uS}|$)`,ZZ=`(?:^|${uS})`,AL=`${Bf}{1,2}${uL}`,h7e=`(?!${Bf})`,g7e=`(?!${ZZ}${AL})`,d7e=`(?!${Bf}{0,1}${uL})`,m7e=`(?!${AL})`,y7e=`[^.${uS}]`,E7e=`${XZ}*?`,$Z={DOT_LITERAL:Bf,PLUS_LITERAL:A7e,QMARK_LITERAL:f7e,SLASH_LITERAL:uS,ONE_CHAR:p7e,QMARK:XZ,END_ANCHOR:uL,DOTS_SLASH:AL,NO_DOT:h7e,NO_DOTS:g7e,NO_DOT_SLASH:d7e,NO_DOTS_SLASH:m7e,QMARK_NO_DOT:y7e,STAR:E7e,START_ANCHOR:ZZ},C7e={...$Z,SLASH_LITERAL:`[${Ju}]`,QMARK:JZ,STAR:`${JZ}*?`,DOTS_SLASH:`${Bf}{1,2}(?:[${Ju}]|$)`,NO_DOT:`(?!${Bf})`,NO_DOTS:`(?!(?:^|[${Ju}])${Bf}{1,2}(?:[${Ju}]|$))`,NO_DOT_SLASH:`(?!${Bf}{0,1}(?:[${Ju}]|$))`,NO_DOTS_SLASH:`(?!${Bf}{1,2}(?:[${Ju}]|$))`,QMARK_NO_DOT:`[^.${Ju}]`,START_ANCHOR:`(?:^|[${Ju}])`,END_ANCHOR:`(?:[${Ju}]|$)`},w7e={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};e$.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:w7e,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:u7e.sep,extglobChars(t){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${t.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(t){return t===!0?C7e:$Z}}});var KI=_(xa=>{"use strict";var I7e=ve("path"),B7e=process.platform==="win32",{REGEX_BACKSLASH:v7e,REGEX_REMOVE_BACKSLASH:D7e,REGEX_SPECIAL_CHARS:P7e,REGEX_SPECIAL_CHARS_GLOBAL:S7e}=WI();xa.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);xa.hasRegexChars=t=>P7e.test(t);xa.isRegexChar=t=>t.length===1&&xa.hasRegexChars(t);xa.escapeRegex=t=>t.replace(S7e,"\\$1");xa.toPosixSlashes=t=>t.replace(v7e,"/");xa.removeBackslashes=t=>t.replace(D7e,e=>e==="\\"?"":e);xa.supportsLookbehinds=()=>{let t=process.version.slice(1).split(".").map(Number);return t.length===3&&t[0]>=9||t[0]===8&&t[1]>=10};xa.isWindows=t=>t&&typeof t.windows=="boolean"?t.windows:B7e===!0||I7e.sep==="\\";xa.escapeLast=(t,e,r)=>{let o=t.lastIndexOf(e,r);return o===-1?t:t[o-1]==="\\"?xa.escapeLast(t,e,o-1):`${t.slice(0,o)}\\${t.slice(o)}`};xa.removePrefix=(t,e={})=>{let r=t;return r.startsWith("./")&&(r=r.slice(2),e.prefix="./"),r};xa.wrapOutput=(t,e={},r={})=>{let o=r.contains?"":"^",a=r.contains?"":"$",n=`${o}(?:${t})${a}`;return e.negated===!0&&(n=`(?:^(?!${n}).*$)`),n}});var l$=_((kQt,a$)=>{"use strict";var t$=KI(),{CHAR_ASTERISK:fL,CHAR_AT:b7e,CHAR_BACKWARD_SLASH:VI,CHAR_COMMA:x7e,CHAR_DOT:pL,CHAR_EXCLAMATION_MARK:hL,CHAR_FORWARD_SLASH:o$,CHAR_LEFT_CURLY_BRACE:gL,CHAR_LEFT_PARENTHESES:dL,CHAR_LEFT_SQUARE_BRACKET:k7e,CHAR_PLUS:Q7e,CHAR_QUESTION_MARK:r$,CHAR_RIGHT_CURLY_BRACE:F7e,CHAR_RIGHT_PARENTHESES:n$,CHAR_RIGHT_SQUARE_BRACKET:R7e}=WI(),i$=t=>t===o$||t===VI,s$=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},T7e=(t,e)=>{let r=e||{},o=t.length-1,a=r.parts===!0||r.scanToEnd===!0,n=[],u=[],A=[],p=t,h=-1,E=0,I=0,D=!1,x=!1,C=!1,T=!1,L=!1,U=!1,z=!1,te=!1,le=!1,ce=!1,ue=0,Ce,he,De={value:"",depth:0,isGlob:!1},Ee=()=>h>=o,g=()=>p.charCodeAt(h+1),me=()=>(Ce=he,p.charCodeAt(++h));for(;h0&&(fe=p.slice(0,E),p=p.slice(E),I-=E),we&&C===!0&&I>0?(we=p.slice(0,I),ie=p.slice(I)):C===!0?(we="",ie=p):we=p,we&&we!==""&&we!=="/"&&we!==p&&i$(we.charCodeAt(we.length-1))&&(we=we.slice(0,-1)),r.unescape===!0&&(ie&&(ie=t$.removeBackslashes(ie)),we&&z===!0&&(we=t$.removeBackslashes(we)));let Z={prefix:fe,input:t,start:E,base:we,glob:ie,isBrace:D,isBracket:x,isGlob:C,isExtglob:T,isGlobstar:L,negated:te,negatedExtglob:le};if(r.tokens===!0&&(Z.maxDepth=0,i$(he)||u.push(De),Z.tokens=u),r.parts===!0||r.tokens===!0){let xe;for(let Re=0;Re{"use strict";var AS=WI(),ll=KI(),{MAX_LENGTH:fS,POSIX_REGEX_SOURCE:N7e,REGEX_NON_SPECIAL_CHARS:L7e,REGEX_SPECIAL_CHARS_BACKREF:M7e,REPLACEMENTS:c$}=AS,O7e=(t,e)=>{if(typeof e.expandRange=="function")return e.expandRange(...t,e);t.sort();let r=`[${t.join("-")}]`;try{new RegExp(r)}catch{return t.map(a=>ll.escapeRegex(a)).join("..")}return r},Om=(t,e)=>`Missing ${t}: "${e}" - use "\\\\${e}" to match literal characters`,mL=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");t=c$[t]||t;let r={...e},o=typeof r.maxLength=="number"?Math.min(fS,r.maxLength):fS,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);let n={type:"bos",value:"",output:r.prepend||""},u=[n],A=r.capture?"":"?:",p=ll.isWindows(e),h=AS.globChars(p),E=AS.extglobChars(h),{DOT_LITERAL:I,PLUS_LITERAL:D,SLASH_LITERAL:x,ONE_CHAR:C,DOTS_SLASH:T,NO_DOT:L,NO_DOT_SLASH:U,NO_DOTS_SLASH:z,QMARK:te,QMARK_NO_DOT:le,STAR:ce,START_ANCHOR:ue}=h,Ce=b=>`(${A}(?:(?!${ue}${b.dot?T:I}).)*?)`,he=r.dot?"":L,De=r.dot?te:le,Ee=r.bash===!0?Ce(r):ce;r.capture&&(Ee=`(${Ee})`),typeof r.noext=="boolean"&&(r.noextglob=r.noext);let g={input:t,index:-1,start:0,dot:r.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:u};t=ll.removePrefix(t,g),a=t.length;let me=[],we=[],fe=[],ie=n,Z,xe=()=>g.index===a-1,Re=g.peek=(b=1)=>t[g.index+b],gt=g.advance=()=>t[++g.index]||"",q=()=>t.slice(g.index+1),nt=(b="",w=0)=>{g.consumed+=b,g.index+=w},Ne=b=>{g.output+=b.output!=null?b.output:b.value,nt(b.value)},Te=()=>{let b=1;for(;Re()==="!"&&(Re(2)!=="("||Re(3)==="?");)gt(),g.start++,b++;return b%2===0?!1:(g.negated=!0,g.start++,!0)},ke=b=>{g[b]++,fe.push(b)},Ve=b=>{g[b]--,fe.pop()},Se=b=>{if(ie.type==="globstar"){let w=g.braces>0&&(b.type==="comma"||b.type==="brace"),S=b.extglob===!0||me.length&&(b.type==="pipe"||b.type==="paren");b.type!=="slash"&&b.type!=="paren"&&!w&&!S&&(g.output=g.output.slice(0,-ie.output.length),ie.type="star",ie.value="*",ie.output=Ee,g.output+=ie.output)}if(me.length&&b.type!=="paren"&&(me[me.length-1].inner+=b.value),(b.value||b.output)&&Ne(b),ie&&ie.type==="text"&&b.type==="text"){ie.value+=b.value,ie.output=(ie.output||"")+b.value;return}b.prev=ie,u.push(b),ie=b},tt=(b,w)=>{let S={...E[w],conditions:1,inner:""};S.prev=ie,S.parens=g.parens,S.output=g.output;let y=(r.capture?"(":"")+S.open;ke("parens"),Se({type:b,value:w,output:g.output?"":C}),Se({type:"paren",extglob:!0,value:gt(),output:y}),me.push(S)},He=b=>{let w=b.close+(r.capture?")":""),S;if(b.type==="negate"){let y=Ee;if(b.inner&&b.inner.length>1&&b.inner.includes("/")&&(y=Ce(r)),(y!==Ee||xe()||/^\)+$/.test(q()))&&(w=b.close=`)$))${y}`),b.inner.includes("*")&&(S=q())&&/^\.[^\\/.]+$/.test(S)){let R=mL(S,{...e,fastpaths:!1}).output;w=b.close=`)${R})${y})`}b.prev.type==="bos"&&(g.negatedExtglob=!0)}Se({type:"paren",extglob:!0,value:Z,output:w}),Ve("parens")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(t)){let b=!1,w=t.replace(M7e,(S,y,R,J,X,$)=>J==="\\"?(b=!0,S):J==="?"?y?y+J+(X?te.repeat(X.length):""):$===0?De+(X?te.repeat(X.length):""):te.repeat(R.length):J==="."?I.repeat(R.length):J==="*"?y?y+J+(X?Ee:""):Ee:y?S:`\\${S}`);return b===!0&&(r.unescape===!0?w=w.replace(/\\/g,""):w=w.replace(/\\+/g,S=>S.length%2===0?"\\\\":S?"\\":"")),w===t&&r.contains===!0?(g.output=t,g):(g.output=ll.wrapOutput(w,g,e),g)}for(;!xe();){if(Z=gt(),Z==="\0")continue;if(Z==="\\"){let S=Re();if(S==="/"&&r.bash!==!0||S==="."||S===";")continue;if(!S){Z+="\\",Se({type:"text",value:Z});continue}let y=/^\\+/.exec(q()),R=0;if(y&&y[0].length>2&&(R=y[0].length,g.index+=R,R%2!==0&&(Z+="\\")),r.unescape===!0?Z=gt():Z+=gt(),g.brackets===0){Se({type:"text",value:Z});continue}}if(g.brackets>0&&(Z!=="]"||ie.value==="["||ie.value==="[^")){if(r.posix!==!1&&Z===":"){let S=ie.value.slice(1);if(S.includes("[")&&(ie.posix=!0,S.includes(":"))){let y=ie.value.lastIndexOf("["),R=ie.value.slice(0,y),J=ie.value.slice(y+2),X=N7e[J];if(X){ie.value=R+X,g.backtrack=!0,gt(),!n.output&&u.indexOf(ie)===1&&(n.output=C);continue}}}(Z==="["&&Re()!==":"||Z==="-"&&Re()==="]")&&(Z=`\\${Z}`),Z==="]"&&(ie.value==="["||ie.value==="[^")&&(Z=`\\${Z}`),r.posix===!0&&Z==="!"&&ie.value==="["&&(Z="^"),ie.value+=Z,Ne({value:Z});continue}if(g.quotes===1&&Z!=='"'){Z=ll.escapeRegex(Z),ie.value+=Z,Ne({value:Z});continue}if(Z==='"'){g.quotes=g.quotes===1?0:1,r.keepQuotes===!0&&Se({type:"text",value:Z});continue}if(Z==="("){ke("parens"),Se({type:"paren",value:Z});continue}if(Z===")"){if(g.parens===0&&r.strictBrackets===!0)throw new SyntaxError(Om("opening","("));let S=me[me.length-1];if(S&&g.parens===S.parens+1){He(me.pop());continue}Se({type:"paren",value:Z,output:g.parens?")":"\\)"}),Ve("parens");continue}if(Z==="["){if(r.nobracket===!0||!q().includes("]")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(Om("closing","]"));Z=`\\${Z}`}else ke("brackets");Se({type:"bracket",value:Z});continue}if(Z==="]"){if(r.nobracket===!0||ie&&ie.type==="bracket"&&ie.value.length===1){Se({type:"text",value:Z,output:`\\${Z}`});continue}if(g.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(Om("opening","["));Se({type:"text",value:Z,output:`\\${Z}`});continue}Ve("brackets");let S=ie.value.slice(1);if(ie.posix!==!0&&S[0]==="^"&&!S.includes("/")&&(Z=`/${Z}`),ie.value+=Z,Ne({value:Z}),r.literalBrackets===!1||ll.hasRegexChars(S))continue;let y=ll.escapeRegex(ie.value);if(g.output=g.output.slice(0,-ie.value.length),r.literalBrackets===!0){g.output+=y,ie.value=y;continue}ie.value=`(${A}${y}|${ie.value})`,g.output+=ie.value;continue}if(Z==="{"&&r.nobrace!==!0){ke("braces");let S={type:"brace",value:Z,output:"(",outputIndex:g.output.length,tokensIndex:g.tokens.length};we.push(S),Se(S);continue}if(Z==="}"){let S=we[we.length-1];if(r.nobrace===!0||!S){Se({type:"text",value:Z,output:Z});continue}let y=")";if(S.dots===!0){let R=u.slice(),J=[];for(let X=R.length-1;X>=0&&(u.pop(),R[X].type!=="brace");X--)R[X].type!=="dots"&&J.unshift(R[X].value);y=O7e(J,r),g.backtrack=!0}if(S.comma!==!0&&S.dots!==!0){let R=g.output.slice(0,S.outputIndex),J=g.tokens.slice(S.tokensIndex);S.value=S.output="\\{",Z=y="\\}",g.output=R;for(let X of J)g.output+=X.output||X.value}Se({type:"brace",value:Z,output:y}),Ve("braces"),we.pop();continue}if(Z==="|"){me.length>0&&me[me.length-1].conditions++,Se({type:"text",value:Z});continue}if(Z===","){let S=Z,y=we[we.length-1];y&&fe[fe.length-1]==="braces"&&(y.comma=!0,S="|"),Se({type:"comma",value:Z,output:S});continue}if(Z==="/"){if(ie.type==="dot"&&g.index===g.start+1){g.start=g.index+1,g.consumed="",g.output="",u.pop(),ie=n;continue}Se({type:"slash",value:Z,output:x});continue}if(Z==="."){if(g.braces>0&&ie.type==="dot"){ie.value==="."&&(ie.output=I);let S=we[we.length-1];ie.type="dots",ie.output+=Z,ie.value+=Z,S.dots=!0;continue}if(g.braces+g.parens===0&&ie.type!=="bos"&&ie.type!=="slash"){Se({type:"text",value:Z,output:I});continue}Se({type:"dot",value:Z,output:I});continue}if(Z==="?"){if(!(ie&&ie.value==="(")&&r.noextglob!==!0&&Re()==="("&&Re(2)!=="?"){tt("qmark",Z);continue}if(ie&&ie.type==="paren"){let y=Re(),R=Z;if(y==="<"&&!ll.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(ie.value==="("&&!/[!=<:]/.test(y)||y==="<"&&!/<([!=]|\w+>)/.test(q()))&&(R=`\\${Z}`),Se({type:"text",value:Z,output:R});continue}if(r.dot!==!0&&(ie.type==="slash"||ie.type==="bos")){Se({type:"qmark",value:Z,output:le});continue}Se({type:"qmark",value:Z,output:te});continue}if(Z==="!"){if(r.noextglob!==!0&&Re()==="("&&(Re(2)!=="?"||!/[!=<:]/.test(Re(3)))){tt("negate",Z);continue}if(r.nonegate!==!0&&g.index===0){Te();continue}}if(Z==="+"){if(r.noextglob!==!0&&Re()==="("&&Re(2)!=="?"){tt("plus",Z);continue}if(ie&&ie.value==="("||r.regex===!1){Se({type:"plus",value:Z,output:D});continue}if(ie&&(ie.type==="bracket"||ie.type==="paren"||ie.type==="brace")||g.parens>0){Se({type:"plus",value:Z});continue}Se({type:"plus",value:D});continue}if(Z==="@"){if(r.noextglob!==!0&&Re()==="("&&Re(2)!=="?"){Se({type:"at",extglob:!0,value:Z,output:""});continue}Se({type:"text",value:Z});continue}if(Z!=="*"){(Z==="$"||Z==="^")&&(Z=`\\${Z}`);let S=L7e.exec(q());S&&(Z+=S[0],g.index+=S[0].length),Se({type:"text",value:Z});continue}if(ie&&(ie.type==="globstar"||ie.star===!0)){ie.type="star",ie.star=!0,ie.value+=Z,ie.output=Ee,g.backtrack=!0,g.globstar=!0,nt(Z);continue}let b=q();if(r.noextglob!==!0&&/^\([^?]/.test(b)){tt("star",Z);continue}if(ie.type==="star"){if(r.noglobstar===!0){nt(Z);continue}let S=ie.prev,y=S.prev,R=S.type==="slash"||S.type==="bos",J=y&&(y.type==="star"||y.type==="globstar");if(r.bash===!0&&(!R||b[0]&&b[0]!=="/")){Se({type:"star",value:Z,output:""});continue}let X=g.braces>0&&(S.type==="comma"||S.type==="brace"),$=me.length&&(S.type==="pipe"||S.type==="paren");if(!R&&S.type!=="paren"&&!X&&!$){Se({type:"star",value:Z,output:""});continue}for(;b.slice(0,3)==="/**";){let se=t[g.index+4];if(se&&se!=="/")break;b=b.slice(3),nt("/**",3)}if(S.type==="bos"&&xe()){ie.type="globstar",ie.value+=Z,ie.output=Ce(r),g.output=ie.output,g.globstar=!0,nt(Z);continue}if(S.type==="slash"&&S.prev.type!=="bos"&&!J&&xe()){g.output=g.output.slice(0,-(S.output+ie.output).length),S.output=`(?:${S.output}`,ie.type="globstar",ie.output=Ce(r)+(r.strictSlashes?")":"|$)"),ie.value+=Z,g.globstar=!0,g.output+=S.output+ie.output,nt(Z);continue}if(S.type==="slash"&&S.prev.type!=="bos"&&b[0]==="/"){let se=b[1]!==void 0?"|$":"";g.output=g.output.slice(0,-(S.output+ie.output).length),S.output=`(?:${S.output}`,ie.type="globstar",ie.output=`${Ce(r)}${x}|${x}${se})`,ie.value+=Z,g.output+=S.output+ie.output,g.globstar=!0,nt(Z+gt()),Se({type:"slash",value:"/",output:""});continue}if(S.type==="bos"&&b[0]==="/"){ie.type="globstar",ie.value+=Z,ie.output=`(?:^|${x}|${Ce(r)}${x})`,g.output=ie.output,g.globstar=!0,nt(Z+gt()),Se({type:"slash",value:"/",output:""});continue}g.output=g.output.slice(0,-ie.output.length),ie.type="globstar",ie.output=Ce(r),ie.value+=Z,g.output+=ie.output,g.globstar=!0,nt(Z);continue}let w={type:"star",value:Z,output:Ee};if(r.bash===!0){w.output=".*?",(ie.type==="bos"||ie.type==="slash")&&(w.output=he+w.output),Se(w);continue}if(ie&&(ie.type==="bracket"||ie.type==="paren")&&r.regex===!0){w.output=Z,Se(w);continue}(g.index===g.start||ie.type==="slash"||ie.type==="dot")&&(ie.type==="dot"?(g.output+=U,ie.output+=U):r.dot===!0?(g.output+=z,ie.output+=z):(g.output+=he,ie.output+=he),Re()!=="*"&&(g.output+=C,ie.output+=C)),Se(w)}for(;g.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(Om("closing","]"));g.output=ll.escapeLast(g.output,"["),Ve("brackets")}for(;g.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(Om("closing",")"));g.output=ll.escapeLast(g.output,"("),Ve("parens")}for(;g.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(Om("closing","}"));g.output=ll.escapeLast(g.output,"{"),Ve("braces")}if(r.strictSlashes!==!0&&(ie.type==="star"||ie.type==="bracket")&&Se({type:"maybe_slash",value:"",output:`${x}?`}),g.backtrack===!0){g.output="";for(let b of g.tokens)g.output+=b.output!=null?b.output:b.value,b.suffix&&(g.output+=b.suffix)}return g};mL.fastpaths=(t,e)=>{let r={...e},o=typeof r.maxLength=="number"?Math.min(fS,r.maxLength):fS,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);t=c$[t]||t;let n=ll.isWindows(e),{DOT_LITERAL:u,SLASH_LITERAL:A,ONE_CHAR:p,DOTS_SLASH:h,NO_DOT:E,NO_DOTS:I,NO_DOTS_SLASH:D,STAR:x,START_ANCHOR:C}=AS.globChars(n),T=r.dot?I:E,L=r.dot?D:E,U=r.capture?"":"?:",z={negated:!1,prefix:""},te=r.bash===!0?".*?":x;r.capture&&(te=`(${te})`);let le=he=>he.noglobstar===!0?te:`(${U}(?:(?!${C}${he.dot?h:u}).)*?)`,ce=he=>{switch(he){case"*":return`${T}${p}${te}`;case".*":return`${u}${p}${te}`;case"*.*":return`${T}${te}${u}${p}${te}`;case"*/*":return`${T}${te}${A}${p}${L}${te}`;case"**":return T+le(r);case"**/*":return`(?:${T}${le(r)}${A})?${L}${p}${te}`;case"**/*.*":return`(?:${T}${le(r)}${A})?${L}${te}${u}${p}${te}`;case"**/.*":return`(?:${T}${le(r)}${A})?${u}${p}${te}`;default:{let De=/^(.*?)\.(\w+)$/.exec(he);if(!De)return;let Ee=ce(De[1]);return Ee?Ee+u+De[2]:void 0}}},ue=ll.removePrefix(t,z),Ce=ce(ue);return Ce&&r.strictSlashes!==!0&&(Ce+=`${A}?`),Ce};u$.exports=mL});var p$=_((FQt,f$)=>{"use strict";var U7e=ve("path"),_7e=l$(),yL=A$(),EL=KI(),H7e=WI(),q7e=t=>t&&typeof t=="object"&&!Array.isArray(t),Oi=(t,e,r=!1)=>{if(Array.isArray(t)){let E=t.map(D=>Oi(D,e,r));return D=>{for(let x of E){let C=x(D);if(C)return C}return!1}}let o=q7e(t)&&t.tokens&&t.input;if(t===""||typeof t!="string"&&!o)throw new TypeError("Expected pattern to be a non-empty string");let a=e||{},n=EL.isWindows(e),u=o?Oi.compileRe(t,e):Oi.makeRe(t,e,!1,!0),A=u.state;delete u.state;let p=()=>!1;if(a.ignore){let E={...e,ignore:null,onMatch:null,onResult:null};p=Oi(a.ignore,E,r)}let h=(E,I=!1)=>{let{isMatch:D,match:x,output:C}=Oi.test(E,u,e,{glob:t,posix:n}),T={glob:t,state:A,regex:u,posix:n,input:E,output:C,match:x,isMatch:D};return typeof a.onResult=="function"&&a.onResult(T),D===!1?(T.isMatch=!1,I?T:!1):p(E)?(typeof a.onIgnore=="function"&&a.onIgnore(T),T.isMatch=!1,I?T:!1):(typeof a.onMatch=="function"&&a.onMatch(T),I?T:!0)};return r&&(h.state=A),h};Oi.test=(t,e,r,{glob:o,posix:a}={})=>{if(typeof t!="string")throw new TypeError("Expected input to be a string");if(t==="")return{isMatch:!1,output:""};let n=r||{},u=n.format||(a?EL.toPosixSlashes:null),A=t===o,p=A&&u?u(t):t;return A===!1&&(p=u?u(t):t,A=p===o),(A===!1||n.capture===!0)&&(n.matchBase===!0||n.basename===!0?A=Oi.matchBase(t,e,r,a):A=e.exec(p)),{isMatch:!!A,match:A,output:p}};Oi.matchBase=(t,e,r,o=EL.isWindows(r))=>(e instanceof RegExp?e:Oi.makeRe(e,r)).test(U7e.basename(t));Oi.isMatch=(t,e,r)=>Oi(e,r)(t);Oi.parse=(t,e)=>Array.isArray(t)?t.map(r=>Oi.parse(r,e)):yL(t,{...e,fastpaths:!1});Oi.scan=(t,e)=>_7e(t,e);Oi.compileRe=(t,e,r=!1,o=!1)=>{if(r===!0)return t.output;let a=e||{},n=a.contains?"":"^",u=a.contains?"":"$",A=`${n}(?:${t.output})${u}`;t&&t.negated===!0&&(A=`^(?!${A}).*$`);let p=Oi.toRegex(A,e);return o===!0&&(p.state=t),p};Oi.makeRe=(t,e={},r=!1,o=!1)=>{if(!t||typeof t!="string")throw new TypeError("Expected a non-empty string");let a={negated:!1,fastpaths:!0};return e.fastpaths!==!1&&(t[0]==="."||t[0]==="*")&&(a.output=yL.fastpaths(t,e)),a.output||(a=yL(t,e)),Oi.compileRe(a,e,r,o)};Oi.toRegex=(t,e)=>{try{let r=e||{};return new RegExp(t,r.flags||(r.nocase?"i":""))}catch(r){if(e&&e.debug===!0)throw r;return/$^/}};Oi.constants=H7e;f$.exports=Oi});var g$=_((RQt,h$)=>{"use strict";h$.exports=p$()});var Xo=_((TQt,E$)=>{"use strict";var m$=ve("util"),y$=zZ(),Xu=g$(),CL=KI(),d$=t=>t===""||t==="./",wi=(t,e,r)=>{e=[].concat(e),t=[].concat(t);let o=new Set,a=new Set,n=new Set,u=0,A=E=>{n.add(E.output),r&&r.onResult&&r.onResult(E)};for(let E=0;E!o.has(E));if(r&&h.length===0){if(r.failglob===!0)throw new Error(`No matches found for "${e.join(", ")}"`);if(r.nonull===!0||r.nullglob===!0)return r.unescape?e.map(E=>E.replace(/\\/g,"")):e}return h};wi.match=wi;wi.matcher=(t,e)=>Xu(t,e);wi.isMatch=(t,e,r)=>Xu(e,r)(t);wi.any=wi.isMatch;wi.not=(t,e,r={})=>{e=[].concat(e).map(String);let o=new Set,a=[],n=A=>{r.onResult&&r.onResult(A),a.push(A.output)},u=new Set(wi(t,e,{...r,onResult:n}));for(let A of a)u.has(A)||o.add(A);return[...o]};wi.contains=(t,e,r)=>{if(typeof t!="string")throw new TypeError(`Expected a string: "${m$.inspect(t)}"`);if(Array.isArray(e))return e.some(o=>wi.contains(t,o,r));if(typeof e=="string"){if(d$(t)||d$(e))return!1;if(t.includes(e)||t.startsWith("./")&&t.slice(2).includes(e))return!0}return wi.isMatch(t,e,{...r,contains:!0})};wi.matchKeys=(t,e,r)=>{if(!CL.isObject(t))throw new TypeError("Expected the first argument to be an object");let o=wi(Object.keys(t),e,r),a={};for(let n of o)a[n]=t[n];return a};wi.some=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=Xu(String(a),r);if(o.some(u=>n(u)))return!0}return!1};wi.every=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=Xu(String(a),r);if(!o.every(u=>n(u)))return!1}return!0};wi.all=(t,e,r)=>{if(typeof t!="string")throw new TypeError(`Expected a string: "${m$.inspect(t)}"`);return[].concat(e).every(o=>Xu(o,r)(t))};wi.capture=(t,e,r)=>{let o=CL.isWindows(r),n=Xu.makeRe(String(t),{...r,capture:!0}).exec(o?CL.toPosixSlashes(e):e);if(n)return n.slice(1).map(u=>u===void 0?"":u)};wi.makeRe=(...t)=>Xu.makeRe(...t);wi.scan=(...t)=>Xu.scan(...t);wi.parse=(t,e)=>{let r=[];for(let o of[].concat(t||[]))for(let a of y$(String(o),e))r.push(Xu.parse(a,e));return r};wi.braces=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");return e&&e.nobrace===!0||!/\{.*\}/.test(t)?[t]:y$(t,e)};wi.braceExpand=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");return wi.braces(t,{...e,expand:!0})};E$.exports=wi});var w$=_((NQt,C$)=>{"use strict";C$.exports=({onlyFirst:t=!1}={})=>{let e=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(e,t?void 0:"g")}});var pS=_((LQt,I$)=>{"use strict";var j7e=w$();I$.exports=t=>typeof t=="string"?t.replace(j7e(),""):t});var v$=_((MQt,B$)=>{function G7e(){this.__data__=[],this.size=0}B$.exports=G7e});var Um=_((OQt,D$)=>{function Y7e(t,e){return t===e||t!==t&&e!==e}D$.exports=Y7e});var zI=_((UQt,P$)=>{var W7e=Um();function K7e(t,e){for(var r=t.length;r--;)if(W7e(t[r][0],e))return r;return-1}P$.exports=K7e});var b$=_((_Qt,S$)=>{var V7e=zI(),z7e=Array.prototype,J7e=z7e.splice;function X7e(t){var e=this.__data__,r=V7e(e,t);if(r<0)return!1;var o=e.length-1;return r==o?e.pop():J7e.call(e,r,1),--this.size,!0}S$.exports=X7e});var k$=_((HQt,x$)=>{var Z7e=zI();function $7e(t){var e=this.__data__,r=Z7e(e,t);return r<0?void 0:e[r][1]}x$.exports=$7e});var F$=_((qQt,Q$)=>{var eYe=zI();function tYe(t){return eYe(this.__data__,t)>-1}Q$.exports=tYe});var T$=_((jQt,R$)=>{var rYe=zI();function nYe(t,e){var r=this.__data__,o=rYe(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}R$.exports=nYe});var JI=_((GQt,N$)=>{var iYe=v$(),sYe=b$(),oYe=k$(),aYe=F$(),lYe=T$();function _m(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e{var cYe=JI();function uYe(){this.__data__=new cYe,this.size=0}L$.exports=uYe});var U$=_((WQt,O$)=>{function AYe(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}O$.exports=AYe});var H$=_((KQt,_$)=>{function fYe(t){return this.__data__.get(t)}_$.exports=fYe});var j$=_((VQt,q$)=>{function pYe(t){return this.__data__.has(t)}q$.exports=pYe});var wL=_((zQt,G$)=>{var hYe=typeof global=="object"&&global&&global.Object===Object&&global;G$.exports=hYe});var ql=_((JQt,Y$)=>{var gYe=wL(),dYe=typeof self=="object"&&self&&self.Object===Object&&self,mYe=gYe||dYe||Function("return this")();Y$.exports=mYe});var dg=_((XQt,W$)=>{var yYe=ql(),EYe=yYe.Symbol;W$.exports=EYe});var J$=_((ZQt,z$)=>{var K$=dg(),V$=Object.prototype,CYe=V$.hasOwnProperty,wYe=V$.toString,XI=K$?K$.toStringTag:void 0;function IYe(t){var e=CYe.call(t,XI),r=t[XI];try{t[XI]=void 0;var o=!0}catch{}var a=wYe.call(t);return o&&(e?t[XI]=r:delete t[XI]),a}z$.exports=IYe});var Z$=_(($Qt,X$)=>{var BYe=Object.prototype,vYe=BYe.toString;function DYe(t){return vYe.call(t)}X$.exports=DYe});var mg=_((eFt,tee)=>{var $$=dg(),PYe=J$(),SYe=Z$(),bYe="[object Null]",xYe="[object Undefined]",eee=$$?$$.toStringTag:void 0;function kYe(t){return t==null?t===void 0?xYe:bYe:eee&&eee in Object(t)?PYe(t):SYe(t)}tee.exports=kYe});var cl=_((tFt,ree)=>{function QYe(t){var e=typeof t;return t!=null&&(e=="object"||e=="function")}ree.exports=QYe});var hS=_((rFt,nee)=>{var FYe=mg(),RYe=cl(),TYe="[object AsyncFunction]",NYe="[object Function]",LYe="[object GeneratorFunction]",MYe="[object Proxy]";function OYe(t){if(!RYe(t))return!1;var e=FYe(t);return e==NYe||e==LYe||e==TYe||e==MYe}nee.exports=OYe});var see=_((nFt,iee)=>{var UYe=ql(),_Ye=UYe["__core-js_shared__"];iee.exports=_Ye});var lee=_((iFt,aee)=>{var IL=see(),oee=function(){var t=/[^.]+$/.exec(IL&&IL.keys&&IL.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();function HYe(t){return!!oee&&oee in t}aee.exports=HYe});var BL=_((sFt,cee)=>{var qYe=Function.prototype,jYe=qYe.toString;function GYe(t){if(t!=null){try{return jYe.call(t)}catch{}try{return t+""}catch{}}return""}cee.exports=GYe});var Aee=_((oFt,uee)=>{var YYe=hS(),WYe=lee(),KYe=cl(),VYe=BL(),zYe=/[\\^$.*+?()[\]{}|]/g,JYe=/^\[object .+?Constructor\]$/,XYe=Function.prototype,ZYe=Object.prototype,$Ye=XYe.toString,eWe=ZYe.hasOwnProperty,tWe=RegExp("^"+$Ye.call(eWe).replace(zYe,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function rWe(t){if(!KYe(t)||WYe(t))return!1;var e=YYe(t)?tWe:JYe;return e.test(VYe(t))}uee.exports=rWe});var pee=_((aFt,fee)=>{function nWe(t,e){return t?.[e]}fee.exports=nWe});var $p=_((lFt,hee)=>{var iWe=Aee(),sWe=pee();function oWe(t,e){var r=sWe(t,e);return iWe(r)?r:void 0}hee.exports=oWe});var gS=_((cFt,gee)=>{var aWe=$p(),lWe=ql(),cWe=aWe(lWe,"Map");gee.exports=cWe});var ZI=_((uFt,dee)=>{var uWe=$p(),AWe=uWe(Object,"create");dee.exports=AWe});var Eee=_((AFt,yee)=>{var mee=ZI();function fWe(){this.__data__=mee?mee(null):{},this.size=0}yee.exports=fWe});var wee=_((fFt,Cee)=>{function pWe(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}Cee.exports=pWe});var Bee=_((pFt,Iee)=>{var hWe=ZI(),gWe="__lodash_hash_undefined__",dWe=Object.prototype,mWe=dWe.hasOwnProperty;function yWe(t){var e=this.__data__;if(hWe){var r=e[t];return r===gWe?void 0:r}return mWe.call(e,t)?e[t]:void 0}Iee.exports=yWe});var Dee=_((hFt,vee)=>{var EWe=ZI(),CWe=Object.prototype,wWe=CWe.hasOwnProperty;function IWe(t){var e=this.__data__;return EWe?e[t]!==void 0:wWe.call(e,t)}vee.exports=IWe});var See=_((gFt,Pee)=>{var BWe=ZI(),vWe="__lodash_hash_undefined__";function DWe(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=BWe&&e===void 0?vWe:e,this}Pee.exports=DWe});var xee=_((dFt,bee)=>{var PWe=Eee(),SWe=wee(),bWe=Bee(),xWe=Dee(),kWe=See();function Hm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e{var kee=xee(),QWe=JI(),FWe=gS();function RWe(){this.size=0,this.__data__={hash:new kee,map:new(FWe||QWe),string:new kee}}Qee.exports=RWe});var Tee=_((yFt,Ree)=>{function TWe(t){var e=typeof t;return e=="string"||e=="number"||e=="symbol"||e=="boolean"?t!=="__proto__":t===null}Ree.exports=TWe});var $I=_((EFt,Nee)=>{var NWe=Tee();function LWe(t,e){var r=t.__data__;return NWe(e)?r[typeof e=="string"?"string":"hash"]:r.map}Nee.exports=LWe});var Mee=_((CFt,Lee)=>{var MWe=$I();function OWe(t){var e=MWe(this,t).delete(t);return this.size-=e?1:0,e}Lee.exports=OWe});var Uee=_((wFt,Oee)=>{var UWe=$I();function _We(t){return UWe(this,t).get(t)}Oee.exports=_We});var Hee=_((IFt,_ee)=>{var HWe=$I();function qWe(t){return HWe(this,t).has(t)}_ee.exports=qWe});var jee=_((BFt,qee)=>{var jWe=$I();function GWe(t,e){var r=jWe(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}qee.exports=GWe});var dS=_((vFt,Gee)=>{var YWe=Fee(),WWe=Mee(),KWe=Uee(),VWe=Hee(),zWe=jee();function qm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e{var JWe=JI(),XWe=gS(),ZWe=dS(),$We=200;function eKe(t,e){var r=this.__data__;if(r instanceof JWe){var o=r.__data__;if(!XWe||o.length<$We-1)return o.push([t,e]),this.size=++r.size,this;r=this.__data__=new ZWe(o)}return r.set(t,e),this.size=r.size,this}Yee.exports=eKe});var mS=_((PFt,Kee)=>{var tKe=JI(),rKe=M$(),nKe=U$(),iKe=H$(),sKe=j$(),oKe=Wee();function jm(t){var e=this.__data__=new tKe(t);this.size=e.size}jm.prototype.clear=rKe;jm.prototype.delete=nKe;jm.prototype.get=iKe;jm.prototype.has=sKe;jm.prototype.set=oKe;Kee.exports=jm});var zee=_((SFt,Vee)=>{var aKe="__lodash_hash_undefined__";function lKe(t){return this.__data__.set(t,aKe),this}Vee.exports=lKe});var Xee=_((bFt,Jee)=>{function cKe(t){return this.__data__.has(t)}Jee.exports=cKe});var $ee=_((xFt,Zee)=>{var uKe=dS(),AKe=zee(),fKe=Xee();function yS(t){var e=-1,r=t==null?0:t.length;for(this.__data__=new uKe;++e{function pKe(t,e){for(var r=-1,o=t==null?0:t.length;++r{function hKe(t,e){return t.has(e)}rte.exports=hKe});var vL=_((FFt,ite)=>{var gKe=$ee(),dKe=tte(),mKe=nte(),yKe=1,EKe=2;function CKe(t,e,r,o,a,n){var u=r&yKe,A=t.length,p=e.length;if(A!=p&&!(u&&p>A))return!1;var h=n.get(t),E=n.get(e);if(h&&E)return h==e&&E==t;var I=-1,D=!0,x=r&EKe?new gKe:void 0;for(n.set(t,e),n.set(e,t);++I{var wKe=ql(),IKe=wKe.Uint8Array;ste.exports=IKe});var ate=_((TFt,ote)=>{function BKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o,a){r[++e]=[a,o]}),r}ote.exports=BKe});var cte=_((NFt,lte)=>{function vKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o){r[++e]=o}),r}lte.exports=vKe});var hte=_((LFt,pte)=>{var ute=dg(),Ate=DL(),DKe=Um(),PKe=vL(),SKe=ate(),bKe=cte(),xKe=1,kKe=2,QKe="[object Boolean]",FKe="[object Date]",RKe="[object Error]",TKe="[object Map]",NKe="[object Number]",LKe="[object RegExp]",MKe="[object Set]",OKe="[object String]",UKe="[object Symbol]",_Ke="[object ArrayBuffer]",HKe="[object DataView]",fte=ute?ute.prototype:void 0,PL=fte?fte.valueOf:void 0;function qKe(t,e,r,o,a,n,u){switch(r){case HKe:if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case _Ke:return!(t.byteLength!=e.byteLength||!n(new Ate(t),new Ate(e)));case QKe:case FKe:case NKe:return DKe(+t,+e);case RKe:return t.name==e.name&&t.message==e.message;case LKe:case OKe:return t==e+"";case TKe:var A=SKe;case MKe:var p=o&xKe;if(A||(A=bKe),t.size!=e.size&&!p)return!1;var h=u.get(t);if(h)return h==e;o|=kKe,u.set(t,e);var E=PKe(A(t),A(e),o,a,n,u);return u.delete(t),E;case UKe:if(PL)return PL.call(t)==PL.call(e)}return!1}pte.exports=qKe});var ES=_((MFt,gte)=>{function jKe(t,e){for(var r=-1,o=e.length,a=t.length;++r{var GKe=Array.isArray;dte.exports=GKe});var SL=_((UFt,mte)=>{var YKe=ES(),WKe=jl();function KKe(t,e,r){var o=e(t);return WKe(t)?o:YKe(o,r(t))}mte.exports=KKe});var Ete=_((_Ft,yte)=>{function VKe(t,e){for(var r=-1,o=t==null?0:t.length,a=0,n=[];++r{function zKe(){return[]}Cte.exports=zKe});var CS=_((qFt,Ite)=>{var JKe=Ete(),XKe=bL(),ZKe=Object.prototype,$Ke=ZKe.propertyIsEnumerable,wte=Object.getOwnPropertySymbols,eVe=wte?function(t){return t==null?[]:(t=Object(t),JKe(wte(t),function(e){return $Ke.call(t,e)}))}:XKe;Ite.exports=eVe});var vte=_((jFt,Bte)=>{function tVe(t,e){for(var r=-1,o=Array(t);++r{function rVe(t){return t!=null&&typeof t=="object"}Dte.exports=rVe});var Ste=_((YFt,Pte)=>{var nVe=mg(),iVe=Zu(),sVe="[object Arguments]";function oVe(t){return iVe(t)&&nVe(t)==sVe}Pte.exports=oVe});var e1=_((WFt,kte)=>{var bte=Ste(),aVe=Zu(),xte=Object.prototype,lVe=xte.hasOwnProperty,cVe=xte.propertyIsEnumerable,uVe=bte(function(){return arguments}())?bte:function(t){return aVe(t)&&lVe.call(t,"callee")&&!cVe.call(t,"callee")};kte.exports=uVe});var Fte=_((KFt,Qte)=>{function AVe(){return!1}Qte.exports=AVe});var r1=_((t1,Gm)=>{var fVe=ql(),pVe=Fte(),Nte=typeof t1=="object"&&t1&&!t1.nodeType&&t1,Rte=Nte&&typeof Gm=="object"&&Gm&&!Gm.nodeType&&Gm,hVe=Rte&&Rte.exports===Nte,Tte=hVe?fVe.Buffer:void 0,gVe=Tte?Tte.isBuffer:void 0,dVe=gVe||pVe;Gm.exports=dVe});var n1=_((VFt,Lte)=>{var mVe=9007199254740991,yVe=/^(?:0|[1-9]\d*)$/;function EVe(t,e){var r=typeof t;return e=e??mVe,!!e&&(r=="number"||r!="symbol"&&yVe.test(t))&&t>-1&&t%1==0&&t{var CVe=9007199254740991;function wVe(t){return typeof t=="number"&&t>-1&&t%1==0&&t<=CVe}Mte.exports=wVe});var Ute=_((JFt,Ote)=>{var IVe=mg(),BVe=wS(),vVe=Zu(),DVe="[object Arguments]",PVe="[object Array]",SVe="[object Boolean]",bVe="[object Date]",xVe="[object Error]",kVe="[object Function]",QVe="[object Map]",FVe="[object Number]",RVe="[object Object]",TVe="[object RegExp]",NVe="[object Set]",LVe="[object String]",MVe="[object WeakMap]",OVe="[object ArrayBuffer]",UVe="[object DataView]",_Ve="[object Float32Array]",HVe="[object Float64Array]",qVe="[object Int8Array]",jVe="[object Int16Array]",GVe="[object Int32Array]",YVe="[object Uint8Array]",WVe="[object Uint8ClampedArray]",KVe="[object Uint16Array]",VVe="[object Uint32Array]",di={};di[_Ve]=di[HVe]=di[qVe]=di[jVe]=di[GVe]=di[YVe]=di[WVe]=di[KVe]=di[VVe]=!0;di[DVe]=di[PVe]=di[OVe]=di[SVe]=di[UVe]=di[bVe]=di[xVe]=di[kVe]=di[QVe]=di[FVe]=di[RVe]=di[TVe]=di[NVe]=di[LVe]=di[MVe]=!1;function zVe(t){return vVe(t)&&BVe(t.length)&&!!di[IVe(t)]}Ote.exports=zVe});var IS=_((XFt,_te)=>{function JVe(t){return function(e){return t(e)}}_te.exports=JVe});var BS=_((i1,Ym)=>{var XVe=wL(),Hte=typeof i1=="object"&&i1&&!i1.nodeType&&i1,s1=Hte&&typeof Ym=="object"&&Ym&&!Ym.nodeType&&Ym,ZVe=s1&&s1.exports===Hte,xL=ZVe&&XVe.process,$Ve=function(){try{var t=s1&&s1.require&&s1.require("util").types;return t||xL&&xL.binding&&xL.binding("util")}catch{}}();Ym.exports=$Ve});var vS=_((ZFt,Gte)=>{var eze=Ute(),tze=IS(),qte=BS(),jte=qte&&qte.isTypedArray,rze=jte?tze(jte):eze;Gte.exports=rze});var kL=_(($Ft,Yte)=>{var nze=vte(),ize=e1(),sze=jl(),oze=r1(),aze=n1(),lze=vS(),cze=Object.prototype,uze=cze.hasOwnProperty;function Aze(t,e){var r=sze(t),o=!r&&ize(t),a=!r&&!o&&oze(t),n=!r&&!o&&!a&&lze(t),u=r||o||a||n,A=u?nze(t.length,String):[],p=A.length;for(var h in t)(e||uze.call(t,h))&&!(u&&(h=="length"||a&&(h=="offset"||h=="parent")||n&&(h=="buffer"||h=="byteLength"||h=="byteOffset")||aze(h,p)))&&A.push(h);return A}Yte.exports=Aze});var DS=_((eRt,Wte)=>{var fze=Object.prototype;function pze(t){var e=t&&t.constructor,r=typeof e=="function"&&e.prototype||fze;return t===r}Wte.exports=pze});var QL=_((tRt,Kte)=>{function hze(t,e){return function(r){return t(e(r))}}Kte.exports=hze});var zte=_((rRt,Vte)=>{var gze=QL(),dze=gze(Object.keys,Object);Vte.exports=dze});var Xte=_((nRt,Jte)=>{var mze=DS(),yze=zte(),Eze=Object.prototype,Cze=Eze.hasOwnProperty;function wze(t){if(!mze(t))return yze(t);var e=[];for(var r in Object(t))Cze.call(t,r)&&r!="constructor"&&e.push(r);return e}Jte.exports=wze});var o1=_((iRt,Zte)=>{var Ize=hS(),Bze=wS();function vze(t){return t!=null&&Bze(t.length)&&!Ize(t)}Zte.exports=vze});var PS=_((sRt,$te)=>{var Dze=kL(),Pze=Xte(),Sze=o1();function bze(t){return Sze(t)?Dze(t):Pze(t)}$te.exports=bze});var FL=_((oRt,ere)=>{var xze=SL(),kze=CS(),Qze=PS();function Fze(t){return xze(t,Qze,kze)}ere.exports=Fze});var nre=_((aRt,rre)=>{var tre=FL(),Rze=1,Tze=Object.prototype,Nze=Tze.hasOwnProperty;function Lze(t,e,r,o,a,n){var u=r&Rze,A=tre(t),p=A.length,h=tre(e),E=h.length;if(p!=E&&!u)return!1;for(var I=p;I--;){var D=A[I];if(!(u?D in e:Nze.call(e,D)))return!1}var x=n.get(t),C=n.get(e);if(x&&C)return x==e&&C==t;var T=!0;n.set(t,e),n.set(e,t);for(var L=u;++I{var Mze=$p(),Oze=ql(),Uze=Mze(Oze,"DataView");ire.exports=Uze});var are=_((cRt,ore)=>{var _ze=$p(),Hze=ql(),qze=_ze(Hze,"Promise");ore.exports=qze});var cre=_((uRt,lre)=>{var jze=$p(),Gze=ql(),Yze=jze(Gze,"Set");lre.exports=Yze});var Are=_((ARt,ure)=>{var Wze=$p(),Kze=ql(),Vze=Wze(Kze,"WeakMap");ure.exports=Vze});var a1=_((fRt,yre)=>{var RL=sre(),TL=gS(),NL=are(),LL=cre(),ML=Are(),mre=mg(),Wm=BL(),fre="[object Map]",zze="[object Object]",pre="[object Promise]",hre="[object Set]",gre="[object WeakMap]",dre="[object DataView]",Jze=Wm(RL),Xze=Wm(TL),Zze=Wm(NL),$ze=Wm(LL),eJe=Wm(ML),yg=mre;(RL&&yg(new RL(new ArrayBuffer(1)))!=dre||TL&&yg(new TL)!=fre||NL&&yg(NL.resolve())!=pre||LL&&yg(new LL)!=hre||ML&&yg(new ML)!=gre)&&(yg=function(t){var e=mre(t),r=e==zze?t.constructor:void 0,o=r?Wm(r):"";if(o)switch(o){case Jze:return dre;case Xze:return fre;case Zze:return pre;case $ze:return hre;case eJe:return gre}return e});yre.exports=yg});var Pre=_((pRt,Dre)=>{var OL=mS(),tJe=vL(),rJe=hte(),nJe=nre(),Ere=a1(),Cre=jl(),wre=r1(),iJe=vS(),sJe=1,Ire="[object Arguments]",Bre="[object Array]",SS="[object Object]",oJe=Object.prototype,vre=oJe.hasOwnProperty;function aJe(t,e,r,o,a,n){var u=Cre(t),A=Cre(e),p=u?Bre:Ere(t),h=A?Bre:Ere(e);p=p==Ire?SS:p,h=h==Ire?SS:h;var E=p==SS,I=h==SS,D=p==h;if(D&&wre(t)){if(!wre(e))return!1;u=!0,E=!1}if(D&&!E)return n||(n=new OL),u||iJe(t)?tJe(t,e,r,o,a,n):rJe(t,e,p,r,o,a,n);if(!(r&sJe)){var x=E&&vre.call(t,"__wrapped__"),C=I&&vre.call(e,"__wrapped__");if(x||C){var T=x?t.value():t,L=C?e.value():e;return n||(n=new OL),a(T,L,r,o,n)}}return D?(n||(n=new OL),nJe(t,e,r,o,a,n)):!1}Dre.exports=aJe});var kre=_((hRt,xre)=>{var lJe=Pre(),Sre=Zu();function bre(t,e,r,o,a){return t===e?!0:t==null||e==null||!Sre(t)&&!Sre(e)?t!==t&&e!==e:lJe(t,e,r,o,bre,a)}xre.exports=bre});var Fre=_((gRt,Qre)=>{var cJe=kre();function uJe(t,e){return cJe(t,e)}Qre.exports=uJe});var UL=_((dRt,Rre)=>{var AJe=$p(),fJe=function(){try{var t=AJe(Object,"defineProperty");return t({},"",{}),t}catch{}}();Rre.exports=fJe});var bS=_((mRt,Nre)=>{var Tre=UL();function pJe(t,e,r){e=="__proto__"&&Tre?Tre(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}Nre.exports=pJe});var _L=_((yRt,Lre)=>{var hJe=bS(),gJe=Um();function dJe(t,e,r){(r!==void 0&&!gJe(t[e],r)||r===void 0&&!(e in t))&&hJe(t,e,r)}Lre.exports=dJe});var Ore=_((ERt,Mre)=>{function mJe(t){return function(e,r,o){for(var a=-1,n=Object(e),u=o(e),A=u.length;A--;){var p=u[t?A:++a];if(r(n[p],p,n)===!1)break}return e}}Mre.exports=mJe});var _re=_((CRt,Ure)=>{var yJe=Ore(),EJe=yJe();Ure.exports=EJe});var HL=_((l1,Km)=>{var CJe=ql(),Gre=typeof l1=="object"&&l1&&!l1.nodeType&&l1,Hre=Gre&&typeof Km=="object"&&Km&&!Km.nodeType&&Km,wJe=Hre&&Hre.exports===Gre,qre=wJe?CJe.Buffer:void 0,jre=qre?qre.allocUnsafe:void 0;function IJe(t,e){if(e)return t.slice();var r=t.length,o=jre?jre(r):new t.constructor(r);return t.copy(o),o}Km.exports=IJe});var xS=_((wRt,Wre)=>{var Yre=DL();function BJe(t){var e=new t.constructor(t.byteLength);return new Yre(e).set(new Yre(t)),e}Wre.exports=BJe});var qL=_((IRt,Kre)=>{var vJe=xS();function DJe(t,e){var r=e?vJe(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.length)}Kre.exports=DJe});var kS=_((BRt,Vre)=>{function PJe(t,e){var r=-1,o=t.length;for(e||(e=Array(o));++r{var SJe=cl(),zre=Object.create,bJe=function(){function t(){}return function(e){if(!SJe(e))return{};if(zre)return zre(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();Jre.exports=bJe});var QS=_((DRt,Zre)=>{var xJe=QL(),kJe=xJe(Object.getPrototypeOf,Object);Zre.exports=kJe});var jL=_((PRt,$re)=>{var QJe=Xre(),FJe=QS(),RJe=DS();function TJe(t){return typeof t.constructor=="function"&&!RJe(t)?QJe(FJe(t)):{}}$re.exports=TJe});var tne=_((SRt,ene)=>{var NJe=o1(),LJe=Zu();function MJe(t){return LJe(t)&&NJe(t)}ene.exports=MJe});var YL=_((bRt,nne)=>{var OJe=mg(),UJe=QS(),_Je=Zu(),HJe="[object Object]",qJe=Function.prototype,jJe=Object.prototype,rne=qJe.toString,GJe=jJe.hasOwnProperty,YJe=rne.call(Object);function WJe(t){if(!_Je(t)||OJe(t)!=HJe)return!1;var e=UJe(t);if(e===null)return!0;var r=GJe.call(e,"constructor")&&e.constructor;return typeof r=="function"&&r instanceof r&&rne.call(r)==YJe}nne.exports=WJe});var WL=_((xRt,ine)=>{function KJe(t,e){if(!(e==="constructor"&&typeof t[e]=="function")&&e!="__proto__")return t[e]}ine.exports=KJe});var RS=_((kRt,sne)=>{var VJe=bS(),zJe=Um(),JJe=Object.prototype,XJe=JJe.hasOwnProperty;function ZJe(t,e,r){var o=t[e];(!(XJe.call(t,e)&&zJe(o,r))||r===void 0&&!(e in t))&&VJe(t,e,r)}sne.exports=ZJe});var Eg=_((QRt,one)=>{var $Je=RS(),eXe=bS();function tXe(t,e,r,o){var a=!r;r||(r={});for(var n=-1,u=e.length;++n{function rXe(t){var e=[];if(t!=null)for(var r in Object(t))e.push(r);return e}ane.exports=rXe});var une=_((RRt,cne)=>{var nXe=cl(),iXe=DS(),sXe=lne(),oXe=Object.prototype,aXe=oXe.hasOwnProperty;function lXe(t){if(!nXe(t))return sXe(t);var e=iXe(t),r=[];for(var o in t)o=="constructor"&&(e||!aXe.call(t,o))||r.push(o);return r}cne.exports=lXe});var Vm=_((TRt,Ane)=>{var cXe=kL(),uXe=une(),AXe=o1();function fXe(t){return AXe(t)?cXe(t,!0):uXe(t)}Ane.exports=fXe});var pne=_((NRt,fne)=>{var pXe=Eg(),hXe=Vm();function gXe(t){return pXe(t,hXe(t))}fne.exports=gXe});var Ene=_((LRt,yne)=>{var hne=_L(),dXe=HL(),mXe=qL(),yXe=kS(),EXe=jL(),gne=e1(),dne=jl(),CXe=tne(),wXe=r1(),IXe=hS(),BXe=cl(),vXe=YL(),DXe=vS(),mne=WL(),PXe=pne();function SXe(t,e,r,o,a,n,u){var A=mne(t,r),p=mne(e,r),h=u.get(p);if(h){hne(t,r,h);return}var E=n?n(A,p,r+"",t,e,u):void 0,I=E===void 0;if(I){var D=dne(p),x=!D&&wXe(p),C=!D&&!x&&DXe(p);E=p,D||x||C?dne(A)?E=A:CXe(A)?E=yXe(A):x?(I=!1,E=dXe(p,!0)):C?(I=!1,E=mXe(p,!0)):E=[]:vXe(p)||gne(p)?(E=A,gne(A)?E=PXe(A):(!BXe(A)||IXe(A))&&(E=EXe(p))):I=!1}I&&(u.set(p,E),a(E,p,o,n,u),u.delete(p)),hne(t,r,E)}yne.exports=SXe});var Ine=_((MRt,wne)=>{var bXe=mS(),xXe=_L(),kXe=_re(),QXe=Ene(),FXe=cl(),RXe=Vm(),TXe=WL();function Cne(t,e,r,o,a){t!==e&&kXe(e,function(n,u){if(a||(a=new bXe),FXe(n))QXe(t,e,u,r,Cne,o,a);else{var A=o?o(TXe(t,u),n,u+"",t,e,a):void 0;A===void 0&&(A=n),xXe(t,u,A)}},RXe)}wne.exports=Cne});var KL=_((ORt,Bne)=>{function NXe(t){return t}Bne.exports=NXe});var Dne=_((URt,vne)=>{function LXe(t,e,r){switch(r.length){case 0:return t.call(e);case 1:return t.call(e,r[0]);case 2:return t.call(e,r[0],r[1]);case 3:return t.call(e,r[0],r[1],r[2])}return t.apply(e,r)}vne.exports=LXe});var VL=_((_Rt,Sne)=>{var MXe=Dne(),Pne=Math.max;function OXe(t,e,r){return e=Pne(e===void 0?t.length-1:e,0),function(){for(var o=arguments,a=-1,n=Pne(o.length-e,0),u=Array(n);++a{function UXe(t){return function(){return t}}bne.exports=UXe});var Fne=_((qRt,Qne)=>{var _Xe=xne(),kne=UL(),HXe=KL(),qXe=kne?function(t,e){return kne(t,"toString",{configurable:!0,enumerable:!1,value:_Xe(e),writable:!0})}:HXe;Qne.exports=qXe});var Tne=_((jRt,Rne)=>{var jXe=800,GXe=16,YXe=Date.now;function WXe(t){var e=0,r=0;return function(){var o=YXe(),a=GXe-(o-r);if(r=o,a>0){if(++e>=jXe)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}Rne.exports=WXe});var zL=_((GRt,Nne)=>{var KXe=Fne(),VXe=Tne(),zXe=VXe(KXe);Nne.exports=zXe});var Mne=_((YRt,Lne)=>{var JXe=KL(),XXe=VL(),ZXe=zL();function $Xe(t,e){return ZXe(XXe(t,e,JXe),t+"")}Lne.exports=$Xe});var Une=_((WRt,One)=>{var eZe=Um(),tZe=o1(),rZe=n1(),nZe=cl();function iZe(t,e,r){if(!nZe(r))return!1;var o=typeof e;return(o=="number"?tZe(r)&&rZe(e,r.length):o=="string"&&e in r)?eZe(r[e],t):!1}One.exports=iZe});var Hne=_((KRt,_ne)=>{var sZe=Mne(),oZe=Une();function aZe(t){return sZe(function(e,r){var o=-1,a=r.length,n=a>1?r[a-1]:void 0,u=a>2?r[2]:void 0;for(n=t.length>3&&typeof n=="function"?(a--,n):void 0,u&&oZe(r[0],r[1],u)&&(n=a<3?void 0:n,a=1),e=Object(e);++o{var lZe=Ine(),cZe=Hne(),uZe=cZe(function(t,e,r,o){lZe(t,e,r,o)});qne.exports=uZe});var qe={};Kt(qe,{AsyncActions:()=>ZL,BufferStream:()=>XL,CachingStrategy:()=>tie,DefaultStream:()=>$L,allSettledSafe:()=>Yc,assertNever:()=>tM,bufferStream:()=>Xm,buildIgnorePattern:()=>mZe,convertMapsToIndexableObjects:()=>NS,dynamicRequire:()=>vf,escapeRegExp:()=>fZe,getArrayWithDefault:()=>u1,getFactoryWithDefault:()=>Al,getMapWithDefault:()=>A1,getSetWithDefault:()=>zm,groupBy:()=>CZe,isIndexableObject:()=>JL,isPathLike:()=>yZe,isTaggedYarnVersion:()=>AZe,makeDeferred:()=>Zne,mapAndFilter:()=>ul,mapAndFind:()=>eh,mergeIntoTarget:()=>nie,overrideType:()=>pZe,parseBoolean:()=>f1,parseInt:()=>Zm,parseOptionalBoolean:()=>rie,plural:()=>TS,prettifyAsyncErrors:()=>Jm,prettifySyncErrors:()=>rM,releaseAfterUseAsync:()=>gZe,replaceEnvVariables:()=>LS,sortMap:()=>Ps,toMerged:()=>EZe,tryParseOptionalBoolean:()=>nM,validateEnum:()=>hZe});function AZe(t){return!!(zne.default.valid(t)&&t.match(/^[^-]+(-rc\.[0-9]+)?$/))}function TS(t,{one:e,more:r,zero:o=r}){return t===0?o:t===1?e:r}function fZe(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function pZe(t){}function tM(t){throw new Error(`Assertion failed: Unexpected object '${t}'`)}function hZe(t,e){let r=Object.values(t);if(!r.includes(e))throw new ot(`Invalid value for enumeration: ${JSON.stringify(e)} (expected one of ${r.map(o=>JSON.stringify(o)).join(", ")})`);return e}function ul(t,e){let r=[];for(let o of t){let a=e(o);a!==Jne&&r.push(a)}return r}function eh(t,e){for(let r of t){let o=e(r);if(o!==Xne)return o}}function JL(t){return typeof t=="object"&&t!==null}async function Yc(t){let e=await Promise.allSettled(t),r=[];for(let o of e){if(o.status==="rejected")throw o.reason;r.push(o.value)}return r}function NS(t){if(t instanceof Map&&(t=Object.fromEntries(t)),JL(t))for(let e of Object.keys(t)){let r=t[e];JL(r)&&(t[e]=NS(r))}return t}function Al(t,e,r){let o=t.get(e);return typeof o>"u"&&t.set(e,o=r()),o}function u1(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=[]),r}function zm(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=new Set),r}function A1(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=new Map),r}async function gZe(t,e){if(e==null)return await t();try{return await t()}finally{await e()}}async function Jm(t,e){try{return await t()}catch(r){throw r.message=e(r.message),r}}function rM(t,e){try{return t()}catch(r){throw r.message=e(r.message),r}}async function Xm(t){return await new Promise((e,r)=>{let o=[];t.on("error",a=>{r(a)}),t.on("data",a=>{o.push(a)}),t.on("end",()=>{e(Buffer.concat(o))})})}function Zne(){let t,e;return{promise:new Promise((o,a)=>{t=o,e=a}),resolve:t,reject:e}}function $ne(t){return c1(Ae.fromPortablePath(t))}function eie(path){let physicalPath=Ae.fromPortablePath(path),currentCacheEntry=c1.cache[physicalPath];delete c1.cache[physicalPath];let result;try{result=$ne(physicalPath);let freshCacheEntry=c1.cache[physicalPath],dynamicModule=eval("module"),freshCacheIndex=dynamicModule.children.indexOf(freshCacheEntry);freshCacheIndex!==-1&&dynamicModule.children.splice(freshCacheIndex,1)}finally{c1.cache[physicalPath]=currentCacheEntry}return result}function dZe(t){let e=Gne.get(t),r=ae.statSync(t);if(e?.mtime===r.mtimeMs)return e.instance;let o=eie(t);return Gne.set(t,{mtime:r.mtimeMs,instance:o}),o}function vf(t,{cachingStrategy:e=2}={}){switch(e){case 0:return eie(t);case 1:return dZe(t);case 2:return $ne(t);default:throw new Error("Unsupported caching strategy")}}function Ps(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function mZe(t){return t.length===0?null:t.map(e=>`(${Kne.default.makeRe(e,{windows:!1,dot:!0}).source})`).join("|")}function LS(t,{env:e}){let r=/\${(?[\d\w_]+)(?:)?(?:-(?[^}]*))?}/g;return t.replace(r,(...o)=>{let{variableName:a,colon:n,fallback:u}=o[o.length-1],A=Object.hasOwn(e,a),p=e[a];if(p||A&&!n)return p;if(u!=null)return u;throw new ot(`Environment variable not found (${a})`)})}function f1(t){switch(t){case"true":case"1":case 1:case!0:return!0;case"false":case"0":case 0:case!1:return!1;default:throw new Error(`Couldn't parse "${t}" as a boolean`)}}function rie(t){return typeof t>"u"?t:f1(t)}function nM(t){try{return rie(t)}catch{return null}}function yZe(t){return!!(Ae.isAbsolute(t)||t.match(/^(\.{1,2}|~)\//))}function nie(t,...e){let r=u=>({value:u}),o=r(t),a=e.map(u=>r(u)),{value:n}=(0,Wne.default)(o,...a,(u,A)=>{if(Array.isArray(u)&&Array.isArray(A)){for(let p of A)u.find(h=>(0,Yne.default)(h,p))||u.push(p);return u}});return n}function EZe(...t){return nie({},...t)}function CZe(t,e){let r=Object.create(null);for(let o of t){let a=o[e];r[a]??=[],r[a].push(o)}return r}function Zm(t){return typeof t=="string"?Number.parseInt(t,10):t}var Yne,Wne,Kne,Vne,zne,eM,Jne,Xne,XL,ZL,$L,c1,Gne,tie,Gl=wt(()=>{Pt();Gt();Yne=et(Fre()),Wne=et(jne()),Kne=et(Xo()),Vne=et(lg()),zne=et(ni()),eM=ve("stream");Jne=Symbol();ul.skip=Jne;Xne=Symbol();eh.skip=Xne;XL=class extends eM.Transform{constructor(){super(...arguments);this.chunks=[]}_transform(r,o,a){if(o!=="buffer"||!Buffer.isBuffer(r))throw new Error("Assertion failed: BufferStream only accept buffers");this.chunks.push(r),a(null,null)}_flush(r){r(null,Buffer.concat(this.chunks))}};ZL=class{constructor(e){this.deferred=new Map;this.promises=new Map;this.limit=(0,Vne.default)(e)}set(e,r){let o=this.deferred.get(e);typeof o>"u"&&this.deferred.set(e,o=Zne());let a=this.limit(()=>r());return this.promises.set(e,a),a.then(()=>{this.promises.get(e)===a&&o.resolve()},n=>{this.promises.get(e)===a&&o.reject(n)}),o.promise}reduce(e,r){let o=this.promises.get(e)??Promise.resolve();this.set(e,()=>r(o))}async wait(){await Promise.all(this.promises.values())}},$L=class extends eM.Transform{constructor(r=Buffer.alloc(0)){super();this.active=!0;this.ifEmpty=r}_transform(r,o,a){if(o!=="buffer"||!Buffer.isBuffer(r))throw new Error("Assertion failed: DefaultStream only accept buffers");this.active=!1,a(null,r)}_flush(r){this.active&&this.ifEmpty.length>0?r(null,this.ifEmpty):r(null)}},c1=eval("require");Gne=new Map;tie=(o=>(o[o.NoCache=0]="NoCache",o[o.FsTime=1]="FsTime",o[o.Node=2]="Node",o))(tie||{})});var $m,iM,sM,iie=wt(()=>{$m=(r=>(r.HARD="HARD",r.SOFT="SOFT",r))($m||{}),iM=(o=>(o.Dependency="Dependency",o.PeerDependency="PeerDependency",o.PeerDependencyMeta="PeerDependencyMeta",o))(iM||{}),sM=(o=>(o.Inactive="inactive",o.Redundant="redundant",o.Active="active",o))(sM||{})});var pe={};Kt(pe,{LogLevel:()=>HS,Style:()=>OS,Type:()=>Ct,addLogFilterSupport:()=>g1,applyColor:()=>Gs,applyHyperlink:()=>ty,applyStyle:()=>Cg,json:()=>wg,jsonOrPretty:()=>BZe,mark:()=>uM,pretty:()=>Ut,prettyField:()=>$u,prettyList:()=>cM,prettyTruncatedLocatorList:()=>_S,stripAnsi:()=>ey.default,supportsColor:()=>US,supportsHyperlinks:()=>lM,tuple:()=>Wc});function sie(t){let e=["KiB","MiB","GiB","TiB"],r=e.length;for(;r>1&&t<1024**r;)r-=1;let o=1024**r;return`${Math.floor(t*100/o)/100} ${e[r-1]}`}function Wc(t,e){return[e,t]}function Cg(t,e,r){return t.get("enableColors")&&r&2&&(e=h1.default.bold(e)),e}function Gs(t,e,r){if(!t.get("enableColors"))return e;let o=wZe.get(r);if(o===null)return e;let a=typeof o>"u"?r:aM.level>=3?o[0]:o[1],n=typeof a=="number"?oM.ansi256(a):a.startsWith("#")?oM.hex(a):oM[a];if(typeof n!="function")throw new Error(`Invalid format type ${a}`);return n(e)}function ty(t,e,r){return t.get("enableHyperlinks")?IZe?`\x1B]8;;${r}\x1B\\${e}\x1B]8;;\x1B\\`:`\x1B]8;;${r}\x07${e}\x1B]8;;\x07`:e}function Ut(t,e,r){if(e===null)return Gs(t,"null",Ct.NULL);if(Object.hasOwn(MS,r))return MS[r].pretty(t,e);if(typeof e!="string")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof e}`);return Gs(t,e,r)}function cM(t,e,r,{separator:o=", "}={}){return[...e].map(a=>Ut(t,a,r)).join(o)}function wg(t,e){if(t===null)return null;if(Object.hasOwn(MS,e))return MS[e].json(t);if(typeof t!="string")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof t}`);return t}function BZe(t,e,[r,o]){return t?wg(r,o):Ut(e,r,o)}function uM(t){return{Check:Gs(t,"\u2713","green"),Cross:Gs(t,"\u2718","red"),Question:Gs(t,"?","cyan")}}function $u(t,{label:e,value:[r,o]}){return`${Ut(t,e,Ct.CODE)}: ${Ut(t,r,o)}`}function _S(t,e,r){let o=[],a=[...e],n=r;for(;a.length>0;){let h=a[0],E=`${jr(t,h)}, `,I=AM(h).length+2;if(o.length>0&&nh).join("").slice(0,-2);let u="X".repeat(a.length.toString().length),A=`and ${u} more.`,p=a.length;for(;o.length>1&&nh).join(""),A.replace(u,Ut(t,p,Ct.NUMBER))].join("")}function g1(t,{configuration:e}){let r=e.get("logFilters"),o=new Map,a=new Map,n=[];for(let I of r){let D=I.get("level");if(typeof D>"u")continue;let x=I.get("code");typeof x<"u"&&o.set(x,D);let C=I.get("text");typeof C<"u"&&a.set(C,D);let T=I.get("pattern");typeof T<"u"&&n.push([oie.default.matcher(T,{contains:!0}),D])}n.reverse();let u=(I,D,x)=>{if(I===null||I===0)return x;let C=a.size>0||n.length>0?(0,ey.default)(D):D;if(a.size>0){let T=a.get(C);if(typeof T<"u")return T??x}if(n.length>0){for(let[T,L]of n)if(T(C))return L??x}if(o.size>0){let T=o.get(zu(I));if(typeof T<"u")return T??x}return x},A=t.reportInfo,p=t.reportWarning,h=t.reportError,E=function(I,D,x,C){switch(u(D,x,C)){case"info":A.call(I,D,x);break;case"warning":p.call(I,D??0,x);break;case"error":h.call(I,D??0,x);break}};t.reportInfo=function(...I){return E(this,...I,"info")},t.reportWarning=function(...I){return E(this,...I,"warning")},t.reportError=function(...I){return E(this,...I,"error")}}var h1,p1,oie,ey,aie,Ct,OS,aM,US,lM,oM,wZe,Co,MS,IZe,HS,Yl=wt(()=>{Pt();h1=et(iL()),p1=et(sg());Gt();oie=et(Xo()),ey=et(pS()),aie=ve("util");jP();wo();Ct={NO_HINT:"NO_HINT",ID:"ID",NULL:"NULL",SCOPE:"SCOPE",NAME:"NAME",RANGE:"RANGE",REFERENCE:"REFERENCE",NUMBER:"NUMBER",PATH:"PATH",URL:"URL",ADDED:"ADDED",REMOVED:"REMOVED",CODE:"CODE",INSPECT:"INSPECT",DURATION:"DURATION",SIZE:"SIZE",SIZE_DIFF:"SIZE_DIFF",IDENT:"IDENT",DESCRIPTOR:"DESCRIPTOR",LOCATOR:"LOCATOR",RESOLUTION:"RESOLUTION",DEPENDENT:"DEPENDENT",PACKAGE_EXTENSION:"PACKAGE_EXTENSION",SETTING:"SETTING",MARKDOWN:"MARKDOWN",MARKDOWN_INLINE:"MARKDOWN_INLINE"},OS=(e=>(e[e.BOLD=2]="BOLD",e))(OS||{}),aM=p1.default.GITHUB_ACTIONS?{level:2}:h1.default.supportsColor?{level:h1.default.supportsColor.level}:{level:0},US=aM.level!==0,lM=US&&!p1.default.GITHUB_ACTIONS&&!p1.default.CIRCLE&&!p1.default.GITLAB,oM=new h1.default.Instance(aM),wZe=new Map([[Ct.NO_HINT,null],[Ct.NULL,["#a853b5",129]],[Ct.SCOPE,["#d75f00",166]],[Ct.NAME,["#d7875f",173]],[Ct.RANGE,["#00afaf",37]],[Ct.REFERENCE,["#87afff",111]],[Ct.NUMBER,["#ffd700",220]],[Ct.PATH,["#d75fd7",170]],[Ct.URL,["#d75fd7",170]],[Ct.ADDED,["#5faf00",70]],[Ct.REMOVED,["#ff3131",160]],[Ct.CODE,["#87afff",111]],[Ct.SIZE,["#ffd700",220]]]),Co=t=>t;MS={[Ct.ID]:Co({pretty:(t,e)=>typeof e=="number"?Gs(t,`${e}`,Ct.NUMBER):Gs(t,e,Ct.CODE),json:t=>t}),[Ct.INSPECT]:Co({pretty:(t,e)=>(0,aie.inspect)(e,{depth:1/0,colors:t.get("enableColors"),compact:!0,breakLength:1/0}),json:t=>t}),[Ct.NUMBER]:Co({pretty:(t,e)=>Gs(t,`${e}`,Ct.NUMBER),json:t=>t}),[Ct.IDENT]:Co({pretty:(t,e)=>Ui(t,e),json:t=>rn(t)}),[Ct.LOCATOR]:Co({pretty:(t,e)=>jr(t,e),json:t=>Qa(t)}),[Ct.DESCRIPTOR]:Co({pretty:(t,e)=>zn(t,e),json:t=>ka(t)}),[Ct.RESOLUTION]:Co({pretty:(t,{descriptor:e,locator:r})=>d1(t,e,r),json:({descriptor:t,locator:e})=>({descriptor:ka(t),locator:e!==null?Qa(e):null})}),[Ct.DEPENDENT]:Co({pretty:(t,{locator:e,descriptor:r})=>fM(t,e,r),json:({locator:t,descriptor:e})=>({locator:Qa(t),descriptor:ka(e)})}),[Ct.PACKAGE_EXTENSION]:Co({pretty:(t,e)=>{switch(e.type){case"Dependency":return`${Ui(t,e.parentDescriptor)} \u27A4 ${Gs(t,"dependencies",Ct.CODE)} \u27A4 ${Ui(t,e.descriptor)}`;case"PeerDependency":return`${Ui(t,e.parentDescriptor)} \u27A4 ${Gs(t,"peerDependencies",Ct.CODE)} \u27A4 ${Ui(t,e.descriptor)}`;case"PeerDependencyMeta":return`${Ui(t,e.parentDescriptor)} \u27A4 ${Gs(t,"peerDependenciesMeta",Ct.CODE)} \u27A4 ${Ui(t,Zo(e.selector))} \u27A4 ${Gs(t,e.key,Ct.CODE)}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${e.type}`)}},json:t=>{switch(t.type){case"Dependency":return`${rn(t.parentDescriptor)} > ${rn(t.descriptor)}`;case"PeerDependency":return`${rn(t.parentDescriptor)} >> ${rn(t.descriptor)}`;case"PeerDependencyMeta":return`${rn(t.parentDescriptor)} >> ${t.selector} / ${t.key}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${t.type}`)}}}),[Ct.SETTING]:Co({pretty:(t,e)=>(t.get(e),ty(t,Gs(t,e,Ct.CODE),`https://yarnpkg.com/configuration/yarnrc#${e}`)),json:t=>t}),[Ct.DURATION]:Co({pretty:(t,e)=>{if(e>1e3*60){let r=Math.floor(e/1e3/60),o=Math.ceil((e-r*60*1e3)/1e3);return o===0?`${r}m`:`${r}m ${o}s`}else{let r=Math.floor(e/1e3),o=e-r*1e3;return o===0?`${r}s`:`${r}s ${o}ms`}},json:t=>t}),[Ct.SIZE]:Co({pretty:(t,e)=>Gs(t,sie(e),Ct.NUMBER),json:t=>t}),[Ct.SIZE_DIFF]:Co({pretty:(t,e)=>{let r=e>=0?"+":"-",o=r==="+"?Ct.REMOVED:Ct.ADDED;return Gs(t,`${r} ${sie(Math.max(Math.abs(e),1))}`,o)},json:t=>t}),[Ct.PATH]:Co({pretty:(t,e)=>Gs(t,Ae.fromPortablePath(e),Ct.PATH),json:t=>Ae.fromPortablePath(t)}),[Ct.MARKDOWN]:Co({pretty:(t,{text:e,format:r,paragraphs:o})=>yo(e,{format:r,paragraphs:o}),json:({text:t})=>t}),[Ct.MARKDOWN_INLINE]:Co({pretty:(t,e)=>(e=e.replace(/(`+)((?:.|[\n])*?)\1/g,(r,o,a)=>Ut(t,o+a+o,Ct.CODE)),e=e.replace(/(\*\*)((?:.|[\n])*?)\1/g,(r,o,a)=>Cg(t,a,2)),e),json:t=>t})};IZe=!!process.env.KONSOLE_VERSION;HS=(a=>(a.Error="error",a.Warning="warning",a.Info="info",a.Discard="discard",a))(HS||{})});var lie=_(ry=>{"use strict";Object.defineProperty(ry,"__esModule",{value:!0});ry.splitWhen=ry.flatten=void 0;function vZe(t){return t.reduce((e,r)=>[].concat(e,r),[])}ry.flatten=vZe;function DZe(t,e){let r=[[]],o=0;for(let a of t)e(a)?(o++,r[o]=[]):r[o].push(a);return r}ry.splitWhen=DZe});var cie=_(qS=>{"use strict";Object.defineProperty(qS,"__esModule",{value:!0});qS.isEnoentCodeError=void 0;function PZe(t){return t.code==="ENOENT"}qS.isEnoentCodeError=PZe});var uie=_(jS=>{"use strict";Object.defineProperty(jS,"__esModule",{value:!0});jS.createDirentFromStats=void 0;var pM=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function SZe(t,e){return new pM(t,e)}jS.createDirentFromStats=SZe});var hie=_(Vi=>{"use strict";Object.defineProperty(Vi,"__esModule",{value:!0});Vi.convertPosixPathToPattern=Vi.convertWindowsPathToPattern=Vi.convertPathToPattern=Vi.escapePosixPath=Vi.escapeWindowsPath=Vi.escape=Vi.removeLeadingDotSegment=Vi.makeAbsolute=Vi.unixify=void 0;var bZe=ve("os"),xZe=ve("path"),Aie=bZe.platform()==="win32",kZe=2,QZe=/(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g,FZe=/(\\?)([()[\]{}]|^!|[!+@](?=\())/g,RZe=/^\\\\([.?])/,TZe=/\\(?![!()+@[\]{}])/g;function NZe(t){return t.replace(/\\/g,"/")}Vi.unixify=NZe;function LZe(t,e){return xZe.resolve(t,e)}Vi.makeAbsolute=LZe;function MZe(t){if(t.charAt(0)==="."){let e=t.charAt(1);if(e==="/"||e==="\\")return t.slice(kZe)}return t}Vi.removeLeadingDotSegment=MZe;Vi.escape=Aie?hM:gM;function hM(t){return t.replace(FZe,"\\$2")}Vi.escapeWindowsPath=hM;function gM(t){return t.replace(QZe,"\\$2")}Vi.escapePosixPath=gM;Vi.convertPathToPattern=Aie?fie:pie;function fie(t){return hM(t).replace(RZe,"//$1").replace(TZe,"/")}Vi.convertWindowsPathToPattern=fie;function pie(t){return gM(t)}Vi.convertPosixPathToPattern=pie});var die=_((cTt,gie)=>{gie.exports=function(e){if(typeof e!="string"||e==="")return!1;for(var r;r=/(\\).|([@?!+*]\(.*\))/g.exec(e);){if(r[2])return!0;e=e.slice(r.index+r[0].length)}return!1}});var Eie=_((uTt,yie)=>{var OZe=die(),mie={"{":"}","(":")","[":"]"},UZe=function(t){if(t[0]==="!")return!0;for(var e=0,r=-2,o=-2,a=-2,n=-2,u=-2;ee&&(u===-1||u>o||(u=t.indexOf("\\",e),u===-1||u>o)))||a!==-1&&t[e]==="{"&&t[e+1]!=="}"&&(a=t.indexOf("}",e),a>e&&(u=t.indexOf("\\",e),u===-1||u>a))||n!==-1&&t[e]==="("&&t[e+1]==="?"&&/[:!=]/.test(t[e+2])&&t[e+3]!==")"&&(n=t.indexOf(")",e),n>e&&(u=t.indexOf("\\",e),u===-1||u>n))||r!==-1&&t[e]==="("&&t[e+1]!=="|"&&(rr&&(u=t.indexOf("\\",r),u===-1||u>n))))return!0;if(t[e]==="\\"){var A=t[e+1];e+=2;var p=mie[A];if(p){var h=t.indexOf(p,e);h!==-1&&(e=h+1)}if(t[e]==="!")return!0}else e++}return!1},_Ze=function(t){if(t[0]==="!")return!0;for(var e=0;e{"use strict";var HZe=Eie(),qZe=ve("path").posix.dirname,jZe=ve("os").platform()==="win32",dM="/",GZe=/\\/g,YZe=/[\{\[].*[\}\]]$/,WZe=/(^|[^\\])([\{\[]|\([^\)]+$)/,KZe=/\\([\!\*\?\|\[\]\(\)\{\}])/g;Cie.exports=function(e,r){var o=Object.assign({flipBackslashes:!0},r);o.flipBackslashes&&jZe&&e.indexOf(dM)<0&&(e=e.replace(GZe,dM)),YZe.test(e)&&(e+=dM),e+="a";do e=qZe(e);while(HZe(e)||WZe.test(e));return e.replace(KZe,"$1")}});var xie=_(Or=>{"use strict";Object.defineProperty(Or,"__esModule",{value:!0});Or.removeDuplicateSlashes=Or.matchAny=Or.convertPatternsToRe=Or.makeRe=Or.getPatternParts=Or.expandBraceExpansion=Or.expandPatternsWithBraceExpansion=Or.isAffectDepthOfReadingPattern=Or.endsWithSlashGlobStar=Or.hasGlobStar=Or.getBaseDirectory=Or.isPatternRelatedToParentDirectory=Or.getPatternsOutsideCurrentDirectory=Or.getPatternsInsideCurrentDirectory=Or.getPositivePatterns=Or.getNegativePatterns=Or.isPositivePattern=Or.isNegativePattern=Or.convertToNegativePattern=Or.convertToPositivePattern=Or.isDynamicPattern=Or.isStaticPattern=void 0;var VZe=ve("path"),zZe=wie(),mM=Xo(),Iie="**",JZe="\\",XZe=/[*?]|^!/,ZZe=/\[[^[]*]/,$Ze=/(?:^|[^!*+?@])\([^(]*\|[^|]*\)/,e$e=/[!*+?@]\([^(]*\)/,t$e=/,|\.\./,r$e=/(?!^)\/{2,}/g;function Bie(t,e={}){return!vie(t,e)}Or.isStaticPattern=Bie;function vie(t,e={}){return t===""?!1:!!(e.caseSensitiveMatch===!1||t.includes(JZe)||XZe.test(t)||ZZe.test(t)||$Ze.test(t)||e.extglob!==!1&&e$e.test(t)||e.braceExpansion!==!1&&n$e(t))}Or.isDynamicPattern=vie;function n$e(t){let e=t.indexOf("{");if(e===-1)return!1;let r=t.indexOf("}",e+1);if(r===-1)return!1;let o=t.slice(e,r);return t$e.test(o)}function i$e(t){return GS(t)?t.slice(1):t}Or.convertToPositivePattern=i$e;function s$e(t){return"!"+t}Or.convertToNegativePattern=s$e;function GS(t){return t.startsWith("!")&&t[1]!=="("}Or.isNegativePattern=GS;function Die(t){return!GS(t)}Or.isPositivePattern=Die;function o$e(t){return t.filter(GS)}Or.getNegativePatterns=o$e;function a$e(t){return t.filter(Die)}Or.getPositivePatterns=a$e;function l$e(t){return t.filter(e=>!yM(e))}Or.getPatternsInsideCurrentDirectory=l$e;function c$e(t){return t.filter(yM)}Or.getPatternsOutsideCurrentDirectory=c$e;function yM(t){return t.startsWith("..")||t.startsWith("./..")}Or.isPatternRelatedToParentDirectory=yM;function u$e(t){return zZe(t,{flipBackslashes:!1})}Or.getBaseDirectory=u$e;function A$e(t){return t.includes(Iie)}Or.hasGlobStar=A$e;function Pie(t){return t.endsWith("/"+Iie)}Or.endsWithSlashGlobStar=Pie;function f$e(t){let e=VZe.basename(t);return Pie(t)||Bie(e)}Or.isAffectDepthOfReadingPattern=f$e;function p$e(t){return t.reduce((e,r)=>e.concat(Sie(r)),[])}Or.expandPatternsWithBraceExpansion=p$e;function Sie(t){let e=mM.braces(t,{expand:!0,nodupes:!0,keepEscaping:!0});return e.sort((r,o)=>r.length-o.length),e.filter(r=>r!=="")}Or.expandBraceExpansion=Sie;function h$e(t,e){let{parts:r}=mM.scan(t,Object.assign(Object.assign({},e),{parts:!0}));return r.length===0&&(r=[t]),r[0].startsWith("/")&&(r[0]=r[0].slice(1),r.unshift("")),r}Or.getPatternParts=h$e;function bie(t,e){return mM.makeRe(t,e)}Or.makeRe=bie;function g$e(t,e){return t.map(r=>bie(r,e))}Or.convertPatternsToRe=g$e;function d$e(t,e){return e.some(r=>r.test(t))}Or.matchAny=d$e;function m$e(t){return t.replace(r$e,"/")}Or.removeDuplicateSlashes=m$e});var Rie=_((pTt,Fie)=>{"use strict";var y$e=ve("stream"),kie=y$e.PassThrough,E$e=Array.prototype.slice;Fie.exports=C$e;function C$e(){let t=[],e=E$e.call(arguments),r=!1,o=e[e.length-1];o&&!Array.isArray(o)&&o.pipe==null?e.pop():o={};let a=o.end!==!1,n=o.pipeError===!0;o.objectMode==null&&(o.objectMode=!0),o.highWaterMark==null&&(o.highWaterMark=64*1024);let u=kie(o);function A(){for(let E=0,I=arguments.length;E0||(r=!1,p())}function x(C){function T(){C.removeListener("merge2UnpipeEnd",T),C.removeListener("end",T),n&&C.removeListener("error",L),D()}function L(U){u.emit("error",U)}if(C._readableState.endEmitted)return D();C.on("merge2UnpipeEnd",T),C.on("end",T),n&&C.on("error",L),C.pipe(u,{end:!1}),C.resume()}for(let C=0;C{"use strict";Object.defineProperty(YS,"__esModule",{value:!0});YS.merge=void 0;var w$e=Rie();function I$e(t){let e=w$e(t);return t.forEach(r=>{r.once("error",o=>e.emit("error",o))}),e.once("close",()=>Tie(t)),e.once("end",()=>Tie(t)),e}YS.merge=I$e;function Tie(t){t.forEach(e=>e.emit("close"))}});var Lie=_(ny=>{"use strict";Object.defineProperty(ny,"__esModule",{value:!0});ny.isEmpty=ny.isString=void 0;function B$e(t){return typeof t=="string"}ny.isString=B$e;function v$e(t){return t===""}ny.isEmpty=v$e});var Df=_(Io=>{"use strict";Object.defineProperty(Io,"__esModule",{value:!0});Io.string=Io.stream=Io.pattern=Io.path=Io.fs=Io.errno=Io.array=void 0;var D$e=lie();Io.array=D$e;var P$e=cie();Io.errno=P$e;var S$e=uie();Io.fs=S$e;var b$e=hie();Io.path=b$e;var x$e=xie();Io.pattern=x$e;var k$e=Nie();Io.stream=k$e;var Q$e=Lie();Io.string=Q$e});var _ie=_(Bo=>{"use strict";Object.defineProperty(Bo,"__esModule",{value:!0});Bo.convertPatternGroupToTask=Bo.convertPatternGroupsToTasks=Bo.groupPatternsByBaseDirectory=Bo.getNegativePatternsAsPositive=Bo.getPositivePatterns=Bo.convertPatternsToTasks=Bo.generate=void 0;var Kc=Df();function F$e(t,e){let r=Mie(t,e),o=Mie(e.ignore,e),a=Oie(r),n=Uie(r,o),u=a.filter(E=>Kc.pattern.isStaticPattern(E,e)),A=a.filter(E=>Kc.pattern.isDynamicPattern(E,e)),p=EM(u,n,!1),h=EM(A,n,!0);return p.concat(h)}Bo.generate=F$e;function Mie(t,e){let r=t;return e.braceExpansion&&(r=Kc.pattern.expandPatternsWithBraceExpansion(r)),e.baseNameMatch&&(r=r.map(o=>o.includes("/")?o:`**/${o}`)),r.map(o=>Kc.pattern.removeDuplicateSlashes(o))}function EM(t,e,r){let o=[],a=Kc.pattern.getPatternsOutsideCurrentDirectory(t),n=Kc.pattern.getPatternsInsideCurrentDirectory(t),u=CM(a),A=CM(n);return o.push(...wM(u,e,r)),"."in A?o.push(IM(".",n,e,r)):o.push(...wM(A,e,r)),o}Bo.convertPatternsToTasks=EM;function Oie(t){return Kc.pattern.getPositivePatterns(t)}Bo.getPositivePatterns=Oie;function Uie(t,e){return Kc.pattern.getNegativePatterns(t).concat(e).map(Kc.pattern.convertToPositivePattern)}Bo.getNegativePatternsAsPositive=Uie;function CM(t){let e={};return t.reduce((r,o)=>{let a=Kc.pattern.getBaseDirectory(o);return a in r?r[a].push(o):r[a]=[o],r},e)}Bo.groupPatternsByBaseDirectory=CM;function wM(t,e,r){return Object.keys(t).map(o=>IM(o,t[o],e,r))}Bo.convertPatternGroupsToTasks=wM;function IM(t,e,r,o){return{dynamic:o,positive:e,negative:r,base:t,patterns:[].concat(e,r.map(Kc.pattern.convertToNegativePattern))}}Bo.convertPatternGroupToTask=IM});var qie=_(WS=>{"use strict";Object.defineProperty(WS,"__esModule",{value:!0});WS.read=void 0;function R$e(t,e,r){e.fs.lstat(t,(o,a)=>{if(o!==null){Hie(r,o);return}if(!a.isSymbolicLink()||!e.followSymbolicLink){BM(r,a);return}e.fs.stat(t,(n,u)=>{if(n!==null){if(e.throwErrorOnBrokenSymbolicLink){Hie(r,n);return}BM(r,a);return}e.markSymbolicLink&&(u.isSymbolicLink=()=>!0),BM(r,u)})})}WS.read=R$e;function Hie(t,e){t(e)}function BM(t,e){t(null,e)}});var jie=_(KS=>{"use strict";Object.defineProperty(KS,"__esModule",{value:!0});KS.read=void 0;function T$e(t,e){let r=e.fs.lstatSync(t);if(!r.isSymbolicLink()||!e.followSymbolicLink)return r;try{let o=e.fs.statSync(t);return e.markSymbolicLink&&(o.isSymbolicLink=()=>!0),o}catch(o){if(!e.throwErrorOnBrokenSymbolicLink)return r;throw o}}KS.read=T$e});var Gie=_(th=>{"use strict";Object.defineProperty(th,"__esModule",{value:!0});th.createFileSystemAdapter=th.FILE_SYSTEM_ADAPTER=void 0;var VS=ve("fs");th.FILE_SYSTEM_ADAPTER={lstat:VS.lstat,stat:VS.stat,lstatSync:VS.lstatSync,statSync:VS.statSync};function N$e(t){return t===void 0?th.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},th.FILE_SYSTEM_ADAPTER),t)}th.createFileSystemAdapter=N$e});var Yie=_(DM=>{"use strict";Object.defineProperty(DM,"__esModule",{value:!0});var L$e=Gie(),vM=class{constructor(e={}){this._options=e,this.followSymbolicLink=this._getValue(this._options.followSymbolicLink,!0),this.fs=L$e.createFileSystemAdapter(this._options.fs),this.markSymbolicLink=this._getValue(this._options.markSymbolicLink,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0)}_getValue(e,r){return e??r}};DM.default=vM});var Ig=_(rh=>{"use strict";Object.defineProperty(rh,"__esModule",{value:!0});rh.statSync=rh.stat=rh.Settings=void 0;var Wie=qie(),M$e=jie(),PM=Yie();rh.Settings=PM.default;function O$e(t,e,r){if(typeof e=="function"){Wie.read(t,SM(),e);return}Wie.read(t,SM(e),r)}rh.stat=O$e;function U$e(t,e){let r=SM(e);return M$e.read(t,r)}rh.statSync=U$e;function SM(t={}){return t instanceof PM.default?t:new PM.default(t)}});var zie=_((BTt,Vie)=>{var Kie;Vie.exports=typeof queueMicrotask=="function"?queueMicrotask.bind(typeof window<"u"?window:global):t=>(Kie||(Kie=Promise.resolve())).then(t).catch(e=>setTimeout(()=>{throw e},0))});var Xie=_((vTt,Jie)=>{Jie.exports=H$e;var _$e=zie();function H$e(t,e){let r,o,a,n=!0;Array.isArray(t)?(r=[],o=t.length):(a=Object.keys(t),r={},o=a.length);function u(p){function h(){e&&e(p,r),e=null}n?_$e(h):h()}function A(p,h,E){r[p]=E,(--o===0||h)&&u(h)}o?a?a.forEach(function(p){t[p](function(h,E){A(p,h,E)})}):t.forEach(function(p,h){p(function(E,I){A(h,E,I)})}):u(null),n=!1}});var bM=_(JS=>{"use strict";Object.defineProperty(JS,"__esModule",{value:!0});JS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=void 0;var zS=process.versions.node.split(".");if(zS[0]===void 0||zS[1]===void 0)throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);var Zie=Number.parseInt(zS[0],10),q$e=Number.parseInt(zS[1],10),$ie=10,j$e=10,G$e=Zie>$ie,Y$e=Zie===$ie&&q$e>=j$e;JS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=G$e||Y$e});var ese=_(XS=>{"use strict";Object.defineProperty(XS,"__esModule",{value:!0});XS.createDirentFromStats=void 0;var xM=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function W$e(t,e){return new xM(t,e)}XS.createDirentFromStats=W$e});var kM=_(ZS=>{"use strict";Object.defineProperty(ZS,"__esModule",{value:!0});ZS.fs=void 0;var K$e=ese();ZS.fs=K$e});var QM=_($S=>{"use strict";Object.defineProperty($S,"__esModule",{value:!0});$S.joinPathSegments=void 0;function V$e(t,e,r){return t.endsWith(r)?t+e:t+r+e}$S.joinPathSegments=V$e});var ose=_(nh=>{"use strict";Object.defineProperty(nh,"__esModule",{value:!0});nh.readdir=nh.readdirWithFileTypes=nh.read=void 0;var z$e=Ig(),tse=Xie(),J$e=bM(),rse=kM(),nse=QM();function X$e(t,e,r){if(!e.stats&&J$e.IS_SUPPORT_READDIR_WITH_FILE_TYPES){ise(t,e,r);return}sse(t,e,r)}nh.read=X$e;function ise(t,e,r){e.fs.readdir(t,{withFileTypes:!0},(o,a)=>{if(o!==null){eb(r,o);return}let n=a.map(A=>({dirent:A,name:A.name,path:nse.joinPathSegments(t,A.name,e.pathSegmentSeparator)}));if(!e.followSymbolicLinks){FM(r,n);return}let u=n.map(A=>Z$e(A,e));tse(u,(A,p)=>{if(A!==null){eb(r,A);return}FM(r,p)})})}nh.readdirWithFileTypes=ise;function Z$e(t,e){return r=>{if(!t.dirent.isSymbolicLink()){r(null,t);return}e.fs.stat(t.path,(o,a)=>{if(o!==null){if(e.throwErrorOnBrokenSymbolicLink){r(o);return}r(null,t);return}t.dirent=rse.fs.createDirentFromStats(t.name,a),r(null,t)})}}function sse(t,e,r){e.fs.readdir(t,(o,a)=>{if(o!==null){eb(r,o);return}let n=a.map(u=>{let A=nse.joinPathSegments(t,u,e.pathSegmentSeparator);return p=>{z$e.stat(A,e.fsStatSettings,(h,E)=>{if(h!==null){p(h);return}let I={name:u,path:A,dirent:rse.fs.createDirentFromStats(u,E)};e.stats&&(I.stats=E),p(null,I)})}});tse(n,(u,A)=>{if(u!==null){eb(r,u);return}FM(r,A)})})}nh.readdir=sse;function eb(t,e){t(e)}function FM(t,e){t(null,e)}});var Ase=_(ih=>{"use strict";Object.defineProperty(ih,"__esModule",{value:!0});ih.readdir=ih.readdirWithFileTypes=ih.read=void 0;var $$e=Ig(),eet=bM(),ase=kM(),lse=QM();function tet(t,e){return!e.stats&&eet.IS_SUPPORT_READDIR_WITH_FILE_TYPES?cse(t,e):use(t,e)}ih.read=tet;function cse(t,e){return e.fs.readdirSync(t,{withFileTypes:!0}).map(o=>{let a={dirent:o,name:o.name,path:lse.joinPathSegments(t,o.name,e.pathSegmentSeparator)};if(a.dirent.isSymbolicLink()&&e.followSymbolicLinks)try{let n=e.fs.statSync(a.path);a.dirent=ase.fs.createDirentFromStats(a.name,n)}catch(n){if(e.throwErrorOnBrokenSymbolicLink)throw n}return a})}ih.readdirWithFileTypes=cse;function use(t,e){return e.fs.readdirSync(t).map(o=>{let a=lse.joinPathSegments(t,o,e.pathSegmentSeparator),n=$$e.statSync(a,e.fsStatSettings),u={name:o,path:a,dirent:ase.fs.createDirentFromStats(o,n)};return e.stats&&(u.stats=n),u})}ih.readdir=use});var fse=_(sh=>{"use strict";Object.defineProperty(sh,"__esModule",{value:!0});sh.createFileSystemAdapter=sh.FILE_SYSTEM_ADAPTER=void 0;var iy=ve("fs");sh.FILE_SYSTEM_ADAPTER={lstat:iy.lstat,stat:iy.stat,lstatSync:iy.lstatSync,statSync:iy.statSync,readdir:iy.readdir,readdirSync:iy.readdirSync};function ret(t){return t===void 0?sh.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},sh.FILE_SYSTEM_ADAPTER),t)}sh.createFileSystemAdapter=ret});var pse=_(TM=>{"use strict";Object.defineProperty(TM,"__esModule",{value:!0});var net=ve("path"),iet=Ig(),set=fse(),RM=class{constructor(e={}){this._options=e,this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!1),this.fs=set.createFileSystemAdapter(this._options.fs),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,net.sep),this.stats=this._getValue(this._options.stats,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0),this.fsStatSettings=new iet.Settings({followSymbolicLink:this.followSymbolicLinks,fs:this.fs,throwErrorOnBrokenSymbolicLink:this.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};TM.default=RM});var tb=_(oh=>{"use strict";Object.defineProperty(oh,"__esModule",{value:!0});oh.Settings=oh.scandirSync=oh.scandir=void 0;var hse=ose(),oet=Ase(),NM=pse();oh.Settings=NM.default;function aet(t,e,r){if(typeof e=="function"){hse.read(t,LM(),e);return}hse.read(t,LM(e),r)}oh.scandir=aet;function cet(t,e){let r=LM(e);return oet.read(t,r)}oh.scandirSync=cet;function LM(t={}){return t instanceof NM.default?t:new NM.default(t)}});var dse=_((TTt,gse)=>{"use strict";function uet(t){var e=new t,r=e;function o(){var n=e;return n.next?e=n.next:(e=new t,r=e),n.next=null,n}function a(n){r.next=n,r=n}return{get:o,release:a}}gse.exports=uet});var yse=_((NTt,MM)=>{"use strict";var Aet=dse();function mse(t,e,r){if(typeof t=="function"&&(r=e,e=t,t=null),!(r>=1))throw new Error("fastqueue concurrency must be equal to or greater than 1");var o=Aet(fet),a=null,n=null,u=0,A=null,p={push:T,drain:Wl,saturated:Wl,pause:E,paused:!1,get concurrency(){return r},set concurrency(ce){if(!(ce>=1))throw new Error("fastqueue concurrency must be equal to or greater than 1");if(r=ce,!p.paused)for(;a&&u=r||p.paused?n?(n.next=Ce,n=Ce):(a=Ce,n=Ce,p.saturated()):(u++,e.call(t,Ce.value,Ce.worked))}function L(ce,ue){var Ce=o.get();Ce.context=t,Ce.release=U,Ce.value=ce,Ce.callback=ue||Wl,Ce.errorHandler=A,u>=r||p.paused?a?(Ce.next=a,a=Ce):(a=Ce,n=Ce,p.saturated()):(u++,e.call(t,Ce.value,Ce.worked))}function U(ce){ce&&o.release(ce);var ue=a;ue&&u<=r?p.paused?u--:(n===a&&(n=null),a=ue.next,ue.next=null,e.call(t,ue.value,ue.worked),n===null&&p.empty()):--u===0&&p.drain()}function z(){a=null,n=null,p.drain=Wl}function te(){a=null,n=null,p.drain(),p.drain=Wl}function le(ce){A=ce}}function Wl(){}function fet(){this.value=null,this.callback=Wl,this.next=null,this.release=Wl,this.context=null,this.errorHandler=null;var t=this;this.worked=function(r,o){var a=t.callback,n=t.errorHandler,u=t.value;t.value=null,t.callback=Wl,t.errorHandler&&n(r,u),a.call(t.context,r,o),t.release(t)}}function pet(t,e,r){typeof t=="function"&&(r=e,e=t,t=null);function o(E,I){e.call(this,E).then(function(D){I(null,D)},I)}var a=mse(t,o,r),n=a.push,u=a.unshift;return a.push=A,a.unshift=p,a.drained=h,a;function A(E){var I=new Promise(function(D,x){n(E,function(C,T){if(C){x(C);return}D(T)})});return I.catch(Wl),I}function p(E){var I=new Promise(function(D,x){u(E,function(C,T){if(C){x(C);return}D(T)})});return I.catch(Wl),I}function h(){if(a.idle())return new Promise(function(D){D()});var E=a.drain,I=new Promise(function(D){a.drain=function(){E(),D()}});return I}}MM.exports=mse;MM.exports.promise=pet});var rb=_(eA=>{"use strict";Object.defineProperty(eA,"__esModule",{value:!0});eA.joinPathSegments=eA.replacePathSegmentSeparator=eA.isAppliedFilter=eA.isFatalError=void 0;function het(t,e){return t.errorFilter===null?!0:!t.errorFilter(e)}eA.isFatalError=het;function get(t,e){return t===null||t(e)}eA.isAppliedFilter=get;function det(t,e){return t.split(/[/\\]/).join(e)}eA.replacePathSegmentSeparator=det;function met(t,e,r){return t===""?e:t.endsWith(r)?t+e:t+r+e}eA.joinPathSegments=met});var _M=_(UM=>{"use strict";Object.defineProperty(UM,"__esModule",{value:!0});var yet=rb(),OM=class{constructor(e,r){this._root=e,this._settings=r,this._root=yet.replacePathSegmentSeparator(e,r.pathSegmentSeparator)}};UM.default=OM});var jM=_(qM=>{"use strict";Object.defineProperty(qM,"__esModule",{value:!0});var Eet=ve("events"),Cet=tb(),wet=yse(),nb=rb(),Iet=_M(),HM=class extends Iet.default{constructor(e,r){super(e,r),this._settings=r,this._scandir=Cet.scandir,this._emitter=new Eet.EventEmitter,this._queue=wet(this._worker.bind(this),this._settings.concurrency),this._isFatalError=!1,this._isDestroyed=!1,this._queue.drain=()=>{this._isFatalError||this._emitter.emit("end")}}read(){return this._isFatalError=!1,this._isDestroyed=!1,setImmediate(()=>{this._pushToQueue(this._root,this._settings.basePath)}),this._emitter}get isDestroyed(){return this._isDestroyed}destroy(){if(this._isDestroyed)throw new Error("The reader is already destroyed");this._isDestroyed=!0,this._queue.killAndDrain()}onEntry(e){this._emitter.on("entry",e)}onError(e){this._emitter.once("error",e)}onEnd(e){this._emitter.once("end",e)}_pushToQueue(e,r){let o={directory:e,base:r};this._queue.push(o,a=>{a!==null&&this._handleError(a)})}_worker(e,r){this._scandir(e.directory,this._settings.fsScandirSettings,(o,a)=>{if(o!==null){r(o,void 0);return}for(let n of a)this._handleEntry(n,e.base);r(null,void 0)})}_handleError(e){this._isDestroyed||!nb.isFatalError(this._settings,e)||(this._isFatalError=!0,this._isDestroyed=!0,this._emitter.emit("error",e))}_handleEntry(e,r){if(this._isDestroyed||this._isFatalError)return;let o=e.path;r!==void 0&&(e.path=nb.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),nb.isAppliedFilter(this._settings.entryFilter,e)&&this._emitEntry(e),e.dirent.isDirectory()&&nb.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_emitEntry(e){this._emitter.emit("entry",e)}};qM.default=HM});var Ese=_(YM=>{"use strict";Object.defineProperty(YM,"__esModule",{value:!0});var Bet=jM(),GM=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new Bet.default(this._root,this._settings),this._storage=[]}read(e){this._reader.onError(r=>{vet(e,r)}),this._reader.onEntry(r=>{this._storage.push(r)}),this._reader.onEnd(()=>{Det(e,this._storage)}),this._reader.read()}};YM.default=GM;function vet(t,e){t(e)}function Det(t,e){t(null,e)}});var Cse=_(KM=>{"use strict";Object.defineProperty(KM,"__esModule",{value:!0});var Pet=ve("stream"),bet=jM(),WM=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new bet.default(this._root,this._settings),this._stream=new Pet.Readable({objectMode:!0,read:()=>{},destroy:()=>{this._reader.isDestroyed||this._reader.destroy()}})}read(){return this._reader.onError(e=>{this._stream.emit("error",e)}),this._reader.onEntry(e=>{this._stream.push(e)}),this._reader.onEnd(()=>{this._stream.push(null)}),this._reader.read(),this._stream}};KM.default=WM});var wse=_(zM=>{"use strict";Object.defineProperty(zM,"__esModule",{value:!0});var xet=tb(),ib=rb(),ket=_M(),VM=class extends ket.default{constructor(){super(...arguments),this._scandir=xet.scandirSync,this._storage=[],this._queue=new Set}read(){return this._pushToQueue(this._root,this._settings.basePath),this._handleQueue(),this._storage}_pushToQueue(e,r){this._queue.add({directory:e,base:r})}_handleQueue(){for(let e of this._queue.values())this._handleDirectory(e.directory,e.base)}_handleDirectory(e,r){try{let o=this._scandir(e,this._settings.fsScandirSettings);for(let a of o)this._handleEntry(a,r)}catch(o){this._handleError(o)}}_handleError(e){if(ib.isFatalError(this._settings,e))throw e}_handleEntry(e,r){let o=e.path;r!==void 0&&(e.path=ib.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),ib.isAppliedFilter(this._settings.entryFilter,e)&&this._pushToStorage(e),e.dirent.isDirectory()&&ib.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_pushToStorage(e){this._storage.push(e)}};zM.default=VM});var Ise=_(XM=>{"use strict";Object.defineProperty(XM,"__esModule",{value:!0});var Qet=wse(),JM=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new Qet.default(this._root,this._settings)}read(){return this._reader.read()}};XM.default=JM});var Bse=_($M=>{"use strict";Object.defineProperty($M,"__esModule",{value:!0});var Fet=ve("path"),Ret=tb(),ZM=class{constructor(e={}){this._options=e,this.basePath=this._getValue(this._options.basePath,void 0),this.concurrency=this._getValue(this._options.concurrency,Number.POSITIVE_INFINITY),this.deepFilter=this._getValue(this._options.deepFilter,null),this.entryFilter=this._getValue(this._options.entryFilter,null),this.errorFilter=this._getValue(this._options.errorFilter,null),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,Fet.sep),this.fsScandirSettings=new Ret.Settings({followSymbolicLinks:this._options.followSymbolicLinks,fs:this._options.fs,pathSegmentSeparator:this._options.pathSegmentSeparator,stats:this._options.stats,throwErrorOnBrokenSymbolicLink:this._options.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};$M.default=ZM});var ob=_(tA=>{"use strict";Object.defineProperty(tA,"__esModule",{value:!0});tA.Settings=tA.walkStream=tA.walkSync=tA.walk=void 0;var vse=Ese(),Tet=Cse(),Net=Ise(),eO=Bse();tA.Settings=eO.default;function Let(t,e,r){if(typeof e=="function"){new vse.default(t,sb()).read(e);return}new vse.default(t,sb(e)).read(r)}tA.walk=Let;function Met(t,e){let r=sb(e);return new Net.default(t,r).read()}tA.walkSync=Met;function Oet(t,e){let r=sb(e);return new Tet.default(t,r).read()}tA.walkStream=Oet;function sb(t={}){return t instanceof eO.default?t:new eO.default(t)}});var ab=_(rO=>{"use strict";Object.defineProperty(rO,"__esModule",{value:!0});var Uet=ve("path"),_et=Ig(),Dse=Df(),tO=class{constructor(e){this._settings=e,this._fsStatSettings=new _et.Settings({followSymbolicLink:this._settings.followSymbolicLinks,fs:this._settings.fs,throwErrorOnBrokenSymbolicLink:this._settings.followSymbolicLinks})}_getFullEntryPath(e){return Uet.resolve(this._settings.cwd,e)}_makeEntry(e,r){let o={name:r,path:r,dirent:Dse.fs.createDirentFromStats(r,e)};return this._settings.stats&&(o.stats=e),o}_isFatalError(e){return!Dse.errno.isEnoentCodeError(e)&&!this._settings.suppressErrors}};rO.default=tO});var sO=_(iO=>{"use strict";Object.defineProperty(iO,"__esModule",{value:!0});var Het=ve("stream"),qet=Ig(),jet=ob(),Get=ab(),nO=class extends Get.default{constructor(){super(...arguments),this._walkStream=jet.walkStream,this._stat=qet.stat}dynamic(e,r){return this._walkStream(e,r)}static(e,r){let o=e.map(this._getFullEntryPath,this),a=new Het.PassThrough({objectMode:!0});a._write=(n,u,A)=>this._getEntry(o[n],e[n],r).then(p=>{p!==null&&r.entryFilter(p)&&a.push(p),n===o.length-1&&a.end(),A()}).catch(A);for(let n=0;nthis._makeEntry(a,r)).catch(a=>{if(o.errorFilter(a))return null;throw a})}_getStat(e){return new Promise((r,o)=>{this._stat(e,this._fsStatSettings,(a,n)=>a===null?r(n):o(a))})}};iO.default=nO});var Pse=_(aO=>{"use strict";Object.defineProperty(aO,"__esModule",{value:!0});var Yet=ob(),Wet=ab(),Ket=sO(),oO=class extends Wet.default{constructor(){super(...arguments),this._walkAsync=Yet.walk,this._readerStream=new Ket.default(this._settings)}dynamic(e,r){return new Promise((o,a)=>{this._walkAsync(e,r,(n,u)=>{n===null?o(u):a(n)})})}async static(e,r){let o=[],a=this._readerStream.static(e,r);return new Promise((n,u)=>{a.once("error",u),a.on("data",A=>o.push(A)),a.once("end",()=>n(o))})}};aO.default=oO});var Sse=_(cO=>{"use strict";Object.defineProperty(cO,"__esModule",{value:!0});var m1=Df(),lO=class{constructor(e,r,o){this._patterns=e,this._settings=r,this._micromatchOptions=o,this._storage=[],this._fillStorage()}_fillStorage(){for(let e of this._patterns){let r=this._getPatternSegments(e),o=this._splitSegmentsIntoSections(r);this._storage.push({complete:o.length<=1,pattern:e,segments:r,sections:o})}}_getPatternSegments(e){return m1.pattern.getPatternParts(e,this._micromatchOptions).map(o=>m1.pattern.isDynamicPattern(o,this._settings)?{dynamic:!0,pattern:o,patternRe:m1.pattern.makeRe(o,this._micromatchOptions)}:{dynamic:!1,pattern:o})}_splitSegmentsIntoSections(e){return m1.array.splitWhen(e,r=>r.dynamic&&m1.pattern.hasGlobStar(r.pattern))}};cO.default=lO});var bse=_(AO=>{"use strict";Object.defineProperty(AO,"__esModule",{value:!0});var Vet=Sse(),uO=class extends Vet.default{match(e){let r=e.split("/"),o=r.length,a=this._storage.filter(n=>!n.complete||n.segments.length>o);for(let n of a){let u=n.sections[0];if(!n.complete&&o>u.length||r.every((p,h)=>{let E=n.segments[h];return!!(E.dynamic&&E.patternRe.test(p)||!E.dynamic&&E.pattern===p)}))return!0}return!1}};AO.default=uO});var xse=_(pO=>{"use strict";Object.defineProperty(pO,"__esModule",{value:!0});var lb=Df(),zet=bse(),fO=class{constructor(e,r){this._settings=e,this._micromatchOptions=r}getFilter(e,r,o){let a=this._getMatcher(r),n=this._getNegativePatternsRe(o);return u=>this._filter(e,u,a,n)}_getMatcher(e){return new zet.default(e,this._settings,this._micromatchOptions)}_getNegativePatternsRe(e){let r=e.filter(lb.pattern.isAffectDepthOfReadingPattern);return lb.pattern.convertPatternsToRe(r,this._micromatchOptions)}_filter(e,r,o,a){if(this._isSkippedByDeep(e,r.path)||this._isSkippedSymbolicLink(r))return!1;let n=lb.path.removeLeadingDotSegment(r.path);return this._isSkippedByPositivePatterns(n,o)?!1:this._isSkippedByNegativePatterns(n,a)}_isSkippedByDeep(e,r){return this._settings.deep===1/0?!1:this._getEntryLevel(e,r)>=this._settings.deep}_getEntryLevel(e,r){let o=r.split("/").length;if(e==="")return o;let a=e.split("/").length;return o-a}_isSkippedSymbolicLink(e){return!this._settings.followSymbolicLinks&&e.dirent.isSymbolicLink()}_isSkippedByPositivePatterns(e,r){return!this._settings.baseNameMatch&&!r.match(e)}_isSkippedByNegativePatterns(e,r){return!lb.pattern.matchAny(e,r)}};pO.default=fO});var kse=_(gO=>{"use strict";Object.defineProperty(gO,"__esModule",{value:!0});var Bg=Df(),hO=class{constructor(e,r){this._settings=e,this._micromatchOptions=r,this.index=new Map}getFilter(e,r){let o=Bg.pattern.convertPatternsToRe(e,this._micromatchOptions),a=Bg.pattern.convertPatternsToRe(r,Object.assign(Object.assign({},this._micromatchOptions),{dot:!0}));return n=>this._filter(n,o,a)}_filter(e,r,o){let a=Bg.path.removeLeadingDotSegment(e.path);if(this._settings.unique&&this._isDuplicateEntry(a)||this._onlyFileFilter(e)||this._onlyDirectoryFilter(e)||this._isSkippedByAbsoluteNegativePatterns(a,o))return!1;let n=e.dirent.isDirectory(),u=this._isMatchToPatterns(a,r,n)&&!this._isMatchToPatterns(a,o,n);return this._settings.unique&&u&&this._createIndexRecord(a),u}_isDuplicateEntry(e){return this.index.has(e)}_createIndexRecord(e){this.index.set(e,void 0)}_onlyFileFilter(e){return this._settings.onlyFiles&&!e.dirent.isFile()}_onlyDirectoryFilter(e){return this._settings.onlyDirectories&&!e.dirent.isDirectory()}_isSkippedByAbsoluteNegativePatterns(e,r){if(!this._settings.absolute)return!1;let o=Bg.path.makeAbsolute(this._settings.cwd,e);return Bg.pattern.matchAny(o,r)}_isMatchToPatterns(e,r,o){let a=Bg.pattern.matchAny(e,r);return!a&&o?Bg.pattern.matchAny(e+"/",r):a}};gO.default=hO});var Qse=_(mO=>{"use strict";Object.defineProperty(mO,"__esModule",{value:!0});var Jet=Df(),dO=class{constructor(e){this._settings=e}getFilter(){return e=>this._isNonFatalError(e)}_isNonFatalError(e){return Jet.errno.isEnoentCodeError(e)||this._settings.suppressErrors}};mO.default=dO});var Rse=_(EO=>{"use strict";Object.defineProperty(EO,"__esModule",{value:!0});var Fse=Df(),yO=class{constructor(e){this._settings=e}getTransformer(){return e=>this._transform(e)}_transform(e){let r=e.path;return this._settings.absolute&&(r=Fse.path.makeAbsolute(this._settings.cwd,r),r=Fse.path.unixify(r)),this._settings.markDirectories&&e.dirent.isDirectory()&&(r+="/"),this._settings.objectMode?Object.assign(Object.assign({},e),{path:r}):r}};EO.default=yO});var ub=_(wO=>{"use strict";Object.defineProperty(wO,"__esModule",{value:!0});var Xet=ve("path"),Zet=xse(),$et=kse(),ett=Qse(),ttt=Rse(),CO=class{constructor(e){this._settings=e,this.errorFilter=new ett.default(this._settings),this.entryFilter=new $et.default(this._settings,this._getMicromatchOptions()),this.deepFilter=new Zet.default(this._settings,this._getMicromatchOptions()),this.entryTransformer=new ttt.default(this._settings)}_getRootDirectory(e){return Xet.resolve(this._settings.cwd,e.base)}_getReaderOptions(e){let r=e.base==="."?"":e.base;return{basePath:r,pathSegmentSeparator:"/",concurrency:this._settings.concurrency,deepFilter:this.deepFilter.getFilter(r,e.positive,e.negative),entryFilter:this.entryFilter.getFilter(e.positive,e.negative),errorFilter:this.errorFilter.getFilter(),followSymbolicLinks:this._settings.followSymbolicLinks,fs:this._settings.fs,stats:this._settings.stats,throwErrorOnBrokenSymbolicLink:this._settings.throwErrorOnBrokenSymbolicLink,transform:this.entryTransformer.getTransformer()}}_getMicromatchOptions(){return{dot:this._settings.dot,matchBase:this._settings.baseNameMatch,nobrace:!this._settings.braceExpansion,nocase:!this._settings.caseSensitiveMatch,noext:!this._settings.extglob,noglobstar:!this._settings.globstar,posix:!0,strictSlashes:!1}}};wO.default=CO});var Tse=_(BO=>{"use strict";Object.defineProperty(BO,"__esModule",{value:!0});var rtt=Pse(),ntt=ub(),IO=class extends ntt.default{constructor(){super(...arguments),this._reader=new rtt.default(this._settings)}async read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return(await this.api(r,e,o)).map(n=>o.transform(n))}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};BO.default=IO});var Nse=_(DO=>{"use strict";Object.defineProperty(DO,"__esModule",{value:!0});var itt=ve("stream"),stt=sO(),ott=ub(),vO=class extends ott.default{constructor(){super(...arguments),this._reader=new stt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e),a=this.api(r,e,o),n=new itt.Readable({objectMode:!0,read:()=>{}});return a.once("error",u=>n.emit("error",u)).on("data",u=>n.emit("data",o.transform(u))).once("end",()=>n.emit("end")),n.once("close",()=>a.destroy()),n}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};DO.default=vO});var Lse=_(SO=>{"use strict";Object.defineProperty(SO,"__esModule",{value:!0});var att=Ig(),ltt=ob(),ctt=ab(),PO=class extends ctt.default{constructor(){super(...arguments),this._walkSync=ltt.walkSync,this._statSync=att.statSync}dynamic(e,r){return this._walkSync(e,r)}static(e,r){let o=[];for(let a of e){let n=this._getFullEntryPath(a),u=this._getEntry(n,a,r);u===null||!r.entryFilter(u)||o.push(u)}return o}_getEntry(e,r,o){try{let a=this._getStat(e);return this._makeEntry(a,r)}catch(a){if(o.errorFilter(a))return null;throw a}}_getStat(e){return this._statSync(e,this._fsStatSettings)}};SO.default=PO});var Mse=_(xO=>{"use strict";Object.defineProperty(xO,"__esModule",{value:!0});var utt=Lse(),Att=ub(),bO=class extends Att.default{constructor(){super(...arguments),this._reader=new utt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return this.api(r,e,o).map(o.transform)}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};xO.default=bO});var Ose=_(oy=>{"use strict";Object.defineProperty(oy,"__esModule",{value:!0});oy.DEFAULT_FILE_SYSTEM_ADAPTER=void 0;var sy=ve("fs"),ftt=ve("os"),ptt=Math.max(ftt.cpus().length,1);oy.DEFAULT_FILE_SYSTEM_ADAPTER={lstat:sy.lstat,lstatSync:sy.lstatSync,stat:sy.stat,statSync:sy.statSync,readdir:sy.readdir,readdirSync:sy.readdirSync};var kO=class{constructor(e={}){this._options=e,this.absolute=this._getValue(this._options.absolute,!1),this.baseNameMatch=this._getValue(this._options.baseNameMatch,!1),this.braceExpansion=this._getValue(this._options.braceExpansion,!0),this.caseSensitiveMatch=this._getValue(this._options.caseSensitiveMatch,!0),this.concurrency=this._getValue(this._options.concurrency,ptt),this.cwd=this._getValue(this._options.cwd,process.cwd()),this.deep=this._getValue(this._options.deep,1/0),this.dot=this._getValue(this._options.dot,!1),this.extglob=this._getValue(this._options.extglob,!0),this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!0),this.fs=this._getFileSystemMethods(this._options.fs),this.globstar=this._getValue(this._options.globstar,!0),this.ignore=this._getValue(this._options.ignore,[]),this.markDirectories=this._getValue(this._options.markDirectories,!1),this.objectMode=this._getValue(this._options.objectMode,!1),this.onlyDirectories=this._getValue(this._options.onlyDirectories,!1),this.onlyFiles=this._getValue(this._options.onlyFiles,!0),this.stats=this._getValue(this._options.stats,!1),this.suppressErrors=this._getValue(this._options.suppressErrors,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!1),this.unique=this._getValue(this._options.unique,!0),this.onlyDirectories&&(this.onlyFiles=!1),this.stats&&(this.objectMode=!0),this.ignore=[].concat(this.ignore)}_getValue(e,r){return e===void 0?r:e}_getFileSystemMethods(e={}){return Object.assign(Object.assign({},oy.DEFAULT_FILE_SYSTEM_ADAPTER),e)}};oy.default=kO});var Ab=_((oNt,_se)=>{"use strict";var Use=_ie(),htt=Tse(),gtt=Nse(),dtt=Mse(),QO=Ose(),Kl=Df();async function FO(t,e){Vc(t);let r=RO(t,htt.default,e),o=await Promise.all(r);return Kl.array.flatten(o)}(function(t){t.glob=t,t.globSync=e,t.globStream=r,t.async=t;function e(h,E){Vc(h);let I=RO(h,dtt.default,E);return Kl.array.flatten(I)}t.sync=e;function r(h,E){Vc(h);let I=RO(h,gtt.default,E);return Kl.stream.merge(I)}t.stream=r;function o(h,E){Vc(h);let I=[].concat(h),D=new QO.default(E);return Use.generate(I,D)}t.generateTasks=o;function a(h,E){Vc(h);let I=new QO.default(E);return Kl.pattern.isDynamicPattern(h,I)}t.isDynamicPattern=a;function n(h){return Vc(h),Kl.path.escape(h)}t.escapePath=n;function u(h){return Vc(h),Kl.path.convertPathToPattern(h)}t.convertPathToPattern=u;let A;(function(h){function E(D){return Vc(D),Kl.path.escapePosixPath(D)}h.escapePath=E;function I(D){return Vc(D),Kl.path.convertPosixPathToPattern(D)}h.convertPathToPattern=I})(A=t.posix||(t.posix={}));let p;(function(h){function E(D){return Vc(D),Kl.path.escapeWindowsPath(D)}h.escapePath=E;function I(D){return Vc(D),Kl.path.convertWindowsPathToPattern(D)}h.convertPathToPattern=I})(p=t.win32||(t.win32={}))})(FO||(FO={}));function RO(t,e,r){let o=[].concat(t),a=new QO.default(r),n=Use.generate(o,a),u=new e(a);return n.map(u.read,u)}function Vc(t){if(![].concat(t).every(o=>Kl.string.isString(o)&&!Kl.string.isEmpty(o)))throw new TypeError("Patterns must be a string (non empty) or an array of strings")}_se.exports=FO});var xn={};Kt(xn,{checksumFile:()=>pb,checksumPattern:()=>hb,makeHash:()=>zi});function zi(...t){let e=(0,fb.createHash)("sha512"),r="";for(let o of t)typeof o=="string"?r+=o:o&&(r&&(e.update(r),r=""),e.update(o));return r&&e.update(r),e.digest("hex")}async function pb(t,{baseFs:e,algorithm:r}={baseFs:ae,algorithm:"sha512"}){let o=await e.openPromise(t,"r");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,fb.createHash)(r),A=0;for(;(A=await e.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest("hex")}finally{await e.closePromise(o)}}async function hb(t,{cwd:e}){let o=(await(0,TO.default)(t,{cwd:Ae.fromPortablePath(e),onlyDirectories:!0})).map(A=>`${A}/**/*`),a=await(0,TO.default)([t,...o],{cwd:Ae.fromPortablePath(e),onlyFiles:!1});a.sort();let n=await Promise.all(a.map(async A=>{let p=[Buffer.from(A)],h=K.join(e,Ae.toPortablePath(A)),E=await ae.lstatPromise(h);return E.isSymbolicLink()?p.push(Buffer.from(await ae.readlinkPromise(h))):E.isFile()&&p.push(await ae.readFilePromise(h)),p.join("\0")})),u=(0,fb.createHash)("sha512");for(let A of n)u.update(A);return u.digest("hex")}var fb,TO,ah=wt(()=>{Pt();fb=ve("crypto"),TO=et(Ab())});var G={};Kt(G,{allPeerRequests:()=>S1,areDescriptorsEqual:()=>Yse,areIdentsEqual:()=>I1,areLocatorsEqual:()=>B1,areVirtualPackagesEquivalent:()=>Dtt,bindDescriptor:()=>Btt,bindLocator:()=>vtt,convertDescriptorToLocator:()=>gb,convertLocatorToDescriptor:()=>LO,convertPackageToLocator:()=>Ctt,convertToIdent:()=>Ett,convertToManifestRange:()=>Ntt,copyPackage:()=>E1,devirtualizeDescriptor:()=>C1,devirtualizeLocator:()=>w1,ensureDevirtualizedDescriptor:()=>wtt,ensureDevirtualizedLocator:()=>Itt,getIdentVendorPath:()=>_O,isPackageCompatible:()=>Cb,isVirtualDescriptor:()=>Pf,isVirtualLocator:()=>zc,makeDescriptor:()=>kn,makeIdent:()=>rA,makeLocator:()=>Ss,makeRange:()=>yb,parseDescriptor:()=>lh,parseFileStyleRange:()=>Rtt,parseIdent:()=>Zo,parseLocator:()=>Sf,parseRange:()=>vg,prettyDependent:()=>fM,prettyDescriptor:()=>zn,prettyIdent:()=>Ui,prettyLocator:()=>jr,prettyLocatorNoColors:()=>AM,prettyRange:()=>cy,prettyReference:()=>D1,prettyResolution:()=>d1,prettyWorkspace:()=>P1,renamePackage:()=>MO,slugifyIdent:()=>NO,slugifyLocator:()=>ly,sortDescriptors:()=>uy,stringifyDescriptor:()=>ka,stringifyIdent:()=>rn,stringifyLocator:()=>Qa,tryParseDescriptor:()=>v1,tryParseIdent:()=>Wse,tryParseLocator:()=>mb,tryParseRange:()=>Ftt,virtualizeDescriptor:()=>OO,virtualizePackage:()=>UO});function rA(t,e){if(t?.startsWith("@"))throw new Error("Invalid scope: don't prefix it with '@'");return{identHash:zi(t,e),scope:t,name:e}}function kn(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:zi(t.identHash,e),range:e}}function Ss(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:zi(t.identHash,e),reference:e}}function Ett(t){return{identHash:t.identHash,scope:t.scope,name:t.name}}function gb(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.descriptorHash,reference:t.range}}function LO(t){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:t.locatorHash,range:t.reference}}function Ctt(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.locatorHash,reference:t.reference}}function MO(t,e){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:e.locatorHash,reference:e.reference,version:t.version,languageName:t.languageName,linkType:t.linkType,conditions:t.conditions,dependencies:new Map(t.dependencies),peerDependencies:new Map(t.peerDependencies),dependenciesMeta:new Map(t.dependenciesMeta),peerDependenciesMeta:new Map(t.peerDependenciesMeta),bin:new Map(t.bin)}}function E1(t){return MO(t,t)}function OO(t,e){if(e.includes("#"))throw new Error("Invalid entropy");return kn(t,`virtual:${e}#${t.range}`)}function UO(t,e){if(e.includes("#"))throw new Error("Invalid entropy");return MO(t,Ss(t,`virtual:${e}#${t.reference}`))}function Pf(t){return t.range.startsWith(y1)}function zc(t){return t.reference.startsWith(y1)}function C1(t){if(!Pf(t))throw new Error("Not a virtual descriptor");return kn(t,t.range.replace(db,""))}function w1(t){if(!zc(t))throw new Error("Not a virtual descriptor");return Ss(t,t.reference.replace(db,""))}function wtt(t){return Pf(t)?kn(t,t.range.replace(db,"")):t}function Itt(t){return zc(t)?Ss(t,t.reference.replace(db,"")):t}function Btt(t,e){return t.range.includes("::")?t:kn(t,`${t.range}::${ay.default.stringify(e)}`)}function vtt(t,e){return t.reference.includes("::")?t:Ss(t,`${t.reference}::${ay.default.stringify(e)}`)}function I1(t,e){return t.identHash===e.identHash}function Yse(t,e){return t.descriptorHash===e.descriptorHash}function B1(t,e){return t.locatorHash===e.locatorHash}function Dtt(t,e){if(!zc(t))throw new Error("Invalid package type");if(!zc(e))throw new Error("Invalid package type");if(!I1(t,e)||t.dependencies.size!==e.dependencies.size)return!1;for(let r of t.dependencies.values()){let o=e.dependencies.get(r.identHash);if(!o||!Yse(r,o))return!1}return!0}function Zo(t){let e=Wse(t);if(!e)throw new Error(`Invalid ident (${t})`);return e}function Wse(t){let e=t.match(Ptt);if(!e)return null;let[,r,o]=e;return rA(typeof r<"u"?r:null,o)}function lh(t,e=!1){let r=v1(t,e);if(!r)throw new Error(`Invalid descriptor (${t})`);return r}function v1(t,e=!1){let r=e?t.match(Stt):t.match(btt);if(!r)return null;let[,o,a,n]=r;if(n==="unknown")throw new Error(`Invalid range (${t})`);let u=typeof o<"u"?o:null,A=typeof n<"u"?n:"unknown";return kn(rA(u,a),A)}function Sf(t,e=!1){let r=mb(t,e);if(!r)throw new Error(`Invalid locator (${t})`);return r}function mb(t,e=!1){let r=e?t.match(xtt):t.match(ktt);if(!r)return null;let[,o,a,n]=r;if(n==="unknown")throw new Error(`Invalid reference (${t})`);let u=typeof o<"u"?o:null,A=typeof n<"u"?n:"unknown";return Ss(rA(u,a),A)}function vg(t,e){let r=t.match(Qtt);if(r===null)throw new Error(`Invalid range (${t})`);let o=typeof r[1]<"u"?r[1]:null;if(typeof e?.requireProtocol=="string"&&o!==e.requireProtocol)throw new Error(`Invalid protocol (${o})`);if(e?.requireProtocol&&o===null)throw new Error(`Missing protocol (${o})`);let a=typeof r[3]<"u"?decodeURIComponent(r[2]):null;if(e?.requireSource&&a===null)throw new Error(`Missing source (${t})`);let n=typeof r[3]<"u"?decodeURIComponent(r[3]):decodeURIComponent(r[2]),u=e?.parseSelector?ay.default.parse(n):n,A=typeof r[4]<"u"?ay.default.parse(r[4]):null;return{protocol:o,source:a,selector:u,params:A}}function Ftt(t,e){try{return vg(t,e)}catch{return null}}function Rtt(t,{protocol:e}){let{selector:r,params:o}=vg(t,{requireProtocol:e,requireBindings:!0});if(typeof o.locator!="string")throw new Error(`Assertion failed: Invalid bindings for ${t}`);return{parentLocator:Sf(o.locator,!0),path:r}}function Hse(t){return t=t.replaceAll("%","%25"),t=t.replaceAll(":","%3A"),t=t.replaceAll("#","%23"),t}function Ttt(t){return t===null?!1:Object.entries(t).length>0}function yb({protocol:t,source:e,selector:r,params:o}){let a="";return t!==null&&(a+=`${t}`),e!==null&&(a+=`${Hse(e)}#`),a+=Hse(r),Ttt(o)&&(a+=`::${ay.default.stringify(o)}`),a}function Ntt(t){let{params:e,protocol:r,source:o,selector:a}=vg(t);for(let n in e)n.startsWith("__")&&delete e[n];return yb({protocol:r,source:o,params:e,selector:a})}function rn(t){return t.scope?`@${t.scope}/${t.name}`:`${t.name}`}function ka(t){return t.scope?`@${t.scope}/${t.name}@${t.range}`:`${t.name}@${t.range}`}function Qa(t){return t.scope?`@${t.scope}/${t.name}@${t.reference}`:`${t.name}@${t.reference}`}function NO(t){return t.scope!==null?`@${t.scope}-${t.name}`:t.name}function ly(t){let{protocol:e,selector:r}=vg(t.reference),o=e!==null?e.replace(Ltt,""):"exotic",a=qse.default.valid(r),n=a!==null?`${o}-${a}`:`${o}`,u=10;return t.scope?`${NO(t)}-${n}-${t.locatorHash.slice(0,u)}`:`${NO(t)}-${n}-${t.locatorHash.slice(0,u)}`}function Ui(t,e){return e.scope?`${Ut(t,`@${e.scope}/`,Ct.SCOPE)}${Ut(t,e.name,Ct.NAME)}`:`${Ut(t,e.name,Ct.NAME)}`}function Eb(t){if(t.startsWith(y1)){let e=Eb(t.substring(t.indexOf("#")+1)),r=t.substring(y1.length,y1.length+mtt);return`${e} [${r}]`}else return t.replace(Mtt,"?[...]")}function cy(t,e){return`${Ut(t,Eb(e),Ct.RANGE)}`}function zn(t,e){return`${Ui(t,e)}${Ut(t,"@",Ct.RANGE)}${cy(t,e.range)}`}function D1(t,e){return`${Ut(t,Eb(e),Ct.REFERENCE)}`}function jr(t,e){return`${Ui(t,e)}${Ut(t,"@",Ct.REFERENCE)}${D1(t,e.reference)}`}function AM(t){return`${rn(t)}@${Eb(t.reference)}`}function uy(t){return Ps(t,[e=>rn(e),e=>e.range])}function P1(t,e){return Ui(t,e.anchoredLocator)}function d1(t,e,r){let o=Pf(e)?C1(e):e;return r===null?`${zn(t,o)} \u2192 ${uM(t).Cross}`:o.identHash===r.identHash?`${zn(t,o)} \u2192 ${D1(t,r.reference)}`:`${zn(t,o)} \u2192 ${jr(t,r)}`}function fM(t,e,r){return r===null?`${jr(t,e)}`:`${jr(t,e)} (via ${cy(t,r.range)})`}function _O(t){return`node_modules/${rn(t)}`}function Cb(t,e){return t.conditions?ytt(t.conditions,r=>{let[,o,a]=r.match(Gse),n=e[o];return n?n.includes(a):!0}):!0}function S1(t){let e=new Set;if("children"in t)e.add(t);else for(let r of t.requests.values())e.add(r);for(let r of e)for(let o of r.children.values())e.add(o);return e}var ay,qse,jse,y1,mtt,Gse,ytt,db,Ptt,Stt,btt,xtt,ktt,Qtt,Ltt,Mtt,wo=wt(()=>{ay=et(ve("querystring")),qse=et(ni()),jse=et(OX());Yl();ah();Gl();wo();y1="virtual:",mtt=5,Gse=/(os|cpu|libc)=([a-z0-9_-]+)/,ytt=(0,jse.makeParser)(Gse);db=/^[^#]*#/;Ptt=/^(?:@([^/]+?)\/)?([^@/]+)$/;Stt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))$/,btt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))?$/;xtt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))$/,ktt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))?$/;Qtt=/^([^#:]*:)?((?:(?!::)[^#])*)(?:#((?:(?!::).)*))?(?:::(.*))?$/;Ltt=/:$/;Mtt=/\?.*/});var Kse,Vse=wt(()=>{wo();Kse={hooks:{reduceDependency:(t,e,r,o,{resolver:a,resolveOptions:n})=>{for(let{pattern:u,reference:A}of e.topLevelWorkspace.manifest.resolutions){if(u.from&&(u.from.fullName!==rn(r)||e.configuration.normalizeLocator(Ss(Zo(u.from.fullName),u.from.description??r.reference)).locatorHash!==r.locatorHash)||u.descriptor.fullName!==rn(t)||e.configuration.normalizeDependency(kn(Sf(u.descriptor.fullName),u.descriptor.description??t.range)).descriptorHash!==t.descriptorHash)continue;return a.bindDescriptor(e.configuration.normalizeDependency(kn(t,A)),e.topLevelWorkspace.anchoredLocator,n)}return t},validateProject:async(t,e)=>{for(let r of t.workspaces){let o=P1(t.configuration,r);await t.configuration.triggerHook(a=>a.validateWorkspace,r,{reportWarning:(a,n)=>e.reportWarning(a,`${o}: ${n}`),reportError:(a,n)=>e.reportError(a,`${o}: ${n}`)})}},validateWorkspace:async(t,e)=>{let{manifest:r}=t;r.resolutions.length&&t.cwd!==t.project.cwd&&r.errors.push(new Error("Resolutions field will be ignored"));for(let o of r.errors)e.reportWarning(57,o.message)}}}});var ci,Dg=wt(()=>{ci=class t{static{this.protocol="workspace:"}supportsDescriptor(e,r){return!!(e.range.startsWith(t.protocol)||r.project.tryWorkspaceByDescriptor(e)!==null)}supportsLocator(e,r){return!!e.reference.startsWith(t.protocol)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[o.project.getWorkspaceByDescriptor(e).anchoredLocator]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.getWorkspaceByCwd(e.reference.slice(t.protocol.length));return{...e,version:o.manifest.version||"0.0.0",languageName:"unknown",linkType:"SOFT",conditions:null,dependencies:r.project.configuration.normalizeDependencyMap(new Map([...o.manifest.dependencies,...o.manifest.devDependencies])),peerDependencies:new Map([...o.manifest.peerDependencies]),dependenciesMeta:o.manifest.dependenciesMeta,peerDependenciesMeta:o.manifest.peerDependenciesMeta,bin:o.manifest.bin}}}});var Ur={};Kt(Ur,{SemVer:()=>$se.SemVer,clean:()=>Utt,getComparator:()=>Xse,mergeComparators:()=>HO,satisfiesWithPrereleases:()=>nA,simplifyRanges:()=>qO,stringifyComparator:()=>Zse,validRange:()=>Fa});function nA(t,e,r=!1){if(!t)return!1;let o=`${e}${r}`,a=zse.get(o);if(typeof a>"u")try{a=new bf.default.Range(e,{includePrerelease:!0,loose:r})}catch{return!1}finally{zse.set(o,a||null)}else if(a===null)return!1;let n;try{n=new bf.default.SemVer(t,a)}catch{return!1}return a.test(n)?!0:(n.prerelease&&(n.prerelease=[]),a.set.some(u=>{for(let A of u)A.semver.prerelease&&(A.semver.prerelease=[]);return u.every(A=>A.test(n))}))}function Fa(t){if(t.indexOf(":")!==-1)return null;let e=Jse.get(t);if(typeof e<"u")return e;try{e=new bf.default.Range(t)}catch{e=null}return Jse.set(t,e),e}function Utt(t){let e=Ott.exec(t);return e?e[1]:null}function Xse(t){if(t.semver===bf.default.Comparator.ANY)return{gt:null,lt:null};switch(t.operator){case"":return{gt:[">=",t.semver],lt:["<=",t.semver]};case">":case">=":return{gt:[t.operator,t.semver],lt:null};case"<":case"<=":return{gt:null,lt:[t.operator,t.semver]};default:throw new Error(`Assertion failed: Unexpected comparator operator (${t.operator})`)}}function HO(t){if(t.length===0)return null;let e=null,r=null;for(let o of t){if(o.gt){let a=e!==null?bf.default.compare(o.gt[1],e[1]):null;(a===null||a>0||a===0&&o.gt[0]===">")&&(e=o.gt)}if(o.lt){let a=r!==null?bf.default.compare(o.lt[1],r[1]):null;(a===null||a<0||a===0&&o.lt[0]==="<")&&(r=o.lt)}}if(e&&r){let o=bf.default.compare(e[1],r[1]);if(o===0&&(e[0]===">"||r[0]==="<")||o>0)return null}return{gt:e,lt:r}}function Zse(t){if(t.gt&&t.lt){if(t.gt[0]===">="&&t.lt[0]==="<="&&t.gt[1].version===t.lt[1].version)return t.gt[1].version;if(t.gt[0]===">="&&t.lt[0]==="<"){if(t.lt[1].version===`${t.gt[1].major+1}.0.0-0`)return`^${t.gt[1].version}`;if(t.lt[1].version===`${t.gt[1].major}.${t.gt[1].minor+1}.0-0`)return`~${t.gt[1].version}`}}let e=[];return t.gt&&e.push(t.gt[0]+t.gt[1].version),t.lt&&e.push(t.lt[0]+t.lt[1].version),e.length?e.join(" "):"*"}function qO(t){let e=t.map(_tt).map(o=>Fa(o).set.map(a=>a.map(n=>Xse(n)))),r=e.shift().map(o=>HO(o)).filter(o=>o!==null);for(let o of e){let a=[];for(let n of r)for(let u of o){let A=HO([n,...u]);A!==null&&a.push(A)}r=a}return r.length===0?null:r.map(o=>Zse(o)).join(" || ")}function _tt(t){let e=t.split("||");if(e.length>1){let r=new Set;for(let o of e)e.some(a=>a!==o&&bf.default.subset(o,a))||r.add(o);if(r.size{bf=et(ni()),$se=et(ni()),zse=new Map;Jse=new Map;Ott=/^(?:[\sv=]*?)((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\s*)$/});function eoe(t){let e=t.match(/^[ \t]+/m);return e?e[0]:" "}function toe(t){return t.charCodeAt(0)===65279?t.slice(1):t}function $o(t){return t.replace(/\\/g,"/")}function wb(t,{yamlCompatibilityMode:e}){return e?nM(t):typeof t>"u"||typeof t=="boolean"?t:null}function roe(t,e){let r=e.search(/[^!]/);if(r===-1)return"invalid";let o=r%2===0?"":"!",a=e.slice(r);return`${o}${t}=${a}`}function jO(t,e){return e.length===1?roe(t,e[0]):`(${e.map(r=>roe(t,r)).join(" | ")})`}var noe,_t,Ay=wt(()=>{Pt();Ml();noe=et(ni());Dg();Gl();xf();wo();_t=class t{constructor(){this.indent=" ";this.name=null;this.version=null;this.os=null;this.cpu=null;this.libc=null;this.type=null;this.packageManager=null;this.private=!1;this.license=null;this.main=null;this.module=null;this.browser=null;this.languageName=null;this.bin=new Map;this.scripts=new Map;this.dependencies=new Map;this.devDependencies=new Map;this.peerDependencies=new Map;this.workspaceDefinitions=[];this.dependenciesMeta=new Map;this.peerDependenciesMeta=new Map;this.resolutions=[];this.files=null;this.publishConfig=null;this.installConfig=null;this.preferUnplugged=null;this.raw={};this.errors=[]}static{this.fileName="package.json"}static{this.allDependencies=["dependencies","devDependencies","peerDependencies"]}static{this.hardDependencies=["dependencies","devDependencies"]}static async tryFind(e,{baseFs:r=new _n}={}){let o=K.join(e,"package.json");try{return await t.fromFile(o,{baseFs:r})}catch(a){if(a.code==="ENOENT")return null;throw a}}static async find(e,{baseFs:r}={}){let o=await t.tryFind(e,{baseFs:r});if(o===null)throw new Error("Manifest not found");return o}static async fromFile(e,{baseFs:r=new _n}={}){let o=new t;return await o.loadFile(e,{baseFs:r}),o}static fromText(e){let r=new t;return r.loadFromText(e),r}loadFromText(e){let r;try{r=JSON.parse(toe(e)||"{}")}catch(o){throw o.message+=` (when parsing ${e})`,o}this.load(r),this.indent=eoe(e)}async loadFile(e,{baseFs:r=new _n}){let o=await r.readFilePromise(e,"utf8"),a;try{a=JSON.parse(toe(o)||"{}")}catch(n){throw n.message+=` (when parsing ${e})`,n}this.load(a),this.indent=eoe(o)}load(e,{yamlCompatibilityMode:r=!1}={}){if(typeof e!="object"||e===null)throw new Error(`Utterly invalid manifest data (${e})`);this.raw=e;let o=[];if(this.name=null,typeof e.name=="string")try{this.name=Zo(e.name)}catch{o.push(new Error("Parsing failed for the 'name' field"))}if(typeof e.version=="string"?this.version=e.version:this.version=null,Array.isArray(e.os)){let n=[];this.os=n;for(let u of e.os)typeof u!="string"?o.push(new Error("Parsing failed for the 'os' field")):n.push(u)}else this.os=null;if(Array.isArray(e.cpu)){let n=[];this.cpu=n;for(let u of e.cpu)typeof u!="string"?o.push(new Error("Parsing failed for the 'cpu' field")):n.push(u)}else this.cpu=null;if(Array.isArray(e.libc)){let n=[];this.libc=n;for(let u of e.libc)typeof u!="string"?o.push(new Error("Parsing failed for the 'libc' field")):n.push(u)}else this.libc=null;if(typeof e.type=="string"?this.type=e.type:this.type=null,typeof e.packageManager=="string"?this.packageManager=e.packageManager:this.packageManager=null,typeof e.private=="boolean"?this.private=e.private:this.private=!1,typeof e.license=="string"?this.license=e.license:this.license=null,typeof e.languageName=="string"?this.languageName=e.languageName:this.languageName=null,typeof e.main=="string"?this.main=$o(e.main):this.main=null,typeof e.module=="string"?this.module=$o(e.module):this.module=null,e.browser!=null)if(typeof e.browser=="string")this.browser=$o(e.browser);else{this.browser=new Map;for(let[n,u]of Object.entries(e.browser))this.browser.set($o(n),typeof u=="string"?$o(u):u)}else this.browser=null;if(this.bin=new Map,typeof e.bin=="string")e.bin.trim()===""?o.push(new Error("Invalid bin field")):this.name!==null?this.bin.set(this.name.name,$o(e.bin)):o.push(new Error("String bin field, but no attached package name"));else if(typeof e.bin=="object"&&e.bin!==null)for(let[n,u]of Object.entries(e.bin)){if(typeof u!="string"||u.trim()===""){o.push(new Error(`Invalid bin definition for '${n}'`));continue}let A=Zo(n);this.bin.set(A.name,$o(u))}if(this.scripts=new Map,typeof e.scripts=="object"&&e.scripts!==null)for(let[n,u]of Object.entries(e.scripts)){if(typeof u!="string"){o.push(new Error(`Invalid script definition for '${n}'`));continue}this.scripts.set(n,u)}if(this.dependencies=new Map,typeof e.dependencies=="object"&&e.dependencies!==null)for(let[n,u]of Object.entries(e.dependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.dependencies.set(p.identHash,p)}if(this.devDependencies=new Map,typeof e.devDependencies=="object"&&e.devDependencies!==null)for(let[n,u]of Object.entries(e.devDependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.devDependencies.set(p.identHash,p)}if(this.peerDependencies=new Map,typeof e.peerDependencies=="object"&&e.peerDependencies!==null)for(let[n,u]of Object.entries(e.peerDependencies)){let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}(typeof u!="string"||!u.startsWith(ci.protocol)&&!Fa(u))&&(o.push(new Error(`Invalid dependency range for '${n}'`)),u="*");let p=kn(A,u);this.peerDependencies.set(p.identHash,p)}typeof e.workspaces=="object"&&e.workspaces!==null&&e.workspaces.nohoist&&o.push(new Error("'nohoist' is deprecated, please use 'installConfig.hoistingLimits' instead"));let a=Array.isArray(e.workspaces)?e.workspaces:typeof e.workspaces=="object"&&e.workspaces!==null&&Array.isArray(e.workspaces.packages)?e.workspaces.packages:[];this.workspaceDefinitions=[];for(let n of a){if(typeof n!="string"){o.push(new Error(`Invalid workspace definition for '${n}'`));continue}this.workspaceDefinitions.push({pattern:n})}if(this.dependenciesMeta=new Map,typeof e.dependenciesMeta=="object"&&e.dependenciesMeta!==null)for(let[n,u]of Object.entries(e.dependenciesMeta)){if(typeof u!="object"||u===null){o.push(new Error(`Invalid meta field for '${n}`));continue}let A=lh(n),p=this.ensureDependencyMeta(A),h=wb(u.built,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid built meta field for '${n}'`));continue}let E=wb(u.optional,{yamlCompatibilityMode:r});if(E===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}let I=wb(u.unplugged,{yamlCompatibilityMode:r});if(I===null){o.push(new Error(`Invalid unplugged meta field for '${n}'`));continue}Object.assign(p,{built:h,optional:E,unplugged:I})}if(this.peerDependenciesMeta=new Map,typeof e.peerDependenciesMeta=="object"&&e.peerDependenciesMeta!==null)for(let[n,u]of Object.entries(e.peerDependenciesMeta)){if(typeof u!="object"||u===null){o.push(new Error(`Invalid meta field for '${n}'`));continue}let A=lh(n),p=this.ensurePeerDependencyMeta(A),h=wb(u.optional,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}Object.assign(p,{optional:h})}if(this.resolutions=[],typeof e.resolutions=="object"&&e.resolutions!==null)for(let[n,u]of Object.entries(e.resolutions)){if(typeof u!="string"){o.push(new Error(`Invalid resolution entry for '${n}'`));continue}try{this.resolutions.push({pattern:pP(n),reference:u})}catch(A){o.push(A);continue}}if(Array.isArray(e.files)){this.files=new Set;for(let n of e.files){if(typeof n!="string"){o.push(new Error(`Invalid files entry for '${n}'`));continue}this.files.add(n)}}else this.files=null;if(typeof e.publishConfig=="object"&&e.publishConfig!==null){if(this.publishConfig={},typeof e.publishConfig.access=="string"&&(this.publishConfig.access=e.publishConfig.access),typeof e.publishConfig.main=="string"&&(this.publishConfig.main=$o(e.publishConfig.main)),typeof e.publishConfig.module=="string"&&(this.publishConfig.module=$o(e.publishConfig.module)),e.publishConfig.browser!=null)if(typeof e.publishConfig.browser=="string")this.publishConfig.browser=$o(e.publishConfig.browser);else{this.publishConfig.browser=new Map;for(let[n,u]of Object.entries(e.publishConfig.browser))this.publishConfig.browser.set($o(n),typeof u=="string"?$o(u):u)}if(typeof e.publishConfig.registry=="string"&&(this.publishConfig.registry=e.publishConfig.registry),typeof e.publishConfig.bin=="string")this.name!==null?this.publishConfig.bin=new Map([[this.name.name,$o(e.publishConfig.bin)]]):o.push(new Error("String bin field, but no attached package name"));else if(typeof e.publishConfig.bin=="object"&&e.publishConfig.bin!==null){this.publishConfig.bin=new Map;for(let[n,u]of Object.entries(e.publishConfig.bin)){if(typeof u!="string"){o.push(new Error(`Invalid bin definition for '${n}'`));continue}this.publishConfig.bin.set(n,$o(u))}}if(Array.isArray(e.publishConfig.executableFiles)){this.publishConfig.executableFiles=new Set;for(let n of e.publishConfig.executableFiles){if(typeof n!="string"){o.push(new Error("Invalid executable file definition"));continue}this.publishConfig.executableFiles.add($o(n))}}}else this.publishConfig=null;if(typeof e.installConfig=="object"&&e.installConfig!==null){this.installConfig={};for(let n of Object.keys(e.installConfig))n==="hoistingLimits"?typeof e.installConfig.hoistingLimits=="string"?this.installConfig.hoistingLimits=e.installConfig.hoistingLimits:o.push(new Error("Invalid hoisting limits definition")):n=="selfReferences"?typeof e.installConfig.selfReferences=="boolean"?this.installConfig.selfReferences=e.installConfig.selfReferences:o.push(new Error("Invalid selfReferences definition, must be a boolean value")):o.push(new Error(`Unrecognized installConfig key: ${n}`))}else this.installConfig=null;if(typeof e.optionalDependencies=="object"&&e.optionalDependencies!==null)for(let[n,u]of Object.entries(e.optionalDependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.dependencies.set(p.identHash,p);let h=kn(A,"unknown"),E=this.ensureDependencyMeta(h);Object.assign(E,{optional:!0})}typeof e.preferUnplugged=="boolean"?this.preferUnplugged=e.preferUnplugged:this.preferUnplugged=null,this.errors=o}getForScope(e){switch(e){case"dependencies":return this.dependencies;case"devDependencies":return this.devDependencies;case"peerDependencies":return this.peerDependencies;default:throw new Error(`Unsupported value ("${e}")`)}}hasConsumerDependency(e){return!!(this.dependencies.has(e.identHash)||this.peerDependencies.has(e.identHash))}hasHardDependency(e){return!!(this.dependencies.has(e.identHash)||this.devDependencies.has(e.identHash))}hasSoftDependency(e){return!!this.peerDependencies.has(e.identHash)}hasDependency(e){return!!(this.hasHardDependency(e)||this.hasSoftDependency(e))}getConditions(){let e=[];return this.os&&this.os.length>0&&e.push(jO("os",this.os)),this.cpu&&this.cpu.length>0&&e.push(jO("cpu",this.cpu)),this.libc&&this.libc.length>0&&e.push(jO("libc",this.libc)),e.length>0?e.join(" & "):null}ensureDependencyMeta(e){if(e.range!=="unknown"&&!noe.default.valid(e.range))throw new Error(`Invalid meta field range for '${ka(e)}'`);let r=rn(e),o=e.range!=="unknown"?e.range:null,a=this.dependenciesMeta.get(r);a||this.dependenciesMeta.set(r,a=new Map);let n=a.get(o);return n||a.set(o,n={}),n}ensurePeerDependencyMeta(e){if(e.range!=="unknown")throw new Error(`Invalid meta field range for '${ka(e)}'`);let r=rn(e),o=this.peerDependenciesMeta.get(r);return o||this.peerDependenciesMeta.set(r,o={}),o}setRawField(e,r,{after:o=[]}={}){let a=new Set(o.filter(n=>Object.hasOwn(this.raw,n)));if(a.size===0||Object.hasOwn(this.raw,e))this.raw[e]=r;else{let n=this.raw,u=this.raw={},A=!1;for(let p of Object.keys(n))u[p]=n[p],A||(a.delete(p),a.size===0&&(u[e]=r,A=!0))}}exportTo(e,{compatibilityMode:r=!0}={}){if(Object.assign(e,this.raw),this.name!==null?e.name=rn(this.name):delete e.name,this.version!==null?e.version=this.version:delete e.version,this.os!==null?e.os=this.os:delete e.os,this.cpu!==null?e.cpu=this.cpu:delete e.cpu,this.type!==null?e.type=this.type:delete e.type,this.packageManager!==null?e.packageManager=this.packageManager:delete e.packageManager,this.private?e.private=!0:delete e.private,this.license!==null?e.license=this.license:delete e.license,this.languageName!==null?e.languageName=this.languageName:delete e.languageName,this.main!==null?e.main=this.main:delete e.main,this.module!==null?e.module=this.module:delete e.module,this.browser!==null){let n=this.browser;typeof n=="string"?e.browser=n:n instanceof Map&&(e.browser=Object.assign({},...Array.from(n.keys()).sort().map(u=>({[u]:n.get(u)}))))}else delete e.browser;this.bin.size===1&&this.name!==null&&this.bin.has(this.name.name)?e.bin=this.bin.get(this.name.name):this.bin.size>0?e.bin=Object.assign({},...Array.from(this.bin.keys()).sort().map(n=>({[n]:this.bin.get(n)}))):delete e.bin,this.workspaceDefinitions.length>0?this.raw.workspaces&&!Array.isArray(this.raw.workspaces)?e.workspaces={...this.raw.workspaces,packages:this.workspaceDefinitions.map(({pattern:n})=>n)}:e.workspaces=this.workspaceDefinitions.map(({pattern:n})=>n):this.raw.workspaces&&!Array.isArray(this.raw.workspaces)&&Object.keys(this.raw.workspaces).length>0?e.workspaces=this.raw.workspaces:delete e.workspaces;let o=[],a=[];for(let n of this.dependencies.values()){let u=this.dependenciesMeta.get(rn(n)),A=!1;if(r&&u){let p=u.get(null);p&&p.optional&&(A=!0)}A?a.push(n):o.push(n)}o.length>0?e.dependencies=Object.assign({},...uy(o).map(n=>({[rn(n)]:n.range}))):delete e.dependencies,a.length>0?e.optionalDependencies=Object.assign({},...uy(a).map(n=>({[rn(n)]:n.range}))):delete e.optionalDependencies,this.devDependencies.size>0?e.devDependencies=Object.assign({},...uy(this.devDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.devDependencies,this.peerDependencies.size>0?e.peerDependencies=Object.assign({},...uy(this.peerDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.peerDependencies,e.dependenciesMeta={};for(let[n,u]of Ps(this.dependenciesMeta.entries(),([A,p])=>A))for(let[A,p]of Ps(u.entries(),([h,E])=>h!==null?`0${h}`:"1")){let h=A!==null?ka(kn(Zo(n),A)):n,E={...p};r&&A===null&&delete E.optional,Object.keys(E).length!==0&&(e.dependenciesMeta[h]=E)}if(Object.keys(e.dependenciesMeta).length===0&&delete e.dependenciesMeta,this.peerDependenciesMeta.size>0?e.peerDependenciesMeta=Object.assign({},...Ps(this.peerDependenciesMeta.entries(),([n,u])=>n).map(([n,u])=>({[n]:u}))):delete e.peerDependenciesMeta,this.resolutions.length>0?e.resolutions=Object.assign({},...this.resolutions.map(({pattern:n,reference:u})=>({[hP(n)]:u}))):delete e.resolutions,this.files!==null?e.files=Array.from(this.files):delete e.files,this.preferUnplugged!==null?e.preferUnplugged=this.preferUnplugged:delete e.preferUnplugged,this.scripts!==null&&this.scripts.size>0){e.scripts??={};for(let n of Object.keys(e.scripts))this.scripts.has(n)||delete e.scripts[n];for(let[n,u]of this.scripts.entries())e.scripts[n]=u}else delete e.scripts;return e}}});var soe=_((wNt,ioe)=>{var Htt=ql(),qtt=function(){return Htt.Date.now()};ioe.exports=qtt});var aoe=_((INt,ooe)=>{var jtt=/\s/;function Gtt(t){for(var e=t.length;e--&&jtt.test(t.charAt(e)););return e}ooe.exports=Gtt});var coe=_((BNt,loe)=>{var Ytt=aoe(),Wtt=/^\s+/;function Ktt(t){return t&&t.slice(0,Ytt(t)+1).replace(Wtt,"")}loe.exports=Ktt});var fy=_((vNt,uoe)=>{var Vtt=mg(),ztt=Zu(),Jtt="[object Symbol]";function Xtt(t){return typeof t=="symbol"||ztt(t)&&Vtt(t)==Jtt}uoe.exports=Xtt});var hoe=_((DNt,poe)=>{var Ztt=coe(),Aoe=cl(),$tt=fy(),foe=NaN,ert=/^[-+]0x[0-9a-f]+$/i,trt=/^0b[01]+$/i,rrt=/^0o[0-7]+$/i,nrt=parseInt;function irt(t){if(typeof t=="number")return t;if($tt(t))return foe;if(Aoe(t)){var e=typeof t.valueOf=="function"?t.valueOf():t;t=Aoe(e)?e+"":e}if(typeof t!="string")return t===0?t:+t;t=Ztt(t);var r=trt.test(t);return r||rrt.test(t)?nrt(t.slice(2),r?2:8):ert.test(t)?foe:+t}poe.exports=irt});var moe=_((PNt,doe)=>{var srt=cl(),GO=soe(),goe=hoe(),ort="Expected a function",art=Math.max,lrt=Math.min;function crt(t,e,r){var o,a,n,u,A,p,h=0,E=!1,I=!1,D=!0;if(typeof t!="function")throw new TypeError(ort);e=goe(e)||0,srt(r)&&(E=!!r.leading,I="maxWait"in r,n=I?art(goe(r.maxWait)||0,e):n,D="trailing"in r?!!r.trailing:D);function x(ue){var Ce=o,he=a;return o=a=void 0,h=ue,u=t.apply(he,Ce),u}function C(ue){return h=ue,A=setTimeout(U,e),E?x(ue):u}function T(ue){var Ce=ue-p,he=ue-h,De=e-Ce;return I?lrt(De,n-he):De}function L(ue){var Ce=ue-p,he=ue-h;return p===void 0||Ce>=e||Ce<0||I&&he>=n}function U(){var ue=GO();if(L(ue))return z(ue);A=setTimeout(U,T(ue))}function z(ue){return A=void 0,D&&o?x(ue):(o=a=void 0,u)}function te(){A!==void 0&&clearTimeout(A),h=0,o=p=a=A=void 0}function le(){return A===void 0?u:z(GO())}function ce(){var ue=GO(),Ce=L(ue);if(o=arguments,a=this,p=ue,Ce){if(A===void 0)return C(p);if(I)return clearTimeout(A),A=setTimeout(U,e),x(p)}return A===void 0&&(A=setTimeout(U,e)),u}return ce.cancel=te,ce.flush=le,ce}doe.exports=crt});var YO=_((SNt,yoe)=>{var urt=moe(),Art=cl(),frt="Expected a function";function prt(t,e,r){var o=!0,a=!0;if(typeof t!="function")throw new TypeError(frt);return Art(r)&&(o="leading"in r?!!r.leading:o,a="trailing"in r?!!r.trailing:a),urt(t,e,{leading:o,maxWait:e,trailing:a})}yoe.exports=prt});function grt(t){return typeof t.reportCode<"u"}var Eoe,Coe,woe,hrt,zt,Ys,Vl=wt(()=>{Eoe=et(YO()),Coe=ve("stream"),woe=ve("string_decoder"),hrt=15,zt=class extends Error{constructor(r,o,a){super(o);this.reportExtra=a;this.reportCode=r}};Ys=class{constructor(){this.cacheHits=new Set;this.cacheMisses=new Set;this.reportedInfos=new Set;this.reportedWarnings=new Set;this.reportedErrors=new Set}getRecommendedLength(){return 180}reportCacheHit(e){this.cacheHits.add(e.locatorHash)}reportCacheMiss(e,r){this.cacheMisses.add(e.locatorHash)}static progressViaCounter(e){let r=0,o,a=new Promise(p=>{o=p}),n=p=>{let h=o;a=new Promise(E=>{o=E}),r=p,h()},u=(p=0)=>{n(r+1)},A=async function*(){for(;r{r=u}),a=(0,Eoe.default)(u=>{let A=r;o=new Promise(p=>{r=p}),e=u,A()},1e3/hrt),n=async function*(){for(;;)await o,yield{title:e}}();return{[Symbol.asyncIterator](){return n},hasProgress:!1,hasTitle:!0,setTitle:a}}async startProgressPromise(e,r){let o=this.reportProgress(e);try{return await r(e)}finally{o.stop()}}startProgressSync(e,r){let o=this.reportProgress(e);try{return r(e)}finally{o.stop()}}reportInfoOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedInfos.has(a)||(this.reportedInfos.add(a),this.reportInfo(e,r),o?.reportExtra?.(this))}reportWarningOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedWarnings.has(a)||(this.reportedWarnings.add(a),this.reportWarning(e,r),o?.reportExtra?.(this))}reportErrorOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedErrors.has(a)||(this.reportedErrors.add(a),this.reportError(e,r),o?.reportExtra?.(this))}reportExceptionOnce(e){grt(e)?this.reportErrorOnce(e.reportCode,e.message,{key:e,reportExtra:e.reportExtra}):this.reportErrorOnce(1,e.stack||e.message,{key:e})}createStreamReporter(e=null){let r=new Coe.PassThrough,o=new woe.StringDecoder,a="";return r.on("data",n=>{let u=o.write(n),A;do if(A=u.indexOf(` +`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a="",e!==null?this.reportInfo(null,`${e} ${p}`):this.reportInfo(null,p)}while(A!==-1);a+=u}),r.on("end",()=>{let n=o.end();n!==""&&(e!==null?this.reportInfo(null,`${e} ${n}`):this.reportInfo(null,n))}),r}}});var py,WO=wt(()=>{Vl();wo();py=class{constructor(e){this.fetchers=e}supports(e,r){return!!this.tryFetcher(e,r)}getLocalPath(e,r){return this.getFetcher(e,r).getLocalPath(e,r)}async fetch(e,r){return await this.getFetcher(e,r).fetch(e,r)}tryFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));return o||null}getFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));if(!o)throw new zt(11,`${jr(r.project.configuration,e)} isn't supported by any available fetcher`);return o}}});var Pg,KO=wt(()=>{wo();Pg=class{constructor(e){this.resolvers=e.filter(r=>r)}supportsDescriptor(e,r){return!!this.tryResolverByDescriptor(e,r)}supportsLocator(e,r){return!!this.tryResolverByLocator(e,r)}shouldPersistResolution(e,r){return this.getResolverByLocator(e,r).shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.getResolverByDescriptor(e,o).bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.getResolverByDescriptor(e,r).getResolutionDependencies(e,r)}async getCandidates(e,r,o){return await this.getResolverByDescriptor(e,o).getCandidates(e,r,o)}async getSatisfying(e,r,o,a){return this.getResolverByDescriptor(e,a).getSatisfying(e,r,o,a)}async resolve(e,r){return await this.getResolverByLocator(e,r).resolve(e,r)}tryResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));return o||null}getResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));if(!o)throw new Error(`${zn(r.project.configuration,e)} isn't supported by any available resolver`);return o}tryResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));return o||null}getResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));if(!o)throw new Error(`${jr(r.project.configuration,e)} isn't supported by any available resolver`);return o}}});var hy,VO=wt(()=>{Pt();wo();hy=class{supports(e){return!!e.reference.startsWith("virtual:")}getLocalPath(e,r){let o=e.reference.indexOf("#");if(o===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(o+1),n=Ss(e,a);return r.fetcher.getLocalPath(n,r)}async fetch(e,r){let o=e.reference.indexOf("#");if(o===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(o+1),n=Ss(e,a),u=await r.fetcher.fetch(n,r);return await this.ensureVirtualLink(e,u,r)}getLocatorFilename(e){return ly(e)}async ensureVirtualLink(e,r,o){let a=r.packageFs.getRealPath(),n=o.project.configuration.get("virtualFolder"),u=this.getLocatorFilename(e),A=qs.makeVirtualPath(n,u,a),p=new ju(A,{baseFs:r.packageFs,pathUtils:K});return{...r,packageFs:p}}}});var Ib,Ioe=wt(()=>{Ib=class t{static{this.protocol="virtual:"}static isVirtualDescriptor(e){return!!e.range.startsWith(t.protocol)}static isVirtualLocator(e){return!!e.reference.startsWith(t.protocol)}supportsDescriptor(e,r){return t.isVirtualDescriptor(e)}supportsLocator(e,r){return t.isVirtualLocator(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){throw new Error('Assertion failed: calling "bindDescriptor" on a virtual descriptor is unsupported')}getResolutionDependencies(e,r){throw new Error('Assertion failed: calling "getResolutionDependencies" on a virtual descriptor is unsupported')}async getCandidates(e,r,o){throw new Error('Assertion failed: calling "getCandidates" on a virtual descriptor is unsupported')}async getSatisfying(e,r,o,a){throw new Error('Assertion failed: calling "getSatisfying" on a virtual descriptor is unsupported')}async resolve(e,r){throw new Error('Assertion failed: calling "resolve" on a virtual locator is unsupported')}}});var gy,zO=wt(()=>{Pt();Dg();gy=class{supports(e){return!!e.reference.startsWith(ci.protocol)}getLocalPath(e,r){return this.getWorkspace(e,r).cwd}async fetch(e,r){let o=this.getWorkspace(e,r).cwd;return{packageFs:new En(o),prefixPath:Bt.dot,localPath:o}}getWorkspace(e,r){return r.project.getWorkspaceByCwd(e.reference.slice(ci.protocol.length))}}});function b1(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Boe(t){return typeof t>"u"?3:b1(t)?0:Array.isArray(t)?1:2}function ZO(t,e){return Object.hasOwn(t,e)}function mrt(t){return b1(t)&&ZO(t,"onConflict")&&typeof t.onConflict=="string"}function yrt(t){if(typeof t>"u")return{onConflict:"default",value:t};if(!mrt(t))return{onConflict:"default",value:t};if(ZO(t,"value"))return t;let{onConflict:e,...r}=t;return{onConflict:e,value:r}}function voe(t,e){let r=b1(t)&&ZO(t,e)?t[e]:void 0;return yrt(r)}function dy(t,e){return[t,e,Doe]}function $O(t){return Array.isArray(t)?t[2]===Doe:!1}function JO(t,e){if(b1(t)){let r={};for(let o of Object.keys(t))r[o]=JO(t[o],e);return dy(e,r)}return Array.isArray(t)?dy(e,t.map(r=>JO(r,e))):dy(e,t)}function XO(t,e,r,o,a){let n,u=[],A=a,p=0;for(let E=a-1;E>=o;--E){let[I,D]=t[E],{onConflict:x,value:C}=voe(D,r),T=Boe(C);if(T!==3){if(n??=T,T!==n||x==="hardReset"){p=A;break}if(T===2)return dy(I,C);if(u.unshift([I,C]),x==="reset"){p=E;break}x==="extend"&&E===o&&(o=0),A=E}}if(typeof n>"u")return null;let h=u.map(([E])=>E).join(", ");switch(n){case 1:return dy(h,new Array().concat(...u.map(([E,I])=>I.map(D=>JO(D,E)))));case 0:{let E=Object.assign({},...u.map(([,T])=>T)),I=Object.keys(E),D={},x=t.map(([T,L])=>[T,voe(L,r).value]),C=drt(x,([T,L])=>{let U=Boe(L);return U!==0&&U!==3});if(C!==-1){let T=x.slice(C+1);for(let L of I)D[L]=XO(T,e,L,0,T.length)}else for(let T of I)D[T]=XO(x,e,T,p,x.length);return dy(h,D)}default:throw new Error("Assertion failed: Non-extendable value type")}}function Poe(t){return XO(t.map(([e,r])=>[e,{".":r}]),[],".",0,t.length)}function x1(t){return $O(t)?t[1]:t}function Bb(t){let e=$O(t)?t[1]:t;if(Array.isArray(e))return e.map(r=>Bb(r));if(b1(e)){let r={};for(let[o,a]of Object.entries(e))r[o]=Bb(a);return r}return e}function e4(t){return $O(t)?t[0]:null}var drt,Doe,Soe=wt(()=>{drt=(t,e,r)=>{let o=[...t];return o.reverse(),o.findIndex(e,r)};Doe=Symbol()});var vb={};Kt(vb,{getDefaultGlobalFolder:()=>r4,getHomeFolder:()=>my,isFolderInside:()=>n4});function r4(){if(process.platform==="win32"){let t=Ae.toPortablePath(process.env.LOCALAPPDATA||Ae.join((0,t4.homedir)(),"AppData","Local"));return K.resolve(t,"Yarn/Berry")}if(process.env.XDG_DATA_HOME){let t=Ae.toPortablePath(process.env.XDG_DATA_HOME);return K.resolve(t,"yarn/berry")}return K.resolve(my(),".yarn/berry")}function my(){return Ae.toPortablePath((0,t4.homedir)()||"/usr/local/share")}function n4(t,e){let r=K.relative(e,t);return r&&!r.startsWith("..")&&!K.isAbsolute(r)}var t4,Db=wt(()=>{Pt();t4=ve("os")});var Qoe=_(yy=>{"use strict";var _Nt=ve("net"),Crt=ve("tls"),i4=ve("http"),boe=ve("https"),wrt=ve("events"),HNt=ve("assert"),Irt=ve("util");yy.httpOverHttp=Brt;yy.httpsOverHttp=vrt;yy.httpOverHttps=Drt;yy.httpsOverHttps=Prt;function Brt(t){var e=new kf(t);return e.request=i4.request,e}function vrt(t){var e=new kf(t);return e.request=i4.request,e.createSocket=xoe,e.defaultPort=443,e}function Drt(t){var e=new kf(t);return e.request=boe.request,e}function Prt(t){var e=new kf(t);return e.request=boe.request,e.createSocket=xoe,e.defaultPort=443,e}function kf(t){var e=this;e.options=t||{},e.proxyOptions=e.options.proxy||{},e.maxSockets=e.options.maxSockets||i4.Agent.defaultMaxSockets,e.requests=[],e.sockets=[],e.on("free",function(o,a,n,u){for(var A=koe(a,n,u),p=0,h=e.requests.length;p=this.maxSockets){n.requests.push(u);return}n.createSocket(u,function(A){A.on("free",p),A.on("close",h),A.on("agentRemove",h),e.onSocket(A);function p(){n.emit("free",A,u)}function h(E){n.removeSocket(A),A.removeListener("free",p),A.removeListener("close",h),A.removeListener("agentRemove",h)}})};kf.prototype.createSocket=function(e,r){var o=this,a={};o.sockets.push(a);var n=s4({},o.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:!1,headers:{host:e.host+":"+e.port}});e.localAddress&&(n.localAddress=e.localAddress),n.proxyAuth&&(n.headers=n.headers||{},n.headers["Proxy-Authorization"]="Basic "+new Buffer(n.proxyAuth).toString("base64")),ch("making CONNECT request");var u=o.request(n);u.useChunkedEncodingByDefault=!1,u.once("response",A),u.once("upgrade",p),u.once("connect",h),u.once("error",E),u.end();function A(I){I.upgrade=!0}function p(I,D,x){process.nextTick(function(){h(I,D,x)})}function h(I,D,x){if(u.removeAllListeners(),D.removeAllListeners(),I.statusCode!==200){ch("tunneling socket could not be established, statusCode=%d",I.statusCode),D.destroy();var C=new Error("tunneling socket could not be established, statusCode="+I.statusCode);C.code="ECONNRESET",e.request.emit("error",C),o.removeSocket(a);return}if(x.length>0){ch("got illegal response body from proxy"),D.destroy();var C=new Error("got illegal response body from proxy");C.code="ECONNRESET",e.request.emit("error",C),o.removeSocket(a);return}return ch("tunneling connection has established"),o.sockets[o.sockets.indexOf(a)]=D,r(D)}function E(I){u.removeAllListeners(),ch(`tunneling socket could not be established, cause=%s +`,I.message,I.stack);var D=new Error("tunneling socket could not be established, cause="+I.message);D.code="ECONNRESET",e.request.emit("error",D),o.removeSocket(a)}};kf.prototype.removeSocket=function(e){var r=this.sockets.indexOf(e);if(r!==-1){this.sockets.splice(r,1);var o=this.requests.shift();o&&this.createSocket(o,function(a){o.request.onSocket(a)})}};function xoe(t,e){var r=this;kf.prototype.createSocket.call(r,t,function(o){var a=t.request.getHeader("host"),n=s4({},r.options,{socket:o,servername:a?a.replace(/:.*$/,""):t.host}),u=Crt.connect(0,n);r.sockets[r.sockets.indexOf(o)]=u,e(u)})}function koe(t,e,r){return typeof t=="string"?{host:t,port:e,localAddress:r}:t}function s4(t){for(var e=1,r=arguments.length;e{Foe.exports=Qoe()});var Ff=_((Qf,Pb)=>{"use strict";Object.defineProperty(Qf,"__esModule",{value:!0});var Toe=["Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array","BigInt64Array","BigUint64Array"];function Srt(t){return Toe.includes(t)}var brt=["Function","Generator","AsyncGenerator","GeneratorFunction","AsyncGeneratorFunction","AsyncFunction","Observable","Array","Buffer","Blob","Object","RegExp","Date","Error","Map","Set","WeakMap","WeakSet","ArrayBuffer","SharedArrayBuffer","DataView","Promise","URL","FormData","URLSearchParams","HTMLElement",...Toe];function xrt(t){return brt.includes(t)}var krt=["null","undefined","string","number","bigint","boolean","symbol"];function Qrt(t){return krt.includes(t)}function Ey(t){return e=>typeof e===t}var{toString:Noe}=Object.prototype,k1=t=>{let e=Noe.call(t).slice(8,-1);if(/HTML\w+Element/.test(e)&&Pe.domElement(t))return"HTMLElement";if(xrt(e))return e},ii=t=>e=>k1(e)===t;function Pe(t){if(t===null)return"null";switch(typeof t){case"undefined":return"undefined";case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"function":return"Function";case"bigint":return"bigint";case"symbol":return"symbol";default:}if(Pe.observable(t))return"Observable";if(Pe.array(t))return"Array";if(Pe.buffer(t))return"Buffer";let e=k1(t);if(e)return e;if(t instanceof String||t instanceof Boolean||t instanceof Number)throw new TypeError("Please don't use object wrappers for primitive types");return"Object"}Pe.undefined=Ey("undefined");Pe.string=Ey("string");var Frt=Ey("number");Pe.number=t=>Frt(t)&&!Pe.nan(t);Pe.bigint=Ey("bigint");Pe.function_=Ey("function");Pe.null_=t=>t===null;Pe.class_=t=>Pe.function_(t)&&t.toString().startsWith("class ");Pe.boolean=t=>t===!0||t===!1;Pe.symbol=Ey("symbol");Pe.numericString=t=>Pe.string(t)&&!Pe.emptyStringOrWhitespace(t)&&!Number.isNaN(Number(t));Pe.array=(t,e)=>Array.isArray(t)?Pe.function_(e)?t.every(e):!0:!1;Pe.buffer=t=>{var e,r,o,a;return(a=(o=(r=(e=t)===null||e===void 0?void 0:e.constructor)===null||r===void 0?void 0:r.isBuffer)===null||o===void 0?void 0:o.call(r,t))!==null&&a!==void 0?a:!1};Pe.blob=t=>ii("Blob")(t);Pe.nullOrUndefined=t=>Pe.null_(t)||Pe.undefined(t);Pe.object=t=>!Pe.null_(t)&&(typeof t=="object"||Pe.function_(t));Pe.iterable=t=>{var e;return Pe.function_((e=t)===null||e===void 0?void 0:e[Symbol.iterator])};Pe.asyncIterable=t=>{var e;return Pe.function_((e=t)===null||e===void 0?void 0:e[Symbol.asyncIterator])};Pe.generator=t=>{var e,r;return Pe.iterable(t)&&Pe.function_((e=t)===null||e===void 0?void 0:e.next)&&Pe.function_((r=t)===null||r===void 0?void 0:r.throw)};Pe.asyncGenerator=t=>Pe.asyncIterable(t)&&Pe.function_(t.next)&&Pe.function_(t.throw);Pe.nativePromise=t=>ii("Promise")(t);var Rrt=t=>{var e,r;return Pe.function_((e=t)===null||e===void 0?void 0:e.then)&&Pe.function_((r=t)===null||r===void 0?void 0:r.catch)};Pe.promise=t=>Pe.nativePromise(t)||Rrt(t);Pe.generatorFunction=ii("GeneratorFunction");Pe.asyncGeneratorFunction=t=>k1(t)==="AsyncGeneratorFunction";Pe.asyncFunction=t=>k1(t)==="AsyncFunction";Pe.boundFunction=t=>Pe.function_(t)&&!t.hasOwnProperty("prototype");Pe.regExp=ii("RegExp");Pe.date=ii("Date");Pe.error=ii("Error");Pe.map=t=>ii("Map")(t);Pe.set=t=>ii("Set")(t);Pe.weakMap=t=>ii("WeakMap")(t);Pe.weakSet=t=>ii("WeakSet")(t);Pe.int8Array=ii("Int8Array");Pe.uint8Array=ii("Uint8Array");Pe.uint8ClampedArray=ii("Uint8ClampedArray");Pe.int16Array=ii("Int16Array");Pe.uint16Array=ii("Uint16Array");Pe.int32Array=ii("Int32Array");Pe.uint32Array=ii("Uint32Array");Pe.float32Array=ii("Float32Array");Pe.float64Array=ii("Float64Array");Pe.bigInt64Array=ii("BigInt64Array");Pe.bigUint64Array=ii("BigUint64Array");Pe.arrayBuffer=ii("ArrayBuffer");Pe.sharedArrayBuffer=ii("SharedArrayBuffer");Pe.dataView=ii("DataView");Pe.enumCase=(t,e)=>Object.values(e).includes(t);Pe.directInstanceOf=(t,e)=>Object.getPrototypeOf(t)===e.prototype;Pe.urlInstance=t=>ii("URL")(t);Pe.urlString=t=>{if(!Pe.string(t))return!1;try{return new URL(t),!0}catch{return!1}};Pe.truthy=t=>!!t;Pe.falsy=t=>!t;Pe.nan=t=>Number.isNaN(t);Pe.primitive=t=>Pe.null_(t)||Qrt(typeof t);Pe.integer=t=>Number.isInteger(t);Pe.safeInteger=t=>Number.isSafeInteger(t);Pe.plainObject=t=>{if(Noe.call(t)!=="[object Object]")return!1;let e=Object.getPrototypeOf(t);return e===null||e===Object.getPrototypeOf({})};Pe.typedArray=t=>Srt(k1(t));var Trt=t=>Pe.safeInteger(t)&&t>=0;Pe.arrayLike=t=>!Pe.nullOrUndefined(t)&&!Pe.function_(t)&&Trt(t.length);Pe.inRange=(t,e)=>{if(Pe.number(e))return t>=Math.min(0,e)&&t<=Math.max(e,0);if(Pe.array(e)&&e.length===2)return t>=Math.min(...e)&&t<=Math.max(...e);throw new TypeError(`Invalid range: ${JSON.stringify(e)}`)};var Nrt=1,Lrt=["innerHTML","ownerDocument","style","attributes","nodeValue"];Pe.domElement=t=>Pe.object(t)&&t.nodeType===Nrt&&Pe.string(t.nodeName)&&!Pe.plainObject(t)&&Lrt.every(e=>e in t);Pe.observable=t=>{var e,r,o,a;return t?t===((r=(e=t)[Symbol.observable])===null||r===void 0?void 0:r.call(e))||t===((a=(o=t)["@@observable"])===null||a===void 0?void 0:a.call(o)):!1};Pe.nodeStream=t=>Pe.object(t)&&Pe.function_(t.pipe)&&!Pe.observable(t);Pe.infinite=t=>t===1/0||t===-1/0;var Loe=t=>e=>Pe.integer(e)&&Math.abs(e%2)===t;Pe.evenInteger=Loe(0);Pe.oddInteger=Loe(1);Pe.emptyArray=t=>Pe.array(t)&&t.length===0;Pe.nonEmptyArray=t=>Pe.array(t)&&t.length>0;Pe.emptyString=t=>Pe.string(t)&&t.length===0;var Mrt=t=>Pe.string(t)&&!/\S/.test(t);Pe.emptyStringOrWhitespace=t=>Pe.emptyString(t)||Mrt(t);Pe.nonEmptyString=t=>Pe.string(t)&&t.length>0;Pe.nonEmptyStringAndNotWhitespace=t=>Pe.string(t)&&!Pe.emptyStringOrWhitespace(t);Pe.emptyObject=t=>Pe.object(t)&&!Pe.map(t)&&!Pe.set(t)&&Object.keys(t).length===0;Pe.nonEmptyObject=t=>Pe.object(t)&&!Pe.map(t)&&!Pe.set(t)&&Object.keys(t).length>0;Pe.emptySet=t=>Pe.set(t)&&t.size===0;Pe.nonEmptySet=t=>Pe.set(t)&&t.size>0;Pe.emptyMap=t=>Pe.map(t)&&t.size===0;Pe.nonEmptyMap=t=>Pe.map(t)&&t.size>0;Pe.propertyKey=t=>Pe.any([Pe.string,Pe.number,Pe.symbol],t);Pe.formData=t=>ii("FormData")(t);Pe.urlSearchParams=t=>ii("URLSearchParams")(t);var Moe=(t,e,r)=>{if(!Pe.function_(e))throw new TypeError(`Invalid predicate: ${JSON.stringify(e)}`);if(r.length===0)throw new TypeError("Invalid number of values");return t.call(r,e)};Pe.any=(t,...e)=>(Pe.array(t)?t:[t]).some(o=>Moe(Array.prototype.some,o,e));Pe.all=(t,...e)=>Moe(Array.prototype.every,t,e);var Ot=(t,e,r,o={})=>{if(!t){let{multipleValues:a}=o,n=a?`received values of types ${[...new Set(r.map(u=>`\`${Pe(u)}\``))].join(", ")}`:`received value of type \`${Pe(r)}\``;throw new TypeError(`Expected value which is \`${e}\`, ${n}.`)}};Qf.assert={undefined:t=>Ot(Pe.undefined(t),"undefined",t),string:t=>Ot(Pe.string(t),"string",t),number:t=>Ot(Pe.number(t),"number",t),bigint:t=>Ot(Pe.bigint(t),"bigint",t),function_:t=>Ot(Pe.function_(t),"Function",t),null_:t=>Ot(Pe.null_(t),"null",t),class_:t=>Ot(Pe.class_(t),"Class",t),boolean:t=>Ot(Pe.boolean(t),"boolean",t),symbol:t=>Ot(Pe.symbol(t),"symbol",t),numericString:t=>Ot(Pe.numericString(t),"string with a number",t),array:(t,e)=>{Ot(Pe.array(t),"Array",t),e&&t.forEach(e)},buffer:t=>Ot(Pe.buffer(t),"Buffer",t),blob:t=>Ot(Pe.blob(t),"Blob",t),nullOrUndefined:t=>Ot(Pe.nullOrUndefined(t),"null or undefined",t),object:t=>Ot(Pe.object(t),"Object",t),iterable:t=>Ot(Pe.iterable(t),"Iterable",t),asyncIterable:t=>Ot(Pe.asyncIterable(t),"AsyncIterable",t),generator:t=>Ot(Pe.generator(t),"Generator",t),asyncGenerator:t=>Ot(Pe.asyncGenerator(t),"AsyncGenerator",t),nativePromise:t=>Ot(Pe.nativePromise(t),"native Promise",t),promise:t=>Ot(Pe.promise(t),"Promise",t),generatorFunction:t=>Ot(Pe.generatorFunction(t),"GeneratorFunction",t),asyncGeneratorFunction:t=>Ot(Pe.asyncGeneratorFunction(t),"AsyncGeneratorFunction",t),asyncFunction:t=>Ot(Pe.asyncFunction(t),"AsyncFunction",t),boundFunction:t=>Ot(Pe.boundFunction(t),"Function",t),regExp:t=>Ot(Pe.regExp(t),"RegExp",t),date:t=>Ot(Pe.date(t),"Date",t),error:t=>Ot(Pe.error(t),"Error",t),map:t=>Ot(Pe.map(t),"Map",t),set:t=>Ot(Pe.set(t),"Set",t),weakMap:t=>Ot(Pe.weakMap(t),"WeakMap",t),weakSet:t=>Ot(Pe.weakSet(t),"WeakSet",t),int8Array:t=>Ot(Pe.int8Array(t),"Int8Array",t),uint8Array:t=>Ot(Pe.uint8Array(t),"Uint8Array",t),uint8ClampedArray:t=>Ot(Pe.uint8ClampedArray(t),"Uint8ClampedArray",t),int16Array:t=>Ot(Pe.int16Array(t),"Int16Array",t),uint16Array:t=>Ot(Pe.uint16Array(t),"Uint16Array",t),int32Array:t=>Ot(Pe.int32Array(t),"Int32Array",t),uint32Array:t=>Ot(Pe.uint32Array(t),"Uint32Array",t),float32Array:t=>Ot(Pe.float32Array(t),"Float32Array",t),float64Array:t=>Ot(Pe.float64Array(t),"Float64Array",t),bigInt64Array:t=>Ot(Pe.bigInt64Array(t),"BigInt64Array",t),bigUint64Array:t=>Ot(Pe.bigUint64Array(t),"BigUint64Array",t),arrayBuffer:t=>Ot(Pe.arrayBuffer(t),"ArrayBuffer",t),sharedArrayBuffer:t=>Ot(Pe.sharedArrayBuffer(t),"SharedArrayBuffer",t),dataView:t=>Ot(Pe.dataView(t),"DataView",t),enumCase:(t,e)=>Ot(Pe.enumCase(t,e),"EnumCase",t),urlInstance:t=>Ot(Pe.urlInstance(t),"URL",t),urlString:t=>Ot(Pe.urlString(t),"string with a URL",t),truthy:t=>Ot(Pe.truthy(t),"truthy",t),falsy:t=>Ot(Pe.falsy(t),"falsy",t),nan:t=>Ot(Pe.nan(t),"NaN",t),primitive:t=>Ot(Pe.primitive(t),"primitive",t),integer:t=>Ot(Pe.integer(t),"integer",t),safeInteger:t=>Ot(Pe.safeInteger(t),"integer",t),plainObject:t=>Ot(Pe.plainObject(t),"plain object",t),typedArray:t=>Ot(Pe.typedArray(t),"TypedArray",t),arrayLike:t=>Ot(Pe.arrayLike(t),"array-like",t),domElement:t=>Ot(Pe.domElement(t),"HTMLElement",t),observable:t=>Ot(Pe.observable(t),"Observable",t),nodeStream:t=>Ot(Pe.nodeStream(t),"Node.js Stream",t),infinite:t=>Ot(Pe.infinite(t),"infinite number",t),emptyArray:t=>Ot(Pe.emptyArray(t),"empty array",t),nonEmptyArray:t=>Ot(Pe.nonEmptyArray(t),"non-empty array",t),emptyString:t=>Ot(Pe.emptyString(t),"empty string",t),emptyStringOrWhitespace:t=>Ot(Pe.emptyStringOrWhitespace(t),"empty string or whitespace",t),nonEmptyString:t=>Ot(Pe.nonEmptyString(t),"non-empty string",t),nonEmptyStringAndNotWhitespace:t=>Ot(Pe.nonEmptyStringAndNotWhitespace(t),"non-empty string and not whitespace",t),emptyObject:t=>Ot(Pe.emptyObject(t),"empty object",t),nonEmptyObject:t=>Ot(Pe.nonEmptyObject(t),"non-empty object",t),emptySet:t=>Ot(Pe.emptySet(t),"empty set",t),nonEmptySet:t=>Ot(Pe.nonEmptySet(t),"non-empty set",t),emptyMap:t=>Ot(Pe.emptyMap(t),"empty map",t),nonEmptyMap:t=>Ot(Pe.nonEmptyMap(t),"non-empty map",t),propertyKey:t=>Ot(Pe.propertyKey(t),"PropertyKey",t),formData:t=>Ot(Pe.formData(t),"FormData",t),urlSearchParams:t=>Ot(Pe.urlSearchParams(t),"URLSearchParams",t),evenInteger:t=>Ot(Pe.evenInteger(t),"even integer",t),oddInteger:t=>Ot(Pe.oddInteger(t),"odd integer",t),directInstanceOf:(t,e)=>Ot(Pe.directInstanceOf(t,e),"T",t),inRange:(t,e)=>Ot(Pe.inRange(t,e),"in range",t),any:(t,...e)=>Ot(Pe.any(t,...e),"predicate returns truthy for any value",e,{multipleValues:!0}),all:(t,...e)=>Ot(Pe.all(t,...e),"predicate returns truthy for all values",e,{multipleValues:!0})};Object.defineProperties(Pe,{class:{value:Pe.class_},function:{value:Pe.function_},null:{value:Pe.null_}});Object.defineProperties(Qf.assert,{class:{value:Qf.assert.class_},function:{value:Qf.assert.function_},null:{value:Qf.assert.null_}});Qf.default=Pe;Pb.exports=Pe;Pb.exports.default=Pe;Pb.exports.assert=Qf.assert});var Ooe=_((GNt,o4)=>{"use strict";var Sb=class extends Error{constructor(e){super(e||"Promise was canceled"),this.name="CancelError"}get isCanceled(){return!0}},bb=class t{static fn(e){return(...r)=>new t((o,a,n)=>{r.push(n),e(...r).then(o,a)})}constructor(e){this._cancelHandlers=[],this._isPending=!0,this._isCanceled=!1,this._rejectOnCancel=!0,this._promise=new Promise((r,o)=>{this._reject=o;let a=A=>{this._isPending=!1,r(A)},n=A=>{this._isPending=!1,o(A)},u=A=>{if(!this._isPending)throw new Error("The `onCancel` handler was attached after the promise settled.");this._cancelHandlers.push(A)};return Object.defineProperties(u,{shouldReject:{get:()=>this._rejectOnCancel,set:A=>{this._rejectOnCancel=A}}}),e(a,n,u)})}then(e,r){return this._promise.then(e,r)}catch(e){return this._promise.catch(e)}finally(e){return this._promise.finally(e)}cancel(e){if(!(!this._isPending||this._isCanceled)){if(this._cancelHandlers.length>0)try{for(let r of this._cancelHandlers)r()}catch(r){this._reject(r)}this._isCanceled=!0,this._rejectOnCancel&&this._reject(new Sb(e))}}get isCanceled(){return this._isCanceled}};Object.setPrototypeOf(bb.prototype,Promise.prototype);o4.exports=bb;o4.exports.CancelError=Sb});var Uoe=_((l4,c4)=>{"use strict";Object.defineProperty(l4,"__esModule",{value:!0});function Ort(t){return t.encrypted}var a4=(t,e)=>{let r;typeof e=="function"?r={connect:e}:r=e;let o=typeof r.connect=="function",a=typeof r.secureConnect=="function",n=typeof r.close=="function",u=()=>{o&&r.connect(),Ort(t)&&a&&(t.authorized?r.secureConnect():t.authorizationError||t.once("secureConnect",r.secureConnect)),n&&t.once("close",r.close)};t.writable&&!t.connecting?u():t.connecting?t.once("connect",u):t.destroyed&&n&&r.close(t._hadError)};l4.default=a4;c4.exports=a4;c4.exports.default=a4});var _oe=_((A4,f4)=>{"use strict";Object.defineProperty(A4,"__esModule",{value:!0});var Urt=Uoe(),_rt=Number(process.versions.node.split(".")[0]),u4=t=>{let e={start:Date.now(),socket:void 0,lookup:void 0,connect:void 0,secureConnect:void 0,upload:void 0,response:void 0,end:void 0,error:void 0,abort:void 0,phases:{wait:void 0,dns:void 0,tcp:void 0,tls:void 0,request:void 0,firstByte:void 0,download:void 0,total:void 0}};t.timings=e;let r=u=>{let A=u.emit.bind(u);u.emit=(p,...h)=>(p==="error"&&(e.error=Date.now(),e.phases.total=e.error-e.start,u.emit=A),A(p,...h))};r(t),t.prependOnceListener("abort",()=>{e.abort=Date.now(),(!e.response||_rt>=13)&&(e.phases.total=Date.now()-e.start)});let o=u=>{e.socket=Date.now(),e.phases.wait=e.socket-e.start;let A=()=>{e.lookup=Date.now(),e.phases.dns=e.lookup-e.socket};u.prependOnceListener("lookup",A),Urt.default(u,{connect:()=>{e.connect=Date.now(),e.lookup===void 0&&(u.removeListener("lookup",A),e.lookup=e.connect,e.phases.dns=e.lookup-e.socket),e.phases.tcp=e.connect-e.lookup},secureConnect:()=>{e.secureConnect=Date.now(),e.phases.tls=e.secureConnect-e.connect}})};t.socket?o(t.socket):t.prependOnceListener("socket",o);let a=()=>{var u;e.upload=Date.now(),e.phases.request=e.upload-(u=e.secureConnect,u??e.connect)};return(typeof t.writableFinished=="boolean"?t.writableFinished:t.finished&&t.outputSize===0&&(!t.socket||t.socket.writableLength===0))?a():t.prependOnceListener("finish",a),t.prependOnceListener("response",u=>{e.response=Date.now(),e.phases.firstByte=e.response-e.upload,u.timings=e,r(u),u.prependOnceListener("end",()=>{e.end=Date.now(),e.phases.download=e.end-e.response,e.phases.total=e.end-e.start})}),e};A4.default=u4;f4.exports=u4;f4.exports.default=u4});var Koe=_((YNt,g4)=>{"use strict";var{V4MAPPED:Hrt,ADDRCONFIG:qrt,ALL:Woe,promises:{Resolver:Hoe},lookup:jrt}=ve("dns"),{promisify:p4}=ve("util"),Grt=ve("os"),Cy=Symbol("cacheableLookupCreateConnection"),h4=Symbol("cacheableLookupInstance"),qoe=Symbol("expires"),Yrt=typeof Woe=="number",joe=t=>{if(!(t&&typeof t.createConnection=="function"))throw new Error("Expected an Agent instance as the first argument")},Wrt=t=>{for(let e of t)e.family!==6&&(e.address=`::ffff:${e.address}`,e.family=6)},Goe=()=>{let t=!1,e=!1;for(let r of Object.values(Grt.networkInterfaces()))for(let o of r)if(!o.internal&&(o.family==="IPv6"?e=!0:t=!0,t&&e))return{has4:t,has6:e};return{has4:t,has6:e}},Krt=t=>Symbol.iterator in t,Yoe={ttl:!0},Vrt={all:!0},xb=class{constructor({cache:e=new Map,maxTtl:r=1/0,fallbackDuration:o=3600,errorTtl:a=.15,resolver:n=new Hoe,lookup:u=jrt}={}){if(this.maxTtl=r,this.errorTtl=a,this._cache=e,this._resolver=n,this._dnsLookup=p4(u),this._resolver instanceof Hoe?(this._resolve4=this._resolver.resolve4.bind(this._resolver),this._resolve6=this._resolver.resolve6.bind(this._resolver)):(this._resolve4=p4(this._resolver.resolve4.bind(this._resolver)),this._resolve6=p4(this._resolver.resolve6.bind(this._resolver))),this._iface=Goe(),this._pending={},this._nextRemovalTime=!1,this._hostnamesToFallback=new Set,o<1)this._fallback=!1;else{this._fallback=!0;let A=setInterval(()=>{this._hostnamesToFallback.clear()},o*1e3);A.unref&&A.unref()}this.lookup=this.lookup.bind(this),this.lookupAsync=this.lookupAsync.bind(this)}set servers(e){this.clear(),this._resolver.setServers(e)}get servers(){return this._resolver.getServers()}lookup(e,r,o){if(typeof r=="function"?(o=r,r={}):typeof r=="number"&&(r={family:r}),!o)throw new Error("Callback must be a function.");this.lookupAsync(e,r).then(a=>{r.all?o(null,a):o(null,a.address,a.family,a.expires,a.ttl)},o)}async lookupAsync(e,r={}){typeof r=="number"&&(r={family:r});let o=await this.query(e);if(r.family===6){let a=o.filter(n=>n.family===6);r.hints&Hrt&&(Yrt&&r.hints&Woe||a.length===0)?Wrt(o):o=a}else r.family===4&&(o=o.filter(a=>a.family===4));if(r.hints&qrt){let{_iface:a}=this;o=o.filter(n=>n.family===6?a.has6:a.has4)}if(o.length===0){let a=new Error(`cacheableLookup ENOTFOUND ${e}`);throw a.code="ENOTFOUND",a.hostname=e,a}return r.all?o:o[0]}async query(e){let r=await this._cache.get(e);if(!r){let o=this._pending[e];if(o)r=await o;else{let a=this.queryAndCache(e);this._pending[e]=a,r=await a}}return r=r.map(o=>({...o})),r}async _resolve(e){let r=async h=>{try{return await h}catch(E){if(E.code==="ENODATA"||E.code==="ENOTFOUND")return[];throw E}},[o,a]=await Promise.all([this._resolve4(e,Yoe),this._resolve6(e,Yoe)].map(h=>r(h))),n=0,u=0,A=0,p=Date.now();for(let h of o)h.family=4,h.expires=p+h.ttl*1e3,n=Math.max(n,h.ttl);for(let h of a)h.family=6,h.expires=p+h.ttl*1e3,u=Math.max(u,h.ttl);return o.length>0?a.length>0?A=Math.min(n,u):A=n:A=u,{entries:[...o,...a],cacheTtl:A}}async _lookup(e){try{return{entries:await this._dnsLookup(e,{all:!0}),cacheTtl:0}}catch{return{entries:[],cacheTtl:0}}}async _set(e,r,o){if(this.maxTtl>0&&o>0){o=Math.min(o,this.maxTtl)*1e3,r[qoe]=Date.now()+o;try{await this._cache.set(e,r,o)}catch(a){this.lookupAsync=async()=>{let n=new Error("Cache Error. Please recreate the CacheableLookup instance.");throw n.cause=a,n}}Krt(this._cache)&&this._tick(o)}}async queryAndCache(e){if(this._hostnamesToFallback.has(e))return this._dnsLookup(e,Vrt);try{let r=await this._resolve(e);r.entries.length===0&&this._fallback&&(r=await this._lookup(e),r.entries.length!==0&&this._hostnamesToFallback.add(e));let o=r.entries.length===0?this.errorTtl:r.cacheTtl;return await this._set(e,r.entries,o),delete this._pending[e],r.entries}catch(r){throw delete this._pending[e],r}}_tick(e){let r=this._nextRemovalTime;(!r||e{this._nextRemovalTime=!1;let o=1/0,a=Date.now();for(let[n,u]of this._cache){let A=u[qoe];a>=A?this._cache.delete(n):A("lookup"in r||(r.lookup=this.lookup),e[Cy](r,o))}uninstall(e){if(joe(e),e[Cy]){if(e[h4]!==this)throw new Error("The agent is not owned by this CacheableLookup instance");e.createConnection=e[Cy],delete e[Cy],delete e[h4]}}updateInterfaceInfo(){let{_iface:e}=this;this._iface=Goe(),(e.has4&&!this._iface.has4||e.has6&&!this._iface.has6)&&this._cache.clear()}clear(e){if(e){this._cache.delete(e);return}this._cache.clear()}};g4.exports=xb;g4.exports.default=xb});var Joe=_((WNt,d4)=>{"use strict";var zrt=typeof URL>"u"?ve("url").URL:URL,Jrt="text/plain",Xrt="us-ascii",Voe=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),Zrt=(t,{stripHash:e})=>{let r=t.match(/^data:([^,]*?),([^#]*?)(?:#(.*))?$/);if(!r)throw new Error(`Invalid URL: ${t}`);let o=r[1].split(";"),a=r[2],n=e?"":r[3],u=!1;o[o.length-1]==="base64"&&(o.pop(),u=!0);let A=(o.shift()||"").toLowerCase(),h=[...o.map(E=>{let[I,D=""]=E.split("=").map(x=>x.trim());return I==="charset"&&(D=D.toLowerCase(),D===Xrt)?"":`${I}${D?`=${D}`:""}`}).filter(Boolean)];return u&&h.push("base64"),(h.length!==0||A&&A!==Jrt)&&h.unshift(A),`data:${h.join(";")},${u?a.trim():a}${n?`#${n}`:""}`},zoe=(t,e)=>{if(e={defaultProtocol:"http:",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripWWW:!0,removeQueryParameters:[/^utm_\w+/i],removeTrailingSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},Reflect.has(e,"normalizeHttps"))throw new Error("options.normalizeHttps is renamed to options.forceHttp");if(Reflect.has(e,"normalizeHttp"))throw new Error("options.normalizeHttp is renamed to options.forceHttps");if(Reflect.has(e,"stripFragment"))throw new Error("options.stripFragment is renamed to options.stripHash");if(t=t.trim(),/^data:/i.test(t))return Zrt(t,e);let r=t.startsWith("//");!r&&/^\.*\//.test(t)||(t=t.replace(/^(?!(?:\w+:)?\/\/)|^\/\//,e.defaultProtocol));let a=new zrt(t);if(e.forceHttp&&e.forceHttps)throw new Error("The `forceHttp` and `forceHttps` options cannot be used together");if(e.forceHttp&&a.protocol==="https:"&&(a.protocol="http:"),e.forceHttps&&a.protocol==="http:"&&(a.protocol="https:"),e.stripAuthentication&&(a.username="",a.password=""),e.stripHash&&(a.hash=""),a.pathname&&(a.pathname=a.pathname.replace(/((?!:).|^)\/{2,}/g,(n,u)=>/^(?!\/)/g.test(u)?`${u}/`:"/")),a.pathname&&(a.pathname=decodeURI(a.pathname)),e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let n=a.pathname.split("/"),u=n[n.length-1];Voe(u,e.removeDirectoryIndex)&&(n=n.slice(0,n.length-1),a.pathname=n.slice(1).join("/")+"/")}if(a.hostname&&(a.hostname=a.hostname.replace(/\.$/,""),e.stripWWW&&/^www\.([a-z\-\d]{2,63})\.([a-z.]{2,5})$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\./,""))),Array.isArray(e.removeQueryParameters))for(let n of[...a.searchParams.keys()])Voe(n,e.removeQueryParameters)&&a.searchParams.delete(n);return e.sortQueryParameters&&a.searchParams.sort(),e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\/$/,"")),t=a.toString(),(e.removeTrailingSlash||a.pathname==="/")&&a.hash===""&&(t=t.replace(/\/$/,"")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\/\//,"//")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\/\//,"")),t};d4.exports=zoe;d4.exports.default=zoe});var $oe=_((KNt,Zoe)=>{Zoe.exports=Xoe;function Xoe(t,e){if(t&&e)return Xoe(t)(e);if(typeof t!="function")throw new TypeError("need wrapper function");return Object.keys(t).forEach(function(o){r[o]=t[o]}),r;function r(){for(var o=new Array(arguments.length),a=0;a{var eae=$oe();m4.exports=eae(kb);m4.exports.strict=eae(tae);kb.proto=kb(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return kb(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return tae(this)},configurable:!0})});function kb(t){var e=function(){return e.called?e.value:(e.called=!0,e.value=t.apply(this,arguments))};return e.called=!1,e}function tae(t){var e=function(){if(e.called)throw new Error(e.onceError);return e.called=!0,e.value=t.apply(this,arguments)},r=t.name||"Function wrapped with `once`";return e.onceError=r+" shouldn't be called more than once",e.called=!1,e}});var E4=_((zNt,nae)=>{var $rt=y4(),ent=function(){},tnt=function(t){return t.setHeader&&typeof t.abort=="function"},rnt=function(t){return t.stdio&&Array.isArray(t.stdio)&&t.stdio.length===3},rae=function(t,e,r){if(typeof e=="function")return rae(t,null,e);e||(e={}),r=$rt(r||ent);var o=t._writableState,a=t._readableState,n=e.readable||e.readable!==!1&&t.readable,u=e.writable||e.writable!==!1&&t.writable,A=function(){t.writable||p()},p=function(){u=!1,n||r.call(t)},h=function(){n=!1,u||r.call(t)},E=function(C){r.call(t,C?new Error("exited with error code: "+C):null)},I=function(C){r.call(t,C)},D=function(){if(n&&!(a&&a.ended))return r.call(t,new Error("premature close"));if(u&&!(o&&o.ended))return r.call(t,new Error("premature close"))},x=function(){t.req.on("finish",p)};return tnt(t)?(t.on("complete",p),t.on("abort",D),t.req?x():t.on("request",x)):u&&!o&&(t.on("end",A),t.on("close",A)),rnt(t)&&t.on("exit",E),t.on("end",h),t.on("finish",p),e.error!==!1&&t.on("error",I),t.on("close",D),function(){t.removeListener("complete",p),t.removeListener("abort",D),t.removeListener("request",x),t.req&&t.req.removeListener("finish",p),t.removeListener("end",A),t.removeListener("close",A),t.removeListener("finish",p),t.removeListener("exit",E),t.removeListener("end",h),t.removeListener("error",I),t.removeListener("close",D)}};nae.exports=rae});var oae=_((JNt,sae)=>{var nnt=y4(),int=E4(),C4=ve("fs"),Q1=function(){},snt=/^v?\.0/.test(process.version),Qb=function(t){return typeof t=="function"},ont=function(t){return!snt||!C4?!1:(t instanceof(C4.ReadStream||Q1)||t instanceof(C4.WriteStream||Q1))&&Qb(t.close)},ant=function(t){return t.setHeader&&Qb(t.abort)},lnt=function(t,e,r,o){o=nnt(o);var a=!1;t.on("close",function(){a=!0}),int(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,ont(t))return t.close(Q1);if(ant(t))return t.abort();if(Qb(t.destroy))return t.destroy();o(u||new Error("stream was destroyed"))}}},iae=function(t){t()},cnt=function(t,e){return t.pipe(e)},unt=function(){var t=Array.prototype.slice.call(arguments),e=Qb(t[t.length-1]||Q1)&&t.pop()||Q1;if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new Error("pump requires two streams per minimum");var r,o=t.map(function(a,n){var u=n0;return lnt(a,u,A,function(p){r||(r=p),p&&o.forEach(iae),!u&&(o.forEach(iae),e(r))})});return t.reduce(cnt)};sae.exports=unt});var lae=_((XNt,aae)=>{"use strict";var{PassThrough:Ant}=ve("stream");aae.exports=t=>{t={...t};let{array:e}=t,{encoding:r}=t,o=r==="buffer",a=!1;e?a=!(r||o):r=r||"utf8",o&&(r=null);let n=new Ant({objectMode:a});r&&n.setEncoding(r);let u=0,A=[];return n.on("data",p=>{A.push(p),a?u=A.length:u+=p.length}),n.getBufferedValue=()=>e?A:o?Buffer.concat(A,u):A.join(""),n.getBufferedLength=()=>u,n}});var cae=_((ZNt,wy)=>{"use strict";var fnt=oae(),pnt=lae(),Fb=class extends Error{constructor(){super("maxBuffer exceeded"),this.name="MaxBufferError"}};async function Rb(t,e){if(!t)return Promise.reject(new Error("Expected a stream"));e={maxBuffer:1/0,...e};let{maxBuffer:r}=e,o;return await new Promise((a,n)=>{let u=A=>{A&&(A.bufferedData=o.getBufferedValue()),n(A)};o=fnt(t,pnt(e),A=>{if(A){u(A);return}a()}),o.on("data",()=>{o.getBufferedLength()>r&&u(new Fb)})}),o.getBufferedValue()}wy.exports=Rb;wy.exports.default=Rb;wy.exports.buffer=(t,e)=>Rb(t,{...e,encoding:"buffer"});wy.exports.array=(t,e)=>Rb(t,{...e,array:!0});wy.exports.MaxBufferError=Fb});var Aae=_((eLt,uae)=>{"use strict";var hnt=new Set([200,203,204,206,300,301,308,404,405,410,414,501]),gnt=new Set([200,203,204,300,301,302,303,307,308,404,405,410,414,501]),dnt=new Set([500,502,503,504]),mnt={date:!0,connection:!0,"keep-alive":!0,"proxy-authenticate":!0,"proxy-authorization":!0,te:!0,trailer:!0,"transfer-encoding":!0,upgrade:!0},ynt={"content-length":!0,"content-encoding":!0,"transfer-encoding":!0,"content-range":!0};function Sg(t){let e=parseInt(t,10);return isFinite(e)?e:0}function Ent(t){return t?dnt.has(t.status):!0}function w4(t){let e={};if(!t)return e;let r=t.trim().split(/,/);for(let o of r){let[a,n]=o.split(/=/,2);e[a.trim()]=n===void 0?!0:n.trim().replace(/^"|"$/g,"")}return e}function Cnt(t){let e=[];for(let r in t){let o=t[r];e.push(o===!0?r:r+"="+o)}if(e.length)return e.join(", ")}uae.exports=class{constructor(e,r,{shared:o,cacheHeuristic:a,immutableMinTimeToLive:n,ignoreCargoCult:u,_fromObject:A}={}){if(A){this._fromObject(A);return}if(!r||!r.headers)throw Error("Response headers missing");this._assertRequestHasHeaders(e),this._responseTime=this.now(),this._isShared=o!==!1,this._cacheHeuristic=a!==void 0?a:.1,this._immutableMinTtl=n!==void 0?n:24*3600*1e3,this._status="status"in r?r.status:200,this._resHeaders=r.headers,this._rescc=w4(r.headers["cache-control"]),this._method="method"in e?e.method:"GET",this._url=e.url,this._host=e.headers.host,this._noAuthorization=!e.headers.authorization,this._reqHeaders=r.headers.vary?e.headers:null,this._reqcc=w4(e.headers["cache-control"]),u&&"pre-check"in this._rescc&&"post-check"in this._rescc&&(delete this._rescc["pre-check"],delete this._rescc["post-check"],delete this._rescc["no-cache"],delete this._rescc["no-store"],delete this._rescc["must-revalidate"],this._resHeaders=Object.assign({},this._resHeaders,{"cache-control":Cnt(this._rescc)}),delete this._resHeaders.expires,delete this._resHeaders.pragma),r.headers["cache-control"]==null&&/no-cache/.test(r.headers.pragma)&&(this._rescc["no-cache"]=!0)}now(){return Date.now()}storable(){return!!(!this._reqcc["no-store"]&&(this._method==="GET"||this._method==="HEAD"||this._method==="POST"&&this._hasExplicitExpiration())&&gnt.has(this._status)&&!this._rescc["no-store"]&&(!this._isShared||!this._rescc.private)&&(!this._isShared||this._noAuthorization||this._allowsStoringAuthenticated())&&(this._resHeaders.expires||this._rescc["max-age"]||this._isShared&&this._rescc["s-maxage"]||this._rescc.public||hnt.has(this._status)))}_hasExplicitExpiration(){return this._isShared&&this._rescc["s-maxage"]||this._rescc["max-age"]||this._resHeaders.expires}_assertRequestHasHeaders(e){if(!e||!e.headers)throw Error("Request headers missing")}satisfiesWithoutRevalidation(e){this._assertRequestHasHeaders(e);let r=w4(e.headers["cache-control"]);return r["no-cache"]||/no-cache/.test(e.headers.pragma)||r["max-age"]&&this.age()>r["max-age"]||r["min-fresh"]&&this.timeToLive()<1e3*r["min-fresh"]||this.stale()&&!(r["max-stale"]&&!this._rescc["must-revalidate"]&&(r["max-stale"]===!0||r["max-stale"]>this.age()-this.maxAge()))?!1:this._requestMatches(e,!1)}_requestMatches(e,r){return(!this._url||this._url===e.url)&&this._host===e.headers.host&&(!e.method||this._method===e.method||r&&e.method==="HEAD")&&this._varyMatches(e)}_allowsStoringAuthenticated(){return this._rescc["must-revalidate"]||this._rescc.public||this._rescc["s-maxage"]}_varyMatches(e){if(!this._resHeaders.vary)return!0;if(this._resHeaders.vary==="*")return!1;let r=this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);for(let o of r)if(e.headers[o]!==this._reqHeaders[o])return!1;return!0}_copyWithoutHopByHopHeaders(e){let r={};for(let o in e)mnt[o]||(r[o]=e[o]);if(e.connection){let o=e.connection.trim().split(/\s*,\s*/);for(let a of o)delete r[a]}if(r.warning){let o=r.warning.split(/,/).filter(a=>!/^\s*1[0-9][0-9]/.test(a));o.length?r.warning=o.join(",").trim():delete r.warning}return r}responseHeaders(){let e=this._copyWithoutHopByHopHeaders(this._resHeaders),r=this.age();return r>3600*24&&!this._hasExplicitExpiration()&&this.maxAge()>3600*24&&(e.warning=(e.warning?`${e.warning}, `:"")+'113 - "rfc7234 5.5.4"'),e.age=`${Math.round(r)}`,e.date=new Date(this.now()).toUTCString(),e}date(){let e=Date.parse(this._resHeaders.date);return isFinite(e)?e:this._responseTime}age(){let e=this._ageValue(),r=(this.now()-this._responseTime)/1e3;return e+r}_ageValue(){return Sg(this._resHeaders.age)}maxAge(){if(!this.storable()||this._rescc["no-cache"]||this._isShared&&this._resHeaders["set-cookie"]&&!this._rescc.public&&!this._rescc.immutable||this._resHeaders.vary==="*")return 0;if(this._isShared){if(this._rescc["proxy-revalidate"])return 0;if(this._rescc["s-maxage"])return Sg(this._rescc["s-maxage"])}if(this._rescc["max-age"])return Sg(this._rescc["max-age"]);let e=this._rescc.immutable?this._immutableMinTtl:0,r=this.date();if(this._resHeaders.expires){let o=Date.parse(this._resHeaders.expires);return Number.isNaN(o)||oo)return Math.max(e,(r-o)/1e3*this._cacheHeuristic)}return e}timeToLive(){let e=this.maxAge()-this.age(),r=e+Sg(this._rescc["stale-if-error"]),o=e+Sg(this._rescc["stale-while-revalidate"]);return Math.max(0,e,r,o)*1e3}stale(){return this.maxAge()<=this.age()}_useStaleIfError(){return this.maxAge()+Sg(this._rescc["stale-if-error"])>this.age()}useStaleWhileRevalidate(){return this.maxAge()+Sg(this._rescc["stale-while-revalidate"])>this.age()}static fromObject(e){return new this(void 0,void 0,{_fromObject:e})}_fromObject(e){if(this._responseTime)throw Error("Reinitialized");if(!e||e.v!==1)throw Error("Invalid serialization");this._responseTime=e.t,this._isShared=e.sh,this._cacheHeuristic=e.ch,this._immutableMinTtl=e.imm!==void 0?e.imm:24*3600*1e3,this._status=e.st,this._resHeaders=e.resh,this._rescc=e.rescc,this._method=e.m,this._url=e.u,this._host=e.h,this._noAuthorization=e.a,this._reqHeaders=e.reqh,this._reqcc=e.reqcc}toObject(){return{v:1,t:this._responseTime,sh:this._isShared,ch:this._cacheHeuristic,imm:this._immutableMinTtl,st:this._status,resh:this._resHeaders,rescc:this._rescc,m:this._method,u:this._url,h:this._host,a:this._noAuthorization,reqh:this._reqHeaders,reqcc:this._reqcc}}revalidationHeaders(e){this._assertRequestHasHeaders(e);let r=this._copyWithoutHopByHopHeaders(e.headers);if(delete r["if-range"],!this._requestMatches(e,!0)||!this.storable())return delete r["if-none-match"],delete r["if-modified-since"],r;if(this._resHeaders.etag&&(r["if-none-match"]=r["if-none-match"]?`${r["if-none-match"]}, ${this._resHeaders.etag}`:this._resHeaders.etag),r["accept-ranges"]||r["if-match"]||r["if-unmodified-since"]||this._method&&this._method!="GET"){if(delete r["if-modified-since"],r["if-none-match"]){let a=r["if-none-match"].split(/,/).filter(n=>!/^\s*W\//.test(n));a.length?r["if-none-match"]=a.join(",").trim():delete r["if-none-match"]}}else this._resHeaders["last-modified"]&&!r["if-modified-since"]&&(r["if-modified-since"]=this._resHeaders["last-modified"]);return r}revalidatedPolicy(e,r){if(this._assertRequestHasHeaders(e),this._useStaleIfError()&&Ent(r))return{modified:!1,matches:!1,policy:this};if(!r||!r.headers)throw Error("Response headers missing");let o=!1;if(r.status!==void 0&&r.status!=304?o=!1:r.headers.etag&&!/^\s*W\//.test(r.headers.etag)?o=this._resHeaders.etag&&this._resHeaders.etag.replace(/^\s*W\//,"")===r.headers.etag:this._resHeaders.etag&&r.headers.etag?o=this._resHeaders.etag.replace(/^\s*W\//,"")===r.headers.etag.replace(/^\s*W\//,""):this._resHeaders["last-modified"]?o=this._resHeaders["last-modified"]===r.headers["last-modified"]:!this._resHeaders.etag&&!this._resHeaders["last-modified"]&&!r.headers.etag&&!r.headers["last-modified"]&&(o=!0),!o)return{policy:new this.constructor(e,r),modified:r.status!=304,matches:!1};let a={};for(let u in this._resHeaders)a[u]=u in r.headers&&!ynt[u]?r.headers[u]:this._resHeaders[u];let n=Object.assign({},r,{status:this._status,method:this._method,headers:a});return{policy:new this.constructor(e,n,{shared:this._isShared,cacheHeuristic:this._cacheHeuristic,immutableMinTimeToLive:this._immutableMinTtl}),modified:!1,matches:!0}}}});var Tb=_((tLt,fae)=>{"use strict";fae.exports=t=>{let e={};for(let[r,o]of Object.entries(t))e[r.toLowerCase()]=o;return e}});var hae=_((rLt,pae)=>{"use strict";var wnt=ve("stream").Readable,Int=Tb(),I4=class extends wnt{constructor(e,r,o,a){if(typeof e!="number")throw new TypeError("Argument `statusCode` should be a number");if(typeof r!="object")throw new TypeError("Argument `headers` should be an object");if(!(o instanceof Buffer))throw new TypeError("Argument `body` should be a buffer");if(typeof a!="string")throw new TypeError("Argument `url` should be a string");super(),this.statusCode=e,this.headers=Int(r),this.body=o,this.url=a}_read(){this.push(this.body),this.push(null)}};pae.exports=I4});var dae=_((nLt,gae)=>{"use strict";var Bnt=["destroy","setTimeout","socket","headers","trailers","rawHeaders","statusCode","httpVersion","httpVersionMinor","httpVersionMajor","rawTrailers","statusMessage"];gae.exports=(t,e)=>{let r=new Set(Object.keys(t).concat(Bnt));for(let o of r)o in e||(e[o]=typeof t[o]=="function"?t[o].bind(t):t[o])}});var yae=_((iLt,mae)=>{"use strict";var vnt=ve("stream").PassThrough,Dnt=dae(),Pnt=t=>{if(!(t&&t.pipe))throw new TypeError("Parameter `response` must be a response stream.");let e=new vnt;return Dnt(t,e),t.pipe(e)};mae.exports=Pnt});var Eae=_(B4=>{B4.stringify=function t(e){if(typeof e>"u")return e;if(e&&Buffer.isBuffer(e))return JSON.stringify(":base64:"+e.toString("base64"));if(e&&e.toJSON&&(e=e.toJSON()),e&&typeof e=="object"){var r="",o=Array.isArray(e);r=o?"[":"{";var a=!0;for(var n in e){var u=typeof e[n]=="function"||!o&&typeof e[n]>"u";Object.hasOwnProperty.call(e,n)&&!u&&(a||(r+=","),a=!1,o?e[n]==null?r+="null":r+=t(e[n]):e[n]!==void 0&&(r+=t(n)+":"+t(e[n])))}return r+=o?"]":"}",r}else return typeof e=="string"?JSON.stringify(/^:/.test(e)?":"+e:e):typeof e>"u"?"null":JSON.stringify(e)};B4.parse=function(t){return JSON.parse(t,function(e,r){return typeof r=="string"?/^:base64:/.test(r)?Buffer.from(r.substring(8),"base64"):/^:/.test(r)?r.substring(1):r:r})}});var Bae=_((oLt,Iae)=>{"use strict";var Snt=ve("events"),Cae=Eae(),bnt=t=>{let e={redis:"@keyv/redis",rediss:"@keyv/redis",mongodb:"@keyv/mongo",mongo:"@keyv/mongo",sqlite:"@keyv/sqlite",postgresql:"@keyv/postgres",postgres:"@keyv/postgres",mysql:"@keyv/mysql",etcd:"@keyv/etcd",offline:"@keyv/offline",tiered:"@keyv/tiered"};if(t.adapter||t.uri){let r=t.adapter||/^[^:+]*/.exec(t.uri)[0];return new(ve(e[r]))(t)}return new Map},wae=["sqlite","postgres","mysql","mongo","redis","tiered"],v4=class extends Snt{constructor(e,{emitErrors:r=!0,...o}={}){if(super(),this.opts={namespace:"keyv",serialize:Cae.stringify,deserialize:Cae.parse,...typeof e=="string"?{uri:e}:e,...o},!this.opts.store){let n={...this.opts};this.opts.store=bnt(n)}if(this.opts.compression){let n=this.opts.compression;this.opts.serialize=n.serialize.bind(n),this.opts.deserialize=n.deserialize.bind(n)}typeof this.opts.store.on=="function"&&r&&this.opts.store.on("error",n=>this.emit("error",n)),this.opts.store.namespace=this.opts.namespace;let a=n=>async function*(){for await(let[u,A]of typeof n=="function"?n(this.opts.store.namespace):n){let p=await this.opts.deserialize(A);if(!(this.opts.store.namespace&&!u.includes(this.opts.store.namespace))){if(typeof p.expires=="number"&&Date.now()>p.expires){this.delete(u);continue}yield[this._getKeyUnprefix(u),p.value]}}};typeof this.opts.store[Symbol.iterator]=="function"&&this.opts.store instanceof Map?this.iterator=a(this.opts.store):typeof this.opts.store.iterator=="function"&&this.opts.store.opts&&this._checkIterableAdaptar()&&(this.iterator=a(this.opts.store.iterator.bind(this.opts.store)))}_checkIterableAdaptar(){return wae.includes(this.opts.store.opts.dialect)||wae.findIndex(e=>this.opts.store.opts.url.includes(e))>=0}_getKeyPrefix(e){return`${this.opts.namespace}:${e}`}_getKeyPrefixArray(e){return e.map(r=>`${this.opts.namespace}:${r}`)}_getKeyUnprefix(e){return e.split(":").splice(1).join(":")}get(e,r){let{store:o}=this.opts,a=Array.isArray(e),n=a?this._getKeyPrefixArray(e):this._getKeyPrefix(e);if(a&&o.getMany===void 0){let u=[];for(let A of n)u.push(Promise.resolve().then(()=>o.get(A)).then(p=>typeof p=="string"?this.opts.deserialize(p):this.opts.compression?this.opts.deserialize(p):p).then(p=>{if(p!=null)return typeof p.expires=="number"&&Date.now()>p.expires?this.delete(A).then(()=>{}):r&&r.raw?p:p.value}));return Promise.allSettled(u).then(A=>{let p=[];for(let h of A)p.push(h.value);return p})}return Promise.resolve().then(()=>a?o.getMany(n):o.get(n)).then(u=>typeof u=="string"?this.opts.deserialize(u):this.opts.compression?this.opts.deserialize(u):u).then(u=>{if(u!=null)return a?u.map((A,p)=>{if(typeof A=="string"&&(A=this.opts.deserialize(A)),A!=null){if(typeof A.expires=="number"&&Date.now()>A.expires){this.delete(e[p]).then(()=>{});return}return r&&r.raw?A:A.value}}):typeof u.expires=="number"&&Date.now()>u.expires?this.delete(e).then(()=>{}):r&&r.raw?u:u.value})}set(e,r,o){let a=this._getKeyPrefix(e);typeof o>"u"&&(o=this.opts.ttl),o===0&&(o=void 0);let{store:n}=this.opts;return Promise.resolve().then(()=>{let u=typeof o=="number"?Date.now()+o:null;return typeof r=="symbol"&&this.emit("error","symbol cannot be serialized"),r={value:r,expires:u},this.opts.serialize(r)}).then(u=>n.set(a,u,o)).then(()=>!0)}delete(e){let{store:r}=this.opts;if(Array.isArray(e)){let a=this._getKeyPrefixArray(e);if(r.deleteMany===void 0){let n=[];for(let u of a)n.push(r.delete(u));return Promise.allSettled(n).then(u=>u.every(A=>A.value===!0))}return Promise.resolve().then(()=>r.deleteMany(a))}let o=this._getKeyPrefix(e);return Promise.resolve().then(()=>r.delete(o))}clear(){let{store:e}=this.opts;return Promise.resolve().then(()=>e.clear())}has(e){let r=this._getKeyPrefix(e),{store:o}=this.opts;return Promise.resolve().then(async()=>typeof o.has=="function"?o.has(r):await o.get(r)!==void 0)}disconnect(){let{store:e}=this.opts;if(typeof e.disconnect=="function")return e.disconnect()}};Iae.exports=v4});var Pae=_((lLt,Dae)=>{"use strict";var xnt=ve("events"),Nb=ve("url"),knt=Joe(),Qnt=cae(),D4=Aae(),vae=hae(),Fnt=Tb(),Rnt=yae(),Tnt=Bae(),F1=class t{constructor(e,r){if(typeof e!="function")throw new TypeError("Parameter `request` must be a function");return this.cache=new Tnt({uri:typeof r=="string"&&r,store:typeof r!="string"&&r,namespace:"cacheable-request"}),this.createCacheableRequest(e)}createCacheableRequest(e){return(r,o)=>{let a;if(typeof r=="string")a=P4(Nb.parse(r)),r={};else if(r instanceof Nb.URL)a=P4(Nb.parse(r.toString())),r={};else{let[I,...D]=(r.path||"").split("?"),x=D.length>0?`?${D.join("?")}`:"";a=P4({...r,pathname:I,search:x})}r={headers:{},method:"GET",cache:!0,strictTtl:!1,automaticFailover:!1,...r,...Nnt(a)},r.headers=Fnt(r.headers);let n=new xnt,u=knt(Nb.format(a),{stripWWW:!1,removeTrailingSlash:!1,stripAuthentication:!1}),A=`${r.method}:${u}`,p=!1,h=!1,E=I=>{h=!0;let D=!1,x,C=new Promise(L=>{x=()=>{D||(D=!0,L())}}),T=L=>{if(p&&!I.forceRefresh){L.status=L.statusCode;let z=D4.fromObject(p.cachePolicy).revalidatedPolicy(I,L);if(!z.modified){let te=z.policy.responseHeaders();L=new vae(p.statusCode,te,p.body,p.url),L.cachePolicy=z.policy,L.fromCache=!0}}L.fromCache||(L.cachePolicy=new D4(I,L,I),L.fromCache=!1);let U;I.cache&&L.cachePolicy.storable()?(U=Rnt(L),(async()=>{try{let z=Qnt.buffer(L);if(await Promise.race([C,new Promise(ue=>L.once("end",ue))]),D)return;let te=await z,le={cachePolicy:L.cachePolicy.toObject(),url:L.url,statusCode:L.fromCache?p.statusCode:L.statusCode,body:te},ce=I.strictTtl?L.cachePolicy.timeToLive():void 0;I.maxTtl&&(ce=ce?Math.min(ce,I.maxTtl):I.maxTtl),await this.cache.set(A,le,ce)}catch(z){n.emit("error",new t.CacheError(z))}})()):I.cache&&p&&(async()=>{try{await this.cache.delete(A)}catch(z){n.emit("error",new t.CacheError(z))}})(),n.emit("response",U||L),typeof o=="function"&&o(U||L)};try{let L=e(I,T);L.once("error",x),L.once("abort",x),n.emit("request",L)}catch(L){n.emit("error",new t.RequestError(L))}};return(async()=>{let I=async x=>{await Promise.resolve();let C=x.cache?await this.cache.get(A):void 0;if(typeof C>"u")return E(x);let T=D4.fromObject(C.cachePolicy);if(T.satisfiesWithoutRevalidation(x)&&!x.forceRefresh){let L=T.responseHeaders(),U=new vae(C.statusCode,L,C.body,C.url);U.cachePolicy=T,U.fromCache=!0,n.emit("response",U),typeof o=="function"&&o(U)}else p=C,x.headers=T.revalidationHeaders(x),E(x)},D=x=>n.emit("error",new t.CacheError(x));this.cache.once("error",D),n.on("response",()=>this.cache.removeListener("error",D));try{await I(r)}catch(x){r.automaticFailover&&!h&&E(r),n.emit("error",new t.CacheError(x))}})(),n}}};function Nnt(t){let e={...t};return e.path=`${t.pathname||"/"}${t.search||""}`,delete e.pathname,delete e.search,e}function P4(t){return{protocol:t.protocol,auth:t.auth,hostname:t.hostname||t.host||"localhost",port:t.port,pathname:t.pathname,search:t.search}}F1.RequestError=class extends Error{constructor(t){super(t.message),this.name="RequestError",Object.assign(this,t)}};F1.CacheError=class extends Error{constructor(t){super(t.message),this.name="CacheError",Object.assign(this,t)}};Dae.exports=F1});var bae=_((ALt,Sae)=>{"use strict";var Lnt=["aborted","complete","headers","httpVersion","httpVersionMinor","httpVersionMajor","method","rawHeaders","rawTrailers","setTimeout","socket","statusCode","statusMessage","trailers","url"];Sae.exports=(t,e)=>{if(e._readableState.autoDestroy)throw new Error("The second stream must have the `autoDestroy` option set to `false`");let r=new Set(Object.keys(t).concat(Lnt)),o={};for(let a of r)a in e||(o[a]={get(){let n=t[a];return typeof n=="function"?n.bind(t):n},set(n){t[a]=n},enumerable:!0,configurable:!1});return Object.defineProperties(e,o),t.once("aborted",()=>{e.destroy(),e.emit("aborted")}),t.once("close",()=>{t.complete&&e.readable?e.once("end",()=>{e.emit("close")}):e.emit("close")}),e}});var kae=_((fLt,xae)=>{"use strict";var{Transform:Mnt,PassThrough:Ont}=ve("stream"),S4=ve("zlib"),Unt=bae();xae.exports=t=>{let e=(t.headers["content-encoding"]||"").toLowerCase();if(!["gzip","deflate","br"].includes(e))return t;let r=e==="br";if(r&&typeof S4.createBrotliDecompress!="function")return t.destroy(new Error("Brotli is not supported on Node.js < 12")),t;let o=!0,a=new Mnt({transform(A,p,h){o=!1,h(null,A)},flush(A){A()}}),n=new Ont({autoDestroy:!1,destroy(A,p){t.destroy(),p(A)}}),u=r?S4.createBrotliDecompress():S4.createUnzip();return u.once("error",A=>{if(o&&!t.readable){n.end();return}n.destroy(A)}),Unt(t,n),t.pipe(a).pipe(u).pipe(n),n}});var x4=_((pLt,Qae)=>{"use strict";var b4=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError("`maxSize` must be a number greater than 0");this.maxSize=e.maxSize,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_set(e,r){if(this.cache.set(e,r),this._size++,this._size>=this.maxSize){if(this._size=0,typeof this.onEviction=="function")for(let[o,a]of this.oldCache.entries())this.onEviction(o,a);this.oldCache=this.cache,this.cache=new Map}}get(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e)){let r=this.oldCache.get(e);return this.oldCache.delete(e),this._set(e,r),r}}set(e,r){return this.cache.has(e)?this.cache.set(e,r):this._set(e,r),this}has(e){return this.cache.has(e)||this.oldCache.has(e)}peek(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e))return this.oldCache.get(e)}delete(e){let r=this.cache.delete(e);return r&&this._size--,this.oldCache.delete(e)||r}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache)yield e;for(let e of this.oldCache){let[r]=e;this.cache.has(r)||(yield e)}}get size(){let e=0;for(let r of this.oldCache.keys())this.cache.has(r)||e++;return Math.min(this._size+e,this.maxSize)}};Qae.exports=b4});var Q4=_((hLt,Nae)=>{"use strict";var _nt=ve("events"),Hnt=ve("tls"),qnt=ve("http2"),jnt=x4(),ea=Symbol("currentStreamsCount"),Fae=Symbol("request"),zl=Symbol("cachedOriginSet"),Iy=Symbol("gracefullyClosing"),Gnt=["maxDeflateDynamicTableSize","maxSessionMemory","maxHeaderListPairs","maxOutstandingPings","maxReservedRemoteStreams","maxSendHeaderBlockLength","paddingStrategy","localAddress","path","rejectUnauthorized","minDHSize","ca","cert","clientCertEngine","ciphers","key","pfx","servername","minVersion","maxVersion","secureProtocol","crl","honorCipherOrder","ecdhCurve","dhparam","secureOptions","sessionIdContext"],Ynt=(t,e,r)=>{let o=0,a=t.length;for(;o>>1;r(t[n],e)?o=n+1:a=n}return o},Wnt=(t,e)=>t.remoteSettings.maxConcurrentStreams>e.remoteSettings.maxConcurrentStreams,k4=(t,e)=>{for(let r of t)r[zl].lengthe[zl].includes(o))&&r[ea]+e[ea]<=e.remoteSettings.maxConcurrentStreams&&Tae(r)},Knt=(t,e)=>{for(let r of t)e[zl].lengthr[zl].includes(o))&&e[ea]+r[ea]<=r.remoteSettings.maxConcurrentStreams&&Tae(e)},Rae=({agent:t,isFree:e})=>{let r={};for(let o in t.sessions){let n=t.sessions[o].filter(u=>{let A=u[bg.kCurrentStreamsCount]{t[Iy]=!0,t[ea]===0&&t.close()},bg=class t extends _nt{constructor({timeout:e=6e4,maxSessions:r=1/0,maxFreeSessions:o=10,maxCachedTlsSessions:a=100}={}){super(),this.sessions={},this.queue={},this.timeout=e,this.maxSessions=r,this.maxFreeSessions=o,this._freeSessionsCount=0,this._sessionsCount=0,this.settings={enablePush:!1},this.tlsSessionCache=new jnt({maxSize:a})}static normalizeOrigin(e,r){return typeof e=="string"&&(e=new URL(e)),r&&e.hostname!==r&&(e.hostname=r),e.origin}normalizeOptions(e){let r="";if(e)for(let o of Gnt)e[o]&&(r+=`:${e[o]}`);return r}_tryToCreateNewSession(e,r){if(!(e in this.queue)||!(r in this.queue[e]))return;let o=this.queue[e][r];this._sessionsCount{Array.isArray(o)?(o=[...o],a()):o=[{resolve:a,reject:n}];let u=this.normalizeOptions(r),A=t.normalizeOrigin(e,r&&r.servername);if(A===void 0){for(let{reject:E}of o)E(new TypeError("The `origin` argument needs to be a string or an URL object"));return}if(u in this.sessions){let E=this.sessions[u],I=-1,D=-1,x;for(let C of E){let T=C.remoteSettings.maxConcurrentStreams;if(T=T||C[Iy]||C.destroyed)continue;x||(I=T),L>D&&(x=C,D=L)}}if(x){if(o.length!==1){for(let{reject:C}of o){let T=new Error(`Expected the length of listeners to be 1, got ${o.length}. +Please report this to https://github.com/szmarczak/http2-wrapper/`);C(T)}return}o[0].resolve(x);return}}if(u in this.queue){if(A in this.queue[u]){this.queue[u][A].listeners.push(...o),this._tryToCreateNewSession(u,A);return}}else this.queue[u]={};let p=()=>{u in this.queue&&this.queue[u][A]===h&&(delete this.queue[u][A],Object.keys(this.queue[u]).length===0&&delete this.queue[u])},h=()=>{let E=`${A}:${u}`,I=!1;try{let D=qnt.connect(e,{createConnection:this.createConnection,settings:this.settings,session:this.tlsSessionCache.get(E),...r});D[ea]=0,D[Iy]=!1;let x=()=>D[ea]{this.tlsSessionCache.set(E,L)}),D.once("error",L=>{for(let{reject:U}of o)U(L);this.tlsSessionCache.delete(E)}),D.setTimeout(this.timeout,()=>{D.destroy()}),D.once("close",()=>{if(I){C&&this._freeSessionsCount--,this._sessionsCount--;let L=this.sessions[u];L.splice(L.indexOf(D),1),L.length===0&&delete this.sessions[u]}else{let L=new Error("Session closed without receiving a SETTINGS frame");L.code="HTTP2WRAPPER_NOSETTINGS";for(let{reject:U}of o)U(L);p()}this._tryToCreateNewSession(u,A)});let T=()=>{if(!(!(u in this.queue)||!x())){for(let L of D[zl])if(L in this.queue[u]){let{listeners:U}=this.queue[u][L];for(;U.length!==0&&x();)U.shift().resolve(D);let z=this.queue[u];if(z[L].listeners.length===0&&(delete z[L],Object.keys(z).length===0)){delete this.queue[u];break}if(!x())break}}};D.on("origin",()=>{D[zl]=D.originSet,x()&&(T(),k4(this.sessions[u],D))}),D.once("remoteSettings",()=>{if(D.ref(),D.unref(),this._sessionsCount++,h.destroyed){let L=new Error("Agent has been destroyed");for(let U of o)U.reject(L);D.destroy();return}D[zl]=D.originSet;{let L=this.sessions;if(u in L){let U=L[u];U.splice(Ynt(U,D,Wnt),0,D)}else L[u]=[D]}this._freeSessionsCount+=1,I=!0,this.emit("session",D),T(),p(),D[ea]===0&&this._freeSessionsCount>this.maxFreeSessions&&D.close(),o.length!==0&&(this.getSession(A,r,o),o.length=0),D.on("remoteSettings",()=>{T(),k4(this.sessions[u],D)})}),D[Fae]=D.request,D.request=(L,U)=>{if(D[Iy])throw new Error("The session is gracefully closing. No new streams are allowed.");let z=D[Fae](L,U);return D.ref(),++D[ea],D[ea]===D.remoteSettings.maxConcurrentStreams&&this._freeSessionsCount--,z.once("close",()=>{if(C=x(),--D[ea],!D.destroyed&&!D.closed&&(Knt(this.sessions[u],D),x()&&!D.closed)){C||(this._freeSessionsCount++,C=!0);let te=D[ea]===0;te&&D.unref(),te&&(this._freeSessionsCount>this.maxFreeSessions||D[Iy])?D.close():(k4(this.sessions[u],D),T())}}),z}}catch(D){for(let x of o)x.reject(D);p()}};h.listeners=o,h.completed=!1,h.destroyed=!1,this.queue[u][A]=h,this._tryToCreateNewSession(u,A)})}request(e,r,o,a){return new Promise((n,u)=>{this.getSession(e,r,[{reject:u,resolve:A=>{try{n(A.request(o,a))}catch(p){u(p)}}}])})}createConnection(e,r){return t.connect(e,r)}static connect(e,r){r.ALPNProtocols=["h2"];let o=e.port||443,a=e.hostname||e.host;return typeof r.servername>"u"&&(r.servername=a),Hnt.connect(o,a,r)}closeFreeSessions(){for(let e of Object.values(this.sessions))for(let r of e)r[ea]===0&&r.close()}destroy(e){for(let r of Object.values(this.sessions))for(let o of r)o.destroy(e);for(let r of Object.values(this.queue))for(let o of Object.values(r))o.destroyed=!0;this.queue={}}get freeSessions(){return Rae({agent:this,isFree:!0})}get busySessions(){return Rae({agent:this,isFree:!1})}};bg.kCurrentStreamsCount=ea;bg.kGracefullyClosing=Iy;Nae.exports={Agent:bg,globalAgent:new bg}});var R4=_((gLt,Lae)=>{"use strict";var{Readable:Vnt}=ve("stream"),F4=class extends Vnt{constructor(e,r){super({highWaterMark:r,autoDestroy:!1}),this.statusCode=null,this.statusMessage="",this.httpVersion="2.0",this.httpVersionMajor=2,this.httpVersionMinor=0,this.headers={},this.trailers={},this.req=null,this.aborted=!1,this.complete=!1,this.upgrade=null,this.rawHeaders=[],this.rawTrailers=[],this.socket=e,this.connection=e,this._dumped=!1}_destroy(e){this.req._request.destroy(e)}setTimeout(e,r){return this.req.setTimeout(e,r),this}_dump(){this._dumped||(this._dumped=!0,this.removeAllListeners("data"),this.resume())}_read(){this.req&&this.req._request.resume()}};Lae.exports=F4});var T4=_((dLt,Mae)=>{"use strict";Mae.exports=t=>{let e={protocol:t.protocol,hostname:typeof t.hostname=="string"&&t.hostname.startsWith("[")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||""}${t.search||""}`};return typeof t.port=="string"&&t.port.length!==0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||""}:${t.password||""}`),e}});var Uae=_((mLt,Oae)=>{"use strict";Oae.exports=(t,e,r)=>{for(let o of r)t.on(o,(...a)=>e.emit(o,...a))}});var Hae=_((yLt,_ae)=>{"use strict";_ae.exports=t=>{switch(t){case":method":case":scheme":case":authority":case":path":return!0;default:return!1}}});var jae=_((CLt,qae)=>{"use strict";var By=(t,e,r)=>{qae.exports[e]=class extends t{constructor(...a){super(typeof r=="string"?r:r(a)),this.name=`${super.name} [${e}]`,this.code=e}}};By(TypeError,"ERR_INVALID_ARG_TYPE",t=>{let e=t[0].includes(".")?"property":"argument",r=t[1],o=Array.isArray(r);return o&&(r=`${r.slice(0,-1).join(", ")} or ${r.slice(-1)}`),`The "${t[0]}" ${e} must be ${o?"one of":"of"} type ${r}. Received ${typeof t[2]}`});By(TypeError,"ERR_INVALID_PROTOCOL",t=>`Protocol "${t[0]}" not supported. Expected "${t[1]}"`);By(Error,"ERR_HTTP_HEADERS_SENT",t=>`Cannot ${t[0]} headers after they are sent to the client`);By(TypeError,"ERR_INVALID_HTTP_TOKEN",t=>`${t[0]} must be a valid HTTP token [${t[1]}]`);By(TypeError,"ERR_HTTP_INVALID_HEADER_VALUE",t=>`Invalid value "${t[0]} for header "${t[1]}"`);By(TypeError,"ERR_INVALID_CHAR",t=>`Invalid character in ${t[0]} [${t[1]}]`)});var U4=_((wLt,Jae)=>{"use strict";var znt=ve("http2"),{Writable:Jnt}=ve("stream"),{Agent:Gae,globalAgent:Xnt}=Q4(),Znt=R4(),$nt=T4(),eit=Uae(),tit=Hae(),{ERR_INVALID_ARG_TYPE:N4,ERR_INVALID_PROTOCOL:rit,ERR_HTTP_HEADERS_SENT:Yae,ERR_INVALID_HTTP_TOKEN:nit,ERR_HTTP_INVALID_HEADER_VALUE:iit,ERR_INVALID_CHAR:sit}=jae(),{HTTP2_HEADER_STATUS:Wae,HTTP2_HEADER_METHOD:Kae,HTTP2_HEADER_PATH:Vae,HTTP2_METHOD_CONNECT:oit}=znt.constants,vo=Symbol("headers"),L4=Symbol("origin"),M4=Symbol("session"),zae=Symbol("options"),Lb=Symbol("flushedHeaders"),R1=Symbol("jobs"),ait=/^[\^`\-\w!#$%&*+.|~]+$/,lit=/[^\t\u0020-\u007E\u0080-\u00FF]/,O4=class extends Jnt{constructor(e,r,o){super({autoDestroy:!1});let a=typeof e=="string"||e instanceof URL;if(a&&(e=$nt(e instanceof URL?e:new URL(e))),typeof r=="function"||r===void 0?(o=r,r=a?e:{...e}):r={...e,...r},r.h2session)this[M4]=r.h2session;else if(r.agent===!1)this.agent=new Gae({maxFreeSessions:0});else if(typeof r.agent>"u"||r.agent===null)typeof r.createConnection=="function"?(this.agent=new Gae({maxFreeSessions:0}),this.agent.createConnection=r.createConnection):this.agent=Xnt;else if(typeof r.agent.request=="function")this.agent=r.agent;else throw new N4("options.agent",["Agent-like Object","undefined","false"],r.agent);if(r.protocol&&r.protocol!=="https:")throw new rit(r.protocol,"https:");let n=r.port||r.defaultPort||this.agent&&this.agent.defaultPort||443,u=r.hostname||r.host||"localhost";delete r.hostname,delete r.host,delete r.port;let{timeout:A}=r;if(r.timeout=void 0,this[vo]=Object.create(null),this[R1]=[],this.socket=null,this.connection=null,this.method=r.method||"GET",this.path=r.path,this.res=null,this.aborted=!1,this.reusedSocket=!1,r.headers)for(let[p,h]of Object.entries(r.headers))this.setHeader(p,h);r.auth&&!("authorization"in this[vo])&&(this[vo].authorization="Basic "+Buffer.from(r.auth).toString("base64")),r.session=r.tlsSession,r.path=r.socketPath,this[zae]=r,n===443?(this[L4]=`https://${u}`,":authority"in this[vo]||(this[vo][":authority"]=u)):(this[L4]=`https://${u}:${n}`,":authority"in this[vo]||(this[vo][":authority"]=`${u}:${n}`)),A&&this.setTimeout(A),o&&this.once("response",o),this[Lb]=!1}get method(){return this[vo][Kae]}set method(e){e&&(this[vo][Kae]=e.toUpperCase())}get path(){return this[vo][Vae]}set path(e){e&&(this[vo][Vae]=e)}get _mustNotHaveABody(){return this.method==="GET"||this.method==="HEAD"||this.method==="DELETE"}_write(e,r,o){if(this._mustNotHaveABody){o(new Error("The GET, HEAD and DELETE methods must NOT have a body"));return}this.flushHeaders();let a=()=>this._request.write(e,r,o);this._request?a():this[R1].push(a)}_final(e){if(this.destroyed)return;this.flushHeaders();let r=()=>{if(this._mustNotHaveABody){e();return}this._request.end(e)};this._request?r():this[R1].push(r)}abort(){this.res&&this.res.complete||(this.aborted||process.nextTick(()=>this.emit("abort")),this.aborted=!0,this.destroy())}_destroy(e,r){this.res&&this.res._dump(),this._request&&this._request.destroy(),r(e)}async flushHeaders(){if(this[Lb]||this.destroyed)return;this[Lb]=!0;let e=this.method===oit,r=o=>{if(this._request=o,this.destroyed){o.destroy();return}e||eit(o,this,["timeout","continue","close","error"]);let a=u=>(...A)=>{!this.writable&&!this.destroyed?u(...A):this.once("finish",()=>{u(...A)})};o.once("response",a((u,A,p)=>{let h=new Znt(this.socket,o.readableHighWaterMark);this.res=h,h.req=this,h.statusCode=u[Wae],h.headers=u,h.rawHeaders=p,h.once("end",()=>{this.aborted?(h.aborted=!0,h.emit("aborted")):(h.complete=!0,h.socket=null,h.connection=null)}),e?(h.upgrade=!0,this.emit("connect",h,o,Buffer.alloc(0))?this.emit("close"):o.destroy()):(o.on("data",E=>{!h._dumped&&!h.push(E)&&o.pause()}),o.once("end",()=>{h.push(null)}),this.emit("response",h)||h._dump())})),o.once("headers",a(u=>this.emit("information",{statusCode:u[Wae]}))),o.once("trailers",a((u,A,p)=>{let{res:h}=this;h.trailers=u,h.rawTrailers=p}));let{socket:n}=o.session;this.socket=n,this.connection=n;for(let u of this[R1])u();this.emit("socket",this.socket)};if(this[M4])try{r(this[M4].request(this[vo]))}catch(o){this.emit("error",o)}else{this.reusedSocket=!0;try{r(await this.agent.request(this[L4],this[zae],this[vo]))}catch(o){this.emit("error",o)}}}getHeader(e){if(typeof e!="string")throw new N4("name","string",e);return this[vo][e.toLowerCase()]}get headersSent(){return this[Lb]}removeHeader(e){if(typeof e!="string")throw new N4("name","string",e);if(this.headersSent)throw new Yae("remove");delete this[vo][e.toLowerCase()]}setHeader(e,r){if(this.headersSent)throw new Yae("set");if(typeof e!="string"||!ait.test(e)&&!tit(e))throw new nit("Header name",e);if(typeof r>"u")throw new iit(r,e);if(lit.test(r))throw new sit("header content",e);this[vo][e.toLowerCase()]=r}setNoDelay(){}setSocketKeepAlive(){}setTimeout(e,r){let o=()=>this._request.setTimeout(e,r);return this._request?o():this[R1].push(o),this}get maxHeadersCount(){if(!this.destroyed&&this._request)return this._request.session.localSettings.maxHeaderListSize}set maxHeadersCount(e){}};Jae.exports=O4});var Zae=_((ILt,Xae)=>{"use strict";var cit=ve("tls");Xae.exports=(t={},e=cit.connect)=>new Promise((r,o)=>{let a=!1,n,u=async()=>{await p,n.off("timeout",A),n.off("error",o),t.resolveSocket?(r({alpnProtocol:n.alpnProtocol,socket:n,timeout:a}),a&&(await Promise.resolve(),n.emit("timeout"))):(n.destroy(),r({alpnProtocol:n.alpnProtocol,timeout:a}))},A=async()=>{a=!0,u()},p=(async()=>{try{n=await e(t,u),n.on("error",o),n.once("timeout",A)}catch(h){o(h)}})()})});var ele=_((BLt,$ae)=>{"use strict";var uit=ve("net");$ae.exports=t=>{let e=t.host,r=t.headers&&t.headers.host;return r&&(r.startsWith("[")?r.indexOf("]")===-1?e=r:e=r.slice(1,-1):e=r.split(":",1)[0]),uit.isIP(e)?"":e}});var nle=_((vLt,H4)=>{"use strict";var tle=ve("http"),_4=ve("https"),Ait=Zae(),fit=x4(),pit=U4(),hit=ele(),git=T4(),Mb=new fit({maxSize:100}),T1=new Map,rle=(t,e,r)=>{e._httpMessage={shouldKeepAlive:!0};let o=()=>{t.emit("free",e,r)};e.on("free",o);let a=()=>{t.removeSocket(e,r)};e.on("close",a);let n=()=>{t.removeSocket(e,r),e.off("close",a),e.off("free",o),e.off("agentRemove",n)};e.on("agentRemove",n),t.emit("free",e,r)},dit=async t=>{let e=`${t.host}:${t.port}:${t.ALPNProtocols.sort()}`;if(!Mb.has(e)){if(T1.has(e))return(await T1.get(e)).alpnProtocol;let{path:r,agent:o}=t;t.path=t.socketPath;let a=Ait(t);T1.set(e,a);try{let{socket:n,alpnProtocol:u}=await a;if(Mb.set(e,u),t.path=r,u==="h2")n.destroy();else{let{globalAgent:A}=_4,p=_4.Agent.prototype.createConnection;o?o.createConnection===p?rle(o,n,t):n.destroy():A.createConnection===p?rle(A,n,t):n.destroy()}return T1.delete(e),u}catch(n){throw T1.delete(e),n}}return Mb.get(e)};H4.exports=async(t,e,r)=>{if((typeof t=="string"||t instanceof URL)&&(t=git(new URL(t))),typeof e=="function"&&(r=e,e=void 0),e={ALPNProtocols:["h2","http/1.1"],...t,...e,resolveSocket:!0},!Array.isArray(e.ALPNProtocols)||e.ALPNProtocols.length===0)throw new Error("The `ALPNProtocols` option must be an Array with at least one entry");e.protocol=e.protocol||"https:";let o=e.protocol==="https:";e.host=e.hostname||e.host||"localhost",e.session=e.tlsSession,e.servername=e.servername||hit(e),e.port=e.port||(o?443:80),e._defaultAgent=o?_4.globalAgent:tle.globalAgent;let a=e.agent;if(a){if(a.addRequest)throw new Error("The `options.agent` object can contain only `http`, `https` or `http2` properties");e.agent=a[o?"https":"http"]}return o&&await dit(e)==="h2"?(a&&(e.agent=a.http2),new pit(e,r)):tle.request(e,r)};H4.exports.protocolCache=Mb});var sle=_((DLt,ile)=>{"use strict";var mit=ve("http2"),yit=Q4(),q4=U4(),Eit=R4(),Cit=nle(),wit=(t,e,r)=>new q4(t,e,r),Iit=(t,e,r)=>{let o=new q4(t,e,r);return o.end(),o};ile.exports={...mit,ClientRequest:q4,IncomingMessage:Eit,...yit,request:wit,get:Iit,auto:Cit}});var G4=_(j4=>{"use strict";Object.defineProperty(j4,"__esModule",{value:!0});var ole=Ff();j4.default=t=>ole.default.nodeStream(t)&&ole.default.function_(t.getBoundary)});var ule=_(Y4=>{"use strict";Object.defineProperty(Y4,"__esModule",{value:!0});var lle=ve("fs"),cle=ve("util"),ale=Ff(),Bit=G4(),vit=cle.promisify(lle.stat);Y4.default=async(t,e)=>{if(e&&"content-length"in e)return Number(e["content-length"]);if(!t)return 0;if(ale.default.string(t))return Buffer.byteLength(t);if(ale.default.buffer(t))return t.length;if(Bit.default(t))return cle.promisify(t.getLength.bind(t))();if(t instanceof lle.ReadStream){let{size:r}=await vit(t.path);return r===0?void 0:r}}});var K4=_(W4=>{"use strict";Object.defineProperty(W4,"__esModule",{value:!0});function Dit(t,e,r){let o={};for(let a of r)o[a]=(...n)=>{e.emit(a,...n)},t.on(a,o[a]);return()=>{for(let a of r)t.off(a,o[a])}}W4.default=Dit});var Ale=_(V4=>{"use strict";Object.defineProperty(V4,"__esModule",{value:!0});V4.default=()=>{let t=[];return{once(e,r,o){e.once(r,o),t.push({origin:e,event:r,fn:o})},unhandleAll(){for(let e of t){let{origin:r,event:o,fn:a}=e;r.removeListener(o,a)}t.length=0}}}});var ple=_(N1=>{"use strict";Object.defineProperty(N1,"__esModule",{value:!0});N1.TimeoutError=void 0;var Pit=ve("net"),Sit=Ale(),fle=Symbol("reentry"),bit=()=>{},Ob=class extends Error{constructor(e,r){super(`Timeout awaiting '${r}' for ${e}ms`),this.event=r,this.name="TimeoutError",this.code="ETIMEDOUT"}};N1.TimeoutError=Ob;N1.default=(t,e,r)=>{if(fle in t)return bit;t[fle]=!0;let o=[],{once:a,unhandleAll:n}=Sit.default(),u=(I,D,x)=>{var C;let T=setTimeout(D,I,I,x);(C=T.unref)===null||C===void 0||C.call(T);let L=()=>{clearTimeout(T)};return o.push(L),L},{host:A,hostname:p}=r,h=(I,D)=>{t.destroy(new Ob(I,D))},E=()=>{for(let I of o)I();n()};if(t.once("error",I=>{if(E(),t.listenerCount("error")===0)throw I}),t.once("close",E),a(t,"response",I=>{a(I,"end",E)}),typeof e.request<"u"&&u(e.request,h,"request"),typeof e.socket<"u"){let I=()=>{h(e.socket,"socket")};t.setTimeout(e.socket,I),o.push(()=>{t.removeListener("timeout",I)})}return a(t,"socket",I=>{var D;let{socketPath:x}=t;if(I.connecting){let C=!!(x??Pit.isIP((D=p??A)!==null&&D!==void 0?D:"")!==0);if(typeof e.lookup<"u"&&!C&&typeof I.address().address>"u"){let T=u(e.lookup,h,"lookup");a(I,"lookup",T)}if(typeof e.connect<"u"){let T=()=>u(e.connect,h,"connect");C?a(I,"connect",T()):a(I,"lookup",L=>{L===null&&a(I,"connect",T())})}typeof e.secureConnect<"u"&&r.protocol==="https:"&&a(I,"connect",()=>{let T=u(e.secureConnect,h,"secureConnect");a(I,"secureConnect",T)})}if(typeof e.send<"u"){let C=()=>u(e.send,h,"send");I.connecting?a(I,"connect",()=>{a(t,"upload-complete",C())}):a(t,"upload-complete",C())}}),typeof e.response<"u"&&a(t,"upload-complete",()=>{let I=u(e.response,h,"response");a(t,"response",I)}),E}});var gle=_(z4=>{"use strict";Object.defineProperty(z4,"__esModule",{value:!0});var hle=Ff();z4.default=t=>{t=t;let e={protocol:t.protocol,hostname:hle.default.string(t.hostname)&&t.hostname.startsWith("[")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||""}${t.search||""}`};return hle.default.string(t.port)&&t.port.length>0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||""}:${t.password||""}`),e}});var dle=_(J4=>{"use strict";Object.defineProperty(J4,"__esModule",{value:!0});var xit=ve("url"),kit=["protocol","host","hostname","port","pathname","search"];J4.default=(t,e)=>{var r,o;if(e.path){if(e.pathname)throw new TypeError("Parameters `path` and `pathname` are mutually exclusive.");if(e.search)throw new TypeError("Parameters `path` and `search` are mutually exclusive.");if(e.searchParams)throw new TypeError("Parameters `path` and `searchParams` are mutually exclusive.")}if(e.search&&e.searchParams)throw new TypeError("Parameters `search` and `searchParams` are mutually exclusive.");if(!t){if(!e.protocol)throw new TypeError("No URL protocol specified");t=`${e.protocol}//${(o=(r=e.hostname)!==null&&r!==void 0?r:e.host)!==null&&o!==void 0?o:""}`}let a=new xit.URL(t);if(e.path){let n=e.path.indexOf("?");n===-1?e.pathname=e.path:(e.pathname=e.path.slice(0,n),e.search=e.path.slice(n+1)),delete e.path}for(let n of kit)e[n]&&(a[n]=e[n].toString());return a}});var mle=_(Z4=>{"use strict";Object.defineProperty(Z4,"__esModule",{value:!0});var X4=class{constructor(){this.weakMap=new WeakMap,this.map=new Map}set(e,r){typeof e=="object"?this.weakMap.set(e,r):this.map.set(e,r)}get(e){return typeof e=="object"?this.weakMap.get(e):this.map.get(e)}has(e){return typeof e=="object"?this.weakMap.has(e):this.map.has(e)}};Z4.default=X4});var eU=_($4=>{"use strict";Object.defineProperty($4,"__esModule",{value:!0});var Qit=async t=>{let e=[],r=0;for await(let o of t)e.push(o),r+=Buffer.byteLength(o);return Buffer.isBuffer(e[0])?Buffer.concat(e,r):Buffer.from(e.join(""))};$4.default=Qit});var Ele=_(xg=>{"use strict";Object.defineProperty(xg,"__esModule",{value:!0});xg.dnsLookupIpVersionToFamily=xg.isDnsLookupIpVersion=void 0;var yle={auto:0,ipv4:4,ipv6:6};xg.isDnsLookupIpVersion=t=>t in yle;xg.dnsLookupIpVersionToFamily=t=>{if(xg.isDnsLookupIpVersion(t))return yle[t];throw new Error("Invalid DNS lookup IP version")}});var tU=_(Ub=>{"use strict";Object.defineProperty(Ub,"__esModule",{value:!0});Ub.isResponseOk=void 0;Ub.isResponseOk=t=>{let{statusCode:e}=t,r=t.request.options.followRedirect?299:399;return e>=200&&e<=r||e===304}});var wle=_(rU=>{"use strict";Object.defineProperty(rU,"__esModule",{value:!0});var Cle=new Set;rU.default=t=>{Cle.has(t)||(Cle.add(t),process.emitWarning(`Got: ${t}`,{type:"DeprecationWarning"}))}});var Ile=_(nU=>{"use strict";Object.defineProperty(nU,"__esModule",{value:!0});var mi=Ff(),Fit=(t,e)=>{if(mi.default.null_(t.encoding))throw new TypeError("To get a Buffer, set `options.responseType` to `buffer` instead");mi.assert.any([mi.default.string,mi.default.undefined],t.encoding),mi.assert.any([mi.default.boolean,mi.default.undefined],t.resolveBodyOnly),mi.assert.any([mi.default.boolean,mi.default.undefined],t.methodRewriting),mi.assert.any([mi.default.boolean,mi.default.undefined],t.isStream),mi.assert.any([mi.default.string,mi.default.undefined],t.responseType),t.responseType===void 0&&(t.responseType="text");let{retry:r}=t;if(e?t.retry={...e.retry}:t.retry={calculateDelay:o=>o.computedValue,limit:0,methods:[],statusCodes:[],errorCodes:[],maxRetryAfter:void 0},mi.default.object(r)?(t.retry={...t.retry,...r},t.retry.methods=[...new Set(t.retry.methods.map(o=>o.toUpperCase()))],t.retry.statusCodes=[...new Set(t.retry.statusCodes)],t.retry.errorCodes=[...new Set(t.retry.errorCodes)]):mi.default.number(r)&&(t.retry.limit=r),mi.default.undefined(t.retry.maxRetryAfter)&&(t.retry.maxRetryAfter=Math.min(...[t.timeout.request,t.timeout.connect].filter(mi.default.number))),mi.default.object(t.pagination)){e&&(t.pagination={...e.pagination,...t.pagination});let{pagination:o}=t;if(!mi.default.function_(o.transform))throw new Error("`options.pagination.transform` must be implemented");if(!mi.default.function_(o.shouldContinue))throw new Error("`options.pagination.shouldContinue` must be implemented");if(!mi.default.function_(o.filter))throw new TypeError("`options.pagination.filter` must be implemented");if(!mi.default.function_(o.paginate))throw new Error("`options.pagination.paginate` must be implemented")}return t.responseType==="json"&&t.headers.accept===void 0&&(t.headers.accept="application/json"),t};nU.default=Fit});var Ble=_(L1=>{"use strict";Object.defineProperty(L1,"__esModule",{value:!0});L1.retryAfterStatusCodes=void 0;L1.retryAfterStatusCodes=new Set([413,429,503]);var Rit=({attemptCount:t,retryOptions:e,error:r,retryAfter:o})=>{if(t>e.limit)return 0;let a=e.methods.includes(r.options.method),n=e.errorCodes.includes(r.code),u=r.response&&e.statusCodes.includes(r.response.statusCode);if(!a||!n&&!u)return 0;if(r.response){if(o)return e.maxRetryAfter===void 0||o>e.maxRetryAfter?0:o;if(r.response.statusCode===413)return 0}let A=Math.random()*100;return 2**(t-1)*1e3+A};L1.default=Rit});var U1=_(Qn=>{"use strict";Object.defineProperty(Qn,"__esModule",{value:!0});Qn.UnsupportedProtocolError=Qn.ReadError=Qn.TimeoutError=Qn.UploadError=Qn.CacheError=Qn.HTTPError=Qn.MaxRedirectsError=Qn.RequestError=Qn.setNonEnumerableProperties=Qn.knownHookEvents=Qn.withoutBody=Qn.kIsNormalizedAlready=void 0;var vle=ve("util"),Dle=ve("stream"),Tit=ve("fs"),uh=ve("url"),Ple=ve("http"),iU=ve("http"),Nit=ve("https"),Lit=_oe(),Mit=Koe(),Sle=Pae(),Oit=kae(),Uit=sle(),_it=Tb(),at=Ff(),Hit=ule(),ble=G4(),qit=K4(),xle=ple(),jit=gle(),kle=dle(),Git=mle(),Yit=eU(),Qle=Ele(),Wit=tU(),Ah=wle(),Kit=Ile(),Vit=Ble(),sU,Ws=Symbol("request"),qb=Symbol("response"),vy=Symbol("responseSize"),Dy=Symbol("downloadedSize"),Py=Symbol("bodySize"),Sy=Symbol("uploadedSize"),_b=Symbol("serverResponsesPiped"),Fle=Symbol("unproxyEvents"),Rle=Symbol("isFromCache"),oU=Symbol("cancelTimeouts"),Tle=Symbol("startedReading"),by=Symbol("stopReading"),Hb=Symbol("triggerRead"),fh=Symbol("body"),M1=Symbol("jobs"),Nle=Symbol("originalResponse"),Lle=Symbol("retryTimeout");Qn.kIsNormalizedAlready=Symbol("isNormalizedAlready");var zit=at.default.string(process.versions.brotli);Qn.withoutBody=new Set(["GET","HEAD"]);Qn.knownHookEvents=["init","beforeRequest","beforeRedirect","beforeError","beforeRetry","afterResponse"];function Jit(t){for(let e in t){let r=t[e];if(!at.default.string(r)&&!at.default.number(r)&&!at.default.boolean(r)&&!at.default.null_(r)&&!at.default.undefined(r))throw new TypeError(`The \`searchParams\` value '${String(r)}' must be a string, number, boolean or null`)}}function Xit(t){return at.default.object(t)&&!("statusCode"in t)}var aU=new Git.default,Zit=async t=>new Promise((e,r)=>{let o=a=>{r(a)};t.pending||e(),t.once("error",o),t.once("ready",()=>{t.off("error",o),e()})}),$it=new Set([300,301,302,303,304,307,308]),est=["context","body","json","form"];Qn.setNonEnumerableProperties=(t,e)=>{let r={};for(let o of t)if(o)for(let a of est)a in o&&(r[a]={writable:!0,configurable:!0,enumerable:!1,value:o[a]});Object.defineProperties(e,r)};var Ji=class extends Error{constructor(e,r,o){var a;if(super(e),Error.captureStackTrace(this,this.constructor),this.name="RequestError",this.code=r.code,o instanceof zb?(Object.defineProperty(this,"request",{enumerable:!1,value:o}),Object.defineProperty(this,"response",{enumerable:!1,value:o[qb]}),Object.defineProperty(this,"options",{enumerable:!1,value:o.options})):Object.defineProperty(this,"options",{enumerable:!1,value:o}),this.timings=(a=this.request)===null||a===void 0?void 0:a.timings,at.default.string(r.stack)&&at.default.string(this.stack)){let n=this.stack.indexOf(this.message)+this.message.length,u=this.stack.slice(n).split(` +`).reverse(),A=r.stack.slice(r.stack.indexOf(r.message)+r.message.length).split(` +`).reverse();for(;A.length!==0&&A[0]===u[0];)u.shift();this.stack=`${this.stack.slice(0,n)}${u.reverse().join(` +`)}${A.reverse().join(` +`)}`}}};Qn.RequestError=Ji;var jb=class extends Ji{constructor(e){super(`Redirected ${e.options.maxRedirects} times. Aborting.`,{},e),this.name="MaxRedirectsError"}};Qn.MaxRedirectsError=jb;var Gb=class extends Ji{constructor(e){super(`Response code ${e.statusCode} (${e.statusMessage})`,{},e.request),this.name="HTTPError"}};Qn.HTTPError=Gb;var Yb=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="CacheError"}};Qn.CacheError=Yb;var Wb=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="UploadError"}};Qn.UploadError=Wb;var Kb=class extends Ji{constructor(e,r,o){super(e.message,e,o),this.name="TimeoutError",this.event=e.event,this.timings=r}};Qn.TimeoutError=Kb;var O1=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="ReadError"}};Qn.ReadError=O1;var Vb=class extends Ji{constructor(e){super(`Unsupported protocol "${e.url.protocol}"`,{},e),this.name="UnsupportedProtocolError"}};Qn.UnsupportedProtocolError=Vb;var tst=["socket","connect","continue","information","upgrade","timeout"],zb=class extends Dle.Duplex{constructor(e,r={},o){super({autoDestroy:!1,highWaterMark:0}),this[Dy]=0,this[Sy]=0,this.requestInitialized=!1,this[_b]=new Set,this.redirects=[],this[by]=!1,this[Hb]=!1,this[M1]=[],this.retryCount=0,this._progressCallbacks=[];let a=()=>this._unlockWrite(),n=()=>this._lockWrite();this.on("pipe",h=>{h.prependListener("data",a),h.on("data",n),h.prependListener("end",a),h.on("end",n)}),this.on("unpipe",h=>{h.off("data",a),h.off("data",n),h.off("end",a),h.off("end",n)}),this.on("pipe",h=>{h instanceof iU.IncomingMessage&&(this.options.headers={...h.headers,...this.options.headers})});let{json:u,body:A,form:p}=r;if((u||A||p)&&this._lockWrite(),Qn.kIsNormalizedAlready in r)this.options=r;else try{this.options=this.constructor.normalizeArguments(e,r,o)}catch(h){at.default.nodeStream(r.body)&&r.body.destroy(),this.destroy(h);return}(async()=>{var h;try{this.options.body instanceof Tit.ReadStream&&await Zit(this.options.body);let{url:E}=this.options;if(!E)throw new TypeError("Missing `url` property");if(this.requestUrl=E.toString(),decodeURI(this.requestUrl),await this._finalizeBody(),await this._makeRequest(),this.destroyed){(h=this[Ws])===null||h===void 0||h.destroy();return}for(let I of this[M1])I();this[M1].length=0,this.requestInitialized=!0}catch(E){if(E instanceof Ji){this._beforeError(E);return}this.destroyed||this.destroy(E)}})()}static normalizeArguments(e,r,o){var a,n,u,A,p;let h=r;if(at.default.object(e)&&!at.default.urlInstance(e))r={...o,...e,...r};else{if(e&&r&&r.url!==void 0)throw new TypeError("The `url` option is mutually exclusive with the `input` argument");r={...o,...r},e!==void 0&&(r.url=e),at.default.urlInstance(r.url)&&(r.url=new uh.URL(r.url.toString()))}if(r.cache===!1&&(r.cache=void 0),r.dnsCache===!1&&(r.dnsCache=void 0),at.assert.any([at.default.string,at.default.undefined],r.method),at.assert.any([at.default.object,at.default.undefined],r.headers),at.assert.any([at.default.string,at.default.urlInstance,at.default.undefined],r.prefixUrl),at.assert.any([at.default.object,at.default.undefined],r.cookieJar),at.assert.any([at.default.object,at.default.string,at.default.undefined],r.searchParams),at.assert.any([at.default.object,at.default.string,at.default.undefined],r.cache),at.assert.any([at.default.object,at.default.number,at.default.undefined],r.timeout),at.assert.any([at.default.object,at.default.undefined],r.context),at.assert.any([at.default.object,at.default.undefined],r.hooks),at.assert.any([at.default.boolean,at.default.undefined],r.decompress),at.assert.any([at.default.boolean,at.default.undefined],r.ignoreInvalidCookies),at.assert.any([at.default.boolean,at.default.undefined],r.followRedirect),at.assert.any([at.default.number,at.default.undefined],r.maxRedirects),at.assert.any([at.default.boolean,at.default.undefined],r.throwHttpErrors),at.assert.any([at.default.boolean,at.default.undefined],r.http2),at.assert.any([at.default.boolean,at.default.undefined],r.allowGetBody),at.assert.any([at.default.string,at.default.undefined],r.localAddress),at.assert.any([Qle.isDnsLookupIpVersion,at.default.undefined],r.dnsLookupIpVersion),at.assert.any([at.default.object,at.default.undefined],r.https),at.assert.any([at.default.boolean,at.default.undefined],r.rejectUnauthorized),r.https&&(at.assert.any([at.default.boolean,at.default.undefined],r.https.rejectUnauthorized),at.assert.any([at.default.function_,at.default.undefined],r.https.checkServerIdentity),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.certificateAuthority),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.key),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.certificate),at.assert.any([at.default.string,at.default.undefined],r.https.passphrase),at.assert.any([at.default.string,at.default.buffer,at.default.array,at.default.undefined],r.https.pfx)),at.assert.any([at.default.object,at.default.undefined],r.cacheOptions),at.default.string(r.method)?r.method=r.method.toUpperCase():r.method="GET",r.headers===o?.headers?r.headers={...r.headers}:r.headers=_it({...o?.headers,...r.headers}),"slashes"in r)throw new TypeError("The legacy `url.Url` has been deprecated. Use `URL` instead.");if("auth"in r)throw new TypeError("Parameter `auth` is deprecated. Use `username` / `password` instead.");if("searchParams"in r&&r.searchParams&&r.searchParams!==o?.searchParams){let x;if(at.default.string(r.searchParams)||r.searchParams instanceof uh.URLSearchParams)x=new uh.URLSearchParams(r.searchParams);else{Jit(r.searchParams),x=new uh.URLSearchParams;for(let C in r.searchParams){let T=r.searchParams[C];T===null?x.append(C,""):T!==void 0&&x.append(C,T)}}(a=o?.searchParams)===null||a===void 0||a.forEach((C,T)=>{x.has(T)||x.append(T,C)}),r.searchParams=x}if(r.username=(n=r.username)!==null&&n!==void 0?n:"",r.password=(u=r.password)!==null&&u!==void 0?u:"",at.default.undefined(r.prefixUrl)?r.prefixUrl=(A=o?.prefixUrl)!==null&&A!==void 0?A:"":(r.prefixUrl=r.prefixUrl.toString(),r.prefixUrl!==""&&!r.prefixUrl.endsWith("/")&&(r.prefixUrl+="/")),at.default.string(r.url)){if(r.url.startsWith("/"))throw new Error("`input` must not start with a slash when using `prefixUrl`");r.url=kle.default(r.prefixUrl+r.url,r)}else(at.default.undefined(r.url)&&r.prefixUrl!==""||r.protocol)&&(r.url=kle.default(r.prefixUrl,r));if(r.url){"port"in r&&delete r.port;let{prefixUrl:x}=r;Object.defineProperty(r,"prefixUrl",{set:T=>{let L=r.url;if(!L.href.startsWith(T))throw new Error(`Cannot change \`prefixUrl\` from ${x} to ${T}: ${L.href}`);r.url=new uh.URL(T+L.href.slice(x.length)),x=T},get:()=>x});let{protocol:C}=r.url;if(C==="unix:"&&(C="http:",r.url=new uh.URL(`http://unix${r.url.pathname}${r.url.search}`)),r.searchParams&&(r.url.search=r.searchParams.toString()),C!=="http:"&&C!=="https:")throw new Vb(r);r.username===""?r.username=r.url.username:r.url.username=r.username,r.password===""?r.password=r.url.password:r.url.password=r.password}let{cookieJar:E}=r;if(E){let{setCookie:x,getCookieString:C}=E;at.assert.function_(x),at.assert.function_(C),x.length===4&&C.length===0&&(x=vle.promisify(x.bind(r.cookieJar)),C=vle.promisify(C.bind(r.cookieJar)),r.cookieJar={setCookie:x,getCookieString:C})}let{cache:I}=r;if(I&&(aU.has(I)||aU.set(I,new Sle((x,C)=>{let T=x[Ws](x,C);return at.default.promise(T)&&(T.once=(L,U)=>{if(L==="error")T.catch(U);else if(L==="abort")(async()=>{try{(await T).once("abort",U)}catch{}})();else throw new Error(`Unknown HTTP2 promise event: ${L}`);return T}),T},I))),r.cacheOptions={...r.cacheOptions},r.dnsCache===!0)sU||(sU=new Mit.default),r.dnsCache=sU;else if(!at.default.undefined(r.dnsCache)&&!r.dnsCache.lookup)throw new TypeError(`Parameter \`dnsCache\` must be a CacheableLookup instance or a boolean, got ${at.default(r.dnsCache)}`);at.default.number(r.timeout)?r.timeout={request:r.timeout}:o&&r.timeout!==o.timeout?r.timeout={...o.timeout,...r.timeout}:r.timeout={...r.timeout},r.context||(r.context={});let D=r.hooks===o?.hooks;r.hooks={...r.hooks};for(let x of Qn.knownHookEvents)if(x in r.hooks)if(at.default.array(r.hooks[x]))r.hooks[x]=[...r.hooks[x]];else throw new TypeError(`Parameter \`${x}\` must be an Array, got ${at.default(r.hooks[x])}`);else r.hooks[x]=[];if(o&&!D)for(let x of Qn.knownHookEvents)o.hooks[x].length>0&&(r.hooks[x]=[...o.hooks[x],...r.hooks[x]]);if("family"in r&&Ah.default('"options.family" was never documented, please use "options.dnsLookupIpVersion"'),o?.https&&(r.https={...o.https,...r.https}),"rejectUnauthorized"in r&&Ah.default('"options.rejectUnauthorized" is now deprecated, please use "options.https.rejectUnauthorized"'),"checkServerIdentity"in r&&Ah.default('"options.checkServerIdentity" was never documented, please use "options.https.checkServerIdentity"'),"ca"in r&&Ah.default('"options.ca" was never documented, please use "options.https.certificateAuthority"'),"key"in r&&Ah.default('"options.key" was never documented, please use "options.https.key"'),"cert"in r&&Ah.default('"options.cert" was never documented, please use "options.https.certificate"'),"passphrase"in r&&Ah.default('"options.passphrase" was never documented, please use "options.https.passphrase"'),"pfx"in r&&Ah.default('"options.pfx" was never documented, please use "options.https.pfx"'),"followRedirects"in r)throw new TypeError("The `followRedirects` option does not exist. Use `followRedirect` instead.");if(r.agent){for(let x in r.agent)if(x!=="http"&&x!=="https"&&x!=="http2")throw new TypeError(`Expected the \`options.agent\` properties to be \`http\`, \`https\` or \`http2\`, got \`${x}\``)}return r.maxRedirects=(p=r.maxRedirects)!==null&&p!==void 0?p:0,Qn.setNonEnumerableProperties([o,h],r),Kit.default(r,o)}_lockWrite(){let e=()=>{throw new TypeError("The payload has been already provided")};this.write=e,this.end=e}_unlockWrite(){this.write=super.write,this.end=super.end}async _finalizeBody(){let{options:e}=this,{headers:r}=e,o=!at.default.undefined(e.form),a=!at.default.undefined(e.json),n=!at.default.undefined(e.body),u=o||a||n,A=Qn.withoutBody.has(e.method)&&!(e.method==="GET"&&e.allowGetBody);if(this._cannotHaveBody=A,u){if(A)throw new TypeError(`The \`${e.method}\` method cannot be used with a body`);if([n,o,a].filter(p=>p).length>1)throw new TypeError("The `body`, `json` and `form` options are mutually exclusive");if(n&&!(e.body instanceof Dle.Readable)&&!at.default.string(e.body)&&!at.default.buffer(e.body)&&!ble.default(e.body))throw new TypeError("The `body` option must be a stream.Readable, string or Buffer");if(o&&!at.default.object(e.form))throw new TypeError("The `form` option must be an Object");{let p=!at.default.string(r["content-type"]);n?(ble.default(e.body)&&p&&(r["content-type"]=`multipart/form-data; boundary=${e.body.getBoundary()}`),this[fh]=e.body):o?(p&&(r["content-type"]="application/x-www-form-urlencoded"),this[fh]=new uh.URLSearchParams(e.form).toString()):(p&&(r["content-type"]="application/json"),this[fh]=e.stringifyJson(e.json));let h=await Hit.default(this[fh],e.headers);at.default.undefined(r["content-length"])&&at.default.undefined(r["transfer-encoding"])&&!A&&!at.default.undefined(h)&&(r["content-length"]=String(h))}}else A?this._lockWrite():this._unlockWrite();this[Py]=Number(r["content-length"])||void 0}async _onResponseBase(e){let{options:r}=this,{url:o}=r;this[Nle]=e,r.decompress&&(e=Oit(e));let a=e.statusCode,n=e;n.statusMessage=n.statusMessage?n.statusMessage:Ple.STATUS_CODES[a],n.url=r.url.toString(),n.requestUrl=this.requestUrl,n.redirectUrls=this.redirects,n.request=this,n.isFromCache=e.fromCache||!1,n.ip=this.ip,n.retryCount=this.retryCount,this[Rle]=n.isFromCache,this[vy]=Number(e.headers["content-length"])||void 0,this[qb]=e,e.once("end",()=>{this[vy]=this[Dy],this.emit("downloadProgress",this.downloadProgress)}),e.once("error",A=>{e.destroy(),this._beforeError(new O1(A,this))}),e.once("aborted",()=>{this._beforeError(new O1({name:"Error",message:"The server aborted pending request",code:"ECONNRESET"},this))}),this.emit("downloadProgress",this.downloadProgress);let u=e.headers["set-cookie"];if(at.default.object(r.cookieJar)&&u){let A=u.map(async p=>r.cookieJar.setCookie(p,o.toString()));r.ignoreInvalidCookies&&(A=A.map(async p=>p.catch(()=>{})));try{await Promise.all(A)}catch(p){this._beforeError(p);return}}if(r.followRedirect&&e.headers.location&&$it.has(a)){if(e.resume(),this[Ws]&&(this[oU](),delete this[Ws],this[Fle]()),(a===303&&r.method!=="GET"&&r.method!=="HEAD"||!r.methodRewriting)&&(r.method="GET","body"in r&&delete r.body,"json"in r&&delete r.json,"form"in r&&delete r.form,this[fh]=void 0,delete r.headers["content-length"]),this.redirects.length>=r.maxRedirects){this._beforeError(new jb(this));return}try{let p=Buffer.from(e.headers.location,"binary").toString(),h=new uh.URL(p,o),E=h.toString();decodeURI(E),h.hostname!==o.hostname||h.port!==o.port?("host"in r.headers&&delete r.headers.host,"cookie"in r.headers&&delete r.headers.cookie,"authorization"in r.headers&&delete r.headers.authorization,(r.username||r.password)&&(r.username="",r.password="")):(h.username=r.username,h.password=r.password),this.redirects.push(E),r.url=h;for(let I of r.hooks.beforeRedirect)await I(r,n);this.emit("redirect",n,r),await this._makeRequest()}catch(p){this._beforeError(p);return}return}if(r.isStream&&r.throwHttpErrors&&!Wit.isResponseOk(n)){this._beforeError(new Gb(n));return}e.on("readable",()=>{this[Hb]&&this._read()}),this.on("resume",()=>{e.resume()}),this.on("pause",()=>{e.pause()}),e.once("end",()=>{this.push(null)}),this.emit("response",e);for(let A of this[_b])if(!A.headersSent){for(let p in e.headers){let h=r.decompress?p!=="content-encoding":!0,E=e.headers[p];h&&A.setHeader(p,E)}A.statusCode=a}}async _onResponse(e){try{await this._onResponseBase(e)}catch(r){this._beforeError(r)}}_onRequest(e){let{options:r}=this,{timeout:o,url:a}=r;Lit.default(e),this[oU]=xle.default(e,o,a);let n=r.cache?"cacheableResponse":"response";e.once(n,p=>{this._onResponse(p)}),e.once("error",p=>{var h;e.destroy(),(h=e.res)===null||h===void 0||h.removeAllListeners("end"),p=p instanceof xle.TimeoutError?new Kb(p,this.timings,this):new Ji(p.message,p,this),this._beforeError(p)}),this[Fle]=qit.default(e,this,tst),this[Ws]=e,this.emit("uploadProgress",this.uploadProgress);let u=this[fh],A=this.redirects.length===0?this:e;at.default.nodeStream(u)?(u.pipe(A),u.once("error",p=>{this._beforeError(new Wb(p,this))})):(this._unlockWrite(),at.default.undefined(u)?(this._cannotHaveBody||this._noPipe)&&(A.end(),this._lockWrite()):(this._writeRequest(u,void 0,()=>{}),A.end(),this._lockWrite())),this.emit("request",e)}async _createCacheableRequest(e,r){return new Promise((o,a)=>{Object.assign(r,jit.default(e)),delete r.url;let n,u=aU.get(r.cache)(r,async A=>{A._readableState.autoDestroy=!1,n&&(await n).emit("cacheableResponse",A),o(A)});r.url=e,u.once("error",a),u.once("request",async A=>{n=A,o(n)})})}async _makeRequest(){var e,r,o,a,n;let{options:u}=this,{headers:A}=u;for(let U in A)if(at.default.undefined(A[U]))delete A[U];else if(at.default.null_(A[U]))throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${U}\` header`);if(u.decompress&&at.default.undefined(A["accept-encoding"])&&(A["accept-encoding"]=zit?"gzip, deflate, br":"gzip, deflate"),u.cookieJar){let U=await u.cookieJar.getCookieString(u.url.toString());at.default.nonEmptyString(U)&&(u.headers.cookie=U)}for(let U of u.hooks.beforeRequest){let z=await U(u);if(!at.default.undefined(z)){u.request=()=>z;break}}u.body&&this[fh]!==u.body&&(this[fh]=u.body);let{agent:p,request:h,timeout:E,url:I}=u;if(u.dnsCache&&!("lookup"in u)&&(u.lookup=u.dnsCache.lookup),I.hostname==="unix"){let U=/(?.+?):(?.+)/.exec(`${I.pathname}${I.search}`);if(U?.groups){let{socketPath:z,path:te}=U.groups;Object.assign(u,{socketPath:z,path:te,host:""})}}let D=I.protocol==="https:",x;u.http2?x=Uit.auto:x=D?Nit.request:Ple.request;let C=(e=u.request)!==null&&e!==void 0?e:x,T=u.cache?this._createCacheableRequest:C;p&&!u.http2&&(u.agent=p[D?"https":"http"]),u[Ws]=C,delete u.request,delete u.timeout;let L=u;if(L.shared=(r=u.cacheOptions)===null||r===void 0?void 0:r.shared,L.cacheHeuristic=(o=u.cacheOptions)===null||o===void 0?void 0:o.cacheHeuristic,L.immutableMinTimeToLive=(a=u.cacheOptions)===null||a===void 0?void 0:a.immutableMinTimeToLive,L.ignoreCargoCult=(n=u.cacheOptions)===null||n===void 0?void 0:n.ignoreCargoCult,u.dnsLookupIpVersion!==void 0)try{L.family=Qle.dnsLookupIpVersionToFamily(u.dnsLookupIpVersion)}catch{throw new Error("Invalid `dnsLookupIpVersion` option value")}u.https&&("rejectUnauthorized"in u.https&&(L.rejectUnauthorized=u.https.rejectUnauthorized),u.https.checkServerIdentity&&(L.checkServerIdentity=u.https.checkServerIdentity),u.https.certificateAuthority&&(L.ca=u.https.certificateAuthority),u.https.certificate&&(L.cert=u.https.certificate),u.https.key&&(L.key=u.https.key),u.https.passphrase&&(L.passphrase=u.https.passphrase),u.https.pfx&&(L.pfx=u.https.pfx));try{let U=await T(I,L);at.default.undefined(U)&&(U=x(I,L)),u.request=h,u.timeout=E,u.agent=p,u.https&&("rejectUnauthorized"in u.https&&delete L.rejectUnauthorized,u.https.checkServerIdentity&&delete L.checkServerIdentity,u.https.certificateAuthority&&delete L.ca,u.https.certificate&&delete L.cert,u.https.key&&delete L.key,u.https.passphrase&&delete L.passphrase,u.https.pfx&&delete L.pfx),Xit(U)?this._onRequest(U):this.writable?(this.once("finish",()=>{this._onResponse(U)}),this._unlockWrite(),this.end(),this._lockWrite()):this._onResponse(U)}catch(U){throw U instanceof Sle.CacheError?new Yb(U,this):new Ji(U.message,U,this)}}async _error(e){try{for(let r of this.options.hooks.beforeError)e=await r(e)}catch(r){e=new Ji(r.message,r,this)}this.destroy(e)}_beforeError(e){if(this[by])return;let{options:r}=this,o=this.retryCount+1;this[by]=!0,e instanceof Ji||(e=new Ji(e.message,e,this));let a=e,{response:n}=a;(async()=>{if(n&&!n.body){n.setEncoding(this._readableState.encoding);try{n.rawBody=await Yit.default(n),n.body=n.rawBody.toString()}catch{}}if(this.listenerCount("retry")!==0){let u;try{let A;n&&"retry-after"in n.headers&&(A=Number(n.headers["retry-after"]),Number.isNaN(A)?(A=Date.parse(n.headers["retry-after"])-Date.now(),A<=0&&(A=1)):A*=1e3),u=await r.retry.calculateDelay({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:Vit.default({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:0})})}catch(A){this._error(new Ji(A.message,A,this));return}if(u){let A=async()=>{try{for(let p of this.options.hooks.beforeRetry)await p(this.options,a,o)}catch(p){this._error(new Ji(p.message,e,this));return}this.destroyed||(this.destroy(),this.emit("retry",o,e))};this[Lle]=setTimeout(A,u);return}}this._error(a)})()}_read(){this[Hb]=!0;let e=this[qb];if(e&&!this[by]){e.readableLength&&(this[Hb]=!1);let r;for(;(r=e.read())!==null;){this[Dy]+=r.length,this[Tle]=!0;let o=this.downloadProgress;o.percent<1&&this.emit("downloadProgress",o),this.push(r)}}}_write(e,r,o){let a=()=>{this._writeRequest(e,r,o)};this.requestInitialized?a():this[M1].push(a)}_writeRequest(e,r,o){this[Ws].destroyed||(this._progressCallbacks.push(()=>{this[Sy]+=Buffer.byteLength(e,r);let a=this.uploadProgress;a.percent<1&&this.emit("uploadProgress",a)}),this[Ws].write(e,r,a=>{!a&&this._progressCallbacks.length>0&&this._progressCallbacks.shift()(),o(a)}))}_final(e){let r=()=>{for(;this._progressCallbacks.length!==0;)this._progressCallbacks.shift()();if(!(Ws in this)){e();return}if(this[Ws].destroyed){e();return}this[Ws].end(o=>{o||(this[Py]=this[Sy],this.emit("uploadProgress",this.uploadProgress),this[Ws].emit("upload-complete")),e(o)})};this.requestInitialized?r():this[M1].push(r)}_destroy(e,r){var o;this[by]=!0,clearTimeout(this[Lle]),Ws in this&&(this[oU](),!((o=this[qb])===null||o===void 0)&&o.complete||this[Ws].destroy()),e!==null&&!at.default.undefined(e)&&!(e instanceof Ji)&&(e=new Ji(e.message,e,this)),r(e)}get _isAboutToError(){return this[by]}get ip(){var e;return(e=this.socket)===null||e===void 0?void 0:e.remoteAddress}get aborted(){var e,r,o;return((r=(e=this[Ws])===null||e===void 0?void 0:e.destroyed)!==null&&r!==void 0?r:this.destroyed)&&!(!((o=this[Nle])===null||o===void 0)&&o.complete)}get socket(){var e,r;return(r=(e=this[Ws])===null||e===void 0?void 0:e.socket)!==null&&r!==void 0?r:void 0}get downloadProgress(){let e;return this[vy]?e=this[Dy]/this[vy]:this[vy]===this[Dy]?e=1:e=0,{percent:e,transferred:this[Dy],total:this[vy]}}get uploadProgress(){let e;return this[Py]?e=this[Sy]/this[Py]:this[Py]===this[Sy]?e=1:e=0,{percent:e,transferred:this[Sy],total:this[Py]}}get timings(){var e;return(e=this[Ws])===null||e===void 0?void 0:e.timings}get isFromCache(){return this[Rle]}pipe(e,r){if(this[Tle])throw new Error("Failed to pipe. The response has been emitted already.");return e instanceof iU.ServerResponse&&this[_b].add(e),super.pipe(e,r)}unpipe(e){return e instanceof iU.ServerResponse&&this[_b].delete(e),super.unpipe(e),this}};Qn.default=zb});var _1=_(Jc=>{"use strict";var rst=Jc&&Jc.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),nst=Jc&&Jc.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&rst(e,t,r)};Object.defineProperty(Jc,"__esModule",{value:!0});Jc.CancelError=Jc.ParseError=void 0;var Mle=U1(),lU=class extends Mle.RequestError{constructor(e,r){let{options:o}=r.request;super(`${e.message} in "${o.url.toString()}"`,e,r.request),this.name="ParseError"}};Jc.ParseError=lU;var cU=class extends Mle.RequestError{constructor(e){super("Promise was canceled",{},e),this.name="CancelError"}get isCanceled(){return!0}};Jc.CancelError=cU;nst(U1(),Jc)});var Ule=_(uU=>{"use strict";Object.defineProperty(uU,"__esModule",{value:!0});var Ole=_1(),ist=(t,e,r,o)=>{let{rawBody:a}=t;try{if(e==="text")return a.toString(o);if(e==="json")return a.length===0?"":r(a.toString());if(e==="buffer")return a;throw new Ole.ParseError({message:`Unknown body type '${e}'`,name:"Error"},t)}catch(n){throw new Ole.ParseError(n,t)}};uU.default=ist});var AU=_(ph=>{"use strict";var sst=ph&&ph.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ost=ph&&ph.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&sst(e,t,r)};Object.defineProperty(ph,"__esModule",{value:!0});var ast=ve("events"),lst=Ff(),cst=Ooe(),Jb=_1(),_le=Ule(),Hle=U1(),ust=K4(),Ast=eU(),qle=tU(),fst=["request","response","redirect","uploadProgress","downloadProgress"];function jle(t){let e,r,o=new ast.EventEmitter,a=new cst((u,A,p)=>{let h=E=>{let I=new Hle.default(void 0,t);I.retryCount=E,I._noPipe=!0,p(()=>I.destroy()),p.shouldReject=!1,p(()=>A(new Jb.CancelError(I))),e=I,I.once("response",async C=>{var T;if(C.retryCount=E,C.request.aborted)return;let L;try{L=await Ast.default(I),C.rawBody=L}catch{return}if(I._isAboutToError)return;let U=((T=C.headers["content-encoding"])!==null&&T!==void 0?T:"").toLowerCase(),z=["gzip","deflate","br"].includes(U),{options:te}=I;if(z&&!te.decompress)C.body=L;else try{C.body=_le.default(C,te.responseType,te.parseJson,te.encoding)}catch(le){if(C.body=L.toString(),qle.isResponseOk(C)){I._beforeError(le);return}}try{for(let[le,ce]of te.hooks.afterResponse.entries())C=await ce(C,async ue=>{let Ce=Hle.default.normalizeArguments(void 0,{...ue,retry:{calculateDelay:()=>0},throwHttpErrors:!1,resolveBodyOnly:!1},te);Ce.hooks.afterResponse=Ce.hooks.afterResponse.slice(0,le);for(let De of Ce.hooks.beforeRetry)await De(Ce);let he=jle(Ce);return p(()=>{he.catch(()=>{}),he.cancel()}),he})}catch(le){I._beforeError(new Jb.RequestError(le.message,le,I));return}if(!qle.isResponseOk(C)){I._beforeError(new Jb.HTTPError(C));return}r=C,u(I.options.resolveBodyOnly?C.body:C)});let D=C=>{if(a.isCanceled)return;let{options:T}=I;if(C instanceof Jb.HTTPError&&!T.throwHttpErrors){let{response:L}=C;u(I.options.resolveBodyOnly?L.body:L);return}A(C)};I.once("error",D);let x=I.options.body;I.once("retry",(C,T)=>{var L,U;if(x===((L=T.request)===null||L===void 0?void 0:L.options.body)&&lst.default.nodeStream((U=T.request)===null||U===void 0?void 0:U.options.body)){D(T);return}h(C)}),ust.default(I,o,fst)};h(0)});a.on=(u,A)=>(o.on(u,A),a);let n=u=>{let A=(async()=>{await a;let{options:p}=r.request;return _le.default(r,u,p.parseJson,p.encoding)})();return Object.defineProperties(A,Object.getOwnPropertyDescriptors(a)),A};return a.json=()=>{let{headers:u}=e.options;return!e.writableFinished&&u.accept===void 0&&(u.accept="application/json"),n("json")},a.buffer=()=>n("buffer"),a.text=()=>n("text"),a}ph.default=jle;ost(_1(),ph)});var Gle=_(fU=>{"use strict";Object.defineProperty(fU,"__esModule",{value:!0});var pst=_1();function hst(t,...e){let r=(async()=>{if(t instanceof pst.RequestError)try{for(let a of e)if(a)for(let n of a)t=await n(t)}catch(a){t=a}throw t})(),o=()=>r;return r.json=o,r.text=o,r.buffer=o,r.on=o,r}fU.default=hst});var Kle=_(pU=>{"use strict";Object.defineProperty(pU,"__esModule",{value:!0});var Yle=Ff();function Wle(t){for(let e of Object.values(t))(Yle.default.plainObject(e)||Yle.default.array(e))&&Wle(e);return Object.freeze(t)}pU.default=Wle});var zle=_(Vle=>{"use strict";Object.defineProperty(Vle,"__esModule",{value:!0})});var hU=_(Xl=>{"use strict";var gst=Xl&&Xl.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),dst=Xl&&Xl.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&gst(e,t,r)};Object.defineProperty(Xl,"__esModule",{value:!0});Xl.defaultHandler=void 0;var Jle=Ff(),Jl=AU(),mst=Gle(),Zb=U1(),yst=Kle(),Est={RequestError:Jl.RequestError,CacheError:Jl.CacheError,ReadError:Jl.ReadError,HTTPError:Jl.HTTPError,MaxRedirectsError:Jl.MaxRedirectsError,TimeoutError:Jl.TimeoutError,ParseError:Jl.ParseError,CancelError:Jl.CancelError,UnsupportedProtocolError:Jl.UnsupportedProtocolError,UploadError:Jl.UploadError},Cst=async t=>new Promise(e=>{setTimeout(e,t)}),{normalizeArguments:Xb}=Zb.default,Xle=(...t)=>{let e;for(let r of t)e=Xb(void 0,r,e);return e},wst=t=>t.isStream?new Zb.default(void 0,t):Jl.default(t),Ist=t=>"defaults"in t&&"options"in t.defaults,Bst=["get","post","put","patch","head","delete"];Xl.defaultHandler=(t,e)=>e(t);var Zle=(t,e)=>{if(t)for(let r of t)r(e)},$le=t=>{t._rawHandlers=t.handlers,t.handlers=t.handlers.map(o=>(a,n)=>{let u,A=o(a,p=>(u=n(p),u));if(A!==u&&!a.isStream&&u){let p=A,{then:h,catch:E,finally:I}=p;Object.setPrototypeOf(p,Object.getPrototypeOf(u)),Object.defineProperties(p,Object.getOwnPropertyDescriptors(u)),p.then=h,p.catch=E,p.finally=I}return A});let e=(o,a={},n)=>{var u,A;let p=0,h=E=>t.handlers[p++](E,p===t.handlers.length?wst:h);if(Jle.default.plainObject(o)){let E={...o,...a};Zb.setNonEnumerableProperties([o,a],E),a=E,o=void 0}try{let E;try{Zle(t.options.hooks.init,a),Zle((u=a.hooks)===null||u===void 0?void 0:u.init,a)}catch(D){E=D}let I=Xb(o,a,n??t.options);if(I[Zb.kIsNormalizedAlready]=!0,E)throw new Jl.RequestError(E.message,E,I);return h(I)}catch(E){if(a.isStream)throw E;return mst.default(E,t.options.hooks.beforeError,(A=a.hooks)===null||A===void 0?void 0:A.beforeError)}};e.extend=(...o)=>{let a=[t.options],n=[...t._rawHandlers],u;for(let A of o)Ist(A)?(a.push(A.defaults.options),n.push(...A.defaults._rawHandlers),u=A.defaults.mutableDefaults):(a.push(A),"handlers"in A&&n.push(...A.handlers),u=A.mutableDefaults);return n=n.filter(A=>A!==Xl.defaultHandler),n.length===0&&n.push(Xl.defaultHandler),$le({options:Xle(...a),handlers:n,mutableDefaults:!!u})};let r=async function*(o,a){let n=Xb(o,a,t.options);n.resolveBodyOnly=!1;let u=n.pagination;if(!Jle.default.object(u))throw new TypeError("`options.pagination` must be implemented");let A=[],{countLimit:p}=u,h=0;for(;h{let n=[];for await(let u of r(o,a))n.push(u);return n},e.paginate.each=r,e.stream=(o,a)=>e(o,{...a,isStream:!0});for(let o of Bst)e[o]=(a,n)=>e(a,{...n,method:o}),e.stream[o]=(a,n)=>e(a,{...n,method:o,isStream:!0});return Object.assign(e,Est),Object.defineProperty(e,"defaults",{value:t.mutableDefaults?t:yst.default(t),writable:t.mutableDefaults,configurable:t.mutableDefaults,enumerable:!0}),e.mergeOptions=Xle,e};Xl.default=$le;dst(zle(),Xl)});var rce=_((Rf,$b)=>{"use strict";var vst=Rf&&Rf.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ece=Rf&&Rf.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&vst(e,t,r)};Object.defineProperty(Rf,"__esModule",{value:!0});var Dst=ve("url"),tce=hU(),Pst={options:{method:"GET",retry:{limit:2,methods:["GET","PUT","HEAD","DELETE","OPTIONS","TRACE"],statusCodes:[408,413,429,500,502,503,504,521,522,524],errorCodes:["ETIMEDOUT","ECONNRESET","EADDRINUSE","ECONNREFUSED","EPIPE","ENOTFOUND","ENETUNREACH","EAI_AGAIN"],maxRetryAfter:void 0,calculateDelay:({computedValue:t})=>t},timeout:{},headers:{"user-agent":"got (https://github.com/sindresorhus/got)"},hooks:{init:[],beforeRequest:[],beforeRedirect:[],beforeRetry:[],beforeError:[],afterResponse:[]},cache:void 0,dnsCache:void 0,decompress:!0,throwHttpErrors:!0,followRedirect:!0,isStream:!1,responseType:"text",resolveBodyOnly:!1,maxRedirects:10,prefixUrl:"",methodRewriting:!0,ignoreInvalidCookies:!1,context:{},http2:!1,allowGetBody:!1,https:void 0,pagination:{transform:t=>t.request.options.responseType==="json"?t.body:JSON.parse(t.body),paginate:t=>{if(!Reflect.has(t.headers,"link"))return!1;let e=t.headers.link.split(","),r;for(let o of e){let a=o.split(";");if(a[1].includes("next")){r=a[0].trimStart().trim(),r=r.slice(1,-1);break}}return r?{url:new Dst.URL(r)}:!1},filter:()=>!0,shouldContinue:()=>!0,countLimit:1/0,backoff:0,requestLimit:1e4,stackAllItems:!0},parseJson:t=>JSON.parse(t),stringifyJson:t=>JSON.stringify(t),cacheOptions:{}},handlers:[tce.defaultHandler],mutableDefaults:!1},gU=tce.default(Pst);Rf.default=gU;$b.exports=gU;$b.exports.default=gU;$b.exports.__esModule=!0;ece(hU(),Rf);ece(AU(),Rf)});var on={};Kt(on,{Method:()=>cce,del:()=>Qst,get:()=>EU,getNetworkSettings:()=>lce,post:()=>CU,put:()=>kst,request:()=>H1});function sce(t){let e=new URL(t),r={host:e.hostname,headers:{}};return e.port&&(r.port=Number(e.port)),e.username&&e.password&&(r.proxyAuth=`${e.username}:${e.password}`),{proxy:r}}async function dU(t){return Al(ice,t,()=>ae.readFilePromise(t).then(e=>(ice.set(t,e),e)))}function xst({statusCode:t,statusMessage:e},r){let o=Ut(r,t,Ct.NUMBER),a=`https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/${t}`;return ty(r,`${o}${e?` (${e})`:""}`,a)}async function ex(t,{configuration:e,customErrorMessage:r}){try{return await t}catch(o){if(o.name!=="HTTPError")throw o;let a=r?.(o,e)??o.response.body?.error;a==null&&(o.message.startsWith("Response code")?a="The remote server failed to provide the requested resource":a=o.message),o.code==="ETIMEDOUT"&&o.event==="socket"&&(a+=`(can be increased via ${Ut(e,"httpTimeout",Ct.SETTING)})`);let n=new zt(35,a,u=>{o.response&&u.reportError(35,` ${$u(e,{label:"Response Code",value:Wc(Ct.NO_HINT,xst(o.response,e))})}`),o.request&&(u.reportError(35,` ${$u(e,{label:"Request Method",value:Wc(Ct.NO_HINT,o.request.options.method)})}`),u.reportError(35,` ${$u(e,{label:"Request URL",value:Wc(Ct.URL,o.request.requestUrl)})}`)),o.request.redirects.length>0&&u.reportError(35,` ${$u(e,{label:"Request Redirects",value:Wc(Ct.NO_HINT,cM(e,o.request.redirects,Ct.URL))})}`),o.request.retryCount===o.request.options.retry.limit&&u.reportError(35,` ${$u(e,{label:"Request Retry Count",value:Wc(Ct.NO_HINT,`${Ut(e,o.request.retryCount,Ct.NUMBER)} (can be increased via ${Ut(e,"httpRetry",Ct.SETTING)})`)})}`)});throw n.originalError=o,n}}function lce(t,e){let r=[...e.configuration.get("networkSettings")].sort(([u],[A])=>A.length-u.length),o={enableNetwork:void 0,httpsCaFilePath:void 0,httpProxy:void 0,httpsProxy:void 0,httpsKeyFilePath:void 0,httpsCertFilePath:void 0},a=Object.keys(o),n=typeof t=="string"?new URL(t):t;for(let[u,A]of r)if(yU.default.isMatch(n.hostname,u))for(let p of a){let h=A.get(p);h!==null&&typeof o[p]>"u"&&(o[p]=h)}for(let u of a)typeof o[u]>"u"&&(o[u]=e.configuration.get(u));return o}async function H1(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u="GET",wrapNetworkRequest:A}){let p={target:t,body:e,configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u},h=async()=>await Fst(t,e,p),E=typeof A<"u"?await A(h,p):h;return await(await r.reduceHook(D=>D.wrapNetworkRequest,E,p))()}async function EU(t,{configuration:e,jsonResponse:r,customErrorMessage:o,wrapNetworkRequest:a,...n}){let u=()=>ex(H1(t,null,{configuration:e,wrapNetworkRequest:a,...n}),{configuration:e,customErrorMessage:o}).then(p=>p.body),A=await(typeof a<"u"?u():Al(nce,t,()=>u().then(p=>(nce.set(t,p),p))));return r?JSON.parse(A.toString()):A}async function kst(t,e,{customErrorMessage:r,...o}){return(await ex(H1(t,e,{...o,method:"PUT"}),{customErrorMessage:r,configuration:o.configuration})).body}async function CU(t,e,{customErrorMessage:r,...o}){return(await ex(H1(t,e,{...o,method:"POST"}),{customErrorMessage:r,configuration:o.configuration})).body}async function Qst(t,{customErrorMessage:e,...r}){return(await ex(H1(t,null,{...r,method:"DELETE"}),{customErrorMessage:e,configuration:r.configuration})).body}async function Fst(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u="GET"}){let A=typeof t=="string"?new URL(t):t,p=lce(A,{configuration:r});if(p.enableNetwork===!1)throw new zt(80,`Request to '${A.href}' has been blocked because of your configuration settings`);if(A.protocol==="http:"&&!yU.default.isMatch(A.hostname,r.get("unsafeHttpWhitelist")))throw new zt(81,`Unsafe http requests must be explicitly whitelisted in your configuration (${A.hostname})`);let E={agent:{http:p.httpProxy?mU.default.httpOverHttp(sce(p.httpProxy)):Sst,https:p.httpsProxy?mU.default.httpsOverHttp(sce(p.httpsProxy)):bst},headers:o,method:u};E.responseType=n?"json":"buffer",e!==null&&(Buffer.isBuffer(e)||!a&&typeof e=="string"?E.body=e:E.json=e);let I=r.get("httpTimeout"),D=r.get("httpRetry"),x=r.get("enableStrictSsl"),C=p.httpsCaFilePath,T=p.httpsCertFilePath,L=p.httpsKeyFilePath,{default:U}=await Promise.resolve().then(()=>et(rce())),z=C?await dU(C):void 0,te=T?await dU(T):void 0,le=L?await dU(L):void 0,ce=U.extend({timeout:{socket:I},retry:D,https:{rejectUnauthorized:x,certificateAuthority:z,certificate:te,key:le},...E});return r.getLimit("networkConcurrency")(()=>ce(A))}var oce,ace,yU,mU,nce,ice,Sst,bst,cce,tx=wt(()=>{Pt();oce=ve("https"),ace=ve("http"),yU=et(Xo()),mU=et(Roe());Vl();Yl();Gl();nce=new Map,ice=new Map,Sst=new ace.Agent({keepAlive:!0}),bst=new oce.Agent({keepAlive:!0});cce=(a=>(a.GET="GET",a.PUT="PUT",a.POST="POST",a.DELETE="DELETE",a))(cce||{})});var Xi={};Kt(Xi,{availableParallelism:()=>IU,getArchitecture:()=>q1,getArchitectureName:()=>Mst,getArchitectureSet:()=>wU,getCaller:()=>Hst,major:()=>Rst,openUrl:()=>Tst});function Lst(){if(process.platform==="darwin"||process.platform==="win32")return null;let t;try{t=ae.readFileSync(Nst)}catch{}if(typeof t<"u"){if(t&&(t.includes("GLIBC")||t.includes("libc")))return"glibc";if(t&&t.includes("musl"))return"musl"}let r=(process.report?.getReport()??{}).sharedObjects??[],o=/\/(?:(ld-linux-|[^/]+-linux-gnu\/)|(libc.musl-|ld-musl-))/;return eh(r,a=>{let n=a.match(o);if(!n)return eh.skip;if(n[1])return"glibc";if(n[2])return"musl";throw new Error("Assertion failed: Expected the libc variant to have been detected")})??null}function q1(){return Ace=Ace??{os:process.platform,cpu:process.arch,libc:Lst()}}function Mst(t=q1()){return t.libc?`${t.os}-${t.cpu}-${t.libc}`:`${t.os}-${t.cpu}`}function wU(){let t=q1();return fce=fce??{os:[t.os],cpu:[t.cpu],libc:t.libc?[t.libc]:[]}}function _st(t){let e=Ost.exec(t);if(!e)return null;let r=e[2]&&e[2].indexOf("native")===0,o=e[2]&&e[2].indexOf("eval")===0,a=Ust.exec(e[2]);return o&&a!=null&&(e[2]=a[1],e[3]=a[2],e[4]=a[3]),{file:r?null:e[2],methodName:e[1]||"",arguments:r?[e[2]]:[],line:e[3]?+e[3]:null,column:e[4]?+e[4]:null}}function Hst(){let e=new Error().stack.split(` +`)[3];return _st(e)}function IU(){return typeof rx.default.availableParallelism<"u"?rx.default.availableParallelism():Math.max(1,rx.default.cpus().length)}var rx,Rst,uce,Tst,Nst,Ace,fce,Ost,Ust,nx=wt(()=>{Pt();rx=et(ve("os"));ix();Gl();Rst=Number(process.versions.node.split(".")[0]),uce=new Map([["darwin","open"],["linux","xdg-open"],["win32","explorer.exe"]]).get(process.platform),Tst=typeof uce<"u"?async t=>{try{return await BU(uce,[t],{cwd:K.cwd()}),!0}catch{return!1}}:void 0,Nst="/usr/bin/ldd";Ost=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,Ust=/\((\S*)(?::(\d+))(?::(\d+))\)/});function bU(t,e,r,o,a){let n=x1(r);if(o.isArray||o.type==="ANY"&&Array.isArray(n))return Array.isArray(n)?n.map((u,A)=>vU(t,`${e}[${A}]`,u,o,a)):String(n).split(/,/).map(u=>vU(t,e,u,o,a));if(Array.isArray(n))throw new Error(`Non-array configuration settings "${e}" cannot be an array`);return vU(t,e,r,o,a)}function vU(t,e,r,o,a){let n=x1(r);switch(o.type){case"ANY":return Bb(n);case"SHAPE":return Yst(t,e,r,o,a);case"MAP":return Wst(t,e,r,o,a)}if(n===null&&!o.isNullable&&o.default!==null)throw new Error(`Non-nullable configuration settings "${e}" cannot be set to null`);if(o.values?.includes(n))return n;let A=(()=>{if(o.type==="BOOLEAN"&&typeof n!="string")return f1(n);if(typeof n!="string")throw new Error(`Expected configuration setting "${e}" to be a string, got ${typeof n}`);let p=LS(n,{env:t.env});switch(o.type){case"ABSOLUTE_PATH":{let h=a,E=e4(r);return E&&E[0]!=="<"&&(h=K.dirname(E)),K.resolve(h,Ae.toPortablePath(p))}case"LOCATOR_LOOSE":return Sf(p,!1);case"NUMBER":return parseInt(p);case"LOCATOR":return Sf(p);case"BOOLEAN":return f1(p);default:return p}})();if(o.values&&!o.values.includes(A))throw new Error(`Invalid value, expected one of ${o.values.join(", ")}`);return A}function Yst(t,e,r,o,a){let n=x1(r);if(typeof n!="object"||Array.isArray(n))throw new ot(`Object configuration settings "${e}" must be an object`);let u=xU(t,o,{ignoreArrays:!0});if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=`${e}.${A}`;if(!o.properties[A])throw new ot(`Unrecognized configuration settings found: ${e}.${A} - run "yarn config -v" to see the list of settings supported in Yarn`);u.set(A,bU(t,h,p,o.properties[A],a))}return u}function Wst(t,e,r,o,a){let n=x1(r),u=new Map;if(typeof n!="object"||Array.isArray(n))throw new ot(`Map configuration settings "${e}" must be an object`);if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=o.normalizeKeys?o.normalizeKeys(A):A,E=`${e}['${h}']`,I=o.valueDefinition;u.set(h,bU(t,E,p,I,a))}return u}function xU(t,e,{ignoreArrays:r=!1}={}){switch(e.type){case"SHAPE":{if(e.isArray&&!r)return[];let o=new Map;for(let[a,n]of Object.entries(e.properties))o.set(a,xU(t,n));return o}case"MAP":return e.isArray&&!r?[]:new Map;case"ABSOLUTE_PATH":return e.default===null?null:t.projectCwd===null?Array.isArray(e.default)?e.default.map(o=>K.normalize(o)):K.isAbsolute(e.default)?K.normalize(e.default):e.isNullable?null:void 0:Array.isArray(e.default)?e.default.map(o=>K.resolve(t.projectCwd,o)):K.resolve(t.projectCwd,e.default);default:return e.default}}function ox(t,e,r){if(e.type==="SECRET"&&typeof t=="string"&&r.hideSecrets)return Gst;if(e.type==="ABSOLUTE_PATH"&&typeof t=="string"&&r.getNativePaths)return Ae.fromPortablePath(t);if(e.isArray&&Array.isArray(t)){let o=[];for(let a of t)o.push(ox(a,e,r));return o}if(e.type==="MAP"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=ox(n,e.valueDefinition,r);typeof u<"u"&&o.set(a,u)}return o}if(e.type==="SHAPE"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=e.properties[a],A=ox(n,u,r);typeof A<"u"&&o.set(a,A)}return o}return t}function Kst(){let t={};for(let[e,r]of Object.entries(process.env))e=e.toLowerCase(),e.startsWith(ax)&&(e=(0,hce.default)(e.slice(ax.length)),t[e]=r);return t}function PU(){let t=`${ax}rc_filename`;for(let[e,r]of Object.entries(process.env))if(e.toLowerCase()===t&&typeof r=="string")return r;return SU}async function pce(t){try{return await ae.readFilePromise(t)}catch{return Buffer.of()}}async function Vst(t,e){return Buffer.compare(...await Promise.all([pce(t),pce(e)]))===0}async function zst(t,e){let[r,o]=await Promise.all([ae.statPromise(t),ae.statPromise(e)]);return r.dev===o.dev&&r.ino===o.ino}async function Xst({configuration:t,selfPath:e}){let r=t.get("yarnPath");return t.get("ignorePath")||r===null||r===e||await Jst(r,e)?null:r}var hce,Tf,gce,dce,mce,DU,qst,j1,jst,xy,ax,SU,Gst,G1,yce,lx,sx,Jst,Je,Y1=wt(()=>{Pt();Ml();hce=et(jV()),Tf=et(sg());Gt();gce=et(Lz()),dce=ve("module"),mce=et(lg()),DU=ve("stream");Vse();Ay();WO();KO();VO();Ioe();zO();Dg();Soe();Db();Yl();ah();tx();Gl();nx();xf();wo();qst=function(){if(!Tf.GITHUB_ACTIONS||!process.env.GITHUB_EVENT_PATH)return!1;let t=Ae.toPortablePath(process.env.GITHUB_EVENT_PATH),e;try{e=ae.readJsonSync(t)}catch{return!1}return!(!("repository"in e)||!e.repository||(e.repository.private??!0))}(),j1=new Set(["@yarnpkg/plugin-constraints","@yarnpkg/plugin-exec","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"]),jst=new Set(["isTestEnv","injectNpmUser","injectNpmPassword","injectNpm2FaToken","zipDataEpilogue","cacheCheckpointOverride","cacheVersionOverride","lockfileVersionOverride","binFolder","version","flags","profile","gpg","ignoreNode","wrapOutput","home","confDir","registry","ignoreCwd"]),xy=/^(?!v)[a-z0-9._-]+$/i,ax="yarn_",SU=".yarnrc.yml",Gst="********",G1=(E=>(E.ANY="ANY",E.BOOLEAN="BOOLEAN",E.ABSOLUTE_PATH="ABSOLUTE_PATH",E.LOCATOR="LOCATOR",E.LOCATOR_LOOSE="LOCATOR_LOOSE",E.NUMBER="NUMBER",E.STRING="STRING",E.SECRET="SECRET",E.SHAPE="SHAPE",E.MAP="MAP",E))(G1||{}),yce=Ct,lx=(r=>(r.JUNCTIONS="junctions",r.SYMLINKS="symlinks",r))(lx||{}),sx={lastUpdateCheck:{description:"Last timestamp we checked whether new Yarn versions were available",type:"STRING",default:null},yarnPath:{description:"Path to the local executable that must be used over the global one",type:"ABSOLUTE_PATH",default:null},ignorePath:{description:"If true, the local executable will be ignored when using the global one",type:"BOOLEAN",default:!1},globalFolder:{description:"Folder where all system-global files are stored",type:"ABSOLUTE_PATH",default:r4()},cacheFolder:{description:"Folder where the cache files must be written",type:"ABSOLUTE_PATH",default:"./.yarn/cache"},compressionLevel:{description:"Zip files compression level, from 0 to 9 or mixed (a variant of 9, which stores some files uncompressed, when compression doesn't yield good results)",type:"NUMBER",values:["mixed",0,1,2,3,4,5,6,7,8,9],default:0},virtualFolder:{description:"Folder where the virtual packages (cf doc) will be mapped on the disk (must be named __virtual__)",type:"ABSOLUTE_PATH",default:"./.yarn/__virtual__"},installStatePath:{description:"Path of the file where the install state will be persisted",type:"ABSOLUTE_PATH",default:"./.yarn/install-state.gz"},immutablePatterns:{description:"Array of glob patterns; files matching them won't be allowed to change during immutable installs",type:"STRING",default:[],isArray:!0},rcFilename:{description:"Name of the files where the configuration can be found",type:"STRING",default:PU()},enableGlobalCache:{description:"If true, the system-wide cache folder will be used regardless of `cache-folder`",type:"BOOLEAN",default:!0},cacheMigrationMode:{description:"Defines the conditions under which Yarn upgrades should cause the cache archives to be regenerated.",type:"STRING",values:["always","match-spec","required-only"],default:"always"},enableColors:{description:"If true, the CLI is allowed to use colors in its output",type:"BOOLEAN",default:US,defaultText:""},enableHyperlinks:{description:"If true, the CLI is allowed to use hyperlinks in its output",type:"BOOLEAN",default:lM,defaultText:""},enableInlineBuilds:{description:"If true, the CLI will print the build output on the command line",type:"BOOLEAN",default:Tf.isCI,defaultText:""},enableMessageNames:{description:"If true, the CLI will prefix most messages with codes suitable for search engines",type:"BOOLEAN",default:!0},enableProgressBars:{description:"If true, the CLI is allowed to show a progress bar for long-running events",type:"BOOLEAN",default:!Tf.isCI,defaultText:""},enableTimers:{description:"If true, the CLI is allowed to print the time spent executing commands",type:"BOOLEAN",default:!0},enableTips:{description:"If true, installs will print a helpful message every day of the week",type:"BOOLEAN",default:!Tf.isCI,defaultText:""},preferInteractive:{description:"If true, the CLI will automatically use the interactive mode when called from a TTY",type:"BOOLEAN",default:!1},preferTruncatedLines:{description:"If true, the CLI will truncate lines that would go beyond the size of the terminal",type:"BOOLEAN",default:!1},progressBarStyle:{description:"Which style of progress bar should be used (only when progress bars are enabled)",type:"STRING",default:void 0,defaultText:""},defaultLanguageName:{description:"Default language mode that should be used when a package doesn't offer any insight",type:"STRING",default:"node"},defaultProtocol:{description:"Default resolution protocol used when resolving pure semver and tag ranges",type:"STRING",default:"npm:"},enableTransparentWorkspaces:{description:"If false, Yarn won't automatically resolve workspace dependencies unless they use the `workspace:` protocol",type:"BOOLEAN",default:!0},supportedArchitectures:{description:"Architectures that Yarn will fetch and inject into the resolver",type:"SHAPE",properties:{os:{description:"Array of supported process.platform strings, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]},cpu:{description:"Array of supported process.arch strings, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]},libc:{description:"Array of supported libc libraries, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]}}},enableMirror:{description:"If true, the downloaded packages will be retrieved and stored in both the local and global folders",type:"BOOLEAN",default:!0},enableNetwork:{description:"If false, Yarn will refuse to use the network if required to",type:"BOOLEAN",default:!0},enableOfflineMode:{description:"If true, Yarn will attempt to retrieve files and metadata from the global cache rather than the network",type:"BOOLEAN",default:!1},httpProxy:{description:"URL of the http proxy that must be used for outgoing http requests",type:"STRING",default:null},httpsProxy:{description:"URL of the http proxy that must be used for outgoing https requests",type:"STRING",default:null},unsafeHttpWhitelist:{description:"List of the hostnames for which http queries are allowed (glob patterns are supported)",type:"STRING",default:[],isArray:!0},httpTimeout:{description:"Timeout of each http request in milliseconds",type:"NUMBER",default:6e4},httpRetry:{description:"Retry times on http failure",type:"NUMBER",default:3},networkConcurrency:{description:"Maximal number of concurrent requests",type:"NUMBER",default:50},taskPoolConcurrency:{description:"Maximal amount of concurrent heavy task processing",type:"NUMBER",default:IU()},taskPoolMode:{description:"Execution strategy for heavy tasks",type:"STRING",values:["async","workers"],default:"workers"},networkSettings:{description:"Network settings per hostname (glob patterns are supported)",type:"MAP",valueDefinition:{description:"",type:"SHAPE",properties:{httpsCaFilePath:{description:"Path to file containing one or multiple Certificate Authority signing certificates",type:"ABSOLUTE_PATH",default:null},enableNetwork:{description:"If false, the package manager will refuse to use the network if required to",type:"BOOLEAN",default:null},httpProxy:{description:"URL of the http proxy that must be used for outgoing http requests",type:"STRING",default:null},httpsProxy:{description:"URL of the http proxy that must be used for outgoing https requests",type:"STRING",default:null},httpsKeyFilePath:{description:"Path to file containing private key in PEM format",type:"ABSOLUTE_PATH",default:null},httpsCertFilePath:{description:"Path to file containing certificate chain in PEM format",type:"ABSOLUTE_PATH",default:null}}}},httpsCaFilePath:{description:"A path to a file containing one or multiple Certificate Authority signing certificates",type:"ABSOLUTE_PATH",default:null},httpsKeyFilePath:{description:"Path to file containing private key in PEM format",type:"ABSOLUTE_PATH",default:null},httpsCertFilePath:{description:"Path to file containing certificate chain in PEM format",type:"ABSOLUTE_PATH",default:null},enableStrictSsl:{description:"If false, SSL certificate errors will be ignored",type:"BOOLEAN",default:!0},logFilters:{description:"Overrides for log levels",type:"SHAPE",isArray:!0,concatenateValues:!0,properties:{code:{description:"Code of the messages covered by this override",type:"STRING",default:void 0},text:{description:"Code of the texts covered by this override",type:"STRING",default:void 0},pattern:{description:"Code of the patterns covered by this override",type:"STRING",default:void 0},level:{description:"Log level override, set to null to remove override",type:"STRING",values:Object.values(HS),isNullable:!0,default:void 0}}},enableTelemetry:{description:"If true, telemetry will be periodically sent, following the rules in https://yarnpkg.com/advanced/telemetry",type:"BOOLEAN",default:!0},telemetryInterval:{description:"Minimal amount of time between two telemetry uploads, in days",type:"NUMBER",default:7},telemetryUserId:{description:"If you desire to tell us which project you are, you can set this field. Completely optional and opt-in.",type:"STRING",default:null},enableHardenedMode:{description:"If true, automatically enable --check-resolutions --refresh-lockfile on installs",type:"BOOLEAN",default:Tf.isPR&&qst,defaultText:""},enableScripts:{description:"If true, packages are allowed to have install scripts by default",type:"BOOLEAN",default:!0},enableStrictSettings:{description:"If true, unknown settings will cause Yarn to abort",type:"BOOLEAN",default:!0},enableImmutableCache:{description:"If true, the cache is reputed immutable and actions that would modify it will throw",type:"BOOLEAN",default:!1},checksumBehavior:{description:"Enumeration defining what to do when a checksum doesn't match expectations",type:"STRING",default:"throw"},injectEnvironmentFiles:{description:"List of all the environment files that Yarn should inject inside the process when it starts",type:"ABSOLUTE_PATH",default:[".env.yarn?"],isArray:!0},packageExtensions:{description:"Map of package corrections to apply on the dependency tree",type:"MAP",valueDefinition:{description:"The extension that will be applied to any package whose version matches the specified range",type:"SHAPE",properties:{dependencies:{description:"The set of dependencies that must be made available to the current package in order for it to work properly",type:"MAP",valueDefinition:{description:"A range",type:"STRING"}},peerDependencies:{description:"Inherited dependencies - the consumer of the package will be tasked to provide them",type:"MAP",valueDefinition:{description:"A semver range",type:"STRING"}},peerDependenciesMeta:{description:"Extra information related to the dependencies listed in the peerDependencies field",type:"MAP",valueDefinition:{description:"The peerDependency meta",type:"SHAPE",properties:{optional:{description:"If true, the selected peer dependency will be marked as optional by the package manager and the consumer omitting it won't be reported as an error",type:"BOOLEAN",default:!1}}}}}}}};Jst=process.platform==="win32"?Vst:zst;Je=class t{constructor(e){this.isCI=Tf.isCI;this.projectCwd=null;this.plugins=new Map;this.settings=new Map;this.values=new Map;this.sources=new Map;this.invalid=new Map;this.env={};this.limits=new Map;this.packageExtensions=null;this.startingCwd=e}static{this.deleteProperty=Symbol()}static{this.telemetry=null}static create(e,r,o){let a=new t(e);typeof r<"u"&&!(r instanceof Map)&&(a.projectCwd=r),a.importSettings(sx);let n=typeof o<"u"?o:r instanceof Map?r:new Map;for(let[u,A]of n)a.activatePlugin(u,A);return a}static async find(e,r,{strict:o=!0,usePathCheck:a=null,useRc:n=!0}={}){let u=Kst();delete u.rcFilename;let A=new t(e),p=await t.findRcFiles(e),h=await t.findFolderRcFile(my());h&&(p.find(Ce=>Ce.path===h.path)||p.unshift(h));let E=Poe(p.map(ue=>[ue.path,ue.data])),I=Bt.dot,D=new Set(Object.keys(sx)),x=({yarnPath:ue,ignorePath:Ce,injectEnvironmentFiles:he})=>({yarnPath:ue,ignorePath:Ce,injectEnvironmentFiles:he}),C=({yarnPath:ue,ignorePath:Ce,injectEnvironmentFiles:he,...De})=>{let Ee={};for(let[g,me]of Object.entries(De))D.has(g)&&(Ee[g]=me);return Ee},T=({yarnPath:ue,ignorePath:Ce,...he})=>{let De={};for(let[Ee,g]of Object.entries(he))D.has(Ee)||(De[Ee]=g);return De};if(A.importSettings(x(sx)),A.useWithSource("",x(u),e,{strict:!1}),E){let[ue,Ce]=E;A.useWithSource(ue,x(Ce),I,{strict:!1})}if(a){if(await Xst({configuration:A,selfPath:a})!==null)return A;A.useWithSource("",{ignorePath:!0},e,{strict:!1,overwrite:!0})}let L=await t.findProjectCwd(e);A.startingCwd=e,A.projectCwd=L;let U=Object.assign(Object.create(null),process.env);A.env=U;let z=await Promise.all(A.get("injectEnvironmentFiles").map(async ue=>{let Ce=ue.endsWith("?")?await ae.readFilePromise(ue.slice(0,-1),"utf8").catch(()=>""):await ae.readFilePromise(ue,"utf8");return(0,gce.parse)(Ce)}));for(let ue of z)for(let[Ce,he]of Object.entries(ue))A.env[Ce]=LS(he,{env:U});if(A.importSettings(C(sx)),A.useWithSource("",C(u),e,{strict:o}),E){let[ue,Ce]=E;A.useWithSource(ue,C(Ce),I,{strict:o})}let te=ue=>"default"in ue?ue.default:ue,le=new Map([["@@core",Kse]]);if(r!==null)for(let ue of r.plugins.keys())le.set(ue,te(r.modules.get(ue)));for(let[ue,Ce]of le)A.activatePlugin(ue,Ce);let ce=new Map([]);if(r!==null){let ue=new Map;for(let[De,Ee]of r.modules)ue.set(De,()=>Ee);let Ce=new Set,he=async(De,Ee)=>{let{factory:g,name:me}=vf(De);if(!g||Ce.has(me))return;let we=new Map(ue),fe=Z=>{if((0,dce.isBuiltin)(Z))return vf(Z);if(we.has(Z))return we.get(Z)();throw new ot(`This plugin cannot access the package referenced via ${Z} which is neither a builtin, nor an exposed entry`)},ie=await Jm(async()=>te(await g(fe)),Z=>`${Z} (when initializing ${me}, defined in ${Ee})`);ue.set(me,()=>ie),Ce.add(me),ce.set(me,ie)};if(u.plugins)for(let De of u.plugins.split(";")){let Ee=K.resolve(e,Ae.toPortablePath(De));await he(Ee,"")}for(let{path:De,cwd:Ee,data:g}of p)if(n&&Array.isArray(g.plugins))for(let me of g.plugins){let we=typeof me!="string"?me.path:me,fe=me?.spec??"",ie=me?.checksum??"";if(j1.has(fe))continue;let Z=K.resolve(Ee,Ae.toPortablePath(we));if(!await ae.existsPromise(Z)){if(!fe){let gt=Ut(A,K.basename(Z,".cjs"),Ct.NAME),q=Ut(A,".gitignore",Ct.NAME),nt=Ut(A,A.values.get("rcFilename"),Ct.NAME),Ne=Ut(A,"https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored",Ct.URL);throw new ot(`Missing source for the ${gt} plugin - please try to remove the plugin from ${nt} then reinstall it manually. This error usually occurs because ${q} is incorrect, check ${Ne} to make sure your plugin folder isn't gitignored.`)}if(!fe.match(/^https?:/)){let gt=Ut(A,K.basename(Z,".cjs"),Ct.NAME),q=Ut(A,A.values.get("rcFilename"),Ct.NAME);throw new ot(`Failed to recognize the source for the ${gt} plugin - please try to delete the plugin from ${q} then reinstall it manually.`)}let xe=await EU(fe,{configuration:A}),Re=zi(xe);if(ie&&ie!==Re){let gt=Ut(A,K.basename(Z,".cjs"),Ct.NAME),q=Ut(A,A.values.get("rcFilename"),Ct.NAME),nt=Ut(A,`yarn plugin import ${fe}`,Ct.CODE);throw new ot(`Failed to fetch the ${gt} plugin from its remote location: its checksum seems to have changed. If this is expected, please remove the plugin from ${q} then run ${nt} to reimport it.`)}await ae.mkdirPromise(K.dirname(Z),{recursive:!0}),await ae.writeFilePromise(Z,xe)}await he(Z,De)}}for(let[ue,Ce]of ce)A.activatePlugin(ue,Ce);if(A.useWithSource("",T(u),e,{strict:o}),E){let[ue,Ce]=E;A.useWithSource(ue,T(Ce),I,{strict:o})}return A.get("enableGlobalCache")&&(A.values.set("cacheFolder",`${A.get("globalFolder")}/cache`),A.sources.set("cacheFolder","")),A}static async findRcFiles(e){let r=PU(),o=[],a=e,n=null;for(;a!==n;){n=a;let u=K.join(n,r);if(ae.existsSync(u)){let A=await ae.readFilePromise(u,"utf8"),p;try{p=Ki(A)}catch{let E="";throw A.match(/^\s+(?!-)[^:]+\s+\S+/m)&&(E=" (in particular, make sure you list the colons after each key name)"),new ot(`Parse error when loading ${u}; please check it's proper Yaml${E}`)}o.unshift({path:u,cwd:n,data:p})}a=K.dirname(n)}return o}static async findFolderRcFile(e){let r=K.join(e,mr.rc),o;try{o=await ae.readFilePromise(r,"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}let a=Ki(o);return{path:r,cwd:e,data:a}}static async findProjectCwd(e){let r=null,o=e,a=null;for(;o!==a;){if(a=o,ae.existsSync(K.join(a,mr.lockfile)))return a;ae.existsSync(K.join(a,mr.manifest))&&(r=a),o=K.dirname(a)}return r}static async updateConfiguration(e,r,o={}){let a=PU(),n=K.join(e,a),u=ae.existsSync(n)?Ki(await ae.readFilePromise(n,"utf8")):{},A=!1,p;if(typeof r=="function"){try{p=r(u)}catch{p=r({})}if(p===u)return!1}else{p=u;for(let h of Object.keys(r)){let E=u[h],I=r[h],D;if(typeof I=="function")try{D=I(E)}catch{D=I(void 0)}else D=I;E!==D&&(D===t.deleteProperty?delete p[h]:p[h]=D,A=!0)}if(!A)return!1}return await ae.changeFilePromise(n,Pa(p),{automaticNewlines:!0}),!0}static async addPlugin(e,r){r.length!==0&&await t.updateConfiguration(e,o=>{let a=o.plugins??[];if(a.length===0)return{...o,plugins:r};let n=[],u=[...r];for(let A of a){let p=typeof A!="string"?A.path:A,h=u.find(E=>E.path===p);h?(n.push(h),u=u.filter(E=>E!==h)):n.push(A)}return n.push(...u),{...o,plugins:n}})}static async updateHomeConfiguration(e){let r=my();return await t.updateConfiguration(r,e)}activatePlugin(e,r){this.plugins.set(e,r),typeof r.configuration<"u"&&this.importSettings(r.configuration)}importSettings(e){for(let[r,o]of Object.entries(e))if(o!=null){if(this.settings.has(r))throw new Error(`Cannot redefine settings "${r}"`);this.settings.set(r,o),this.values.set(r,xU(this,o))}}useWithSource(e,r,o,a){try{this.use(e,r,o,a)}catch(n){throw n.message+=` (in ${Ut(this,e,Ct.PATH)})`,n}}use(e,r,o,{strict:a=!0,overwrite:n=!1}={}){a=a&&this.get("enableStrictSettings");for(let u of["enableStrictSettings",...Object.keys(r)]){let A=r[u],p=e4(A);if(p&&(e=p),typeof A>"u"||u==="plugins"||e===""&&jst.has(u))continue;if(u==="rcFilename")throw new ot(`The rcFilename settings can only be set via ${`${ax}RC_FILENAME`.toUpperCase()}, not via a rc file`);let h=this.settings.get(u);if(!h){let I=my(),D=e[0]!=="<"?K.dirname(e):null;if(a&&!(D!==null?I===D:!1))throw new ot(`Unrecognized or legacy configuration settings found: ${u} - run "yarn config -v" to see the list of settings supported in Yarn`);this.invalid.set(u,e);continue}if(this.sources.has(u)&&!(n||h.type==="MAP"||h.isArray&&h.concatenateValues))continue;let E;try{E=bU(this,u,A,h,o)}catch(I){throw I.message+=` in ${Ut(this,e,Ct.PATH)}`,I}if(u==="enableStrictSettings"&&e!==""){a=E;continue}if(h.type==="MAP"){let I=this.values.get(u);this.values.set(u,new Map(n?[...I,...E]:[...E,...I])),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else if(h.isArray&&h.concatenateValues){let I=this.values.get(u);this.values.set(u,n?[...I,...E]:[...E,...I]),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else this.values.set(u,E),this.sources.set(u,e)}}get(e){if(!this.values.has(e))throw new Error(`Invalid configuration key "${e}"`);return this.values.get(e)}getSpecial(e,{hideSecrets:r=!1,getNativePaths:o=!1}){let a=this.get(e),n=this.settings.get(e);if(typeof n>"u")throw new ot(`Couldn't find a configuration settings named "${e}"`);return ox(a,n,{hideSecrets:r,getNativePaths:o})}getSubprocessStreams(e,{header:r,prefix:o,report:a}){let n,u,A=ae.createWriteStream(e);if(this.get("enableInlineBuilds")){let p=a.createStreamReporter(`${o} ${Ut(this,"STDOUT","green")}`),h=a.createStreamReporter(`${o} ${Ut(this,"STDERR","red")}`);n=new DU.PassThrough,n.pipe(p),n.pipe(A),u=new DU.PassThrough,u.pipe(h),u.pipe(A)}else n=A,u=A,typeof r<"u"&&n.write(`${r} +`);return{stdout:n,stderr:u}}makeResolver(){let e=[];for(let r of this.plugins.values())for(let o of r.resolvers||[])e.push(new o);return new Pg([new Ib,new ci,...e])}makeFetcher(){let e=[];for(let r of this.plugins.values())for(let o of r.fetchers||[])e.push(new o);return new py([new hy,new gy,...e])}getLinkers(){let e=[];for(let r of this.plugins.values())for(let o of r.linkers||[])e.push(new o);return e}getSupportedArchitectures(){let e=q1(),r=this.get("supportedArchitectures"),o=r.get("os");o!==null&&(o=o.map(u=>u==="current"?e.os:u));let a=r.get("cpu");a!==null&&(a=a.map(u=>u==="current"?e.cpu:u));let n=r.get("libc");return n!==null&&(n=ul(n,u=>u==="current"?e.libc??ul.skip:u)),{os:o,cpu:a,libc:n}}isInteractive({interactive:e,stdout:r}){return r.isTTY?e??this.get("preferInteractive"):!1}async getPackageExtensions(){if(this.packageExtensions!==null)return this.packageExtensions;this.packageExtensions=new Map;let e=this.packageExtensions,r=(o,a,{userProvided:n=!1}={})=>{if(!Fa(o.range))throw new Error("Only semver ranges are allowed as keys for the packageExtensions setting");let u=new _t;u.load(a,{yamlCompatibilityMode:!0});let A=u1(e,o.identHash),p=[];A.push([o.range,p]);let h={status:"inactive",userProvided:n,parentDescriptor:o};for(let E of u.dependencies.values())p.push({...h,type:"Dependency",descriptor:E});for(let E of u.peerDependencies.values())p.push({...h,type:"PeerDependency",descriptor:E});for(let[E,I]of u.peerDependenciesMeta)for(let[D,x]of Object.entries(I))p.push({...h,type:"PeerDependencyMeta",selector:E,key:D,value:x})};await this.triggerHook(o=>o.registerPackageExtensions,this,r);for(let[o,a]of this.get("packageExtensions"))r(lh(o,!0),NS(a),{userProvided:!0});return e}normalizeLocator(e){return Fa(e.reference)?Ss(e,`${this.get("defaultProtocol")}${e.reference}`):xy.test(e.reference)?Ss(e,`${this.get("defaultProtocol")}${e.reference}`):e}normalizeDependency(e){return Fa(e.range)?kn(e,`${this.get("defaultProtocol")}${e.range}`):xy.test(e.range)?kn(e,`${this.get("defaultProtocol")}${e.range}`):e}normalizeDependencyMap(e){return new Map([...e].map(([r,o])=>[r,this.normalizeDependency(o)]))}normalizePackage(e,{packageExtensions:r}){let o=E1(e),a=r.get(e.identHash);if(typeof a<"u"){let u=e.version;if(u!==null){for(let[A,p]of a)if(nA(u,A))for(let h of p)switch(h.status==="inactive"&&(h.status="redundant"),h.type){case"Dependency":typeof o.dependencies.get(h.descriptor.identHash)>"u"&&(h.status="active",o.dependencies.set(h.descriptor.identHash,this.normalizeDependency(h.descriptor)));break;case"PeerDependency":typeof o.peerDependencies.get(h.descriptor.identHash)>"u"&&(h.status="active",o.peerDependencies.set(h.descriptor.identHash,h.descriptor));break;case"PeerDependencyMeta":{let E=o.peerDependenciesMeta.get(h.selector);(typeof E>"u"||!Object.hasOwn(E,h.key)||E[h.key]!==h.value)&&(h.status="active",Al(o.peerDependenciesMeta,h.selector,()=>({}))[h.key]=h.value)}break;default:tM(h)}}}let n=u=>u.scope?`${u.scope}__${u.name}`:`${u.name}`;for(let u of o.peerDependenciesMeta.keys()){let A=Zo(u);o.peerDependencies.has(A.identHash)||o.peerDependencies.set(A.identHash,kn(A,"*"))}for(let u of o.peerDependencies.values()){if(u.scope==="types")continue;let A=n(u),p=rA("types",A),h=rn(p);o.peerDependencies.has(p.identHash)||o.peerDependenciesMeta.has(h)||(o.peerDependencies.set(p.identHash,kn(p,"*")),o.peerDependenciesMeta.set(h,{optional:!0}))}return o.dependencies=new Map(Ps(o.dependencies,([,u])=>ka(u))),o.peerDependencies=new Map(Ps(o.peerDependencies,([,u])=>ka(u))),o}getLimit(e){return Al(this.limits,e,()=>(0,mce.default)(this.get(e)))}async triggerHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);n&&await n(...r)}}async triggerMultipleHooks(e,r){for(let o of r)await this.triggerHook(e,...o)}async reduceHook(e,r,...o){let a=r;for(let n of this.plugins.values()){let u=n.hooks;if(!u)continue;let A=e(u);A&&(a=await A(a,...o))}return a}async firstHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);if(!n)continue;let u=await n(...r);if(typeof u<"u")return u}return null}}});var Hr={};Kt(Hr,{EndStrategy:()=>RU,ExecError:()=>cx,PipeError:()=>W1,execvp:()=>BU,pipevp:()=>Xc});function kg(t){return t!==null&&typeof t.fd=="number"}function kU(){}function QU(){for(let t of Qg)t.kill()}async function Xc(t,e,{cwd:r,env:o=process.env,strict:a=!1,stdin:n=null,stdout:u,stderr:A,end:p=2}){let h=["pipe","pipe","pipe"];n===null?h[0]="ignore":kg(n)&&(h[0]=n),kg(u)&&(h[1]=u),kg(A)&&(h[2]=A);let E=(0,FU.default)(t,e,{cwd:Ae.fromPortablePath(r),env:{...o,PWD:Ae.fromPortablePath(r)},stdio:h});Qg.add(E),Qg.size===1&&(process.on("SIGINT",kU),process.on("SIGTERM",QU)),!kg(n)&&n!==null&&n.pipe(E.stdin),kg(u)||E.stdout.pipe(u,{end:!1}),kg(A)||E.stderr.pipe(A,{end:!1});let I=()=>{for(let D of new Set([u,A]))kg(D)||D.end()};return new Promise((D,x)=>{E.on("error",C=>{Qg.delete(E),Qg.size===0&&(process.off("SIGINT",kU),process.off("SIGTERM",QU)),(p===2||p===1)&&I(),x(C)}),E.on("close",(C,T)=>{Qg.delete(E),Qg.size===0&&(process.off("SIGINT",kU),process.off("SIGTERM",QU)),(p===2||p===1&&C!==0)&&I(),C===0||!a?D({code:TU(C,T)}):x(new W1({fileName:t,code:C,signal:T}))})})}async function BU(t,e,{cwd:r,env:o=process.env,encoding:a="utf8",strict:n=!1}){let u=["ignore","pipe","pipe"],A=[],p=[],h=Ae.fromPortablePath(r);typeof o.PWD<"u"&&(o={...o,PWD:h});let E=(0,FU.default)(t,e,{cwd:h,env:o,stdio:u});return E.stdout.on("data",I=>{A.push(I)}),E.stderr.on("data",I=>{p.push(I)}),await new Promise((I,D)=>{E.on("error",x=>{let C=Je.create(r),T=Ut(C,t,Ct.PATH);D(new zt(1,`Process ${T} failed to spawn`,L=>{L.reportError(1,` ${$u(C,{label:"Thrown Error",value:Wc(Ct.NO_HINT,x.message)})}`)}))}),E.on("close",(x,C)=>{let T=a==="buffer"?Buffer.concat(A):Buffer.concat(A).toString(a),L=a==="buffer"?Buffer.concat(p):Buffer.concat(p).toString(a);x===0||!n?I({code:TU(x,C),stdout:T,stderr:L}):D(new cx({fileName:t,code:x,signal:C,stdout:T,stderr:L}))})})}function TU(t,e){let r=Zst.get(e);return typeof r<"u"?128+r:t??1}function $st(t,e,{configuration:r,report:o}){o.reportError(1,` ${$u(r,t!==null?{label:"Exit Code",value:Wc(Ct.NUMBER,t)}:{label:"Exit Signal",value:Wc(Ct.CODE,e)})}`)}var FU,RU,W1,cx,Qg,Zst,ix=wt(()=>{Pt();FU=et(OT());Y1();Vl();Yl();RU=(o=>(o[o.Never=0]="Never",o[o.ErrorCode=1]="ErrorCode",o[o.Always=2]="Always",o))(RU||{}),W1=class extends zt{constructor({fileName:e,code:r,signal:o}){let a=Je.create(K.cwd()),n=Ut(a,e,Ct.PATH);super(1,`Child ${n} reported an error`,u=>{$st(r,o,{configuration:a,report:u})}),this.code=TU(r,o)}},cx=class extends W1{constructor({fileName:e,code:r,signal:o,stdout:a,stderr:n}){super({fileName:e,code:r,signal:o}),this.stdout=a,this.stderr=n}};Qg=new Set;Zst=new Map([["SIGINT",2],["SIGQUIT",3],["SIGKILL",9],["SIGTERM",15]])});function Cce(t){Ece=t}function K1(){return typeof NU>"u"&&(NU=Ece()),NU}var NU,Ece,LU=wt(()=>{Ece=()=>{throw new Error("Assertion failed: No libzip instance is available, and no factory was configured")}});var wce=_((ux,OU)=>{var eot=Object.assign({},ve("fs")),MU=function(){var t=typeof document<"u"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename<"u"&&(t=t||__filename),function(e){e=e||{};var r=typeof e<"u"?e:{},o,a;r.ready=new Promise(function(ze,it){o=ze,a=it});var n={},u;for(u in r)r.hasOwnProperty(u)&&(n[u]=r[u]);var A=[],p="./this.program",h=function(ze,it){throw it},E=!1,I=!0,D="";function x(ze){return r.locateFile?r.locateFile(ze,D):D+ze}var C,T,L,U;I&&(E?D=ve("path").dirname(D)+"/":D=__dirname+"/",C=function(it,vt){var ar=ia(it);return ar?vt?ar:ar.toString():(L||(L=eot),U||(U=ve("path")),it=U.normalize(it),L.readFileSync(it,vt?null:"utf8"))},T=function(it){var vt=C(it,!0);return vt.buffer||(vt=new Uint8Array(vt)),me(vt.buffer),vt},process.argv.length>1&&(p=process.argv[1].replace(/\\/g,"/")),A=process.argv.slice(2),h=function(ze){process.exit(ze)},r.inspect=function(){return"[Emscripten Module object]"});var z=r.print||console.log.bind(console),te=r.printErr||console.warn.bind(console);for(u in n)n.hasOwnProperty(u)&&(r[u]=n[u]);n=null,r.arguments&&(A=r.arguments),r.thisProgram&&(p=r.thisProgram),r.quit&&(h=r.quit);var le=0,ce=function(ze){le=ze},ue;r.wasmBinary&&(ue=r.wasmBinary);var Ce=r.noExitRuntime||!0;typeof WebAssembly!="object"&&Hi("no native wasm support detected");function he(ze,it,vt){switch(it=it||"i8",it.charAt(it.length-1)==="*"&&(it="i32"),it){case"i1":return Ve[ze>>0];case"i8":return Ve[ze>>0];case"i16":return ap((ze>>1)*2);case"i32":return Rs((ze>>2)*4);case"i64":return Rs((ze>>2)*4);case"float":return gu((ze>>2)*4);case"double":return op((ze>>3)*8);default:Hi("invalid type for getValue: "+it)}return null}var De,Ee=!1,g;function me(ze,it){ze||Hi("Assertion failed: "+it)}function we(ze){var it=r["_"+ze];return me(it,"Cannot call unknown function "+ze+", make sure it is exported"),it}function fe(ze,it,vt,ar,ee){var ye={string:function(Qi){var Pn=0;if(Qi!=null&&Qi!==0){var fa=(Qi.length<<2)+1;Pn=pi(fa),gt(Qi,Pn,fa)}return Pn},array:function(Qi){var Pn=pi(Qi.length);return Ne(Qi,Pn),Pn}};function Le(Qi){return it==="string"?xe(Qi):it==="boolean"?!!Qi:Qi}var ht=we(ze),mt=[],Dt=0;if(ar)for(var er=0;er=vt)&&Se[ar];)++ar;return Z.decode(Se.subarray(ze,ar))}function Re(ze,it,vt,ar){if(!(ar>0))return 0;for(var ee=vt,ye=vt+ar-1,Le=0;Le=55296&&ht<=57343){var mt=ze.charCodeAt(++Le);ht=65536+((ht&1023)<<10)|mt&1023}if(ht<=127){if(vt>=ye)break;it[vt++]=ht}else if(ht<=2047){if(vt+1>=ye)break;it[vt++]=192|ht>>6,it[vt++]=128|ht&63}else if(ht<=65535){if(vt+2>=ye)break;it[vt++]=224|ht>>12,it[vt++]=128|ht>>6&63,it[vt++]=128|ht&63}else{if(vt+3>=ye)break;it[vt++]=240|ht>>18,it[vt++]=128|ht>>12&63,it[vt++]=128|ht>>6&63,it[vt++]=128|ht&63}}return it[vt]=0,vt-ee}function gt(ze,it,vt){return Re(ze,Se,it,vt)}function q(ze){for(var it=0,vt=0;vt=55296&&ar<=57343&&(ar=65536+((ar&1023)<<10)|ze.charCodeAt(++vt)&1023),ar<=127?++it:ar<=2047?it+=2:ar<=65535?it+=3:it+=4}return it}function nt(ze){var it=q(ze)+1,vt=aa(it);return vt&&Re(ze,Ve,vt,it),vt}function Ne(ze,it){Ve.set(ze,it)}function Te(ze,it){return ze%it>0&&(ze+=it-ze%it),ze}var ke,Ve,Se,tt,He,b,w,S,y,R;function J(ze){ke=ze,r.HEAP_DATA_VIEW=R=new DataView(ze),r.HEAP8=Ve=new Int8Array(ze),r.HEAP16=tt=new Int16Array(ze),r.HEAP32=b=new Int32Array(ze),r.HEAPU8=Se=new Uint8Array(ze),r.HEAPU16=He=new Uint16Array(ze),r.HEAPU32=w=new Uint32Array(ze),r.HEAPF32=S=new Float32Array(ze),r.HEAPF64=y=new Float64Array(ze)}var X=r.INITIAL_MEMORY||16777216,$,se=[],be=[],Fe=[],lt=!1;function Et(){if(r.preRun)for(typeof r.preRun=="function"&&(r.preRun=[r.preRun]);r.preRun.length;)St(r.preRun.shift());hs(se)}function qt(){lt=!0,hs(be)}function nr(){if(r.postRun)for(typeof r.postRun=="function"&&(r.postRun=[r.postRun]);r.postRun.length;)Pr(r.postRun.shift());hs(Fe)}function St(ze){se.unshift(ze)}function cn(ze){be.unshift(ze)}function Pr(ze){Fe.unshift(ze)}var yr=0,Rr=null,Xr=null;function $n(ze){yr++,r.monitorRunDependencies&&r.monitorRunDependencies(yr)}function Xs(ze){if(yr--,r.monitorRunDependencies&&r.monitorRunDependencies(yr),yr==0&&(Rr!==null&&(clearInterval(Rr),Rr=null),Xr)){var it=Xr;Xr=null,it()}}r.preloadedImages={},r.preloadedAudios={};function Hi(ze){r.onAbort&&r.onAbort(ze),ze+="",te(ze),Ee=!0,g=1,ze="abort("+ze+"). Build with -s ASSERTIONS=1 for more info.";var it=new WebAssembly.RuntimeError(ze);throw a(it),it}var Qs="data:application/octet-stream;base64,";function Zs(ze){return ze.startsWith(Qs)}var xi="data:application/octet-stream;base64,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QCAAKAJIIgEgASADaiADEAcaAkAgAyAAKAJsIgFNBEAgACABIANrNgJsDAELIABCADcCbAsgACAAKAJoIANrIgE2AmggACAAKAJYIANrNgJYIAEgACgChC5JBEAgACABNgKELgsgAEH8gAEoAgARAwAgAiADaiECCwJAIAAoAgAiASgCBCIERQ0AIAAoAjwhBSAAIAIgBCACIARJGyICBH8gACgCSCAAKAJoaiAFaiEFIAEgBCACazYCBAJAAkACQAJAIAEoAhwiBCgCFEEBaw4CAQACCyAEQaABaiAFIAEoAgAgAkHcgAEoAgARCAAMAgsgASABKAIwIAUgASgCACACQcSAASgCABEEADYCMAwBCyAFIAEoAgAgAhAHGgsgASABKAIAIAJqNgIAIAEgASgCCCACajYCCCAAKAI8BSAFCyACaiICNgI8AkAgACgChC4iASACakEDSQ0AIAAoAmggAWshAQJAIAAoAnRBgQhPBEAgACAAIAAoAkggAWoiAi0AACACLQABIAAoAnwRAAA2AlQMAQsgAUUNACAAIAFBAWsgACgChAERAgAaCyAAKAKELiAAKAI8IgJBAUZrIgRFDQAgACABIAQgACgCgAERBQAgACAAKAKELiAEazYChC4gACgCPCECCyACQYUCSw0AIAAoAgAoAgRFDQAgACgCMCEBDAELCwJAIAAoAkQiAiAAKAJAIgNNDQAgAAJ/IAAoAjwgACgCaGoiASADSwRAIAAoAkggAWpBACACIAFrIgNBggIgA0GCAkkbIgMQGSABIANqDAELIAFBggJqIgEgA00NASAAKAJIIANqQQAgAiADayICIAEgA2siAyACIANJGyIDEBkgACgCQCADags2AkALC50CAQF/AkAgAAJ/IAAoAqAuIgFBwABGBEAgACgCBCAAKAIQaiAAKQOYLjcAACAAQgA3A5guIAAgACgCEEEIajYCEEEADAELIAFBIE4EQCAAKAIEIAAoAhBqIAApA5guPgAAIAAgAEGcLmo1AgA3A5guIAAgACgCEEEEajYCECAAIAAoAqAuQSBrIgE2AqAuCyABQRBOBEAgACgCBCAAKAIQaiAAKQOYLj0AACAAIAAoAhBBAmo2AhAgACAAKQOYLkIQiDcDmC4gACAAKAKgLkEQayIBNgKgLgsgAUEISA0BIAAgACgCECIBQQFqNgIQ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KAJUIgEEfyABQQAgARAiEBkgACgCVAVBAAsQBiAAQQA2AlQLC9wMAgl/AX4jAEFAaiIGJAACQAJAAkACQAJAIAEoAjBBABAjIgVBAkZBACABKAI4QQAQIyIEQQFGGw0AIAVBAUZBACAEQQJGGw0AIAVBAkciAw0BIARBAkcNAQsgASABLwEMQYAQcjsBDEEAIQMMAQsgASABLwEMQf/vA3E7AQxBACEFIANFBEBB9eABIAEoAjAgAEEIahBpIgVFDQILIAJBgAJxBEAgBSEDDAELIARBAkcEQCAFIQMMAQtB9cYBIAEoAjggAEEIahBpIgNFBEAgBRAcDAILIAMgBTYCAAsgASABLwEMQf7/A3EgAS8BUiIFQQBHcjsBDAJAAkACQAJAAn8CQAJAIAEpAyhC/v///w9WDQAgASkDIEL+////D1YNACACQYAEcUUNASABKQNIQv////8PVA0BCyAFQYECa0H//wNxQQNJIQdBAQwBCyAFQYECa0H//wNxIQQgAkGACnFBgApHDQEgBEEDSSEHQQALIQkgBkIcEBciBEUEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyADEBwMBQsgAkGACHEhBQJAAkAgAkGAAnEEQAJAIAUNACABKQMgQv////8PVg0AIAEpAyhCgICAgBBUDQMLIAQgASkDKBAYIAEpAyAhDAwBCwJAAkACQCAFDQAgASkDIEL/////D1YNACABKQMoIgxC/////w9WDQEgASkDSEKAgICAEFQNBAsgASkDKCIMQv////8PVA0BCyAEIAwQGAsgASkDICIMQv////8PWgRAIAQgDBAYCyABKQNIIgxC/////w9UDQELIAQgDBAYCyAELQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAQQCCADEBwMBQtBASEKQQEgBC0AAAR+IAQpAxAFQgALp0H//wNxIAYQRyEFIAQQCCAFIAM2AgAgBw0BDAILIAMhBSAEQQJLDQELIAZCBxAXIgRFBEAgAEEIaiIABEAgAEEANgIEIABBDjYCAAsgBRAcDAMLIARBAhANIARBhxJBAhAsIAQgAS0AUhBwIAQgAS8BEBANIAQtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAsgBBAIDAILQYGyAkEHIAYQRyEDIAQQCCADIAU2AgBBASELIAMhBQsgBkIuEBciA0UEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyAFEBwMAgsgA0GjEkGoEiACQYACcSIHG0EEECwgB0UEQCADIAkEf0EtBSABLwEIC0H//wNxEA0LIAMgCQR/QS0FIAEvAQoLQf//A3EQDSADIAEvAQwQDSADIAsEf0HjAAUgASgCEAtB//8DcRANIAYgASgCFDYCPAJ/IAZBPGoQjQEiCEUEQEEAIQlBIQwBCwJ/IAgoAhQiBEHQAE4EQCAEQQl0DAELIAhB0AA2AhRBgMACCyEEIAgoAgRBBXQgCCgCCEELdGogCCgCAEEBdmohCSAIKAIMIAQgCCgCEEEFdGpqQaDAAWoLIQQgAyAJQf//A3EQDSADIARB//8DcRANIAMCfyALBEBBACABKQMoQhRUDQEaCyABKAIYCxASIAEpAyAhDCADAn8gAwJ/AkAgBwRAIAxC/v///w9YBEAgASkDKEL/////D1QNAgsgA0F/EBJBfwwDC0F/IAxC/v///w9WDQEaCyAMpwsQEiABKQMoIgxC/////w8gDEL/////D1QbpwsQEiADIAEoAjAiBAR/IAQvAQQFQQALQf//A3EQDSADIAEoAjQgAhBsIAVBgAYQbGpB//8DcRANIAdFBEAgAyABKAI4IgQEfyAELwEEBUEAC0H//wNxEA0gAyABLwE8EA0gAyABLwFAEA0gAyABKAJEEBIgAyABKQNIIgxC/////w8gDEL/////D1QbpxASCyADLQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAMQCCAFEBwMAgsgACAGIAMtAAAEfiADKQMQBUIACxAbIQQgAxAIIARBf0wNACABKAIwIgMEQCAAIAMQYUF/TA0BCyAFBEAgACAFQYAGEGtBf0wNAQsgBRAcIAEoAjQiBQRAIAAgBSACEGtBAEgNAgsgBw0CIAEoAjgiAUUNAiAAIAEQYUEATg0CDAELIAUQHAtBfyEKCyAGQUBrJAAgCgtNAQJ/IAEtAAAhAgJAIAAtAAAiA0UNACACIANHDQADQCABLQABIQIgAC0AASIDRQ0BIAFBAWohASAAQQFqIQAgAiADRg0ACwsgAyACawvcAwICfgF/IAOtIQQgACkDmC4hBQJAIAACfyAAAn4gACgCoC4iBkEDaiIDQT9NBEAgBCAGrYYgBYQMAQsgBkHAAEYEQCAAKAIEIAAoAhBqIAU3AAAgACgCEEEIagwCCyAAKAIEIAAoAhBqIAQgBq2GIAWENwAAIAAgACgCEEEIajYCECAGQT1rIQMgBEHAACAGa62ICyIENwOYLiAAIAM2AqAuIANBOU4EQCAAKAIEIAAoAhBqIAQ3AAAgACAAKAIQQQhqNgIQDAILIANBGU4EQCAAKAIEIAAoAhBqIAQ+AAAgACAAKAIQQQRqNgIQIAAgACkDmC5CIIgiBDcDmC4gACAAKAKgLkEgayIDNgKgLgsgA0EJTgR/IAAoAgQgACgCEGogBD0AACAAIAAoAhBBAmo2AhAgACkDmC5CEIghBCAAKAKgLkEQawUgAwtBAUgNASAAKAIQCyIDQQFqNgIQIAAoAgQgA2ogBDwAAAsgAEEANgKgLiAAQgA3A5guIAAoAgQgACgCEGogAjsAACAAIAAoAhBBAmoiAzYCECAAKAIEIANqIAJBf3M7AAAgACAAKAIQQQJqIgM2AhAgAgRAIAAoAgQgA2ogASACEAcaIAAgACgCECACajYCEAsLrAQCAX8BfgJAIAANACABUA0AIAMEQCADQQA2AgQgA0ESNgIAC0EADwsCQAJAIAAgASACIAMQiQEiBEUNAEEYEAkiAkUEQCADBEAgA0EANgIEIANBDjYCAAsCQCAEKAIoIgBFBEAgBCkDGCEBDAELIABBADYCKCAEKAIoQgA3AyAgBCAEKQMYIgUgBCkDICIBIAEgBVQbIgE3AxgLIAQpAwggAVYEQANAIAQoAgAgAadBBHRqKAIAEAYgAUIBfCIBIAQpAwhUDQALCyAEKAIAEAYgBCgCBBAGIAQQBgwBCyACQQA2AhQgAiAENgIQIAJBABABNgIMIAJBADYCCCACQgA3AgACf0E4EAkiAEUEQCADBEAgA0EANgIEIANBDjYCAAtBAAwBCyAAQQA2AgggAEIANwMAIABCADcDICAAQoCAgIAQNwIsIABBADoAKCAAQQA2AhQgAEIANwIMIABBADsBNCAAIAI2AgggAEEkNgIEIABCPyACQQBCAEEOQSQRDAAiASABQgBTGzcDGCAACyIADQEgAigCECIDBEACQCADKAIoIgBFBEAgAykDGCEBDAELIABBADYCKCADKAIoQgA3AyAgAyADKQMYIgUgAykDICIBIAEgBVQbIgE3AxgLIAMpAwggAVYEQANAIAMoAgAgAadBBHRqKAIAEAYgAUIBfCIBIAMpAwhUDQALCyADKAIAEAYgAygCBBAGIAMQBgsgAhAGC0EAIQALIAALiwwBBn8gACABaiEFAkACQCAAKAIEIgJBAXENACACQQNxRQ0BIAAoAgAiAiABaiEBAkAgACACayIAQciEASgCAEcEQCACQf8BTQRAIAAoAggiBCACQQN2IgJBA3RB3IQBakYaIAAoAgwiAyAERw0CQbSEAUG0hAEoAgBBfiACd3E2AgAMAwsgACgCGCEGAkAgACAAKAIMIgNHBEAgACgCCCICQcSEASgCAEkaIAIgAzYCDCADIAI2AggMAQsCQCAAQRRqIgIoAgAiBA0AIABBEGoiAigCACIEDQBBACEDDAELA0AgAiEHIAQiA0EUaiICKAIAIgQNACADQRBqIQIgAygCECIEDQALIAdBADYCAAsgBkUNAgJAIAAgACgCHCIEQQJ0QeSGAWoiAigCAEYEQCACIAM2AgAgAw0BQbiEAUG4hAEoAgBBfiAEd3E2AgAMBAsgBkEQQRQgBigCECAARhtqIAM2AgAgA0UNAwsgAyAGNgIYIAAoAhAiAgRAIAMgAjYCECACIAM2AhgLIAAoAhQiAkUNAiADIAI2AhQgAiADNgIYDAILIAUoAgQiAkEDcUEDRw0BQbyEASABNgIAIAUgAkF+cTYCBCAAIAFBAXI2AgQgBSABNgIADwsgBCADNgIMIAMgBDYCCAsCQCAFKAIEIgJBAnFFBEAgBUHMhAEoAgBGBEBBzIQBIAA2AgBBwIQBQcCEASgCACABaiIBNgIAIAAgAUEBcjYCBCAAQciEASgCAEcNA0G8hAFBADYCAEHIhAFBADYCAA8LIAVByIQBKAIARgRAQciEASAANgIAQbyEAUG8hAEoAgAgAWoiATYCACAAIAFBAXI2AgQgACABaiABNgIADwsgAkF4cSABaiEBAkAgAkH/AU0EQCAFKAIIIgQgAkEDdiICQQN0QdyEAWpGGiAEIAUoAgwiA0YEQEG0hAFBtIQBKAIAQX4gAndxNgIADAILIAQgAzYCDCADIAQ2AggMAQsgBSgCGCEGAkAgBSAFKAIMIgNHBEAgBSgCCCICQcSEASgCAEkaIAIgAzYCDCADIAI2AggMAQsCQCAFQRRqIgQoAgAiAg0AIAVBEGoiBCgCACICDQBBACEDDAELA0AgBCEHIAIiA0EUaiIEKAIAIgINACADQRBqIQQgAygCECICDQALIAdBADYCAAsgBkUNAAJAIAUgBSgCHCIEQQJ0QeSGAWoiAigCAEYEQCACIAM2AgAgAw0BQbiEAUG4hAEoAgBBfiAEd3E2AgAMAgsgBkEQQRQgBigCECAFRhtqIAM2AgAgA0UNAQsgAyAGNgIYIAUoAhAiAgRAIAMgAjYCECACIAM2AhgLIAUoAhQiAkUNACADIAI2AhQgAiADNgIYCyAAIAFBAXI2AgQgACABaiABNgIAIABByIQBKAIARw0BQbyEASABNgIADwsgBSACQX5xNgIEIAAgAUEBcjYCBCAAIAFqIAE2AgALIAFB/wFNBEAgAUEDdiICQQN0QdyEAWohAQJ/QbSEASgCACIDQQEgAnQiAnFFBEBBtIQBIAIgA3I2AgAgAQwBCyABKAIICyECIAEgADYCCCACIAA2AgwgACABNgIMIAAgAjYCCA8LQR8hAiAAQgA3AhAgAUH///8HTQRAIAFBCHYiAiACQYD+P2pBEHZBCHEiBHQiAiACQYDgH2pBEHZBBHEiA3QiAiACQYCAD2pBEHZBAnEiAnRBD3YgAyAEciACcmsiAkEBdCABIAJBFWp2QQFxckEcaiECCyAAIAI2AhwgAkECdEHkhgFqIQcCQAJAQbiEASgCACIEQQEgAnQiA3FFBEBBuIQBIAMgBHI2AgAgByAANgIAIAAgBzYCGAwBCyABQQBBGSACQQF2ayACQR9GG3QhAiAHKAIAIQMDQCADIgQoAgRBeHEgAUYNAiACQR12IQMgAkEBdCECIAQgA0EEcWoiB0EQaigCACIDDQALIAcgADYCECAAIAQ2AhgLIAAgADYCDCAAIAA2AggPCyAEKAIIIgEgADYCDCAEIAA2AgggAEEANgIYIAAgBDYCDCAAIAE2AggLC1gCAX8BfgJAAn9BACAARQ0AGiAArUIChiICpyIBIABBBHJBgIAESQ0AGkF/IAEgAkIgiKcbCyIBEAkiAEUNACAAQQRrLQAAQQNxRQ0AIABBACABEBkLIAALQwEDfwJAIAJFDQADQCAALQAAIgQgAS0AACIFRgRAIAFBAWohASAAQQFqIQAgAkEBayICDQEMAgsLIAQgBWshAwsgAwsUACAAEEAgACgCABAgIAAoAgQQIAutBAIBfgV/IwBBEGsiBCQAIAAgAWshBgJAAkAgAUEBRgRAIAAgBi0AACACEBkMAQsgAUEJTwRAIAAgBikAADcAACAAIAJBAWtBB3FBAWoiBWohACACIAVrIgFFDQIgBSAGaiECA0AgACACKQAANwAAIAJBCGohAiAAQQhqIQAgAUEIayIBDQALDAILAkACQAJAAkAgAUEEaw4FAAICAgECCyAEIAYoAAAiATYCBCAEIAE2AgAMAgsgBCAGKQAANwMADAELQQghByAEQQhqIQgDQCAIIAYgByABIAEgB0sbIgUQByAFaiEIIAcgBWsiBw0ACyAEIAQpAwg3AwALAkAgBQ0AIAJBEEkNACAEKQMAIQMgAkEQayIGQQR2QQFqQQdxIgEEQANAIAAgAzcACCAAIAM3AAAgAkEQayECIABBEGohACABQQFrIgENAAsLIAZB8ABJDQADQCAAIAM3AHggACADNwBwIAAgAzcAaCAAIAM3AGAgACADNwBYIAAgAzcAUCAAIAM3AEggACADNwBAIAAgAzcAOCAAIAM3ADAgACADNwAoIAAgAzcAICAAIAM3ABggACADNwAQIAAgAzcACCAAIAM3AAAgAEGAAWohACACQYABayICQQ9LDQALCyACQQhPBEBBCCAFayEBA0AgACAEKQMANwAAIAAgAWohACACIAFrIgJBB0sNAAsLIAJFDQEgACAEIAIQBxoLIAAgAmohAAsgBEEQaiQAIAALXwECfyAAKAIIIgEEQCABEAsgAEEANgIICwJAIAAoAgQiAUUNACABKAIAIgJBAXFFDQAgASgCEEF+Rw0AIAEgAkF+cSICNgIAIAINACABECAgAEEANgIECyAAQQA6AAwL1wICBH8BfgJAAkAgACgCQCABp0EEdGooAgAiA0UEQCACBEAgAkEANgIEIAJBFDYCAAsMAQsgACgCACADKQNIIgdBABAUIQMgACgCACEAIANBf0wEQCACBEAgAiAAKAIMNgIAIAIgACgCEDYCBAsMAQtCACEBIwBBEGsiBiQAQX8hAwJAIABCGkEBEBRBf0wEQCACBEAgAiAAKAIMNgIAIAIgACgCEDYCBAsMAQsgAEIEIAZBCmogAhAtIgRFDQBBHiEAQQEhBQNAIAQQDCAAaiEAIAVBAkcEQCAFQQFqIQUMAQsLIAQtAAAEfyAEKQMQIAQpAwhRBUEAC0UEQCACBEAgAkEANgIEIAJBFDYCAAsgBBAIDAELIAQQCCAAIQMLIAZBEGokACADIgBBAEgNASAHIACtfCIBQn9VDQEgAgRAIAJBFjYCBCACQQQ2AgALC0IAIQELIAELYAIBfgF/AkAgAEUNACAAQQhqEF8iAEUNACABIAEoAjBBAWo2AjAgACADNgIIIAAgAjYCBCAAIAE2AgAgAEI/IAEgA0EAQgBBDiACEQoAIgQgBEIAUxs3AxggACEFCyAFCyIAIAAoAiRBAWtBAU0EQCAAQQBCAEEKEA4aIABBADYCJAsLbgACQAJAAkAgA0IQVA0AIAJFDQECfgJAAkACQCACKAIIDgMCAAEECyACKQMAIAB8DAILIAIpAwAgAXwMAQsgAikDAAsiA0IAUw0AIAEgA1oNAgsgBARAIARBADYCBCAEQRI2AgALC0J/IQMLIAMLggICAX8CfgJAQQEgAiADGwRAIAIgA2oQCSIFRQRAIAQEQCAEQQA2AgQgBEEONgIAC0EADwsgAq0hBgJAAkAgAARAIAAgBhATIgBFBEAgBARAIARBADYCBCAEQQ42AgALDAULIAUgACACEAcaIAMNAQwCCyABIAUgBhARIgdCf1cEQCAEBEAgBCABKAIMNgIAIAQgASgCEDYCBAsMBAsgBiAHVQRAIAQEQCAEQQA2AgQgBEERNgIACwwECyADRQ0BCyACIAVqIgBBADoAACACQQFIDQAgBSECA0AgAi0AAEUEQCACQSA6AAALIAJBAWoiAiAASQ0ACwsLIAUPCyAFEAZBAAuBAQEBfwJAIAAEQCADQYAGcSEFQQAhAwNAAkAgAC8BCCACRw0AIAUgACgCBHFFDQAgA0EATg0DIANBAWohAwsgACgCACIADQALCyAEBEAgBEEANgIEIARBCTYCAAtBAA8LIAEEQCABIAAvAQo7AQALIAAvAQpFBEBBwBQPCyAAKAIMC1cBAX9BEBAJIgNFBEBBAA8LIAMgATsBCiADIAA7AQggA0GABjYCBCADQQA2AgACQCABBEAgAyACIAEQYyIANgIMIAANASADEAZBAA8LIANBADYCDAsgAwvuBQIEfwV+IwBB4ABrIgQkACAEQQhqIgNCADcDICADQQA2AhggA0L/////DzcDECADQQA7AQwgA0G/hig2AgggA0EBOgAGIANBADsBBCADQQA2AgAgA0IANwNIIANBgIDYjXg2AkQgA0IANwMoIANCADcDMCADQgA3AzggA0FAa0EAOwEAIANCADcDUCABKQMIUCIDRQRAIAEoAgAoAgApA0ghBwsCfgJAIAMEQCAHIQkMAQsgByEJA0AgCqdBBHQiBSABKAIAaigCACIDKQNIIgggCSAIIAlUGyIJIAEpAyBWBEAgAgRAIAJBADYCBCACQRM2AgALQn8MAwsgAygCMCIGBH8gBi8BBAVBAAtB//8Dca0gCCADKQMgfHxCHnwiCCAHIAcgCFQbIgcgASkDIFYEQCACBEAgAkEANgIEIAJBEzYCAAtCfwwDCyAAKAIAIAEoAgAgBWooAgApA0hBABAUIQYgACgCACEDIAZBf0wEQCACBEAgAiADKAIMNgIAIAIgAygCEDYCBAtCfwwDCyAEQQhqIANBAEEBIAIQaEJ/UQRAIARBCGoQNkJ/DAMLAkACQCABKAIAIAVqKAIAIgMvAQogBC8BEkkNACADKAIQIAQoAhhHDQAgAygCFCAEKAIcRw0AIAMoAjAgBCgCOBBiRQ0AAkAgBCgCICIGIAMoAhhHBEAgBCkDKCEIDAELIAMpAyAiCyAEKQMoIghSDQAgCyEIIAMpAyggBCkDMFENAgsgBC0AFEEIcUUNACAGDQAgCEIAUg0AIAQpAzBQDQELIAIEQCACQQA2AgQgAkEVNgIACyAEQQhqEDZCfwwDCyABKAIAIAVqKAIAKAI0IAQoAjwQbyEDIAEoAgAgBWooAgAiBUEBOgAEIAUgAzYCNCAEQQA2AjwgBEEIahA2IApCAXwiCiABKQMIVA0ACwsgByAJfSIHQv///////////wAgB0L///////////8AVBsLIQcgBEHgAGokACAHC8YBAQJ/QdgAEAkiAUUEQCAABEAgAEEANgIEIABBDjYCAAtBAA8LIAECf0EYEAkiAkUEQCAABEAgAEEANgIEIABBDjYCAAtBAAwBCyACQQA2AhAgAkIANwMIIAJBADYCACACCyIANgJQIABFBEAgARAGQQAPCyABQgA3AwAgAUEANgIQIAFCADcCCCABQgA3AhQgAUEANgJUIAFCADcCHCABQgA3ACEgAUIANwMwIAFCADcDOCABQUBrQgA3AwAgAUIANwNIIAELgBMCD38CfiMAQdAAayIFJAAgBSABNgJMIAVBN2ohEyAFQThqIRBBACEBA0ACQCAOQQBIDQBB/////wcgDmsgAUgEQEGEhAFBPTYCAEF/IQ4MAQsgASAOaiEOCyAFKAJMIgchAQJAAkACQAJAAkACQAJAAkAgBQJ/AkAgBy0AACIGBEADQAJAAkAgBkH/AXEiBkUEQCABIQYMAQsgBkElRw0BIAEhBgNAIAEtAAFBJUcNASAFIAFBAmoiCDYCTCAGQQFqIQYgAS0AAiEMIAghASAMQSVGDQALCyAGIAdrIQEgAARAIAAgByABEC4LIAENDSAFKAJMIQEgBSgCTCwAAUEwa0EKTw0DIAEtAAJBJEcNAyABLAABQTBrIQ9BASERIAFBA2oMBAsgBSABQQFqIgg2AkwgAS0AASEGIAghAQwACwALIA4hDSAADQggEUUNAkEBIQEDQCAEIAFBAnRqKAIAIgAEQCADIAFBA3RqIAAgAhB4QQEhDSABQQFqIgFBCkcNAQwKCwtBASENIAFBCk8NCANAIAQgAUECdGooAgANCCABQQFqIgFBCkcNAAsMCAtBfyEPIAFBAWoLIgE2AkxBACEIAkAgASwAACIKQSBrIgZBH0sNAEEBIAZ0IgZBidEEcUUNAANAAkAgBSABQQFqIgg2AkwgASwAASIKQSBrIgFBIE8NAEEBIAF0IgFBidEEcUUNACABIAZyIQYgCCEBDAELCyAIIQEgBiEICwJAIApBKkYEQCAFAn8CQCABLAABQTBrQQpPDQAgBSgCTCIBLQACQSRHDQAgASwAAUECdCAEakHAAWtBCjYCACABLAABQQN0IANqQYADaygCACELQQEhESABQQNqDAELIBENCEEAIRFBACELIAAEQCACIAIoAgAiAUEEajYCACABKAIAIQsLIAUoAkxBAWoLIgE2AkwgC0F/Sg0BQQAgC2shCyAIQYDAAHIhCAwBCyAFQcwAahB3IgtBAEgNBiAFKAJMIQELQX8hCQJAIAEtAABBLkcNACABLQABQSpGBEACQCABLAACQTBrQQpPDQAgBSgCTCIBLQADQSRHDQAgASwAAkECdCAEakHAAWtBCjYCACABLAACQQN0IANqQYADaygCACEJIAUgAUEEaiIBNgJMDAILIBENByAABH8gAiACKAIAIgFBBGo2AgAgASgCAAVBAAshCSAFIAUoAkxBAmoiATYCTAwBCyAFIAFBAWo2AkwgBUHMAGoQdyEJIAUoAkwhAQtBACEGA0AgBiESQX8hDSABLAAAQcEAa0E5Sw0HIAUgAUEBaiIKNgJMIAEsAAAhBiAKIQEgBiASQTpsakGf7ABqLQAAIgZBAWtBCEkNAAsgBkETRg0CIAZFDQYgD0EATgRAIAQgD0ECdGogBjYCACAFIAMgD0EDdGopAwA3A0AMBAsgAA0BC0EAIQ0MBQsgBUFAayAGIAIQeCAFKAJMIQoMAgsgD0F/Sg0DC0EAIQEgAEUNBAsgCEH//3txIgwgCCAIQYDAAHEbIQZBACENQaQIIQ8gECEIAkACQAJAAn8CQAJAAkACQAJ/AkACQAJAAkACQAJAAkAgCkEBaywAACIBQV9xIAEgAUEPcUEDRhsgASASGyIBQdgAaw4hBBISEhISEhISDhIPBg4ODhIGEhISEgIFAxISCRIBEhIEAAsCQCABQcEAaw4HDhILEg4ODgALIAFB0wBGDQkMEQsgBSkDQCEUQaQIDAULQQAhAQJAAkACQAJAAkACQAJAIBJB/wFxDggAAQIDBBcFBhcLIAUoAkAgDjYCAAwWCyAFKAJAIA42AgAMFQsgBSgCQCAOrDcDAAwUCyAFKAJAIA47AQAMEwsgBSgCQCAOOgAADBILIAUoAkAgDjYCAAwRCyAFKAJAIA6sNwMADBALIAlBCCAJQQhLGyEJIAZBCHIhBkH4ACEBCyAQIQcgAUEgcSEMIAUpA0AiFFBFBEADQCAHQQFrIgcgFKdBD3FBsPAAai0AACAMcjoAACAUQg9WIQogFEIEiCEUIAoNAAsLIAUpA0BQDQMgBkEIcUUNAyABQQR2QaQIaiEPQQIhDQwDCyAQIQEgBSkDQCIUUEUEQANAIAFBAWsiASAUp0EHcUEwcjoAACAUQgdWIQcgFEIDiCEUIAcNAAsLIAEhByAGQQhxRQ0CIAkgECAHayIBQQFqIAEgCUgbIQkMAgsgBSkDQCIUQn9XBEAgBUIAIBR9IhQ3A0BBASENQaQIDAELIAZBgBBxBEBBASENQaUIDAELQaYIQaQIIAZBAXEiDRsLIQ8gECEBAkAgFEKAgICAEFQEQCAUIRUMAQsDQCABQQFrIgEgFCAUQgqAIhVCCn59p0EwcjoAACAUQv////+fAVYhByAVIRQgBw0ACwsgFaciBwRAA0AgAUEBayIBIAcgB0EKbiIMQQpsa0EwcjoAACAHQQlLIQogDCEHIAoNAAsLIAEhBwsgBkH//3txIAYgCUF/ShshBgJAIAUpA0AiFEIAUg0AIAkNAEEAIQkgECEHDAoLIAkgFFAgECAHa2oiASABIAlIGyEJDAkLIAUoAkAiAUGKEiABGyIHQQAgCRB6IgEgByAJaiABGyEIIAwhBiABIAdrIAkgARshCQwICyAJBEAgBSgCQAwCC0EAIQEgAEEgIAtBACAGECcMAgsgBUEANgIMIAUgBSkDQD4CCCAFIAVBCGo2AkBBfyEJIAVBCGoLIQhBACEBAkADQCAIKAIAIgdFDQECQCAFQQRqIAcQeSIHQQBIIgwNACAHIAkgAWtLDQAgCEEEaiEIIAkgASAHaiIBSw0BDAILC0F/IQ0gDA0FCyAAQSAgCyABIAYQJyABRQRAQQAhAQwBC0EAIQggBSgCQCEKA0AgCigCACIHRQ0BIAVBBGogBxB5IgcgCGoiCCABSg0BIAAgBUEEaiAHEC4gCkEEaiEKIAEgCEsNAAsLIABBICALIAEgBkGAwABzECcgCyABIAEgC0gbIQEMBQsgACAFKwNAIAsgCSAGIAFBABEdACEBDAQLIAUgBSkDQDwAN0EBIQkgEyEHIAwhBgwCC0F/IQ0LIAVB0ABqJAAgDQ8LIABBICANIAggB2siDCAJIAkgDEgbIgpqIgggCyAIIAtKGyIBIAggBhAnIAAgDyANEC4gAEEwIAEgCCAGQYCABHMQJyAAQTAgCiAMQQAQJyAAIAcgDBAuIABBICABIAggBkGAwABzECcMAAsAC54DAgR/AX4gAARAIAAoAgAiAQRAIAEQGhogACgCABALCyAAKAIcEAYgACgCIBAQIAAoAiQQECAAKAJQIgMEQCADKAIQIgIEQCADKAIAIgEEfwNAIAIgBEECdGooAgAiAgRAA0AgAigCGCEBIAIQBiABIgINAAsgAygCACEBCyABIARBAWoiBEsEQCADKAIQIQIMAQsLIAMoAhAFIAILEAYLIAMQBgsgACgCQCIBBEAgACkDMFAEfyABBSABED5CAiEFAkAgACkDMEICVA0AQQEhAgNAIAAoAkAgAkEEdGoQPiAFIAApAzBaDQEgBachAiAFQgF8IQUMAAsACyAAKAJACxAGCwJAIAAoAkRFDQBBACECQgEhBQNAIAAoAkwgAkECdGooAgAiAUEBOgAoIAFBDGoiASgCAEUEQCABBEAgAUEANgIEIAFBCDYCAAsLIAUgADUCRFoNASAFpyECIAVCAXwhBQwACwALIAAoAkwQBiAAKAJUIgIEQCACKAIIIgEEQCACKAIMIAERAwALIAIQBgsgAEEIahAxIAAQBgsL6gMCAX4EfwJAIAAEfiABRQRAIAMEQCADQQA2AgQgA0ESNgIAC0J/DwsgAkGDIHEEQAJAIAApAzBQDQBBPEE9IAJBAXEbIQcgAkECcUUEQANAIAAgBCACIAMQUyIFBEAgASAFIAcRAgBFDQYLIARCAXwiBCAAKQMwVA0ADAILAAsDQCAAIAQgAiADEFMiBQRAIAECfyAFECJBAWohBgNAQQAgBkUNARogBSAGQQFrIgZqIggtAABBL0cNAAsgCAsiBkEBaiAFIAYbIAcRAgBFDQULIARCAXwiBCAAKQMwVA0ACwsgAwRAIANBADYCBCADQQk2AgALQn8PC0ESIQYCQAJAIAAoAlAiBUUNACABRQ0AQQkhBiAFKQMIUA0AIAUoAhAgAS0AACIHBH9CpesKIQQgASEAA0AgBCAHrUL/AYN8IQQgAC0AASIHBEAgAEEBaiEAIARC/////w+DQiF+IQQMAQsLIASnBUGFKgsgBSgCAHBBAnRqKAIAIgBFDQADQCABIAAoAgAQOEUEQCACQQhxBEAgACkDCCIEQn9RDQMMBAsgACkDECIEQn9RDQIMAwsgACgCGCIADQALCyADBEAgA0EANgIEIAMgBjYCAAtCfyEECyAEBUJ/Cw8LIAMEQCADQgA3AgALIAQL3AQCB38BfgJAAkAgAEUNACABRQ0AIAJCf1UNAQsgBARAIARBADYCBCAEQRI2AgALQQAPCwJAIAAoAgAiB0UEQEGAAiEHQYACEDwiBkUNASAAKAIQEAYgAEGAAjYCACAAIAY2AhALAkACQCAAKAIQIAEtAAAiBQR/QqXrCiEMIAEhBgNAIAwgBa1C/wGDfCEMIAYtAAEiBQRAIAZBAWohBiAMQv////8Pg0IhfiEMDAELCyAMpwVBhSoLIgYgB3BBAnRqIggoAgAiBQRAA0ACQCAFKAIcIAZHDQAgASAFKAIAEDgNAAJAIANBCHEEQCAFKQMIQn9SDQELIAUpAxBCf1ENBAsgBARAIARBADYCBCAEQQo2AgALQQAPCyAFKAIYIgUNAAsLQSAQCSIFRQ0CIAUgATYCACAFIAgoAgA2AhggCCAFNgIAIAVCfzcDCCAFIAY2AhwgACAAKQMIQgF8Igw3AwggDLogB7hEAAAAAAAA6D+iZEUNACAHQQBIDQAgByAHQQF0IghGDQAgCBA8IgpFDQECQCAMQgAgBxtQBEAgACgCECEJDAELIAAoAhAhCUEAIQQDQCAJIARBAnRqKAIAIgYEQANAIAYoAhghASAGIAogBigCHCAIcEECdGoiCygCADYCGCALIAY2AgAgASIGDQALCyAEQQFqIgQgB0cNAAsLIAkQBiAAIAg2AgAgACAKNgIQCyADQQhxBEAgBSACNwMICyAFIAI3AxBBAQ8LIAQEQCAEQQA2AgQgBEEONgIAC0EADwsgBARAIARBADYCBCAEQQ42AgALQQAL3Q8BF38jAEFAaiIHQgA3AzAgB0IANwM4IAdCADcDICAHQgA3AygCQAJAAkACQAJAIAIEQCACQQNxIQggAkEBa0EDTwRAIAJBfHEhBgNAIAdBIGogASAJQQF0IgxqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBAnJqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBBHJqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBBnJqLwEAQQF0aiIKIAovAQBBAWo7AQAgCUEEaiEJIAZBBGsiBg0ACwsgCARAA0AgB0EgaiABIAlBAXRqLwEAQQF0aiIGIAYvAQBBAWo7AQAgCUEBaiEJIAhBAWsiCA0ACwsgBCgCACEJQQ8hCyAHLwE+IhENAgwBCyAEKAIAIQkLQQ4hC0EAIREgBy8BPA0AQQ0hCyAHLwE6DQBBDCELIAcvATgNAEELIQsgBy8BNg0AQQohCyAHLwE0DQBBCSELIAcvATINAEEIIQsgBy8BMA0AQQchCyAHLwEuDQBBBiELIAcvASwNAEEFIQsgBy8BKg0AQQQhCyAHLwEoDQBBAyELIAcvASYNAEECIQsgBy8BJA0AIAcvASJFBEAgAyADKAIAIgBBBGo2AgAgAEHAAjYBACADIAMoAgAiAEEEajYCACAAQcACNgEAQQEhDQwDCyAJQQBHIRtBASELQQEhCQwBCyALIAkgCSALSxshG0EBIQ5BASEJA0AgB0EgaiAJQQF0ai8BAA0BIAlBAWoiCSALRw0ACyALIQkLQX8hCCAHLwEiIg9BAksNAUEEIAcvASQiECAPQQF0amsiBkEASA0BIAZBAXQgBy8BJiISayIGQQBIDQEgBkEBdCAHLwEoIhNrIgZBAEgNASAGQQF0IAcvASoiFGsiBkEASA0BIAZBAXQgBy8BLCIVayIGQQBIDQEgBkEBdCAHLwEuIhZrIgZBAEgNASAGQQF0IAcvATAiF2siBkEASA0BIAZBAXQgBy8BMiIZayIGQQBIDQEgBkEBdCAHLwE0IhxrIgZBAEgNASAGQQF0IAcvATYiDWsiBkEASA0BIAZBAXQgBy8BOCIYayIGQQBIDQEgBkEBdCAHLwE6IgxrIgZBAEgNASAGQQF0IAcvATwiCmsiBkEASA0BIAZBAXQgEWsiBkEASA0BIAZBACAARSAOchsNASAJIBtLIRpBACEIIAdBADsBAiAHIA87AQQgByAPIBBqIgY7AQYgByAGIBJqIgY7AQggByAGIBNqIgY7AQogByAGIBRqIgY7AQwgByAGIBVqIgY7AQ4gByAGIBZqIgY7ARAgByAGIBdqIgY7ARIgByAGIBlqIgY7ARQgByAGIBxqIgY7ARYgByAGIA1qIgY7ARggByAGIBhqIgY7ARogByAGIAxqIgY7ARwgByAGIApqOwEeAkAgAkUNACACQQFHBEAgAkF+cSEGA0AgASAIQQF0ai8BACIKBEAgByAKQQF0aiIKIAovAQAiCkEBajsBACAFIApBAXRqIAg7AQALIAEgCEEBciIMQQF0ai8BACIKBEAgByAKQQF0aiIKIAovAQAiCkEBajsBACAFIApBAXRqIAw7AQALIAhBAmohCCAGQQJrIgYNAAsLIAJBAXFFDQAgASAIQQF0ai8BACICRQ0AIAcgAkEBdGoiAiACLwEAIgJBAWo7AQAgBSACQQF0aiAIOwEACyAJIBsgGhshDUEUIRBBACEWIAUiCiEYQQAhEgJAAkACQCAADgICAAELQQEhCCANQQpLDQNBgQIhEEHw2QAhGEGw2QAhCkEBIRIMAQsgAEECRiEWQQAhEEHw2gAhGEGw2gAhCiAAQQJHBEAMAQtBASEIIA1BCUsNAgtBASANdCITQQFrIRwgAygCACEUQQAhFSANIQZBACEPQQAhDkF/IQIDQEEBIAZ0IRoCQANAIAkgD2shFwJAIAUgFUEBdGovAQAiCCAQTwRAIAogCCAQa0EBdCIAai8BACERIAAgGGotAAAhAAwBC0EAQeAAIAhBAWogEEkiBhshACAIQQAgBhshEQsgDiAPdiEMQX8gF3QhBiAaIQgDQCAUIAYgCGoiCCAMakECdGoiGSAROwECIBkgFzoAASAZIAA6AAAgCA0AC0EBIAlBAWt0IQYDQCAGIgBBAXYhBiAAIA5xDQALIAdBIGogCUEBdGoiBiAGLwEAQQFrIgY7AQAgAEEBayAOcSAAakEAIAAbIQ4gFUEBaiEVIAZB//8DcUUEQCAJIAtGDQIgASAFIBVBAXRqLwEAQQF0ai8BACEJCyAJIA1NDQAgDiAccSIAIAJGDQALQQEgCSAPIA0gDxsiD2siBnQhAiAJIAtJBEAgCyAPayEMIAkhCAJAA0AgAiAHQSBqIAhBAXRqLwEAayICQQFIDQEgAkEBdCECIAZBAWoiBiAPaiIIIAtJDQALIAwhBgtBASAGdCECC0EBIQggEiACIBNqIhNBtApLcQ0DIBYgE0HQBEtxDQMgAygCACICIABBAnRqIgggDToAASAIIAY6AAAgCCAUIBpBAnRqIhQgAmtBAnY7AQIgACECDAELCyAOBEAgFCAOQQJ0aiIAQQA7AQIgACAXOgABIABBwAA6AAALIAMgAygCACATQQJ0ajYCAAsgBCANNgIAQQAhCAsgCAusAQICfgF/IAFBAmqtIQIgACkDmC4hAwJAIAAoAqAuIgFBA2oiBEE/TQRAIAIgAa2GIAOEIQIMAQsgAUHAAEYEQCAAKAIEIAAoAhBqIAM3AAAgACAAKAIQQQhqNgIQQQMhBAwBCyAAKAIEIAAoAhBqIAIgAa2GIAOENwAAIAAgACgCEEEIajYCECABQT1rIQQgAkHAACABa62IIQILIAAgAjcDmC4gACAENgKgLguXAwICfgN/QYDJADMBACECIAApA5guIQMCQCAAKAKgLiIFQYLJAC8BACIGaiIEQT9NBEAgAiAFrYYgA4QhAgwBCyAFQcAARgRAIAAoAgQgACgCEGogAzcAACAAIAAoAhBBCGo2AhAgBiEEDAELIAAoAgQgACgCEGogAiAFrYYgA4Q3AAAgACAAKAIQQQhqNgIQIARBQGohBCACQcAAIAVrrYghAgsgACACNwOYLiAAIAQ2AqAuIAEEQAJAIARBOU4EQCAAKAIEIAAoAhBqIAI3AAAgACAAKAIQQQhqNgIQDAELIARBGU4EQCAAKAIEIAAoAhBqIAI+AAAgACAAKAIQQQRqNgIQIAAgACkDmC5CIIgiAjcDmC4gACAAKAKgLkEgayIENgKgLgsgBEEJTgR/IAAoAgQgACgCEGogAj0AACAAIAAoAhBBAmo2AhAgACkDmC5CEIghAiAAKAKgLkEQawUgBAtBAUgNACAAIAAoAhAiAUEBajYCECABIAAoAgRqIAI8AAALIABBADYCoC4gAEIANwOYLgsL8hQBEn8gASgCCCICKAIAIQUgAigCDCEHIAEoAgAhCCAAQoCAgIDQxwA3A6ApQQAhAgJAAkAgB0EASgRAQX8hDANAAkAgCCACQQJ0aiIDLwEABEAgACAAKAKgKUEBaiIDNgKgKSAAIANBAnRqQawXaiACNgIAIAAgAmpBqClqQQA6AAAgAiEMDAELIANBADsBAgsgAkEBaiICIAdHDQALIABB/C1qIQ8gAEH4LWohESAAKAKgKSIEQQFKDQIMAQsgAEH8LWohDyAAQfgtaiERQX8hDAsDQCAAIARBAWoiAjYCoCkgACACQQJ0akGsF2ogDEEBaiIDQQAgDEECSCIGGyICNgIAIAggAkECdCIEakEBOwEAIAAgAmpBqClqQQA6AAAgACAAKAL4LUEBazYC+C0gBQRAIA8gDygCACAEIAVqLwECazYCAAsgAyAMIAYbIQwgACgCoCkiBEECSA0ACwsgASAMNgIEIARBAXYhBgNAIAAgBkECdGpBrBdqKAIAIQkCQCAGIgJBAXQiAyAESg0AIAggCUECdGohCiAAIAlqQagpaiENIAYhBQNAAkAgAyAETgRAIAMhAgwBCyAIIABBrBdqIgIgA0EBciIEQQJ0aigCACILQQJ0ai8BACIOIAggAiADQQJ0aigCACIQQQJ0ai8BACICTwRAIAIgDkcEQCADIQIMAgsgAyECIABBqClqIgMgC2otAAAgAyAQai0AAEsNAQsgBCECCyAKLwEAIgQgCCAAIAJBAnRqQawXaigCACIDQQJ0ai8BACILSQRAIAUhAgwCCwJAIAQgC0cNACANLQAAIAAgA2pBqClqLQAASw0AIAUhAgwCCyAAIAVBAnRqQawXaiADNgIAIAIhBSACQQF0IgMgACgCoCkiBEwNAAsLIAAgAkECdGpBrBdqIAk2AgAgBkECTgRAIAZBAWshBiAAKAKgKSEEDAELCyAAKAKgKSEDA0AgByEGIAAgA0EBayIENgKgKSAAKAKwFyEKIAAgACADQQJ0akGsF2ooAgAiCTYCsBdBASECAkAgA0EDSA0AIAggCUECdGohDSAAIAlqQagpaiELQQIhA0EBIQUDQAJAIAMgBE4EQCADIQIMAQsgCCAAQawXaiICIANBAXIiB0ECdGooAgAiBEECdGovAQAiDiAIIAIgA0ECdGooAgAiEEECdGovAQAiAk8EQCACIA5HBEAgAyECDAILIAMhAiAAQagpaiIDIARqLQAAIAMgEGotAABLDQELIAchAgsgDS8BACIHIAggACACQQJ0akGsF2ooAgAiA0ECdGovAQAiBEkEQCAFIQIMAgsCQCAEIAdHDQAgCy0AACAAIANqQagpai0AAEsNACAFIQIMAgsgACAFQQJ0akGsF2ogAzYCACACIQUgAkEBdCIDIAAoAqApIgRMDQALC0ECIQMgAEGsF2oiByACQQJ0aiAJNgIAIAAgACgCpClBAWsiBTYCpCkgACgCsBchAiAHIAVBAnRqIAo2AgAgACAAKAKkKUEBayIFNgKkKSAHIAVBAnRqIAI2AgAgCCAGQQJ0aiINIAggAkECdGoiBS8BACAIIApBAnRqIgQvAQBqOwEAIABBqClqIgkgBmoiCyACIAlqLQAAIgIgCSAKai0AACIKIAIgCksbQQFqOgAAIAUgBjsBAiAEIAY7AQIgACAGNgKwF0EBIQVBASECAkAgACgCoCkiBEECSA0AA0AgDS8BACIKIAggAAJ/IAMgAyAETg0AGiAIIAcgA0EBciICQQJ0aigCACIEQQJ0ai8BACIOIAggByADQQJ0aigCACIQQQJ0ai8BACISTwRAIAMgDiASRw0BGiADIAQgCWotAAAgCSAQai0AAEsNARoLIAILIgJBAnRqQawXaigCACIDQQJ0ai8BACIESQRAIAUhAgwCCwJAIAQgCkcNACALLQAAIAAgA2pBqClqLQAASw0AIAUhAgwCCyAAIAVBAnRqQawXaiADNgIAIAIhBSACQQF0IgMgACgCoCkiBEwNAAsLIAZBAWohByAAIAJBAnRqQawXaiAGNgIAIAAoAqApIgNBAUoNAAsgACAAKAKkKUEBayICNgKkKSAAQawXaiIDIAJBAnRqIAAoArAXNgIAIAEoAgQhCSABKAIIIgIoAhAhBiACKAIIIQogAigCBCEQIAIoAgAhDSABKAIAIQcgAEGkF2pCADcBACAAQZwXakIANwEAIABBlBdqQgA3AQAgAEGMF2oiAUIANwEAQQAhBSAHIAMgACgCpClBAnRqKAIAQQJ0akEAOwECAkAgACgCpCkiAkG7BEoNACACQQFqIQIDQCAHIAAgAkECdGpBrBdqKAIAIgRBAnQiEmoiCyAHIAsvAQJBAnRqLwECIgNBAWogBiADIAZJGyIOOwECIAMgBk8hEwJAIAQgCUoNACAAIA5BAXRqQYwXaiIDIAMvAQBBAWo7AQBBACEDIAQgCk4EQCAQIAQgCmtBAnRqKAIAIQMLIBEgESgCACALLwEAIgQgAyAOamxqNgIAIA1FDQAgDyAPKAIAIAMgDSASai8BAmogBGxqNgIACyAFIBNqIQUgAkEBaiICQb0ERw0ACyAFRQ0AIAAgBkEBdGpBjBdqIQQDQCAGIQIDQCAAIAIiA0EBayICQQF0akGMF2oiDy8BACIKRQ0ACyAPIApBAWs7AQAgACADQQF0akGMF2oiAiACLwEAQQJqOwEAIAQgBC8BAEEBayIDOwEAIAVBAkohAiAFQQJrIQUgAg0ACyAGRQ0AQb0EIQIDQCADQf//A3EiBQRAA0AgACACQQFrIgJBAnRqQawXaigCACIDIAlKDQAgByADQQJ0aiIDLwECIAZHBEAgESARKAIAIAYgAy8BAGxqIgQ2AgAgESAEIAMvAQAgAy8BAmxrNgIAIAMgBjsBAgsgBUEBayIFDQALCyAGQQFrIgZFDQEgACAGQQF0akGMF2ovAQAhAwwACwALIwBBIGsiAiABIgAvAQBBAXQiATsBAiACIAEgAC8BAmpBAXQiATsBBCACIAEgAC8BBGpBAXQiATsBBiACIAEgAC8BBmpBAXQiATsBCCACIAEgAC8BCGpBAXQiATsBCiACIAEgAC8BCmpBAXQiATsBDCACIAEgAC8BDGpBAXQiATsBDiACIAEgAC8BDmpBAXQiATsBECACIAEgAC8BEGpBAXQiATsBEiACIAEgAC8BEmpBAXQiATsBFCACIAEgAC8BFGpBAXQiATsBFiACIAEgAC8BFmpBAXQiATsBGCACIAEgAC8BGGpBAXQiATsBGiACIAEgAC8BGmpBAXQiATsBHCACIAAvARwgAWpBAXQ7AR5BACEAIAxBAE4EQANAIAggAEECdGoiAy8BAiIBBEAgAiABQQF0aiIFIAUvAQAiBUEBajsBACADIAWtQoD+A4NCCIhCgpCAgQh+QpDCiKKIAYNCgYKEiBB+QiCIp0H/AXEgBUH/AXGtQoKQgIEIfkKQwoiiiAGDQoGChIgQfkIYiKdBgP4DcXJBECABa3Y7AQALIAAgDEchASAAQQFqIQAgAQ0ACwsLcgEBfyMAQRBrIgQkAAJ/QQAgAEUNABogAEEIaiEAIAFFBEAgAlBFBEAgAARAIABBADYCBCAAQRI2AgALQQAMAgtBAEIAIAMgABA6DAELIAQgAjcDCCAEIAE2AgAgBEIBIAMgABA6CyEAIARBEGokACAACyIAIAAgASACIAMQJiIARQRAQQAPCyAAKAIwQQAgAiADECULAwABC8gFAQR/IABB//8DcSEDIABBEHYhBEEBIQAgAkEBRgRAIAMgAS0AAGpB8f8DcCIAIARqQfH/A3BBEHQgAHIPCwJAIAEEfyACQRBJDQECQCACQa8rSwRAA0AgAkGwK2shAkG1BSEFIAEhAANAIAMgAC0AAGoiAyAEaiADIAAtAAFqIgNqIAMgAC0AAmoiA2ogAyAALQADaiIDaiADIAAtAARqIgNqIAMgAC0ABWoiA2ogAyAALQAGaiIDaiADIAAtAAdqIgNqIQQgBQRAIABBCGohACAFQQFrIQUMAQsLIARB8f8DcCEEIANB8f8DcCEDIAFBsCtqIQEgAkGvK0sNAAsgAkEISQ0BCwNAIAMgAS0AAGoiACAEaiAAIAEtAAFqIgBqIAAgAS0AAmoiAGogACABLQADaiIAaiAAIAEtAARqIgBqIAAgAS0ABWoiAGogACABLQAGaiIAaiAAIAEtAAdqIgNqIQQgAUEIaiEBIAJBCGsiAkEHSw0ACwsCQCACRQ0AIAJBAWshBiACQQNxIgUEQCABIQADQCACQQFrIQIgAyAALQAAaiIDIARqIQQgAEEBaiIBIQAgBUEBayIFDQALCyAGQQNJDQADQCADIAEtAABqIgAgAS0AAWoiBSABLQACaiIGIAEtAANqIgMgBiAFIAAgBGpqamohBCABQQRqIQEgAkEEayICDQALCyADQfH/A3AgBEHx/wNwQRB0cgVBAQsPCwJAIAJFDQAgAkEBayEGIAJBA3EiBQRAIAEhAANAIAJBAWshAiADIAAtAABqIgMgBGohBCAAQQFqIgEhACAFQQFrIgUNAAsLIAZBA0kNAANAIAMgAS0AAGoiACABLQABaiIFIAEtAAJqIgYgAS0AA2oiAyAGIAUgACAEampqaiEEIAFBBGohASACQQRrIgINAAsLIANB8f8DcCAEQfH/A3BBEHRyCx8AIAAgAiADQcCAASgCABEAACEAIAEgAiADEAcaIAALIwAgACAAKAJAIAIgA0HUgAEoAgARAAA2AkAgASACIAMQBxoLzSoCGH8HfiAAKAIMIgIgACgCECIDaiEQIAMgAWshASAAKAIAIgUgACgCBGohA0F/IAAoAhwiBygCpAF0IQRBfyAHKAKgAXQhCyAHKAI4IQwCf0EAIAcoAiwiEUUNABpBACACIAxJDQAaIAJBhAJqIAwgEWpNCyEWIBBBgwJrIRMgASACaiEXIANBDmshFCAEQX9zIRggC0F/cyESIAcoApwBIRUgBygCmAEhDSAHKAKIASEIIAc1AoQBIR0gBygCNCEOIAcoAjAhGSAQQQFqIQ8DQCAIQThyIQYgBSAIQQN2QQdxayELAn8gAiANIAUpAAAgCK2GIB2EIh2nIBJxQQJ0IgFqIgMtAAAiBA0AGiACIAEgDWoiAS0AAjoAACAGIAEtAAEiAWshBiACQQFqIA0gHSABrYgiHacgEnFBAnQiAWoiAy0AACIEDQAaIAIgASANaiIDLQACOgABIAYgAy0AASIDayEGIA0gHSADrYgiHacgEnFBAnRqIgMtAAAhBCACQQJqCyEBIAtBB2ohBSAGIAMtAAEiAmshCCAdIAKtiCEdAkACQAJAIARB/wFxRQ0AAkACQAJAAkACQANAIARBEHEEQCAVIB0gBK1CD4OIIhqnIBhxQQJ0aiECAn8gCCAEQQ9xIgZrIgRBG0sEQCAEIQggBQwBCyAEQThyIQggBSkAACAErYYgGoQhGiAFIARBA3ZrQQdqCyELIAMzAQIhGyAIIAItAAEiA2shCCAaIAOtiCEaIAItAAAiBEEQcQ0CA0AgBEHAAHFFBEAgCCAVIAIvAQJBAnRqIBqnQX8gBHRBf3NxQQJ0aiICLQABIgNrIQggGiADrYghGiACLQAAIgRBEHFFDQEMBAsLIAdB0f4ANgIEIABB7A42AhggGiEdDAMLIARB/wFxIgJBwABxRQRAIAggDSADLwECQQJ0aiAdp0F/IAJ0QX9zcUECdGoiAy0AASICayEIIB0gAq2IIR0gAy0AACIERQ0HDAELCyAEQSBxBEAgB0G//gA2AgQgASECDAgLIAdB0f4ANgIEIABB0A42AhggASECDAcLIB1BfyAGdEF/c62DIBt8IhunIQUgCCAEQQ9xIgNrIQggGiAErUIPg4ghHSABIBdrIgYgAjMBAiAaQX8gA3RBf3Otg3ynIgRPDQIgBCAGayIGIBlNDQEgBygCjEdFDQEgB0HR/gA2AgQgAEG5DDYCGAsgASECIAshBQwFCwJAIA5FBEAgDCARIAZraiEDDAELIAYgDk0EQCAMIA4gBmtqIQMMAQsgDCARIAYgDmsiBmtqIQMgBSAGTQ0AIAUgBmshBQJAAkAgASADTSABIA8gAWusIhogBq0iGyAaIBtUGyIapyIGaiICIANLcQ0AIAMgBmogAUsgASADT3ENACABIAMgBhAHGiACIQEMAQsgASADIAMgAWsiASABQR91IgFqIAFzIgIQByACaiEBIBogAq0iHn0iHFANACACIANqIQIDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgASACKQAANwAAIAEgAikAGDcAGCABIAIpABA3ABAgASACKQAINwAIIBpCIH0hGiACQSBqIQIgAUEgaiEBIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAEgAikAADcAACABIAIpABg3ABggASACKQAQNwAQIAEgAikACDcACCABIAIpADg3ADggASACKQAwNwAwIAEgAikAKDcAKCABIAIpACA3ACAgASACKQBYNwBYIAEgAikAUDcAUCABIAIpAEg3AEggASACKQBANwBAIAEgAikAYDcAYCABIAIpAGg3AGggASACKQBwNwBwIAEgAikAeDcAeCACQYABaiECIAFBgAFqIQEgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAEgAikAADcAACABIAIpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCABIAIpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCABIAIoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCABIAIvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCABIAItAAA6AAAgAkEBaiECIAFBAWohAQsgHEIAUg0ACwsgDiEGIAwhAwsgBSAGSwRAAkACQCABIANNIAEgDyABa6wiGiAGrSIbIBogG1QbIhqnIglqIgIgA0txDQAgAyAJaiABSyABIANPcQ0AIAEgAyAJEAcaDAELIAEgAyADIAFrIgEgAUEfdSIBaiABcyIBEAcgAWohAiAaIAGtIh59IhxQDQAgASADaiEBA0ACQCAcIB4gHCAeVBsiG0IgVARAIBshGgwBCyAbIhpCIH0iIEIFiEIBfEIDgyIfUEUEQANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCAaQiB9IRogAUEgaiEBIAJBIGohAiAfQgF9Ih9CAFINAAsLICBC4ABUDQADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggAiABKQA4NwA4IAIgASkAMDcAMCACIAEpACg3ACggAiABKQAgNwAgIAIgASkAWDcAWCACIAEpAFA3AFAgAiABKQBINwBIIAIgASkAQDcAQCACIAEpAGA3AGAgAiABKQBoNwBoIAIgASkAcDcAcCACIAEpAHg3AHggAUGAAWohASACQYABaiECIBpCgAF9IhpCH1YNAAsLIBpCEFoEQCACIAEpAAA3AAAgAiABKQAINwAIIBpCEH0hGiACQRBqIQIgAUEQaiEBCyAaQghaBEAgAiABKQAANwAAIBpCCH0hGiACQQhqIQIgAUEIaiEBCyAaQgRaBEAgAiABKAAANgAAIBpCBH0hGiACQQRqIQIgAUEEaiEBCyAaQgJaBEAgAiABLwAAOwAAIBpCAn0hGiACQQJqIQIgAUECaiEBCyAcIBt9IRwgGlBFBEAgAiABLQAAOgAAIAJBAWohAiABQQFqIQELIBxCAFINAAsLIAUgBmshAUEAIARrIQUCQCAEQQdLBEAgBCEDDAELIAEgBE0EQCAEIQMMAQsgAiAEayEFA0ACQCACIAUpAAA3AAAgBEEBdCEDIAEgBGshASACIARqIQIgBEEDSw0AIAMhBCABIANLDQELC0EAIANrIQULIAIgBWohBAJAIAUgDyACa6wiGiABrSIbIBogG1QbIhqnIgFIIAVBf0pxDQAgBUEBSCABIARqIAJLcQ0AIAIgBCABEAcgAWohAgwDCyACIAQgAyADQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANAiABIARqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAILAkAgASADTSABIA8gAWusIhogBa0iGyAaIBtUGyIapyIEaiICIANLcQ0AIAMgBGogAUsgASADT3ENACABIAMgBBAHGgwCCyABIAMgAyABayIBIAFBH3UiAWogAXMiARAHIAFqIQIgGiABrSIefSIcUA0BIAEgA2ohAQNAAkAgHCAeIBwgHlQbIhtCIFQEQCAbIRoMAQsgGyIaQiB9IiBCBYhCAXxCA4MiH1BFBEADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggGkIgfSEaIAFBIGohASACQSBqIQIgH0IBfSIfQgBSDQALCyAgQuAAVA0AA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIAIgASkAODcAOCACIAEpADA3ADAgAiABKQAoNwAoIAIgASkAIDcAICACIAEpAFg3AFggAiABKQBQNwBQIAIgASkASDcASCACIAEpAEA3AEAgAiABKQBgNwBgIAIgASkAaDcAaCACIAEpAHA3AHAgAiABKQB4NwB4IAFBgAFqIQEgAkGAAWohAiAaQoABfSIaQh9WDQALCyAaQhBaBEAgAiABKQAANwAAIAIgASkACDcACCAaQhB9IRogAkEQaiECIAFBEGohAQsgGkIIWgRAIAIgASkAADcAACAaQgh9IRogAkEIaiECIAFBCGohAQsgGkIEWgRAIAIgASgAADYAACAaQgR9IRogAkEEaiECIAFBBGohAQsgGkICWgRAIAIgAS8AADsAACAaQgJ9IRogAkECaiECIAFBAmohAQsgHCAbfSEcIBpQRQRAIAIgAS0AADoAACACQQFqIQIgAUEBaiEBCyAcUEUNAAsMAQsCQAJAIBYEQAJAIAQgBUkEQCAHKAKYRyAESw0BCyABIARrIQMCQEEAIARrIgVBf0ogDyABa6wiGiAbIBogG1QbIhqnIgIgBUpxDQAgBUEBSCACIANqIAFLcQ0AIAEgAyACEAcgAmohAgwFCyABIAMgBCAEQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANBCABIANqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAQLIBAgAWsiCUEBaiIGIAUgBSAGSxshAyABIARrIQIgAUEHcUUNAiADRQ0CIAEgAi0AADoAACACQQFqIQIgAUEBaiIGQQdxQQAgA0EBayIFGw0BIAYhASAFIQMgCSEGDAILAkAgBCAFSQRAIAcoAphHIARLDQELIAEgASAEayIGKQAANwAAIAEgBUEBa0EHcUEBaiIDaiECIAUgA2siBEUNAyADIAZqIQEDQCACIAEpAAA3AAAgAUEIaiEBIAJBCGohAiAEQQhrIgQNAAsMAwsgASAEIAUQPyECDAILIAEgAi0AADoAASAJQQFrIQYgA0ECayEFIAJBAWohAgJAIAFBAmoiCkEHcUUNACAFRQ0AIAEgAi0AADoAAiAJQQJrIQYgA0EDayEFIAJBAWohAgJAIAFBA2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAAyAJQQNrIQYgA0EEayEFIAJBAWohAgJAIAFBBGoiCkEHcUUNACAFRQ0AIAEgAi0AADoABCAJQQRrIQYgA0EFayEFIAJBAWohAgJAIAFBBWoiCkEHcUUNACAFRQ0AIAEgAi0AADoABSAJQQVrIQYgA0EGayEFIAJBAWohAgJAIAFBBmoiCkEHcUUNACAFRQ0AIAEgAi0AADoABiAJQQZrIQYgA0EHayEFIAJBAWohAgJAIAFBB2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAByAJQQdrIQYgA0EIayEDIAFBCGohASACQQFqIQIMBgsgCiEBIAUhAwwFCyAKIQEgBSEDDAQLIAohASAFIQMMAwsgCiEBIAUhAwwCCyAKIQEgBSEDDAELIAohASAFIQMLAkACQCAGQRdNBEAgA0UNASADQQFrIQUgA0EHcSIEBEADQCABIAItAAA6AAAgA0EBayEDIAFBAWohASACQQFqIQIgBEEBayIEDQALCyAFQQdJDQEDQCABIAItAAA6AAAgASACLQABOgABIAEgAi0AAjoAAiABIAItAAM6AAMgASACLQAEOgAEIAEgAi0ABToABSABIAItAAY6AAYgASACLQAHOgAHIAFBCGohASACQQhqIQIgA0EIayIDDQALDAELIAMNAQsgASECDAELIAEgBCADED8hAgsgCyEFDAELIAEgAy0AAjoAACABQQFqIQILIAUgFE8NACACIBNJDQELCyAAIAI2AgwgACAFIAhBA3ZrIgE2AgAgACATIAJrQYMCajYCECAAIBQgAWtBDmo2AgQgByAIQQdxIgA2AogBIAcgHUJ/IACthkJ/hYM+AoQBC+cFAQR/IAMgAiACIANLGyEEIAAgAWshAgJAIABBB3FFDQAgBEUNACAAIAItAAA6AAAgA0EBayEGIAJBAWohAiAAQQFqIgdBB3FBACAEQQFrIgUbRQRAIAchACAFIQQgBiEDDAELIAAgAi0AADoAASADQQJrIQYgBEECayEFIAJBAWohAgJAIABBAmoiB0EHcUUNACAFRQ0AIAAgAi0AADoAAiADQQNrIQYgBEEDayEFIAJBAWohAgJAIABBA2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAAyADQQRrIQYgBEEEayEFIAJBAWohAgJAIABBBGoiB0EHcUUNACAFRQ0AIAAgAi0AADoABCADQQVrIQYgBEEFayEFIAJBAWohAgJAIABBBWoiB0EHcUUNACAFRQ0AIAAgAi0AADoABSADQQZrIQYgBEEGayEFIAJBAWohAgJAIABBBmoiB0EHcUUNACAFRQ0AIAAgAi0AADoABiADQQdrIQYgBEEHayEFIAJBAWohAgJAIABBB2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAByADQQhrIQMgBEEIayEEIABBCGohACACQQFqIQIMBgsgByEAIAUhBCAGIQMMBQsgByEAIAUhBCAGIQMMBAsgByEAIAUhBCAGIQMMAwsgByEAIAUhBCAGIQMMAgsgByEAIAUhBCAGIQMMAQsgByEAIAUhBCAGIQMLAkAgA0EXTQRAIARFDQEgBEEBayEBIARBB3EiAwRAA0AgACACLQAAOgAAIARBAWshBCAAQQFqIQAgAkEBaiECIANBAWsiAw0ACwsgAUEHSQ0BA0AgACACLQAAOgAAIAAgAi0AAToAASAAIAItAAI6AAIgACACLQADOgADIAAgAi0ABDoABCAAIAItAAU6AAUgACACLQAGOgAGIAAgAi0ABzoAByAAQQhqIQAgAkEIaiECIARBCGsiBA0ACwwBCyAERQ0AIAAgASAEED8hAAsgAAvyCAEXfyAAKAJoIgwgACgCMEGGAmsiBWtBACAFIAxJGyENIAAoAnQhAiAAKAKQASEPIAAoAkgiDiAMaiIJIAAoAnAiBUECIAUbIgVBAWsiBmoiAy0AASESIAMtAAAhEyAGIA5qIQZBAyEDIAAoApQBIRYgACgCPCEUIAAoAkwhECAAKAI4IRECQAJ/IAVBA0kEQCANIQggDgwBCyAAIABBACAJLQABIAAoAnwRAAAgCS0AAiAAKAJ8EQAAIQoDQCAAIAogAyAJai0AACAAKAJ8EQAAIQogACgCUCAKQQF0ai8BACIIIAEgCCABQf//A3FJIggbIQEgA0ECayAHIAgbIQcgA0EBaiIDIAVNDQALIAFB//8DcSAHIA1qIghB//8DcU0NASAGIAdB//8DcSIDayEGIA4gA2sLIQMCQAJAIAwgAUH//wNxTQ0AIAIgAkECdiAFIA9JGyEKIA1B//8DcSEVIAlBAmohDyAJQQRrIRcDQAJAAkAgBiABQf//A3EiC2otAAAgE0cNACAGIAtBAWoiAWotAAAgEkcNACADIAtqIgItAAAgCS0AAEcNACABIANqLQAAIAktAAFGDQELIApBAWsiCkUNAiAQIAsgEXFBAXRqLwEAIgEgCEH//wNxSw0BDAILIAJBAmohAUEAIQQgDyECAkADQCACLQAAIAEtAABHDQEgAi0AASABLQABRwRAIARBAXIhBAwCCyACLQACIAEtAAJHBEAgBEECciEEDAILIAItAAMgAS0AA0cEQCAEQQNyIQQMAgsgAi0ABCABLQAERwRAIARBBHIhBAwCCyACLQAFIAEtAAVHBEAgBEEFciEEDAILIAItAAYgAS0ABkcEQCAEQQZyIQQMAgsgAi0AByABLQAHRwRAIARBB3IhBAwCCyABQQhqIQEgAkEIaiECIARB+AFJIRggBEEIaiEEIBgNAAtBgAIhBAsCQAJAIAUgBEECaiICSQRAIAAgCyAHQf//A3FrIgY2AmwgAiAUSwRAIBQPCyACIBZPBEAgAg8LIAkgBEEBaiIFaiIBLQABIRIgAS0AACETAkAgAkEESQ0AIAIgBmogDE8NACAGQf//A3EhCCAEQQFrIQtBACEDQQAhBwNAIBAgAyAIaiARcUEBdGovAQAiASAGQf//A3FJBEAgAyAVaiABTw0IIAMhByABIQYLIANBAWoiAyALTQ0ACyAAIAAgAEEAIAIgF2oiAS0AACAAKAJ8EQAAIAEtAAEgACgCfBEAACABLQACIAAoAnwRAAAhASAAKAJQIAFBAXRqLwEAIgEgBkH//wNxTwRAIAdB//8DcSEDIAYhAQwDCyAEQQJrIgdB//8DcSIDIBVqIAFPDQYMAgsgAyAFaiEGIAIhBQsgCkEBayIKRQ0DIBAgCyARcUEBdGovAQAiASAIQf//A3FNDQMMAQsgByANaiEIIA4gA2siAyAFaiEGIAIhBQsgDCABQf//A3FLDQALCyAFDwsgAiEFCyAFIAAoAjwiACAAIAVLGwuGBQETfyAAKAJ0IgMgA0ECdiAAKAJwIgNBAiADGyIDIAAoApABSRshByAAKAJoIgogACgCMEGGAmsiBWtB//8DcUEAIAUgCkkbIQwgACgCSCIIIApqIgkgA0EBayICaiIFLQABIQ0gBS0AACEOIAlBAmohBSACIAhqIQsgACgClAEhEiAAKAI8IQ8gACgCTCEQIAAoAjghESAAKAKIAUEFSCETA0ACQCAKIAFB//8DcU0NAANAAkACQCALIAFB//8DcSIGai0AACAORw0AIAsgBkEBaiIBai0AACANRw0AIAYgCGoiAi0AACAJLQAARw0AIAEgCGotAAAgCS0AAUYNAQsgB0EBayIHRQ0CIAwgECAGIBFxQQF0ai8BACIBSQ0BDAILCyACQQJqIQRBACECIAUhAQJAA0AgAS0AACAELQAARw0BIAEtAAEgBC0AAUcEQCACQQFyIQIMAgsgAS0AAiAELQACRwRAIAJBAnIhAgwCCyABLQADIAQtAANHBEAgAkEDciECDAILIAEtAAQgBC0ABEcEQCACQQRyIQIMAgsgAS0ABSAELQAFRwRAIAJBBXIhAgwCCyABLQAGIAQtAAZHBEAgAkEGciECDAILIAEtAAcgBC0AB0cEQCACQQdyIQIMAgsgBEEIaiEEIAFBCGohASACQfgBSSEUIAJBCGohAiAUDQALQYACIQILAkAgAyACQQJqIgFJBEAgACAGNgJsIAEgD0sEQCAPDwsgASASTwRAIAEPCyAIIAJBAWoiA2ohCyADIAlqIgMtAAEhDSADLQAAIQ4gASEDDAELIBMNAQsgB0EBayIHRQ0AIAwgECAGIBFxQQF0ai8BACIBSQ0BCwsgAwvLAQECfwJAA0AgAC0AACABLQAARw0BIAAtAAEgAS0AAUcEQCACQQFyDwsgAC0AAiABLQACRwRAIAJBAnIPCyAALQADIAEtAANHBEAgAkEDcg8LIAAtAAQgAS0ABEcEQCACQQRyDwsgAC0ABSABLQAFRwRAIAJBBXIPCyAALQAGIAEtAAZHBEAgAkEGcg8LIAAtAAcgAS0AB0cEQCACQQdyDwsgAUEIaiEBIABBCGohACACQfgBSSEDIAJBCGohAiADDQALQYACIQILIAIL5wwBB38gAEF/cyEAIAJBF08EQAJAIAFBA3FFDQAgAS0AACAAQf8BcXNBAnRB0BhqKAIAIABBCHZzIQAgAkEBayIEQQAgAUEBaiIDQQNxG0UEQCAEIQIgAyEBDAELIAEtAAEgAEH/AXFzQQJ0QdAYaigCACAAQQh2cyEAIAFBAmohAwJAIAJBAmsiBEUNACADQQNxRQ0AIAEtAAIgAEH/AXFzQQJ0QdAYaigCACAAQQh2cyEAIAFBA2ohAwJAIAJBA2siBEUNACADQQNxRQ0AIAEtAAMgAEH/AXFzQQJ0QdAYaigCACAAQQh2cyEAIAFBBGohASACQQRrIQIMAgsgBCECIAMhAQwBCyAEIQIgAyEBCyACQRRuIgNBbGwhCQJAIANBAWsiCEUEQEEAIQQMAQsgA0EUbCABakEUayEDQQAhBANAIAEoAhAgB3MiB0EWdkH8B3FB0DhqKAIAIAdBDnZB/AdxQdAwaigCACAHQQZ2QfwHcUHQKGooAgAgB0H/AXFBAnRB0CBqKAIAc3NzIQcgASgCDCAGcyIGQRZ2QfwHcUHQOGooAgAgBkEOdkH8B3FB0DBqKAIAIAZBBnZB/AdxQdAoaigCACAGQf8BcUECdEHQIGooAgBzc3MhBiABKAIIIAVzIgVBFnZB/AdxQdA4aigCACAFQQ52QfwHcUHQMGooAgAgBUEGdkH8B3FB0ChqKAIAIAVB/wFxQQJ0QdAgaigCAHNzcyEFIAEoAgQgBHMiBEEWdkH8B3FB0DhqKAIAIARBDnZB/AdxQdAwaigCACAEQQZ2QfwHcUHQKGooAgAgBEH/AXFBAnRB0CBqKAIAc3NzIQQgASgCACAAcyIAQRZ2QfwHcUHQOGooAgAgAEEOdkH8B3FB0DBqKAIAIABBBnZB/AdxQdAoaigCACAAQf8BcUECdEHQIGooAgBzc3MhACABQRRqIQEgCEEBayIIDQALIAMhAQsgAiAJaiECIAEoAhAgASgCDCABKAIIIAEoAgQgASgCACAAcyIAQQh2IABB/wFxQQJ0QdAYaigCAHMiAEEIdiAAQf8BcUECdEHQGGooAgBzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyIAQf8BcUECdEHQGGooAgAgBHNzIABBCHZzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyIAQQh2IABB/wFxQQJ0QdAYaigCAHMiAEEIdiAAQf8BcUECdEHQGGooAgBzIgBB/wFxQQJ0QdAYaigCACAFc3MgAEEIdnMiAEEIdiAAQf8BcUECdEHQGGooAgBzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyIAQQh2IABB/wFxQQJ0QdAYaigCAHMiAEH/AXFBAnRB0BhqKAIAIAZzcyAAQQh2cyIAQQh2IABB/wFxQQJ0QdAYaigCAHMiAEEIdiAAQf8BcUECdEHQGGooAgBzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyIAQf8BcUECdEHQGGooAgAgB3NzIABBCHZzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyIAQQh2IABB/wFxQQJ0QdAYaigCAHMiAEEIdiAAQf8BcUECdEHQGGooAgBzIgBBCHYgAEH/AXFBAnRB0BhqKAIAcyEAIAFBFGohAQsgAkEHSwRAA0AgAS0AByABLQAGIAEtAAUgAS0ABCABLQADIAEtAAIgAS0AASABLQAAIABB/wFxc0ECdEHQGGooAgAgAEEIdnMiAEH/AXFzQQJ0QdAYaigCACAAQQh2cyIAQf8BcXNBAnRB0BhqKAIAIABBCHZzIgBB/wFxc0ECdEHQGGooAgAgAEEIdnMiAEH/AXFzQQJ0QdAYaigCACAAQQh2cyIAQf8BcXNBAnRB0BhqKAIAIABBCHZzIgBB/wFxc0ECdEHQGGooAgAgAEEIdnMiAEH/AXFzQQJ0QdAYaigCACAAQQh2cyEAIAFBCGohASACQQhrIgJBB0sNAAsLAkAgAkUNACACQQFxBH8gAS0AACAAQf8BcXNBAnRB0BhqKAIAIABBCHZzIQAgAUEBaiEBIAJBAWsFIAILIQMgAkEBRg0AA0AgAS0AASABLQAAIABB/wFxc0ECdEHQGGooAgAgAEEIdnMiAEH/AXFzQQJ0QdAYaigCACAAQQh2cyEAIAFBAmohASADQQJrIgMNAAsLIABBf3MLwgIBA38jAEEQayIIJAACfwJAIAAEQCAEDQEgBVANAQsgBgRAIAZBADYCBCAGQRI2AgALQQAMAQtBgAEQCSIHRQRAIAYEQCAGQQA2AgQgBkEONgIAC0EADAELIAcgATcDCCAHQgA3AwAgB0EoaiIJECogByAFNwMYIAcgBDYCECAHIAM6AGAgB0EANgJsIAdCADcCZCAAKQMYIQEgCEF/NgIIIAhCjoCAgPAANwMAIAdBECAIECQgAUL/gQGDhCIBNwNwIAcgAadBBnZBAXE6AHgCQCACRQ0AIAkgAhBgQX9KDQAgBxAGQQAMAQsgBhBfIgIEQCAAIAAoAjBBAWo2AjAgAiAHNgIIIAJBATYCBCACIAA2AgAgAkI/IAAgB0EAQgBBDkEBEQoAIgEgAUIAUxs3AxgLIAILIQAgCEEQaiQAIAALYgEBf0E4EAkiAUUEQCAABEAgAEEANgIEIABBDjYCAAtBAA8LIAFBADYCCCABQgA3AwAgAUIANwMgIAFCgICAgBA3AiwgAUEAOgAoIAFBADYCFCABQgA3AgwgAUEAOwE0IAELuwEBAX4gASkDACICQgKDUEUEQCAAIAEpAxA3AxALIAJCBINQRQRAIAAgASkDGDcDGAsgAkIIg1BFBEAgACABKQMgNwMgCyACQhCDUEUEQCAAIAEoAig2AigLIAJCIINQRQRAIAAgASgCLDYCLAsgAkLAAINQRQRAIAAgAS8BMDsBMAsgAkKAAYNQRQRAIAAgAS8BMjsBMgsgAkKAAoNQRQRAIAAgASgCNDYCNAsgACAAKQMAIAKENwMAQQALGQAgAUUEQEEADwsgACABKAIAIAEzAQQQGws3AQJ/IABBACABG0UEQCAAIAFGDwsgAC8BBCIDIAEvAQRGBH8gACgCACABKAIAIAMQPQVBAQtFCyIBAX8gAUUEQEEADwsgARAJIgJFBEBBAA8LIAIgACABEAcLKQAgACABIAIgAyAEEEUiAEUEQEEADwsgACACQQAgBBA1IQEgABAGIAELcQEBfgJ/AkAgAkJ/VwRAIAMEQCADQQA2AgQgA0EUNgIACwwBCyAAIAEgAhARIgRCf1cEQCADBEAgAyAAKAIMNgIAIAMgACgCEDYCBAsMAQtBACACIARXDQEaIAMEQCADQQA2AgQgA0ERNgIACwtBfwsLNQAgACABIAJBABAmIgBFBEBBfw8LIAMEQCADIAAtAAk6AAALIAQEQCAEIAAoAkQ2AgALQQAL/AECAn8BfiMAQRBrIgMkAAJAIAAgA0EOaiABQYAGQQAQRiIARQRAIAIhAAwBCyADLwEOIgFBBUkEQCACIQAMAQsgAC0AAEEBRwRAIAIhAAwBCyAAIAGtQv//A4MQFyIBRQRAIAIhAAwBCyABEH0aAkAgARAVIAIEfwJ/IAIvAQQhAEEAIAIoAgAiBEUNABpBACAEIABB1IABKAIAEQAACwVBAAtHBEAgAiEADAELIAEgAS0AAAR+IAEpAwggASkDEH0FQgALIgVC//8DgxATIAWnQf//A3FBgBBBABA1IgBFBEAgAiEADAELIAIQEAsgARAICyADQRBqJAAgAAvmDwIIfwJ+IwBB4ABrIgckAEEeQS4gAxshCwJAAkAgAgRAIAIiBSIGLQAABH4gBikDCCAGKQMQfQVCAAsgC61aDQEgBARAIARBADYCBCAEQRM2AgALQn8hDQwCCyABIAutIAcgBBAtIgUNAEJ/IQ0MAQsgBUIEEBMoAABBoxJBqBIgAxsoAABHBEAgBARAIARBADYCBCAEQRM2AgALQn8hDSACDQEgBRAIDAELIABCADcDICAAQQA2AhggAEL/////DzcDECAAQQA7AQwgAEG/hig2AgggAEEBOgAGIABBADsBBCAAQQA2AgAgAEIANwNIIABBgIDYjXg2AkQgAEIANwMoIABCADcDMCAAQgA3AzggAEFAa0EAOwEAIABCADcDUCAAIAMEf0EABSAFEAwLOwEIIAAgBRAMOwEKIAAgBRAMOwEMIAAgBRAMNgIQIAUQDCEGIAUQDCEJIAdBADYCWCAHQgA3A1AgB0IANwNIIAcgCUEfcTYCPCAHIAZBC3Y2AjggByAGQQV2QT9xNgI0IAcgBkEBdEE+cTYCMCAHIAlBCXZB0ABqNgJEIAcgCUEFdkEPcUEBazYCQCAAIAdBMGoQBTYCFCAAIAUQFTYCGCAAIAUQFa03AyAgACAFEBWtNwMoIAUQDCEIIAUQDCEGIAACfiADBEBBACEJIABBADYCRCAAQQA7AUAgAEEANgI8QgAMAQsgBRAMIQkgACAFEAw2AjwgACAFEAw7AUAgACAFEBU2AkQgBRAVrQs3A0ggBS0AAEUEQCAEBEAgBEEANgIEIARBFDYCAAtCfyENIAINASAFEAgMAQsCQCAALwEMIgpBAXEEQCAKQcAAcQRAIABB//8DOwFSDAILIABBATsBUgwBCyAAQQA7AVILIABBADYCOCAAQgA3AzAgBiAIaiAJaiEKAkAgAgRAIAUtAAAEfiAFKQMIIAUpAxB9BUIACyAKrVoNASAEBEAgBEEANgIEIARBFTYCAAtCfyENDAILIAUQCCABIAqtQQAgBBAtIgUNAEJ/IQ0MAQsCQCAIRQ0AIAAgBSABIAhBASAEEGQiCDYCMCAIRQRAIAQoAgBBEUYEQCAEBEAgBEEANgIEIARBFTYCAAsLQn8hDSACDQIgBRAIDAILIAAtAA1BCHFFDQAgCEECECNBBUcNACAEBEAgBEEANgIEIARBFTYCAAtCfyENIAINASAFEAgMAQsgAEE0aiEIAkAgBkUNACAFIAEgBkEAIAQQRSIMRQRAQn8hDSACDQIgBRAIDAILIAwgBkGAAkGABCADGyAIIAQQbiEGIAwQBiAGRQRAQn8hDSACDQIgBRAIDAILIANFDQAgAEEBOgAECwJAIAlFDQAgACAFIAEgCUEAIAQQZCIBNgI4IAFFBEBCfyENIAINAiAFEAgMAgsgAC0ADUEIcUUNACABQQIQI0EFRw0AIAQEQCAEQQA2AgQgBEEVNgIAC0J/IQ0gAg0BIAUQCAwBCyAAIAAoAjRB9eABIAAoAjAQZzYCMCAAIAAoAjRB9cYBIAAoAjgQZzYCOAJAAkAgACkDKEL/////D1ENACAAKQMgQv////8PUQ0AIAApA0hC/////w9SDQELAkACQAJAIAgoAgAgB0EwakEBQYACQYAEIAMbIAQQRiIBRQRAIAJFDQEMAgsgASAHMwEwEBciAUUEQCAEBEAgBEEANgIEIARBDjYCAAsgAkUNAQwCCwJAIAApAyhC/////w9RBEAgACABEB03AygMAQsgA0UNAEEAIQYCQCABKQMQIg5CCHwiDSAOVA0AIAEpAwggDVQNACABIA03AxBBASEGCyABIAY6AAALIAApAyBC/////w9RBEAgACABEB03AyALAkAgAw0AIAApA0hC/////w9RBEAgACABEB03A0gLIAAoAjxB//8DRw0AIAAgARAVNgI8CyABLQAABH8gASkDECABKQMIUQVBAAsNAiAEBEAgBEEANgIEIARBFTYCAAsgARAIIAINAQsgBRAIC0J/IQ0MAgsgARAICyAFLQAARQRAIAQEQCAEQQA2AgQgBEEUNgIAC0J/IQ0gAg0BIAUQCAwBCyACRQRAIAUQCAtCfyENIAApA0hCf1cEQCAEBEAgBEEWNgIEIARBBDYCAAsMAQsjAEEQayIDJABBASEBAkAgACgCEEHjAEcNAEEAIQECQCAAKAI0IANBDmpBgbICQYAGQQAQRiICBEAgAy8BDiIFQQZLDQELIAQEQCAEQQA2AgQgBEEVNgIACwwBCyACIAWtQv//A4MQFyICRQRAIAQEQCAEQQA2AgQgBEEUNgIACwwBC0EBIQECQAJAAkAgAhAMQQFrDgICAQALQQAhASAEBEAgBEEANgIEIARBGDYCAAsgAhAIDAILIAApAyhCE1YhAQsgAkICEBMvAABBwYoBRwRAQQAhASAEBEAgBEEANgIEIARBGDYCAAsgAhAIDAELIAIQfUEBayIFQf8BcUEDTwRAQQAhASAEBEAgBEEANgIEIARBGDYCAAsgAhAIDAELIAMvAQ5BB0cEQEEAIQEgBARAIARBADYCBCAEQRU2AgALIAIQCAwBCyAAIAE6AAYgACAFQf8BcUGBAmo7AVIgACACEAw2AhAgAhAIQQEhAQsgA0EQaiQAIAFFDQAgCCAIKAIAEG02AgAgCiALaq0hDQsgB0HgAGokACANC4ECAQR/IwBBEGsiBCQAAkAgASAEQQxqQcAAQQAQJSIGRQ0AIAQoAgxBBWoiA0GAgARPBEAgAgRAIAJBADYCBCACQRI2AgALDAELQQAgA60QFyIDRQRAIAIEQCACQQA2AgQgAkEONgIACwwBCyADQQEQcCADIAEEfwJ/IAEvAQQhBUEAIAEoAgAiAUUNABpBACABIAVB1IABKAIAEQAACwVBAAsQEiADIAYgBCgCDBAsAn8gAy0AAEUEQCACBEAgAkEANgIEIAJBFDYCAAtBAAwBCyAAIAMtAAAEfiADKQMQBUIAC6dB//8DcSADKAIEEEcLIQUgAxAICyAEQRBqJAAgBQvgAQICfwF+QTAQCSICRQRAIAEEQCABQQA2AgQgAUEONgIAC0EADwsgAkIANwMIIAJBADYCACACQgA3AxAgAkIANwMYIAJCADcDICACQgA3ACUgAFAEQCACDwsCQCAAQv////8AVg0AIACnQQR0EAkiA0UNACACIAM2AgBBACEBQgEhBANAIAMgAUEEdGoiAUIANwIAIAFCADcABSAAIARSBEAgBKchASAEQgF8IQQMAQsLIAIgADcDCCACIAA3AxAgAg8LIAEEQCABQQA2AgQgAUEONgIAC0EAEBAgAhAGQQAL7gECA38BfiMAQRBrIgQkAAJAIARBDGpCBBAXIgNFBEBBfyECDAELAkAgAQRAIAJBgAZxIQUDQAJAIAUgASgCBHFFDQACQCADKQMIQgBUBEAgA0EAOgAADAELIANCADcDECADQQE6AAALIAMgAS8BCBANIAMgAS8BChANIAMtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAtBfyECDAQLQX8hAiAAIARBDGpCBBAbQQBIDQMgATMBCiIGUA0AIAAgASgCDCAGEBtBAEgNAwsgASgCACIBDQALC0EAIQILIAMQCAsgBEEQaiQAIAILPAEBfyAABEAgAUGABnEhAQNAIAEgACgCBHEEQCACIAAvAQpqQQRqIQILIAAoAgAiAA0ACwsgAkH//wNxC5wBAQN/IABFBEBBAA8LIAAhAwNAAn8CQAJAIAAvAQgiAUH04AFNBEAgAUEBRg0BIAFB9cYBRg0BDAILIAFBgbICRg0AIAFB9eABRw0BCyAAKAIAIQEgAEEANgIAIAAoAgwQBiAAEAYgASADIAAgA0YbIQMCQCACRQRAQQAhAgwBCyACIAE2AgALIAEMAQsgACICKAIACyIADQALIAMLsgQCBX8BfgJAAkACQCAAIAGtEBciAQRAIAEtAAANAUEAIQAMAgsgBARAIARBADYCBCAEQQ42AgALQQAPC0EAIQADQCABLQAABH4gASkDCCABKQMQfQVCAAtCBFQNASABEAwhByABIAEQDCIGrRATIghFBEBBACECIAQEQCAEQQA2AgQgBEEVNgIACyABEAggAEUNAwNAIAAoAgAhASAAKAIMEAYg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DCAAQRg2AggLDAMLIAAgBiAFLwFqQQAgBCABEQYAIQEgBhALIAFFDQILAkAgDUUEQCABIQMMAQsgACABIAUvAWgQgQEhAyABEAsgA0UNAQsCQCAJRSAMckUEQCADIQEMAQsgACADQQEQgAEhASADEAsgAUUNAQsgASEDDAELQQAhAwsgBUHwAGokACADC4UBAQF/IAFFBEAgAEEIaiIABEAgAEEANgIEIABBEjYCAAtBAA8LQTgQCSIDRQRAIABBCGoiAARAIABBADYCBCAAQQ42AgALQQAPCyADQQA2AhAgA0IANwIIIANCADcDKCADQQA2AgQgAyACNgIAIANCADcDGCADQQA2AjAgACABQTsgAxBCCw8AIAAgASACQQBBABCCAQusAgECfyABRQRAIABBCGoiAARAIABBADYCBCAAQRI2AgALQQAPCwJAIAJBfUsNACACQf//A3FBCEYNACAAQQhqIgAEQCAAQQA2AgQgAEEQNgIAC0EADwsCQEGwwAAQCSIFBEAgBUEANgIIIAVCADcCACAFQYiBAUGogQEgAxs2AqhAIAUgAjYCFCAFIAM6ABAgBUEAOgAPIAVBADsBDCAFIAMgAkF9SyIGcToADiAFQQggAiAGG0H//wNxIAQgBUGIgQFBqIEBIAMbKAIAEQAAIgI2AqxAIAINASAFEDEgBRAGCyAAQQhqIgAEQCAAQQA2AgQgAEEONgIAC0EADwsgACABQTogBRBCIgAEfyAABSAFKAKsQCAFKAKoQCgCBBEDACAFEDEgBRAGQQALC6ABAQF/IAIgACgCBCIDIAIgA0kbIgIEQCAAIAMgAms2AgQCQAJAAkACQCAAKAIcIgMoAhRBAWsOAgEAAgsgA0GgAWogASAAKAIAIAJB3IABKAIAEQgADAILIAAgACgCMCABIAAoAgAgAkHEgAEoAgARBAA2AjAMAQsgASAAKAIAIAIQBxoLIAAgACgCACACajYCACAAIAAoAgggAmo2AggLC7cCAQR/QX4hAgJAIABFDQAgACgCIEUNACAAKAIkIgRFDQAgACgCHCIBRQ0AIAEoAgAgAEcNAAJAAkAgASgCICIDQTlrDjkBAgICAgICAgICAgIBAgICAQICAgICAgICAgICAgICAgICAQICAgICAgICAgICAQICAgICAgICAgEACyADQZoFRg0AIANBKkcN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DCABajYCDCAGIAYoAgggAWo2AgggBSAFKAIUIAFqNgIUIAUgBSgCECABazYCECAGIAYoAhAgAWsiATYCECABDQAgBiAGKAIENgIIC0EAIQRBACEJIAMoAhBFDQAMCgsgAygCHCgCJCEGIAMgAygCGCIBQQFqNgIYIAEgBmotAAAhASADIARBAWo2AhAgAygCBCAEaiABOgAAIAEEQCADKAIQIQQMAQsLIAMoAhwoAixFDQAgAygCECIGIAlNDQAgBQJ/IAUoAjAhBEEAIAMoAgQgCWoiAUUNABogBCABIAYgCWtB1IABKAIAEQAACzYCMAsgA0HnADYCIAsCQCADKAIcKAIsBEAgAygCDCADKAIQIgFBAmpJBH8gBRAKIAMoAhANAkEABSABCyADKAIEaiAFKAIwOwAAIAMgAygCEEECajYCECADQaABakHkgAEoAgARAQAaCyADQfEANgIgIAUQCiADKAIQRQ0BDAcLDAYLIAUoAgQNAQsgAygCPA0AIApFDQEgAygCIEGaBUYNAQsCfyADKAKIASIBRQRAIAMgChCFAQwBCwJAAkACQCADKAKMAUECaw4CAAECCwJ/AkADQAJAAkAgAygCPA0AIAMQLyADKAI8DQAgCg0BQQAMBAsgAygCSCADKAJoai0AACEEIAMgAygC8C0iAUEBajYC8C0gASADKALsLWpBADoAACADIAMoAvAtIgFBAWo2AvAtIAEgAygC7C1qQQA6AAAgAyADKALwLSIBQQFqNgLwLSABIAMoAuwtaiAEOgAAIAMgBEECdGoiASABLwHkAUEBajsB5AEgAyADKAI8QQFrNgI8IAMgAygCaEEBaiIBNgJoIAMoAvAtIAMoAvQtRw0BQQAhBCADIAMoAlgiBkEATgR/IAMoAkggBmoFQQALIAEgBmtBABAPIAMgAygCaDYCWCADKAIAEAogAygCACgCEA0BDAILCyADQQA2AoQuIApBBEYEQCADIAMoAlgiAUEATgR/IAMoAkggAWoFQQALIAMoAmggAWtBARAPIAMgAygCaDYCWCADKAIAEApBA0ECIAMoAgAoAhAbDAILIAMoAvAtBEBBACEEIAMgAygCWCIBQQBOBH8gAygCSCABagVBAAsgAygCaCABa0EAEA8gAyADKAJoNgJYIAMoAgAQCiADKAIAKAIQRQ0BC0EBIQQLIAQL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bGl0ZXJhbC9sZW5ndGhzIHNldABpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQAdW5rbm93biBoZWFkZXIgZmxhZ3Mgc2V0AGludmFsaWQgZGlzdGFuY2VzIHNldABpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0AEZpbGUgYWxyZWFkeSBleGlzdHMAdG9vIG1hbnkgbGVuZ3RoIG9yIGRpc3RhbmNlIHN5bWJvbHMAaW52YWxpZCBzdG9yZWQgYmxvY2sgbGVuZ3RocwAlcyVzJXMAYnVmZmVyIGVycm9yAE5vIGVycm9yAHN0cmVhbSBlcnJvcgBUZWxsIGVycm9yAEludGVybmFsIGVycm9yAFNlZWsgZXJyb3IAV3JpdGUgZXJyb3IAZmlsZSBlcnJvcgBSZWFkIGVycm9yAFpsaWIgZXJyb3IAZGF0YSBlcnJvcgBDUkMgZXJyb3IAaW5jb21wYXRpYmxlIHZlcnNpb24AaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrAGluY29ycmVjdCBoZWFkZXIgY2hlY2sAaW5jb3JyZWN0IGxlbmd0aCBjaGVjawBpbmNvcnJlY3QgZGF0YSBjaGVjawBpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjawBoZWFkZXIgY3JjIG1pc21hdGNoADEuMi4xMy56bGliLW5nAGludmFsaWQgd2luZG93IHNpemUAUmVhZC1vbmx5IGFyY2hpdmUATm90IGEgemlwIGFyY2hpdmUAUmVzb3VyY2Ugc3RpbGwgaW4gdXNlAE1hbGxvYyBmYWlsdXJlAGludmFsaWQgYmxvY2sgdHlwZQBGYWlsdXJlIHRvIGNyZWF0ZSB0ZW1wb3JhcnkgZmlsZQBDYW4ndCBvcGVuIGZpbGUATm8gc3VjaCBmaWxlAFByZW1hdHVyZSBlbmQgb2YgZmlsZQBDYW4ndCByZW1vdmUgZmlsZQBpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUAaW52YWxpZCBkaXN0YW5jZSBjb2RlAHVua25vd24gY29tcHJlc3Npb24gbWV0aG9kAHN0cmVhbSBlbmQAQ29tcHJlc3NlZCBkYXRhIGludmFsaWQATXVsdGktZGlzayB6aXAgYXJjaGl2ZXMgbm90IHN1cHBvcnRl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UgAIANIACAAyAAgAsgAIAHIACADyAAgACgAIAIoACABKAAgAygAIACoACACqAAgAagAIAOoACAAaAAgAmgAIAFoACADaAAgAOgAIALoACAB6AAgA+gAIAAYACACGAAgARgAIAMYACAAmAAgApgAIAGYACADmAAgAFgAIAJYACABWAAgA1gAIADYACAC2AAgAdgAIAPYACAAOAAgAjgAIAE4ACADOAAgALgAIAK4ACABuAAgA7gAIAB4ACACeAAgAXgAIAN4ACAA+AAgAvgAIAH4ACAD+AAgAAQAIAIEACABBAAgAwQAIACEACAChAAgAYQAIAOEACAARAAgAkQAIAFEACADRAAgAMQAIALEACABxAAgA8QAIAAkACACJAAgASQAIAMkACAApAAgAqQAIAGkACADpAAgAGQAIAJkACABZAAgA2QAIADkACAC5AAgAeQAIAPkACAAFAAgAhQAIAEUACADFAAgAJQAIAKUACABlAAgA5QAIABUACACVAAgAVQAIANUACAA1AAgAtQAIAHUACAD1AAgADQAIAI0ACABNAAgAzQAIAC0ACACtAAgAbQAIAO0ACAAdAAgAnQAIAF0ACADdAAgAPQAIAL0ACAB9AAgA/QAIABMACQATAQkAkwAJAJMBCQBTAAkAUwEJANMACQDTAQkAMwAJADMBCQCzAAkAswEJAHMACQBzAQkA8wAJAPMBCQALAAkACwEJAIsACQCLAQkASwAJAEsBCQDLAAkAywEJACsACQArAQkAqwAJAKsBCQBrAAkAawEJAOsACQDrAQkAGwAJABsBCQCbAAkAmwEJAFsACQBbAQkA2wAJANsBCQA7AAkAOwEJALsACQC7AQkAewAJAHsBCQD7AAkA+wEJAAcACQAHAQkAhwAJAIcBCQBHAAkARwEJAMcACQDHAQkAJwAJACcBCQCnAAkApwEJAGcACQBnAQkA5wAJAOcBCQAXAAkAFwEJAJcACQCXAQkAVwAJAFcBCQDXAAkA1wEJADcACQA3AQkAtwAJALcBCQB3AAkAdwEJAPcACQD3AQkADwAJAA8BCQCPAAkAjwEJAE8ACQBPAQkAzwAJAM8BCQAvAAkALwEJAK8ACQCvAQkAbwAJAG8BCQDvAAkA7wEJAB8ACQAfAQkAnwAJAJ8BCQBfAAkAXwEJAN8ACQDfAQkAPwAJAD8BCQC/AAkAvwEJAH8ACQB/AQkA/wAJAP8BCQAAAAcAQAAHACAABwBgAAcAEAAHAFAABwAwAAcAcAAHAAgABwBIAAcAKAAHAGgABwAYAAcAWAAHADgABwB4AAcABAAHAEQABwAkAAcAZAAHABQABwBUAAcANAAHAHQABwADAAgAgwAIAEMACADDAAgAIwAIAKMACABjAAgA4wAIAAAABQAQAAUACAAFABgABQAEAAUAFAAFAAwABQAcAAUAAgAFABIABQAKAAUAGgAFAAYABQAWAAUADgAFAB4ABQABAAUAEQAFAAkABQAZAAUABQAFABUABQANAAUAHQAFAAMABQATAAUACwAFABsABQAHAAUAFwAFAEGBywAL7AYBAgMEBAUFBgYGBgcHBwcICAgICAgICAkJCQkJCQkJCgoKCgoKCgoKCgoKCgoKCgsLCwsLCwsLCwsLCwsLCwsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8AABAREhITExQUFBQVFRUVFhYWFhYWFhYXFxcXFxcXFxgYGBgYGBgYGBgYGBgYGBgZGRkZGRkZGRkZGRkZGRkZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhobGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAAECAwQFBgcICAkJCgoLCwwMDAwNDQ0NDg4ODg8PDw8QEBAQEBAQEBEREREREREREhISEhISEhITExMTExMTExQUFBQUFBQUFBQUFBQUFBQVFRUVFRUVFRUVFRUVFRUVFhYWFhYWFhYWFhYWFhYWFhcXFxcXFxcXFxcXFxcXFxcYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhobGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbHAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAoAAAAMAAAADgAAABAAAAAUAAAAGAAAABwAAAAgAAAAKAAAADAAAAA4AAAAQAAAAFAAAABgAAAAcAAAAIAAAACgAAAAwAAAAOAAQYTSAAutAQEAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAAABAACAAQAAAAIAAAADAAAABAAAAAYAAAAIAAAADAAAABAAAAAYAAAAIAAAADAAAABAAAAAYAAAgCAAAMApAAABAQAAHgEAAA8AAAAAJQAAQCoAAAAAAAAeAAAADwAAAAAAAADAKgAAAAAAABMAAAAHAEHg0wALTQEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAQAAAAEAAAABAAAAAQAAAAFAAAABQAAAAUAAAAFAEHQ1AALZQEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAEGA1gALIwIAAAADAAAABwAAAAAAAAAQERIACAcJBgoFCwQMAw0CDgEPAEHQ1gALTQEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAQAAAAEAAAABAAAAAQAAAAFAAAABQAAAAUAAAAFAEHA1wALZQEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAEG42AALASwAQcTYAAthLQAAAAQABAAIAAQALgAAAAQABgAQAAYALwAAAAQADAAgABgALwAAAAgAEAAgACAALwAAAAgAEACAAIAALwAAAAgAIACAAAABMAAAACAAgAACAQAEMAAAACAAAgECAQAQMABBsNkAC6UTAwAEAAUABgAHAAgACQAKAAsADQAPABEAEwAXABsAHwAjACsAMwA7AEMAUwBjAHMAgwCjAMMA4wACAQAAAAAAABAAEAAQABAAEAAQABAAEAARABEAEQARABIAEgASABIAEwATABMAEwAUABQAFAAUABUAFQAVABUAEABNAMoAAAABAAIAAwAEAAUABwAJAA0AEQAZACEAMQBBAGEAgQDBAAEBgQEBAgEDAQQBBgEIAQwBEAEYASABMAFAAWAAAAAAEAAQABAAEAARABEAEgASABMAEwAUABQAFQAVABYAFgAXABcAGAAYABkAGQAaABoAGwAbABwAHAAdAB0AQABAAGAHAAAACFAAAAgQABQIcwASBx8AAAhwAAAIMAAACcAAEAcKAAAIYAAACCAAAAmgAAAIAAAACIAAAAhAAAAJ4AAQBwYAAAhYAAAIGAAACZAAEwc7AAAIeAAACDgAAAnQABEHEQAACGgAAAgoAAAJsAAACAgAAAiIAAAISAAACfAAEAcEAAAIVAAACBQAFQjjABMHKwAACHQAAAg0AAAJyAARBw0AAAhkAAAIJAAACagAAAgEAAAIhAAACEQAAAnoABAHCAAACFwAAAgcAAAJmAAUB1MAAAh8AAAIPAAACdgAEgcXAAAIbAAACCwAAAm4AAAIDAAACIwAAAhMAAAJ+AAQBwMAAAhSAAAIEgAVCKMAEwcjAAAIcgAACDIAAAnEABEHCwAACGIAAAgiAAAJpAAACAIAAAiCAAAIQgAACeQAEAcHAAAIWgAACBoAAAmUABQHQwAACHoAAAg6AAAJ1AASBxMAAAhqAAAIKgAACbQAAAgKAAAIigAACEoAAAn0ABAHBQAACFYAAAgWAEAIAAATBzMAAAh2AAAINgAACcwAEQcPAAAIZgAACCYAAAmsAAAIBgAACIYAAAhGAAAJ7AAQBwkAAAheAAAIHgAACZwAFAdjAAAIfgAACD4AAAncABIHGwAACG4AAAguAAAJvAAACA4AAAiOAAAITgAACfwAYAcAAAAIUQAACBEAFQiDABIHHwAACHEAAAgxAAAJwgAQBwoAAAhhAAAIIQAACaIAAAgBAAAIgQAACEEAAAniABAHBgAACFkAAAgZAAAJkgATBzsAAAh5AAAIOQAACdIAEQcRAAAIaQAACCkAAAmyAAAICQAACIkAAAhJAAAJ8gAQBwQAAAhVAAAIFQAQCAIBEwcrAAAIdQAACDUAAAnKABEHDQAACGUAAAglAAAJqgAACAUAAAiFAAAIRQAACeoAEAcIAAAIXQAACB0AAAmaABQHUwAACH0AAAg9AAAJ2gASBxcAAAhtAAAILQAACboAAAgNAAAIjQAACE0AAAn6ABAHAwAACFMAAAgTABUIwwATByMAAAhzAAAIMwAACcYAEQcLAAAIYwAACCMAAAmmAAAIAwAACIMAAAhDAAAJ5gAQBwcAAAhbAAAIGwAACZYAFAdDAAAIewAACDsAAAnWABIHEwAACGsAAAgrAAAJtgAACAsAAAiLAAAISwAACfYAEAcFAAAIVwAACBcAQAgAABMHMwAACHcAAAg3AAAJzgARBw8AAAhnAAAIJwAACa4AAAgHAAAIhwAACEcAAAnuABAHCQAACF8AAAgfAAAJngAUB2MAAAh/AAAIPwAACd4AEgcbAAAIbwAACC8AAAm+AAAIDwAACI8AAAhPAAAJ/gBgBwAAAAhQAAAIEAAUCHMAEgcfAAAIcAAACDAAAAnBABAHCgAACGAAAAggAAAJoQAACAAAAAiAAAAIQAAACeEAEAcGAAAIWAAACBgAAAmRABMHOwAACHgAAAg4AAAJ0QARBxEAAAhoAAAIKAAACbEAAAgIAAAIiAAACEgAAAnxABAHBAAACFQAAAgUABUI4wATBysAAAh0AAAINAAACckAEQcNAAAIZAAACCQAAAmpAAAIBAAACIQAAAhEAAAJ6QAQBwgAAAhcAAAIHAAACZkAFAdTAAAIfAAACDwAAAnZABIHFwAACGwAAAgsAAAJuQAACAwAAAiMAAAITAAACfkAEAcDAAAIUgAACBIAFQijABMHIwAACHIAAAgyAAAJxQARBwsAAAhiAAAIIgAACaUAAAgCAAAIggAACEIAAAnlABAHBwAACFoAAAgaAAAJlQAUB0MAAAh6AAAIOgAACdUAEgcTAAAIagAACCoAAAm1AAAICgAACIoAAAhKAAAJ9QAQBwUAAAhWAAAIFgBACAAAEwczAAAIdgAACDYAAAnNABEHDwAACGYAAAgmAAAJrQAACAYAAAiGAAAIRgAACe0AEAcJAAAIXgAACB4AAAmdABQHYwAACH4AAAg+AAAJ3QASBxsAAAhuAAAILgAACb0AAAgOAAAIjgAACE4AAAn9AGAHAAAACFEAAAgRABUIgwASBx8AAAhxAAAIMQAACcMAEAcKAAAIYQAACCEAAAmjAAAIAQAACIEAAAhBAAAJ4wAQBwYAAAhZAAAIGQAACZMAEwc7AAAIeQAACDkAAAnTABEHEQAACGkAAAgpAAAJswAACAkAAAiJAAAISQAACfMAEAcEAAAIVQAACBUAEAgCARMHKwAACHUAAAg1AAAJywARBw0AAAhlAAAIJQAACasAAAgFAAAIhQAACEUAAAnrABAHCAAACF0AAAgdAAAJmwAUB1MAAAh9AAAIPQAACdsAEgcXAAAIbQAACC0AAAm7AAAIDQAACI0AAAhNAAAJ+wAQBwMAAAhTAAAIEwAVCMMAEwcjAAAIcwAACDMAAAnHABEHCwAACGMAAAgjAAAJpwAACAMAAAiDAAAIQwAACecAEAcHAAAIWwAACBsAAAmXABQHQwAACHsAAAg7AAAJ1wASBxMAAAhrAAAIKwAACbcAAAgLAAAIiwAACEsAAAn3ABAHBQAACFcAAAgXAEAIAAATBzMAAAh3AAAINwAACc8AEQcPAAAIZwAACCcAAAmvAAAIBwAACIcAAAhHAAAJ7wAQBwkAAAhfAAAIHwAACZ8AFAdjAAAIfwAACD8AAAnfABIHGwAACG8AAAgvAAAJvwAACA8AAAiPAAAITwAACf8AEAUBABcFAQETBREAGwUBEBEFBQAZBQEEFQVBAB0FAUAQBQMAGAUBAhQFIQAcBQEgEgUJABoFAQgWBYEAQAUAABAFAgAXBYEBEwUZABsFARgRBQcAGQUBBhUFYQAdBQFgEAUEABgFAQMUBTEAHAUBMBIFDQAaBQEMFgXBAEAFAAAQABEAEgAAAAgABwAJAAYACgAFAAsABAAMAAMADQACAA4AAQAPAEHg7AALQREACgAREREAAAAABQAAAAAAAAkAAAAACwAAAAAAAAAAEQAPChEREQMKBwABAAkLCwAACQYLAAALAAYRAAAAERERAEGx7QALIQsAAAAAAAAAABEACgoREREACgAAAgAJCwAAAAkACwAACwBB6+0ACwEMAEH37QALFQwAAAAADAAAAAAJDAAAAAAADAAADABBpe4ACwEOAEGx7gALFQ0AAAAEDQAAAAAJDgAAAAAADgAADgBB3+4ACwEQAEHr7gALHg8AAAAADwAAAAAJEAAAAAAAEAAAEAAAEgAAABISEgBBou8ACw4SAAAAEhISAAAAAAAACQBB0+8ACwELAEHf7wALFQoAAAAACgAAAAAJCwAAAAAACwAACwBBjfAACwEMAEGZ8AALJwwAAAAADAAAAAAJDAAAAAAADAAADAAAMDEyMzQ1Njc4OUFCQ0RFRgBB5PAACwE+AEGL8QALBf//////AEHQ8QALVxkSRDsCPyxHFD0zMAobBkZLRTcPSQ6OFwNAHTxpKzYfSi0cASAlKSEIDBUWIi4QOD4LNDEYZHR1di9BCX85ESNDMkKJiosFBCYoJw0qHjWMBxpIkxOUlQBBsPIAC4oOSWxsZWdhbCBieXRlIHNlcXVlbmNlAERvbWFpbiBlcnJvcgBSZXN1bHQgbm90IHJlcHJlc2VudGFibGUATm90IGEgdHR5AFBlcm1pc3Npb24gZGVuaWVkAE9wZXJhdGlvbiBub3QgcGVybWl0dGVkAE5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnkATm8gc3VjaCBwcm9jZXNzAEZpbGUgZXhpc3RzAFZhbHVlIHRvbyBsYXJnZSBmb3IgZGF0YSB0eXBlAE5vIHNwYWNlIGxlZnQgb24gZGV2aWNlAE91dCBvZiBtZW1vcnkAUmVzb3VyY2UgYnVzeQBJbnRlcnJ1cHRlZCBzeXN0ZW0gY2FsbABSZXNvdXJjZSB0ZW1wb3JhcmlseSB1bmF2YWlsYWJsZQBJbnZhbGlkIHNlZWsAQ3Jvc3MtZGV2aWNlIGxpbmsAUmVhZC1vbmx5IGZpbGUgc3lzdGVtAERpcmVjdG9yeSBub3QgZW1wdHkAQ29ubmVjdGlvbiByZXNldCBieSBwZWVyAE9wZXJhdGlvbiB0aW1lZCBvdXQAQ29ubmVjdGlvbiByZWZ1c2VkAEhvc3QgaXMgZG93bgBIb3N0IGlzIHVucmVhY2hhYmxlAEFkZHJlc3MgaW4gdXNlAEJyb2tlbiBwaXBlAEkvTyBlcnJvcgBObyBzdWNoIGRldmljZSBvciBhZGRyZXNzAEJsb2NrIGRldmljZSByZXF1aXJlZABObyBzdWNoIGRldmljZQBOb3QgYSBkaXJlY3RvcnkASXMgYSBkaXJlY3RvcnkAVGV4dCBmaWxlIGJ1c3kARXhlYyBmb3JtYXQgZXJyb3IASW52YWxpZCBhcmd1bWVudABBcmd1bWVudCBsaXN0IHRvbyBsb25nAFN5bWJvbGljIGxpbmsgbG9vcABGaWxlbmFtZSB0b28gbG9uZwBUb28gbWFueSBvcGVuIGZpbGVzIGluIHN5c3RlbQBObyBmaWxlIGRlc2NyaXB0b3JzIGF2YWlsYWJsZQBCYWQgZmlsZSBkZXNjcmlwdG9yAE5vIGNoaWxkIHByb2Nlc3MAQmFkIGFkZHJlc3MARmlsZSB0b28gbGFyZ2UAVG9vIG1hbnkgbGlua3MATm8gbG9ja3MgYXZhaWxhYmxlAFJlc291cmNlIGRlYWRsb2NrIHdvdWxkIG9jY3VyAFN0YXRlIG5vdCByZWNvdmVyYWJsZQBQcmV2aW91cyBvd25lciBkaWVkAE9wZXJhdGlvbiBjYW5jZWxlZABGdW5jdGlvbiBub3QgaW1wbGVtZW50ZWQATm8gbWVzc2FnZSBvZiBkZXNpcmVkIHR5cGUASWRlbnRpZmllciByZW1vdmVkAERldmljZSBub3QgYSBzdHJlYW0ATm8gZGF0YSBhdmFpbGFibGUARGV2aWNlIHRpbWVvdXQAT3V0IG9mIHN0cmVhbXMgcmVzb3VyY2VzAExpbmsgaGFzIGJlZW4gc2V2ZXJlZABQcm90b2NvbCBlcnJvcgBCYWQgbWVzc2FnZQBGaWxlIGRlc2NyaXB0b3IgaW4gYmFkIHN0YXRlAE5vdCBhIHNvY2tldABEZXN0aW5hdGlvbiBhZGRyZXNzIHJlcXVpcmVkAE1lc3NhZ2UgdG9vIGxhcmdlAFByb3RvY29sIHdyb25nIHR5cGUgZm9yIHNvY2tldABQcm90b2NvbCBub3QgYXZhaWxhYmxlAFByb3RvY29sIG5vdCBzdXBwb3J0ZWQAU29ja2V0IHR5cGUgbm90IHN1cHBvcnRlZABOb3Qgc3VwcG9ydGVkAFByb3RvY29sIGZhbWlseSBub3Qgc3VwcG9ydGVkAEFkZHJlc3MgZmFtaWx5IG5vdCBzdXBwb3J0ZWQgYnkgcHJvdG9jb2wAQWRkcmVzcyBub3QgYXZhaWxhYmxlAE5ldHdvcmsgaXMgZG93bgBOZXR3b3JrIHVucmVhY2hhYmxlAENvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yawBDb25uZWN0aW9uIGFib3J0ZWQATm8gYnVmZmVyIHNwYWNlIGF2YWlsYWJsZQBTb2NrZXQgaXMgY29ubmVjdGVkAFNvY2tldCBub3QgY29ubmVjdGVkAENhbm5vdCBzZW5kIGFmdGVyIHNvY2tldCBzaHV0ZG93bgBPcGVyYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcwBPcGVyYXRpb24gaW4gcHJvZ3Jlc3MAU3RhbGUgZmlsZSBoYW5kbGUAUmVtb3RlIEkvTyBlcnJvcgBRdW90YSBleGNlZWRlZABObyBtZWRpdW0gZm91bmQAV3JvbmcgbWVkaXVtIHR5cGUATm8gZXJyb3IgaW5mb3JtYXRpb24AQcCAAQuFARMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAAjAAAAgERQADEAAAAyAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADIAAAAzAAAANAAAADUAAAA2AAAANwAAADgAQfSCAQsCXEQAQbCDAQsQ/////////////////////w==";Zs(xi)||(xi=x(xi));function Fs(ze){try{if(ze==xi&&ue)return new Uint8Array(ue);var it=ia(ze);if(it)return it;if(T)return T(ze);throw"sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)"}catch(vt){Hi(vt)}}function $s(ze,it){var vt,ar,ee;try{ee=Fs(ze),ar=new WebAssembly.Module(ee),vt=new WebAssembly.Instance(ar,it)}catch(Le){var ye=Le.toString();throw te("failed to compile wasm module: "+ye),(ye.includes("imported Memory")||ye.includes("memory import"))&&te("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."),Le}return[vt,ar]}function SA(){var ze={a:dc};function it(ee,ye){var Le=ee.exports;r.asm=Le,De=r.asm.g,J(De.buffer),$=r.asm.W,cn(r.asm.h),Xs("wasm-instantiate")}if($n("wasm-instantiate"),r.instantiateWasm)try{var vt=r.instantiateWasm(ze,it);return vt}catch(ee){return te("Module.instantiateWasm callback failed with error: "+ee),!1}var ar=$s(xi,ze);return it(ar[0]),r.asm}function gu(ze){return R.getFloat32(ze,!0)}function op(ze){return R.getFloat64(ze,!0)}function ap(ze){return R.getInt16(ze,!0)}function Rs(ze){return R.getInt32(ze,!0)}function Ln(ze,it){R.setInt32(ze,it,!0)}function hs(ze){for(;ze.length>0;){var it=ze.shift();if(typeof it=="function"){it(r);continue}var vt=it.func;typeof vt=="number"?it.arg===void 0?$.get(vt)():$.get(vt)(it.arg):vt(it.arg===void 0?null:it.arg)}}function Ts(ze,it){var vt=new Date(Rs((ze>>2)*4)*1e3);Ln((it>>2)*4,vt.getUTCSeconds()),Ln((it+4>>2)*4,vt.getUTCMinutes()),Ln((it+8>>2)*4,vt.getUTCHours()),Ln((it+12>>2)*4,vt.getUTCDate()),Ln((it+16>>2)*4,vt.getUTCMonth()),Ln((it+20>>2)*4,vt.getUTCFullYear()-1900),Ln((it+24>>2)*4,vt.getUTCDay()),Ln((it+36>>2)*4,0),Ln((it+32>>2)*4,0);var ar=Date.UTC(vt.getUTCFullYear(),0,1,0,0,0,0),ee=(vt.getTime()-ar)/(1e3*60*60*24)|0;return Ln((it+28>>2)*4,ee),Ts.GMTString||(Ts.GMTString=nt("GMT")),Ln((it+40>>2)*4,Ts.GMTString),it}function pc(ze,it){return Ts(ze,it)}function hc(ze,it,vt){Se.copyWithin(ze,it,it+vt)}function gc(ze){try{return De.grow(ze-ke.byteLength+65535>>>16),J(De.buffer),1}catch{}}function bA(ze){var it=Se.length;ze=ze>>>0;var vt=2147483648;if(ze>vt)return!1;for(var ar=1;ar<=4;ar*=2){var ee=it*(1+.2/ar);ee=Math.min(ee,ze+100663296);var ye=Math.min(vt,Te(Math.max(ze,ee),65536)),Le=gc(ye);if(Le)return!0}return!1}function xA(ze){ce(ze)}function Ro(ze){var it=Date.now()/1e3|0;return ze&&Ln((ze>>2)*4,it),it}function To(){if(To.called)return;To.called=!0;var ze=new Date().getFullYear(),it=new Date(ze,0,1),vt=new Date(ze,6,1),ar=it.getTimezoneOffset(),ee=vt.getTimezoneOffset(),ye=Math.max(ar,ee);Ln((ja()>>2)*4,ye*60),Ln((rs()>>2)*4,+(ar!=ee));function Le(sn){var ei=sn.toTimeString().match(/\(([A-Za-z ]+)\)$/);return ei?ei[1]:"GMT"}var ht=Le(it),mt=Le(vt),Dt=nt(ht),er=nt(mt);ee>2)*4,Dt),Ln((Di()+4>>2)*4,er)):(Ln((Di()>>2)*4,er),Ln((Di()+4>>2)*4,Dt))}function kA(ze){To();var it=Date.UTC(Rs((ze+20>>2)*4)+1900,Rs((ze+16>>2)*4),Rs((ze+12>>2)*4),Rs((ze+8>>2)*4),Rs((ze+4>>2)*4),Rs((ze>>2)*4),0),vt=new Date(it);Ln((ze+24>>2)*4,vt.getUTCDay());var ar=Date.UTC(vt.getUTCFullYear(),0,1,0,0,0,0),ee=(vt.getTime()-ar)/(1e3*60*60*24)|0;return Ln((ze+28>>2)*4,ee),vt.getTime()/1e3|0}var pr=typeof atob=="function"?atob:function(ze){var it="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",vt="",ar,ee,ye,Le,ht,mt,Dt,er=0;ze=ze.replace(/[^A-Za-z0-9\+\/\=]/g,"");do Le=it.indexOf(ze.charAt(er++)),ht=it.indexOf(ze.charAt(er++)),mt=it.indexOf(ze.charAt(er++)),Dt=it.indexOf(ze.charAt(er++)),ar=Le<<2|ht>>4,ee=(ht&15)<<4|mt>>2,ye=(mt&3)<<6|Dt,vt=vt+String.fromCharCode(ar),mt!==64&&(vt=vt+String.fromCharCode(ee)),Dt!==64&&(vt=vt+String.fromCharCode(ye));while(er0||(Et(),yr>0))return;function it(){Dn||(Dn=!0,r.calledRun=!0,!Ee&&(qt(),o(r),r.onRuntimeInitialized&&r.onRuntimeInitialized(),nr()))}r.setStatus?(r.setStatus("Running..."),setTimeout(function(){setTimeout(function(){r.setStatus("")},1),it()},1)):it()}if(r.run=Sl,r.preInit)for(typeof r.preInit=="function"&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();return Sl(),e}}();typeof ux=="object"&&typeof OU=="object"?OU.exports=MU:typeof define=="function"&&define.amd?define([],function(){return MU}):typeof ux=="object"&&(ux.createModule=MU)});var Nf,Ice,Bce,vce=wt(()=>{Nf=["number","number"],Ice=(Z=>(Z[Z.ZIP_ER_OK=0]="ZIP_ER_OK",Z[Z.ZIP_ER_MULTIDISK=1]="ZIP_ER_MULTIDISK",Z[Z.ZIP_ER_RENAME=2]="ZIP_ER_RENAME",Z[Z.ZIP_ER_CLOSE=3]="ZIP_ER_CLOSE",Z[Z.ZIP_ER_SEEK=4]="ZIP_ER_SEEK",Z[Z.ZIP_ER_READ=5]="ZIP_ER_READ",Z[Z.ZIP_ER_WRITE=6]="ZIP_ER_WRITE",Z[Z.ZIP_ER_CRC=7]="ZIP_ER_CRC",Z[Z.ZIP_ER_ZIPCLOSED=8]="ZIP_ER_ZIPCLOSED",Z[Z.ZIP_ER_NOENT=9]="ZIP_ER_NOENT",Z[Z.ZIP_ER_EXISTS=10]="ZIP_ER_EXISTS",Z[Z.ZIP_ER_OPEN=11]="ZIP_ER_OPEN",Z[Z.ZIP_ER_TMPOPEN=12]="ZIP_ER_TMPOPEN",Z[Z.ZIP_ER_ZLIB=13]="ZIP_ER_ZLIB",Z[Z.ZIP_ER_MEMORY=14]="ZIP_ER_MEMORY",Z[Z.ZIP_ER_CHANGED=15]="ZIP_ER_CHANGED",Z[Z.ZIP_ER_COMPNOTSUPP=16]="ZIP_ER_COMPNOTSUPP",Z[Z.ZIP_ER_EOF=17]="ZIP_ER_EOF",Z[Z.ZIP_ER_INVAL=18]="ZIP_ER_INVAL",Z[Z.ZIP_ER_NOZIP=19]="ZIP_ER_NOZIP",Z[Z.ZIP_ER_INTERNAL=20]="ZIP_ER_INTERNAL",Z[Z.ZIP_ER_INCONS=21]="ZIP_ER_INCONS",Z[Z.ZIP_ER_REMOVE=22]="ZIP_ER_REMOVE",Z[Z.ZIP_ER_DELETED=23]="ZIP_ER_DELETED",Z[Z.ZIP_ER_ENCRNOTSUPP=24]="ZIP_ER_ENCRNOTSUPP",Z[Z.ZIP_ER_RDONLY=25]="ZIP_ER_RDONLY",Z[Z.ZIP_ER_NOPASSWD=26]="ZIP_ER_NOPASSWD",Z[Z.ZIP_ER_WRONGPASSWD=27]="ZIP_ER_WRONGPASSWD",Z[Z.ZIP_ER_OPNOTSUPP=28]="ZIP_ER_OPNOTSUPP",Z[Z.ZIP_ER_INUSE=29]="ZIP_ER_INUSE",Z[Z.ZIP_ER_TELL=30]="ZIP_ER_TELL",Z[Z.ZIP_ER_COMPRESSED_DATA=31]="ZIP_ER_COMPRESSED_DATA",Z))(Ice||{}),Bce=t=>({get HEAPU8(){return t.HEAPU8},errors:Ice,SEEK_SET:0,SEEK_CUR:1,SEEK_END:2,ZIP_CHECKCONS:4,ZIP_EXCL:2,ZIP_RDONLY:16,ZIP_FL_OVERWRITE:8192,ZIP_FL_COMPRESSED:4,ZIP_OPSYS_DOS:0,ZIP_OPSYS_AMIGA:1,ZIP_OPSYS_OPENVMS:2,ZIP_OPSYS_UNIX:3,ZIP_OPSYS_VM_CMS:4,ZIP_OPSYS_ATARI_ST:5,ZIP_OPSYS_OS_2:6,ZIP_OPSYS_MACINTOSH:7,ZIP_OPSYS_Z_SYSTEM:8,ZIP_OPSYS_CPM:9,ZIP_OPSYS_WINDOWS_NTFS:10,ZIP_OPSYS_MVS:11,ZIP_OPSYS_VSE:12,ZIP_OPSYS_ACORN_RISC:13,ZIP_OPSYS_VFAT:14,ZIP_OPSYS_ALTERNATE_MVS:15,ZIP_OPSYS_BEOS:16,ZIP_OPSYS_TANDEM:17,ZIP_OPSYS_OS_400:18,ZIP_OPSYS_OS_X:19,ZIP_CM_DEFAULT:-1,ZIP_CM_STORE:0,ZIP_CM_DEFLATE:8,uint08S:t._malloc(1),uint32S:t._malloc(4),malloc:t._malloc,free:t._free,getValue:t.getValue,openFromSource:t.cwrap("zip_open_from_source","number",["number","number","number"]),close:t.cwrap("zip_close","number",["number"]),discard:t.cwrap("zip_discard",null,["number"]),getError:t.cwrap("zip_get_error","number",["number"]),getName:t.cwrap("zip_get_name","string",["number","number","number"]),getNumEntries:t.cwrap("zip_get_num_entries","number",["number","number"]),delete:t.cwrap("zip_delete","number",["number","number"]),statIndex:t.cwrap("zip_stat_index","number",["number",...Nf,"number","number"]),fopenIndex:t.cwrap("zip_fopen_index","number",["number",...Nf,"number"]),fread:t.cwrap("zip_fread","number",["number","number","number","number"]),fclose:t.cwrap("zip_fclose","number",["number"]),dir:{add:t.cwrap("zip_dir_add","number",["number","string"])},file:{add:t.cwrap("zip_file_add","number",["number","string","number","number"]),getError:t.cwrap("zip_file_get_error","number",["number"]),getExternalAttributes:t.cwrap("zip_file_get_external_attributes","number",["number",...Nf,"number","number","number"]),setExternalAttributes:t.cwrap("zip_file_set_external_attributes","number",["number",...Nf,"number","number","number"]),setMtime:t.cwrap("zip_file_set_mtime","number",["number",...Nf,"number","number"]),setCompression:t.cwrap("zip_set_file_compression","number",["number",...Nf,"number","number"])},ext:{countSymlinks:t.cwrap("zip_ext_count_symlinks","number",["number"])},error:{initWithCode:t.cwrap("zip_error_init_with_code",null,["number","number"]),strerror:t.cwrap("zip_error_strerror","string",["number"])},name:{locate:t.cwrap("zip_name_locate","number",["number","string","number"])},source:{fromUnattachedBuffer:t.cwrap("zip_source_buffer_create","number",["number",...Nf,"number","number"]),fromBuffer:t.cwrap("zip_source_buffer","number",["number","number",...Nf,"number"]),free:t.cwrap("zip_source_free",null,["number"]),keep:t.cwrap("zip_source_keep",null,["number"]),open:t.cwrap("zip_source_open","number",["number"]),close:t.cwrap("zip_source_close","number",["number"]),seek:t.cwrap("zip_source_seek","number",["number",...Nf,"number"]),tell:t.cwrap("zip_source_tell","number",["number"]),read:t.cwrap("zip_source_read","number",["number","number","number"]),error:t.cwrap("zip_source_error","number",["number"])},struct:{statS:t.cwrap("zipstruct_statS","number",[]),statSize:t.cwrap("zipstruct_stat_size","number",["number"]),statCompSize:t.cwrap("zipstruct_stat_comp_size","number",["number"]),statCompMethod:t.cwrap("zipstruct_stat_comp_method","number",["number"]),statMtime:t.cwrap("zipstruct_stat_mtime","number",["number"]),statCrc:t.cwrap("zipstruct_stat_crc","number",["number"]),errorS:t.cwrap("zipstruct_errorS","number",[]),errorCodeZip:t.cwrap("zipstruct_error_code_zip","number",["number"])}})});function UU(t,e){let r=t.indexOf(e);if(r<=0)return null;let o=r;for(;r>=0&&(o=r+e.length,t[o]!==K.sep);){if(t[r-1]===K.sep)return null;r=t.indexOf(e,o)}return t.length>o&&t[o]!==K.sep?null:t.slice(0,o)}var iA,Dce=wt(()=>{Pt();Pt();sA();iA=class t extends Gp{static async openPromise(e,r){let o=new t(r);try{return await e(o)}finally{o.saveAndClose()}}constructor(e={}){let r=e.fileExtensions,o=e.readOnlyArchives,a=typeof r>"u"?A=>UU(A,".zip"):A=>{for(let p of r){let h=UU(A,p);if(h)return h}return null},n=(A,p)=>new Zi(p,{baseFs:A,readOnly:o,stats:A.statSync(p)}),u=async(A,p)=>{let h={baseFs:A,readOnly:o,stats:await A.statPromise(p)};return()=>new Zi(p,h)};super({...e,factorySync:n,factoryPromise:u,getMountPoint:a})}}});function tot(t){if(typeof t=="string"&&String(+t)===t)return+t;if(typeof t=="number"&&Number.isFinite(t))return t<0?Date.now()/1e3:t;if(Pce.types.isDate(t))return t.getTime()/1e3;throw new Error("Invalid time")}function Ax(){return Buffer.from([80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])}var ta,_U,Pce,HU,Sce,fx,Zi,qU=wt(()=>{Pt();Pt();Pt();Pt();Pt();Pt();ta=ve("fs"),_U=ve("stream"),Pce=ve("util"),HU=et(ve("zlib"));LU();Sce="mixed";fx=class extends Error{constructor(e,r){super(e),this.name="Libzip Error",this.code=r}},Zi=class extends qu{constructor(r,o={}){super();this.listings=new Map;this.entries=new Map;this.fileSources=new Map;this.fds=new Map;this.nextFd=0;this.ready=!1;this.readOnly=!1;let a=o;if(this.level=typeof a.level<"u"?a.level:Sce,r??=Ax(),typeof r=="string"){let{baseFs:A=new _n}=a;this.baseFs=A,this.path=r}else this.path=null,this.baseFs=null;if(o.stats)this.stats=o.stats;else if(typeof r=="string")try{this.stats=this.baseFs.statSync(r)}catch(A){if(A.code==="ENOENT"&&a.create)this.stats=Ia.makeDefaultStats();else throw A}else this.stats=Ia.makeDefaultStats();this.libzip=K1();let n=this.libzip.malloc(4);try{let A=0;o.readOnly&&(A|=this.libzip.ZIP_RDONLY,this.readOnly=!0),typeof r=="string"&&(r=a.create?Ax():this.baseFs.readFileSync(r));let p=this.allocateUnattachedSource(r);try{this.zip=this.libzip.openFromSource(p,A,n),this.lzSource=p}catch(h){throw this.libzip.source.free(p),h}if(this.zip===0){let h=this.libzip.struct.errorS();throw this.libzip.error.initWithCode(h,this.libzip.getValue(n,"i32")),this.makeLibzipError(h)}}finally{this.libzip.free(n)}this.listings.set(Bt.root,new Set);let u=this.libzip.getNumEntries(this.zip,0);for(let A=0;Ar)throw new Error("Overread");let n=Buffer.from(this.libzip.HEAPU8.subarray(o,o+r));return process.env.YARN_IS_TEST_ENV&&process.env.YARN_ZIP_DATA_EPILOGUE&&(n=Buffer.concat([n,Buffer.from(process.env.YARN_ZIP_DATA_EPILOGUE)])),n}finally{this.libzip.free(o)}}finally{this.libzip.source.close(this.lzSource),this.libzip.source.free(this.lzSource),this.ready=!1}}discardAndClose(){this.prepareClose(),this.libzip.discard(this.zip),this.ready=!1}saveAndClose(){if(!this.path||!this.baseFs)throw new Error("ZipFS cannot be saved and must be discarded when loaded from a buffer");if(this.readOnly){this.discardAndClose();return}let r=this.baseFs.existsSync(this.path)||this.stats.mode===Ia.DEFAULT_MODE?void 0:this.stats.mode;this.baseFs.writeFileSync(this.path,this.getBufferAndClose(),{mode:r}),this.ready=!1}resolve(r){return K.resolve(Bt.root,r)}async openPromise(r,o,a){return this.openSync(r,o,a)}openSync(r,o,a){let n=this.nextFd++;return this.fds.set(n,{cursor:0,p:r}),n}hasOpenFileHandles(){return!!this.fds.size}async opendirPromise(r,o){return this.opendirSync(r,o)}opendirSync(r,o={}){let a=this.resolveFilename(`opendir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`opendir '${r}'`);let n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`opendir '${r}'`);let u=[...n],A=this.openSync(a,"r");return eP(this,a,u,{onClose:()=>{this.closeSync(A)}})}async readPromise(r,o,a,n,u){return this.readSync(r,o,a,n,u)}readSync(r,o,a=0,n=o.byteLength,u=-1){let A=this.fds.get(r);if(typeof A>"u")throw sr.EBADF("read");let p=u===-1||u===null?A.cursor:u,h=this.readFileSync(A.p);h.copy(o,a,p,p+n);let E=Math.max(0,Math.min(h.length-p,n));return(u===-1||u===null)&&(A.cursor+=E),E}async writePromise(r,o,a,n,u){return typeof o=="string"?this.writeSync(r,o,u):this.writeSync(r,o,a,n,u)}writeSync(r,o,a,n,u){throw typeof this.fds.get(r)>"u"?sr.EBADF("read"):new Error("Unimplemented")}async closePromise(r){return this.closeSync(r)}closeSync(r){if(typeof this.fds.get(r)>"u")throw sr.EBADF("read");this.fds.delete(r)}createReadStream(r,{encoding:o}={}){if(r===null)throw new Error("Unimplemented");let a=this.openSync(r,"r"),n=Object.assign(new _U.PassThrough({emitClose:!0,autoDestroy:!0,destroy:(A,p)=>{clearImmediate(u),this.closeSync(a),p(A)}}),{close(){n.destroy()},bytesRead:0,path:r,pending:!1}),u=setImmediate(async()=>{try{let A=await this.readFilePromise(r,o);n.bytesRead=A.length,n.end(A)}catch(A){n.destroy(A)}});return n}createWriteStream(r,{encoding:o}={}){if(this.readOnly)throw sr.EROFS(`open '${r}'`);if(r===null)throw new Error("Unimplemented");let a=[],n=this.openSync(r,"w"),u=Object.assign(new _U.PassThrough({autoDestroy:!0,emitClose:!0,destroy:(A,p)=>{try{A?p(A):(this.writeFileSync(r,Buffer.concat(a),o),p(null))}catch(h){p(h)}finally{this.closeSync(n)}}}),{close(){u.destroy()},bytesWritten:0,path:r,pending:!1});return u.on("data",A=>{let p=Buffer.from(A);u.bytesWritten+=p.length,a.push(p)}),u}async realpathPromise(r){return this.realpathSync(r)}realpathSync(r){let o=this.resolveFilename(`lstat '${r}'`,r);if(!this.entries.has(o)&&!this.listings.has(o))throw sr.ENOENT(`lstat '${r}'`);return o}async existsPromise(r){return this.existsSync(r)}existsSync(r){if(!this.ready)throw sr.EBUSY(`archive closed, existsSync '${r}'`);if(this.symlinkCount===0){let a=K.resolve(Bt.root,r);return this.entries.has(a)||this.listings.has(a)}let o;try{o=this.resolveFilename(`stat '${r}'`,r,void 0,!1)}catch{return!1}return o===void 0?!1:this.entries.has(o)||this.listings.has(o)}async accessPromise(r,o){return this.accessSync(r,o)}accessSync(r,o=ta.constants.F_OK){let a=this.resolveFilename(`access '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`access '${r}'`);if(this.readOnly&&o&ta.constants.W_OK)throw sr.EROFS(`access '${r}'`)}async statPromise(r,o={bigint:!1}){return o.bigint?this.statSync(r,{bigint:!0}):this.statSync(r)}statSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`stat '${r}'`,r,void 0,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw sr.ENOENT(`stat '${r}'`)}if(r[r.length-1]==="/"&&!this.listings.has(a))throw sr.ENOTDIR(`stat '${r}'`);return this.statImpl(`stat '${r}'`,a,o)}}async fstatPromise(r,o){return this.fstatSync(r,o)}fstatSync(r,o){let a=this.fds.get(r);if(typeof a>"u")throw sr.EBADF("fstatSync");let{p:n}=a,u=this.resolveFilename(`stat '${n}'`,n);if(!this.entries.has(u)&&!this.listings.has(u))throw sr.ENOENT(`stat '${n}'`);if(n[n.length-1]==="/"&&!this.listings.has(u))throw sr.ENOTDIR(`stat '${n}'`);return this.statImpl(`fstat '${n}'`,u,o)}async lstatPromise(r,o={bigint:!1}){return o.bigint?this.lstatSync(r,{bigint:!0}):this.lstatSync(r)}lstatSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`lstat '${r}'`,r,!1,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw sr.ENOENT(`lstat '${r}'`)}if(r[r.length-1]==="/"&&!this.listings.has(a))throw sr.ENOTDIR(`lstat '${r}'`);return this.statImpl(`lstat '${r}'`,a,o)}}statImpl(r,o,a={}){let n=this.entries.get(o);if(typeof n<"u"){let u=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,n,0,0,u)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let p=this.stats.uid,h=this.stats.gid,E=this.libzip.struct.statSize(u)>>>0,I=512,D=Math.ceil(E/I),x=(this.libzip.struct.statMtime(u)>>>0)*1e3,C=x,T=x,L=x,U=new Date(C),z=new Date(T),te=new Date(L),le=new Date(x),ce=this.listings.has(o)?ta.constants.S_IFDIR:this.isSymbolicLink(n)?ta.constants.S_IFLNK:ta.constants.S_IFREG,ue=ce===ta.constants.S_IFDIR?493:420,Ce=ce|this.getUnixMode(n,ue)&511,he=this.libzip.struct.statCrc(u),De=Object.assign(new Ia.StatEntry,{uid:p,gid:h,size:E,blksize:I,blocks:D,atime:U,birthtime:z,ctime:te,mtime:le,atimeMs:C,birthtimeMs:T,ctimeMs:L,mtimeMs:x,mode:Ce,crc:he});return a.bigint===!0?Ia.convertToBigIntStats(De):De}if(this.listings.has(o)){let u=this.stats.uid,A=this.stats.gid,p=0,h=512,E=0,I=this.stats.mtimeMs,D=this.stats.mtimeMs,x=this.stats.mtimeMs,C=this.stats.mtimeMs,T=new Date(I),L=new Date(D),U=new Date(x),z=new Date(C),te=ta.constants.S_IFDIR|493,ce=Object.assign(new Ia.StatEntry,{uid:u,gid:A,size:p,blksize:h,blocks:E,atime:T,birthtime:L,ctime:U,mtime:z,atimeMs:I,birthtimeMs:D,ctimeMs:x,mtimeMs:C,mode:te,crc:0});return a.bigint===!0?Ia.convertToBigIntStats(ce):ce}throw new Error("Unreachable")}getUnixMode(r,o){if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,"i8")>>>0!==this.libzip.ZIP_OPSYS_UNIX?o:this.libzip.getValue(this.libzip.uint32S,"i32")>>>16}registerListing(r){let o=this.listings.get(r);if(o)return o;this.registerListing(K.dirname(r)).add(K.basename(r));let n=new Set;return this.listings.set(r,n),n}registerEntry(r,o){this.registerListing(K.dirname(r)).add(K.basename(r)),this.entries.set(r,o)}unregisterListing(r){this.listings.delete(r),this.listings.get(K.dirname(r))?.delete(K.basename(r))}unregisterEntry(r){this.unregisterListing(r);let o=this.entries.get(r);this.entries.delete(r),!(typeof o>"u")&&(this.fileSources.delete(o),this.isSymbolicLink(o)&&this.symlinkCount--)}deleteEntry(r,o){if(this.unregisterEntry(r),this.libzip.delete(this.zip,o)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}resolveFilename(r,o,a=!0,n=!0){if(!this.ready)throw sr.EBUSY(`archive closed, ${r}`);let u=K.resolve(Bt.root,o);if(u==="/")return Bt.root;let A=this.entries.get(u);if(a&&A!==void 0)if(this.symlinkCount!==0&&this.isSymbolicLink(A)){let p=this.getFileSource(A).toString();return this.resolveFilename(r,K.resolve(K.dirname(u),p),!0,n)}else return u;for(;;){let p=this.resolveFilename(r,K.dirname(u),!0,n);if(p===void 0)return p;let h=this.listings.has(p),E=this.entries.has(p);if(!h&&!E){if(n===!1)return;throw sr.ENOENT(r)}if(!h)throw sr.ENOTDIR(r);if(u=K.resolve(p,K.basename(u)),!a||this.symlinkCount===0)break;let I=this.libzip.name.locate(this.zip,u.slice(1),0);if(I===-1)break;if(this.isSymbolicLink(I)){let D=this.getFileSource(I).toString();u=K.resolve(K.dirname(u),D)}else break}return u}allocateBuffer(r){Buffer.isBuffer(r)||(r=Buffer.from(r));let o=this.libzip.malloc(r.byteLength);if(!o)throw new Error("Couldn't allocate enough memory");return new Uint8Array(this.libzip.HEAPU8.buffer,o,r.byteLength).set(r),{buffer:o,byteLength:r.byteLength}}allocateUnattachedSource(r){let o=this.libzip.struct.errorS(),{buffer:a,byteLength:n}=this.allocateBuffer(r),u=this.libzip.source.fromUnattachedBuffer(a,n,0,1,o);if(u===0)throw this.libzip.free(o),this.makeLibzipError(o);return u}allocateSource(r){let{buffer:o,byteLength:a}=this.allocateBuffer(r),n=this.libzip.source.fromBuffer(this.zip,o,a,0,1);if(n===0)throw this.libzip.free(o),this.makeLibzipError(this.libzip.getError(this.zip));return n}setFileSource(r,o){let a=Buffer.isBuffer(o)?o:Buffer.from(o),n=K.relative(Bt.root,r),u=this.allocateSource(o);try{let A=this.libzip.file.add(this.zip,n,u,this.libzip.ZIP_FL_OVERWRITE);if(A===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.level!=="mixed"){let p=this.level===0?this.libzip.ZIP_CM_STORE:this.libzip.ZIP_CM_DEFLATE;if(this.libzip.file.setCompression(this.zip,A,0,p,this.level)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}return this.fileSources.set(A,a),A}catch(A){throw this.libzip.source.free(u),A}}isSymbolicLink(r){if(this.symlinkCount===0)return!1;if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,"i8")>>>0!==this.libzip.ZIP_OPSYS_UNIX?!1:(this.libzip.getValue(this.libzip.uint32S,"i32")>>>16&ta.constants.S_IFMT)===ta.constants.S_IFLNK}getFileSource(r,o={asyncDecompress:!1}){let a=this.fileSources.get(r);if(typeof a<"u")return a;let n=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,r,0,0,n)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let A=this.libzip.struct.statCompSize(n),p=this.libzip.struct.statCompMethod(n),h=this.libzip.malloc(A);try{let E=this.libzip.fopenIndex(this.zip,r,0,this.libzip.ZIP_FL_COMPRESSED);if(E===0)throw this.makeLibzipError(this.libzip.getError(this.zip));try{let I=this.libzip.fread(E,h,A,0);if(I===-1)throw this.makeLibzipError(this.libzip.file.getError(E));if(IA)throw new Error("Overread");let D=this.libzip.HEAPU8.subarray(h,h+A),x=Buffer.from(D);if(p===0)return this.fileSources.set(r,x),x;if(o.asyncDecompress)return new Promise((C,T)=>{HU.default.inflateRaw(x,(L,U)=>{L?T(L):(this.fileSources.set(r,U),C(U))})});{let C=HU.default.inflateRawSync(x);return this.fileSources.set(r,C),C}}finally{this.libzip.fclose(E)}}finally{this.libzip.free(h)}}async fchmodPromise(r,o){return this.chmodPromise(this.fdToPath(r,"fchmod"),o)}fchmodSync(r,o){return this.chmodSync(this.fdToPath(r,"fchmodSync"),o)}async chmodPromise(r,o){return this.chmodSync(r,o)}chmodSync(r,o){if(this.readOnly)throw sr.EROFS(`chmod '${r}'`);o&=493;let a=this.resolveFilename(`chmod '${r}'`,r,!1),n=this.entries.get(a);if(typeof n>"u")throw new Error(`Assertion failed: The entry should have been registered (${a})`);let A=this.getUnixMode(n,ta.constants.S_IFREG|0)&-512|o;if(this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,A<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async fchownPromise(r,o,a){return this.chownPromise(this.fdToPath(r,"fchown"),o,a)}fchownSync(r,o,a){return this.chownSync(this.fdToPath(r,"fchownSync"),o,a)}async chownPromise(r,o,a){return this.chownSync(r,o,a)}chownSync(r,o,a){throw new Error("Unimplemented")}async renamePromise(r,o){return this.renameSync(r,o)}renameSync(r,o){throw new Error("Unimplemented")}async copyFilePromise(r,o,a){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=await this.getFileSource(n,{asyncDecompress:!0}),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}copyFileSync(r,o,a=0){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=this.getFileSource(n),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}prepareCopyFile(r,o,a=0){if(this.readOnly)throw sr.EROFS(`copyfile '${r} -> '${o}'`);if(a&ta.constants.COPYFILE_FICLONE_FORCE)throw sr.ENOSYS("unsupported clone operation",`copyfile '${r}' -> ${o}'`);let n=this.resolveFilename(`copyfile '${r} -> ${o}'`,r),u=this.entries.get(n);if(typeof u>"u")throw sr.EINVAL(`copyfile '${r}' -> '${o}'`);let A=this.resolveFilename(`copyfile '${r}' -> ${o}'`,o),p=this.entries.get(A);if(a&(ta.constants.COPYFILE_EXCL|ta.constants.COPYFILE_FICLONE_FORCE)&&typeof p<"u")throw sr.EEXIST(`copyfile '${r}' -> '${o}'`);return{indexSource:u,resolvedDestP:A,indexDest:p}}async appendFilePromise(r,o,a){if(this.readOnly)throw sr.EROFS(`open '${r}'`);return typeof a>"u"?a={flag:"a"}:typeof a=="string"?a={flag:"a",encoding:a}:typeof a.flag>"u"&&(a={flag:"a",...a}),this.writeFilePromise(r,o,a)}appendFileSync(r,o,a={}){if(this.readOnly)throw sr.EROFS(`open '${r}'`);return typeof a>"u"?a={flag:"a"}:typeof a=="string"?a={flag:"a",encoding:a}:typeof a.flag>"u"&&(a={flag:"a",...a}),this.writeFileSync(r,o,a)}fdToPath(r,o){let a=this.fds.get(r)?.p;if(typeof a>"u")throw sr.EBADF(o);return a}async writeFilePromise(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a=="object"&&a.flag&&a.flag.includes("a")&&(o=Buffer.concat([await this.getFileSource(A,{asyncDecompress:!0}),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&await this.chmodPromise(p,u)}writeFileSync(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a=="object"&&a.flag&&a.flag.includes("a")&&(o=Buffer.concat([this.getFileSource(A),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&this.chmodSync(p,u)}prepareWriteFile(r,o){if(typeof r=="number"&&(r=this.fdToPath(r,"read")),this.readOnly)throw sr.EROFS(`open '${r}'`);let a=this.resolveFilename(`open '${r}'`,r);if(this.listings.has(a))throw sr.EISDIR(`open '${r}'`);let n=null,u=null;typeof o=="string"?n=o:typeof o=="object"&&({encoding:n=null,mode:u=null}=o);let A=this.entries.get(a);return{encoding:n,mode:u,resolvedP:a,index:A}}async unlinkPromise(r){return this.unlinkSync(r)}unlinkSync(r){if(this.readOnly)throw sr.EROFS(`unlink '${r}'`);let o=this.resolveFilename(`unlink '${r}'`,r);if(this.listings.has(o))throw sr.EISDIR(`unlink '${r}'`);let a=this.entries.get(o);if(typeof a>"u")throw sr.EINVAL(`unlink '${r}'`);this.deleteEntry(o,a)}async utimesPromise(r,o,a){return this.utimesSync(r,o,a)}utimesSync(r,o,a){if(this.readOnly)throw sr.EROFS(`utimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r);this.utimesImpl(n,a)}async lutimesPromise(r,o,a){return this.lutimesSync(r,o,a)}lutimesSync(r,o,a){if(this.readOnly)throw sr.EROFS(`lutimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r,!1);this.utimesImpl(n,a)}utimesImpl(r,o){this.listings.has(r)&&(this.entries.has(r)||this.hydrateDirectory(r));let a=this.entries.get(r);if(a===void 0)throw new Error("Unreachable");if(this.libzip.file.setMtime(this.zip,a,0,tot(o),0)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async mkdirPromise(r,o){return this.mkdirSync(r,o)}mkdirSync(r,{mode:o=493,recursive:a=!1}={}){if(a)return this.mkdirpSync(r,{chmod:o});if(this.readOnly)throw sr.EROFS(`mkdir '${r}'`);let n=this.resolveFilename(`mkdir '${r}'`,r);if(this.entries.has(n)||this.listings.has(n))throw sr.EEXIST(`mkdir '${r}'`);this.hydrateDirectory(n),this.chmodSync(n,o)}async rmdirPromise(r,o){return this.rmdirSync(r,o)}rmdirSync(r,{recursive:o=!1}={}){if(this.readOnly)throw sr.EROFS(`rmdir '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rmdir '${r}'`,r),n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`rmdir '${r}'`);if(n.size>0)throw sr.ENOTEMPTY(`rmdir '${r}'`);let u=this.entries.get(a);if(typeof u>"u")throw sr.EINVAL(`rmdir '${r}'`);this.deleteEntry(r,u)}async rmPromise(r,o){return this.rmSync(r,o)}rmSync(r,{recursive:o=!1}={}){if(this.readOnly)throw sr.EROFS(`rm '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rm '${r}'`,r),n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`rm '${r}'`);if(n.size>0)throw sr.ENOTEMPTY(`rm '${r}'`);let u=this.entries.get(a);if(typeof u>"u")throw sr.EINVAL(`rm '${r}'`);this.deleteEntry(r,u)}hydrateDirectory(r){let o=this.libzip.dir.add(this.zip,K.relative(Bt.root,r));if(o===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.registerListing(r),this.registerEntry(r,o),o}async linkPromise(r,o){return this.linkSync(r,o)}linkSync(r,o){throw sr.EOPNOTSUPP(`link '${r}' -> '${o}'`)}async symlinkPromise(r,o){return this.symlinkSync(r,o)}symlinkSync(r,o){if(this.readOnly)throw sr.EROFS(`symlink '${r}' -> '${o}'`);let a=this.resolveFilename(`symlink '${r}' -> '${o}'`,o);if(this.listings.has(a))throw sr.EISDIR(`symlink '${r}' -> '${o}'`);if(this.entries.has(a))throw sr.EEXIST(`symlink '${r}' -> '${o}'`);let n=this.setFileSource(a,r);if(this.registerEntry(a,n),this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,(ta.constants.S_IFLNK|511)<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));this.symlinkCount+=1}async readFilePromise(r,o){typeof o=="object"&&(o=o?o.encoding:void 0);let a=await this.readFileBuffer(r,{asyncDecompress:!0});return o?a.toString(o):a}readFileSync(r,o){typeof o=="object"&&(o=o?o.encoding:void 0);let a=this.readFileBuffer(r);return o?a.toString(o):a}readFileBuffer(r,o={asyncDecompress:!1}){typeof r=="number"&&(r=this.fdToPath(r,"read"));let a=this.resolveFilename(`open '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`open '${r}'`);if(r[r.length-1]==="/"&&!this.listings.has(a))throw sr.ENOTDIR(`open '${r}'`);if(this.listings.has(a))throw sr.EISDIR("read");let n=this.entries.get(a);if(n===void 0)throw new Error("Unreachable");return this.getFileSource(n,o)}async readdirPromise(r,o){return this.readdirSync(r,o)}readdirSync(r,o){let a=this.resolveFilename(`scandir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`scandir '${r}'`);let n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`scandir '${r}'`);if(o?.recursive)if(o?.withFileTypes){let u=Array.from(n,A=>Object.assign(this.statImpl("lstat",K.join(r,A)),{name:A,path:Bt.dot}));for(let A of u){if(!A.isDirectory())continue;let p=K.join(A.path,A.name),h=this.listings.get(K.join(a,p));for(let E of h)u.push(Object.assign(this.statImpl("lstat",K.join(r,p,E)),{name:E,path:p}))}return u}else{let u=[...n];for(let A of u){let p=this.listings.get(K.join(a,A));if(!(typeof p>"u"))for(let h of p)u.push(K.join(A,h))}return u}else return o?.withFileTypes?Array.from(n,u=>Object.assign(this.statImpl("lstat",K.join(r,u)),{name:u,path:void 0})):[...n]}async readlinkPromise(r){let o=this.prepareReadlink(r);return(await this.getFileSource(o,{asyncDecompress:!0})).toString()}readlinkSync(r){let o=this.prepareReadlink(r);return this.getFileSource(o).toString()}prepareReadlink(r){let o=this.resolveFilename(`readlink '${r}'`,r,!1);if(!this.entries.has(o)&&!this.listings.has(o))throw sr.ENOENT(`readlink '${r}'`);if(r[r.length-1]==="/"&&!this.listings.has(o))throw sr.ENOTDIR(`open '${r}'`);if(this.listings.has(o))throw sr.EINVAL(`readlink '${r}'`);let a=this.entries.get(o);if(a===void 0)throw new Error("Unreachable");if(!this.isSymbolicLink(a))throw sr.EINVAL(`readlink '${r}'`);return a}async truncatePromise(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>"u")throw sr.EINVAL(`open '${r}'`);let u=await this.getFileSource(n,{asyncDecompress:!0}),A=Buffer.alloc(o,0);return u.copy(A),await this.writeFilePromise(r,A)}truncateSync(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>"u")throw sr.EINVAL(`open '${r}'`);let u=this.getFileSource(n),A=Buffer.alloc(o,0);return u.copy(A),this.writeFileSync(r,A)}async ftruncatePromise(r,o){return this.truncatePromise(this.fdToPath(r,"ftruncate"),o)}ftruncateSync(r,o){return this.truncateSync(this.fdToPath(r,"ftruncateSync"),o)}watch(r,o,a){let n;switch(typeof o){case"function":case"string":case"undefined":n=!0;break;default:({persistent:n=!0}=o);break}if(!n)return{on:()=>{},close:()=>{}};let u=setInterval(()=>{},24*60*60*1e3);return{on:()=>{},close:()=>{clearInterval(u)}}}watchFile(r,o,a){let n=K.resolve(Bt.root,r);return um(this,n,o,a)}unwatchFile(r,o){let a=K.resolve(Bt.root,r);return q0(this,a,o)}}});function xce(t,e,r=Buffer.alloc(0),o){let a=new Zi(r),n=I=>I===e||I.startsWith(`${e}/`)?I.slice(0,e.length):null,u=async(I,D)=>()=>a,A=(I,D)=>a,p={...t},h=new _n(p),E=new Gp({baseFs:h,getMountPoint:n,factoryPromise:u,factorySync:A,magicByte:21,maxAge:1/0,typeCheck:o?.typeCheck});return uI(bce.default,new Yp(E)),a}var bce,kce=wt(()=>{Pt();bce=et(ve("fs"));qU()});var Qce=wt(()=>{Dce();qU();kce()});var V1={};Kt(V1,{DEFAULT_COMPRESSION_LEVEL:()=>Sce,LibzipError:()=>fx,ZipFS:()=>Zi,ZipOpenFS:()=>iA,getArchivePart:()=>UU,getLibzipPromise:()=>not,getLibzipSync:()=>rot,makeEmptyArchive:()=>Ax,mountMemoryDrive:()=>xce});function rot(){return K1()}async function not(){return K1()}var Fce,sA=wt(()=>{LU();Fce=et(wce());vce();Qce();Cce(()=>{let t=(0,Fce.default)();return Bce(t)})});var z1,Rce=wt(()=>{Pt();Gt();J1();z1=class extends st{constructor(){super(...arguments);this.cwd=de.String("--cwd",process.cwd(),{description:"The directory to run the command in"});this.commandName=de.String();this.args=de.Proxy()}static{this.usage={description:"run a command using yarn's portable shell",details:` + This command will run a command using Yarn's portable shell. + + Make sure to escape glob patterns, redirections, and other features that might be expanded by your own shell. + + Note: To escape something from Yarn's shell, you might have to escape it twice, the first time from your own shell. + + Note: Don't use this command in Yarn scripts, as Yarn's shell is automatically used. + + For a list of features, visit: https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-shell/README.md. + `,examples:[["Run a simple command","$0 echo Hello"],["Run a command with a glob pattern","$0 echo '*.js'"],["Run a command with a redirection","$0 echo Hello World '>' hello.txt"],["Run a command with an escaped glob pattern (The double escape is needed in Unix shells)",`$0 echo '"*.js"'`],["Run a command with a variable (Double quotes are needed in Unix shells, to prevent them from expanding the variable)",'$0 "GREETING=Hello echo $GREETING World"']]}}async execute(){let r=this.args.length>0?`${this.commandName} ${this.args.join(" ")}`:this.commandName;return await ky(r,[],{cwd:Ae.toPortablePath(this.cwd),stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}}});var fl,Tce=wt(()=>{fl=class extends Error{constructor(e){super(e),this.name="ShellError"}}});var gx={};Kt(gx,{fastGlobOptions:()=>Mce,isBraceExpansion:()=>jU,isGlobPattern:()=>iot,match:()=>sot,micromatchOptions:()=>hx});function iot(t){if(!px.default.scan(t,hx).isGlob)return!1;try{px.default.parse(t,hx)}catch{return!1}return!0}function sot(t,{cwd:e,baseFs:r}){return(0,Nce.default)(t,{...Mce,cwd:Ae.fromPortablePath(e),fs:aP(Lce.default,new Yp(r))})}function jU(t){return px.default.scan(t,hx).isBrace}var Nce,Lce,px,hx,Mce,Oce=wt(()=>{Pt();Nce=et(Ab()),Lce=et(ve("fs")),px=et(Xo()),hx={strictBrackets:!0},Mce={onlyDirectories:!1,onlyFiles:!1}});function GU(){}function YU(){for(let t of Fg)t.kill()}function qce(t,e,r,o){return a=>{let n=a[0]instanceof oA.Transform?"pipe":a[0],u=a[1]instanceof oA.Transform?"pipe":a[1],A=a[2]instanceof oA.Transform?"pipe":a[2],p=(0,_ce.default)(t,e,{...o,stdio:[n,u,A]});return Fg.add(p),Fg.size===1&&(process.on("SIGINT",GU),process.on("SIGTERM",YU)),a[0]instanceof oA.Transform&&a[0].pipe(p.stdin),a[1]instanceof oA.Transform&&p.stdout.pipe(a[1],{end:!1}),a[2]instanceof oA.Transform&&p.stderr.pipe(a[2],{end:!1}),{stdin:p.stdin,promise:new Promise(h=>{p.on("error",E=>{switch(Fg.delete(p),Fg.size===0&&(process.off("SIGINT",GU),process.off("SIGTERM",YU)),E.code){case"ENOENT":a[2].write(`command not found: ${t} +`),h(127);break;case"EACCES":a[2].write(`permission denied: ${t} +`),h(128);break;default:a[2].write(`uncaught error: ${E.message} +`),h(1);break}}),p.on("close",E=>{Fg.delete(p),Fg.size===0&&(process.off("SIGINT",GU),process.off("SIGTERM",YU)),h(E!==null?E:129)})})}}}function jce(t){return e=>{let r=e[0]==="pipe"?new oA.PassThrough:e[0];return{stdin:r,promise:Promise.resolve().then(()=>t({stdin:r,stdout:e[1],stderr:e[2]}))}}}function dx(t,e){return KU.start(t,e)}function Uce(t,e=null){let r=new oA.PassThrough,o=new Hce.StringDecoder,a="";return r.on("data",n=>{let u=o.write(n),A;do if(A=u.indexOf(` +`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a="",t(e!==null?`${e} ${p}`:p)}while(A!==-1);a+=u}),r.on("end",()=>{let n=o.end();n!==""&&t(e!==null?`${e} ${n}`:n)}),r}function Gce(t,{prefix:e}){return{stdout:Uce(r=>t.stdout.write(`${r} +`),t.stdout.isTTY?e:null),stderr:Uce(r=>t.stderr.write(`${r} +`),t.stderr.isTTY?e:null)}}var _ce,oA,Hce,Fg,Zl,WU,KU,VU=wt(()=>{_ce=et(OT()),oA=ve("stream"),Hce=ve("string_decoder"),Fg=new Set;Zl=class{constructor(e){this.stream=e}close(){}get(){return this.stream}},WU=class{constructor(){this.stream=null}close(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");this.stream.end()}attach(e){this.stream=e}get(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");return this.stream}},KU=class t{constructor(e,r){this.stdin=null;this.stdout=null;this.stderr=null;this.pipe=null;this.ancestor=e,this.implementation=r}static start(e,{stdin:r,stdout:o,stderr:a}){let n=new t(null,e);return n.stdin=r,n.stdout=o,n.stderr=a,n}pipeTo(e,r=1){let o=new t(this,e),a=new WU;return o.pipe=a,o.stdout=this.stdout,o.stderr=this.stderr,(r&1)===1?this.stdout=a:this.ancestor!==null&&(this.stderr=this.ancestor.stdout),(r&2)===2?this.stderr=a:this.ancestor!==null&&(this.stderr=this.ancestor.stderr),o}async exec(){let e=["ignore","ignore","ignore"];if(this.pipe)e[0]="pipe";else{if(this.stdin===null)throw new Error("Assertion failed: No input stream registered");e[0]=this.stdin.get()}let r;if(this.stdout===null)throw new Error("Assertion failed: No output stream registered");r=this.stdout,e[1]=r.get();let o;if(this.stderr===null)throw new Error("Assertion failed: No error stream registered");o=this.stderr,e[2]=o.get();let a=this.implementation(e);return this.pipe&&this.pipe.attach(a.stdin),await a.promise.then(n=>(r.close(),o.close(),n))}async run(){let e=[];for(let o=this;o;o=o.ancestor)e.push(o.exec());return(await Promise.all(e))[0]}}});var e2={};Kt(e2,{EntryCommand:()=>z1,ShellError:()=>fl,execute:()=>ky,globUtils:()=>gx});function Yce(t,e,r){let o=new pl.PassThrough({autoDestroy:!0});switch(t){case 0:(e&1)===1&&r.stdin.pipe(o,{end:!1}),(e&2)===2&&r.stdin instanceof pl.Writable&&o.pipe(r.stdin,{end:!1});break;case 1:(e&1)===1&&r.stdout.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stdout,{end:!1});break;case 2:(e&1)===1&&r.stderr.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stderr,{end:!1});break;default:throw new fl(`Bad file descriptor: "${t}"`)}return o}function yx(t,e={}){let r={...t,...e};return r.environment={...t.environment,...e.environment},r.variables={...t.variables,...e.variables},r}async function aot(t,e,r){let o=[],a=new pl.PassThrough;return a.on("data",n=>o.push(n)),await Ex(t,e,yx(r,{stdout:a})),Buffer.concat(o).toString().replace(/[\r\n]+$/,"")}async function Wce(t,e,r){let o=t.map(async n=>{let u=await Rg(n.args,e,r);return{name:n.name,value:u.join(" ")}});return(await Promise.all(o)).reduce((n,u)=>(n[u.name]=u.value,n),{})}function mx(t){return t.match(/[^ \r\n\t]+/g)||[]}async function Zce(t,e,r,o,a=o){switch(t.name){case"$":o(String(process.pid));break;case"#":o(String(e.args.length));break;case"@":if(t.quoted)for(let n of e.args)a(n);else for(let n of e.args){let u=mx(n);for(let A=0;A=0&&n"u"&&(t.defaultValue?u=(await Rg(t.defaultValue,e,r)).join(" "):t.alternativeValue&&(u="")),typeof u>"u")throw A?new fl(`Unbound argument #${n}`):new fl(`Unbound variable "${t.name}"`);if(t.quoted)o(u);else{let p=mx(u);for(let E=0;Eo.push(n));let a=Number(o.join(" "));return Number.isNaN(a)?X1({type:"variable",name:o.join(" ")},e,r):X1({type:"number",value:a},e,r)}else return lot[t.type](await X1(t.left,e,r),await X1(t.right,e,r))}async function Rg(t,e,r){let o=new Map,a=[],n=[],u=E=>{n.push(E)},A=()=>{n.length>0&&a.push(n.join("")),n=[]},p=E=>{u(E),A()},h=(E,I,D)=>{let x=JSON.stringify({type:E,fd:I}),C=o.get(x);typeof C>"u"&&o.set(x,C=[]),C.push(D)};for(let E of t){let I=!1;switch(E.type){case"redirection":{let D=await Rg(E.args,e,r);for(let x of D)h(E.subtype,E.fd,x)}break;case"argument":for(let D of E.segments)switch(D.type){case"text":u(D.text);break;case"glob":u(D.pattern),I=!0;break;case"shell":{let x=await aot(D.shell,e,r);if(D.quoted)u(x);else{let C=mx(x);for(let T=0;T"u")throw new Error("Assertion failed: Expected a glob pattern to have been set");let x=await e.glob.match(D,{cwd:r.cwd,baseFs:e.baseFs});if(x.length===0){let C=jU(D)?". Note: Brace expansion of arbitrary strings isn't currently supported. For more details, please read this issue: https://github.com/yarnpkg/berry/issues/22":"";throw new fl(`No matches found: "${D}"${C}`)}for(let C of x.sort())p(C)}}if(o.size>0){let E=[];for(let[I,D]of o.entries())E.splice(E.length,0,I,String(D.length),...D);a.splice(0,0,"__ysh_set_redirects",...E,"--")}return a}function Z1(t,e,r){e.builtins.has(t[0])||(t=["command",...t]);let o=Ae.fromPortablePath(r.cwd),a=r.environment;typeof a.PWD<"u"&&(a={...a,PWD:o});let[n,...u]=t;if(n==="command")return qce(u[0],u.slice(1),e,{cwd:o,env:a});let A=e.builtins.get(n);if(typeof A>"u")throw new Error(`Assertion failed: A builtin should exist for "${n}"`);return jce(async({stdin:p,stdout:h,stderr:E})=>{let{stdin:I,stdout:D,stderr:x}=r;r.stdin=p,r.stdout=h,r.stderr=E;try{return await A(u,e,r)}finally{r.stdin=I,r.stdout=D,r.stderr=x}})}function cot(t,e,r){return o=>{let a=new pl.PassThrough,n=Ex(t,e,yx(r,{stdin:a}));return{stdin:a,promise:n}}}function uot(t,e,r){return o=>{let a=new pl.PassThrough,n=Ex(t,e,r);return{stdin:a,promise:n}}}function Kce(t,e,r,o){if(e.length===0)return t;{let a;do a=String(Math.random());while(Object.hasOwn(o.procedures,a));return o.procedures={...o.procedures},o.procedures[a]=t,Z1([...e,"__ysh_run_procedure",a],r,o)}}async function Vce(t,e,r){let o=t,a=null,n=null;for(;o;){let u=o.then?{...r}:r,A;switch(o.type){case"command":{let p=await Rg(o.args,e,r),h=await Wce(o.envs,e,r);A=o.envs.length?Z1(p,e,yx(u,{environment:h})):Z1(p,e,u)}break;case"subshell":{let p=await Rg(o.args,e,r),h=cot(o.subshell,e,u);A=Kce(h,p,e,u)}break;case"group":{let p=await Rg(o.args,e,r),h=uot(o.group,e,u);A=Kce(h,p,e,u)}break;case"envs":{let p=await Wce(o.envs,e,r);u.environment={...u.environment,...p},A=Z1(["true"],e,u)}break}if(typeof A>"u")throw new Error("Assertion failed: An action should have been generated");if(a===null)n=dx(A,{stdin:new Zl(u.stdin),stdout:new Zl(u.stdout),stderr:new Zl(u.stderr)});else{if(n===null)throw new Error("Assertion failed: The execution pipeline should have been setup");switch(a){case"|":n=n.pipeTo(A,1);break;case"|&":n=n.pipeTo(A,3);break}}o.then?(a=o.then.type,o=o.then.chain):o=null}if(n===null)throw new Error("Assertion failed: The execution pipeline should have been setup");return await n.run()}async function Aot(t,e,r,{background:o=!1}={}){function a(n){let u=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],A=u[n%u.length];return zce.default.hex(A)}if(o){let n=r.nextBackgroundJobIndex++,u=a(n),A=`[${n}]`,p=u(A),{stdout:h,stderr:E}=Gce(r,{prefix:p});return r.backgroundJobs.push(Vce(t,e,yx(r,{stdout:h,stderr:E})).catch(I=>E.write(`${I.message} +`)).finally(()=>{r.stdout.isTTY&&r.stdout.write(`Job ${p}, '${u(mm(t))}' has ended +`)})),0}return await Vce(t,e,r)}async function fot(t,e,r,{background:o=!1}={}){let a,n=A=>{a=A,r.variables["?"]=String(A)},u=async A=>{try{return await Aot(A.chain,e,r,{background:o&&typeof A.then>"u"})}catch(p){if(!(p instanceof fl))throw p;return r.stderr.write(`${p.message} +`),1}};for(n(await u(t));t.then;){if(r.exitCode!==null)return r.exitCode;switch(t.then.type){case"&&":a===0&&n(await u(t.then.line));break;case"||":a!==0&&n(await u(t.then.line));break;default:throw new Error(`Assertion failed: Unsupported command type: "${t.then.type}"`)}t=t.then.line}return a}async function Ex(t,e,r){let o=r.backgroundJobs;r.backgroundJobs=[];let a=0;for(let{command:n,type:u}of t){if(a=await fot(n,e,r,{background:u==="&"}),r.exitCode!==null)return r.exitCode;r.variables["?"]=String(a)}return await Promise.all(r.backgroundJobs),r.backgroundJobs=o,a}function $ce(t){switch(t.type){case"variable":return t.name==="@"||t.name==="#"||t.name==="*"||Number.isFinite(parseInt(t.name,10))||"defaultValue"in t&&!!t.defaultValue&&t.defaultValue.some(e=>$1(e))||"alternativeValue"in t&&!!t.alternativeValue&&t.alternativeValue.some(e=>$1(e));case"arithmetic":return zU(t.arithmetic);case"shell":return JU(t.shell);default:return!1}}function $1(t){switch(t.type){case"redirection":return t.args.some(e=>$1(e));case"argument":return t.segments.some(e=>$ce(e));default:throw new Error(`Assertion failed: Unsupported argument type: "${t.type}"`)}}function zU(t){switch(t.type){case"variable":return $ce(t);case"number":return!1;default:return zU(t.left)||zU(t.right)}}function JU(t){return t.some(({command:e})=>{for(;e;){let r=e.chain;for(;r;){let o;switch(r.type){case"subshell":o=JU(r.subshell);break;case"command":o=r.envs.some(a=>a.args.some(n=>$1(n)))||r.args.some(a=>$1(a));break}if(o)return!0;if(!r.then)break;r=r.then.chain}if(!e.then)break;e=e.then.line}return!1})}async function ky(t,e=[],{baseFs:r=new _n,builtins:o={},cwd:a=Ae.toPortablePath(process.cwd()),env:n=process.env,stdin:u=process.stdin,stdout:A=process.stdout,stderr:p=process.stderr,variables:h={},glob:E=gx}={}){let I={};for(let[C,T]of Object.entries(n))typeof T<"u"&&(I[C]=T);let D=new Map(oot);for(let[C,T]of Object.entries(o))D.set(C,T);u===null&&(u=new pl.PassThrough,u.end());let x=uP(t,E);if(!JU(x)&&x.length>0&&e.length>0){let{command:C}=x[x.length-1];for(;C.then;)C=C.then.line;let T=C.chain;for(;T.then;)T=T.then.chain;T.type==="command"&&(T.args=T.args.concat(e.map(L=>({type:"argument",segments:[{type:"text",text:L}]}))))}return await Ex(x,{args:e,baseFs:r,builtins:D,initialStdin:u,initialStdout:A,initialStderr:p,glob:E},{cwd:a,environment:I,exitCode:null,procedures:{},stdin:u,stdout:A,stderr:p,variables:Object.assign({},h,{"?":0}),nextBackgroundJobIndex:1,backgroundJobs:[]})}var zce,Jce,pl,Xce,oot,lot,J1=wt(()=>{Pt();Ml();zce=et(iL()),Jce=ve("os"),pl=ve("stream"),Xce=ve("timers/promises");Rce();Tce();Oce();VU();VU();oot=new Map([["cd",async([t=(0,Jce.homedir)(),...e],r,o)=>{let a=K.resolve(o.cwd,Ae.toPortablePath(t));if(!(await r.baseFs.statPromise(a).catch(u=>{throw u.code==="ENOENT"?new fl(`cd: no such file or directory: ${t}`):u})).isDirectory())throw new fl(`cd: not a directory: ${t}`);return o.cwd=a,0}],["pwd",async(t,e,r)=>(r.stdout.write(`${Ae.fromPortablePath(r.cwd)} +`),0)],[":",async(t,e,r)=>0],["true",async(t,e,r)=>0],["false",async(t,e,r)=>1],["exit",async([t,...e],r,o)=>o.exitCode=parseInt(t??o.variables["?"],10)],["echo",async(t,e,r)=>(r.stdout.write(`${t.join(" ")} +`),0)],["sleep",async([t],e,r)=>{if(typeof t>"u")throw new fl("sleep: missing operand");let o=Number(t);if(Number.isNaN(o))throw new fl(`sleep: invalid time interval '${t}'`);return await(0,Xce.setTimeout)(1e3*o,0)}],["unset",async(t,e,r)=>{for(let o of t)delete r.environment[o],delete r.variables[o];return 0}],["__ysh_run_procedure",async(t,e,r)=>{let o=r.procedures[t[0]];return await dx(o,{stdin:new Zl(r.stdin),stdout:new Zl(r.stdout),stderr:new Zl(r.stderr)}).run()}],["__ysh_set_redirects",async(t,e,r)=>{let o=r.stdin,a=r.stdout,n=r.stderr,u=[],A=[],p=[],h=0;for(;t[h]!=="--";){let I=t[h++],{type:D,fd:x}=JSON.parse(I),C=z=>{switch(x){case null:case 0:u.push(z);break;default:throw new Error(`Unsupported file descriptor: "${x}"`)}},T=z=>{switch(x){case null:case 1:A.push(z);break;case 2:p.push(z);break;default:throw new Error(`Unsupported file descriptor: "${x}"`)}},L=Number(t[h++]),U=h+L;for(let z=h;ze.baseFs.createReadStream(K.resolve(r.cwd,Ae.toPortablePath(t[z]))));break;case"<<<":C(()=>{let te=new pl.PassThrough;return process.nextTick(()=>{te.write(`${t[z]} +`),te.end()}),te});break;case"<&":C(()=>Yce(Number(t[z]),1,r));break;case">":case">>":{let te=K.resolve(r.cwd,Ae.toPortablePath(t[z]));T(te==="/dev/null"?new pl.Writable({autoDestroy:!0,emitClose:!0,write(le,ce,ue){setImmediate(ue)}}):e.baseFs.createWriteStream(te,D===">>"?{flags:"a"}:void 0))}break;case">&":T(Yce(Number(t[z]),2,r));break;default:throw new Error(`Assertion failed: Unsupported redirection type: "${D}"`)}}if(u.length>0){let I=new pl.PassThrough;o=I;let D=x=>{if(x===u.length)I.end();else{let C=u[x]();C.pipe(I,{end:!1}),C.on("end",()=>{D(x+1)})}};D(0)}if(A.length>0){let I=new pl.PassThrough;a=I;for(let D of A)I.pipe(D)}if(p.length>0){let I=new pl.PassThrough;n=I;for(let D of p)I.pipe(D)}let E=await dx(Z1(t.slice(h+1),e,r),{stdin:new Zl(o),stdout:new Zl(a),stderr:new Zl(n)}).run();return await Promise.all(A.map(I=>new Promise((D,x)=>{I.on("error",C=>{x(C)}),I.on("close",()=>{D()}),I.end()}))),await Promise.all(p.map(I=>new Promise((D,x)=>{I.on("error",C=>{x(C)}),I.on("close",()=>{D()}),I.end()}))),E}]]);lot={addition:(t,e)=>t+e,subtraction:(t,e)=>t-e,multiplication:(t,e)=>t*e,division:(t,e)=>Math.trunc(t/e)}});var Cx=_((OOt,eue)=>{function pot(t,e){for(var r=-1,o=t==null?0:t.length,a=Array(o);++r{var tue=dg(),hot=Cx(),got=jl(),dot=fy(),mot=1/0,rue=tue?tue.prototype:void 0,nue=rue?rue.toString:void 0;function iue(t){if(typeof t=="string")return t;if(got(t))return hot(t,iue)+"";if(dot(t))return nue?nue.call(t):"";var e=t+"";return e=="0"&&1/t==-mot?"-0":e}sue.exports=iue});var t2=_((_Ot,aue)=>{var yot=oue();function Eot(t){return t==null?"":yot(t)}aue.exports=Eot});var XU=_((HOt,lue)=>{function Cot(t,e,r){var o=-1,a=t.length;e<0&&(e=-e>a?0:a+e),r=r>a?a:r,r<0&&(r+=a),a=e>r?0:r-e>>>0,e>>>=0;for(var n=Array(a);++o{var wot=XU();function Iot(t,e,r){var o=t.length;return r=r===void 0?o:r,!e&&r>=o?t:wot(t,e,r)}cue.exports=Iot});var ZU=_((jOt,Aue)=>{var Bot="\\ud800-\\udfff",vot="\\u0300-\\u036f",Dot="\\ufe20-\\ufe2f",Pot="\\u20d0-\\u20ff",Sot=vot+Dot+Pot,bot="\\ufe0e\\ufe0f",xot="\\u200d",kot=RegExp("["+xot+Bot+Sot+bot+"]");function Qot(t){return kot.test(t)}Aue.exports=Qot});var pue=_((GOt,fue)=>{function Fot(t){return t.split("")}fue.exports=Fot});var wue=_((YOt,Cue)=>{var hue="\\ud800-\\udfff",Rot="\\u0300-\\u036f",Tot="\\ufe20-\\ufe2f",Not="\\u20d0-\\u20ff",Lot=Rot+Tot+Not,Mot="\\ufe0e\\ufe0f",Oot="["+hue+"]",$U="["+Lot+"]",e3="\\ud83c[\\udffb-\\udfff]",Uot="(?:"+$U+"|"+e3+")",gue="[^"+hue+"]",due="(?:\\ud83c[\\udde6-\\uddff]){2}",mue="[\\ud800-\\udbff][\\udc00-\\udfff]",_ot="\\u200d",yue=Uot+"?",Eue="["+Mot+"]?",Hot="(?:"+_ot+"(?:"+[gue,due,mue].join("|")+")"+Eue+yue+")*",qot=Eue+yue+Hot,jot="(?:"+[gue+$U+"?",$U,due,mue,Oot].join("|")+")",Got=RegExp(e3+"(?="+e3+")|"+jot+qot,"g");function Yot(t){return t.match(Got)||[]}Cue.exports=Yot});var Bue=_((WOt,Iue)=>{var Wot=pue(),Kot=ZU(),Vot=wue();function zot(t){return Kot(t)?Vot(t):Wot(t)}Iue.exports=zot});var Due=_((KOt,vue)=>{var Jot=uue(),Xot=ZU(),Zot=Bue(),$ot=t2();function eat(t){return function(e){e=$ot(e);var r=Xot(e)?Zot(e):void 0,o=r?r[0]:e.charAt(0),a=r?Jot(r,1).join(""):e.slice(1);return o[t]()+a}}vue.exports=eat});var Sue=_((VOt,Pue)=>{var tat=Due(),rat=tat("toUpperCase");Pue.exports=rat});var t3=_((zOt,bue)=>{var nat=t2(),iat=Sue();function sat(t){return iat(nat(t).toLowerCase())}bue.exports=sat});var xue=_((JOt,wx)=>{function oat(){var t=0,e=1,r=2,o=3,a=4,n=5,u=6,A=7,p=8,h=9,E=10,I=11,D=12,x=13,C=14,T=15,L=16,U=17,z=0,te=1,le=2,ce=3,ue=4;function Ce(g,me){return 55296<=g.charCodeAt(me)&&g.charCodeAt(me)<=56319&&56320<=g.charCodeAt(me+1)&&g.charCodeAt(me+1)<=57343}function he(g,me){me===void 0&&(me=0);var we=g.charCodeAt(me);if(55296<=we&&we<=56319&&me=1){var fe=g.charCodeAt(me-1),ie=we;return 55296<=fe&&fe<=56319?(fe-55296)*1024+(ie-56320)+65536:ie}return we}function De(g,me,we){var fe=[g].concat(me).concat([we]),ie=fe[fe.length-2],Z=we,xe=fe.lastIndexOf(C);if(xe>1&&fe.slice(1,xe).every(function(q){return q==o})&&[o,x,U].indexOf(g)==-1)return le;var Re=fe.lastIndexOf(a);if(Re>0&&fe.slice(1,Re).every(function(q){return q==a})&&[D,a].indexOf(ie)==-1)return fe.filter(function(q){return q==a}).length%2==1?ce:ue;if(ie==t&&Z==e)return z;if(ie==r||ie==t||ie==e)return Z==C&&me.every(function(q){return q==o})?le:te;if(Z==r||Z==t||Z==e)return te;if(ie==u&&(Z==u||Z==A||Z==h||Z==E))return z;if((ie==h||ie==A)&&(Z==A||Z==p))return z;if((ie==E||ie==p)&&Z==p)return z;if(Z==o||Z==T)return z;if(Z==n)return z;if(ie==D)return z;var gt=fe.indexOf(o)!=-1?fe.lastIndexOf(o)-1:fe.length-2;return[x,U].indexOf(fe[gt])!=-1&&fe.slice(gt+1,-1).every(function(q){return q==o})&&Z==C||ie==T&&[L,U].indexOf(Z)!=-1?z:me.indexOf(a)!=-1?le:ie==a&&Z==a?z:te}this.nextBreak=function(g,me){if(me===void 0&&(me=0),me<0)return 0;if(me>=g.length-1)return g.length;for(var we=Ee(he(g,me)),fe=[],ie=me+1;ie{var aat=/^(.*?)(\x1b\[[^m]+m|\x1b\]8;;.*?(\x1b\\|\u0007))/,Ix;function lat(){if(Ix)return Ix;if(typeof Intl.Segmenter<"u"){let t=new Intl.Segmenter("en",{granularity:"grapheme"});return Ix=e=>Array.from(t.segment(e),({segment:r})=>r)}else{let t=xue(),e=new t;return Ix=r=>e.splitGraphemes(r)}}kue.exports=(t,e=0,r=t.length)=>{if(e<0||r<0)throw new RangeError("Negative indices aren't supported by this implementation");let o=r-e,a="",n=0,u=0;for(;t.length>0;){let A=t.match(aat)||[t,t,void 0],p=lat()(A[1]),h=Math.min(e-n,p.length);p=p.slice(h);let E=Math.min(o-u,p.length);a+=p.slice(0,E).join(""),n+=h,u+=E,typeof A[2]<"u"&&(a+=A[2]),t=t.slice(A[0].length)}return a}});var nn,r2=wt(()=>{nn=process.env.YARN_IS_TEST_ENV?"0.0.0":"4.5.1"});function Mue(t,{configuration:e,json:r}){if(!e.get("enableMessageNames"))return"";let a=zu(t===null?0:t);return!r&&t===null?Ut(e,a,"grey"):a}function r3(t,{configuration:e,json:r}){let o=Mue(t,{configuration:e,json:r});if(!o||t===null||t===0)return o;let a=vr[t],n=`https://yarnpkg.com/advanced/error-codes#${o}---${a}`.toLowerCase();return ty(e,o,n)}async function Qy({configuration:t,stdout:e,forceError:r},o){let a=await Nt.start({configuration:t,stdout:e,includeFooter:!1},async n=>{let u=!1,A=!1;for(let p of o)typeof p.option<"u"&&(p.error||r?(A=!0,n.reportError(50,p.message)):(u=!0,n.reportWarning(50,p.message)),p.callback?.());u&&!A&&n.reportSeparator()});return a.hasErrors()?a.exitCode():null}var Nue,Bx,cat,Fue,Rue,hh,Lue,Tue,uat,Aat,vx,fat,Nt,n2=wt(()=>{Nue=et(Que()),Bx=et(sg());jP();Vl();r2();Yl();cat="\xB7",Fue=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Rue=80,hh=Bx.default.GITHUB_ACTIONS?{start:t=>`::group::${t} +`,end:t=>`::endgroup:: +`}:Bx.default.TRAVIS?{start:t=>`travis_fold:start:${t} +`,end:t=>`travis_fold:end:${t} +`}:Bx.default.GITLAB?{start:t=>`section_start:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}[collapsed=true]\r\x1B[0K${t} +`,end:t=>`section_end:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}\r\x1B[0K`}:null,Lue=hh!==null,Tue=new Date,uat=["iTerm.app","Apple_Terminal","WarpTerminal","vscode"].includes(process.env.TERM_PROGRAM)||!!process.env.WT_SESSION,Aat=t=>t,vx=Aat({patrick:{date:[17,3],chars:["\u{1F340}","\u{1F331}"],size:40},simba:{date:[19,7],chars:["\u{1F981}","\u{1F334}"],size:40},jack:{date:[31,10],chars:["\u{1F383}","\u{1F987}"],size:40},hogsfather:{date:[31,12],chars:["\u{1F389}","\u{1F384}"],size:40},default:{chars:["=","-"],size:80}}),fat=uat&&Object.keys(vx).find(t=>{let e=vx[t];return!(e.date&&(e.date[0]!==Tue.getDate()||e.date[1]!==Tue.getMonth()+1))})||"default";Nt=class extends Ys{constructor({configuration:r,stdout:o,json:a=!1,forceSectionAlignment:n=!1,includeNames:u=!0,includePrefix:A=!0,includeFooter:p=!0,includeLogs:h=!a,includeInfos:E=h,includeWarnings:I=h}){super();this.uncommitted=new Set;this.warningCount=0;this.errorCount=0;this.timerFooter=[];this.startTime=Date.now();this.indent=0;this.level=0;this.progress=new Map;this.progressTime=0;this.progressFrame=0;this.progressTimeout=null;this.progressStyle=null;this.progressMaxScaledSize=null;if(g1(this,{configuration:r}),this.configuration=r,this.forceSectionAlignment=n,this.includeNames=u,this.includePrefix=A,this.includeFooter=p,this.includeInfos=E,this.includeWarnings=I,this.json=a,this.stdout=o,r.get("enableProgressBars")&&!a&&o.isTTY&&o.columns>22){let D=r.get("progressBarStyle")||fat;if(!Object.hasOwn(vx,D))throw new Error("Assertion failed: Invalid progress bar style");this.progressStyle=vx[D];let x=Math.min(this.getRecommendedLength(),80);this.progressMaxScaledSize=Math.floor(this.progressStyle.size*x/80)}}static async start(r,o){let a=new this(r),n=process.emitWarning;process.emitWarning=(u,A)=>{if(typeof u!="string"){let h=u;u=h.message,A=A??h.name}let p=typeof A<"u"?`${A}: ${u}`:u;a.reportWarning(0,p)},r.includeVersion&&a.reportInfo(0,Cg(r.configuration,`Yarn ${nn}`,2));try{await o(a)}catch(u){a.reportExceptionOnce(u)}finally{await a.finalize(),process.emitWarning=n}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}getRecommendedLength(){let o=this.progressStyle!==null?this.stdout.columns-1:super.getRecommendedLength();return Math.max(40,o-12-this.indent*2)}startSectionSync({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}async startSectionPromise({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return await n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}startTimerImpl(r,o,a){return{cb:typeof o=="function"?o:a,reportHeader:()=>{this.level+=1,this.reportInfo(null,`\u250C ${r}`),this.indent+=1,hh!==null&&!this.json&&this.includeInfos&&this.stdout.write(hh.start(r))},reportFooter:A=>{if(this.indent-=1,hh!==null&&!this.json&&this.includeInfos){this.stdout.write(hh.end(r));for(let p of this.timerFooter)p()}this.configuration.get("enableTimers")&&A>200?this.reportInfo(null,`\u2514 Completed in ${Ut(this.configuration,A,Ct.DURATION)}`):this.reportInfo(null,"\u2514 Completed"),this.level-=1},skipIfEmpty:(typeof o=="function"?{}:o).skipIfEmpty}}startTimerSync(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionSync(u,n)}async startTimerPromise(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionPromise(u,n)}reportSeparator(){this.indent===0?this.writeLine(""):this.reportInfo(null,"")}reportInfo(r,o){if(!this.includeInfos)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"",u=`${this.formatPrefix(n,"blueBright")}${o}`;this.json?this.reportJson({type:"info",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(u)}reportWarning(r,o){if(this.warningCount+=1,!this.includeWarnings)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"warning",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,"yellowBright")}${o}`)}reportError(r,o){this.errorCount+=1,this.timerFooter.push(()=>this.reportErrorImpl(r,o)),this.reportErrorImpl(r,o)}reportErrorImpl(r,o){this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"error",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,"redBright")}${o}`,{truncate:!1})}reportFold(r,o){if(!hh)return;let a=`${hh.start(r)}${o}${hh.end(r)}`;this.timerFooter.push(()=>this.stdout.write(a))}reportProgress(r){if(this.progressStyle===null)return{...Promise.resolve(),stop:()=>{}};if(r.hasProgress&&r.hasTitle)throw new Error("Unimplemented: Progress bars can't have both progress and titles.");let o=!1,a=Promise.resolve().then(async()=>{let u={progress:r.hasProgress?0:void 0,title:r.hasTitle?"":void 0};this.progress.set(r,{definition:u,lastScaledSize:r.hasProgress?-1:void 0,lastTitle:void 0}),this.refreshProgress({delta:-1});for await(let{progress:A,title:p}of r)o||u.progress===A&&u.title===p||(u.progress=A,u.title=p,this.refreshProgress());n()}),n=()=>{o||(o=!0,this.progress.delete(r),this.refreshProgress({delta:1}))};return{...a,stop:n}}reportJson(r){this.json&&this.writeLine(`${JSON.stringify(r)}`)}async finalize(){if(!this.includeFooter)return;let r="";this.errorCount>0?r="Failed with errors":this.warningCount>0?r="Done with warnings":r="Done";let o=Ut(this.configuration,Date.now()-this.startTime,Ct.DURATION),a=this.configuration.get("enableTimers")?`${r} in ${o}`:r;this.errorCount>0?this.reportError(0,a):this.warningCount>0?this.reportWarning(0,a):this.reportInfo(0,a)}writeLine(r,{truncate:o}={}){this.clearProgress({clear:!0}),this.stdout.write(`${this.truncate(r,{truncate:o})} +`),this.writeProgress()}writeLines(r,{truncate:o}={}){this.clearProgress({delta:r.length});for(let a of r)this.stdout.write(`${this.truncate(a,{truncate:o})} +`);this.writeProgress()}commit(){let r=this.uncommitted;this.uncommitted=new Set;for(let o of r)o.committed=!0,o.action()}clearProgress({delta:r=0,clear:o=!1}){this.progressStyle!==null&&this.progress.size+r>0&&(this.stdout.write(`\x1B[${this.progress.size+r}A`),(r>0||o)&&this.stdout.write("\x1B[0J"))}writeProgress(){if(this.progressStyle===null||(this.progressTimeout!==null&&clearTimeout(this.progressTimeout),this.progressTimeout=null,this.progress.size===0))return;let r=Date.now();r-this.progressTime>Rue&&(this.progressFrame=(this.progressFrame+1)%Fue.length,this.progressTime=r);let o=Fue[this.progressFrame];for(let a of this.progress.values()){let n="";if(typeof a.lastScaledSize<"u"){let h=this.progressStyle.chars[0].repeat(a.lastScaledSize),E=this.progressStyle.chars[1].repeat(this.progressMaxScaledSize-a.lastScaledSize);n=` ${h}${E}`}let u=this.formatName(null),A=u?`${u}: `:"",p=a.definition.title?` ${a.definition.title}`:"";this.stdout.write(`${Ut(this.configuration,"\u27A4","blueBright")} ${A}${o}${n}${p} +`)}this.progressTimeout=setTimeout(()=>{this.refreshProgress({force:!0})},Rue)}refreshProgress({delta:r=0,force:o=!1}={}){let a=!1,n=!1;if(o||this.progress.size===0)a=!0;else for(let u of this.progress.values()){let A=typeof u.definition.progress<"u"?Math.trunc(this.progressMaxScaledSize*u.definition.progress):void 0,p=u.lastScaledSize;u.lastScaledSize=A;let h=u.lastTitle;if(u.lastTitle=u.definition.title,A!==p||(n=h!==u.definition.title)){a=!0;break}}a&&(this.clearProgress({delta:r,clear:n}),this.writeProgress())}truncate(r,{truncate:o}={}){return this.progressStyle===null&&(o=!1),typeof o>"u"&&(o=this.configuration.get("preferTruncatedLines")),o&&(r=(0,Nue.default)(r,0,this.stdout.columns-1)),r}formatName(r){return this.includeNames?Mue(r,{configuration:this.configuration,json:this.json}):""}formatPrefix(r,o){return this.includePrefix?`${Ut(this.configuration,"\u27A4",o)} ${r}${this.formatIndent()}`:""}formatNameWithHyperlink(r){return this.includeNames?r3(r,{configuration:this.configuration,json:this.json}):""}formatIndent(){return this.level>0||!this.forceSectionAlignment?"\u2502 ".repeat(this.indent):`${cat} `}}});var hn={};Kt(hn,{PackageManager:()=>_ue,detectPackageManager:()=>Hue,executePackageAccessibleBinary:()=>Wue,executePackageScript:()=>Dx,executePackageShellcode:()=>n3,executeWorkspaceAccessibleBinary:()=>Eat,executeWorkspaceLifecycleScript:()=>Gue,executeWorkspaceScript:()=>jue,getPackageAccessibleBinaries:()=>Px,getWorkspaceAccessibleBinaries:()=>Yue,hasPackageScript:()=>dat,hasWorkspaceScript:()=>i3,isNodeScript:()=>s3,makeScriptEnv:()=>i2,maybeExecuteWorkspaceLifecycleScript:()=>yat,prepareExternalProject:()=>gat});async function gh(t,e,r,o=[]){if(process.platform==="win32"){let a=`@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @"${r}" ${o.map(n=>`"${n.replace('"','""')}"`).join(" ")} %*`;await ae.writeFilePromise(K.format({dir:t,name:e,ext:".cmd"}),a)}await ae.writeFilePromise(K.join(t,e),`#!/bin/sh +exec "${r}" ${o.map(a=>`'${a.replace(/'/g,`'"'"'`)}'`).join(" ")} "$@" +`,{mode:493})}async function Hue(t){let e=await _t.tryFind(t);if(e?.packageManager){let o=mb(e.packageManager);if(o?.name){let a=`found ${JSON.stringify({packageManager:e.packageManager})} in manifest`,[n]=o.reference.split(".");switch(o.name){case"yarn":return{packageManagerField:!0,packageManager:Number(n)===1?"Yarn Classic":"Yarn",reason:a};case"npm":return{packageManagerField:!0,packageManager:"npm",reason:a};case"pnpm":return{packageManagerField:!0,packageManager:"pnpm",reason:a}}}}let r;try{r=await ae.readFilePromise(K.join(t,mr.lockfile),"utf8")}catch{}return r!==void 0?r.match(/^__metadata:$/m)?{packageManager:"Yarn",reason:'"__metadata" key found in yarn.lock'}:{packageManager:"Yarn Classic",reason:'"__metadata" key not found in yarn.lock, must be a Yarn classic lockfile'}:ae.existsSync(K.join(t,"package-lock.json"))?{packageManager:"npm",reason:`found npm's "package-lock.json" lockfile`}:ae.existsSync(K.join(t,"pnpm-lock.yaml"))?{packageManager:"pnpm",reason:`found pnpm's "pnpm-lock.yaml" lockfile`}:null}async function i2({project:t,locator:e,binFolder:r,ignoreCorepack:o,lifecycleScript:a,baseEnv:n=t?.configuration.env??process.env}){let u={};for(let[E,I]of Object.entries(n))typeof I<"u"&&(u[E.toLowerCase()!=="path"?E:"PATH"]=I);let A=Ae.fromPortablePath(r);u.BERRY_BIN_FOLDER=Ae.fromPortablePath(A);let p=process.env.COREPACK_ROOT&&!o?Ae.join(process.env.COREPACK_ROOT,"dist/yarn.js"):process.argv[1];if(await Promise.all([gh(r,"node",process.execPath),...nn!==null?[gh(r,"run",process.execPath,[p,"run"]),gh(r,"yarn",process.execPath,[p]),gh(r,"yarnpkg",process.execPath,[p]),gh(r,"node-gyp",process.execPath,[p,"run","--top-level","node-gyp"])]:[]]),t&&(u.INIT_CWD=Ae.fromPortablePath(t.configuration.startingCwd),u.PROJECT_CWD=Ae.fromPortablePath(t.cwd)),u.PATH=u.PATH?`${A}${Ae.delimiter}${u.PATH}`:`${A}`,u.npm_execpath=`${A}${Ae.sep}yarn`,u.npm_node_execpath=`${A}${Ae.sep}node`,e){if(!t)throw new Error("Assertion failed: Missing project");let E=t.tryWorkspaceByLocator(e),I=E?E.manifest.version??"":t.storedPackages.get(e.locatorHash).version??"";u.npm_package_name=rn(e),u.npm_package_version=I;let D;if(E)D=E.cwd;else{let x=t.storedPackages.get(e.locatorHash);if(!x)throw new Error(`Package for ${jr(t.configuration,e)} not found in the project`);let C=t.configuration.getLinkers(),T={project:t,report:new Nt({stdout:new dh.PassThrough,configuration:t.configuration})},L=C.find(U=>U.supportsPackage(x,T));if(!L)throw new Error(`The package ${jr(t.configuration,x)} isn't supported by any of the available linkers`);D=await L.findPackageLocation(x,T)}u.npm_package_json=Ae.fromPortablePath(K.join(D,mr.manifest))}let h=nn!==null?`yarn/${nn}`:`yarn/${vf("@yarnpkg/core").version}-core`;return u.npm_config_user_agent=`${h} npm/? node/${process.version} ${process.platform} ${process.arch}`,a&&(u.npm_lifecycle_event=a),t&&await t.configuration.triggerHook(E=>E.setupScriptEnvironment,t,u,async(E,I,D)=>await gh(r,E,I,D)),u}async function gat(t,e,{configuration:r,report:o,workspace:a=null,locator:n=null}){await hat(async()=>{await ae.mktempPromise(async u=>{let A=K.join(u,"pack.log"),p=null,{stdout:h,stderr:E}=r.getSubprocessStreams(A,{prefix:Ae.fromPortablePath(t),report:o}),I=n&&zc(n)?w1(n):n,D=I?Qa(I):"an external project";h.write(`Packing ${D} from sources +`);let x=await Hue(t),C;x!==null?(h.write(`Using ${x.packageManager} for bootstrap. Reason: ${x.reason} + +`),C=x.packageManager):(h.write(`No package manager configuration detected; defaulting to Yarn + +`),C="Yarn");let T=C==="Yarn"&&!x?.packageManagerField;await ae.mktempPromise(async L=>{let U=await i2({binFolder:L,ignoreCorepack:T,baseEnv:{...process.env,COREPACK_ENABLE_AUTO_PIN:"0"}}),te=new Map([["Yarn Classic",async()=>{let ce=a!==null?["workspace",a]:[],ue=K.join(t,mr.manifest),Ce=await ae.readFilePromise(ue),he=await Xc(process.execPath,[process.argv[1],"set","version","classic","--only-if-needed","--yarn-path"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(he.code!==0)return he.code;await ae.writeFilePromise(ue,Ce),await ae.appendFilePromise(K.join(t,".npmignore"),`/.yarn +`),h.write(` +`),delete U.NODE_ENV;let De=await Xc("yarn",["install"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(De.code!==0)return De.code;h.write(` +`);let Ee=await Xc("yarn",[...ce,"pack","--filename",Ae.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ee.code!==0?Ee.code:0}],["Yarn",async()=>{let ce=a!==null?["workspace",a]:[];U.YARN_ENABLE_INLINE_BUILDS="1";let ue=K.join(t,mr.lockfile);await ae.existsPromise(ue)||await ae.writeFilePromise(ue,"");let Ce=await Xc("yarn",[...ce,"pack","--install-if-needed","--filename",Ae.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ce.code!==0?Ce.code:0}],["npm",async()=>{if(a!==null){let me=new dh.PassThrough,we=Xm(me);me.pipe(h,{end:!1});let fe=await Xc("npm",["--version"],{cwd:t,env:U,stdin:p,stdout:me,stderr:E,end:0});if(me.end(),fe.code!==0)return h.end(),E.end(),fe.code;let ie=(await we).toString().trim();if(!nA(ie,">=7.x")){let Z=rA(null,"npm"),xe=kn(Z,ie),Re=kn(Z,">=7.x");throw new Error(`Workspaces aren't supported by ${zn(r,xe)}; please upgrade to ${zn(r,Re)} (npm has been detected as the primary package manager for ${Ut(r,t,Ct.PATH)})`)}}let ce=a!==null?["--workspace",a]:[];delete U.npm_config_user_agent,delete U.npm_config_production,delete U.NPM_CONFIG_PRODUCTION,delete U.NODE_ENV;let ue=await Xc("npm",["install","--legacy-peer-deps"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(ue.code!==0)return ue.code;let Ce=new dh.PassThrough,he=Xm(Ce);Ce.pipe(h);let De=await Xc("npm",["pack","--silent",...ce],{cwd:t,env:U,stdin:p,stdout:Ce,stderr:E});if(De.code!==0)return De.code;let Ee=(await he).toString().trim().replace(/^.*\n/s,""),g=K.resolve(t,Ae.toPortablePath(Ee));return await ae.renamePromise(g,e),0}]]).get(C);if(typeof te>"u")throw new Error("Assertion failed: Unsupported workflow");let le=await te();if(!(le===0||typeof le>"u"))throw ae.detachTemp(u),new zt(58,`Packing the package failed (exit code ${le}, logs can be found here: ${Ut(r,A,Ct.PATH)})`)})})})}async function dat(t,e,{project:r}){let o=r.tryWorkspaceByLocator(t);if(o!==null)return i3(o,e);let a=r.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${jr(r.configuration,t)} not found in the project`);return await iA.openPromise(async n=>{let u=r.configuration,A=r.configuration.getLinkers(),p={project:r,report:new Nt({stdout:new dh.PassThrough,configuration:u})},h=A.find(x=>x.supportsPackage(a,p));if(!h)throw new Error(`The package ${jr(r.configuration,a)} isn't supported by any of the available linkers`);let E=await h.findPackageLocation(a,p),I=new En(E,{baseFs:n});return(await _t.find(Bt.dot,{baseFs:I})).scripts.has(e)})}async function Dx(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await ae.mktempPromise(async p=>{let{manifest:h,env:E,cwd:I}=await que(t,{project:a,binFolder:p,cwd:o,lifecycleScript:e}),D=h.scripts.get(e);if(typeof D>"u")return 1;let x=async()=>await ky(D,r,{cwd:I,env:E,stdin:n,stdout:u,stderr:A});return await(await a.configuration.reduceHook(T=>T.wrapScriptExecution,x,a,t,e,{script:D,args:r,cwd:I,env:E,stdin:n,stdout:u,stderr:A}))()})}async function n3(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await ae.mktempPromise(async p=>{let{env:h,cwd:E}=await que(t,{project:a,binFolder:p,cwd:o});return await ky(e,r,{cwd:E,env:h,stdin:n,stdout:u,stderr:A})})}async function mat(t,{binFolder:e,cwd:r,lifecycleScript:o}){let a=await i2({project:t.project,locator:t.anchoredLocator,binFolder:e,lifecycleScript:o});return await o3(e,await Yue(t)),typeof r>"u"&&(r=K.dirname(await ae.realpathPromise(K.join(t.cwd,"package.json")))),{manifest:t.manifest,binFolder:e,env:a,cwd:r}}async function que(t,{project:e,binFolder:r,cwd:o,lifecycleScript:a}){let n=e.tryWorkspaceByLocator(t);if(n!==null)return mat(n,{binFolder:r,cwd:o,lifecycleScript:a});let u=e.storedPackages.get(t.locatorHash);if(!u)throw new Error(`Package for ${jr(e.configuration,t)} not found in the project`);return await iA.openPromise(async A=>{let p=e.configuration,h=e.configuration.getLinkers(),E={project:e,report:new Nt({stdout:new dh.PassThrough,configuration:p})},I=h.find(L=>L.supportsPackage(u,E));if(!I)throw new Error(`The package ${jr(e.configuration,u)} isn't supported by any of the available linkers`);let D=await i2({project:e,locator:t,binFolder:r,lifecycleScript:a});await o3(r,await Px(t,{project:e}));let x=await I.findPackageLocation(u,E),C=new En(x,{baseFs:A}),T=await _t.find(Bt.dot,{baseFs:C});return typeof o>"u"&&(o=x),{manifest:T,binFolder:r,env:D,cwd:o}})}async function jue(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u}){return await Dx(t.anchoredLocator,e,r,{cwd:o,project:t.project,stdin:a,stdout:n,stderr:u})}function i3(t,e){return t.manifest.scripts.has(e)}async function Gue(t,e,{cwd:r,report:o}){let{configuration:a}=t.project,n=null;await ae.mktempPromise(async u=>{let A=K.join(u,`${e}.log`),p=`# This file contains the result of Yarn calling the "${e}" lifecycle script inside a workspace ("${Ae.fromPortablePath(t.cwd)}") +`,{stdout:h,stderr:E}=a.getSubprocessStreams(A,{report:o,prefix:jr(a,t.anchoredLocator),header:p});o.reportInfo(36,`Calling the "${e}" lifecycle script`);let I=await jue(t,e,[],{cwd:r,stdin:n,stdout:h,stderr:E});if(h.end(),E.end(),I!==0)throw ae.detachTemp(u),new zt(36,`${(0,Oue.default)(e)} script failed (exit code ${Ut(a,I,Ct.NUMBER)}, logs can be found here: ${Ut(a,A,Ct.PATH)}); run ${Ut(a,`yarn ${e}`,Ct.CODE)} to investigate`)})}async function yat(t,e,r){i3(t,e)&&await Gue(t,e,r)}function s3(t){let e=K.extname(t);if(e.match(/\.[cm]?[jt]sx?$/))return!0;if(e===".exe"||e===".bin")return!1;let r=Buffer.alloc(4),o;try{o=ae.openSync(t,"r")}catch{return!0}try{ae.readSync(o,r,0,r.length,0)}finally{ae.closeSync(o)}let a=r.readUint32BE();return!(a===3405691582||a===3489328638||a===2135247942||(a&4294901760)===1297743872)}async function Px(t,{project:e}){let r=e.configuration,o=new Map,a=e.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${jr(r,t)} not found in the project`);let n=new dh.Writable,u=r.getLinkers(),A={project:e,report:new Nt({configuration:r,stdout:n})},p=new Set([t.locatorHash]);for(let E of a.dependencies.values()){let I=e.storedResolutions.get(E.descriptorHash);if(!I)throw new Error(`Assertion failed: The resolution (${zn(r,E)}) should have been registered`);p.add(I)}let h=await Promise.all(Array.from(p,async E=>{let I=e.storedPackages.get(E);if(!I)throw new Error(`Assertion failed: The package (${E}) should have been registered`);if(I.bin.size===0)return ul.skip;let D=u.find(C=>C.supportsPackage(I,A));if(!D)return ul.skip;let x=null;try{x=await D.findPackageLocation(I,A)}catch(C){if(C.code==="LOCATOR_NOT_INSTALLED")return ul.skip;throw C}return{dependency:I,packageLocation:x}}));for(let E of h){if(E===ul.skip)continue;let{dependency:I,packageLocation:D}=E;for(let[x,C]of I.bin){let T=K.resolve(D,C);o.set(x,[I,Ae.fromPortablePath(T),s3(T)])}}return o}async function Yue(t){return await Px(t.anchoredLocator,{project:t.project})}async function o3(t,e){await Promise.all(Array.from(e,([r,[,o,a]])=>a?gh(t,r,process.execPath,[o]):gh(t,r,o,[])))}async function Wue(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A,nodeArgs:p=[],packageAccessibleBinaries:h}){h??=await Px(t,{project:a});let E=h.get(e);if(!E)throw new Error(`Binary not found (${e}) for ${jr(a.configuration,t)}`);return await ae.mktempPromise(async I=>{let[,D]=E,x=await i2({project:a,locator:t,binFolder:I});await o3(x.BERRY_BIN_FOLDER,h);let C=s3(Ae.toPortablePath(D))?Xc(process.execPath,[...p,D,...r],{cwd:o,env:x,stdin:n,stdout:u,stderr:A}):Xc(D,r,{cwd:o,env:x,stdin:n,stdout:u,stderr:A}),T;try{T=await C}finally{await ae.removePromise(x.BERRY_BIN_FOLDER)}return T.code})}async function Eat(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A}){return await Wue(t.anchoredLocator,e,r,{project:t.project,cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A})}var Oue,Uue,dh,_ue,pat,hat,a3=wt(()=>{Pt();Pt();sA();J1();Oue=et(t3()),Uue=et(lg()),dh=ve("stream");Ay();Vl();n2();r2();ix();Yl();Gl();xf();wo();_ue=(a=>(a.Yarn1="Yarn Classic",a.Yarn2="Yarn",a.Npm="npm",a.Pnpm="pnpm",a))(_ue||{});pat=2,hat=(0,Uue.default)(pat)});var Fy=_((y4t,Vue)=>{"use strict";var Kue=new Map([["C","cwd"],["f","file"],["z","gzip"],["P","preservePaths"],["U","unlink"],["strip-components","strip"],["stripComponents","strip"],["keep-newer","newer"],["keepNewer","newer"],["keep-newer-files","newer"],["keepNewerFiles","newer"],["k","keep"],["keep-existing","keep"],["keepExisting","keep"],["m","noMtime"],["no-mtime","noMtime"],["p","preserveOwner"],["L","follow"],["h","follow"]]);Vue.exports=t=>t?Object.keys(t).map(e=>[Kue.has(e)?Kue.get(e):e,t[e]]).reduce((e,r)=>(e[r[0]]=r[1],e),Object.create(null)):{}});var Ty=_((E4t,nAe)=>{"use strict";var zue=typeof process=="object"&&process?process:{stdout:null,stderr:null},Cat=ve("events"),Jue=ve("stream"),Xue=ve("string_decoder").StringDecoder,Lf=Symbol("EOF"),Mf=Symbol("maybeEmitEnd"),mh=Symbol("emittedEnd"),Sx=Symbol("emittingEnd"),s2=Symbol("emittedError"),bx=Symbol("closed"),Zue=Symbol("read"),xx=Symbol("flush"),$ue=Symbol("flushChunk"),Ra=Symbol("encoding"),Of=Symbol("decoder"),kx=Symbol("flowing"),o2=Symbol("paused"),Ry=Symbol("resume"),bs=Symbol("bufferLength"),l3=Symbol("bufferPush"),c3=Symbol("bufferShift"),Do=Symbol("objectMode"),Po=Symbol("destroyed"),u3=Symbol("emitData"),eAe=Symbol("emitEnd"),A3=Symbol("emitEnd2"),Uf=Symbol("async"),a2=t=>Promise.resolve().then(t),tAe=global._MP_NO_ITERATOR_SYMBOLS_!=="1",wat=tAe&&Symbol.asyncIterator||Symbol("asyncIterator not implemented"),Iat=tAe&&Symbol.iterator||Symbol("iterator not implemented"),Bat=t=>t==="end"||t==="finish"||t==="prefinish",vat=t=>t instanceof ArrayBuffer||typeof t=="object"&&t.constructor&&t.constructor.name==="ArrayBuffer"&&t.byteLength>=0,Dat=t=>!Buffer.isBuffer(t)&&ArrayBuffer.isView(t),Qx=class{constructor(e,r,o){this.src=e,this.dest=r,this.opts=o,this.ondrain=()=>e[Ry](),r.on("drain",this.ondrain)}unpipe(){this.dest.removeListener("drain",this.ondrain)}proxyErrors(){}end(){this.unpipe(),this.opts.end&&this.dest.end()}},f3=class extends Qx{unpipe(){this.src.removeListener("error",this.proxyErrors),super.unpipe()}constructor(e,r,o){super(e,r,o),this.proxyErrors=a=>r.emit("error",a),e.on("error",this.proxyErrors)}};nAe.exports=class rAe extends Jue{constructor(e){super(),this[kx]=!1,this[o2]=!1,this.pipes=[],this.buffer=[],this[Do]=e&&e.objectMode||!1,this[Do]?this[Ra]=null:this[Ra]=e&&e.encoding||null,this[Ra]==="buffer"&&(this[Ra]=null),this[Uf]=e&&!!e.async||!1,this[Of]=this[Ra]?new Xue(this[Ra]):null,this[Lf]=!1,this[mh]=!1,this[Sx]=!1,this[bx]=!1,this[s2]=null,this.writable=!0,this.readable=!0,this[bs]=0,this[Po]=!1}get bufferLength(){return this[bs]}get encoding(){return this[Ra]}set encoding(e){if(this[Do])throw new Error("cannot set encoding in objectMode");if(this[Ra]&&e!==this[Ra]&&(this[Of]&&this[Of].lastNeed||this[bs]))throw new Error("cannot change encoding");this[Ra]!==e&&(this[Of]=e?new Xue(e):null,this.buffer.length&&(this.buffer=this.buffer.map(r=>this[Of].write(r)))),this[Ra]=e}setEncoding(e){this.encoding=e}get objectMode(){return this[Do]}set objectMode(e){this[Do]=this[Do]||!!e}get async(){return this[Uf]}set async(e){this[Uf]=this[Uf]||!!e}write(e,r,o){if(this[Lf])throw new Error("write after end");if(this[Po])return this.emit("error",Object.assign(new Error("Cannot call write after a stream was destroyed"),{code:"ERR_STREAM_DESTROYED"})),!0;typeof r=="function"&&(o=r,r="utf8"),r||(r="utf8");let a=this[Uf]?a2:n=>n();return!this[Do]&&!Buffer.isBuffer(e)&&(Dat(e)?e=Buffer.from(e.buffer,e.byteOffset,e.byteLength):vat(e)?e=Buffer.from(e):typeof e!="string"&&(this.objectMode=!0)),this[Do]?(this.flowing&&this[bs]!==0&&this[xx](!0),this.flowing?this.emit("data",e):this[l3](e),this[bs]!==0&&this.emit("readable"),o&&a(o),this.flowing):e.length?(typeof e=="string"&&!(r===this[Ra]&&!this[Of].lastNeed)&&(e=Buffer.from(e,r)),Buffer.isBuffer(e)&&this[Ra]&&(e=this[Of].write(e)),this.flowing&&this[bs]!==0&&this[xx](!0),this.flowing?this.emit("data",e):this[l3](e),this[bs]!==0&&this.emit("readable"),o&&a(o),this.flowing):(this[bs]!==0&&this.emit("readable"),o&&a(o),this.flowing)}read(e){if(this[Po])return null;if(this[bs]===0||e===0||e>this[bs])return this[Mf](),null;this[Do]&&(e=null),this.buffer.length>1&&!this[Do]&&(this.encoding?this.buffer=[this.buffer.join("")]:this.buffer=[Buffer.concat(this.buffer,this[bs])]);let r=this[Zue](e||null,this.buffer[0]);return this[Mf](),r}[Zue](e,r){return e===r.length||e===null?this[c3]():(this.buffer[0]=r.slice(e),r=r.slice(0,e),this[bs]-=e),this.emit("data",r),!this.buffer.length&&!this[Lf]&&this.emit("drain"),r}end(e,r,o){return typeof e=="function"&&(o=e,e=null),typeof r=="function"&&(o=r,r="utf8"),e&&this.write(e,r),o&&this.once("end",o),this[Lf]=!0,this.writable=!1,(this.flowing||!this[o2])&&this[Mf](),this}[Ry](){this[Po]||(this[o2]=!1,this[kx]=!0,this.emit("resume"),this.buffer.length?this[xx]():this[Lf]?this[Mf]():this.emit("drain"))}resume(){return this[Ry]()}pause(){this[kx]=!1,this[o2]=!0}get destroyed(){return this[Po]}get flowing(){return this[kx]}get paused(){return this[o2]}[l3](e){this[Do]?this[bs]+=1:this[bs]+=e.length,this.buffer.push(e)}[c3](){return this.buffer.length&&(this[Do]?this[bs]-=1:this[bs]-=this.buffer[0].length),this.buffer.shift()}[xx](e){do;while(this[$ue](this[c3]()));!e&&!this.buffer.length&&!this[Lf]&&this.emit("drain")}[$ue](e){return e?(this.emit("data",e),this.flowing):!1}pipe(e,r){if(this[Po])return;let o=this[mh];return r=r||{},e===zue.stdout||e===zue.stderr?r.end=!1:r.end=r.end!==!1,r.proxyErrors=!!r.proxyErrors,o?r.end&&e.end():(this.pipes.push(r.proxyErrors?new f3(this,e,r):new Qx(this,e,r)),this[Uf]?a2(()=>this[Ry]()):this[Ry]()),e}unpipe(e){let r=this.pipes.find(o=>o.dest===e);r&&(this.pipes.splice(this.pipes.indexOf(r),1),r.unpipe())}addListener(e,r){return this.on(e,r)}on(e,r){let o=super.on(e,r);return e==="data"&&!this.pipes.length&&!this.flowing?this[Ry]():e==="readable"&&this[bs]!==0?super.emit("readable"):Bat(e)&&this[mh]?(super.emit(e),this.removeAllListeners(e)):e==="error"&&this[s2]&&(this[Uf]?a2(()=>r.call(this,this[s2])):r.call(this,this[s2])),o}get emittedEnd(){return this[mh]}[Mf](){!this[Sx]&&!this[mh]&&!this[Po]&&this.buffer.length===0&&this[Lf]&&(this[Sx]=!0,this.emit("end"),this.emit("prefinish"),this.emit("finish"),this[bx]&&this.emit("close"),this[Sx]=!1)}emit(e,r,...o){if(e!=="error"&&e!=="close"&&e!==Po&&this[Po])return;if(e==="data")return r?this[Uf]?a2(()=>this[u3](r)):this[u3](r):!1;if(e==="end")return this[eAe]();if(e==="close"){if(this[bx]=!0,!this[mh]&&!this[Po])return;let n=super.emit("close");return this.removeAllListeners("close"),n}else if(e==="error"){this[s2]=r;let n=super.emit("error",r);return this[Mf](),n}else if(e==="resume"){let n=super.emit("resume");return this[Mf](),n}else if(e==="finish"||e==="prefinish"){let n=super.emit(e);return this.removeAllListeners(e),n}let a=super.emit(e,r,...o);return this[Mf](),a}[u3](e){for(let o of this.pipes)o.dest.write(e)===!1&&this.pause();let r=super.emit("data",e);return this[Mf](),r}[eAe](){this[mh]||(this[mh]=!0,this.readable=!1,this[Uf]?a2(()=>this[A3]()):this[A3]())}[A3](){if(this[Of]){let r=this[Of].end();if(r){for(let o of this.pipes)o.dest.write(r);super.emit("data",r)}}for(let r of this.pipes)r.end();let e=super.emit("end");return this.removeAllListeners("end"),e}collect(){let e=[];this[Do]||(e.dataLength=0);let r=this.promise();return this.on("data",o=>{e.push(o),this[Do]||(e.dataLength+=o.length)}),r.then(()=>e)}concat(){return this[Do]?Promise.reject(new Error("cannot concat in objectMode")):this.collect().then(e=>this[Do]?Promise.reject(new Error("cannot concat in objectMode")):this[Ra]?e.join(""):Buffer.concat(e,e.dataLength))}promise(){return new Promise((e,r)=>{this.on(Po,()=>r(new Error("stream destroyed"))),this.on("error",o=>r(o)),this.on("end",()=>e())})}[wat](){return{next:()=>{let r=this.read();if(r!==null)return Promise.resolve({done:!1,value:r});if(this[Lf])return Promise.resolve({done:!0});let o=null,a=null,n=h=>{this.removeListener("data",u),this.removeListener("end",A),a(h)},u=h=>{this.removeListener("error",n),this.removeListener("end",A),this.pause(),o({value:h,done:!!this[Lf]})},A=()=>{this.removeListener("error",n),this.removeListener("data",u),o({done:!0})},p=()=>n(new Error("stream destroyed"));return new Promise((h,E)=>{a=E,o=h,this.once(Po,p),this.once("error",n),this.once("end",A),this.once("data",u)})}}}[Iat](){return{next:()=>{let r=this.read();return{value:r,done:r===null}}}}destroy(e){return this[Po]?(e?this.emit("error",e):this.emit(Po),this):(this[Po]=!0,this.buffer.length=0,this[bs]=0,typeof this.close=="function"&&!this[bx]&&this.close(),e?this.emit("error",e):this.emit(Po),this)}static isStream(e){return!!e&&(e instanceof rAe||e instanceof Jue||e instanceof Cat&&(typeof e.pipe=="function"||typeof e.write=="function"&&typeof e.end=="function"))}}});var sAe=_((C4t,iAe)=>{var Pat=ve("zlib").constants||{ZLIB_VERNUM:4736};iAe.exports=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},Pat))});var b3=_(hl=>{"use strict";var m3=ve("assert"),yh=ve("buffer").Buffer,lAe=ve("zlib"),Tg=hl.constants=sAe(),Sat=Ty(),oAe=yh.concat,Ng=Symbol("_superWrite"),Ly=class extends Error{constructor(e){super("zlib: "+e.message),this.code=e.code,this.errno=e.errno,this.code||(this.code="ZLIB_ERROR"),this.message="zlib: "+e.message,Error.captureStackTrace(this,this.constructor)}get name(){return"ZlibError"}},bat=Symbol("opts"),l2=Symbol("flushFlag"),aAe=Symbol("finishFlushFlag"),S3=Symbol("fullFlushFlag"),ui=Symbol("handle"),Fx=Symbol("onError"),Ny=Symbol("sawError"),p3=Symbol("level"),h3=Symbol("strategy"),g3=Symbol("ended"),w4t=Symbol("_defaultFullFlush"),Rx=class extends Sat{constructor(e,r){if(!e||typeof e!="object")throw new TypeError("invalid options for ZlibBase constructor");super(e),this[Ny]=!1,this[g3]=!1,this[bat]=e,this[l2]=e.flush,this[aAe]=e.finishFlush;try{this[ui]=new lAe[r](e)}catch(o){throw new Ly(o)}this[Fx]=o=>{this[Ny]||(this[Ny]=!0,this.close(),this.emit("error",o))},this[ui].on("error",o=>this[Fx](new Ly(o))),this.once("end",()=>this.close)}close(){this[ui]&&(this[ui].close(),this[ui]=null,this.emit("close"))}reset(){if(!this[Ny])return m3(this[ui],"zlib binding closed"),this[ui].reset()}flush(e){this.ended||(typeof e!="number"&&(e=this[S3]),this.write(Object.assign(yh.alloc(0),{[l2]:e})))}end(e,r,o){return e&&this.write(e,r),this.flush(this[aAe]),this[g3]=!0,super.end(null,null,o)}get ended(){return this[g3]}write(e,r,o){if(typeof r=="function"&&(o=r,r="utf8"),typeof e=="string"&&(e=yh.from(e,r)),this[Ny])return;m3(this[ui],"zlib binding closed");let a=this[ui]._handle,n=a.close;a.close=()=>{};let u=this[ui].close;this[ui].close=()=>{},yh.concat=h=>h;let A;try{let h=typeof e[l2]=="number"?e[l2]:this[l2];A=this[ui]._processChunk(e,h),yh.concat=oAe}catch(h){yh.concat=oAe,this[Fx](new Ly(h))}finally{this[ui]&&(this[ui]._handle=a,a.close=n,this[ui].close=u,this[ui].removeAllListeners("error"))}this[ui]&&this[ui].on("error",h=>this[Fx](new Ly(h)));let p;if(A)if(Array.isArray(A)&&A.length>0){p=this[Ng](yh.from(A[0]));for(let h=1;h{this.flush(a),n()};try{this[ui].params(e,r)}finally{this[ui].flush=o}this[ui]&&(this[p3]=e,this[h3]=r)}}}},y3=class extends _f{constructor(e){super(e,"Deflate")}},E3=class extends _f{constructor(e){super(e,"Inflate")}},d3=Symbol("_portable"),C3=class extends _f{constructor(e){super(e,"Gzip"),this[d3]=e&&!!e.portable}[Ng](e){return this[d3]?(this[d3]=!1,e[9]=255,super[Ng](e)):super[Ng](e)}},w3=class extends _f{constructor(e){super(e,"Gunzip")}},I3=class extends _f{constructor(e){super(e,"DeflateRaw")}},B3=class extends _f{constructor(e){super(e,"InflateRaw")}},v3=class extends _f{constructor(e){super(e,"Unzip")}},Tx=class extends Rx{constructor(e,r){e=e||{},e.flush=e.flush||Tg.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||Tg.BROTLI_OPERATION_FINISH,super(e,r),this[S3]=Tg.BROTLI_OPERATION_FLUSH}},D3=class extends Tx{constructor(e){super(e,"BrotliCompress")}},P3=class extends Tx{constructor(e){super(e,"BrotliDecompress")}};hl.Deflate=y3;hl.Inflate=E3;hl.Gzip=C3;hl.Gunzip=w3;hl.DeflateRaw=I3;hl.InflateRaw=B3;hl.Unzip=v3;typeof lAe.BrotliCompress=="function"?(hl.BrotliCompress=D3,hl.BrotliDecompress=P3):hl.BrotliCompress=hl.BrotliDecompress=class{constructor(){throw new Error("Brotli is not supported in this version of Node.js")}}});var My=_((v4t,cAe)=>{var xat=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform;cAe.exports=xat!=="win32"?t=>t:t=>t&&t.replace(/\\/g,"/")});var Nx=_((P4t,uAe)=>{"use strict";var kat=Ty(),x3=My(),k3=Symbol("slurp");uAe.exports=class extends kat{constructor(e,r,o){switch(super(),this.pause(),this.extended=r,this.globalExtended=o,this.header=e,this.startBlockSize=512*Math.ceil(e.size/512),this.blockRemain=this.startBlockSize,this.remain=e.size,this.type=e.type,this.meta=!1,this.ignore=!1,this.type){case"File":case"OldFile":case"Link":case"SymbolicLink":case"CharacterDevice":case"BlockDevice":case"Directory":case"FIFO":case"ContiguousFile":case"GNUDumpDir":break;case"NextFileHasLongLinkpath":case"NextFileHasLongPath":case"OldGnuLongPath":case"GlobalExtendedHeader":case"ExtendedHeader":case"OldExtendedHeader":this.meta=!0;break;default:this.ignore=!0}this.path=x3(e.path),this.mode=e.mode,this.mode&&(this.mode=this.mode&4095),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=e.size,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=x3(e.linkpath),this.uname=e.uname,this.gname=e.gname,r&&this[k3](r),o&&this[k3](o,!0)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error("writing more to entry than is appropriate");let o=this.remain,a=this.blockRemain;return this.remain=Math.max(0,o-r),this.blockRemain=Math.max(0,a-r),this.ignore?!0:o>=r?super.write(e):super.write(e.slice(0,o))}[k3](e,r){for(let o in e)e[o]!==null&&e[o]!==void 0&&!(r&&o==="path")&&(this[o]=o==="path"||o==="linkpath"?x3(e[o]):e[o])}}});var Q3=_(Lx=>{"use strict";Lx.name=new Map([["0","File"],["","OldFile"],["1","Link"],["2","SymbolicLink"],["3","CharacterDevice"],["4","BlockDevice"],["5","Directory"],["6","FIFO"],["7","ContiguousFile"],["g","GlobalExtendedHeader"],["x","ExtendedHeader"],["A","SolarisACL"],["D","GNUDumpDir"],["I","Inode"],["K","NextFileHasLongLinkpath"],["L","NextFileHasLongPath"],["M","ContinuationFile"],["N","OldGnuLongPath"],["S","SparseFile"],["V","TapeVolumeHeader"],["X","OldExtendedHeader"]]);Lx.code=new Map(Array.from(Lx.name).map(t=>[t[1],t[0]]))});var hAe=_((b4t,pAe)=>{"use strict";var Qat=(t,e)=>{if(Number.isSafeInteger(t))t<0?Rat(t,e):Fat(t,e);else throw Error("cannot encode number outside of javascript safe integer range");return e},Fat=(t,e)=>{e[0]=128;for(var r=e.length;r>1;r--)e[r-1]=t&255,t=Math.floor(t/256)},Rat=(t,e)=>{e[0]=255;var r=!1;t=t*-1;for(var o=e.length;o>1;o--){var a=t&255;t=Math.floor(t/256),r?e[o-1]=AAe(a):a===0?e[o-1]=0:(r=!0,e[o-1]=fAe(a))}},Tat=t=>{let e=t[0],r=e===128?Lat(t.slice(1,t.length)):e===255?Nat(t):null;if(r===null)throw Error("invalid base256 encoding");if(!Number.isSafeInteger(r))throw Error("parsed number outside of javascript safe integer range");return r},Nat=t=>{for(var e=t.length,r=0,o=!1,a=e-1;a>-1;a--){var n=t[a],u;o?u=AAe(n):n===0?u=n:(o=!0,u=fAe(n)),u!==0&&(r-=u*Math.pow(256,e-a-1))}return r},Lat=t=>{for(var e=t.length,r=0,o=e-1;o>-1;o--){var a=t[o];a!==0&&(r+=a*Math.pow(256,e-o-1))}return r},AAe=t=>(255^t)&255,fAe=t=>(255^t)+1&255;pAe.exports={encode:Qat,parse:Tat}});var Uy=_((x4t,dAe)=>{"use strict";var F3=Q3(),Oy=ve("path").posix,gAe=hAe(),R3=Symbol("slurp"),gl=Symbol("type"),L3=class{constructor(e,r,o,a){this.cksumValid=!1,this.needPax=!1,this.nullBlock=!1,this.block=null,this.path=null,this.mode=null,this.uid=null,this.gid=null,this.size=null,this.mtime=null,this.cksum=null,this[gl]="0",this.linkpath=null,this.uname=null,this.gname=null,this.devmaj=0,this.devmin=0,this.atime=null,this.ctime=null,Buffer.isBuffer(e)?this.decode(e,r||0,o,a):e&&this.set(e)}decode(e,r,o,a){if(r||(r=0),!e||!(e.length>=r+512))throw new Error("need 512 bytes for header");if(this.path=Lg(e,r,100),this.mode=Eh(e,r+100,8),this.uid=Eh(e,r+108,8),this.gid=Eh(e,r+116,8),this.size=Eh(e,r+124,12),this.mtime=T3(e,r+136,12),this.cksum=Eh(e,r+148,12),this[R3](o),this[R3](a,!0),this[gl]=Lg(e,r+156,1),this[gl]===""&&(this[gl]="0"),this[gl]==="0"&&this.path.substr(-1)==="/"&&(this[gl]="5"),this[gl]==="5"&&(this.size=0),this.linkpath=Lg(e,r+157,100),e.slice(r+257,r+265).toString()==="ustar\x0000")if(this.uname=Lg(e,r+265,32),this.gname=Lg(e,r+297,32),this.devmaj=Eh(e,r+329,8),this.devmin=Eh(e,r+337,8),e[r+475]!==0){let u=Lg(e,r+345,155);this.path=u+"/"+this.path}else{let u=Lg(e,r+345,130);u&&(this.path=u+"/"+this.path),this.atime=T3(e,r+476,12),this.ctime=T3(e,r+488,12)}let n=8*32;for(let u=r;u=r+512))throw new Error("need 512 bytes for header");let o=this.ctime||this.atime?130:155,a=Mat(this.path||"",o),n=a[0],u=a[1];this.needPax=a[2],this.needPax=Mg(e,r,100,n)||this.needPax,this.needPax=Ch(e,r+100,8,this.mode)||this.needPax,this.needPax=Ch(e,r+108,8,this.uid)||this.needPax,this.needPax=Ch(e,r+116,8,this.gid)||this.needPax,this.needPax=Ch(e,r+124,12,this.size)||this.needPax,this.needPax=N3(e,r+136,12,this.mtime)||this.needPax,e[r+156]=this[gl].charCodeAt(0),this.needPax=Mg(e,r+157,100,this.linkpath)||this.needPax,e.write("ustar\x0000",r+257,8),this.needPax=Mg(e,r+265,32,this.uname)||this.needPax,this.needPax=Mg(e,r+297,32,this.gname)||this.needPax,this.needPax=Ch(e,r+329,8,this.devmaj)||this.needPax,this.needPax=Ch(e,r+337,8,this.devmin)||this.needPax,this.needPax=Mg(e,r+345,o,u)||this.needPax,e[r+475]!==0?this.needPax=Mg(e,r+345,155,u)||this.needPax:(this.needPax=Mg(e,r+345,130,u)||this.needPax,this.needPax=N3(e,r+476,12,this.atime)||this.needPax,this.needPax=N3(e,r+488,12,this.ctime)||this.needPax);let A=8*32;for(let p=r;p{let o=t,a="",n,u=Oy.parse(t).root||".";if(Buffer.byteLength(o)<100)n=[o,a,!1];else{a=Oy.dirname(o),o=Oy.basename(o);do Buffer.byteLength(o)<=100&&Buffer.byteLength(a)<=e?n=[o,a,!1]:Buffer.byteLength(o)>100&&Buffer.byteLength(a)<=e?n=[o.substr(0,99),a,!0]:(o=Oy.join(Oy.basename(a),o),a=Oy.dirname(a));while(a!==u&&!n);n||(n=[t.substr(0,99),"",!0])}return n},Lg=(t,e,r)=>t.slice(e,e+r).toString("utf8").replace(/\0.*/,""),T3=(t,e,r)=>Oat(Eh(t,e,r)),Oat=t=>t===null?null:new Date(t*1e3),Eh=(t,e,r)=>t[e]&128?gAe.parse(t.slice(e,e+r)):_at(t,e,r),Uat=t=>isNaN(t)?null:t,_at=(t,e,r)=>Uat(parseInt(t.slice(e,e+r).toString("utf8").replace(/\0.*$/,"").trim(),8)),Hat={12:8589934591,8:2097151},Ch=(t,e,r,o)=>o===null?!1:o>Hat[r]||o<0?(gAe.encode(o,t.slice(e,e+r)),!0):(qat(t,e,r,o),!1),qat=(t,e,r,o)=>t.write(jat(o,r),e,r,"ascii"),jat=(t,e)=>Gat(Math.floor(t).toString(8),e),Gat=(t,e)=>(t.length===e-1?t:new Array(e-t.length-1).join("0")+t+" ")+"\0",N3=(t,e,r,o)=>o===null?!1:Ch(t,e,r,o.getTime()/1e3),Yat=new Array(156).join("\0"),Mg=(t,e,r,o)=>o===null?!1:(t.write(o+Yat,e,r,"utf8"),o.length!==Buffer.byteLength(o)||o.length>r);dAe.exports=L3});var Mx=_((k4t,mAe)=>{"use strict";var Wat=Uy(),Kat=ve("path"),c2=class{constructor(e,r){this.atime=e.atime||null,this.charset=e.charset||null,this.comment=e.comment||null,this.ctime=e.ctime||null,this.gid=e.gid||null,this.gname=e.gname||null,this.linkpath=e.linkpath||null,this.mtime=e.mtime||null,this.path=e.path||null,this.size=e.size||null,this.uid=e.uid||null,this.uname=e.uname||null,this.dev=e.dev||null,this.ino=e.ino||null,this.nlink=e.nlink||null,this.global=r||!1}encode(){let e=this.encodeBody();if(e==="")return null;let r=Buffer.byteLength(e),o=512*Math.ceil(1+r/512),a=Buffer.allocUnsafe(o);for(let n=0;n<512;n++)a[n]=0;new Wat({path:("PaxHeader/"+Kat.basename(this.path)).slice(0,99),mode:this.mode||420,uid:this.uid||null,gid:this.gid||null,size:r,mtime:this.mtime||null,type:this.global?"GlobalExtendedHeader":"ExtendedHeader",linkpath:"",uname:this.uname||"",gname:this.gname||"",devmaj:0,devmin:0,atime:this.atime||null,ctime:this.ctime||null}).encode(a),a.write(e,512,r,"utf8");for(let n=r+512;n=Math.pow(10,n)&&(n+=1),n+a+o}};c2.parse=(t,e,r)=>new c2(Vat(zat(t),e),r);var Vat=(t,e)=>e?Object.keys(t).reduce((r,o)=>(r[o]=t[o],r),e):t,zat=t=>t.replace(/\n$/,"").split(` +`).reduce(Jat,Object.create(null)),Jat=(t,e)=>{let r=parseInt(e,10);if(r!==Buffer.byteLength(e)+1)return t;e=e.substr((r+" ").length);let o=e.split("="),a=o.shift().replace(/^SCHILY\.(dev|ino|nlink)/,"$1");if(!a)return t;let n=o.join("=");return t[a]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(a)?new Date(n*1e3):/^[0-9]+$/.test(n)?+n:n,t};mAe.exports=c2});var _y=_((Q4t,yAe)=>{yAe.exports=t=>{let e=t.length-1,r=-1;for(;e>-1&&t.charAt(e)==="/";)r=e,e--;return r===-1?t:t.slice(0,r)}});var Ox=_((F4t,EAe)=>{"use strict";EAe.exports=t=>class extends t{warn(e,r,o={}){this.file&&(o.file=this.file),this.cwd&&(o.cwd=this.cwd),o.code=r instanceof Error&&r.code||e,o.tarCode=e,!this.strict&&o.recoverable!==!1?(r instanceof Error&&(o=Object.assign(r,o),r=r.message),this.emit("warn",o.tarCode,r,o)):r instanceof Error?this.emit("error",Object.assign(r,o)):this.emit("error",Object.assign(new Error(`${e}: ${r}`),o))}}});var O3=_((T4t,CAe)=>{"use strict";var Ux=["|","<",">","?",":"],M3=Ux.map(t=>String.fromCharCode(61440+t.charCodeAt(0))),Xat=new Map(Ux.map((t,e)=>[t,M3[e]])),Zat=new Map(M3.map((t,e)=>[t,Ux[e]]));CAe.exports={encode:t=>Ux.reduce((e,r)=>e.split(r).join(Xat.get(r)),t),decode:t=>M3.reduce((e,r)=>e.split(r).join(Zat.get(r)),t)}});var U3=_((N4t,IAe)=>{var{isAbsolute:$at,parse:wAe}=ve("path").win32;IAe.exports=t=>{let e="",r=wAe(t);for(;$at(t)||r.root;){let o=t.charAt(0)==="/"&&t.slice(0,4)!=="//?/"?"/":r.root;t=t.substr(o.length),e+=o,r=wAe(t)}return[e,t]}});var vAe=_((L4t,BAe)=>{"use strict";BAe.exports=(t,e,r)=>(t&=4095,r&&(t=(t|384)&-19),e&&(t&256&&(t|=64),t&32&&(t|=8),t&4&&(t|=1)),t)});var z3=_((U4t,OAe)=>{"use strict";var QAe=Ty(),FAe=Mx(),RAe=Uy(),lA=ve("fs"),DAe=ve("path"),aA=My(),elt=_y(),TAe=(t,e)=>e?(t=aA(t).replace(/^\.(\/|$)/,""),elt(e)+"/"+t):aA(t),tlt=16*1024*1024,PAe=Symbol("process"),SAe=Symbol("file"),bAe=Symbol("directory"),H3=Symbol("symlink"),xAe=Symbol("hardlink"),u2=Symbol("header"),_x=Symbol("read"),q3=Symbol("lstat"),Hx=Symbol("onlstat"),j3=Symbol("onread"),G3=Symbol("onreadlink"),Y3=Symbol("openfile"),W3=Symbol("onopenfile"),wh=Symbol("close"),qx=Symbol("mode"),K3=Symbol("awaitDrain"),_3=Symbol("ondrain"),cA=Symbol("prefix"),kAe=Symbol("hadError"),NAe=Ox(),rlt=O3(),LAe=U3(),MAe=vAe(),jx=NAe(class extends QAe{constructor(e,r){if(r=r||{},super(r),typeof e!="string")throw new TypeError("path is required");this.path=aA(e),this.portable=!!r.portable,this.myuid=process.getuid&&process.getuid()||0,this.myuser=process.env.USER||"",this.maxReadSize=r.maxReadSize||tlt,this.linkCache=r.linkCache||new Map,this.statCache=r.statCache||new Map,this.preservePaths=!!r.preservePaths,this.cwd=aA(r.cwd||process.cwd()),this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.mtime=r.mtime||null,this.prefix=r.prefix?aA(r.prefix):null,this.fd=null,this.blockLen=null,this.blockRemain=null,this.buf=null,this.offset=null,this.length=null,this.pos=null,this.remain=null,typeof r.onwarn=="function"&&this.on("warn",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=LAe(this.path);a&&(this.path=n,o=a)}this.win32=!!r.win32||process.platform==="win32",this.win32&&(this.path=rlt.decode(this.path.replace(/\\/g,"/")),e=e.replace(/\\/g,"/")),this.absolute=aA(r.absolute||DAe.resolve(this.cwd,e)),this.path===""&&(this.path="./"),o&&this.warn("TAR_ENTRY_INFO",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.statCache.has(this.absolute)?this[Hx](this.statCache.get(this.absolute)):this[q3]()}emit(e,...r){return e==="error"&&(this[kAe]=!0),super.emit(e,...r)}[q3](){lA.lstat(this.absolute,(e,r)=>{if(e)return this.emit("error",e);this[Hx](r)})}[Hx](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=ilt(e),this.emit("stat",e),this[PAe]()}[PAe](){switch(this.type){case"File":return this[SAe]();case"Directory":return this[bAe]();case"SymbolicLink":return this[H3]();default:return this.end()}}[qx](e){return MAe(e,this.type==="Directory",this.portable)}[cA](e){return TAe(e,this.prefix)}[u2](){this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.header=new RAe({path:this[cA](this.path),linkpath:this.type==="Link"?this[cA](this.linkpath):this.linkpath,mode:this[qx](this.stat.mode),uid:this.portable?null:this.stat.uid,gid:this.portable?null:this.stat.gid,size:this.stat.size,mtime:this.noMtime?null:this.mtime||this.stat.mtime,type:this.type,uname:this.portable?null:this.stat.uid===this.myuid?this.myuser:"",atime:this.portable?null:this.stat.atime,ctime:this.portable?null:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new FAe({atime:this.portable?null:this.header.atime,ctime:this.portable?null:this.header.ctime,gid:this.portable?null:this.header.gid,mtime:this.noMtime?null:this.mtime||this.header.mtime,path:this[cA](this.path),linkpath:this.type==="Link"?this[cA](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?null:this.header.uid,uname:this.portable?null:this.header.uname,dev:this.portable?null:this.stat.dev,ino:this.portable?null:this.stat.ino,nlink:this.portable?null:this.stat.nlink}).encode()),super.write(this.header.block)}[bAe](){this.path.substr(-1)!=="/"&&(this.path+="/"),this.stat.size=0,this[u2](),this.end()}[H3](){lA.readlink(this.absolute,(e,r)=>{if(e)return this.emit("error",e);this[G3](r)})}[G3](e){this.linkpath=aA(e),this[u2](),this.end()}[xAe](e){this.type="Link",this.linkpath=aA(DAe.relative(this.cwd,e)),this.stat.size=0,this[u2](),this.end()}[SAe](){if(this.stat.nlink>1){let e=this.stat.dev+":"+this.stat.ino;if(this.linkCache.has(e)){let r=this.linkCache.get(e);if(r.indexOf(this.cwd)===0)return this[xAe](r)}this.linkCache.set(e,this.absolute)}if(this[u2](),this.stat.size===0)return this.end();this[Y3]()}[Y3](){lA.open(this.absolute,"r",(e,r)=>{if(e)return this.emit("error",e);this[W3](r)})}[W3](e){if(this.fd=e,this[kAe])return this[wh]();this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let r=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(r),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[_x]()}[_x](){let{fd:e,buf:r,offset:o,length:a,pos:n}=this;lA.read(e,r,o,a,n,(u,A)=>{if(u)return this[wh](()=>this.emit("error",u));this[j3](A)})}[wh](e){lA.close(this.fd,e)}[j3](e){if(e<=0&&this.remain>0){let a=new Error("encountered unexpected EOF");return a.path=this.absolute,a.syscall="read",a.code="EOF",this[wh](()=>this.emit("error",a))}if(e>this.remain){let a=new Error("did not encounter expected EOF");return a.path=this.absolute,a.syscall="read",a.code="EOF",this[wh](()=>this.emit("error",a))}if(e===this.remain)for(let a=e;athis[_3]())}[K3](e){this.once("drain",e)}write(e){if(this.blockRemaine?this.emit("error",e):this.end());this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[_x]()}}),V3=class extends jx{[q3](){this[Hx](lA.lstatSync(this.absolute))}[H3](){this[G3](lA.readlinkSync(this.absolute))}[Y3](){this[W3](lA.openSync(this.absolute,"r"))}[_x](){let e=!0;try{let{fd:r,buf:o,offset:a,length:n,pos:u}=this,A=lA.readSync(r,o,a,n,u);this[j3](A),e=!1}finally{if(e)try{this[wh](()=>{})}catch{}}}[K3](e){e()}[wh](e){lA.closeSync(this.fd),e()}},nlt=NAe(class extends QAe{constructor(e,r){r=r||{},super(r),this.preservePaths=!!r.preservePaths,this.portable=!!r.portable,this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.readEntry=e,this.type=e.type,this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.prefix=r.prefix||null,this.path=aA(e.path),this.mode=this[qx](e.mode),this.uid=this.portable?null:e.uid,this.gid=this.portable?null:e.gid,this.uname=this.portable?null:e.uname,this.gname=this.portable?null:e.gname,this.size=e.size,this.mtime=this.noMtime?null:r.mtime||e.mtime,this.atime=this.portable?null:e.atime,this.ctime=this.portable?null:e.ctime,this.linkpath=aA(e.linkpath),typeof r.onwarn=="function"&&this.on("warn",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=LAe(this.path);a&&(this.path=n,o=a)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.header=new RAe({path:this[cA](this.path),linkpath:this.type==="Link"?this[cA](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?null:this.uid,gid:this.portable?null:this.gid,size:this.size,mtime:this.noMtime?null:this.mtime,type:this.type,uname:this.portable?null:this.uname,atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime}),o&&this.warn("TAR_ENTRY_INFO",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.header.encode()&&!this.noPax&&super.write(new FAe({atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime,gid:this.portable?null:this.gid,mtime:this.noMtime?null:this.mtime,path:this[cA](this.path),linkpath:this.type==="Link"?this[cA](this.linkpath):this.linkpath,size:this.size,uid:this.portable?null:this.uid,uname:this.portable?null:this.uname,dev:this.portable?null:this.readEntry.dev,ino:this.portable?null:this.readEntry.ino,nlink:this.portable?null:this.readEntry.nlink}).encode()),super.write(this.header.block),e.pipe(this)}[cA](e){return TAe(e,this.prefix)}[qx](e){return MAe(e,this.type==="Directory",this.portable)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error("writing more to entry than is appropriate");return this.blockRemain-=r,super.write(e)}end(){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),super.end()}});jx.Sync=V3;jx.Tar=nlt;var ilt=t=>t.isFile()?"File":t.isDirectory()?"Directory":t.isSymbolicLink()?"SymbolicLink":"Unsupported";OAe.exports=jx});var Zx=_((H4t,YAe)=>{"use strict";var Jx=class{constructor(e,r){this.path=e||"./",this.absolute=r,this.entry=null,this.stat=null,this.readdir=null,this.pending=!1,this.ignore=!1,this.piped=!1}},slt=Ty(),olt=b3(),alt=Nx(),i_=z3(),llt=i_.Sync,clt=i_.Tar,ult=$P(),UAe=Buffer.alloc(1024),Wx=Symbol("onStat"),Gx=Symbol("ended"),uA=Symbol("queue"),Hy=Symbol("current"),Og=Symbol("process"),Yx=Symbol("processing"),_Ae=Symbol("processJob"),AA=Symbol("jobs"),J3=Symbol("jobDone"),Kx=Symbol("addFSEntry"),HAe=Symbol("addTarEntry"),e_=Symbol("stat"),t_=Symbol("readdir"),Vx=Symbol("onreaddir"),zx=Symbol("pipe"),qAe=Symbol("entry"),X3=Symbol("entryOpt"),r_=Symbol("writeEntryClass"),GAe=Symbol("write"),Z3=Symbol("ondrain"),Xx=ve("fs"),jAe=ve("path"),Alt=Ox(),$3=My(),s_=Alt(class extends slt{constructor(e){super(e),e=e||Object.create(null),this.opt=e,this.file=e.file||"",this.cwd=e.cwd||process.cwd(),this.maxReadSize=e.maxReadSize,this.preservePaths=!!e.preservePaths,this.strict=!!e.strict,this.noPax=!!e.noPax,this.prefix=$3(e.prefix||""),this.linkCache=e.linkCache||new Map,this.statCache=e.statCache||new Map,this.readdirCache=e.readdirCache||new Map,this[r_]=i_,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),this.portable=!!e.portable,this.zip=null,e.gzip?(typeof e.gzip!="object"&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new olt.Gzip(e.gzip),this.zip.on("data",r=>super.write(r)),this.zip.on("end",r=>super.end()),this.zip.on("drain",r=>this[Z3]()),this.on("resume",r=>this.zip.resume())):this.on("drain",this[Z3]),this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,this.mtime=e.mtime||null,this.filter=typeof e.filter=="function"?e.filter:r=>!0,this[uA]=new ult,this[AA]=0,this.jobs=+e.jobs||4,this[Yx]=!1,this[Gx]=!1}[GAe](e){return super.write(e)}add(e){return this.write(e),this}end(e){return e&&this.write(e),this[Gx]=!0,this[Og](),this}write(e){if(this[Gx])throw new Error("write after end");return e instanceof alt?this[HAe](e):this[Kx](e),this.flowing}[HAe](e){let r=$3(jAe.resolve(this.cwd,e.path));if(!this.filter(e.path,e))e.resume();else{let o=new Jx(e.path,r,!1);o.entry=new clt(e,this[X3](o)),o.entry.on("end",a=>this[J3](o)),this[AA]+=1,this[uA].push(o)}this[Og]()}[Kx](e){let r=$3(jAe.resolve(this.cwd,e));this[uA].push(new Jx(e,r)),this[Og]()}[e_](e){e.pending=!0,this[AA]+=1;let r=this.follow?"stat":"lstat";Xx[r](e.absolute,(o,a)=>{e.pending=!1,this[AA]-=1,o?this.emit("error",o):this[Wx](e,a)})}[Wx](e,r){this.statCache.set(e.absolute,r),e.stat=r,this.filter(e.path,r)||(e.ignore=!0),this[Og]()}[t_](e){e.pending=!0,this[AA]+=1,Xx.readdir(e.absolute,(r,o)=>{if(e.pending=!1,this[AA]-=1,r)return this.emit("error",r);this[Vx](e,o)})}[Vx](e,r){this.readdirCache.set(e.absolute,r),e.readdir=r,this[Og]()}[Og](){if(!this[Yx]){this[Yx]=!0;for(let e=this[uA].head;e!==null&&this[AA]this.warn(r,o,a),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix}}[qAe](e){this[AA]+=1;try{return new this[r_](e.path,this[X3](e)).on("end",()=>this[J3](e)).on("error",r=>this.emit("error",r))}catch(r){this.emit("error",r)}}[Z3](){this[Hy]&&this[Hy].entry&&this[Hy].entry.resume()}[zx](e){e.piped=!0,e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n==="./"?"":n.replace(/\/*$/,"/");this[Kx](u+a)});let r=e.entry,o=this.zip;o?r.on("data",a=>{o.write(a)||r.pause()}):r.on("data",a=>{super.write(a)||r.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}}),n_=class extends s_{constructor(e){super(e),this[r_]=llt}pause(){}resume(){}[e_](e){let r=this.follow?"statSync":"lstatSync";this[Wx](e,Xx[r](e.absolute))}[t_](e,r){this[Vx](e,Xx.readdirSync(e.absolute))}[zx](e){let r=e.entry,o=this.zip;e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n==="./"?"":n.replace(/\/*$/,"/");this[Kx](u+a)}),o?r.on("data",a=>{o.write(a)}):r.on("data",a=>{super[GAe](a)})}};s_.Sync=n_;YAe.exports=s_});var zy=_(f2=>{"use strict";var flt=Ty(),plt=ve("events").EventEmitter,Ta=ve("fs"),l_=Ta.writev;if(!l_){let t=process.binding("fs"),e=t.FSReqWrap||t.FSReqCallback;l_=(r,o,a,n)=>{let u=(p,h)=>n(p,h,o),A=new e;A.oncomplete=u,t.writeBuffers(r,o,a,A)}}var Ky=Symbol("_autoClose"),Zc=Symbol("_close"),A2=Symbol("_ended"),Jn=Symbol("_fd"),WAe=Symbol("_finished"),Bh=Symbol("_flags"),o_=Symbol("_flush"),c_=Symbol("_handleChunk"),u_=Symbol("_makeBuf"),nk=Symbol("_mode"),$x=Symbol("_needDrain"),Yy=Symbol("_onerror"),Vy=Symbol("_onopen"),a_=Symbol("_onread"),jy=Symbol("_onwrite"),vh=Symbol("_open"),Hf=Symbol("_path"),Ug=Symbol("_pos"),fA=Symbol("_queue"),Gy=Symbol("_read"),KAe=Symbol("_readSize"),Ih=Symbol("_reading"),ek=Symbol("_remain"),VAe=Symbol("_size"),tk=Symbol("_write"),qy=Symbol("_writing"),rk=Symbol("_defaultFlag"),Wy=Symbol("_errored"),ik=class extends flt{constructor(e,r){if(r=r||{},super(r),this.readable=!0,this.writable=!1,typeof e!="string")throw new TypeError("path must be a string");this[Wy]=!1,this[Jn]=typeof r.fd=="number"?r.fd:null,this[Hf]=e,this[KAe]=r.readSize||16*1024*1024,this[Ih]=!1,this[VAe]=typeof r.size=="number"?r.size:1/0,this[ek]=this[VAe],this[Ky]=typeof r.autoClose=="boolean"?r.autoClose:!0,typeof this[Jn]=="number"?this[Gy]():this[vh]()}get fd(){return this[Jn]}get path(){return this[Hf]}write(){throw new TypeError("this is a readable stream")}end(){throw new TypeError("this is a readable stream")}[vh](){Ta.open(this[Hf],"r",(e,r)=>this[Vy](e,r))}[Vy](e,r){e?this[Yy](e):(this[Jn]=r,this.emit("open",r),this[Gy]())}[u_](){return Buffer.allocUnsafe(Math.min(this[KAe],this[ek]))}[Gy](){if(!this[Ih]){this[Ih]=!0;let e=this[u_]();if(e.length===0)return process.nextTick(()=>this[a_](null,0,e));Ta.read(this[Jn],e,0,e.length,null,(r,o,a)=>this[a_](r,o,a))}}[a_](e,r,o){this[Ih]=!1,e?this[Yy](e):this[c_](r,o)&&this[Gy]()}[Zc](){if(this[Ky]&&typeof this[Jn]=="number"){let e=this[Jn];this[Jn]=null,Ta.close(e,r=>r?this.emit("error",r):this.emit("close"))}}[Yy](e){this[Ih]=!0,this[Zc](),this.emit("error",e)}[c_](e,r){let o=!1;return this[ek]-=e,e>0&&(o=super.write(ethis[Vy](e,r))}[Vy](e,r){this[rk]&&this[Bh]==="r+"&&e&&e.code==="ENOENT"?(this[Bh]="w",this[vh]()):e?this[Yy](e):(this[Jn]=r,this.emit("open",r),this[o_]())}end(e,r){return e&&this.write(e,r),this[A2]=!0,!this[qy]&&!this[fA].length&&typeof this[Jn]=="number"&&this[jy](null,0),this}write(e,r){return typeof e=="string"&&(e=Buffer.from(e,r)),this[A2]?(this.emit("error",new Error("write() after end()")),!1):this[Jn]===null||this[qy]||this[fA].length?(this[fA].push(e),this[$x]=!0,!1):(this[qy]=!0,this[tk](e),!0)}[tk](e){Ta.write(this[Jn],e,0,e.length,this[Ug],(r,o)=>this[jy](r,o))}[jy](e,r){e?this[Yy](e):(this[Ug]!==null&&(this[Ug]+=r),this[fA].length?this[o_]():(this[qy]=!1,this[A2]&&!this[WAe]?(this[WAe]=!0,this[Zc](),this.emit("finish")):this[$x]&&(this[$x]=!1,this.emit("drain"))))}[o_](){if(this[fA].length===0)this[A2]&&this[jy](null,0);else if(this[fA].length===1)this[tk](this[fA].pop());else{let e=this[fA];this[fA]=[],l_(this[Jn],e,this[Ug],(r,o)=>this[jy](r,o))}}[Zc](){if(this[Ky]&&typeof this[Jn]=="number"){let e=this[Jn];this[Jn]=null,Ta.close(e,r=>r?this.emit("error",r):this.emit("close"))}}},f_=class extends sk{[vh](){let e;if(this[rk]&&this[Bh]==="r+")try{e=Ta.openSync(this[Hf],this[Bh],this[nk])}catch(r){if(r.code==="ENOENT")return this[Bh]="w",this[vh]();throw r}else e=Ta.openSync(this[Hf],this[Bh],this[nk]);this[Vy](null,e)}[Zc](){if(this[Ky]&&typeof this[Jn]=="number"){let e=this[Jn];this[Jn]=null,Ta.closeSync(e),this.emit("close")}}[tk](e){let r=!0;try{this[jy](null,Ta.writeSync(this[Jn],e,0,e.length,this[Ug])),r=!1}finally{if(r)try{this[Zc]()}catch{}}}};f2.ReadStream=ik;f2.ReadStreamSync=A_;f2.WriteStream=sk;f2.WriteStreamSync=f_});var fk=_((G4t,tfe)=>{"use strict";var hlt=Ox(),glt=Uy(),dlt=ve("events"),mlt=$P(),ylt=1024*1024,Elt=Nx(),zAe=Mx(),Clt=b3(),p_=Buffer.from([31,139]),$l=Symbol("state"),_g=Symbol("writeEntry"),qf=Symbol("readEntry"),h_=Symbol("nextEntry"),JAe=Symbol("processEntry"),ec=Symbol("extendedHeader"),p2=Symbol("globalExtendedHeader"),Dh=Symbol("meta"),XAe=Symbol("emitMeta"),yi=Symbol("buffer"),jf=Symbol("queue"),Hg=Symbol("ended"),ZAe=Symbol("emittedEnd"),qg=Symbol("emit"),Na=Symbol("unzip"),ok=Symbol("consumeChunk"),ak=Symbol("consumeChunkSub"),g_=Symbol("consumeBody"),$Ae=Symbol("consumeMeta"),efe=Symbol("consumeHeader"),lk=Symbol("consuming"),d_=Symbol("bufferConcat"),m_=Symbol("maybeEnd"),h2=Symbol("writing"),Ph=Symbol("aborted"),ck=Symbol("onDone"),jg=Symbol("sawValidEntry"),uk=Symbol("sawNullBlock"),Ak=Symbol("sawEOF"),wlt=t=>!0;tfe.exports=hlt(class extends dlt{constructor(e){e=e||{},super(e),this.file=e.file||"",this[jg]=null,this.on(ck,r=>{(this[$l]==="begin"||this[jg]===!1)&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),e.ondone?this.on(ck,e.ondone):this.on(ck,r=>{this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||ylt,this.filter=typeof e.filter=="function"?e.filter:wlt,this.writable=!0,this.readable=!1,this[jf]=new mlt,this[yi]=null,this[qf]=null,this[_g]=null,this[$l]="begin",this[Dh]="",this[ec]=null,this[p2]=null,this[Hg]=!1,this[Na]=null,this[Ph]=!1,this[uk]=!1,this[Ak]=!1,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),typeof e.onentry=="function"&&this.on("entry",e.onentry)}[efe](e,r){this[jg]===null&&(this[jg]=!1);let o;try{o=new glt(e,r,this[ec],this[p2])}catch(a){return this.warn("TAR_ENTRY_INVALID",a)}if(o.nullBlock)this[uk]?(this[Ak]=!0,this[$l]==="begin"&&(this[$l]="header"),this[qg]("eof")):(this[uk]=!0,this[qg]("nullBlock"));else if(this[uk]=!1,!o.cksumValid)this.warn("TAR_ENTRY_INVALID","checksum failure",{header:o});else if(!o.path)this.warn("TAR_ENTRY_INVALID","path is required",{header:o});else{let a=o.type;if(/^(Symbolic)?Link$/.test(a)&&!o.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:o});else if(!/^(Symbolic)?Link$/.test(a)&&o.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath forbidden",{header:o});else{let n=this[_g]=new Elt(o,this[ec],this[p2]);if(!this[jg])if(n.remain){let u=()=>{n.invalid||(this[jg]=!0)};n.on("end",u)}else this[jg]=!0;n.meta?n.size>this.maxMetaEntrySize?(n.ignore=!0,this[qg]("ignoredEntry",n),this[$l]="ignore",n.resume()):n.size>0&&(this[Dh]="",n.on("data",u=>this[Dh]+=u),this[$l]="meta"):(this[ec]=null,n.ignore=n.ignore||!this.filter(n.path,n),n.ignore?(this[qg]("ignoredEntry",n),this[$l]=n.remain?"ignore":"header",n.resume()):(n.remain?this[$l]="body":(this[$l]="header",n.end()),this[qf]?this[jf].push(n):(this[jf].push(n),this[h_]())))}}}[JAe](e){let r=!0;return e?Array.isArray(e)?this.emit.apply(this,e):(this[qf]=e,this.emit("entry",e),e.emittedEnd||(e.on("end",o=>this[h_]()),r=!1)):(this[qf]=null,r=!1),r}[h_](){do;while(this[JAe](this[jf].shift()));if(!this[jf].length){let e=this[qf];!e||e.flowing||e.size===e.remain?this[h2]||this.emit("drain"):e.once("drain",o=>this.emit("drain"))}}[g_](e,r){let o=this[_g],a=o.blockRemain,n=a>=e.length&&r===0?e:e.slice(r,r+a);return o.write(n),o.blockRemain||(this[$l]="header",this[_g]=null,o.end()),n.length}[$Ae](e,r){let o=this[_g],a=this[g_](e,r);return this[_g]||this[XAe](o),a}[qg](e,r,o){!this[jf].length&&!this[qf]?this.emit(e,r,o):this[jf].push([e,r,o])}[XAe](e){switch(this[qg]("meta",this[Dh]),e.type){case"ExtendedHeader":case"OldExtendedHeader":this[ec]=zAe.parse(this[Dh],this[ec],!1);break;case"GlobalExtendedHeader":this[p2]=zAe.parse(this[Dh],this[p2],!0);break;case"NextFileHasLongPath":case"OldGnuLongPath":this[ec]=this[ec]||Object.create(null),this[ec].path=this[Dh].replace(/\0.*/,"");break;case"NextFileHasLongLinkpath":this[ec]=this[ec]||Object.create(null),this[ec].linkpath=this[Dh].replace(/\0.*/,"");break;default:throw new Error("unknown meta: "+e.type)}}abort(e){this[Ph]=!0,this.emit("abort",e),this.warn("TAR_ABORT",e,{recoverable:!1})}write(e){if(this[Ph])return;if(this[Na]===null&&e){if(this[yi]&&(e=Buffer.concat([this[yi],e]),this[yi]=null),e.lengththis[ok](n)),this[Na].on("error",n=>this.abort(n)),this[Na].on("end",n=>{this[Hg]=!0,this[ok]()}),this[h2]=!0;let a=this[Na][o?"end":"write"](e);return this[h2]=!1,a}}this[h2]=!0,this[Na]?this[Na].write(e):this[ok](e),this[h2]=!1;let r=this[jf].length?!1:this[qf]?this[qf].flowing:!0;return!r&&!this[jf].length&&this[qf].once("drain",o=>this.emit("drain")),r}[d_](e){e&&!this[Ph]&&(this[yi]=this[yi]?Buffer.concat([this[yi],e]):e)}[m_](){if(this[Hg]&&!this[ZAe]&&!this[Ph]&&!this[lk]){this[ZAe]=!0;let e=this[_g];if(e&&e.blockRemain){let r=this[yi]?this[yi].length:0;this.warn("TAR_BAD_ARCHIVE",`Truncated input (needed ${e.blockRemain} more bytes, only ${r} available)`,{entry:e}),this[yi]&&e.write(this[yi]),e.end()}this[qg](ck)}}[ok](e){if(this[lk])this[d_](e);else if(!e&&!this[yi])this[m_]();else{if(this[lk]=!0,this[yi]){this[d_](e);let r=this[yi];this[yi]=null,this[ak](r)}else this[ak](e);for(;this[yi]&&this[yi].length>=512&&!this[Ph]&&!this[Ak];){let r=this[yi];this[yi]=null,this[ak](r)}this[lk]=!1}(!this[yi]||this[Hg])&&this[m_]()}[ak](e){let r=0,o=e.length;for(;r+512<=o&&!this[Ph]&&!this[Ak];)switch(this[$l]){case"begin":case"header":this[efe](e,r),r+=512;break;case"ignore":case"body":r+=this[g_](e,r);break;case"meta":r+=this[$Ae](e,r);break;default:throw new Error("invalid state: "+this[$l])}r{"use strict";var Ilt=Fy(),nfe=fk(),Jy=ve("fs"),Blt=zy(),rfe=ve("path"),y_=_y();sfe.exports=(t,e,r)=>{typeof t=="function"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e=="function"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=Ilt(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return e.length&&Dlt(o,e),o.noResume||vlt(o),o.file&&o.sync?Plt(o):o.file?Slt(o,r):ife(o)};var vlt=t=>{let e=t.onentry;t.onentry=e?r=>{e(r),r.resume()}:r=>r.resume()},Dlt=(t,e)=>{let r=new Map(e.map(n=>[y_(n),!0])),o=t.filter,a=(n,u)=>{let A=u||rfe.parse(n).root||".",p=n===A?!1:r.has(n)?r.get(n):a(rfe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(y_(n)):n=>a(y_(n))},Plt=t=>{let e=ife(t),r=t.file,o=!0,a;try{let n=Jy.statSync(r),u=t.maxReadSize||16*1024*1024;if(n.size{let r=new nfe(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on("error",A),r.on("end",u),Jy.stat(a,(p,h)=>{if(p)A(p);else{let E=new Blt.ReadStream(a,{readSize:o,size:h.size});E.on("error",A),E.pipe(r)}})});return e?n.then(e,e):n},ife=t=>new nfe(t)});var Afe=_((W4t,ufe)=>{"use strict";var blt=Fy(),hk=Zx(),ofe=zy(),afe=pk(),lfe=ve("path");ufe.exports=(t,e,r)=>{if(typeof e=="function"&&(r=e),Array.isArray(t)&&(e=t,t={}),!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");e=Array.from(e);let o=blt(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return o.file&&o.sync?xlt(o,e):o.file?klt(o,e,r):o.sync?Qlt(o,e):Flt(o,e)};var xlt=(t,e)=>{let r=new hk.Sync(t),o=new ofe.WriteStreamSync(t.file,{mode:t.mode||438});r.pipe(o),cfe(r,e)},klt=(t,e,r)=>{let o=new hk(t),a=new ofe.WriteStream(t.file,{mode:t.mode||438});o.pipe(a);let n=new Promise((u,A)=>{a.on("error",A),a.on("close",u),o.on("error",A)});return E_(o,e),r?n.then(r,r):n},cfe=(t,e)=>{e.forEach(r=>{r.charAt(0)==="@"?afe({file:lfe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},E_=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)==="@")return afe({file:lfe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>E_(t,e));t.add(r)}t.end()},Qlt=(t,e)=>{let r=new hk.Sync(t);return cfe(r,e),r},Flt=(t,e)=>{let r=new hk(t);return E_(r,e),r}});var C_=_((K4t,yfe)=>{"use strict";var Rlt=Fy(),ffe=Zx(),dl=ve("fs"),pfe=zy(),hfe=pk(),gfe=ve("path"),dfe=Uy();yfe.exports=(t,e,r)=>{let o=Rlt(t);if(!o.file)throw new TypeError("file is required");if(o.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),o.sync?Tlt(o,e):Llt(o,e,r)};var Tlt=(t,e)=>{let r=new ffe.Sync(t),o=!0,a,n;try{try{a=dl.openSync(t.file,"r+")}catch(p){if(p.code==="ENOENT")a=dl.openSync(t.file,"w+");else throw p}let u=dl.fstatSync(a),A=Buffer.alloc(512);e:for(n=0;nu.size)break;n+=h,t.mtimeCache&&t.mtimeCache.set(p.path,p.mtime)}o=!1,Nlt(t,r,n,a,e)}finally{if(o)try{dl.closeSync(a)}catch{}}},Nlt=(t,e,r,o,a)=>{let n=new pfe.WriteStreamSync(t.file,{fd:o,start:r});e.pipe(n),Mlt(e,a)},Llt=(t,e,r)=>{e=Array.from(e);let o=new ffe(t),a=(u,A,p)=>{let h=(C,T)=>{C?dl.close(u,L=>p(C)):p(null,T)},E=0;if(A===0)return h(null,0);let I=0,D=Buffer.alloc(512),x=(C,T)=>{if(C)return h(C);if(I+=T,I<512&&T)return dl.read(u,D,I,D.length-I,E+I,x);if(E===0&&D[0]===31&&D[1]===139)return h(new Error("cannot append to compressed archives"));if(I<512)return h(null,E);let L=new dfe(D);if(!L.cksumValid)return h(null,E);let U=512*Math.ceil(L.size/512);if(E+U+512>A||(E+=U+512,E>=A))return h(null,E);t.mtimeCache&&t.mtimeCache.set(L.path,L.mtime),I=0,dl.read(u,D,0,512,E,x)};dl.read(u,D,0,512,E,x)},n=new Promise((u,A)=>{o.on("error",A);let p="r+",h=(E,I)=>{if(E&&E.code==="ENOENT"&&p==="r+")return p="w+",dl.open(t.file,p,h);if(E)return A(E);dl.fstat(I,(D,x)=>{if(D)return dl.close(I,()=>A(D));a(I,x.size,(C,T)=>{if(C)return A(C);let L=new pfe.WriteStream(t.file,{fd:I,start:T});o.pipe(L),L.on("error",A),L.on("close",u),mfe(o,e)})})};dl.open(t.file,p,h)});return r?n.then(r,r):n},Mlt=(t,e)=>{e.forEach(r=>{r.charAt(0)==="@"?hfe({file:gfe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},mfe=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)==="@")return hfe({file:gfe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>mfe(t,e));t.add(r)}t.end()}});var Cfe=_((V4t,Efe)=>{"use strict";var Olt=Fy(),Ult=C_();Efe.exports=(t,e,r)=>{let o=Olt(t);if(!o.file)throw new TypeError("file is required");if(o.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),_lt(o),Ult(o,e,r)};var _lt=t=>{let e=t.filter;t.mtimeCache||(t.mtimeCache=new Map),t.filter=e?(r,o)=>e(r,o)&&!(t.mtimeCache.get(r)>o.mtime):(r,o)=>!(t.mtimeCache.get(r)>o.mtime)}});var Bfe=_((z4t,Ife)=>{var{promisify:wfe}=ve("util"),Sh=ve("fs"),Hlt=t=>{if(!t)t={mode:511,fs:Sh};else if(typeof t=="object")t={mode:511,fs:Sh,...t};else if(typeof t=="number")t={mode:t,fs:Sh};else if(typeof t=="string")t={mode:parseInt(t,8),fs:Sh};else throw new TypeError("invalid options argument");return t.mkdir=t.mkdir||t.fs.mkdir||Sh.mkdir,t.mkdirAsync=wfe(t.mkdir),t.stat=t.stat||t.fs.stat||Sh.stat,t.statAsync=wfe(t.stat),t.statSync=t.statSync||t.fs.statSync||Sh.statSync,t.mkdirSync=t.mkdirSync||t.fs.mkdirSync||Sh.mkdirSync,t};Ife.exports=Hlt});var Dfe=_((J4t,vfe)=>{var qlt=process.platform,{resolve:jlt,parse:Glt}=ve("path"),Ylt=t=>{if(/\0/.test(t))throw Object.assign(new TypeError("path must be a string without null bytes"),{path:t,code:"ERR_INVALID_ARG_VALUE"});if(t=jlt(t),qlt==="win32"){let e=/[*|"<>?:]/,{root:r}=Glt(t);if(e.test(t.substr(r.length)))throw Object.assign(new Error("Illegal characters in path."),{path:t,code:"EINVAL"})}return t};vfe.exports=Ylt});var kfe=_((X4t,xfe)=>{var{dirname:Pfe}=ve("path"),Sfe=(t,e,r=void 0)=>r===e?Promise.resolve():t.statAsync(e).then(o=>o.isDirectory()?r:void 0,o=>o.code==="ENOENT"?Sfe(t,Pfe(e),e):void 0),bfe=(t,e,r=void 0)=>{if(r!==e)try{return t.statSync(e).isDirectory()?r:void 0}catch(o){return o.code==="ENOENT"?bfe(t,Pfe(e),e):void 0}};xfe.exports={findMade:Sfe,findMadeSync:bfe}});var B_=_((Z4t,Ffe)=>{var{dirname:Qfe}=ve("path"),w_=(t,e,r)=>{e.recursive=!1;let o=Qfe(t);return o===t?e.mkdirAsync(t,e).catch(a=>{if(a.code!=="EISDIR")throw a}):e.mkdirAsync(t,e).then(()=>r||t,a=>{if(a.code==="ENOENT")return w_(o,e).then(n=>w_(t,e,n));if(a.code!=="EEXIST"&&a.code!=="EROFS")throw a;return e.statAsync(t).then(n=>{if(n.isDirectory())return r;throw a},()=>{throw a})})},I_=(t,e,r)=>{let o=Qfe(t);if(e.recursive=!1,o===t)try{return e.mkdirSync(t,e)}catch(a){if(a.code!=="EISDIR")throw a;return}try{return e.mkdirSync(t,e),r||t}catch(a){if(a.code==="ENOENT")return I_(t,e,I_(o,e,r));if(a.code!=="EEXIST"&&a.code!=="EROFS")throw a;try{if(!e.statSync(t).isDirectory())throw a}catch{throw a}}};Ffe.exports={mkdirpManual:w_,mkdirpManualSync:I_}});var Nfe=_(($4t,Tfe)=>{var{dirname:Rfe}=ve("path"),{findMade:Wlt,findMadeSync:Klt}=kfe(),{mkdirpManual:Vlt,mkdirpManualSync:zlt}=B_(),Jlt=(t,e)=>(e.recursive=!0,Rfe(t)===t?e.mkdirAsync(t,e):Wlt(e,t).then(o=>e.mkdirAsync(t,e).then(()=>o).catch(a=>{if(a.code==="ENOENT")return Vlt(t,e);throw a}))),Xlt=(t,e)=>{if(e.recursive=!0,Rfe(t)===t)return e.mkdirSync(t,e);let o=Klt(e,t);try{return e.mkdirSync(t,e),o}catch(a){if(a.code==="ENOENT")return zlt(t,e);throw a}};Tfe.exports={mkdirpNative:Jlt,mkdirpNativeSync:Xlt}});var Ufe=_((eUt,Ofe)=>{var Lfe=ve("fs"),Zlt=process.version,v_=Zlt.replace(/^v/,"").split("."),Mfe=+v_[0]>10||+v_[0]==10&&+v_[1]>=12,$lt=Mfe?t=>t.mkdir===Lfe.mkdir:()=>!1,ect=Mfe?t=>t.mkdirSync===Lfe.mkdirSync:()=>!1;Ofe.exports={useNative:$lt,useNativeSync:ect}});var Yfe=_((tUt,Gfe)=>{var Xy=Bfe(),Zy=Dfe(),{mkdirpNative:_fe,mkdirpNativeSync:Hfe}=Nfe(),{mkdirpManual:qfe,mkdirpManualSync:jfe}=B_(),{useNative:tct,useNativeSync:rct}=Ufe(),$y=(t,e)=>(t=Zy(t),e=Xy(e),tct(e)?_fe(t,e):qfe(t,e)),nct=(t,e)=>(t=Zy(t),e=Xy(e),rct(e)?Hfe(t,e):jfe(t,e));$y.sync=nct;$y.native=(t,e)=>_fe(Zy(t),Xy(e));$y.manual=(t,e)=>qfe(Zy(t),Xy(e));$y.nativeSync=(t,e)=>Hfe(Zy(t),Xy(e));$y.manualSync=(t,e)=>jfe(Zy(t),Xy(e));Gfe.exports=$y});var Zfe=_((rUt,Xfe)=>{"use strict";var tc=ve("fs"),Gg=ve("path"),ict=tc.lchown?"lchown":"chown",sct=tc.lchownSync?"lchownSync":"chownSync",Kfe=tc.lchown&&!process.version.match(/v1[1-9]+\./)&&!process.version.match(/v10\.[6-9]/),Wfe=(t,e,r)=>{try{return tc[sct](t,e,r)}catch(o){if(o.code!=="ENOENT")throw o}},oct=(t,e,r)=>{try{return tc.chownSync(t,e,r)}catch(o){if(o.code!=="ENOENT")throw o}},act=Kfe?(t,e,r,o)=>a=>{!a||a.code!=="EISDIR"?o(a):tc.chown(t,e,r,o)}:(t,e,r,o)=>o,D_=Kfe?(t,e,r)=>{try{return Wfe(t,e,r)}catch(o){if(o.code!=="EISDIR")throw o;oct(t,e,r)}}:(t,e,r)=>Wfe(t,e,r),lct=process.version,Vfe=(t,e,r)=>tc.readdir(t,e,r),cct=(t,e)=>tc.readdirSync(t,e);/^v4\./.test(lct)&&(Vfe=(t,e,r)=>tc.readdir(t,r));var gk=(t,e,r,o)=>{tc[ict](t,e,r,act(t,e,r,a=>{o(a&&a.code!=="ENOENT"?a:null)}))},zfe=(t,e,r,o,a)=>{if(typeof e=="string")return tc.lstat(Gg.resolve(t,e),(n,u)=>{if(n)return a(n.code!=="ENOENT"?n:null);u.name=e,zfe(t,u,r,o,a)});if(e.isDirectory())P_(Gg.resolve(t,e.name),r,o,n=>{if(n)return a(n);let u=Gg.resolve(t,e.name);gk(u,r,o,a)});else{let n=Gg.resolve(t,e.name);gk(n,r,o,a)}},P_=(t,e,r,o)=>{Vfe(t,{withFileTypes:!0},(a,n)=>{if(a){if(a.code==="ENOENT")return o();if(a.code!=="ENOTDIR"&&a.code!=="ENOTSUP")return o(a)}if(a||!n.length)return gk(t,e,r,o);let u=n.length,A=null,p=h=>{if(!A){if(h)return o(A=h);if(--u===0)return gk(t,e,r,o)}};n.forEach(h=>zfe(t,h,e,r,p))})},uct=(t,e,r,o)=>{if(typeof e=="string")try{let a=tc.lstatSync(Gg.resolve(t,e));a.name=e,e=a}catch(a){if(a.code==="ENOENT")return;throw a}e.isDirectory()&&Jfe(Gg.resolve(t,e.name),r,o),D_(Gg.resolve(t,e.name),r,o)},Jfe=(t,e,r)=>{let o;try{o=cct(t,{withFileTypes:!0})}catch(a){if(a.code==="ENOENT")return;if(a.code==="ENOTDIR"||a.code==="ENOTSUP")return D_(t,e,r);throw a}return o&&o.length&&o.forEach(a=>uct(t,a,e,r)),D_(t,e,r)};Xfe.exports=P_;P_.sync=Jfe});var rpe=_((nUt,S_)=>{"use strict";var $fe=Yfe(),rc=ve("fs"),dk=ve("path"),epe=Zfe(),$c=My(),mk=class extends Error{constructor(e,r){super("Cannot extract through symbolic link"),this.path=r,this.symlink=e}get name(){return"SylinkError"}},yk=class extends Error{constructor(e,r){super(r+": Cannot cd into '"+e+"'"),this.path=e,this.code=r}get name(){return"CwdError"}},Ek=(t,e)=>t.get($c(e)),g2=(t,e,r)=>t.set($c(e),r),Act=(t,e)=>{rc.stat(t,(r,o)=>{(r||!o.isDirectory())&&(r=new yk(t,r&&r.code||"ENOTDIR")),e(r)})};S_.exports=(t,e,r)=>{t=$c(t);let o=e.umask,a=e.mode|448,n=(a&o)!==0,u=e.uid,A=e.gid,p=typeof u=="number"&&typeof A=="number"&&(u!==e.processUid||A!==e.processGid),h=e.preserve,E=e.unlink,I=e.cache,D=$c(e.cwd),x=(L,U)=>{L?r(L):(g2(I,t,!0),U&&p?epe(U,u,A,z=>x(z)):n?rc.chmod(t,a,r):r())};if(I&&Ek(I,t)===!0)return x();if(t===D)return Act(t,x);if(h)return $fe(t,{mode:a}).then(L=>x(null,L),x);let T=$c(dk.relative(D,t)).split("/");Ck(D,T,a,I,E,D,null,x)};var Ck=(t,e,r,o,a,n,u,A)=>{if(!e.length)return A(null,u);let p=e.shift(),h=$c(dk.resolve(t+"/"+p));if(Ek(o,h))return Ck(h,e,r,o,a,n,u,A);rc.mkdir(h,r,tpe(h,e,r,o,a,n,u,A))},tpe=(t,e,r,o,a,n,u,A)=>p=>{p?rc.lstat(t,(h,E)=>{if(h)h.path=h.path&&$c(h.path),A(h);else if(E.isDirectory())Ck(t,e,r,o,a,n,u,A);else if(a)rc.unlink(t,I=>{if(I)return A(I);rc.mkdir(t,r,tpe(t,e,r,o,a,n,u,A))});else{if(E.isSymbolicLink())return A(new mk(t,t+"/"+e.join("/")));A(p)}}):(u=u||t,Ck(t,e,r,o,a,n,u,A))},fct=t=>{let e=!1,r="ENOTDIR";try{e=rc.statSync(t).isDirectory()}catch(o){r=o.code}finally{if(!e)throw new yk(t,r)}};S_.exports.sync=(t,e)=>{t=$c(t);let r=e.umask,o=e.mode|448,a=(o&r)!==0,n=e.uid,u=e.gid,A=typeof n=="number"&&typeof u=="number"&&(n!==e.processUid||u!==e.processGid),p=e.preserve,h=e.unlink,E=e.cache,I=$c(e.cwd),D=L=>{g2(E,t,!0),L&&A&&epe.sync(L,n,u),a&&rc.chmodSync(t,o)};if(E&&Ek(E,t)===!0)return D();if(t===I)return fct(I),D();if(p)return D($fe.sync(t,o));let C=$c(dk.relative(I,t)).split("/"),T=null;for(let L=C.shift(),U=I;L&&(U+="/"+L);L=C.shift())if(U=$c(dk.resolve(U)),!Ek(E,U))try{rc.mkdirSync(U,o),T=T||U,g2(E,U,!0)}catch{let te=rc.lstatSync(U);if(te.isDirectory()){g2(E,U,!0);continue}else if(h){rc.unlinkSync(U),rc.mkdirSync(U,o),T=T||U,g2(E,U,!0);continue}else if(te.isSymbolicLink())return new mk(U,U+"/"+C.join("/"))}return D(T)}});var x_=_((iUt,npe)=>{var b_=Object.create(null),{hasOwnProperty:pct}=Object.prototype;npe.exports=t=>(pct.call(b_,t)||(b_[t]=t.normalize("NFKD")),b_[t])});var ape=_((sUt,ope)=>{var ipe=ve("assert"),hct=x_(),gct=_y(),{join:spe}=ve("path"),dct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,mct=dct==="win32";ope.exports=()=>{let t=new Map,e=new Map,r=h=>h.split("/").slice(0,-1).reduce((I,D)=>(I.length&&(D=spe(I[I.length-1],D)),I.push(D||"/"),I),[]),o=new Set,a=h=>{let E=e.get(h);if(!E)throw new Error("function does not have any path reservations");return{paths:E.paths.map(I=>t.get(I)),dirs:[...E.dirs].map(I=>t.get(I))}},n=h=>{let{paths:E,dirs:I}=a(h);return E.every(D=>D[0]===h)&&I.every(D=>D[0]instanceof Set&&D[0].has(h))},u=h=>o.has(h)||!n(h)?!1:(o.add(h),h(()=>A(h)),!0),A=h=>{if(!o.has(h))return!1;let{paths:E,dirs:I}=e.get(h),D=new Set;return E.forEach(x=>{let C=t.get(x);ipe.equal(C[0],h),C.length===1?t.delete(x):(C.shift(),typeof C[0]=="function"?D.add(C[0]):C[0].forEach(T=>D.add(T)))}),I.forEach(x=>{let C=t.get(x);ipe(C[0]instanceof Set),C[0].size===1&&C.length===1?t.delete(x):C[0].size===1?(C.shift(),D.add(C[0])):C[0].delete(h)}),o.delete(h),D.forEach(x=>u(x)),!0};return{check:n,reserve:(h,E)=>{h=mct?["win32 parallelization disabled"]:h.map(D=>hct(gct(spe(D))).toLowerCase());let I=new Set(h.map(D=>r(D)).reduce((D,x)=>D.concat(x)));return e.set(E,{dirs:I,paths:h}),h.forEach(D=>{let x=t.get(D);x?x.push(E):t.set(D,[E])}),I.forEach(D=>{let x=t.get(D);x?x[x.length-1]instanceof Set?x[x.length-1].add(E):x.push(new Set([E])):t.set(D,[new Set([E])])}),u(E)}}}});var upe=_((oUt,cpe)=>{var yct=process.platform,Ect=yct==="win32",Cct=global.__FAKE_TESTING_FS__||ve("fs"),{O_CREAT:wct,O_TRUNC:Ict,O_WRONLY:Bct,UV_FS_O_FILEMAP:lpe=0}=Cct.constants,vct=Ect&&!!lpe,Dct=512*1024,Pct=lpe|Ict|wct|Bct;cpe.exports=vct?t=>t"w"});var O_=_((aUt,vpe)=>{"use strict";var Sct=ve("assert"),bct=fk(),Fn=ve("fs"),xct=zy(),Gf=ve("path"),wpe=rpe(),Ape=O3(),kct=ape(),Qct=U3(),ml=My(),Fct=_y(),Rct=x_(),fpe=Symbol("onEntry"),F_=Symbol("checkFs"),ppe=Symbol("checkFs2"),Bk=Symbol("pruneCache"),R_=Symbol("isReusable"),nc=Symbol("makeFs"),T_=Symbol("file"),N_=Symbol("directory"),vk=Symbol("link"),hpe=Symbol("symlink"),gpe=Symbol("hardlink"),dpe=Symbol("unsupported"),mpe=Symbol("checkPath"),bh=Symbol("mkdir"),So=Symbol("onError"),wk=Symbol("pending"),ype=Symbol("pend"),eE=Symbol("unpend"),k_=Symbol("ended"),Q_=Symbol("maybeClose"),L_=Symbol("skip"),d2=Symbol("doChown"),m2=Symbol("uid"),y2=Symbol("gid"),E2=Symbol("checkedCwd"),Ipe=ve("crypto"),Bpe=upe(),Tct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,C2=Tct==="win32",Nct=(t,e)=>{if(!C2)return Fn.unlink(t,e);let r=t+".DELETE."+Ipe.randomBytes(16).toString("hex");Fn.rename(t,r,o=>{if(o)return e(o);Fn.unlink(r,e)})},Lct=t=>{if(!C2)return Fn.unlinkSync(t);let e=t+".DELETE."+Ipe.randomBytes(16).toString("hex");Fn.renameSync(t,e),Fn.unlinkSync(e)},Epe=(t,e,r)=>t===t>>>0?t:e===e>>>0?e:r,Cpe=t=>Rct(Fct(ml(t))).toLowerCase(),Mct=(t,e)=>{e=Cpe(e);for(let r of t.keys()){let o=Cpe(r);(o===e||o.indexOf(e+"/")===0)&&t.delete(r)}},Oct=t=>{for(let e of t.keys())t.delete(e)},w2=class extends bct{constructor(e){if(e||(e={}),e.ondone=r=>{this[k_]=!0,this[Q_]()},super(e),this[E2]=!1,this.reservations=kct(),this.transform=typeof e.transform=="function"?e.transform:null,this.writable=!0,this.readable=!1,this[wk]=0,this[k_]=!1,this.dirCache=e.dirCache||new Map,typeof e.uid=="number"||typeof e.gid=="number"){if(typeof e.uid!="number"||typeof e.gid!="number")throw new TypeError("cannot set owner without number uid and gid");if(e.preserveOwner)throw new TypeError("cannot preserve owner in archive and also set owner explicitly");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=null,this.gid=null,this.setOwner=!1;e.preserveOwner===void 0&&typeof e.uid!="number"?this.preserveOwner=process.getuid&&process.getuid()===0:this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():null,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():null,this.forceChown=e.forceChown===!0,this.win32=!!e.win32||C2,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=ml(Gf.resolve(e.cwd||process.cwd())),this.strip=+e.strip||0,this.processUmask=e.noChmod?0:process.umask(),this.umask=typeof e.umask=="number"?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on("entry",r=>this[fpe](r))}warn(e,r,o={}){return(e==="TAR_BAD_ARCHIVE"||e==="TAR_ABORT")&&(o.recoverable=!1),super.warn(e,r,o)}[Q_](){this[k_]&&this[wk]===0&&(this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close"))}[mpe](e){if(this.strip){let r=ml(e.path).split("/");if(r.length=this.strip)e.linkpath=o.slice(this.strip).join("/");else return!1}}if(!this.preservePaths){let r=ml(e.path),o=r.split("/");if(o.includes("..")||C2&&/^[a-z]:\.\.$/i.test(o[0]))return this.warn("TAR_ENTRY_ERROR","path contains '..'",{entry:e,path:r}),!1;let[a,n]=Qct(r);a&&(e.path=n,this.warn("TAR_ENTRY_INFO",`stripping ${a} from absolute path`,{entry:e,path:r}))}if(Gf.isAbsolute(e.path)?e.absolute=ml(Gf.resolve(e.path)):e.absolute=ml(Gf.resolve(this.cwd,e.path)),!this.preservePaths&&e.absolute.indexOf(this.cwd+"/")!==0&&e.absolute!==this.cwd)return this.warn("TAR_ENTRY_ERROR","path escaped extraction target",{entry:e,path:ml(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&e.type!=="Directory"&&e.type!=="GNUDumpDir")return!1;if(this.win32){let{root:r}=Gf.win32.parse(e.absolute);e.absolute=r+Ape.encode(e.absolute.substr(r.length));let{root:o}=Gf.win32.parse(e.path);e.path=o+Ape.encode(e.path.substr(o.length))}return!0}[fpe](e){if(!this[mpe](e))return e.resume();switch(Sct.equal(typeof e.absolute,"string"),e.type){case"Directory":case"GNUDumpDir":e.mode&&(e.mode=e.mode|448);case"File":case"OldFile":case"ContiguousFile":case"Link":case"SymbolicLink":return this[F_](e);case"CharacterDevice":case"BlockDevice":case"FIFO":default:return this[dpe](e)}}[So](e,r){e.name==="CwdError"?this.emit("error",e):(this.warn("TAR_ENTRY_ERROR",e,{entry:r}),this[eE](),r.resume())}[bh](e,r,o){wpe(ml(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r,noChmod:this.noChmod},o)}[d2](e){return this.forceChown||this.preserveOwner&&(typeof e.uid=="number"&&e.uid!==this.processUid||typeof e.gid=="number"&&e.gid!==this.processGid)||typeof this.uid=="number"&&this.uid!==this.processUid||typeof this.gid=="number"&&this.gid!==this.processGid}[m2](e){return Epe(this.uid,e.uid,this.processUid)}[y2](e){return Epe(this.gid,e.gid,this.processGid)}[T_](e,r){let o=e.mode&4095||this.fmode,a=new xct.WriteStream(e.absolute,{flags:Bpe(e.size),mode:o,autoClose:!1});a.on("error",p=>{a.fd&&Fn.close(a.fd,()=>{}),a.write=()=>!0,this[So](p,e),r()});let n=1,u=p=>{if(p){a.fd&&Fn.close(a.fd,()=>{}),this[So](p,e),r();return}--n===0&&Fn.close(a.fd,h=>{h?this[So](h,e):this[eE](),r()})};a.on("finish",p=>{let h=e.absolute,E=a.fd;if(e.mtime&&!this.noMtime){n++;let I=e.atime||new Date,D=e.mtime;Fn.futimes(E,I,D,x=>x?Fn.utimes(h,I,D,C=>u(C&&x)):u())}if(this[d2](e)){n++;let I=this[m2](e),D=this[y2](e);Fn.fchown(E,I,D,x=>x?Fn.chown(h,I,D,C=>u(C&&x)):u())}u()});let A=this.transform&&this.transform(e)||e;A!==e&&(A.on("error",p=>{this[So](p,e),r()}),e.pipe(A)),A.pipe(a)}[N_](e,r){let o=e.mode&4095||this.dmode;this[bh](e.absolute,o,a=>{if(a){this[So](a,e),r();return}let n=1,u=A=>{--n===0&&(r(),this[eE](),e.resume())};e.mtime&&!this.noMtime&&(n++,Fn.utimes(e.absolute,e.atime||new Date,e.mtime,u)),this[d2](e)&&(n++,Fn.chown(e.absolute,this[m2](e),this[y2](e),u)),u()})}[dpe](e){e.unsupported=!0,this.warn("TAR_ENTRY_UNSUPPORTED",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[hpe](e,r){this[vk](e,e.linkpath,"symlink",r)}[gpe](e,r){let o=ml(Gf.resolve(this.cwd,e.linkpath));this[vk](e,o,"link",r)}[ype](){this[wk]++}[eE](){this[wk]--,this[Q_]()}[L_](e){this[eE](),e.resume()}[R_](e,r){return e.type==="File"&&!this.unlink&&r.isFile()&&r.nlink<=1&&!C2}[F_](e){this[ype]();let r=[e.path];e.linkpath&&r.push(e.linkpath),this.reservations.reserve(r,o=>this[ppe](e,o))}[Bk](e){e.type==="SymbolicLink"?Oct(this.dirCache):e.type!=="Directory"&&Mct(this.dirCache,e.absolute)}[ppe](e,r){this[Bk](e);let o=A=>{this[Bk](e),r(A)},a=()=>{this[bh](this.cwd,this.dmode,A=>{if(A){this[So](A,e),o();return}this[E2]=!0,n()})},n=()=>{if(e.absolute!==this.cwd){let A=ml(Gf.dirname(e.absolute));if(A!==this.cwd)return this[bh](A,this.dmode,p=>{if(p){this[So](p,e),o();return}u()})}u()},u=()=>{Fn.lstat(e.absolute,(A,p)=>{if(p&&(this.keep||this.newer&&p.mtime>e.mtime)){this[L_](e),o();return}if(A||this[R_](e,p))return this[nc](null,e,o);if(p.isDirectory()){if(e.type==="Directory"){let h=!this.noChmod&&e.mode&&(p.mode&4095)!==e.mode,E=I=>this[nc](I,e,o);return h?Fn.chmod(e.absolute,e.mode,E):E()}if(e.absolute!==this.cwd)return Fn.rmdir(e.absolute,h=>this[nc](h,e,o))}if(e.absolute===this.cwd)return this[nc](null,e,o);Nct(e.absolute,h=>this[nc](h,e,o))})};this[E2]?n():a()}[nc](e,r,o){if(e){this[So](e,r),o();return}switch(r.type){case"File":case"OldFile":case"ContiguousFile":return this[T_](r,o);case"Link":return this[gpe](r,o);case"SymbolicLink":return this[hpe](r,o);case"Directory":case"GNUDumpDir":return this[N_](r,o)}}[vk](e,r,o,a){Fn[o](r,e.absolute,n=>{n?this[So](n,e):(this[eE](),e.resume()),a()})}},Ik=t=>{try{return[null,t()]}catch(e){return[e,null]}},M_=class extends w2{[nc](e,r){return super[nc](e,r,()=>{})}[F_](e){if(this[Bk](e),!this[E2]){let n=this[bh](this.cwd,this.dmode);if(n)return this[So](n,e);this[E2]=!0}if(e.absolute!==this.cwd){let n=ml(Gf.dirname(e.absolute));if(n!==this.cwd){let u=this[bh](n,this.dmode);if(u)return this[So](u,e)}}let[r,o]=Ik(()=>Fn.lstatSync(e.absolute));if(o&&(this.keep||this.newer&&o.mtime>e.mtime))return this[L_](e);if(r||this[R_](e,o))return this[nc](null,e);if(o.isDirectory()){if(e.type==="Directory"){let u=!this.noChmod&&e.mode&&(o.mode&4095)!==e.mode,[A]=u?Ik(()=>{Fn.chmodSync(e.absolute,e.mode)}):[];return this[nc](A,e)}let[n]=Ik(()=>Fn.rmdirSync(e.absolute));this[nc](n,e)}let[a]=e.absolute===this.cwd?[]:Ik(()=>Lct(e.absolute));this[nc](a,e)}[T_](e,r){let o=e.mode&4095||this.fmode,a=A=>{let p;try{Fn.closeSync(n)}catch(h){p=h}(A||p)&&this[So](A||p,e),r()},n;try{n=Fn.openSync(e.absolute,Bpe(e.size),o)}catch(A){return a(A)}let u=this.transform&&this.transform(e)||e;u!==e&&(u.on("error",A=>this[So](A,e)),e.pipe(u)),u.on("data",A=>{try{Fn.writeSync(n,A,0,A.length)}catch(p){a(p)}}),u.on("end",A=>{let p=null;if(e.mtime&&!this.noMtime){let h=e.atime||new Date,E=e.mtime;try{Fn.futimesSync(n,h,E)}catch(I){try{Fn.utimesSync(e.absolute,h,E)}catch{p=I}}}if(this[d2](e)){let h=this[m2](e),E=this[y2](e);try{Fn.fchownSync(n,h,E)}catch(I){try{Fn.chownSync(e.absolute,h,E)}catch{p=p||I}}}a(p)})}[N_](e,r){let o=e.mode&4095||this.dmode,a=this[bh](e.absolute,o);if(a){this[So](a,e),r();return}if(e.mtime&&!this.noMtime)try{Fn.utimesSync(e.absolute,e.atime||new Date,e.mtime)}catch{}if(this[d2](e))try{Fn.chownSync(e.absolute,this[m2](e),this[y2](e))}catch{}r(),e.resume()}[bh](e,r){try{return wpe.sync(ml(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r})}catch(o){return o}}[vk](e,r,o,a){try{Fn[o+"Sync"](r,e.absolute),a(),e.resume()}catch(n){return this[So](n,e)}}};w2.Sync=M_;vpe.exports=w2});var xpe=_((lUt,bpe)=>{"use strict";var Uct=Fy(),Dk=O_(),Ppe=ve("fs"),Spe=zy(),Dpe=ve("path"),U_=_y();bpe.exports=(t,e,r)=>{typeof t=="function"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e=="function"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=Uct(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return e.length&&_ct(o,e),o.file&&o.sync?Hct(o):o.file?qct(o,r):o.sync?jct(o):Gct(o)};var _ct=(t,e)=>{let r=new Map(e.map(n=>[U_(n),!0])),o=t.filter,a=(n,u)=>{let A=u||Dpe.parse(n).root||".",p=n===A?!1:r.has(n)?r.get(n):a(Dpe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(U_(n)):n=>a(U_(n))},Hct=t=>{let e=new Dk.Sync(t),r=t.file,o=Ppe.statSync(r),a=t.maxReadSize||16*1024*1024;new Spe.ReadStreamSync(r,{readSize:a,size:o.size}).pipe(e)},qct=(t,e)=>{let r=new Dk(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on("error",A),r.on("close",u),Ppe.stat(a,(p,h)=>{if(p)A(p);else{let E=new Spe.ReadStream(a,{readSize:o,size:h.size});E.on("error",A),E.pipe(r)}})});return e?n.then(e,e):n},jct=t=>new Dk.Sync(t),Gct=t=>new Dk(t)});var kpe=_(us=>{"use strict";us.c=us.create=Afe();us.r=us.replace=C_();us.t=us.list=pk();us.u=us.update=Cfe();us.x=us.extract=xpe();us.Pack=Zx();us.Unpack=O_();us.Parse=fk();us.ReadEntry=Nx();us.WriteEntry=z3();us.Header=Uy();us.Pax=Mx();us.types=Q3()});var __,Qpe,xh,I2,B2,Fpe=wt(()=>{__=et(lg()),Qpe=ve("worker_threads"),xh=Symbol("kTaskInfo"),I2=class{constructor(e,r){this.fn=e;this.limit=(0,__.default)(r.poolSize)}run(e){return this.limit(()=>this.fn(e))}},B2=class{constructor(e,r){this.source=e;this.workers=[];this.limit=(0,__.default)(r.poolSize),this.cleanupInterval=setInterval(()=>{if(this.limit.pendingCount===0&&this.limit.activeCount===0){let o=this.workers.pop();o?o.terminate():clearInterval(this.cleanupInterval)}},5e3).unref()}createWorker(){this.cleanupInterval.refresh();let e=new Qpe.Worker(this.source,{eval:!0,execArgv:[...process.execArgv,"--unhandled-rejections=strict"]});return e.on("message",r=>{if(!e[xh])throw new Error("Assertion failed: Worker sent a result without having a task assigned");e[xh].resolve(r),e[xh]=null,e.unref(),this.workers.push(e)}),e.on("error",r=>{e[xh]?.reject(r),e[xh]=null}),e.on("exit",r=>{r!==0&&e[xh]?.reject(new Error(`Worker exited with code ${r}`)),e[xh]=null}),e}run(e){return this.limit(()=>{let r=this.workers.pop()??this.createWorker();return r.ref(),new Promise((o,a)=>{r[xh]={resolve:o,reject:a},r.postMessage(e)})})}}});var Tpe=_((fUt,Rpe)=>{var H_;Rpe.exports.getContent=()=>(typeof H_>"u"&&(H_=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),H_)});var $i={};Kt($i,{convertToZip:()=>Vct,convertToZipWorker:()=>G_,extractArchiveTo:()=>Upe,getDefaultTaskPool:()=>Mpe,getTaskPoolForConfiguration:()=>Ope,makeArchiveFromDirectory:()=>Kct});function Yct(t,e){switch(t){case"async":return new I2(G_,{poolSize:e});case"workers":return new B2((0,j_.getContent)(),{poolSize:e});default:throw new Error(`Assertion failed: Unknown value ${t} for taskPoolMode`)}}function Mpe(){return typeof q_>"u"&&(q_=Yct("workers",Xi.availableParallelism())),q_}function Ope(t){return typeof t>"u"?Mpe():Al(Wct,t,()=>{let e=t.get("taskPoolMode"),r=t.get("taskPoolConcurrency");switch(e){case"async":return new I2(G_,{poolSize:r});case"workers":return new B2((0,j_.getContent)(),{poolSize:r});default:throw new Error(`Assertion failed: Unknown value ${e} for taskPoolMode`)}})}async function G_(t){let{tmpFile:e,tgz:r,compressionLevel:o,extractBufferOpts:a}=t,n=new Zi(e,{create:!0,level:o,stats:Ia.makeDefaultStats()}),u=Buffer.from(r.buffer,r.byteOffset,r.byteLength);return await Upe(u,n,a),n.saveAndClose(),e}async function Kct(t,{baseFs:e=new _n,prefixPath:r=Bt.root,compressionLevel:o,inMemory:a=!1}={}){let n;if(a)n=new Zi(null,{level:o});else{let A=await ae.mktempPromise(),p=K.join(A,"archive.zip");n=new Zi(p,{create:!0,level:o})}let u=K.resolve(Bt.root,r);return await n.copyPromise(u,t,{baseFs:e,stableTime:!0,stableSort:!0}),n}async function Vct(t,e={}){let r=await ae.mktempPromise(),o=K.join(r,"archive.zip"),a=e.compressionLevel??e.configuration?.get("compressionLevel")??"mixed",n={prefixPath:e.prefixPath,stripComponents:e.stripComponents};return await(e.taskPool??Ope(e.configuration)).run({tmpFile:o,tgz:t,compressionLevel:a,extractBufferOpts:n}),new Zi(o,{level:e.compressionLevel})}async function*zct(t){let e=new Lpe.default.Parse,r=new Npe.PassThrough({objectMode:!0,autoDestroy:!0,emitClose:!0});e.on("entry",o=>{r.write(o)}),e.on("error",o=>{r.destroy(o)}),e.on("close",()=>{r.destroyed||r.end()}),e.end(t);for await(let o of r){let a=o;yield a,a.resume()}}async function Upe(t,e,{stripComponents:r=0,prefixPath:o=Bt.dot}={}){function a(n){if(n.path[0]==="/")return!0;let u=n.path.split(/\//g);return!!(u.some(A=>A==="..")||u.length<=r)}for await(let n of zct(t)){if(a(n))continue;let u=K.normalize(Ae.toPortablePath(n.path)).replace(/\/$/,"").split(/\//g);if(u.length<=r)continue;let A=u.slice(r).join("/"),p=K.join(o,A),h=420;switch((n.type==="Directory"||(n.mode??0)&73)&&(h|=73),n.type){case"Directory":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.mkdirSync(p,{mode:h}),e.utimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break;case"OldFile":case"File":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.writeFileSync(p,await Xm(n),{mode:h}),e.utimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break;case"SymbolicLink":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.symlinkSync(n.linkpath,p),e.lutimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break}}return e}var Npe,Lpe,j_,q_,Wct,_pe=wt(()=>{Ke();Pt();sA();Npe=ve("stream"),Lpe=et(kpe());Fpe();Gl();j_=et(Tpe());Wct=new WeakMap});var qpe=_((Y_,Hpe)=>{(function(t,e){typeof Y_=="object"?Hpe.exports=e():typeof define=="function"&&define.amd?define(e):t.treeify=e()})(Y_,function(){function t(a,n){var u=n?"\u2514":"\u251C";return a?u+="\u2500 ":u+="\u2500\u2500\u2510",u}function e(a,n){var u=[];for(var A in a)a.hasOwnProperty(A)&&(n&&typeof a[A]=="function"||u.push(A));return u}function r(a,n,u,A,p,h,E){var I="",D=0,x,C,T=A.slice(0);if(T.push([n,u])&&A.length>0&&(A.forEach(function(U,z){z>0&&(I+=(U[1]?" ":"\u2502")+" "),!C&&U[0]===n&&(C=!0)}),I+=t(a,u)+a,p&&(typeof n!="object"||n instanceof Date)&&(I+=": "+n),C&&(I+=" (circular ref.)"),E(I)),!C&&typeof n=="object"){var L=e(n,h);L.forEach(function(U){x=++D===L.length,r(U,n[U],x,T,p,h,E)})}}var o={};return o.asLines=function(a,n,u,A){var p=typeof u!="function"?u:!1;r(".",a,!1,[],n,p,A||u)},o.asTree=function(a,n,u){var A="";return r(".",a,!1,[],n,u,function(p){A+=p+` +`}),A},o})});var As={};Kt(As,{emitList:()=>Jct,emitTree:()=>Wpe,treeNodeToJson:()=>Ype,treeNodeToTreeify:()=>Gpe});function Gpe(t,{configuration:e}){let r={},o=0,a=(n,u)=>{let A=Array.isArray(n)?n.entries():Object.entries(n);for(let[p,h]of A){if(!h)continue;let{label:E,value:I,children:D}=h,x=[];typeof E<"u"&&x.push(Cg(e,E,2)),typeof I<"u"&&x.push(Ut(e,I[0],I[1])),x.length===0&&x.push(Cg(e,`${p}`,2));let C=x.join(": ").trim(),T=`\0${o++}\0`,L=u[`${T}${C}`]={};typeof D<"u"&&a(D,L)}};if(typeof t.children>"u")throw new Error("The root node must only contain children");return a(t.children,r),r}function Ype(t){let e=r=>{if(typeof r.children>"u"){if(typeof r.value>"u")throw new Error("Assertion failed: Expected a value to be set if the children are missing");return wg(r.value[0],r.value[1])}let o=Array.isArray(r.children)?r.children.entries():Object.entries(r.children??{}),a=Array.isArray(r.children)?[]:{};for(let[n,u]of o)u&&(a[Xct(n)]=e(u));return typeof r.value>"u"?a:{value:wg(r.value[0],r.value[1]),children:a}};return e(t)}function Jct(t,{configuration:e,stdout:r,json:o}){let a=t.map(n=>({value:n}));Wpe({children:a},{configuration:e,stdout:r,json:o})}function Wpe(t,{configuration:e,stdout:r,json:o,separators:a=0}){if(o){let u=Array.isArray(t.children)?t.children.values():Object.values(t.children??{});for(let A of u)A&&r.write(`${JSON.stringify(Ype(A))} +`);return}let n=(0,jpe.asTree)(Gpe(t,{configuration:e}),!1,!1);if(n=n.replace(/\0[0-9]+\0/g,""),a>=1&&(n=n.replace(/^([├└]─)/gm,`\u2502 +$1`).replace(/^│\n/,"")),a>=2)for(let u=0;u<2;++u)n=n.replace(/^([│ ].{2}[├│ ].{2}[^\n]+\n)(([│ ]).{2}[├└].{2}[^\n]*\n[│ ].{2}[│ ].{2}[├└]─)/gm,`$1$3 \u2502 +$2`).replace(/^│\n/,"");if(a>=3)throw new Error("Only the first two levels are accepted by treeUtils.emitTree");r.write(n)}function Xct(t){return typeof t=="string"?t.replace(/^\0[0-9]+\0/,""):t}var jpe,Kpe=wt(()=>{jpe=et(qpe());Yl()});function v2(t){let e=t.match(Zct);if(!e?.groups)throw new Error("Assertion failed: Expected the checksum to match the requested pattern");let r=e.groups.cacheVersion?parseInt(e.groups.cacheVersion):null;return{cacheKey:e.groups.cacheKey??null,cacheVersion:r,cacheSpec:e.groups.cacheSpec??null,hash:e.groups.hash}}var Vpe,W_,K_,Pk,Yr,Zct,V_=wt(()=>{Ke();Pt();Pt();sA();Vpe=ve("crypto"),W_=et(ve("fs"));Vl();ah();Gl();wo();K_=Zm(process.env.YARN_CACHE_CHECKPOINT_OVERRIDE??process.env.YARN_CACHE_VERSION_OVERRIDE??9),Pk=Zm(process.env.YARN_CACHE_VERSION_OVERRIDE??10),Yr=class t{constructor(e,{configuration:r,immutable:o=r.get("enableImmutableCache"),check:a=!1}){this.markedFiles=new Set;this.mutexes=new Map;this.cacheId=`-${(0,Vpe.randomBytes)(8).toString("hex")}.tmp`;this.configuration=r,this.cwd=e,this.immutable=o,this.check=a;let{cacheSpec:n,cacheKey:u}=t.getCacheKey(r);this.cacheSpec=n,this.cacheKey=u}static async find(e,{immutable:r,check:o}={}){let a=new t(e.get("cacheFolder"),{configuration:e,immutable:r,check:o});return await a.setup(),a}static getCacheKey(e){let r=e.get("compressionLevel"),o=r!=="mixed"?`c${r}`:"";return{cacheKey:[Pk,o].join(""),cacheSpec:o}}get mirrorCwd(){if(!this.configuration.get("enableMirror"))return null;let e=`${this.configuration.get("globalFolder")}/cache`;return e!==this.cwd?e:null}getVersionFilename(e){return`${ly(e)}-${this.cacheKey}.zip`}getChecksumFilename(e,r){let a=v2(r).hash.slice(0,10);return`${ly(e)}-${a}.zip`}isChecksumCompatible(e){if(e===null)return!1;let{cacheVersion:r,cacheSpec:o}=v2(e);if(r===null||r{let he=new Zi,De=K.join(Bt.root,_O(e));return he.mkdirSync(De,{recursive:!0}),he.writeJsonSync(K.join(De,mr.manifest),{name:rn(e),mocked:!0}),he},E=async(he,{isColdHit:De,controlPath:Ee=null})=>{if(Ee===null&&u.unstablePackages?.has(e.locatorHash))return{isValid:!0,hash:null};let g=r&&!De?v2(r).cacheKey:this.cacheKey,me=!u.skipIntegrityCheck||!r?`${g}/${await pb(he)}`:r;if(Ee!==null){let fe=!u.skipIntegrityCheck||!r?`${this.cacheKey}/${await pb(Ee)}`:r;if(me!==fe)throw new zt(18,"The remote archive doesn't match the local checksum - has the local cache been corrupted?")}let we=null;switch(r!==null&&me!==r&&(this.check?we="throw":v2(r).cacheKey!==v2(me).cacheKey?we="update":we=this.configuration.get("checksumBehavior")),we){case null:case"update":return{isValid:!0,hash:me};case"ignore":return{isValid:!0,hash:r};case"reset":return{isValid:!1,hash:r};default:case"throw":throw new zt(18,"The remote archive doesn't match the expected checksum")}},I=async he=>{if(!n)throw new Error(`Cache check required but no loader configured for ${jr(this.configuration,e)}`);let De=await n(),Ee=De.getRealPath();De.saveAndClose(),await ae.chmodPromise(Ee,420);let g=await E(he,{controlPath:Ee,isColdHit:!1});if(!g.isValid)throw new Error("Assertion failed: Expected a valid checksum");return g.hash},D=async()=>{if(A===null||!await ae.existsPromise(A)){let he=await n(),De=he.getRealPath();return he.saveAndClose(),{source:"loader",path:De}}return{source:"mirror",path:A}},x=async()=>{if(!n)throw new Error(`Cache entry required but missing for ${jr(this.configuration,e)}`);if(this.immutable)throw new zt(56,`Cache entry required but missing for ${jr(this.configuration,e)}`);let{path:he,source:De}=await D(),{hash:Ee}=await E(he,{isColdHit:!0}),g=this.getLocatorPath(e,Ee),me=[];De!=="mirror"&&A!==null&&me.push(async()=>{let fe=`${A}${this.cacheId}`;await ae.copyFilePromise(he,fe,W_.default.constants.COPYFILE_FICLONE),await ae.chmodPromise(fe,420),await ae.renamePromise(fe,A)}),(!u.mirrorWriteOnly||A===null)&&me.push(async()=>{let fe=`${g}${this.cacheId}`;await ae.copyFilePromise(he,fe,W_.default.constants.COPYFILE_FICLONE),await ae.chmodPromise(fe,420),await ae.renamePromise(fe,g)});let we=u.mirrorWriteOnly?A??g:g;return await Promise.all(me.map(fe=>fe())),[!1,we,Ee]},C=async()=>{let De=(async()=>{let Ee=u.unstablePackages?.has(e.locatorHash),g=Ee||!r||this.isChecksumCompatible(r)?this.getLocatorPath(e,r):null,me=g!==null?this.markedFiles.has(g)||await p.existsPromise(g):!1,we=!!u.mockedPackages?.has(e.locatorHash)&&(!this.check||!me),fe=we||me,ie=fe?o:a;if(ie&&ie(),fe){let Z=null,xe=g;if(!we)if(this.check)Z=await I(xe);else{let Re=await E(xe,{isColdHit:!1});if(Re.isValid)Z=Re.hash;else return x()}return[we,xe,Z]}else{if(this.immutable&&Ee)throw new zt(56,`Cache entry required but missing for ${jr(this.configuration,e)}; consider defining ${pe.pretty(this.configuration,"supportedArchitectures",pe.Type.CODE)} to cache packages for multiple systems`);return x()}})();this.mutexes.set(e.locatorHash,De);try{return await De}finally{this.mutexes.delete(e.locatorHash)}};for(let he;he=this.mutexes.get(e.locatorHash);)await he;let[T,L,U]=await C();T||this.markedFiles.add(L);let z,te=T?()=>h():()=>new Zi(L,{baseFs:p,readOnly:!0}),le=new Am(()=>rM(()=>z=te(),he=>`Failed to open the cache entry for ${jr(this.configuration,e)}: ${he}`),K),ce=new ju(L,{baseFs:le,pathUtils:K}),ue=()=>{z?.discardAndClose()},Ce=u.unstablePackages?.has(e.locatorHash)?null:U;return[ce,ue,Ce]}},Zct=/^(?:(?(?[0-9]+)(?.*))\/)?(?.*)$/});var Sk,zpe=wt(()=>{Sk=(r=>(r[r.SCRIPT=0]="SCRIPT",r[r.SHELLCODE=1]="SHELLCODE",r))(Sk||{})});var $ct,tE,z_=wt(()=>{Pt();Ml();xf();wo();$ct=[[/^(git(?:\+(?:https|ssh))?:\/\/.*(?:\.git)?)#(.*)$/,(t,e,r,o)=>`${r}#commit=${o}`],[/^https:\/\/((?:[^/]+?)@)?codeload\.github\.com\/([^/]+\/[^/]+)\/tar\.gz\/([0-9a-f]+)$/,(t,e,r="",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https:\/\/((?:[^/]+?)@)?github\.com\/([^/]+\/[^/]+?)(?:\.git)?#([0-9a-f]+)$/,(t,e,r="",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https?:\/\/[^/]+\/(?:[^/]+\/)*(?:@.+(?:\/|(?:%2f)))?([^/]+)\/(?:-|download)\/\1-[^/]+\.tgz(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.pkg\.github\.com\/download\/(?:@[^/]+)\/(?:[^/]+)\/(?:[^/]+)\/(?:[0-9a-f]+)(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.fontawesome\.com\/(?:@[^/]+)\/([^/]+)\/-\/([^/]+)\/\1-\2.tgz(?:#|$)/,t=>`npm:${t}`],[/^https?:\/\/[^/]+\/.*\/(@[^/]+)\/([^/]+)\/-\/\1\/\2-(?:[.\d\w-]+)\.tgz(?:#|$)/,(t,e)=>yb({protocol:"npm:",source:null,selector:t,params:{__archiveUrl:e}})],[/^[^/]+\.tgz#[0-9a-f]+$/,t=>`npm:${t}`]],tE=class{constructor(e){this.resolver=e;this.resolutions=null}async setup(e,{report:r}){let o=K.join(e.cwd,mr.lockfile);if(!ae.existsSync(o))return;let a=await ae.readFilePromise(o,"utf8"),n=Ki(a);if(Object.hasOwn(n,"__metadata"))return;let u=this.resolutions=new Map;for(let A of Object.keys(n)){let p=v1(A);if(!p){r.reportWarning(14,`Failed to parse the string "${A}" into a proper descriptor`);continue}let h=Fa(p.range)?kn(p,`npm:${p.range}`):p,{version:E,resolved:I}=n[A];if(!I)continue;let D;for(let[C,T]of $ct){let L=I.match(C);if(L){D=T(E,...L);break}}if(!D){r.reportWarning(14,`${zn(e.configuration,h)}: Only some patterns can be imported from legacy lockfiles (not "${I}")`);continue}let x=h;try{let C=vg(h.range),T=v1(C.selector,!0);T&&(x=T)}catch{}u.set(h.descriptorHash,Ss(x,D))}}supportsDescriptor(e,r){return this.resolutions?this.resolutions.has(e.descriptorHash):!1}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Assertion failed: This resolver doesn't support resolving locators to packages")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!this.resolutions)throw new Error("Assertion failed: The resolution store should have been setup");let a=this.resolutions.get(e.descriptorHash);if(!a)throw new Error("Assertion failed: The resolution should have been registered");let n=LO(a),u=o.project.configuration.normalizeDependency(n);return await this.resolver.getCandidates(u,r,o)}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){throw new Error("Assertion failed: This resolver doesn't support resolving locators to packages")}}});var pA,Jpe=wt(()=>{Vl();n2();Yl();pA=class extends Ys{constructor({configuration:r,stdout:o,suggestInstall:a=!0}){super();this.errorCount=0;g1(this,{configuration:r}),this.configuration=r,this.stdout=o,this.suggestInstall=a}static async start(r,o){let a=new this(r);try{await o(a)}catch(n){a.reportExceptionOnce(n)}finally{await a.finalize()}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}reportCacheHit(r){}reportCacheMiss(r){}startSectionSync(r,o){return o()}async startSectionPromise(r,o){return await o()}startTimerSync(r,o,a){return(typeof o=="function"?o:a)()}async startTimerPromise(r,o,a){return await(typeof o=="function"?o:a)()}reportSeparator(){}reportInfo(r,o){}reportWarning(r,o){}reportError(r,o){this.errorCount+=1,this.stdout.write(`${Ut(this.configuration,"\u27A4","redBright")} ${this.formatNameWithHyperlink(r)}: ${o} +`)}reportProgress(r){return{...Promise.resolve().then(async()=>{for await(let{}of r);}),stop:()=>{}}}reportJson(r){}reportFold(r,o){}async finalize(){this.errorCount>0&&(this.stdout.write(` +`),this.stdout.write(`${Ut(this.configuration,"\u27A4","redBright")} Errors happened when preparing the environment required to run this command. +`),this.suggestInstall&&this.stdout.write(`${Ut(this.configuration,"\u27A4","redBright")} This might be caused by packages being missing from the lockfile, in which case running "yarn install" might help. +`))}formatNameWithHyperlink(r){return r3(r,{configuration:this.configuration,json:!1})}}});var rE,J_=wt(()=>{wo();rE=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return!!(r.project.storedResolutions.get(e.descriptorHash)||r.project.originalPackages.has(gb(e).locatorHash))}supportsLocator(e,r){return!!(r.project.originalPackages.has(e.locatorHash)&&!r.project.lockfileNeedsRefresh)}shouldPersistResolution(e,r){throw new Error("The shouldPersistResolution method shouldn't be called on the lockfile resolver, which would always answer yes")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){let a=o.project.storedResolutions.get(e.descriptorHash);if(a){let u=o.project.originalPackages.get(a);if(u)return[u]}let n=o.project.originalPackages.get(gb(e).locatorHash);if(n)return[n];throw new Error("Resolution expected from the lockfile data")}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.originalPackages.get(e.locatorHash);if(!o)throw new Error("The lockfile resolver isn't meant to resolve packages - they should already have been stored into a cache");return o}}});function Yf(){}function eut(t,e,r,o,a){for(var n=0,u=e.length,A=0,p=0;nx.length?T:x}),h.value=t.join(E)}else h.value=t.join(r.slice(A,A+h.count));A+=h.count,h.added||(p+=h.count)}}var D=e[u-1];return u>1&&typeof D.value=="string"&&(D.added||D.removed)&&t.equals("",D.value)&&(e[u-2].value+=D.value,e.pop()),e}function tut(t){return{newPos:t.newPos,components:t.components.slice(0)}}function rut(t,e){if(typeof t=="function")e.callback=t;else if(t)for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e}function $pe(t,e,r){return r=rut(r,{ignoreWhitespace:!0}),t8.diff(t,e,r)}function nut(t,e,r){return r8.diff(t,e,r)}function bk(t){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?bk=function(e){return typeof e}:bk=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},bk(t)}function X_(t){return out(t)||aut(t)||lut(t)||cut()}function out(t){if(Array.isArray(t))return Z_(t)}function aut(t){if(typeof Symbol<"u"&&Symbol.iterator in Object(t))return Array.from(t)}function lut(t,e){if(t){if(typeof t=="string")return Z_(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Z_(t,e)}}function Z_(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r"u"&&(u.context=4);var A=nut(r,o,u);if(!A)return;A.push({value:"",lines:[]});function p(U){return U.map(function(z){return" "+z})}for(var h=[],E=0,I=0,D=[],x=1,C=1,T=function(z){var te=A[z],le=te.lines||te.value.replace(/\n$/,"").split(` +`);if(te.lines=le,te.added||te.removed){var ce;if(!E){var ue=A[z-1];E=x,I=C,ue&&(D=u.context>0?p(ue.lines.slice(-u.context)):[],E-=D.length,I-=D.length)}(ce=D).push.apply(ce,X_(le.map(function(fe){return(te.added?"+":"-")+fe}))),te.added?C+=le.length:x+=le.length}else{if(E)if(le.length<=u.context*2&&z=A.length-2&&le.length<=u.context){var g=/\n$/.test(r),me=/\n$/.test(o),we=le.length==0&&D.length>Ee.oldLines;!g&&we&&r.length>0&&D.splice(Ee.oldLines,0,"\\ No newline at end of file"),(!g&&!we||!me)&&D.push("\\ No newline at end of file")}h.push(Ee),E=0,I=0,D=[]}x+=le.length,C+=le.length}},L=0;L{Yf.prototype={diff:function(e,r){var o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=o.callback;typeof o=="function"&&(a=o,o={}),this.options=o;var n=this;function u(T){return a?(setTimeout(function(){a(void 0,T)},0),!0):T}e=this.castInput(e),r=this.castInput(r),e=this.removeEmpty(this.tokenize(e)),r=this.removeEmpty(this.tokenize(r));var A=r.length,p=e.length,h=1,E=A+p;o.maxEditLength&&(E=Math.min(E,o.maxEditLength));var I=[{newPos:-1,components:[]}],D=this.extractCommon(I[0],r,e,0);if(I[0].newPos+1>=A&&D+1>=p)return u([{value:this.join(r),count:r.length}]);function x(){for(var T=-1*h;T<=h;T+=2){var L=void 0,U=I[T-1],z=I[T+1],te=(z?z.newPos:0)-T;U&&(I[T-1]=void 0);var le=U&&U.newPos+1=A&&te+1>=p)return u(eut(n,L.components,r,e,n.useLongestToken));I[T]=L}h++}if(a)(function T(){setTimeout(function(){if(h>E)return a();x()||T()},0)})();else for(;h<=E;){var C=x();if(C)return C}},pushComponent:function(e,r,o){var a=e[e.length-1];a&&a.added===r&&a.removed===o?e[e.length-1]={count:a.count+1,added:r,removed:o}:e.push({count:1,added:r,removed:o})},extractCommon:function(e,r,o,a){for(var n=r.length,u=o.length,A=e.newPos,p=A-a,h=0;A+1"u"?r:u}:o;return typeof t=="string"?t:JSON.stringify($_(t,null,null,a),a," ")};D2.equals=function(t,e){return Yf.prototype.equals.call(D2,t.replace(/,([\r\n])/g,"$1"),e.replace(/,([\r\n])/g,"$1"))};e8=new Yf;e8.tokenize=function(t){return t.slice()};e8.join=e8.removeEmpty=function(t){return t}});var rhe=_((HUt,the)=>{var Aut=jl(),fut=fy(),put=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,hut=/^\w*$/;function gut(t,e){if(Aut(t))return!1;var r=typeof t;return r=="number"||r=="symbol"||r=="boolean"||t==null||fut(t)?!0:hut.test(t)||!put.test(t)||e!=null&&t in Object(e)}the.exports=gut});var she=_((qUt,ihe)=>{var nhe=dS(),dut="Expected a function";function i8(t,e){if(typeof t!="function"||e!=null&&typeof e!="function")throw new TypeError(dut);var r=function(){var o=arguments,a=e?e.apply(this,o):o[0],n=r.cache;if(n.has(a))return n.get(a);var u=t.apply(this,o);return r.cache=n.set(a,u)||n,u};return r.cache=new(i8.Cache||nhe),r}i8.Cache=nhe;ihe.exports=i8});var ahe=_((jUt,ohe)=>{var mut=she(),yut=500;function Eut(t){var e=mut(t,function(o){return r.size===yut&&r.clear(),o}),r=e.cache;return e}ohe.exports=Eut});var s8=_((GUt,lhe)=>{var Cut=ahe(),wut=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Iut=/\\(\\)?/g,But=Cut(function(t){var e=[];return t.charCodeAt(0)===46&&e.push(""),t.replace(wut,function(r,o,a,n){e.push(a?n.replace(Iut,"$1"):o||r)}),e});lhe.exports=But});var Yg=_((YUt,che)=>{var vut=jl(),Dut=rhe(),Put=s8(),Sut=t2();function but(t,e){return vut(t)?t:Dut(t,e)?[t]:Put(Sut(t))}che.exports=but});var nE=_((WUt,uhe)=>{var xut=fy(),kut=1/0;function Qut(t){if(typeof t=="string"||xut(t))return t;var e=t+"";return e=="0"&&1/t==-kut?"-0":e}uhe.exports=Qut});var xk=_((KUt,Ahe)=>{var Fut=Yg(),Rut=nE();function Tut(t,e){e=Fut(e,t);for(var r=0,o=e.length;t!=null&&r{var Nut=RS(),Lut=Yg(),Mut=n1(),fhe=cl(),Out=nE();function Uut(t,e,r,o){if(!fhe(t))return t;e=Lut(e,t);for(var a=-1,n=e.length,u=n-1,A=t;A!=null&&++a{var _ut=xk(),Hut=o8(),qut=Yg();function jut(t,e,r){for(var o=-1,a=e.length,n={};++o{function Gut(t,e){return t!=null&&e in Object(t)}dhe.exports=Gut});var a8=_((XUt,yhe)=>{var Yut=Yg(),Wut=e1(),Kut=jl(),Vut=n1(),zut=wS(),Jut=nE();function Xut(t,e,r){e=Yut(e,t);for(var o=-1,a=e.length,n=!1;++o{var Zut=mhe(),$ut=a8();function eAt(t,e){return t!=null&&$ut(t,e,Zut)}Ehe.exports=eAt});var Ihe=_(($Ut,whe)=>{var tAt=ghe(),rAt=Che();function nAt(t,e){return tAt(t,e,function(r,o){return rAt(t,o)})}whe.exports=nAt});var Phe=_((e3t,Dhe)=>{var Bhe=dg(),iAt=e1(),sAt=jl(),vhe=Bhe?Bhe.isConcatSpreadable:void 0;function oAt(t){return sAt(t)||iAt(t)||!!(vhe&&t&&t[vhe])}Dhe.exports=oAt});var xhe=_((t3t,bhe)=>{var aAt=ES(),lAt=Phe();function She(t,e,r,o,a){var n=-1,u=t.length;for(r||(r=lAt),a||(a=[]);++n0&&r(A)?e>1?She(A,e-1,r,o,a):aAt(a,A):o||(a[a.length]=A)}return a}bhe.exports=She});var Qhe=_((r3t,khe)=>{var cAt=xhe();function uAt(t){var e=t==null?0:t.length;return e?cAt(t,1):[]}khe.exports=uAt});var l8=_((n3t,Fhe)=>{var AAt=Qhe(),fAt=VL(),pAt=zL();function hAt(t){return pAt(fAt(t,void 0,AAt),t+"")}Fhe.exports=hAt});var c8=_((i3t,Rhe)=>{var gAt=Ihe(),dAt=l8(),mAt=dAt(function(t,e){return t==null?{}:gAt(t,e)});Rhe.exports=mAt});var kk,The=wt(()=>{Vl();kk=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return this.resolver.supportsDescriptor(e,r)}supportsLocator(e,r){return this.resolver.supportsLocator(e,r)}shouldPersistResolution(e,r){return this.resolver.shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.resolver.bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){throw new zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async getSatisfying(e,r,o,a){throw new zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async resolve(e,r){throw new zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}}});var Ri,u8=wt(()=>{Vl();Ri=class extends Ys{reportCacheHit(e){}reportCacheMiss(e){}startSectionSync(e,r){return r()}async startSectionPromise(e,r){return await r()}startTimerSync(e,r,o){return(typeof r=="function"?r:o)()}async startTimerPromise(e,r,o){return await(typeof r=="function"?r:o)()}reportSeparator(){}reportInfo(e,r){}reportWarning(e,r){}reportError(e,r){}reportProgress(e){return{...Promise.resolve().then(async()=>{for await(let{}of e);}),stop:()=>{}}}reportJson(e){}reportFold(e,r){}async finalize(){}}});var Nhe,iE,A8=wt(()=>{Pt();Nhe=et(Ab());Ay();Dg();Yl();ah();xf();wo();iE=class{constructor(e,{project:r}){this.workspacesCwds=new Set;this.project=r,this.cwd=e}async setup(){this.manifest=await _t.tryFind(this.cwd)??new _t,this.relativeCwd=K.relative(this.project.cwd,this.cwd)||Bt.dot;let e=this.manifest.name?this.manifest.name:rA(null,`${this.computeCandidateName()}-${zi(this.relativeCwd).substring(0,6)}`);this.anchoredDescriptor=kn(e,`${ci.protocol}${this.relativeCwd}`),this.anchoredLocator=Ss(e,`${ci.protocol}${this.relativeCwd}`);let r=this.manifest.workspaceDefinitions.map(({pattern:a})=>a);if(r.length===0)return;let o=await(0,Nhe.default)(r,{cwd:Ae.fromPortablePath(this.cwd),onlyDirectories:!0,ignore:["**/node_modules","**/.git","**/.yarn"]});o.sort(),await o.reduce(async(a,n)=>{let u=K.resolve(this.cwd,Ae.toPortablePath(n)),A=await ae.existsPromise(K.join(u,"package.json"));await a,A&&this.workspacesCwds.add(u)},Promise.resolve())}get anchoredPackage(){let e=this.project.storedPackages.get(this.anchoredLocator.locatorHash);if(!e)throw new Error(`Assertion failed: Expected workspace ${P1(this.project.configuration,this)} (${Ut(this.project.configuration,K.join(this.cwd,mr.manifest),Ct.PATH)}) to have been resolved. Run "yarn install" to update the lockfile`);return e}accepts(e){let r=e.indexOf(":"),o=r!==-1?e.slice(0,r+1):null,a=r!==-1?e.slice(r+1):e;if(o===ci.protocol&&K.normalize(a)===this.relativeCwd||o===ci.protocol&&(a==="*"||a==="^"||a==="~"))return!0;let n=Fa(a);return n?o===ci.protocol?n.test(this.manifest.version??"0.0.0"):this.project.configuration.get("enableTransparentWorkspaces")&&this.manifest.version!==null?n.test(this.manifest.version):!1:!1}computeCandidateName(){return this.cwd===this.project.cwd?"root-workspace":`${K.basename(this.cwd)}`||"unnamed-workspace"}getRecursiveWorkspaceDependencies({dependencies:e=_t.hardDependencies}={}){let r=new Set,o=a=>{for(let n of e)for(let u of a.manifest[n].values()){let A=this.project.tryWorkspaceByDescriptor(u);A===null||r.has(A)||(r.add(A),o(A))}};return o(this),r}getRecursiveWorkspaceDependents({dependencies:e=_t.hardDependencies}={}){let r=new Set,o=a=>{for(let n of this.project.workspaces)e.some(A=>[...n.manifest[A].values()].some(p=>{let h=this.project.tryWorkspaceByDescriptor(p);return h!==null&&B1(h.anchoredLocator,a.anchoredLocator)}))&&!r.has(n)&&(r.add(n),o(n))};return o(this),r}getRecursiveWorkspaceChildren(){let e=new Set([this]);for(let r of e)for(let o of r.workspacesCwds){let a=this.project.workspacesByCwd.get(o);a&&e.add(a)}return e.delete(this),Array.from(e)}async persistManifest(){let e={};this.manifest.exportTo(e);let r=K.join(this.cwd,_t.fileName),o=`${JSON.stringify(e,null,this.manifest.indent)} +`;await ae.changeFilePromise(r,o,{automaticNewlines:!0}),this.manifest.raw=e}}});function BAt({project:t,allDescriptors:e,allResolutions:r,allPackages:o,accessibleLocators:a=new Set,optionalBuilds:n=new Set,peerRequirements:u=new Map,peerWarnings:A=[],peerRequirementNodes:p=new Map,volatileDescriptors:h=new Set}){let E=new Map,I=[],D=new Map,x=new Map,C=new Map,T=new Map,L=new Map(t.workspaces.map(ce=>{let ue=ce.anchoredLocator.locatorHash,Ce=o.get(ue);if(typeof Ce>"u")throw new Error("Assertion failed: The workspace should have an associated package");return[ue,E1(Ce)]})),U=()=>{let ce=ae.mktempSync(),ue=K.join(ce,"stacktrace.log"),Ce=String(I.length+1).length,he=I.map((De,Ee)=>`${`${Ee+1}.`.padStart(Ce," ")} ${Qa(De)} +`).join("");throw ae.writeFileSync(ue,he),ae.detachTemp(ce),new zt(45,`Encountered a stack overflow when resolving peer dependencies; cf ${Ae.fromPortablePath(ue)}`)},z=ce=>{let ue=r.get(ce.descriptorHash);if(typeof ue>"u")throw new Error("Assertion failed: The resolution should have been registered");let Ce=o.get(ue);if(!Ce)throw new Error("Assertion failed: The package could not be found");return Ce},te=(ce,ue,Ce,{top:he,optional:De})=>{I.length>1e3&&U(),I.push(ue);let Ee=le(ce,ue,Ce,{top:he,optional:De});return I.pop(),Ee},le=(ce,ue,Ce,{top:he,optional:De})=>{if(De||n.delete(ue.locatorHash),a.has(ue.locatorHash))return;a.add(ue.locatorHash);let Ee=o.get(ue.locatorHash);if(!Ee)throw new Error(`Assertion failed: The package (${jr(t.configuration,ue)}) should have been registered`);let g=[],me=new Map,we=[],fe=[],ie=[],Z=[];for(let Re of Array.from(Ee.dependencies.values())){if(Ee.peerDependencies.has(Re.identHash)&&Ee.locatorHash!==he)continue;if(Pf(Re))throw new Error("Assertion failed: Virtual packages shouldn't be encountered when virtualizing a branch");h.delete(Re.descriptorHash);let gt=De;if(!gt){let Se=Ee.dependenciesMeta.get(rn(Re));if(typeof Se<"u"){let tt=Se.get(null);typeof tt<"u"&&tt.optional&&(gt=!0)}}let q=r.get(Re.descriptorHash);if(!q)throw new Error(`Assertion failed: The resolution (${zn(t.configuration,Re)}) should have been registered`);let nt=L.get(q)||o.get(q);if(!nt)throw new Error(`Assertion failed: The package (${q}, resolved from ${zn(t.configuration,Re)}) should have been registered`);if(nt.peerDependencies.size===0){te(Re,nt,new Map,{top:he,optional:gt});continue}let Ne,Te,ke=new Set,Ve=new Map;we.push(()=>{Ne=OO(Re,ue.locatorHash),Te=UO(nt,ue.locatorHash),Ee.dependencies.delete(Re.identHash),Ee.dependencies.set(Ne.identHash,Ne),r.set(Ne.descriptorHash,Te.locatorHash),e.set(Ne.descriptorHash,Ne),o.set(Te.locatorHash,Te),g.push([nt,Ne,Te])}),fe.push(()=>{T.set(Te.locatorHash,Ve);for(let Se of Te.peerDependencies.values()){let He=Al(me,Se.identHash,()=>{let b=Ce.get(Se.identHash)??null,w=Ee.dependencies.get(Se.identHash);return!w&&I1(ue,Se)&&(ce.identHash===ue.identHash?w=ce:(w=kn(ue,ce.range),e.set(w.descriptorHash,w),r.set(w.descriptorHash,ue.locatorHash),h.delete(w.descriptorHash),b=null)),w||(w=kn(Se,"missing:")),{subject:ue,ident:Se,provided:w,root:!b,requests:new Map,hash:`p${zi(ue.locatorHash,Se.identHash).slice(0,5)}`}}).provided;if(He.range==="missing:"&&Te.dependencies.has(Se.identHash)){Te.peerDependencies.delete(Se.identHash);continue}Ve.set(Se.identHash,{requester:Te,descriptor:Se,meta:Te.peerDependenciesMeta.get(rn(Se)),children:new Map}),Te.dependencies.set(Se.identHash,He),Pf(He)&&zm(C,He.descriptorHash).add(Te.locatorHash),D.set(He.identHash,He),He.range==="missing:"&&ke.add(He.identHash)}Te.dependencies=new Map(Ps(Te.dependencies,([Se,tt])=>rn(tt)))}),ie.push(()=>{if(!o.has(Te.locatorHash))return;let Se=E.get(nt.locatorHash);typeof Se=="number"&&Se>=2&&U();let tt=E.get(nt.locatorHash),He=typeof tt<"u"?tt+1:1;E.set(nt.locatorHash,He),te(Ne,Te,Ve,{top:he,optional:gt}),E.set(nt.locatorHash,He-1)}),Z.push(()=>{let Se=Ee.dependencies.get(Re.identHash);if(typeof Se>"u")throw new Error("Assertion failed: Expected the peer dependency to have been turned into a dependency");let tt=r.get(Se.descriptorHash);if(typeof tt>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let He=T.get(tt);if(typeof He>"u")throw new Error("Assertion failed: Expected the peer requests to be registered");for(let b of me.values()){let w=He.get(b.ident.identHash);w&&(b.requests.set(Se.descriptorHash,w),p.set(b.hash,b),b.root||Ce.get(b.ident.identHash)?.children.set(Se.descriptorHash,w))}if(o.has(Te.locatorHash))for(let b of ke)Te.dependencies.delete(b)})}for(let Re of[...we,...fe])Re();let xe;do{xe=!0;for(let[Re,gt,q]of g){let nt=A1(x,Re.locatorHash),Ne=zi(...[...q.dependencies.values()].map(Se=>{let tt=Se.range!=="missing:"?r.get(Se.descriptorHash):"missing:";if(typeof tt>"u")throw new Error(`Assertion failed: Expected the resolution for ${zn(t.configuration,Se)} to have been registered`);return tt===he?`${tt} (top)`:tt}),gt.identHash),Te=nt.get(Ne);if(typeof Te>"u"){nt.set(Ne,gt);continue}if(Te===gt)continue;o.delete(q.locatorHash),e.delete(gt.descriptorHash),r.delete(gt.descriptorHash),a.delete(q.locatorHash);let ke=C.get(gt.descriptorHash)||[],Ve=[Ee.locatorHash,...ke];C.delete(gt.descriptorHash);for(let Se of Ve){let tt=o.get(Se);typeof tt>"u"||(tt.dependencies.get(gt.identHash).descriptorHash!==Te.descriptorHash&&(xe=!1),tt.dependencies.set(gt.identHash,Te))}for(let Se of me.values())Se.provided.descriptorHash===gt.descriptorHash&&(Se.provided=Te)}}while(!xe);for(let Re of[...ie,...Z])Re()};for(let ce of t.workspaces){let ue=ce.anchoredLocator;h.delete(ce.anchoredDescriptor.descriptorHash),te(ce.anchoredDescriptor,ue,new Map,{top:ue.locatorHash,optional:!1})}for(let ce of p.values()){if(!ce.root)continue;let ue=o.get(ce.subject.locatorHash);if(typeof ue>"u")continue;for(let he of ce.requests.values()){let De=`p${zi(ce.subject.locatorHash,rn(ce.ident),he.requester.locatorHash).slice(0,5)}`;u.set(De,{subject:ce.subject.locatorHash,requested:ce.ident,rootRequester:he.requester.locatorHash,allRequesters:Array.from(S1(he),Ee=>Ee.requester.locatorHash)})}let Ce=[...S1(ce)];if(ce.provided.range!=="missing:"){let he=z(ce.provided),De=he.version??"0.0.0",Ee=me=>{if(me.startsWith(ci.protocol)){if(!t.tryWorkspaceByLocator(he))return null;me=me.slice(ci.protocol.length),(me==="^"||me==="~")&&(me="*")}return me},g=!0;for(let me of Ce){let we=Ee(me.descriptor.range);if(we===null){g=!1;continue}if(!nA(De,we)){g=!1;let fe=`p${zi(ce.subject.locatorHash,rn(ce.ident),me.requester.locatorHash).slice(0,5)}`;A.push({type:1,subject:ue,requested:ce.ident,requester:me.requester,version:De,hash:fe,requirementCount:Ce.length})}}if(!g){let me=Ce.map(we=>Ee(we.descriptor.range));A.push({type:3,node:ce,range:me.includes(null)?null:qO(me),hash:ce.hash})}}else{let he=!0;for(let De of Ce)if(!De.meta?.optional){he=!1;let Ee=`p${zi(ce.subject.locatorHash,rn(ce.ident),De.requester.locatorHash).slice(0,5)}`;A.push({type:0,subject:ue,requested:ce.ident,requester:De.requester,hash:Ee})}he||A.push({type:2,node:ce,hash:ce.hash})}}}function*vAt(t){let e=new Map;if("children"in t)e.set(t,t);else for(let r of t.requests.values())e.set(r,r);for(let[r,o]of e){yield{request:r,root:o};for(let a of r.children.values())e.has(a)||e.set(a,o)}}function DAt(t,e){let r=[],o=[],a=!1;for(let n of t.peerWarnings)if(!(n.type===1||n.type===0)){if(!t.tryWorkspaceByLocator(n.node.subject)){a=!0;continue}if(n.type===3){let u=t.storedResolutions.get(n.node.provided.descriptorHash);if(typeof u>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let A=t.storedPackages.get(u);if(typeof A>"u")throw new Error("Assertion failed: Expected the package to be registered");let p=eh(vAt(n.node),({request:I,root:D})=>nA(A.version??"0.0.0",I.descriptor.range)?eh.skip:I===D?Ui(t.configuration,I.requester):`${Ui(t.configuration,I.requester)} (via ${Ui(t.configuration,D.requester)})`),h=[...S1(n.node)].length>1?"and other dependencies request":"requests",E=n.range?cy(t.configuration,n.range):Ut(t.configuration,"but they have non-overlapping ranges!","redBright");r.push(`${Ui(t.configuration,n.node.ident)} is listed by your project with version ${D1(t.configuration,A.version??"0.0.0")} (${Ut(t.configuration,n.hash,Ct.CODE)}), which doesn't satisfy what ${p} ${h} (${E}).`)}if(n.type===2){let u=n.node.requests.size>1?" and other dependencies":"";o.push(`${jr(t.configuration,n.node.subject)} doesn't provide ${Ui(t.configuration,n.node.ident)} (${Ut(t.configuration,n.hash,Ct.CODE)}), requested by ${Ui(t.configuration,n.node.requests.values().next().value.requester)}${u}.`)}}e.startSectionSync({reportFooter:()=>{e.reportWarning(86,`Some peer dependencies are incorrectly met by your project; run ${Ut(t.configuration,"yarn explain peer-requirements ",Ct.CODE)} for details, where ${Ut(t.configuration,"",Ct.CODE)} is the six-letter p-prefixed code.`)},skipIfEmpty:!0},()=>{for(let n of Ps(r,u=>ey.default(u)))e.reportWarning(60,n);for(let n of Ps(o,u=>ey.default(u)))e.reportWarning(2,n)}),a&&e.reportWarning(86,`Some peer dependencies are incorrectly met by dependencies; run ${Ut(t.configuration,"yarn explain peer-requirements",Ct.CODE)} for details.`)}var Qk,Fk,Rk,Ohe,h8,p8,g8,Tk,yAt,EAt,Lhe,CAt,wAt,IAt,yl,f8,Nk,Mhe,Qt,Uhe=wt(()=>{Pt();Pt();Ml();Gt();Qk=ve("crypto");n8();Fk=et(c8()),Rk=et(lg()),Ohe=et(ni()),h8=ve("util"),p8=et(ve("v8")),g8=et(ve("zlib"));V_();Y1();z_();J_();Ay();KO();Vl();The();n2();u8();Dg();A8();Db();Yl();ah();Gl();nx();a3();xf();wo();Tk=Zm(process.env.YARN_LOCKFILE_VERSION_OVERRIDE??8),yAt=3,EAt=/ *, */g,Lhe=/\/$/,CAt=32,wAt=(0,h8.promisify)(g8.default.gzip),IAt=(0,h8.promisify)(g8.default.gunzip),yl=(r=>(r.UpdateLockfile="update-lockfile",r.SkipBuild="skip-build",r))(yl||{}),f8={restoreLinkersCustomData:["linkersCustomData"],restoreResolutions:["accessibleLocators","conditionalLocators","disabledLocators","optionalBuilds","storedDescriptors","storedResolutions","storedPackages","lockFileChecksum"],restoreBuildState:["skippedBuilds","storedBuildState"]},Nk=(a=>(a[a.NotProvided=0]="NotProvided",a[a.NotCompatible=1]="NotCompatible",a[a.NodeNotProvided=2]="NodeNotProvided",a[a.NodeNotCompatible=3]="NodeNotCompatible",a))(Nk||{}),Mhe=t=>zi(`${yAt}`,t),Qt=class t{constructor(e,{configuration:r}){this.resolutionAliases=new Map;this.workspaces=[];this.workspacesByCwd=new Map;this.workspacesByIdent=new Map;this.storedResolutions=new Map;this.storedDescriptors=new Map;this.storedPackages=new Map;this.storedChecksums=new Map;this.storedBuildState=new Map;this.accessibleLocators=new Set;this.conditionalLocators=new Set;this.disabledLocators=new Set;this.originalPackages=new Map;this.optionalBuilds=new Set;this.skippedBuilds=new Set;this.lockfileLastVersion=null;this.lockfileNeedsRefresh=!1;this.peerRequirements=new Map;this.peerWarnings=[];this.peerRequirementNodes=new Map;this.linkersCustomData=new Map;this.lockFileChecksum=null;this.installStateChecksum=null;this.configuration=r,this.cwd=e}static async find(e,r){if(!e.projectCwd)throw new ot(`No project found in ${r}`);let o=e.projectCwd,a=r,n=null;for(;n!==e.projectCwd;){if(n=a,ae.existsSync(K.join(n,mr.manifest))){o=n;break}a=K.dirname(n)}let u=new t(e.projectCwd,{configuration:e});Je.telemetry?.reportProject(u.cwd),await u.setupResolutions(),await u.setupWorkspaces(),Je.telemetry?.reportWorkspaceCount(u.workspaces.length),Je.telemetry?.reportDependencyCount(u.workspaces.reduce((C,T)=>C+T.manifest.dependencies.size+T.manifest.devDependencies.size,0));let A=u.tryWorkspaceByCwd(o);if(A)return{project:u,workspace:A,locator:A.anchoredLocator};let p=await u.findLocatorForLocation(`${o}/`,{strict:!0});if(p)return{project:u,locator:p,workspace:null};let h=Ut(e,u.cwd,Ct.PATH),E=Ut(e,K.relative(u.cwd,o),Ct.PATH),I=`- If ${h} isn't intended to be a project, remove any yarn.lock and/or package.json file there.`,D=`- If ${h} is intended to be a project, it might be that you forgot to list ${E} in its workspace configuration.`,x=`- Finally, if ${h} is fine and you intend ${E} to be treated as a completely separate project (not even a workspace), create an empty yarn.lock file in it.`;throw new ot(`The nearest package directory (${Ut(e,o,Ct.PATH)}) doesn't seem to be part of the project declared in ${Ut(e,u.cwd,Ct.PATH)}. + +${[I,D,x].join(` +`)}`)}async setupResolutions(){this.storedResolutions=new Map,this.storedDescriptors=new Map,this.storedPackages=new Map,this.lockFileChecksum=null;let e=K.join(this.cwd,mr.lockfile),r=this.configuration.get("defaultLanguageName");if(ae.existsSync(e)){let o=await ae.readFilePromise(e,"utf8");this.lockFileChecksum=Mhe(o);let a=Ki(o);if(a.__metadata){let n=a.__metadata.version,u=a.__metadata.cacheKey;this.lockfileLastVersion=n,this.lockfileNeedsRefresh=n"u")throw new Error(`Assertion failed: Expected the lockfile entry to have a resolution field (${A})`);let h=Sf(p.resolution,!0),E=new _t;E.load(p,{yamlCompatibilityMode:!0});let I=E.version,D=E.languageName||r,x=p.linkType.toUpperCase(),C=p.conditions??null,T=E.dependencies,L=E.peerDependencies,U=E.dependenciesMeta,z=E.peerDependenciesMeta,te=E.bin;if(p.checksum!=null){let ce=typeof u<"u"&&!p.checksum.includes("/")?`${u}/${p.checksum}`:p.checksum;this.storedChecksums.set(h.locatorHash,ce)}let le={...h,version:I,languageName:D,linkType:x,conditions:C,dependencies:T,peerDependencies:L,dependenciesMeta:U,peerDependenciesMeta:z,bin:te};this.originalPackages.set(le.locatorHash,le);for(let ce of A.split(EAt)){let ue=lh(ce);n<=6&&(ue=this.configuration.normalizeDependency(ue),ue=kn(ue,ue.range.replace(/^patch:[^@]+@(?!npm(:|%3A))/,"$1npm%3A"))),this.storedDescriptors.set(ue.descriptorHash,ue),this.storedResolutions.set(ue.descriptorHash,h.locatorHash)}}}else o.includes("yarn lockfile v1")&&(this.lockfileLastVersion=-1)}}async setupWorkspaces(){this.workspaces=[],this.workspacesByCwd=new Map,this.workspacesByIdent=new Map;let e=new Set,r=(0,Rk.default)(4),o=async(a,n)=>{if(e.has(n))return a;e.add(n);let u=new iE(n,{project:this});await r(()=>u.setup());let A=a.then(()=>{this.addWorkspace(u)});return Array.from(u.workspacesCwds).reduce(o,A)};await o(Promise.resolve(),this.cwd)}addWorkspace(e){let r=this.workspacesByIdent.get(e.anchoredLocator.identHash);if(typeof r<"u")throw new Error(`Duplicate workspace name ${Ui(this.configuration,e.anchoredLocator)}: ${Ae.fromPortablePath(e.cwd)} conflicts with ${Ae.fromPortablePath(r.cwd)}`);this.workspaces.push(e),this.workspacesByCwd.set(e.cwd,e),this.workspacesByIdent.set(e.anchoredLocator.identHash,e)}get topLevelWorkspace(){return this.getWorkspaceByCwd(this.cwd)}tryWorkspaceByCwd(e){K.isAbsolute(e)||(e=K.resolve(this.cwd,e)),e=K.normalize(e).replace(/\/+$/,"");let r=this.workspacesByCwd.get(e);return r||null}getWorkspaceByCwd(e){let r=this.tryWorkspaceByCwd(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByFilePath(e){let r=null;for(let o of this.workspaces)K.relative(o.cwd,e).startsWith("../")||r&&r.cwd.length>=o.cwd.length||(r=o);return r||null}getWorkspaceByFilePath(e){let r=this.tryWorkspaceByFilePath(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByIdent(e){let r=this.workspacesByIdent.get(e.identHash);return typeof r>"u"?null:r}getWorkspaceByIdent(e){let r=this.tryWorkspaceByIdent(e);if(!r)throw new Error(`Workspace not found (${Ui(this.configuration,e)})`);return r}tryWorkspaceByDescriptor(e){if(e.range.startsWith(ci.protocol)){let o=e.range.slice(ci.protocol.length);if(o!=="^"&&o!=="~"&&o!=="*"&&!Fa(o))return this.tryWorkspaceByCwd(o)}let r=this.tryWorkspaceByIdent(e);return r===null||(Pf(e)&&(e=C1(e)),!r.accepts(e.range))?null:r}getWorkspaceByDescriptor(e){let r=this.tryWorkspaceByDescriptor(e);if(r===null)throw new Error(`Workspace not found (${zn(this.configuration,e)})`);return r}tryWorkspaceByLocator(e){let r=this.tryWorkspaceByIdent(e);return r===null||(zc(e)&&(e=w1(e)),r.anchoredLocator.locatorHash!==e.locatorHash)?null:r}getWorkspaceByLocator(e){let r=this.tryWorkspaceByLocator(e);if(!r)throw new Error(`Workspace not found (${jr(this.configuration,e)})`);return r}deleteDescriptor(e){this.storedResolutions.delete(e),this.storedDescriptors.delete(e)}deleteLocator(e){this.originalPackages.delete(e),this.storedPackages.delete(e),this.accessibleLocators.delete(e)}forgetResolution(e){if("descriptorHash"in e){let r=this.storedResolutions.get(e.descriptorHash);this.deleteDescriptor(e.descriptorHash);let o=new Set(this.storedResolutions.values());typeof r<"u"&&!o.has(r)&&this.deleteLocator(r)}if("locatorHash"in e){this.deleteLocator(e.locatorHash);for(let[r,o]of this.storedResolutions)o===e.locatorHash&&this.deleteDescriptor(r)}}forgetTransientResolutions(){let e=this.configuration.makeResolver(),r=new Map;for(let[o,a]of this.storedResolutions.entries()){let n=r.get(a);n||r.set(a,n=new Set),n.add(o)}for(let o of this.originalPackages.values()){let a;try{a=e.shouldPersistResolution(o,{project:this,resolver:e})}catch{a=!1}if(!a){this.deleteLocator(o.locatorHash);let n=r.get(o.locatorHash);if(n){r.delete(o.locatorHash);for(let u of n)this.deleteDescriptor(u)}}}}forgetVirtualResolutions(){for(let e of this.storedPackages.values())for(let[r,o]of e.dependencies)Pf(o)&&e.dependencies.set(r,C1(o))}getDependencyMeta(e,r){let o={},n=this.topLevelWorkspace.manifest.dependenciesMeta.get(rn(e));if(!n)return o;let u=n.get(null);if(u&&Object.assign(o,u),r===null||!Ohe.default.valid(r))return o;for(let[A,p]of n)A!==null&&A===r&&Object.assign(o,p);return o}async findLocatorForLocation(e,{strict:r=!1}={}){let o=new Ri,a=this.configuration.getLinkers(),n={project:this,report:o};for(let u of a){let A=await u.findPackageLocator(e,n);if(A){if(r&&(await u.findPackageLocation(A,n)).replace(Lhe,"")!==e.replace(Lhe,""))continue;return A}}return null}async loadUserConfig(){let e=K.join(this.cwd,".pnp.cjs");await ae.existsPromise(e)&&vf(e).setup();let r=K.join(this.cwd,"yarn.config.cjs");return await ae.existsPromise(r)?vf(r):null}async preparePackage(e,{resolver:r,resolveOptions:o}){let a=await this.configuration.getPackageExtensions(),n=this.configuration.normalizePackage(e,{packageExtensions:a});for(let[u,A]of n.dependencies){let p=await this.configuration.reduceHook(E=>E.reduceDependency,A,this,n,A,{resolver:r,resolveOptions:o});if(!I1(A,p))throw new Error("Assertion failed: The descriptor ident cannot be changed through aliases");let h=r.bindDescriptor(p,n,o);n.dependencies.set(u,h)}return n}async resolveEverything(e){if(!this.workspacesByCwd||!this.workspacesByIdent)throw new Error("Workspaces must have been setup before calling this function");this.forgetVirtualResolutions();let r=new Map(this.originalPackages),o=[];e.lockfileOnly||this.forgetTransientResolutions();let a=e.resolver||this.configuration.makeResolver(),n=new tE(a);await n.setup(this,{report:e.report});let u=e.lockfileOnly?[new kk(a)]:[n,a],A=new Pg([new rE(a),...u]),p=new Pg([...u]),h=this.configuration.makeFetcher(),E=e.lockfileOnly?{project:this,report:e.report,resolver:A}:{project:this,report:e.report,resolver:A,fetchOptions:{project:this,cache:e.cache,checksums:this.storedChecksums,report:e.report,fetcher:h,cacheOptions:{mirrorWriteOnly:!0}}},I=new Map,D=new Map,x=new Map,C=new Map,T=new Map,L=new Map,U=this.topLevelWorkspace.anchoredLocator,z=new Set,te=[],le=wU(),ce=this.configuration.getSupportedArchitectures();await e.report.startProgressPromise(Ys.progressViaTitle(),async ie=>{let Z=async nt=>{let Ne=await Jm(async()=>await A.resolve(nt,E),Se=>`${jr(this.configuration,nt)}: ${Se}`);if(!B1(nt,Ne))throw new Error(`Assertion failed: The locator cannot be changed by the resolver (went from ${jr(this.configuration,nt)} to ${jr(this.configuration,Ne)})`);C.set(Ne.locatorHash,Ne),!r.delete(Ne.locatorHash)&&!this.tryWorkspaceByLocator(Ne)&&o.push(Ne);let ke=await this.preparePackage(Ne,{resolver:A,resolveOptions:E}),Ve=Yc([...ke.dependencies.values()].map(Se=>q(Se)));return te.push(Ve),Ve.catch(()=>{}),D.set(ke.locatorHash,ke),ke},xe=async nt=>{let Ne=T.get(nt.locatorHash);if(typeof Ne<"u")return Ne;let Te=Promise.resolve().then(()=>Z(nt));return T.set(nt.locatorHash,Te),Te},Re=async(nt,Ne)=>{let Te=await q(Ne);return I.set(nt.descriptorHash,nt),x.set(nt.descriptorHash,Te.locatorHash),Te},gt=async nt=>{ie.setTitle(zn(this.configuration,nt));let Ne=this.resolutionAliases.get(nt.descriptorHash);if(typeof Ne<"u")return Re(nt,this.storedDescriptors.get(Ne));let Te=A.getResolutionDependencies(nt,E),ke=Object.fromEntries(await Yc(Object.entries(Te).map(async([tt,He])=>{let b=A.bindDescriptor(He,U,E),w=await q(b);return z.add(w.locatorHash),[tt,w]}))),Se=(await Jm(async()=>await A.getCandidates(nt,ke,E),tt=>`${zn(this.configuration,nt)}: ${tt}`))[0];if(typeof Se>"u")throw new zt(82,`${zn(this.configuration,nt)}: No candidates found`);if(e.checkResolutions){let{locators:tt}=await p.getSatisfying(nt,ke,[Se],{...E,resolver:p});if(!tt.find(He=>He.locatorHash===Se.locatorHash))throw new zt(78,`Invalid resolution ${d1(this.configuration,nt,Se)}`)}return I.set(nt.descriptorHash,nt),x.set(nt.descriptorHash,Se.locatorHash),xe(Se)},q=nt=>{let Ne=L.get(nt.descriptorHash);if(typeof Ne<"u")return Ne;I.set(nt.descriptorHash,nt);let Te=Promise.resolve().then(()=>gt(nt));return L.set(nt.descriptorHash,Te),Te};for(let nt of this.workspaces){let Ne=nt.anchoredDescriptor;te.push(q(Ne))}for(;te.length>0;){let nt=[...te];te.length=0,await Yc(nt)}});let ue=ul(r.values(),ie=>this.tryWorkspaceByLocator(ie)?ul.skip:ie);if(o.length>0||ue.length>0){let ie=new Set(this.workspaces.flatMap(nt=>{let Ne=D.get(nt.anchoredLocator.locatorHash);if(!Ne)throw new Error("Assertion failed: The workspace should have been resolved");return Array.from(Ne.dependencies.values(),Te=>{let ke=x.get(Te.descriptorHash);if(!ke)throw new Error("Assertion failed: The resolution should have been registered");return ke})})),Z=nt=>ie.has(nt.locatorHash)?"0":"1",xe=nt=>Qa(nt),Re=Ps(o,[Z,xe]),gt=Ps(ue,[Z,xe]),q=e.report.getRecommendedLength();Re.length>0&&e.report.reportInfo(85,`${Ut(this.configuration,"+",Ct.ADDED)} ${_S(this.configuration,Re,q)}`),gt.length>0&&e.report.reportInfo(85,`${Ut(this.configuration,"-",Ct.REMOVED)} ${_S(this.configuration,gt,q)}`)}let Ce=new Set(this.resolutionAliases.values()),he=new Set(D.keys()),De=new Set,Ee=new Map,g=[],me=new Map;BAt({project:this,accessibleLocators:De,volatileDescriptors:Ce,optionalBuilds:he,peerRequirements:Ee,peerWarnings:g,peerRequirementNodes:me,allDescriptors:I,allResolutions:x,allPackages:D});for(let ie of z)he.delete(ie);for(let ie of Ce)I.delete(ie),x.delete(ie);let we=new Set,fe=new Set;for(let ie of D.values())ie.conditions!=null&&he.has(ie.locatorHash)&&(Cb(ie,ce)||(Cb(ie,le)&&e.report.reportWarningOnce(77,`${jr(this.configuration,ie)}: Your current architecture (${process.platform}-${process.arch}) is supported by this package, but is missing from the ${Ut(this.configuration,"supportedArchitectures",Ct.SETTING)} setting`),fe.add(ie.locatorHash)),we.add(ie.locatorHash));this.storedResolutions=x,this.storedDescriptors=I,this.storedPackages=D,this.accessibleLocators=De,this.conditionalLocators=we,this.disabledLocators=fe,this.originalPackages=C,this.optionalBuilds=he,this.peerRequirements=Ee,this.peerWarnings=g,this.peerRequirementNodes=me}async fetchEverything({cache:e,report:r,fetcher:o,mode:a,persistProject:n=!0}){let u={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators},A=o||this.configuration.makeFetcher(),p={checksums:this.storedChecksums,project:this,cache:e,fetcher:A,report:r,cacheOptions:u},h=Array.from(new Set(Ps(this.storedResolutions.values(),[C=>{let T=this.storedPackages.get(C);if(!T)throw new Error("Assertion failed: The locator should have been registered");return Qa(T)}])));a==="update-lockfile"&&(h=h.filter(C=>!this.storedChecksums.has(C)));let E=!1,I=Ys.progressViaCounter(h.length);await r.reportProgress(I);let D=(0,Rk.default)(CAt);if(await Yc(h.map(C=>D(async()=>{let T=this.storedPackages.get(C);if(!T)throw new Error("Assertion failed: The locator should have been registered");if(zc(T))return;let L;try{L=await A.fetch(T,p)}catch(U){U.message=`${jr(this.configuration,T)}: ${U.message}`,r.reportExceptionOnce(U),E=U;return}L.checksum!=null?this.storedChecksums.set(T.locatorHash,L.checksum):this.storedChecksums.delete(T.locatorHash),L.releaseFs&&L.releaseFs()}).finally(()=>{I.tick()}))),E)throw E;let x=n&&a!=="update-lockfile"?await this.cacheCleanup({cache:e,report:r}):null;if(r.cacheMisses.size>0||x){let T=(await Promise.all([...r.cacheMisses].map(async ue=>{let Ce=this.storedPackages.get(ue),he=this.storedChecksums.get(ue)??null,De=e.getLocatorPath(Ce,he);return(await ae.statPromise(De)).size}))).reduce((ue,Ce)=>ue+Ce,0)-(x?.size??0),L=r.cacheMisses.size,U=x?.count??0,z=`${TS(L,{zero:"No new packages",one:"A package was",more:`${Ut(this.configuration,L,Ct.NUMBER)} packages were`})} added to the project`,te=`${TS(U,{zero:"none were",one:"one was",more:`${Ut(this.configuration,U,Ct.NUMBER)} were`})} removed`,le=T!==0?` (${Ut(this.configuration,T,Ct.SIZE_DIFF)})`:"",ce=U>0?L>0?`${z}, and ${te}${le}.`:`${z}, but ${te}${le}.`:`${z}${le}.`;r.reportInfo(13,ce)}}async linkEverything({cache:e,report:r,fetcher:o,mode:a}){let n={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators,skipIntegrityCheck:!0},u=o||this.configuration.makeFetcher(),A={checksums:this.storedChecksums,project:this,cache:e,fetcher:u,report:r,cacheOptions:n},p=this.configuration.getLinkers(),h={project:this,report:r},E=new Map(p.map(we=>{let fe=we.makeInstaller(h),ie=we.getCustomDataKey(),Z=this.linkersCustomData.get(ie);return typeof Z<"u"&&fe.attachCustomData(Z),[we,fe]})),I=new Map,D=new Map,x=new Map,C=new Map(await Yc([...this.accessibleLocators].map(async we=>{let fe=this.storedPackages.get(we);if(!fe)throw new Error("Assertion failed: The locator should have been registered");return[we,await u.fetch(fe,A)]}))),T=[],L=new Set,U=[];for(let we of this.accessibleLocators){let fe=this.storedPackages.get(we);if(typeof fe>"u")throw new Error("Assertion failed: The locator should have been registered");let ie=C.get(fe.locatorHash);if(typeof ie>"u")throw new Error("Assertion failed: The fetch result should have been registered");let Z=[],xe=gt=>{Z.push(gt)},Re=this.tryWorkspaceByLocator(fe);if(Re!==null){let gt=[],{scripts:q}=Re.manifest;for(let Ne of["preinstall","install","postinstall"])q.has(Ne)&>.push({type:0,script:Ne});try{for(let[Ne,Te]of E)if(Ne.supportsPackage(fe,h)&&(await Te.installPackage(fe,ie,{holdFetchResult:xe})).buildRequest!==null)throw new Error("Assertion failed: Linkers can't return build directives for workspaces; this responsibility befalls to the Yarn core")}finally{Z.length===0?ie.releaseFs?.():T.push(Yc(Z).catch(()=>{}).then(()=>{ie.releaseFs?.()}))}let nt=K.join(ie.packageFs.getRealPath(),ie.prefixPath);D.set(fe.locatorHash,nt),!zc(fe)&>.length>0&&x.set(fe.locatorHash,{buildDirectives:gt,buildLocations:[nt]})}else{let gt=p.find(Ne=>Ne.supportsPackage(fe,h));if(!gt)throw new zt(12,`${jr(this.configuration,fe)} isn't supported by any available linker`);let q=E.get(gt);if(!q)throw new Error("Assertion failed: The installer should have been registered");let nt;try{nt=await q.installPackage(fe,ie,{holdFetchResult:xe})}finally{Z.length===0?ie.releaseFs?.():T.push(Yc(Z).then(()=>{}).then(()=>{ie.releaseFs?.()}))}I.set(fe.locatorHash,gt),D.set(fe.locatorHash,nt.packageLocation),nt.buildRequest&&nt.packageLocation&&(nt.buildRequest.skipped?(L.add(fe.locatorHash),this.skippedBuilds.has(fe.locatorHash)||U.push([fe,nt.buildRequest.explain])):x.set(fe.locatorHash,{buildDirectives:nt.buildRequest.directives,buildLocations:[nt.packageLocation]}))}}let z=new Map;for(let we of this.accessibleLocators){let fe=this.storedPackages.get(we);if(!fe)throw new Error("Assertion failed: The locator should have been registered");let ie=this.tryWorkspaceByLocator(fe)!==null,Z=async(xe,Re)=>{let gt=D.get(fe.locatorHash);if(typeof gt>"u")throw new Error(`Assertion failed: The package (${jr(this.configuration,fe)}) should have been registered`);let q=[];for(let nt of fe.dependencies.values()){let Ne=this.storedResolutions.get(nt.descriptorHash);if(typeof Ne>"u")throw new Error(`Assertion failed: The resolution (${zn(this.configuration,nt)}, from ${jr(this.configuration,fe)})should have been registered`);let Te=this.storedPackages.get(Ne);if(typeof Te>"u")throw new Error(`Assertion failed: The package (${Ne}, resolved from ${zn(this.configuration,nt)}) should have been registered`);let ke=this.tryWorkspaceByLocator(Te)===null?I.get(Ne):null;if(typeof ke>"u")throw new Error(`Assertion failed: The package (${Ne}, resolved from ${zn(this.configuration,nt)}) should have been registered`);ke===xe||ke===null?D.get(Te.locatorHash)!==null&&q.push([nt,Te]):!ie&>!==null&&u1(z,Ne).push(gt)}gt!==null&&await Re.attachInternalDependencies(fe,q)};if(ie)for(let[xe,Re]of E)xe.supportsPackage(fe,h)&&await Z(xe,Re);else{let xe=I.get(fe.locatorHash);if(!xe)throw new Error("Assertion failed: The linker should have been found");let Re=E.get(xe);if(!Re)throw new Error("Assertion failed: The installer should have been registered");await Z(xe,Re)}}for(let[we,fe]of z){let ie=this.storedPackages.get(we);if(!ie)throw new Error("Assertion failed: The package should have been registered");let Z=I.get(ie.locatorHash);if(!Z)throw new Error("Assertion failed: The linker should have been found");let xe=E.get(Z);if(!xe)throw new Error("Assertion failed: The installer should have been registered");await xe.attachExternalDependents(ie,fe)}let te=new Map;for(let[we,fe]of E){let ie=await fe.finalizeInstall();for(let Z of ie?.records??[])Z.buildRequest.skipped?(L.add(Z.locator.locatorHash),this.skippedBuilds.has(Z.locator.locatorHash)||U.push([Z.locator,Z.buildRequest.explain])):x.set(Z.locator.locatorHash,{buildDirectives:Z.buildRequest.directives,buildLocations:Z.buildLocations});typeof ie?.customData<"u"&&te.set(we.getCustomDataKey(),ie.customData)}if(this.linkersCustomData=te,await Yc(T),a==="skip-build")return;for(let[,we]of Ps(U,([fe])=>Qa(fe)))we(r);let le=new Set(x.keys()),ce=(0,Qk.createHash)("sha512");ce.update(process.versions.node),await this.configuration.triggerHook(we=>we.globalHashGeneration,this,we=>{ce.update("\0"),ce.update(we)});let ue=ce.digest("hex"),Ce=new Map,he=we=>{let fe=Ce.get(we.locatorHash);if(typeof fe<"u")return fe;let ie=this.storedPackages.get(we.locatorHash);if(typeof ie>"u")throw new Error("Assertion failed: The package should have been registered");let Z=(0,Qk.createHash)("sha512");Z.update(we.locatorHash),Ce.set(we.locatorHash,"");for(let xe of ie.dependencies.values()){let Re=this.storedResolutions.get(xe.descriptorHash);if(typeof Re>"u")throw new Error(`Assertion failed: The resolution (${zn(this.configuration,xe)}) should have been registered`);let gt=this.storedPackages.get(Re);if(typeof gt>"u")throw new Error("Assertion failed: The package should have been registered");Z.update(he(gt))}return fe=Z.digest("hex"),Ce.set(we.locatorHash,fe),fe},De=(we,fe)=>{let ie=(0,Qk.createHash)("sha512");ie.update(ue),ie.update(he(we));for(let Z of fe)ie.update(Z);return ie.digest("hex")},Ee=new Map,g=!1,me=we=>{let fe=new Set([we.locatorHash]);for(let ie of fe){let Z=this.storedPackages.get(ie);if(!Z)throw new Error("Assertion failed: The package should have been registered");for(let xe of Z.dependencies.values()){let Re=this.storedResolutions.get(xe.descriptorHash);if(!Re)throw new Error(`Assertion failed: The resolution (${zn(this.configuration,xe)}) should have been registered`);if(Re!==we.locatorHash&&le.has(Re))return!1;let gt=this.storedPackages.get(Re);if(!gt)throw new Error("Assertion failed: The package should have been registered");let q=this.tryWorkspaceByLocator(gt);if(q){if(q.anchoredLocator.locatorHash!==we.locatorHash&&le.has(q.anchoredLocator.locatorHash))return!1;fe.add(q.anchoredLocator.locatorHash)}fe.add(Re)}}return!0};for(;le.size>0;){let we=le.size,fe=[];for(let ie of le){let Z=this.storedPackages.get(ie);if(!Z)throw new Error("Assertion failed: The package should have been registered");if(!me(Z))continue;let xe=x.get(Z.locatorHash);if(!xe)throw new Error("Assertion failed: The build directive should have been registered");let Re=De(Z,xe.buildLocations);if(this.storedBuildState.get(Z.locatorHash)===Re){Ee.set(Z.locatorHash,Re),le.delete(ie);continue}g||(await this.persistInstallStateFile(),g=!0),this.storedBuildState.has(Z.locatorHash)?r.reportInfo(8,`${jr(this.configuration,Z)} must be rebuilt because its dependency tree changed`):r.reportInfo(7,`${jr(this.configuration,Z)} must be built because it never has been before or the last one failed`);let gt=xe.buildLocations.map(async q=>{if(!K.isAbsolute(q))throw new Error(`Assertion failed: Expected the build location to be absolute (not ${q})`);for(let nt of xe.buildDirectives){let Ne=`# This file contains the result of Yarn building a package (${Qa(Z)}) +`;switch(nt.type){case 0:Ne+=`# Script name: ${nt.script} +`;break;case 1:Ne+=`# Script code: ${nt.script} +`;break}let Te=null;if(!await ae.mktempPromise(async Ve=>{let Se=K.join(Ve,"build.log"),{stdout:tt,stderr:He}=this.configuration.getSubprocessStreams(Se,{header:Ne,prefix:jr(this.configuration,Z),report:r}),b;try{switch(nt.type){case 0:b=await Dx(Z,nt.script,[],{cwd:q,project:this,stdin:Te,stdout:tt,stderr:He});break;case 1:b=await n3(Z,nt.script,[],{cwd:q,project:this,stdin:Te,stdout:tt,stderr:He});break}}catch(y){He.write(y.stack),b=1}if(tt.end(),He.end(),b===0)return!0;ae.detachTemp(Ve);let w=`${jr(this.configuration,Z)} couldn't be built successfully (exit code ${Ut(this.configuration,b,Ct.NUMBER)}, logs can be found here: ${Ut(this.configuration,Se,Ct.PATH)})`,S=this.optionalBuilds.has(Z.locatorHash);return S?r.reportInfo(9,w):r.reportError(9,w),Lue&&r.reportFold(Ae.fromPortablePath(Se),ae.readFileSync(Se,"utf8")),S}))return!1}return!0});fe.push(...gt,Promise.allSettled(gt).then(q=>{le.delete(ie),q.every(nt=>nt.status==="fulfilled"&&nt.value===!0)&&Ee.set(Z.locatorHash,Re)}))}if(await Yc(fe),we===le.size){let ie=Array.from(le).map(Z=>{let xe=this.storedPackages.get(Z);if(!xe)throw new Error("Assertion failed: The package should have been registered");return jr(this.configuration,xe)}).join(", ");r.reportError(3,`Some packages have circular dependencies that make their build order unsatisfiable - as a result they won't be built (affected packages are: ${ie})`);break}}this.storedBuildState=Ee,this.skippedBuilds=L}async installWithNewReport(e,r){return(await Nt.start({configuration:this.configuration,json:e.json,stdout:e.stdout,forceSectionAlignment:!0,includeLogs:!e.json&&!e.quiet,includeVersion:!0},async a=>{await this.install({...r,report:a})})).exitCode()}async install(e){let r=this.configuration.get("nodeLinker");Je.telemetry?.reportInstall(r);let o=!1;if(await e.report.startTimerPromise("Project validation",{skipIfEmpty:!0},async()=>{this.configuration.get("enableOfflineMode")&&e.report.reportWarning(90,"Offline work is enabled; Yarn won't fetch packages from the remote registry if it can avoid it"),await this.configuration.triggerHook(E=>E.validateProject,this,{reportWarning:(E,I)=>{e.report.reportWarning(E,I)},reportError:(E,I)=>{e.report.reportError(E,I),o=!0}})}),o)return;let a=await this.configuration.getPackageExtensions();for(let E of a.values())for(let[,I]of E)for(let D of I)D.status="inactive";let n=K.join(this.cwd,mr.lockfile),u=null;if(e.immutable)try{u=await ae.readFilePromise(n,"utf8")}catch(E){throw E.code==="ENOENT"?new zt(28,"The lockfile would have been created by this install, which is explicitly forbidden."):E}await e.report.startTimerPromise("Resolution step",async()=>{await this.resolveEverything(e)}),await e.report.startTimerPromise("Post-resolution validation",{skipIfEmpty:!0},async()=>{DAt(this,e.report);for(let[,E]of a)for(let[,I]of E)for(let D of I)if(D.userProvided){let x=Ut(this.configuration,D,Ct.PACKAGE_EXTENSION);switch(D.status){case"inactive":e.report.reportWarning(68,`${x}: No matching package in the dependency tree; you may not need this rule anymore.`);break;case"redundant":e.report.reportWarning(69,`${x}: This rule seems redundant when applied on the original package; the extension may have been applied upstream.`);break}}if(u!==null){let E=G0(u,this.generateLockfile());if(E!==u){let I=ehe(n,n,u,E,void 0,void 0,{maxEditLength:100});if(I){e.report.reportSeparator();for(let D of I.hunks){e.report.reportInfo(null,`@@ -${D.oldStart},${D.oldLines} +${D.newStart},${D.newLines} @@`);for(let x of D.lines)x.startsWith("+")?e.report.reportError(28,Ut(this.configuration,x,Ct.ADDED)):x.startsWith("-")?e.report.reportError(28,Ut(this.configuration,x,Ct.REMOVED)):e.report.reportInfo(null,Ut(this.configuration,x,"grey"))}e.report.reportSeparator()}throw new zt(28,"The lockfile would have been modified by this install, which is explicitly forbidden.")}}});for(let E of a.values())for(let[,I]of E)for(let D of I)D.userProvided&&D.status==="active"&&Je.telemetry?.reportPackageExtension(wg(D,Ct.PACKAGE_EXTENSION));await e.report.startTimerPromise("Fetch step",async()=>{await this.fetchEverything(e)});let A=e.immutable?[...new Set(this.configuration.get("immutablePatterns"))].sort():[],p=await Promise.all(A.map(async E=>hb(E,{cwd:this.cwd})));(typeof e.persistProject>"u"||e.persistProject)&&await this.persist(),await e.report.startTimerPromise("Link step",async()=>{if(e.mode==="update-lockfile"){e.report.reportWarning(73,`Skipped due to ${Ut(this.configuration,"mode=update-lockfile",Ct.CODE)}`);return}await this.linkEverything(e);let E=await Promise.all(A.map(async I=>hb(I,{cwd:this.cwd})));for(let I=0;I{await this.configuration.triggerHook(E=>E.validateProjectAfterInstall,this,{reportWarning:(E,I)=>{e.report.reportWarning(E,I)},reportError:(E,I)=>{e.report.reportError(E,I),h=!0}})}),!h&&await this.configuration.triggerHook(E=>E.afterAllInstalled,this,e)}generateLockfile(){let e=new Map;for(let[n,u]of this.storedResolutions.entries()){let A=e.get(u);A||e.set(u,A=new Set),A.add(n)}let r={},{cacheKey:o}=Yr.getCacheKey(this.configuration);r.__metadata={version:Tk,cacheKey:o};for(let[n,u]of e.entries()){let A=this.originalPackages.get(n);if(!A)continue;let p=[];for(let I of u){let D=this.storedDescriptors.get(I);if(!D)throw new Error("Assertion failed: The descriptor should have been registered");p.push(D)}let h=p.map(I=>ka(I)).sort().join(", "),E=new _t;E.version=A.linkType==="HARD"?A.version:"0.0.0-use.local",E.languageName=A.languageName,E.dependencies=new Map(A.dependencies),E.peerDependencies=new Map(A.peerDependencies),E.dependenciesMeta=new Map(A.dependenciesMeta),E.peerDependenciesMeta=new Map(A.peerDependenciesMeta),E.bin=new Map(A.bin),r[h]={...E.exportTo({},{compatibilityMode:!1}),linkType:A.linkType.toLowerCase(),resolution:Qa(A),checksum:this.storedChecksums.get(A.locatorHash),conditions:A.conditions||void 0}}return`${[`# This file is generated by running "yarn install" inside your project. +`,`# Manual changes might be lost - proceed with caution! +`].join("")} +`+Pa(r)}async persistLockfile(){let e=K.join(this.cwd,mr.lockfile),r="";try{r=await ae.readFilePromise(e,"utf8")}catch{}let o=this.generateLockfile(),a=G0(r,o);a!==r&&(await ae.writeFilePromise(e,a),this.lockFileChecksum=Mhe(a),this.lockfileNeedsRefresh=!1)}async persistInstallStateFile(){let e=[];for(let u of Object.values(f8))e.push(...u);let r=(0,Fk.default)(this,e),o=p8.default.serialize(r),a=zi(o);if(this.installStateChecksum===a)return;let n=this.configuration.get("installStatePath");await ae.mkdirPromise(K.dirname(n),{recursive:!0}),await ae.writeFilePromise(n,await wAt(o)),this.installStateChecksum=a}async restoreInstallState({restoreLinkersCustomData:e=!0,restoreResolutions:r=!0,restoreBuildState:o=!0}={}){let a=this.configuration.get("installStatePath"),n;try{let u=await IAt(await ae.readFilePromise(a));n=p8.default.deserialize(u),this.installStateChecksum=zi(u)}catch{r&&await this.applyLightResolution();return}e&&typeof n.linkersCustomData<"u"&&(this.linkersCustomData=n.linkersCustomData),o&&Object.assign(this,(0,Fk.default)(n,f8.restoreBuildState)),r&&(n.lockFileChecksum===this.lockFileChecksum?Object.assign(this,(0,Fk.default)(n,f8.restoreResolutions)):await this.applyLightResolution())}async applyLightResolution(){await this.resolveEverything({lockfileOnly:!0,report:new Ri}),await this.persistInstallStateFile()}async persist(){let e=(0,Rk.default)(4);await Promise.all([this.persistLockfile(),...this.workspaces.map(r=>e(()=>r.persistManifest()))])}async cacheCleanup({cache:e,report:r}){if(this.configuration.get("enableGlobalCache"))return null;let o=new Set([".gitignore"]);if(!n4(e.cwd,this.cwd)||!await ae.existsPromise(e.cwd))return null;let a=[];for(let u of await ae.readdirPromise(e.cwd)){if(o.has(u))continue;let A=K.resolve(e.cwd,u);e.markedFiles.has(A)||(e.immutable?r.reportError(56,`${Ut(this.configuration,K.basename(A),"magenta")} appears to be unused and would be marked for deletion, but the cache is immutable`):a.push(ae.lstatPromise(A).then(async p=>(await ae.removePromise(A),p.size))))}if(a.length===0)return null;let n=await Promise.all(a);return{count:a.length,size:n.reduce((u,A)=>u+A,0)}}}});function PAt(t){let o=Math.floor(t.timeNow/864e5),a=t.updateInterval*864e5,n=t.state.lastUpdate??t.timeNow+a+Math.floor(a*t.randomInitialInterval),u=n+a,A=t.state.lastTips??o*864e5,p=A+864e5+8*36e5-t.timeZone,h=u<=t.timeNow,E=p<=t.timeNow,I=null;return(h||E||!t.state.lastUpdate||!t.state.lastTips)&&(I={},I.lastUpdate=h?t.timeNow:n,I.lastTips=A,I.blocks=h?{}:t.state.blocks,I.displayedTips=t.state.displayedTips),{nextState:I,triggerUpdate:h,triggerTips:E,nextTips:E?o*864e5:A}}var sE,_he=wt(()=>{Pt();r2();ah();tx();Gl();xf();sE=class{constructor(e,r){this.values=new Map;this.hits=new Map;this.enumerators=new Map;this.nextTips=0;this.displayedTips=[];this.shouldCommitTips=!1;this.configuration=e;let o=this.getRegistryPath();this.isNew=!ae.existsSync(o),this.shouldShowTips=!1,this.sendReport(r),this.startBuffer()}commitTips(){this.shouldShowTips&&(this.shouldCommitTips=!0)}selectTip(e){let r=new Set(this.displayedTips),o=A=>A&&nn?nA(nn,A):!1,a=e.map((A,p)=>p).filter(A=>e[A]&&o(e[A]?.selector));if(a.length===0)return null;let n=a.filter(A=>!r.has(A));if(n.length===0){let A=Math.floor(a.length*.2);this.displayedTips=A>0?this.displayedTips.slice(-A):[],n=a.filter(p=>!r.has(p))}let u=n[Math.floor(Math.random()*n.length)];return this.displayedTips.push(u),this.commitTips(),e[u]}reportVersion(e){this.reportValue("version",e.replace(/-git\..*/,"-git"))}reportCommandName(e){this.reportValue("commandName",e||"")}reportPluginName(e){this.reportValue("pluginName",e)}reportProject(e){this.reportEnumerator("projectCount",e)}reportInstall(e){this.reportHit("installCount",e)}reportPackageExtension(e){this.reportValue("packageExtension",e)}reportWorkspaceCount(e){this.reportValue("workspaceCount",String(e))}reportDependencyCount(e){this.reportValue("dependencyCount",String(e))}reportValue(e,r){zm(this.values,e).add(r)}reportEnumerator(e,r){zm(this.enumerators,e).add(zi(r))}reportHit(e,r="*"){let o=A1(this.hits,e),a=Al(o,r,()=>0);o.set(r,a+1)}getRegistryPath(){let e=this.configuration.get("globalFolder");return K.join(e,"telemetry.json")}sendReport(e){let r=this.getRegistryPath(),o;try{o=ae.readJsonSync(r)}catch{o={}}let{nextState:a,triggerUpdate:n,triggerTips:u,nextTips:A}=PAt({state:o,timeNow:Date.now(),timeZone:new Date().getTimezoneOffset()*60*1e3,randomInitialInterval:Math.random(),updateInterval:this.configuration.get("telemetryInterval")});if(this.nextTips=A,this.displayedTips=o.displayedTips??[],a!==null)try{ae.mkdirSync(K.dirname(r),{recursive:!0}),ae.writeJsonSync(r,a)}catch{return!1}if(u&&this.configuration.get("enableTips")&&(this.shouldShowTips=!0),n){let p=o.blocks??{};if(Object.keys(p).length===0){let h=`https://browser-http-intake.logs.datadoghq.eu/v1/input/${e}?ddsource=yarn`,E=I=>CU(h,I,{configuration:this.configuration}).catch(()=>{});for(let[I,D]of Object.entries(o.blocks??{})){if(Object.keys(D).length===0)continue;let x=D;x.userId=I,x.reportType="primary";for(let L of Object.keys(x.enumerators??{}))x.enumerators[L]=x.enumerators[L].length;E(x);let C=new Map,T=20;for(let[L,U]of Object.entries(x.values))U.length>0&&C.set(L,U.slice(0,T));for(;C.size>0;){let L={};L.userId=I,L.reportType="secondary",L.metrics={};for(let[U,z]of C)L.metrics[U]=z.shift(),z.length===0&&C.delete(U);E(L)}}}}return!0}applyChanges(){let e=this.getRegistryPath(),r;try{r=ae.readJsonSync(e)}catch{r={}}let o=this.configuration.get("telemetryUserId")??"*",a=r.blocks=r.blocks??{},n=a[o]=a[o]??{};for(let u of this.hits.keys()){let A=n.hits=n.hits??{},p=A[u]=A[u]??{};for(let[h,E]of this.hits.get(u))p[h]=(p[h]??0)+E}for(let u of["values","enumerators"])for(let A of this[u].keys()){let p=n[u]=n[u]??{};p[A]=[...new Set([...p[A]??[],...this[u].get(A)??[]])]}this.shouldCommitTips&&(r.lastTips=this.nextTips,r.displayedTips=this.displayedTips),ae.mkdirSync(K.dirname(e),{recursive:!0}),ae.writeJsonSync(e,r)}startBuffer(){process.on("exit",()=>{try{this.applyChanges()}catch{}})}}});var P2={};Kt(P2,{BuildDirectiveType:()=>Sk,CACHE_CHECKPOINT:()=>K_,CACHE_VERSION:()=>Pk,Cache:()=>Yr,Configuration:()=>Je,DEFAULT_RC_FILENAME:()=>SU,FormatType:()=>yce,InstallMode:()=>yl,LEGACY_PLUGINS:()=>j1,LOCKFILE_VERSION:()=>Tk,LegacyMigrationResolver:()=>tE,LightReport:()=>pA,LinkType:()=>$m,LockfileResolver:()=>rE,Manifest:()=>_t,MessageName:()=>vr,MultiFetcher:()=>py,PackageExtensionStatus:()=>sM,PackageExtensionType:()=>iM,PeerWarningType:()=>Nk,Project:()=>Qt,Report:()=>Ys,ReportError:()=>zt,SettingsType:()=>G1,StreamReport:()=>Nt,TAG_REGEXP:()=>xy,TelemetryManager:()=>sE,ThrowReport:()=>Ri,VirtualFetcher:()=>hy,WindowsLinkType:()=>lx,Workspace:()=>iE,WorkspaceFetcher:()=>gy,WorkspaceResolver:()=>ci,YarnVersion:()=>nn,execUtils:()=>Hr,folderUtils:()=>vb,formatUtils:()=>pe,hashUtils:()=>xn,httpUtils:()=>on,miscUtils:()=>qe,nodeUtils:()=>Xi,parseMessageName:()=>qP,reportOptionDeprecations:()=>Qy,scriptUtils:()=>hn,semverUtils:()=>Ur,stringifyMessageName:()=>zu,structUtils:()=>G,tgzUtils:()=>$i,treeUtils:()=>As});var Ke=wt(()=>{ix();Db();Yl();ah();tx();Gl();nx();a3();xf();wo();_pe();Kpe();V_();Y1();Y1();zpe();z_();Jpe();J_();Ay();jP();WO();Uhe();Vl();n2();_he();u8();VO();zO();Dg();A8();r2();iie()});var Whe=_((x_t,b2)=>{"use strict";var bAt=process.env.TERM_PROGRAM==="Hyper",xAt=process.platform==="win32",jhe=process.platform==="linux",d8={ballotDisabled:"\u2612",ballotOff:"\u2610",ballotOn:"\u2611",bullet:"\u2022",bulletWhite:"\u25E6",fullBlock:"\u2588",heart:"\u2764",identicalTo:"\u2261",line:"\u2500",mark:"\u203B",middot:"\xB7",minus:"\uFF0D",multiplication:"\xD7",obelus:"\xF7",pencilDownRight:"\u270E",pencilRight:"\u270F",pencilUpRight:"\u2710",percent:"%",pilcrow2:"\u2761",pilcrow:"\xB6",plusMinus:"\xB1",section:"\xA7",starsOff:"\u2606",starsOn:"\u2605",upDownArrow:"\u2195"},Ghe=Object.assign({},d8,{check:"\u221A",cross:"\xD7",ellipsisLarge:"...",ellipsis:"...",info:"i",question:"?",questionSmall:"?",pointer:">",pointerSmall:"\xBB",radioOff:"( )",radioOn:"(*)",warning:"\u203C"}),Yhe=Object.assign({},d8,{ballotCross:"\u2718",check:"\u2714",cross:"\u2716",ellipsisLarge:"\u22EF",ellipsis:"\u2026",info:"\u2139",question:"?",questionFull:"\uFF1F",questionSmall:"\uFE56",pointer:jhe?"\u25B8":"\u276F",pointerSmall:jhe?"\u2023":"\u203A",radioOff:"\u25EF",radioOn:"\u25C9",warning:"\u26A0"});b2.exports=xAt&&!bAt?Ghe:Yhe;Reflect.defineProperty(b2.exports,"common",{enumerable:!1,value:d8});Reflect.defineProperty(b2.exports,"windows",{enumerable:!1,value:Ghe});Reflect.defineProperty(b2.exports,"other",{enumerable:!1,value:Yhe})});var eu=_((k_t,m8)=>{"use strict";var kAt=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),QAt=/[\u001b\u009b][[\]#;?()]*(?:(?:(?:[^\W_]*;?[^\W_]*)\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g,Khe=()=>{let t={enabled:!0,visible:!0,styles:{},keys:{}};"FORCE_COLOR"in process.env&&(t.enabled=process.env.FORCE_COLOR!=="0");let e=n=>{let u=n.open=`\x1B[${n.codes[0]}m`,A=n.close=`\x1B[${n.codes[1]}m`,p=n.regex=new RegExp(`\\u001b\\[${n.codes[1]}m`,"g");return n.wrap=(h,E)=>{h.includes(A)&&(h=h.replace(p,A+u));let I=u+h+A;return E?I.replace(/\r*\n/g,`${A}$&${u}`):I},n},r=(n,u,A)=>typeof n=="function"?n(u):n.wrap(u,A),o=(n,u)=>{if(n===""||n==null)return"";if(t.enabled===!1)return n;if(t.visible===!1)return"";let A=""+n,p=A.includes(` +`),h=u.length;for(h>0&&u.includes("unstyle")&&(u=[...new Set(["unstyle",...u])].reverse());h-- >0;)A=r(t.styles[u[h]],A,p);return A},a=(n,u,A)=>{t.styles[n]=e({name:n,codes:u}),(t.keys[A]||(t.keys[A]=[])).push(n),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(h){t.alias(n,h)},get(){let h=E=>o(E,h.stack);return Reflect.setPrototypeOf(h,t),h.stack=this.stack?this.stack.concat(n):[n],h}})};return a("reset",[0,0],"modifier"),a("bold",[1,22],"modifier"),a("dim",[2,22],"modifier"),a("italic",[3,23],"modifier"),a("underline",[4,24],"modifier"),a("inverse",[7,27],"modifier"),a("hidden",[8,28],"modifier"),a("strikethrough",[9,29],"modifier"),a("black",[30,39],"color"),a("red",[31,39],"color"),a("green",[32,39],"color"),a("yellow",[33,39],"color"),a("blue",[34,39],"color"),a("magenta",[35,39],"color"),a("cyan",[36,39],"color"),a("white",[37,39],"color"),a("gray",[90,39],"color"),a("grey",[90,39],"color"),a("bgBlack",[40,49],"bg"),a("bgRed",[41,49],"bg"),a("bgGreen",[42,49],"bg"),a("bgYellow",[43,49],"bg"),a("bgBlue",[44,49],"bg"),a("bgMagenta",[45,49],"bg"),a("bgCyan",[46,49],"bg"),a("bgWhite",[47,49],"bg"),a("blackBright",[90,39],"bright"),a("redBright",[91,39],"bright"),a("greenBright",[92,39],"bright"),a("yellowBright",[93,39],"bright"),a("blueBright",[94,39],"bright"),a("magentaBright",[95,39],"bright"),a("cyanBright",[96,39],"bright"),a("whiteBright",[97,39],"bright"),a("bgBlackBright",[100,49],"bgBright"),a("bgRedBright",[101,49],"bgBright"),a("bgGreenBright",[102,49],"bgBright"),a("bgYellowBright",[103,49],"bgBright"),a("bgBlueBright",[104,49],"bgBright"),a("bgMagentaBright",[105,49],"bgBright"),a("bgCyanBright",[106,49],"bgBright"),a("bgWhiteBright",[107,49],"bgBright"),t.ansiRegex=QAt,t.hasColor=t.hasAnsi=n=>(t.ansiRegex.lastIndex=0,typeof n=="string"&&n!==""&&t.ansiRegex.test(n)),t.alias=(n,u)=>{let A=typeof u=="string"?t[u]:u;if(typeof A!="function")throw new TypeError("Expected alias to be the name of an existing color (string) or a function");A.stack||(Reflect.defineProperty(A,"name",{value:n}),t.styles[n]=A,A.stack=[n]),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(p){t.alias(n,p)},get(){let p=h=>o(h,p.stack);return Reflect.setPrototypeOf(p,t),p.stack=this.stack?this.stack.concat(A.stack):A.stack,p}})},t.theme=n=>{if(!kAt(n))throw new TypeError("Expected theme to be an object");for(let u of Object.keys(n))t.alias(u,n[u]);return t},t.alias("unstyle",n=>typeof n=="string"&&n!==""?(t.ansiRegex.lastIndex=0,n.replace(t.ansiRegex,"")):""),t.alias("noop",n=>n),t.none=t.clear=t.noop,t.stripColor=t.unstyle,t.symbols=Whe(),t.define=a,t};m8.exports=Khe();m8.exports.create=Khe});var bo=_(an=>{"use strict";var FAt=Object.prototype.toString,ic=eu(),Vhe=!1,y8=[],zhe={yellow:"blue",cyan:"red",green:"magenta",black:"white",blue:"yellow",red:"cyan",magenta:"green",white:"black"};an.longest=(t,e)=>t.reduce((r,o)=>Math.max(r,e?o[e].length:o.length),0);an.hasColor=t=>!!t&&ic.hasColor(t);var Mk=an.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);an.nativeType=t=>FAt.call(t).slice(8,-1).toLowerCase().replace(/\s/g,"");an.isAsyncFn=t=>an.nativeType(t)==="asyncfunction";an.isPrimitive=t=>t!=null&&typeof t!="object"&&typeof t!="function";an.resolve=(t,e,...r)=>typeof e=="function"?e.call(t,...r):e;an.scrollDown=(t=[])=>[...t.slice(1),t[0]];an.scrollUp=(t=[])=>[t.pop(),...t];an.reorder=(t=[])=>{let e=t.slice();return e.sort((r,o)=>r.index>o.index?1:r.index{let o=t.length,a=r===o?0:r<0?o-1:r,n=t[e];t[e]=t[a],t[a]=n};an.width=(t,e=80)=>{let r=t&&t.columns?t.columns:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[0]),process.platform==="win32"?r-1:r};an.height=(t,e=20)=>{let r=t&&t.rows?t.rows:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[1]),r};an.wordWrap=(t,e={})=>{if(!t)return t;typeof e=="number"&&(e={width:e});let{indent:r="",newline:o=` +`+r,width:a=80}=e,n=(o+r).match(/[^\S\n]/g)||[];a-=n.length;let u=`.{1,${a}}([\\s\\u200B]+|$)|[^\\s\\u200B]+?([\\s\\u200B]+|$)`,A=t.trim(),p=new RegExp(u,"g"),h=A.match(p)||[];return h=h.map(E=>E.replace(/\n$/,"")),e.padEnd&&(h=h.map(E=>E.padEnd(a," "))),e.padStart&&(h=h.map(E=>E.padStart(a," "))),r+h.join(o)};an.unmute=t=>{let e=t.stack.find(o=>ic.keys.color.includes(o));return e?ic[e]:t.stack.find(o=>o.slice(2)==="bg")?ic[e.slice(2)]:o=>o};an.pascal=t=>t?t[0].toUpperCase()+t.slice(1):"";an.inverse=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>ic.keys.color.includes(o));if(e){let o=ic["bg"+an.pascal(e)];return o?o.black:t}let r=t.stack.find(o=>o.slice(0,2)==="bg");return r?ic[r.slice(2).toLowerCase()]||t:ic.none};an.complement=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>ic.keys.color.includes(o)),r=t.stack.find(o=>o.slice(0,2)==="bg");if(e&&!r)return ic[zhe[e]||e];if(r){let o=r.slice(2).toLowerCase(),a=zhe[o];return a&&ic["bg"+an.pascal(a)]||t}return ic.none};an.meridiem=t=>{let e=t.getHours(),r=t.getMinutes(),o=e>=12?"pm":"am";e=e%12;let a=e===0?12:e,n=r<10?"0"+r:r;return a+":"+n+" "+o};an.set=(t={},e="",r)=>e.split(".").reduce((o,a,n,u)=>{let A=u.length-1>n?o[a]||{}:r;return!an.isObject(A)&&n{let o=t[e]==null?e.split(".").reduce((a,n)=>a&&a[n],t):t[e];return o??r};an.mixin=(t,e)=>{if(!Mk(t))return e;if(!Mk(e))return t;for(let r of Object.keys(e)){let o=Object.getOwnPropertyDescriptor(e,r);if(o.hasOwnProperty("value"))if(t.hasOwnProperty(r)&&Mk(o.value)){let a=Object.getOwnPropertyDescriptor(t,r);Mk(a.value)?t[r]=an.merge({},t[r],e[r]):Reflect.defineProperty(t,r,o)}else Reflect.defineProperty(t,r,o);else Reflect.defineProperty(t,r,o)}return t};an.merge=(...t)=>{let e={};for(let r of t)an.mixin(e,r);return e};an.mixinEmitter=(t,e)=>{let r=e.constructor.prototype;for(let o of Object.keys(r)){let a=r[o];typeof a=="function"?an.define(t,o,a.bind(e)):an.define(t,o,a)}};an.onExit=t=>{let e=(r,o)=>{Vhe||(Vhe=!0,y8.forEach(a=>a()),r===!0&&process.exit(128+o))};y8.length===0&&(process.once("SIGTERM",e.bind(null,!0,15)),process.once("SIGINT",e.bind(null,!0,2)),process.once("exit",e)),y8.push(t)};an.define=(t,e,r)=>{Reflect.defineProperty(t,e,{value:r})};an.defineExport=(t,e,r)=>{let o;Reflect.defineProperty(t,e,{enumerable:!0,configurable:!0,set(a){o=a},get(){return o?o():r()}})}});var Jhe=_(cE=>{"use strict";cE.ctrl={a:"first",b:"backward",c:"cancel",d:"deleteForward",e:"last",f:"forward",g:"reset",i:"tab",k:"cutForward",l:"reset",n:"newItem",m:"cancel",j:"submit",p:"search",r:"remove",s:"save",u:"undo",w:"cutLeft",x:"toggleCursor",v:"paste"};cE.shift={up:"shiftUp",down:"shiftDown",left:"shiftLeft",right:"shiftRight",tab:"prev"};cE.fn={up:"pageUp",down:"pageDown",left:"pageLeft",right:"pageRight",delete:"deleteForward"};cE.option={b:"backward",f:"forward",d:"cutRight",left:"cutLeft",up:"altUp",down:"altDown"};cE.keys={pageup:"pageUp",pagedown:"pageDown",home:"home",end:"end",cancel:"cancel",delete:"deleteForward",backspace:"delete",down:"down",enter:"submit",escape:"cancel",left:"left",space:"space",number:"number",return:"submit",right:"right",tab:"next",up:"up"}});var $he=_((R_t,Zhe)=>{"use strict";var Xhe=ve("readline"),RAt=Jhe(),TAt=/^(?:\x1b)([a-zA-Z0-9])$/,NAt=/^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/,LAt={OP:"f1",OQ:"f2",OR:"f3",OS:"f4","[11~":"f1","[12~":"f2","[13~":"f3","[14~":"f4","[[A":"f1","[[B":"f2","[[C":"f3","[[D":"f4","[[E":"f5","[15~":"f5","[17~":"f6","[18~":"f7","[19~":"f8","[20~":"f9","[21~":"f10","[23~":"f11","[24~":"f12","[A":"up","[B":"down","[C":"right","[D":"left","[E":"clear","[F":"end","[H":"home",OA:"up",OB:"down",OC:"right",OD:"left",OE:"clear",OF:"end",OH:"home","[1~":"home","[2~":"insert","[3~":"delete","[4~":"end","[5~":"pageup","[6~":"pagedown","[[5~":"pageup","[[6~":"pagedown","[7~":"home","[8~":"end","[a":"up","[b":"down","[c":"right","[d":"left","[e":"clear","[2$":"insert","[3$":"delete","[5$":"pageup","[6$":"pagedown","[7$":"home","[8$":"end",Oa:"up",Ob:"down",Oc:"right",Od:"left",Oe:"clear","[2^":"insert","[3^":"delete","[5^":"pageup","[6^":"pagedown","[7^":"home","[8^":"end","[Z":"tab"};function MAt(t){return["[a","[b","[c","[d","[e","[2$","[3$","[5$","[6$","[7$","[8$","[Z"].includes(t)}function OAt(t){return["Oa","Ob","Oc","Od","Oe","[2^","[3^","[5^","[6^","[7^","[8^"].includes(t)}var Ok=(t="",e={})=>{let r,o={name:e.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:t,raw:t,...e};if(Buffer.isBuffer(t)?t[0]>127&&t[1]===void 0?(t[0]-=128,t="\x1B"+String(t)):t=String(t):t!==void 0&&typeof t!="string"?t=String(t):t||(t=o.sequence||""),o.sequence=o.sequence||t||o.name,t==="\r")o.raw=void 0,o.name="return";else if(t===` +`)o.name="enter";else if(t===" ")o.name="tab";else if(t==="\b"||t==="\x7F"||t==="\x1B\x7F"||t==="\x1B\b")o.name="backspace",o.meta=t.charAt(0)==="\x1B";else if(t==="\x1B"||t==="\x1B\x1B")o.name="escape",o.meta=t.length===2;else if(t===" "||t==="\x1B ")o.name="space",o.meta=t.length===2;else if(t<="")o.name=String.fromCharCode(t.charCodeAt(0)+97-1),o.ctrl=!0;else if(t.length===1&&t>="0"&&t<="9")o.name="number";else if(t.length===1&&t>="a"&&t<="z")o.name=t;else if(t.length===1&&t>="A"&&t<="Z")o.name=t.toLowerCase(),o.shift=!0;else if(r=TAt.exec(t))o.meta=!0,o.shift=/^[A-Z]$/.test(r[1]);else if(r=NAt.exec(t)){let a=[...t];a[0]==="\x1B"&&a[1]==="\x1B"&&(o.option=!0);let n=[r[1],r[2],r[4],r[6]].filter(Boolean).join(""),u=(r[3]||r[5]||1)-1;o.ctrl=!!(u&4),o.meta=!!(u&10),o.shift=!!(u&1),o.code=n,o.name=LAt[n],o.shift=MAt(n)||o.shift,o.ctrl=OAt(n)||o.ctrl}return o};Ok.listen=(t={},e)=>{let{stdin:r}=t;if(!r||r!==process.stdin&&!r.isTTY)throw new Error("Invalid stream passed");let o=Xhe.createInterface({terminal:!0,input:r});Xhe.emitKeypressEvents(r,o);let a=(A,p)=>e(A,Ok(A,p),o),n=r.isRaw;return r.isTTY&&r.setRawMode(!0),r.on("keypress",a),o.resume(),()=>{r.isTTY&&r.setRawMode(n),r.removeListener("keypress",a),o.pause(),o.close()}};Ok.action=(t,e,r)=>{let o={...RAt,...r};return e.ctrl?(e.action=o.ctrl[e.name],e):e.option&&o.option?(e.action=o.option[e.name],e):e.shift?(e.action=o.shift[e.name],e):(e.action=o.keys[e.name],e)};Zhe.exports=Ok});var t0e=_((T_t,e0e)=>{"use strict";e0e.exports=t=>{t.timers=t.timers||{};let e=t.options.timers;if(e)for(let r of Object.keys(e)){let o=e[r];typeof o=="number"&&(o={interval:o}),UAt(t,r,o)}};function UAt(t,e,r={}){let o=t.timers[e]={name:e,start:Date.now(),ms:0,tick:0},a=r.interval||120;o.frames=r.frames||[],o.loading=!0;let n=setInterval(()=>{o.ms=Date.now()-o.start,o.tick++,t.render()},a);return o.stop=()=>{o.loading=!1,clearInterval(n)},Reflect.defineProperty(o,"interval",{value:n}),t.once("close",()=>o.stop()),o.stop}});var n0e=_((N_t,r0e)=>{"use strict";var{define:_At,width:HAt}=bo(),E8=class{constructor(e){let r=e.options;_At(this,"_prompt",e),this.type=e.type,this.name=e.name,this.message="",this.header="",this.footer="",this.error="",this.hint="",this.input="",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt="",this.buffer="",this.width=HAt(r.stdout||process.stdout),Object.assign(this,r),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let r=this._color||e[this.status];return typeof r=="function"?r:e.pending}set loading(e){this._loading=e}get loading(){return typeof this._loading=="boolean"?this._loading:this.loadingChoices?"choices":!1}get status(){return this.cancelled?"cancelled":this.submitted?"submitted":"pending"}};r0e.exports=E8});var s0e=_((L_t,i0e)=>{"use strict";var C8=bo(),Ks=eu(),w8={default:Ks.noop,noop:Ks.noop,set inverse(t){this._inverse=t},get inverse(){return this._inverse||C8.inverse(this.primary)},set complement(t){this._complement=t},get complement(){return this._complement||C8.complement(this.primary)},primary:Ks.cyan,success:Ks.green,danger:Ks.magenta,strong:Ks.bold,warning:Ks.yellow,muted:Ks.dim,disabled:Ks.gray,dark:Ks.dim.gray,underline:Ks.underline,set info(t){this._info=t},get info(){return this._info||this.primary},set em(t){this._em=t},get em(){return this._em||this.primary.underline},set heading(t){this._heading=t},get heading(){return this._heading||this.muted.underline},set pending(t){this._pending=t},get pending(){return this._pending||this.primary},set submitted(t){this._submitted=t},get submitted(){return this._submitted||this.success},set cancelled(t){this._cancelled=t},get cancelled(){return this._cancelled||this.danger},set typing(t){this._typing=t},get typing(){return this._typing||this.dim},set placeholder(t){this._placeholder=t},get placeholder(){return this._placeholder||this.primary.dim},set highlight(t){this._highlight=t},get highlight(){return this._highlight||this.inverse}};w8.merge=(t={})=>{t.styles&&typeof t.styles.enabled=="boolean"&&(Ks.enabled=t.styles.enabled),t.styles&&typeof t.styles.visible=="boolean"&&(Ks.visible=t.styles.visible);let e=C8.merge({},w8,t.styles);delete e.merge;for(let r of Object.keys(Ks))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>Ks[r]});for(let r of Object.keys(Ks.styles))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>Ks[r]});return e};i0e.exports=w8});var a0e=_((M_t,o0e)=>{"use strict";var I8=process.platform==="win32",Wf=eu(),qAt=bo(),B8={...Wf.symbols,upDownDoubleArrow:"\u21D5",upDownDoubleArrow2:"\u2B0D",upDownArrow:"\u2195",asterisk:"*",asterism:"\u2042",bulletWhite:"\u25E6",electricArrow:"\u2301",ellipsisLarge:"\u22EF",ellipsisSmall:"\u2026",fullBlock:"\u2588",identicalTo:"\u2261",indicator:Wf.symbols.check,leftAngle:"\u2039",mark:"\u203B",minus:"\u2212",multiplication:"\xD7",obelus:"\xF7",percent:"%",pilcrow:"\xB6",pilcrow2:"\u2761",pencilUpRight:"\u2710",pencilDownRight:"\u270E",pencilRight:"\u270F",plus:"+",plusMinus:"\xB1",pointRight:"\u261E",rightAngle:"\u203A",section:"\xA7",hexagon:{off:"\u2B21",on:"\u2B22",disabled:"\u2B22"},ballot:{on:"\u2611",off:"\u2610",disabled:"\u2612"},stars:{on:"\u2605",off:"\u2606",disabled:"\u2606"},folder:{on:"\u25BC",off:"\u25B6",disabled:"\u25B6"},prefix:{pending:Wf.symbols.question,submitted:Wf.symbols.check,cancelled:Wf.symbols.cross},separator:{pending:Wf.symbols.pointerSmall,submitted:Wf.symbols.middot,cancelled:Wf.symbols.middot},radio:{off:I8?"( )":"\u25EF",on:I8?"(*)":"\u25C9",disabled:I8?"(|)":"\u24BE"},numbers:["\u24EA","\u2460","\u2461","\u2462","\u2463","\u2464","\u2465","\u2466","\u2467","\u2468","\u2469","\u246A","\u246B","\u246C","\u246D","\u246E","\u246F","\u2470","\u2471","\u2472","\u2473","\u3251","\u3252","\u3253","\u3254","\u3255","\u3256","\u3257","\u3258","\u3259","\u325A","\u325B","\u325C","\u325D","\u325E","\u325F","\u32B1","\u32B2","\u32B3","\u32B4","\u32B5","\u32B6","\u32B7","\u32B8","\u32B9","\u32BA","\u32BB","\u32BC","\u32BD","\u32BE","\u32BF"]};B8.merge=t=>{let e=qAt.merge({},Wf.symbols,B8,t.symbols);return delete e.merge,e};o0e.exports=B8});var c0e=_((O_t,l0e)=>{"use strict";var jAt=s0e(),GAt=a0e(),YAt=bo();l0e.exports=t=>{t.options=YAt.merge({},t.options.theme,t.options),t.symbols=GAt.merge(t.options),t.styles=jAt.merge(t.options)}});var h0e=_((f0e,p0e)=>{"use strict";var u0e=process.env.TERM_PROGRAM==="Apple_Terminal",WAt=eu(),v8=bo(),tu=p0e.exports=f0e,Si="\x1B[",A0e="\x07",D8=!1,kh=tu.code={bell:A0e,beep:A0e,beginning:`${Si}G`,down:`${Si}J`,esc:Si,getPosition:`${Si}6n`,hide:`${Si}?25l`,line:`${Si}2K`,lineEnd:`${Si}K`,lineStart:`${Si}1K`,restorePosition:Si+(u0e?"8":"u"),savePosition:Si+(u0e?"7":"s"),screen:`${Si}2J`,show:`${Si}?25h`,up:`${Si}1J`},Wg=tu.cursor={get hidden(){return D8},hide(){return D8=!0,kh.hide},show(){return D8=!1,kh.show},forward:(t=1)=>`${Si}${t}C`,backward:(t=1)=>`${Si}${t}D`,nextLine:(t=1)=>`${Si}E`.repeat(t),prevLine:(t=1)=>`${Si}F`.repeat(t),up:(t=1)=>t?`${Si}${t}A`:"",down:(t=1)=>t?`${Si}${t}B`:"",right:(t=1)=>t?`${Si}${t}C`:"",left:(t=1)=>t?`${Si}${t}D`:"",to(t,e){return e?`${Si}${e+1};${t+1}H`:`${Si}${t+1}G`},move(t=0,e=0){let r="";return r+=t<0?Wg.left(-t):t>0?Wg.right(t):"",r+=e<0?Wg.up(-e):e>0?Wg.down(e):"",r},restore(t={}){let{after:e,cursor:r,initial:o,input:a,prompt:n,size:u,value:A}=t;if(o=v8.isPrimitive(o)?String(o):"",a=v8.isPrimitive(a)?String(a):"",A=v8.isPrimitive(A)?String(A):"",u){let p=tu.cursor.up(u)+tu.cursor.to(n.length),h=a.length-r;return h>0&&(p+=tu.cursor.left(h)),p}if(A||e){let p=!a&&o?-o.length:-a.length+r;return e&&(p-=e.length),a===""&&o&&!n.includes(o)&&(p+=o.length),tu.cursor.move(p)}}},P8=tu.erase={screen:kh.screen,up:kh.up,down:kh.down,line:kh.line,lineEnd:kh.lineEnd,lineStart:kh.lineStart,lines(t){let e="";for(let r=0;r{if(!e)return P8.line+Wg.to(0);let r=n=>[...WAt.unstyle(n)].length,o=t.split(/\r?\n/),a=0;for(let n of o)a+=1+Math.floor(Math.max(r(n)-1,0)/e);return(P8.line+Wg.prevLine()).repeat(a-1)+P8.line+Wg.to(0)}});var uE=_((U_t,d0e)=>{"use strict";var KAt=ve("events"),g0e=eu(),S8=$he(),VAt=t0e(),zAt=n0e(),JAt=c0e(),La=bo(),Kg=h0e(),b8=class t extends KAt{constructor(e={}){super(),this.name=e.name,this.type=e.type,this.options=e,JAt(this),VAt(this),this.state=new zAt(this),this.initial=[e.initial,e.default].find(r=>r!=null),this.stdout=e.stdout||process.stdout,this.stdin=e.stdin||process.stdin,this.scale=e.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=ZAt(this.options.margin),this.setMaxListeners(0),XAt(this)}async keypress(e,r={}){this.keypressed=!0;let o=S8.action(e,S8(e,r),this.options.actions);this.state.keypress=o,this.emit("keypress",e,o),this.emit("state",this.state.clone());let a=this.options[o.action]||this[o.action]||this.dispatch;if(typeof a=="function")return await a.call(this,e,o);this.alert()}alert(){delete this.state.alert,this.options.show===!1?this.emit("alert"):this.stdout.write(Kg.code.beep)}cursorHide(){this.stdout.write(Kg.cursor.hide()),La.onExit(()=>this.cursorShow())}cursorShow(){this.stdout.write(Kg.cursor.show())}write(e){e&&(this.stdout&&this.state.show!==!1&&this.stdout.write(e),this.state.buffer+=e)}clear(e=0){let r=this.state.buffer;this.state.buffer="",!(!r&&!e||this.options.show===!1)&&this.stdout.write(Kg.cursor.down(e)+Kg.clear(r,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:e,after:r,rest:o}=this.sections(),{cursor:a,initial:n="",input:u="",value:A=""}=this,p=this.state.size=o.length,h={after:r,cursor:a,initial:n,input:u,prompt:e,size:p,value:A},E=Kg.cursor.restore(h);E&&this.stdout.write(E)}sections(){let{buffer:e,input:r,prompt:o}=this.state;o=g0e.unstyle(o);let a=g0e.unstyle(e),n=a.indexOf(o),u=a.slice(0,n),p=a.slice(n).split(` +`),h=p[0],E=p[p.length-1],D=(o+(r?" "+r:"")).length,x=De.call(this,this.value),this.result=()=>o.call(this,this.value),typeof r.initial=="function"&&(this.initial=await r.initial.call(this,this)),typeof r.onRun=="function"&&await r.onRun.call(this,this),typeof r.onSubmit=="function"){let a=r.onSubmit.bind(this),n=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>(await a(this.name,this.value,this),n())}await this.start(),await this.render()}render(){throw new Error("expected prompt to have a custom render method")}run(){return new Promise(async(e,r)=>{if(this.once("submit",e),this.once("cancel",r),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit("run")})}async element(e,r,o){let{options:a,state:n,symbols:u,timers:A}=this,p=A&&A[e];n.timer=p;let h=a[e]||n[e]||u[e],E=r&&r[e]!=null?r[e]:await h;if(E==="")return E;let I=await this.resolve(E,n,r,o);return!I&&r&&r[e]?this.resolve(h,n,r,o):I}async prefix(){let e=await this.element("prefix")||this.symbols,r=this.timers&&this.timers.prefix,o=this.state;return o.timer=r,La.isObject(e)&&(e=e[o.status]||e.pending),La.hasColor(e)?e:(this.styles[o.status]||this.styles.pending)(e)}async message(){let e=await this.element("message");return La.hasColor(e)?e:this.styles.strong(e)}async separator(){let e=await this.element("separator")||this.symbols,r=this.timers&&this.timers.separator,o=this.state;o.timer=r;let a=e[o.status]||e.pending||o.separator,n=await this.resolve(a,o);return La.isObject(n)&&(n=n[o.status]||n.pending),La.hasColor(n)?n:this.styles.muted(n)}async pointer(e,r){let o=await this.element("pointer",e,r);if(typeof o=="string"&&La.hasColor(o))return o;if(o){let a=this.styles,n=this.index===r,u=n?a.primary:h=>h,A=await this.resolve(o[n?"on":"off"]||o,this.state),p=La.hasColor(A)?A:u(A);return n?p:" ".repeat(A.length)}}async indicator(e,r){let o=await this.element("indicator",e,r);if(typeof o=="string"&&La.hasColor(o))return o;if(o){let a=this.styles,n=e.enabled===!0,u=n?a.success:a.dark,A=o[n?"on":"off"]||o;return La.hasColor(A)?A:u(A)}return""}body(){return null}footer(){if(this.state.status==="pending")return this.element("footer")}header(){if(this.state.status==="pending")return this.element("header")}async hint(){if(this.state.status==="pending"&&!this.isValue(this.state.input)){let e=await this.element("hint");return La.hasColor(e)?e:this.styles.muted(e)}}error(e){return this.state.submitted?"":e||this.state.error}format(e){return e}result(e){return e}validate(e){return this.options.required===!0?this.isValue(e):!0}isValue(e){return e!=null&&e!==""}resolve(e,...r){return La.resolve(this,e,...r)}get base(){return t.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||La.height(this.stdout,25)}get width(){return this.options.columns||La.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(e){this.state.cursor=e}get cursor(){return this.state.cursor}set input(e){this.state.input=e}get input(){return this.state.input}set value(e){this.state.value=e}get value(){let{input:e,value:r}=this.state,o=[r,e].find(this.isValue.bind(this));return this.isValue(o)?o:this.initial}static get prompt(){return e=>new this(e).run()}};function XAt(t){let e=a=>t[a]===void 0||typeof t[a]=="function",r=["actions","choices","initial","margin","roles","styles","symbols","theme","timers","value"],o=["body","footer","error","header","hint","indicator","message","prefix","separator","skip"];for(let a of Object.keys(t.options)){if(r.includes(a)||/^on[A-Z]/.test(a))continue;let n=t.options[a];typeof n=="function"&&e(a)?o.includes(a)||(t[a]=n.bind(t)):typeof t[a]!="function"&&(t[a]=n)}}function ZAt(t){typeof t=="number"&&(t=[t,t,t,t]);let e=[].concat(t||[]),r=a=>a%2===0?` +`:" ",o=[];for(let a=0;a<4;a++){let n=r(a);e[a]?o.push(n.repeat(e[a])):o.push("")}return o}d0e.exports=b8});var E0e=_((__t,y0e)=>{"use strict";var $At=bo(),m0e={default(t,e){return e},checkbox(t,e){throw new Error("checkbox role is not implemented yet")},editable(t,e){throw new Error("editable role is not implemented yet")},expandable(t,e){throw new Error("expandable role is not implemented yet")},heading(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||"",e},input(t,e){throw new Error("input role is not implemented yet")},option(t,e){return m0e.default(t,e)},radio(t,e){throw new Error("radio role is not implemented yet")},separator(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||t.symbols.line.repeat(5),e},spacer(t,e){return e}};y0e.exports=(t,e={})=>{let r=$At.merge({},m0e,e.roles);return r[t]||r.default}});var x2=_((H_t,I0e)=>{"use strict";var eft=eu(),tft=uE(),rft=E0e(),Uk=bo(),{reorder:x8,scrollUp:nft,scrollDown:ift,isObject:C0e,swap:sft}=Uk,k8=class extends tft{constructor(e){super(e),this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=""}async initialize(){typeof this.options.initial=="function"&&(this.initial=await this.options.initial.call(this)),await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:r,autofocus:o,suggest:a}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach(n=>n.enabled=!1),typeof a!="function"&&this.selectable.length===0)throw new Error("At least one choice must be selectable");C0e(r)&&(r=Object.keys(r)),Array.isArray(r)?(o!=null&&(this.index=this.findIndex(o)),r.forEach(n=>this.enable(this.find(n))),await this.render()):(o!=null&&(r=o),typeof r=="string"&&(r=this.findIndex(r)),typeof r=="number"&&r>-1&&(this.index=Math.max(0,Math.min(r,this.choices.length)),this.enable(this.find(this.index)))),this.isDisabled(this.focused)&&await this.down()}async toChoices(e,r){this.state.loadingChoices=!0;let o=[],a=0,n=async(u,A)=>{typeof u=="function"&&(u=await u.call(this)),u instanceof Promise&&(u=await u);for(let p=0;p(this.state.loadingChoices=!1,u))}async toChoice(e,r,o){if(typeof e=="function"&&(e=await e.call(this,this)),e instanceof Promise&&(e=await e),typeof e=="string"&&(e={name:e}),e.normalized)return e;e.normalized=!0;let a=e.value;if(e=rft(e.role,this.options)(this,e),typeof e.disabled=="string"&&!e.hint&&(e.hint=e.disabled,e.disabled=!0),e.disabled===!0&&e.hint==null&&(e.hint="(disabled)"),e.index!=null)return e;e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||"",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input="",e.index=r,e.cursor=0,Uk.define(e,"parent",o),e.level=o?o.level+1:1,e.indent==null&&(e.indent=o?o.indent+" ":e.indent||""),e.path=o?o.path+"."+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),this.isDisabled(e)||(this.longest=Math.max(this.longest,eft.unstyle(e.message).length));let u={...e};return e.reset=(A=u.input,p=u.value)=>{for(let h of Object.keys(u))e[h]=u[h];e.input=A,e.value=p},a==null&&typeof e.initial=="function"&&(e.input=await e.initial.call(this,this.state,e,r)),e}async onChoice(e,r){this.emit("choice",e,r,this),typeof e.onChoice=="function"&&await e.onChoice.call(this,this.state,e,r)}async addChoice(e,r,o){let a=await this.toChoice(e,r,o);return this.choices.push(a),this.index=this.choices.length-1,this.limit=this.choices.length,a}async newItem(e,r,o){let a={name:"New choice name?",editable:!0,newChoice:!0,...e},n=await this.addChoice(a,r,o);return n.updateChoice=()=>{delete n.newChoice,n.name=n.message=n.input,n.input="",n.cursor=0},this.render()}indent(e){return e.indent==null?e.level>1?" ".repeat(e.level-1):"":e.indent}dispatch(e,r){if(this.multiple&&this[r.name])return this[r.name]();this.alert()}focus(e,r){return typeof r!="boolean"&&(r=e.enabled),r&&!e.enabled&&this.selected.length>=this.maxSelected?this.alert():(this.index=e.index,e.enabled=r&&!this.isDisabled(e),e)}space(){return this.multiple?(this.toggle(this.focused),this.render()):this.alert()}a(){if(this.maxSelectedr.enabled);return this.choices.forEach(r=>r.enabled=!e),this.render()}i(){return this.choices.length-this.selected.length>this.maxSelected?this.alert():(this.choices.forEach(e=>e.enabled=!e.enabled),this.render())}g(e=this.focused){return this.choices.some(r=>!!r.parent)?(this.toggle(e.parent&&!e.choices?e.parent:e),this.render()):this.a()}toggle(e,r){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();typeof r!="boolean"&&(r=!e.enabled),e.enabled=r,e.choices&&e.choices.forEach(a=>this.toggle(a,r));let o=e.parent;for(;o;){let a=o.choices.filter(n=>this.isDisabled(n));o.enabled=a.every(n=>n.enabled===!0),o=o.parent}return w0e(this,this.choices),this.emit("toggle",e,this),e}enable(e){return this.selected.length>=this.maxSelected?this.alert():(e.enabled=!this.isDisabled(e),e.choices&&e.choices.forEach(this.enable.bind(this)),e)}disable(e){return e.enabled=!1,e.choices&&e.choices.forEach(this.disable.bind(this)),e}number(e){this.num+=e;let r=o=>{let a=Number(o);if(a>this.choices.length-1)return this.alert();let n=this.focused,u=this.choices.find(A=>a===A.index);if(!u.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(u)===-1){let A=x8(this.choices),p=A.indexOf(u);if(n.index>p){let h=A.slice(p,p+this.limit),E=A.filter(I=>!h.includes(I));this.choices=h.concat(E)}else{let h=p-this.limit+1;this.choices=A.slice(h).concat(A.slice(0,h))}}return this.index=this.choices.indexOf(u),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise(o=>{let a=this.choices.length,n=this.num,u=(A=!1,p)=>{clearTimeout(this.numberTimeout),A&&(p=r(n)),this.num="",o(p)};if(n==="0"||n.length===1&&+(n+"0")>a)return u(!0);if(Number(n)>a)return u(!1,this.alert());this.numberTimeout=setTimeout(()=>u(!0),this.delay)})}home(){return this.choices=x8(this.choices),this.index=0,this.render()}end(){let e=this.choices.length-this.limit,r=x8(this.choices);return this.choices=r.slice(e).concat(r.slice(0,e)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){return this.visible.length<=1?this.alert():this.up()}next(){return this.visible.length<=1?this.alert():this.down()}right(){return this.cursor>=this.input.length?this.alert():(this.cursor++,this.render())}left(){return this.cursor<=0?this.alert():(this.cursor--,this.render())}up(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===0?this.alert():e>r&&o===0?this.scrollUp():(this.index=(o-1%e+e)%e,this.isDisabled()?this.up():this.render())}down(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===r-1?this.alert():e>r&&o===r-1?this.scrollDown():(this.index=(o+1)%e,this.isDisabled()?this.down():this.render())}scrollUp(e=0){return this.choices=nft(this.choices),this.index=e,this.isDisabled()?this.up():this.render()}scrollDown(e=this.visible.length-1){return this.choices=ift(this.choices),this.index=e,this.isDisabled()?this.down():this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){return this.visible.length<=1?this.alert():(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled()?this.up():this.render())}pageDown(){return this.visible.length>=this.choices.length?this.alert():(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled()?this.down():this.render())}swap(e){sft(this.choices,this.index,e)}isDisabled(e=this.focused){return e&&["disabled","collapsed","hidden","completing","readonly"].some(o=>e[o]===!0)?!0:e&&e.role==="heading"}isEnabled(e=this.focused){if(Array.isArray(e))return e.every(r=>this.isEnabled(r));if(e.choices){let r=e.choices.filter(o=>!this.isDisabled(o));return e.enabled&&r.every(o=>this.isEnabled(o))}return e.enabled&&!this.isDisabled(e)}isChoice(e,r){return e.name===r||e.index===Number(r)}isSelected(e){return Array.isArray(this.initial)?this.initial.some(r=>this.isChoice(e,r)):this.isChoice(e,this.initial)}map(e=[],r="value"){return[].concat(e||[]).reduce((o,a)=>(o[a]=this.find(a,r),o),{})}filter(e,r){let a=typeof e=="function"?e:(A,p)=>[A.name,p].includes(e),u=(this.options.multiple?this.state._choices:this.choices).filter(a);return r?u.map(A=>A[r]):u}find(e,r){if(C0e(e))return r?e[r]:e;let a=typeof e=="function"?e:(u,A)=>[u.name,A].includes(e),n=this.choices.find(a);if(n)return r?n[r]:n}findIndex(e){return this.choices.indexOf(this.find(e))}async submit(){let e=this.focused;if(!e)return this.alert();if(e.newChoice)return e.input?(e.updateChoice(),this.render()):this.alert();if(this.choices.some(u=>u.newChoice))return this.alert();let{reorder:r,sort:o}=this.options,a=this.multiple===!0,n=this.selected;return n===void 0?this.alert():(Array.isArray(n)&&r!==!1&&o!==!0&&(n=Uk.reorder(n)),this.value=a?n.map(u=>u.name):n.name,super.submit())}set choices(e=[]){this.state._choices=this.state._choices||[],this.state.choices=e;for(let r of e)this.state._choices.some(o=>o.name===r.name)||this.state._choices.push(r);if(!this._initial&&this.options.initial){this._initial=!0;let r=this.initial;if(typeof r=="string"||typeof r=="number"){let o=this.find(r);o&&(this.initial=o.index,this.focus(o,!0))}}}get choices(){return w0e(this,this.state.choices||[])}set visible(e){this.state.visible=e}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(e){this.state.limit=e}get limit(){let{state:e,options:r,choices:o}=this,a=e.limit||this._limit||r.limit||o.length;return Math.min(a,this.height)}set value(e){super.value=e}get value(){return typeof super.value!="string"&&super.value===this.initial?this.input:super.value}set index(e){this.state.index=e}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let e=this.choices[this.index];return e&&this.state.submitted&&this.multiple!==!0&&(e.enabled=!0),e}get selectable(){return this.choices.filter(e=>!this.isDisabled(e))}get selected(){return this.multiple?this.enabled:this.focused}};function w0e(t,e){if(e instanceof Promise)return e;if(typeof e=="function"){if(Uk.isAsyncFn(e))return e;e=e.call(t,t)}for(let r of e){if(Array.isArray(r.choices)){let o=r.choices.filter(a=>!t.isDisabled(a));r.enabled=o.every(a=>a.enabled===!0)}t.isDisabled(r)===!0&&delete r.enabled}return e}I0e.exports=k8});var Qh=_((q_t,B0e)=>{"use strict";var oft=x2(),Q8=bo(),F8=class extends oft{constructor(e){super(e),this.emptyError=this.options.emptyError||"No items were selected"}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}separator(){if(this.options.separator)return super.separator();let e=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():e}pointer(e,r){return!this.multiple||this.options.pointer?super.pointer(e,r):""}indicator(e,r){return this.multiple?super.indicator(e,r):""}choiceMessage(e,r){let o=this.resolve(e.message,this.state,e,r);return e.role==="heading"&&!Q8.hasColor(o)&&(o=this.styles.strong(o)),this.resolve(o,this.state,e,r)}choiceSeparator(){return":"}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await this.indicator(e,r)+(e.pad||""),u=await this.resolve(e.hint,this.state,e,r);u&&!Q8.hasColor(u)&&(u=this.styles.muted(u));let A=this.indent(e),p=await this.choiceMessage(e,r),h=()=>[this.margin[3],A+a+n,p,this.margin[1],u].filter(Boolean).join(" ");return e.role==="heading"?h():e.disabled?(Q8.hasColor(p)||(p=this.styles.disabled(p)),h()):(o&&(p=this.styles.em(p)),h())}async renderChoices(){if(this.state.loading==="choices")return this.styles.warning("Loading choices");if(this.state.submitted)return"";let e=this.visible.map(async(n,u)=>await this.renderChoice(n,u)),r=await Promise.all(e);r.length||r.push(this.styles.danger("No matching choices"));let o=this.margin[0]+r.join(` +`),a;return this.options.choicesHeader&&(a=await this.resolve(this.options.choicesHeader,this.state)),[a,o].filter(Boolean).join(` +`)}format(){return!this.state.submitted||this.state.cancelled?"":Array.isArray(this.selected)?this.selected.map(e=>this.styles.primary(e.name)).join(", "):this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:r}=this.state,o="",a=await this.header(),n=await this.prefix(),u=await this.separator(),A=await this.message();this.options.promptLine!==!1&&(o=[n,A,u,""].join(" "),this.state.prompt=o);let p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),I=await this.footer();p&&(o+=p),h&&!o.includes(h)&&(o+=" "+h),e&&!p&&!E.trim()&&this.multiple&&this.emptyError!=null&&(o+=this.styles.danger(this.emptyError)),this.clear(r),this.write([a,o,E,I].filter(Boolean).join(` +`)),this.write(this.margin[2]),this.restore()}};B0e.exports=F8});var D0e=_((j_t,v0e)=>{"use strict";var aft=Qh(),lft=(t,e)=>{let r=t.toLowerCase();return o=>{let n=o.toLowerCase().indexOf(r),u=e(o.slice(n,n+r.length));return n>=0?o.slice(0,n)+u+o.slice(n+r.length):o}},R8=class extends aft{constructor(e){super(e),this.cursorShow()}moveCursor(e){this.state.cursor+=e}dispatch(e){return this.append(e)}space(e){return this.options.multiple?super.space(e):this.append(e)}append(e){let{cursor:r,input:o}=this.state;return this.input=o.slice(0,r)+e+o.slice(r),this.moveCursor(1),this.complete()}delete(){let{cursor:e,input:r}=this.state;return r?(this.input=r.slice(0,e-1)+r.slice(e),this.moveCursor(-1),this.complete()):this.alert()}deleteForward(){let{cursor:e,input:r}=this.state;return r[e]===void 0?this.alert():(this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.complete())}number(e){return this.append(e)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(e=this.input,r=this.state._choices){if(typeof this.options.suggest=="function")return this.options.suggest.call(this,e,r);let o=e.toLowerCase();return r.filter(a=>a.message.toLowerCase().includes(o))}pointer(){return""}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map(e=>this.styles.primary(e.message)).join(", ");if(this.state.submitted){let e=this.value=this.input=this.focused.value;return this.styles.primary(e)}return this.input}async render(){if(this.state.status!=="pending")return super.render();let e=this.options.highlight?this.options.highlight.bind(this):this.styles.placeholder,r=lft(this.input,e),o=this.choices;this.choices=o.map(a=>({...a,message:r(a.message)})),await super.render(),this.choices=o}submit(){return this.options.multiple&&(this.value=this.selected.map(e=>e.name)),super.submit()}};v0e.exports=R8});var N8=_((G_t,P0e)=>{"use strict";var T8=bo();P0e.exports=(t,e={})=>{t.cursorHide();let{input:r="",initial:o="",pos:a,showCursor:n=!0,color:u}=e,A=u||t.styles.placeholder,p=T8.inverse(t.styles.primary),h=T=>p(t.styles.black(T)),E=r,I=" ",D=h(I);if(t.blink&&t.blink.off===!0&&(h=T=>T,D=""),n&&a===0&&o===""&&r==="")return h(I);if(n&&a===0&&(r===o||r===""))return h(o[0])+A(o.slice(1));o=T8.isPrimitive(o)?`${o}`:"",r=T8.isPrimitive(r)?`${r}`:"";let x=o&&o.startsWith(r)&&o!==r,C=x?h(o[r.length]):D;if(a!==r.length&&n===!0&&(E=r.slice(0,a)+h(r[a])+r.slice(a+1),C=""),n===!1&&(C=""),x){let T=t.styles.unstyle(E+C);return E+C+A(o.slice(T.length))}return E+C}});var _k=_((Y_t,S0e)=>{"use strict";var cft=eu(),uft=Qh(),Aft=N8(),L8=class extends uft{constructor(e){super({...e,multiple:!0}),this.type="form",this.initial=this.options.initial,this.align=[this.options.align,"right"].find(r=>r!=null),this.emptyError="",this.values={}}async reset(e){return await super.reset(),e===!0&&(this._index=this.index),this.index=this._index,this.values={},this.choices.forEach(r=>r.reset&&r.reset()),this.render()}dispatch(e){return!!e&&this.append(e)}append(e){let r=this.focused;if(!r)return this.alert();let{cursor:o,input:a}=r;return r.value=r.input=a.slice(0,o)+e+a.slice(o),r.cursor++,this.render()}delete(){let e=this.focused;if(!e||e.cursor<=0)return this.alert();let{cursor:r,input:o}=e;return e.value=e.input=o.slice(0,r-1)+o.slice(r),e.cursor--,this.render()}deleteForward(){let e=this.focused;if(!e)return this.alert();let{cursor:r,input:o}=e;if(o[r]===void 0)return this.alert();let a=`${o}`.slice(0,r)+`${o}`.slice(r+1);return e.value=e.input=a,this.render()}right(){let e=this.focused;return e?e.cursor>=e.input.length?this.alert():(e.cursor++,this.render()):this.alert()}left(){let e=this.focused;return e?e.cursor<=0?this.alert():(e.cursor--,this.render()):this.alert()}space(e,r){return this.dispatch(e,r)}number(e,r){return this.dispatch(e,r)}next(){let e=this.focused;if(!e)return this.alert();let{initial:r,input:o}=e;return r&&r.startsWith(o)&&o!==r?(e.value=e.input=r,e.cursor=e.value.length,this.render()):super.next()}prev(){let e=this.focused;return e?e.cursor===0?super.prev():(e.value=e.input="",e.cursor=0,this.render()):this.alert()}separator(){return""}format(e){return this.state.submitted?"":super.format(e)}pointer(){return""}indicator(e){return e.input?"\u29BF":"\u2299"}async choiceSeparator(e,r){let o=await this.resolve(e.separator,this.state,e,r)||":";return o?" "+this.styles.disabled(o):""}async renderChoice(e,r){await this.onChoice(e,r);let{state:o,styles:a}=this,{cursor:n,initial:u="",name:A,hint:p,input:h=""}=e,{muted:E,submitted:I,primary:D,danger:x}=a,C=p,T=this.index===r,L=e.validate||(()=>!0),U=await this.choiceSeparator(e,r),z=e.message;this.align==="right"&&(z=z.padStart(this.longest+1," ")),this.align==="left"&&(z=z.padEnd(this.longest+1," "));let te=this.values[A]=h||u,le=h?"success":"dark";await L.call(e,te,this.state)!==!0&&(le="danger");let ce=a[le],ue=ce(await this.indicator(e,r))+(e.pad||""),Ce=this.indent(e),he=()=>[Ce,ue,z+U,h,C].filter(Boolean).join(" ");if(o.submitted)return z=cft.unstyle(z),h=I(h),C="",he();if(e.format)h=await e.format.call(this,h,e,r);else{let De=this.styles.muted;h=Aft(this,{input:h,initial:u,pos:n,showCursor:T,color:De})}return this.isValue(h)||(h=this.styles.muted(this.symbols.ellipsis)),e.result&&(this.values[A]=await e.result.call(this,te,e,r)),T&&(z=D(z)),e.error?h+=(h?" ":"")+x(e.error.trim()):e.hint&&(h+=(h?" ":"")+E(e.hint.trim())),he()}async submit(){return this.value=this.values,super.base.submit.call(this)}};S0e.exports=L8});var M8=_((W_t,x0e)=>{"use strict";var fft=_k(),pft=()=>{throw new Error("expected prompt to have a custom authenticate method")},b0e=(t=pft)=>{class e extends fft{constructor(o){super(o)}async submit(){this.value=await t.call(this,this.values,this.state),super.base.submit.call(this)}static create(o){return b0e(o)}}return e};x0e.exports=b0e()});var F0e=_((K_t,Q0e)=>{"use strict";var hft=M8();function gft(t,e){return t.username===this.options.username&&t.password===this.options.password}var k0e=(t=gft)=>{let e=[{name:"username",message:"username"},{name:"password",message:"password",format(o){return this.options.showPassword?o:(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(o.length))}}];class r extends hft.create(t){constructor(a){super({...a,choices:e})}static create(a){return k0e(a)}}return r};Q0e.exports=k0e()});var Hk=_((V_t,R0e)=>{"use strict";var dft=uE(),{isPrimitive:mft,hasColor:yft}=bo(),O8=class extends dft{constructor(e){super(e),this.cursorHide()}async initialize(){let e=await this.resolve(this.initial,this.state);this.input=await this.cast(e),await super.initialize()}dispatch(e){return this.isValue(e)?(this.input=e,this.submit()):this.alert()}format(e){let{styles:r,state:o}=this;return o.submitted?r.success(e):r.primary(e)}cast(e){return this.isTrue(e)}isTrue(e){return/^[ty1]/i.test(e)}isFalse(e){return/^[fn0]/i.test(e)}isValue(e){return mft(e)&&(this.isTrue(e)||this.isFalse(e))}async hint(){if(this.state.status==="pending"){let e=await this.element("hint");return yft(e)?e:this.styles.muted(e)}}async render(){let{input:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=this.styles.muted(this.default),A=[o,n,u,a].filter(Boolean).join(" ");this.state.prompt=A;let p=await this.header(),h=this.value=this.cast(e),E=await this.format(h),I=await this.error()||await this.hint(),D=await this.footer();I&&!A.includes(I)&&(E+=" "+I),A+=" "+E,this.clear(r),this.write([p,A,D].filter(Boolean).join(` +`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}};R0e.exports=O8});var N0e=_((z_t,T0e)=>{"use strict";var Eft=Hk(),U8=class extends Eft{constructor(e){super(e),this.default=this.options.default||(this.initial?"(Y/n)":"(y/N)")}};T0e.exports=U8});var M0e=_((J_t,L0e)=>{"use strict";var Cft=Qh(),wft=_k(),AE=wft.prototype,_8=class extends Cft{constructor(e){super({...e,multiple:!0}),this.align=[this.options.align,"left"].find(r=>r!=null),this.emptyError="",this.values={}}dispatch(e,r){let o=this.focused,a=o.parent||{};return!o.editable&&!a.editable&&(e==="a"||e==="i")?super[e]():AE.dispatch.call(this,e,r)}append(e,r){return AE.append.call(this,e,r)}delete(e,r){return AE.delete.call(this,e,r)}space(e){return this.focused.editable?this.append(e):super.space()}number(e){return this.focused.editable?this.append(e):super.number(e)}next(){return this.focused.editable?AE.next.call(this):super.next()}prev(){return this.focused.editable?AE.prev.call(this):super.prev()}async indicator(e,r){let o=e.indicator||"",a=e.editable?o:super.indicator(e,r);return await this.resolve(a,this.state,e,r)||""}indent(e){return e.role==="heading"?"":e.editable?" ":" "}async renderChoice(e,r){return e.indent="",e.editable?AE.renderChoice.call(this,e,r):super.renderChoice(e,r)}error(){return""}footer(){return this.state.error}async validate(){let e=!0;for(let r of this.choices){if(typeof r.validate!="function"||r.role==="heading")continue;let o=r.parent?this.value[r.parent.name]:this.value;if(r.editable?o=r.value===r.name?r.initial||"":r.value:this.isDisabled(r)||(o=r.enabled===!0),e=await r.validate(o,this.state),e!==!0)break}return e!==!0&&(this.state.error=typeof e=="string"?e:"Invalid Input"),e}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some(e=>e.newChoice))return this.alert();this.value={};for(let e of this.choices){let r=e.parent?this.value[e.parent.name]:this.value;if(e.role==="heading"){this.value[e.name]={};continue}e.editable?r[e.name]=e.value===e.name?e.initial||"":e.value:this.isDisabled(e)||(r[e.name]=e.enabled===!0)}return this.base.submit.call(this)}};L0e.exports=_8});var Vg=_((X_t,O0e)=>{"use strict";var Ift=uE(),Bft=N8(),{isPrimitive:vft}=bo(),H8=class extends Ift{constructor(e){super(e),this.initial=vft(this.initial)?String(this.initial):"",this.initial&&this.cursorHide(),this.state.prevCursor=0,this.state.clipboard=[]}async keypress(e,r={}){let o=this.state.prevKeypress;return this.state.prevKeypress=r,this.options.multiline===!0&&r.name==="return"&&(!o||o.name!=="return")?this.append(` +`,r):super.keypress(e,r)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value="",this.cursor=0,this.render()}dispatch(e,r){if(!e||r.ctrl||r.code)return this.alert();this.append(e)}append(e){let{cursor:r,input:o}=this.state;this.input=`${o}`.slice(0,r)+e+`${o}`.slice(r),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:r}=this.state;if(e<=0)return this.alert();this.input=`${r}`.slice(0,e-1)+`${r}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:r}=this.state;if(r[e]===void 0)return this.alert();this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let r=this.input.slice(0,e),o=this.input.slice(e),a=r.split(" ");this.state.clipboard.push(a.pop()),this.input=a.join(" "),this.cursor=this.input.length,this.input+=o,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){this.state.prevCursor?(this.cursor=this.state.prevCursor,this.state.prevCursor=0):(this.state.prevCursor=this.cursor,this.cursor=0),this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let e=this.initial!=null?String(this.initial):"";if(!e||!e.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){return this.cursor>=this.input.length?this.alert():(this.moveCursor(1),this.render())}left(){return this.cursor<=0?this.alert():(this.moveCursor(-1),this.render())}isValue(e){return!!e}async format(e=this.value){let r=await this.resolve(this.initial,this.state);return this.state.submitted?this.styles.submitted(e||r):Bft(this,{input:e,initial:r,pos:this.cursor})}async render(){let e=this.state.size,r=await this.prefix(),o=await this.separator(),a=await this.message(),n=[r,a,o].filter(Boolean).join(" ");this.state.prompt=n;let u=await this.header(),A=await this.format(),p=await this.error()||await this.hint(),h=await this.footer();p&&!A.includes(p)&&(A+=" "+p),n+=" "+A,this.clear(e),this.write([u,n,h].filter(Boolean).join(` +`)),this.restore()}};O0e.exports=H8});var _0e=_((Z_t,U0e)=>{"use strict";var Dft=t=>t.filter((e,r)=>t.lastIndexOf(e)===r),qk=t=>Dft(t).filter(Boolean);U0e.exports=(t,e={},r="")=>{let{past:o=[],present:a=""}=e,n,u;switch(t){case"prev":case"undo":return n=o.slice(0,o.length-1),u=o[o.length-1]||"",{past:qk([r,...n]),present:u};case"next":case"redo":return n=o.slice(1),u=o[0]||"",{past:qk([...n,r]),present:u};case"save":return{past:qk([...o,r]),present:""};case"remove":return u=qk(o.filter(A=>A!==r)),a="",u.length&&(a=u.pop()),{past:u,present:a};default:throw new Error(`Invalid action: "${t}"`)}}});var j8=_(($_t,q0e)=>{"use strict";var Pft=Vg(),H0e=_0e(),q8=class extends Pft{constructor(e){super(e);let r=this.options.history;if(r&&r.store){let o=r.values||this.initial;this.autosave=!!r.autosave,this.store=r.store,this.data=this.store.get("values")||{past:[],present:o},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(e){return this.store?(this.data=H0e(e,this.data,this.input),this.data.present?(this.input=this.data.present,this.cursor=this.input.length,this.render()):this.alert()):this.alert()}altUp(){return this.completion("prev")}altDown(){return this.completion("next")}prev(){return this.save(),super.prev()}save(){this.store&&(this.data=H0e("save",this.data,this.input),this.store.set("values",this.data))}submit(){return this.store&&this.autosave===!0&&this.save(),super.submit()}};q0e.exports=q8});var G0e=_((e8t,j0e)=>{"use strict";var Sft=Vg(),G8=class extends Sft{format(){return""}};j0e.exports=G8});var W0e=_((t8t,Y0e)=>{"use strict";var bft=Vg(),Y8=class extends bft{constructor(e={}){super(e),this.sep=this.options.separator||/, */,this.initial=e.initial||""}split(e=this.value){return e?String(e).split(this.sep):[]}format(){let e=this.state.submitted?this.styles.primary:r=>r;return this.list.map(e).join(", ")}async submit(e){let r=this.state.error||await this.validate(this.list,this.state);return r!==!0?(this.state.error=r,super.submit()):(this.value=this.list,super.submit())}get list(){return this.split()}};Y0e.exports=Y8});var V0e=_((r8t,K0e)=>{"use strict";var xft=Qh(),W8=class extends xft{constructor(e){super({...e,multiple:!0})}};K0e.exports=W8});var V8=_((n8t,z0e)=>{"use strict";var kft=Vg(),K8=class extends kft{constructor(e={}){super({style:"number",...e}),this.min=this.isValue(e.min)?this.toNumber(e.min):-1/0,this.max=this.isValue(e.max)?this.toNumber(e.max):1/0,this.delay=e.delay!=null?e.delay:1e3,this.float=e.float!==!1,this.round=e.round===!0||e.float===!1,this.major=e.major||10,this.minor=e.minor||1,this.initial=e.initial!=null?e.initial:"",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(e){return!/[-+.]/.test(e)||e==="."&&this.input.includes(".")?this.alert("invalid number"):super.append(e)}number(e){return super.append(e)}next(){return this.input&&this.input!==this.initial?this.alert():this.isValue(this.initial)?(this.input=this.initial,this.cursor=String(this.initial).length,this.render()):this.alert()}up(e){let r=e||this.minor,o=this.toNumber(this.input);return o>this.max+r?this.alert():(this.input=`${o+r}`,this.render())}down(e){let r=e||this.minor,o=this.toNumber(this.input);return othis.isValue(r));return this.value=this.toNumber(e||0),super.submit()}};z0e.exports=K8});var X0e=_((i8t,J0e)=>{J0e.exports=V8()});var $0e=_((s8t,Z0e)=>{"use strict";var Qft=Vg(),z8=class extends Qft{constructor(e){super(e),this.cursorShow()}format(e=this.input){return this.keypressed?(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(e.length)):""}};Z0e.exports=z8});var rge=_((o8t,tge)=>{"use strict";var Fft=eu(),Rft=x2(),ege=bo(),J8=class extends Rft{constructor(e={}){super(e),this.widths=[].concat(e.messageWidth||50),this.align=[].concat(e.align||"left"),this.linebreak=e.linebreak||!1,this.edgeLength=e.edgeLength||3,this.newline=e.newline||` + `;let r=e.startNumber||1;typeof this.scale=="number"&&(this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((o,a)=>({name:a+r})))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let e=0;for(let r of this.choices){e=Math.max(e,r.message.length),r.scaleIndex=r.initial||2,r.scale=[];for(let o=0;o=this.scale.length-1?this.alert():(e.scaleIndex++,this.render())}left(){let e=this.focused;return e.scaleIndex<=0?this.alert():(e.scaleIndex--,this.render())}indent(){return""}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.index)).join(", "):""}pointer(){return""}renderScaleKey(){return this.scaleKey===!1||this.state.submitted?"":["",...this.scale.map(o=>` ${o.name} - ${o.message}`)].map(o=>this.styles.muted(o)).join(` +`)}renderScaleHeading(e){let r=this.scale.map(p=>p.name);typeof this.options.renderScaleHeading=="function"&&(r=this.options.renderScaleHeading.call(this,e));let o=this.scaleLength-r.join("").length,a=Math.round(o/(r.length-1)),u=r.map(p=>this.styles.strong(p)).join(" ".repeat(a)),A=" ".repeat(this.widths[0]);return this.margin[3]+A+this.margin[1]+u}scaleIndicator(e,r,o){if(typeof this.options.scaleIndicator=="function")return this.options.scaleIndicator.call(this,e,r,o);let a=e.scaleIndex===r.index;return r.disabled?this.styles.hint(this.symbols.radio.disabled):a?this.styles.success(this.symbols.radio.on):this.symbols.radio.off}renderScale(e,r){let o=e.scale.map(n=>this.scaleIndicator(e,n,r)),a=this.term==="Hyper"?"":" ";return o.join(a+this.symbols.line.repeat(this.edgeLength))}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await e.hint;n&&!ege.hasColor(n)&&(n=this.styles.muted(n));let u=C=>this.margin[3]+C.replace(/\s+$/,"").padEnd(this.widths[0]," "),A=this.newline,p=this.indent(e),h=await this.resolve(e.message,this.state,e,r),E=await this.renderScale(e,r),I=this.margin[1]+this.margin[3];this.scaleLength=Fft.unstyle(E).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-I.length);let x=ege.wordWrap(h,{width:this.widths[0],newline:A}).split(` +`).map(C=>u(C)+this.margin[1]);return o&&(E=this.styles.info(E),x=x.map(C=>this.styles.info(C))),x[0]+=E,this.linebreak&&x.push(""),[p+a,x.join(` +`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return"";this.tableize();let e=this.visible.map(async(a,n)=>await this.renderChoice(a,n)),r=await Promise.all(e),o=await this.renderScaleHeading();return this.margin[0]+[o,...r.map(a=>a.join(" "))].join(` +`)}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u="";this.options.promptLine!==!1&&(u=[o,n,a,""].join(" "),this.state.prompt=u);let A=await this.header(),p=await this.format(),h=await this.renderScaleKey(),E=await this.error()||await this.hint(),I=await this.renderChoices(),D=await this.footer(),x=this.emptyError;p&&(u+=p),E&&!u.includes(E)&&(u+=" "+E),e&&!p&&!I.trim()&&this.multiple&&x!=null&&(u+=this.styles.danger(x)),this.clear(r),this.write([A,u,h,I,D].filter(Boolean).join(` +`)),this.state.submitted||this.write(this.margin[2]),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}};tge.exports=J8});var sge=_((a8t,ige)=>{"use strict";var nge=eu(),Tft=(t="")=>typeof t=="string"?t.replace(/^['"]|['"]$/g,""):"",Z8=class{constructor(e){this.name=e.key,this.field=e.field||{},this.value=Tft(e.initial||this.field.initial||""),this.message=e.message||this.name,this.cursor=0,this.input="",this.lines=[]}},Nft=async(t={},e={},r=o=>o)=>{let o=new Set,a=t.fields||[],n=t.template,u=[],A=[],p=[],h=1;typeof n=="function"&&(n=await n());let E=-1,I=()=>n[++E],D=()=>n[E+1],x=C=>{C.line=h,u.push(C)};for(x({type:"bos",value:""});Ele.name===U.key);U.field=a.find(le=>le.name===U.key),te||(te=new Z8(U),A.push(te)),te.lines.push(U.line-1);continue}let T=u[u.length-1];T.type==="text"&&T.line===h?T.value+=C:x({type:"text",value:C})}return x({type:"eos",value:""}),{input:n,tabstops:u,unique:o,keys:p,items:A}};ige.exports=async t=>{let e=t.options,r=new Set(e.required===!0?[]:e.required||[]),o={...e.values,...e.initial},{tabstops:a,items:n,keys:u}=await Nft(e,o),A=X8("result",t,e),p=X8("format",t,e),h=X8("validate",t,e,!0),E=t.isValue.bind(t);return async(I={},D=!1)=>{let x=0;I.required=r,I.items=n,I.keys=u,I.output="";let C=async(z,te,le,ce)=>{let ue=await h(z,te,le,ce);return ue===!1?"Invalid field "+le.name:ue};for(let z of a){let te=z.value,le=z.key;if(z.type!=="template"){te&&(I.output+=te);continue}if(z.type==="template"){let ce=n.find(Ee=>Ee.name===le);e.required===!0&&I.required.add(ce.name);let ue=[ce.input,I.values[ce.value],ce.value,te].find(E),he=(ce.field||{}).message||z.inner;if(D){let Ee=await C(I.values[le],I,ce,x);if(Ee&&typeof Ee=="string"||Ee===!1){I.invalid.set(le,Ee);continue}I.invalid.delete(le);let g=await A(I.values[le],I,ce,x);I.output+=nge.unstyle(g);continue}ce.placeholder=!1;let De=te;te=await p(te,I,ce,x),ue!==te?(I.values[le]=ue,te=t.styles.typing(ue),I.missing.delete(he)):(I.values[le]=void 0,ue=`<${he}>`,te=t.styles.primary(ue),ce.placeholder=!0,I.required.has(le)&&I.missing.add(he)),I.missing.has(he)&&I.validating&&(te=t.styles.warning(ue)),I.invalid.has(le)&&I.validating&&(te=t.styles.danger(ue)),x===I.index&&(De!==te?te=t.styles.underline(te):te=t.styles.heading(nge.unstyle(te))),x++}te&&(I.output+=te)}let T=I.output.split(` +`).map(z=>" "+z),L=n.length,U=0;for(let z of n)I.invalid.has(z.name)&&z.lines.forEach(te=>{T[te][0]===" "&&(T[te]=I.styles.danger(I.symbols.bullet)+T[te].slice(1))}),t.isValue(I.values[z.name])&&U++;return I.completed=(U/L*100).toFixed(0),I.output=T.join(` +`),I.output}};function X8(t,e,r,o){return(a,n,u,A)=>typeof u.field[t]=="function"?u.field[t].call(e,a,n,u,A):[o,a].find(p=>e.isValue(p))}});var age=_((l8t,oge)=>{"use strict";var Lft=eu(),Mft=sge(),Oft=uE(),$8=class extends Oft{constructor(e){super(e),this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await Mft(this),await super.initialize()}async reset(e){this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},e!==!0&&(await this.initialize(),await this.render())}moveCursor(e){let r=this.getItem();this.cursor+=e,r.cursor+=e}dispatch(e,r){if(!r.code&&!r.ctrl&&e!=null&&this.getItem()){this.append(e,r);return}this.alert()}append(e,r){let o=this.getItem(),a=o.input.slice(0,this.cursor),n=o.input.slice(this.cursor);this.input=o.input=`${a}${e}${n}`,this.moveCursor(1),this.render()}delete(){let e=this.getItem();if(this.cursor<=0||!e.input)return this.alert();let r=e.input.slice(this.cursor),o=e.input.slice(0,this.cursor-1);this.input=e.input=`${o}${r}`,this.moveCursor(-1),this.render()}increment(e){return e>=this.state.keys.length-1?0:e+1}decrement(e){return e<=0?this.state.keys.length-1:e-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(e){let r=this.state.completed<100?this.styles.warning:this.styles.success;return this.state.submitted===!0&&this.state.completed!==100&&(r=this.styles.danger),r(`${this.state.completed}% completed`)}async render(){let{index:e,keys:r=[],submitted:o,size:a}=this.state,n=[this.options.newline,` +`].find(z=>z!=null),u=await this.prefix(),A=await this.separator(),p=await this.message(),h=[u,p,A].filter(Boolean).join(" ");this.state.prompt=h;let E=await this.header(),I=await this.error()||"",D=await this.hint()||"",x=o?"":await this.interpolate(this.state),C=this.state.key=r[e]||"",T=await this.format(C),L=await this.footer();T&&(h+=" "+T),D&&!T&&this.state.completed===0&&(h+=" "+D),this.clear(a);let U=[E,h,x,L,I.trim()];this.write(U.filter(Boolean).join(n)),this.restore()}getItem(e){let{items:r,keys:o,index:a}=this.state,n=r.find(u=>u.name===o[a]);return n&&n.input!=null&&(this.input=n.input,this.cursor=n.cursor),n}async submit(){typeof this.interpolate!="function"&&await this.initialize(),await this.interpolate(this.state,!0);let{invalid:e,missing:r,output:o,values:a}=this.state;if(e.size){let A="";for(let[p,h]of e)A+=`Invalid ${p}: ${h} +`;return this.state.error=A,super.submit()}if(r.size)return this.state.error="Required: "+[...r.keys()].join(", "),super.submit();let u=Lft.unstyle(o).split(` +`).map(A=>A.slice(1)).join(` +`);return this.value={values:a,result:u},super.submit()}};oge.exports=$8});var cge=_((c8t,lge)=>{"use strict";var Uft="(Use + to sort)",_ft=Qh(),eH=class extends _ft{constructor(e){super({...e,reorder:!1,sort:!0,multiple:!0}),this.state.hint=[this.options.hint,Uft].find(this.isValue.bind(this))}indicator(){return""}async renderChoice(e,r){let o=await super.renderChoice(e,r),a=this.symbols.identicalTo+" ",n=this.index===r&&this.sorting?this.styles.muted(a):" ";return this.options.drag===!1&&(n=""),this.options.numbered===!0?n+`${r+1} - `+o:n+o}get selected(){return this.choices}submit(){return this.value=this.choices.map(e=>e.value),super.submit()}};lge.exports=eH});var Age=_((u8t,uge)=>{"use strict";var Hft=x2(),tH=class extends Hft{constructor(e={}){if(super(e),this.emptyError=e.emptyError||"No items were selected",this.term=process.env.TERM_PROGRAM,!this.options.header){let r=["","4 - Strongly Agree","3 - Agree","2 - Neutral","1 - Disagree","0 - Strongly Disagree",""];r=r.map(o=>this.styles.muted(o)),this.state.header=r.join(` + `)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let r=await super.toChoices(...e);for(let o of r)o.scale=qft(5,this.options),o.scaleIdx=2;return r}dispatch(){this.alert()}space(){let e=this.focused,r=e.scale[e.scaleIdx],o=r.selected;return e.scale.forEach(a=>a.selected=!1),r.selected=!o,this.render()}indicator(){return""}pointer(){return""}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIdx>=e.scale.length-1?this.alert():(e.scaleIdx++,this.render())}left(){let e=this.focused;return e.scaleIdx<=0?this.alert():(e.scaleIdx--,this.render())}indent(){return" "}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=this.term==="Hyper",n=a?9:8,u=a?"":" ",A=this.symbols.line.repeat(n),p=" ".repeat(n+(a?0:1)),h=te=>(te?this.styles.success("\u25C9"):"\u25EF")+u,E=r+1+".",I=o?this.styles.heading:this.styles.noop,D=await this.resolve(e.message,this.state,e,r),x=this.indent(e),C=x+e.scale.map((te,le)=>h(le===e.scaleIdx)).join(A),T=te=>te===e.scaleIdx?I(te):te,L=x+e.scale.map((te,le)=>T(le)).join(p),U=()=>[E,D].filter(Boolean).join(" "),z=()=>[U(),C,L," "].filter(Boolean).join(` +`);return o&&(C=this.styles.cyan(C),L=this.styles.cyan(L)),z()}async renderChoices(){if(this.state.submitted)return"";let e=this.visible.map(async(o,a)=>await this.renderChoice(o,a)),r=await Promise.all(e);return r.length||r.push(this.styles.danger("No matching choices")),r.join(` +`)}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.scaleIdx)).join(", "):""}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=[o,n,a].filter(Boolean).join(" ");this.state.prompt=u;let A=await this.header(),p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),I=await this.footer();(p||!h)&&(u+=" "+p),h&&!u.includes(h)&&(u+=" "+h),e&&!p&&!E&&this.multiple&&this.type!=="form"&&(u+=this.styles.danger(this.emptyError)),this.clear(r),this.write([u,A,E,I].filter(Boolean).join(` +`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}};function qft(t,e={}){if(Array.isArray(e.scale))return e.scale.map(o=>({...o}));let r=[];for(let o=1;o{fge.exports=j8()});var gge=_((f8t,hge)=>{"use strict";var jft=Hk(),rH=class extends jft{async initialize(){await super.initialize(),this.value=this.initial=!!this.options.initial,this.disabled=this.options.disabled||"no",this.enabled=this.options.enabled||"yes",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(e="",r){switch(e.toLowerCase()){case" ":return this.toggle();case"1":case"y":case"t":return this.enable();case"0":case"n":case"f":return this.disable();default:return this.alert()}}format(){let e=o=>this.styles.primary.underline(o);return[this.value?this.disabled:e(this.disabled),this.value?e(this.enabled):this.enabled].join(this.styles.muted(" / "))}async render(){let{size:e}=this.state,r=await this.header(),o=await this.prefix(),a=await this.separator(),n=await this.message(),u=await this.format(),A=await this.error()||await this.hint(),p=await this.footer(),h=[o,n,a,u].join(" ");this.state.prompt=h,A&&!h.includes(A)&&(h+=" "+A),this.clear(e),this.write([r,h,p].filter(Boolean).join(` +`)),this.write(this.margin[2]),this.restore()}};hge.exports=rH});var mge=_((p8t,dge)=>{"use strict";var Gft=Qh(),nH=class extends Gft{constructor(e){if(super(e),typeof this.options.correctChoice!="number"||this.options.correctChoice<0)throw new Error("Please specify the index of the correct answer from the list of choices")}async toChoices(e,r){let o=await super.toChoices(e,r);if(o.length<2)throw new Error("Please give at least two choices to the user");if(this.options.correctChoice>o.length)throw new Error("Please specify the index of the correct answer from the list of choices");return o}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}};dge.exports=nH});var Ege=_(iH=>{"use strict";var yge=bo(),fs=(t,e)=>{yge.defineExport(iH,t,e),yge.defineExport(iH,t.toLowerCase(),e)};fs("AutoComplete",()=>D0e());fs("BasicAuth",()=>F0e());fs("Confirm",()=>N0e());fs("Editable",()=>M0e());fs("Form",()=>_k());fs("Input",()=>j8());fs("Invisible",()=>G0e());fs("List",()=>W0e());fs("MultiSelect",()=>V0e());fs("Numeral",()=>X0e());fs("Password",()=>$0e());fs("Scale",()=>rge());fs("Select",()=>Qh());fs("Snippet",()=>age());fs("Sort",()=>cge());fs("Survey",()=>Age());fs("Text",()=>pge());fs("Toggle",()=>gge());fs("Quiz",()=>mge())});var wge=_((g8t,Cge)=>{Cge.exports={ArrayPrompt:x2(),AuthPrompt:M8(),BooleanPrompt:Hk(),NumberPrompt:V8(),StringPrompt:Vg()}});var Q2=_((d8t,Bge)=>{"use strict";var Ige=ve("assert"),oH=ve("events"),Fh=bo(),ru=class extends oH{constructor(e,r){super(),this.options=Fh.merge({},e),this.answers={...r}}register(e,r){if(Fh.isObject(e)){for(let a of Object.keys(e))this.register(a,e[a]);return this}Ige.equal(typeof r,"function","expected a function");let o=e.toLowerCase();return r.prototype instanceof this.Prompt?this.prompts[o]=r:this.prompts[o]=r(this.Prompt,this),this}async prompt(e=[]){for(let r of[].concat(e))try{typeof r=="function"&&(r=await r.call(this)),await this.ask(Fh.merge({},this.options,r))}catch(o){return Promise.reject(o)}return this.answers}async ask(e){typeof e=="function"&&(e=await e.call(this));let r=Fh.merge({},this.options,e),{type:o,name:a}=e,{set:n,get:u}=Fh;if(typeof o=="function"&&(o=await o.call(this,e,this.answers)),!o)return this.answers[a];Ige(this.prompts[o],`Prompt "${o}" is not registered`);let A=new this.prompts[o](r),p=u(this.answers,a);A.state.answers=this.answers,A.enquirer=this,a&&A.on("submit",E=>{this.emit("answer",a,E,A),n(this.answers,a,E)});let h=A.emit.bind(A);return A.emit=(...E)=>(this.emit.call(this,...E),h(...E)),this.emit("prompt",A,this),r.autofill&&p!=null?(A.value=A.input=p,r.autofill==="show"&&await A.submit()):p=A.value=await A.run(),p}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||uE()}static get prompts(){return Ege()}static get types(){return wge()}static get prompt(){let e=(r,...o)=>{let a=new this(...o),n=a.emit.bind(a);return a.emit=(...u)=>(e.emit(...u),n(...u)),a.prompt(r)};return Fh.mixinEmitter(e,new oH),e}};Fh.mixinEmitter(ru,new oH);var sH=ru.prompts;for(let t of Object.keys(sH)){let e=t.toLowerCase(),r=o=>new sH[t](o).run();ru.prompt[e]=r,ru[e]=r,ru[t]||Reflect.defineProperty(ru,t,{get:()=>sH[t]})}var k2=t=>{Fh.defineExport(ru,t,()=>ru.types[t])};k2("ArrayPrompt");k2("AuthPrompt");k2("BooleanPrompt");k2("NumberPrompt");k2("StringPrompt");Bge.exports=ru});var N2=_((Z8t,kge)=>{var Jft=xk();function Xft(t,e,r){var o=t==null?void 0:Jft(t,e);return o===void 0?r:o}kge.exports=Xft});var Rge=_((iHt,Fge)=>{function Zft(t,e){for(var r=-1,o=t==null?0:t.length;++r{var $ft=Eg(),ept=PS();function tpt(t,e){return t&&$ft(e,ept(e),t)}Tge.exports=tpt});var Mge=_((oHt,Lge)=>{var rpt=Eg(),npt=Vm();function ipt(t,e){return t&&rpt(e,npt(e),t)}Lge.exports=ipt});var Uge=_((aHt,Oge)=>{var spt=Eg(),opt=CS();function apt(t,e){return spt(t,opt(t),e)}Oge.exports=apt});var fH=_((lHt,_ge)=>{var lpt=ES(),cpt=QS(),upt=CS(),Apt=bL(),fpt=Object.getOwnPropertySymbols,ppt=fpt?function(t){for(var e=[];t;)lpt(e,upt(t)),t=cpt(t);return e}:Apt;_ge.exports=ppt});var qge=_((cHt,Hge)=>{var hpt=Eg(),gpt=fH();function dpt(t,e){return hpt(t,gpt(t),e)}Hge.exports=dpt});var pH=_((uHt,jge)=>{var mpt=SL(),ypt=fH(),Ept=Vm();function Cpt(t){return mpt(t,Ept,ypt)}jge.exports=Cpt});var Yge=_((AHt,Gge)=>{var wpt=Object.prototype,Ipt=wpt.hasOwnProperty;function Bpt(t){var e=t.length,r=new t.constructor(e);return e&&typeof t[0]=="string"&&Ipt.call(t,"index")&&(r.index=t.index,r.input=t.input),r}Gge.exports=Bpt});var Kge=_((fHt,Wge)=>{var vpt=xS();function Dpt(t,e){var r=e?vpt(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.byteLength)}Wge.exports=Dpt});var zge=_((pHt,Vge)=>{var Ppt=/\w*$/;function Spt(t){var e=new t.constructor(t.source,Ppt.exec(t));return e.lastIndex=t.lastIndex,e}Vge.exports=Spt});var ede=_((hHt,$ge)=>{var Jge=dg(),Xge=Jge?Jge.prototype:void 0,Zge=Xge?Xge.valueOf:void 0;function bpt(t){return Zge?Object(Zge.call(t)):{}}$ge.exports=bpt});var rde=_((gHt,tde)=>{var xpt=xS(),kpt=Kge(),Qpt=zge(),Fpt=ede(),Rpt=qL(),Tpt="[object Boolean]",Npt="[object Date]",Lpt="[object Map]",Mpt="[object Number]",Opt="[object RegExp]",Upt="[object Set]",_pt="[object String]",Hpt="[object Symbol]",qpt="[object ArrayBuffer]",jpt="[object DataView]",Gpt="[object Float32Array]",Ypt="[object Float64Array]",Wpt="[object Int8Array]",Kpt="[object Int16Array]",Vpt="[object Int32Array]",zpt="[object Uint8Array]",Jpt="[object Uint8ClampedArray]",Xpt="[object Uint16Array]",Zpt="[object Uint32Array]";function $pt(t,e,r){var o=t.constructor;switch(e){case qpt:return xpt(t);case Tpt:case Npt:return new o(+t);case jpt:return kpt(t,r);case Gpt:case Ypt:case Wpt:case Kpt:case Vpt:case zpt:case Jpt:case Xpt:case Zpt:return Rpt(t,r);case Lpt:return new o;case Mpt:case _pt:return new o(t);case Opt:return Qpt(t);case Upt:return new o;case Hpt:return Fpt(t)}}tde.exports=$pt});var ide=_((dHt,nde)=>{var eht=a1(),tht=Zu(),rht="[object Map]";function nht(t){return tht(t)&&eht(t)==rht}nde.exports=nht});var lde=_((mHt,ade)=>{var iht=ide(),sht=IS(),sde=BS(),ode=sde&&sde.isMap,oht=ode?sht(ode):iht;ade.exports=oht});var ude=_((yHt,cde)=>{var aht=a1(),lht=Zu(),cht="[object Set]";function uht(t){return lht(t)&&aht(t)==cht}cde.exports=uht});var hde=_((EHt,pde)=>{var Aht=ude(),fht=IS(),Ade=BS(),fde=Ade&&Ade.isSet,pht=fde?fht(fde):Aht;pde.exports=pht});var hH=_((CHt,yde)=>{var hht=mS(),ght=Rge(),dht=RS(),mht=Nge(),yht=Mge(),Eht=HL(),Cht=kS(),wht=Uge(),Iht=qge(),Bht=FL(),vht=pH(),Dht=a1(),Pht=Yge(),Sht=rde(),bht=jL(),xht=jl(),kht=r1(),Qht=lde(),Fht=cl(),Rht=hde(),Tht=PS(),Nht=Vm(),Lht=1,Mht=2,Oht=4,gde="[object Arguments]",Uht="[object Array]",_ht="[object Boolean]",Hht="[object Date]",qht="[object Error]",dde="[object Function]",jht="[object GeneratorFunction]",Ght="[object Map]",Yht="[object Number]",mde="[object Object]",Wht="[object RegExp]",Kht="[object Set]",Vht="[object String]",zht="[object Symbol]",Jht="[object WeakMap]",Xht="[object ArrayBuffer]",Zht="[object DataView]",$ht="[object Float32Array]",e0t="[object Float64Array]",t0t="[object Int8Array]",r0t="[object Int16Array]",n0t="[object Int32Array]",i0t="[object Uint8Array]",s0t="[object Uint8ClampedArray]",o0t="[object Uint16Array]",a0t="[object Uint32Array]",Ai={};Ai[gde]=Ai[Uht]=Ai[Xht]=Ai[Zht]=Ai[_ht]=Ai[Hht]=Ai[$ht]=Ai[e0t]=Ai[t0t]=Ai[r0t]=Ai[n0t]=Ai[Ght]=Ai[Yht]=Ai[mde]=Ai[Wht]=Ai[Kht]=Ai[Vht]=Ai[zht]=Ai[i0t]=Ai[s0t]=Ai[o0t]=Ai[a0t]=!0;Ai[qht]=Ai[dde]=Ai[Jht]=!1;function Gk(t,e,r,o,a,n){var u,A=e&Lht,p=e&Mht,h=e&Oht;if(r&&(u=a?r(t,o,a,n):r(t)),u!==void 0)return u;if(!Fht(t))return t;var E=xht(t);if(E){if(u=Pht(t),!A)return Cht(t,u)}else{var I=Dht(t),D=I==dde||I==jht;if(kht(t))return Eht(t,A);if(I==mde||I==gde||D&&!a){if(u=p||D?{}:bht(t),!A)return p?Iht(t,yht(u,t)):wht(t,mht(u,t))}else{if(!Ai[I])return a?t:{};u=Sht(t,I,A)}}n||(n=new hht);var x=n.get(t);if(x)return x;n.set(t,u),Rht(t)?t.forEach(function(L){u.add(Gk(L,e,r,L,t,n))}):Qht(t)&&t.forEach(function(L,U){u.set(U,Gk(L,e,r,U,t,n))});var C=h?p?vht:Bht:p?Nht:Tht,T=E?void 0:C(t);return ght(T||t,function(L,U){T&&(U=L,L=t[U]),dht(u,U,Gk(L,e,r,U,t,n))}),u}yde.exports=Gk});var gH=_((wHt,Ede)=>{var l0t=hH(),c0t=1,u0t=4;function A0t(t){return l0t(t,c0t|u0t)}Ede.exports=A0t});var dH=_((IHt,Cde)=>{var f0t=o8();function p0t(t,e,r){return t==null?t:f0t(t,e,r)}Cde.exports=p0t});var Dde=_((bHt,vde)=>{var h0t=Object.prototype,g0t=h0t.hasOwnProperty;function d0t(t,e){return t!=null&&g0t.call(t,e)}vde.exports=d0t});var Sde=_((xHt,Pde)=>{var m0t=Dde(),y0t=a8();function E0t(t,e){return t!=null&&y0t(t,e,m0t)}Pde.exports=E0t});var xde=_((kHt,bde)=>{function C0t(t){var e=t==null?0:t.length;return e?t[e-1]:void 0}bde.exports=C0t});var Qde=_((QHt,kde)=>{var w0t=xk(),I0t=XU();function B0t(t,e){return e.length<2?t:w0t(t,I0t(e,0,-1))}kde.exports=B0t});var yH=_((FHt,Fde)=>{var v0t=Yg(),D0t=xde(),P0t=Qde(),S0t=nE();function b0t(t,e){return e=v0t(e,t),t=P0t(t,e),t==null||delete t[S0t(D0t(e))]}Fde.exports=b0t});var EH=_((RHt,Rde)=>{var x0t=yH();function k0t(t,e){return t==null?!0:x0t(t,e)}Rde.exports=k0t});var Ode=_((l6t,R0t)=>{R0t.exports={name:"@yarnpkg/cli",version:"4.5.1",license:"BSD-2-Clause",main:"./sources/index.ts",exports:{".":"./sources/index.ts","./polyfills":"./sources/polyfills.ts","./package.json":"./package.json"},dependencies:{"@yarnpkg/core":"workspace:^","@yarnpkg/fslib":"workspace:^","@yarnpkg/libzip":"workspace:^","@yarnpkg/parsers":"workspace:^","@yarnpkg/plugin-compat":"workspace:^","@yarnpkg/plugin-constraints":"workspace:^","@yarnpkg/plugin-dlx":"workspace:^","@yarnpkg/plugin-essentials":"workspace:^","@yarnpkg/plugin-exec":"workspace:^","@yarnpkg/plugin-file":"workspace:^","@yarnpkg/plugin-git":"workspace:^","@yarnpkg/plugin-github":"workspace:^","@yarnpkg/plugin-http":"workspace:^","@yarnpkg/plugin-init":"workspace:^","@yarnpkg/plugin-interactive-tools":"workspace:^","@yarnpkg/plugin-link":"workspace:^","@yarnpkg/plugin-nm":"workspace:^","@yarnpkg/plugin-npm":"workspace:^","@yarnpkg/plugin-npm-cli":"workspace:^","@yarnpkg/plugin-pack":"workspace:^","@yarnpkg/plugin-patch":"workspace:^","@yarnpkg/plugin-pnp":"workspace:^","@yarnpkg/plugin-pnpm":"workspace:^","@yarnpkg/plugin-stage":"workspace:^","@yarnpkg/plugin-typescript":"workspace:^","@yarnpkg/plugin-version":"workspace:^","@yarnpkg/plugin-workspace-tools":"workspace:^","@yarnpkg/shell":"workspace:^","ci-info":"^4.0.0",clipanion:"^4.0.0-rc.2",semver:"^7.1.2",tslib:"^2.4.0",typanion:"^3.14.0"},devDependencies:{"@types/semver":"^7.1.0","@yarnpkg/builder":"workspace:^","@yarnpkg/monorepo":"workspace:^","@yarnpkg/pnpify":"workspace:^"},peerDependencies:{"@yarnpkg/core":"workspace:^"},scripts:{postpack:"rm -rf lib",prepack:'run build:compile "$(pwd)"',"build:cli+hook":"run build:pnp:hook && builder build bundle","build:cli":"builder build bundle","run:cli":"builder run","update-local":"run build:cli --no-git-hash && rsync -a --delete bundles/ bin/"},publishConfig:{main:"./lib/index.js",bin:null,exports:{".":"./lib/index.js","./package.json":"./package.json"}},files:["/lib/**/*","!/lib/pluginConfiguration.*","!/lib/cli.*"],"@yarnpkg/builder":{bundles:{standard:["@yarnpkg/plugin-essentials","@yarnpkg/plugin-compat","@yarnpkg/plugin-constraints","@yarnpkg/plugin-dlx","@yarnpkg/plugin-exec","@yarnpkg/plugin-file","@yarnpkg/plugin-git","@yarnpkg/plugin-github","@yarnpkg/plugin-http","@yarnpkg/plugin-init","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-link","@yarnpkg/plugin-nm","@yarnpkg/plugin-npm","@yarnpkg/plugin-npm-cli","@yarnpkg/plugin-pack","@yarnpkg/plugin-patch","@yarnpkg/plugin-pnp","@yarnpkg/plugin-pnpm","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"]}},repository:{type:"git",url:"ssh://git@github.com/yarnpkg/berry.git",directory:"packages/yarnpkg-cli"},engines:{node:">=18.12.0"}}});var bH=_((U5t,Jde)=>{"use strict";Jde.exports=function(e,r){r===!0&&(r=0);var o="";if(typeof e=="string")try{o=new URL(e).protocol}catch{}else e&&e.constructor===URL&&(o=e.protocol);var a=o.split(/\:|\+/).filter(Boolean);return typeof r=="number"?a[r]:a}});var Zde=_((_5t,Xde)=>{"use strict";var $0t=bH();function egt(t){var e={protocols:[],protocol:null,port:null,resource:"",host:"",user:"",password:"",pathname:"",hash:"",search:"",href:t,query:{},parse_failed:!1};try{var r=new URL(t);e.protocols=$0t(r),e.protocol=e.protocols[0],e.port=r.port,e.resource=r.hostname,e.host=r.host,e.user=r.username||"",e.password=r.password||"",e.pathname=r.pathname,e.hash=r.hash.slice(1),e.search=r.search.slice(1),e.href=r.href,e.query=Object.fromEntries(r.searchParams)}catch{e.protocols=["file"],e.protocol=e.protocols[0],e.port="",e.resource="",e.user="",e.pathname="",e.hash="",e.search="",e.href=t,e.query={},e.parse_failed=!0}return e}Xde.exports=egt});var tme=_((H5t,eme)=>{"use strict";var tgt=Zde();function rgt(t){return t&&typeof t=="object"&&"default"in t?t:{default:t}}var ngt=rgt(tgt),igt="text/plain",sgt="us-ascii",$de=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),ogt=(t,{stripHash:e})=>{let r=/^data:(?[^,]*?),(?[^#]*?)(?:#(?.*))?$/.exec(t);if(!r)throw new Error(`Invalid URL: ${t}`);let{type:o,data:a,hash:n}=r.groups,u=o.split(";");n=e?"":n;let A=!1;u[u.length-1]==="base64"&&(u.pop(),A=!0);let p=(u.shift()||"").toLowerCase(),E=[...u.map(I=>{let[D,x=""]=I.split("=").map(C=>C.trim());return D==="charset"&&(x=x.toLowerCase(),x===sgt)?"":`${D}${x?`=${x}`:""}`}).filter(Boolean)];return A&&E.push("base64"),(E.length>0||p&&p!==igt)&&E.unshift(p),`data:${E.join(";")},${A?a.trim():a}${n?`#${n}`:""}`};function agt(t,e){if(e={defaultProtocol:"http:",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripTextFragment:!0,stripWWW:!0,removeQueryParameters:[/^utm_\w+/i],removeTrailingSlash:!0,removeSingleSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},t=t.trim(),/^data:/i.test(t))return ogt(t,e);if(/^view-source:/i.test(t))throw new Error("`view-source:` is not supported as it is a non-standard protocol");let r=t.startsWith("//");!r&&/^\.*\//.test(t)||(t=t.replace(/^(?!(?:\w+:)?\/\/)|^\/\//,e.defaultProtocol));let a=new URL(t);if(e.forceHttp&&e.forceHttps)throw new Error("The `forceHttp` and `forceHttps` options cannot be used together");if(e.forceHttp&&a.protocol==="https:"&&(a.protocol="http:"),e.forceHttps&&a.protocol==="http:"&&(a.protocol="https:"),e.stripAuthentication&&(a.username="",a.password=""),e.stripHash?a.hash="":e.stripTextFragment&&(a.hash=a.hash.replace(/#?:~:text.*?$/i,"")),a.pathname){let u=/\b[a-z][a-z\d+\-.]{1,50}:\/\//g,A=0,p="";for(;;){let E=u.exec(a.pathname);if(!E)break;let I=E[0],D=E.index,x=a.pathname.slice(A,D);p+=x.replace(/\/{2,}/g,"/"),p+=I,A=D+I.length}let h=a.pathname.slice(A,a.pathname.length);p+=h.replace(/\/{2,}/g,"/"),a.pathname=p}if(a.pathname)try{a.pathname=decodeURI(a.pathname)}catch{}if(e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let u=a.pathname.split("/"),A=u[u.length-1];$de(A,e.removeDirectoryIndex)&&(u=u.slice(0,-1),a.pathname=u.slice(1).join("/")+"/")}if(a.hostname&&(a.hostname=a.hostname.replace(/\.$/,""),e.stripWWW&&/^www\.(?!www\.)[a-z\-\d]{1,63}\.[a-z.\-\d]{2,63}$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\./,""))),Array.isArray(e.removeQueryParameters))for(let u of[...a.searchParams.keys()])$de(u,e.removeQueryParameters)&&a.searchParams.delete(u);if(e.removeQueryParameters===!0&&(a.search=""),e.sortQueryParameters){a.searchParams.sort();try{a.search=decodeURIComponent(a.search)}catch{}}e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\/$/,""));let n=t;return t=a.toString(),!e.removeSingleSlash&&a.pathname==="/"&&!n.endsWith("/")&&a.hash===""&&(t=t.replace(/\/$/,"")),(e.removeTrailingSlash||a.pathname==="/")&&a.hash===""&&e.removeSingleSlash&&(t=t.replace(/\/$/,"")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\/\//,"//")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\/\//,"")),t}var xH=(t,e=!1)=>{let r=/^(?:([a-z_][a-z0-9_-]{0,31})@|https?:\/\/)([\w\.\-@]+)[\/:]([\~,\.\w,\-,\_,\/]+?(?:\.git|\/)?)$/,o=n=>{let u=new Error(n);throw u.subject_url=t,u};(typeof t!="string"||!t.trim())&&o("Invalid url."),t.length>xH.MAX_INPUT_LENGTH&&o("Input exceeds maximum length. If needed, change the value of parseUrl.MAX_INPUT_LENGTH."),e&&(typeof e!="object"&&(e={stripHash:!1}),t=agt(t,e));let a=ngt.default(t);if(a.parse_failed){let n=a.href.match(r);n?(a.protocols=["ssh"],a.protocol="ssh",a.resource=n[2],a.host=n[2],a.user=n[1],a.pathname=`/${n[3]}`,a.parse_failed=!1):o("URL parsing failed.")}return a};xH.MAX_INPUT_LENGTH=2048;eme.exports=xH});var ime=_((q5t,nme)=>{"use strict";var lgt=bH();function rme(t){if(Array.isArray(t))return t.indexOf("ssh")!==-1||t.indexOf("rsync")!==-1;if(typeof t!="string")return!1;var e=lgt(t);if(t=t.substring(t.indexOf("://")+3),rme(e))return!0;var r=new RegExp(".([a-zA-Z\\d]+):(\\d+)/");return!t.match(r)&&t.indexOf("@"){"use strict";var cgt=tme(),sme=ime();function ugt(t){var e=cgt(t);return e.token="",e.password==="x-oauth-basic"?e.token=e.user:e.user==="x-token-auth"&&(e.token=e.password),sme(e.protocols)||e.protocols.length===0&&sme(t)?e.protocol="ssh":e.protocols.length?e.protocol=e.protocols[0]:(e.protocol="file",e.protocols=["file"]),e.href=e.href.replace(/\/$/,""),e}ome.exports=ugt});var cme=_((G5t,lme)=>{"use strict";var Agt=ame();function kH(t){if(typeof t!="string")throw new Error("The url must be a string.");var e=/^([a-z\d-]{1,39})\/([-\.\w]{1,100})$/i;e.test(t)&&(t="https://github.com/"+t);var r=Agt(t),o=r.resource.split("."),a=null;switch(r.toString=function(L){return kH.stringify(this,L)},r.source=o.length>2?o.slice(1-o.length).join("."):r.source=r.resource,r.git_suffix=/\.git$/.test(r.pathname),r.name=decodeURIComponent((r.pathname||r.href).replace(/(^\/)|(\/$)/g,"").replace(/\.git$/,"")),r.owner=decodeURIComponent(r.user),r.source){case"git.cloudforge.com":r.owner=r.user,r.organization=o[0],r.source="cloudforge.com";break;case"visualstudio.com":if(r.resource==="vs-ssh.visualstudio.com"){a=r.name.split("/"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3],r.full_name=a[2]+"/"+a[3]);break}else{a=r.name.split("/"),a.length===2?(r.owner=a[1],r.name=a[1],r.full_name="_git/"+r.name):a.length===3?(r.name=a[2],a[0]==="DefaultCollection"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+"/_git/"+r.name):(r.owner=a[0],r.full_name=r.owner+"/_git/"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+"/"+r.owner+"/_git/"+r.name);break}case"dev.azure.com":case"azure.com":if(r.resource==="ssh.dev.azure.com"){a=r.name.split("/"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3]);break}else{a=r.name.split("/"),a.length===5?(r.organization=a[0],r.owner=a[1],r.name=a[4],r.full_name="_git/"+r.name):a.length===3?(r.name=a[2],a[0]==="DefaultCollection"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+"/_git/"+r.name):(r.owner=a[0],r.full_name=r.owner+"/_git/"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+"/"+r.owner+"/_git/"+r.name),r.query&&r.query.path&&(r.filepath=r.query.path.replace(/^\/+/g,"")),r.query&&r.query.version&&(r.ref=r.query.version.replace(/^GB/,""));break}default:a=r.name.split("/");var n=a.length-1;if(a.length>=2){var u=a.indexOf("-",2),A=a.indexOf("blob",2),p=a.indexOf("tree",2),h=a.indexOf("commit",2),E=a.indexOf("src",2),I=a.indexOf("raw",2),D=a.indexOf("edit",2);n=u>0?u-1:A>0?A-1:p>0?p-1:h>0?h-1:E>0?E-1:I>0?I-1:D>0?D-1:n,r.owner=a.slice(0,n).join("/"),r.name=a[n],h&&(r.commit=a[n+2])}r.ref="",r.filepathtype="",r.filepath="";var x=a.length>n&&a[n+1]==="-"?n+1:n;a.length>x+2&&["raw","src","blob","tree","edit"].indexOf(a[x+1])>=0&&(r.filepathtype=a[x+1],r.ref=a[x+2],a.length>x+3&&(r.filepath=a.slice(x+3).join("/"))),r.organization=r.owner;break}r.full_name||(r.full_name=r.owner,r.name&&(r.full_name&&(r.full_name+="/"),r.full_name+=r.name)),r.owner.startsWith("scm/")&&(r.source="bitbucket-server",r.owner=r.owner.replace("scm/",""),r.organization=r.owner,r.full_name=r.owner+"/"+r.name);var C=/(projects|users)\/(.*?)\/repos\/(.*?)((\/.*$)|$)/,T=C.exec(r.pathname);return T!=null&&(r.source="bitbucket-server",T[1]==="users"?r.owner="~"+T[2]:r.owner=T[2],r.organization=r.owner,r.name=T[3],a=T[4].split("/"),a.length>1&&(["raw","browse"].indexOf(a[1])>=0?(r.filepathtype=a[1],a.length>2&&(r.filepath=a.slice(2).join("/"))):a[1]==="commits"&&a.length>2&&(r.commit=a[2])),r.full_name=r.owner+"/"+r.name,r.query.at?r.ref=r.query.at:r.ref=""),r}kH.stringify=function(t,e){e=e||(t.protocols&&t.protocols.length?t.protocols.join("+"):t.protocol);var r=t.port?":"+t.port:"",o=t.user||"git",a=t.git_suffix?".git":"";switch(e){case"ssh":return r?"ssh://"+o+"@"+t.resource+r+"/"+t.full_name+a:o+"@"+t.resource+":"+t.full_name+a;case"git+ssh":case"ssh+git":case"ftp":case"ftps":return e+"://"+o+"@"+t.resource+r+"/"+t.full_name+a;case"http":case"https":var n=t.token?fgt(t):t.user&&(t.protocols.includes("http")||t.protocols.includes("https"))?t.user+"@":"";return e+"://"+n+t.resource+r+"/"+pgt(t)+a;default:return t.href}};function fgt(t){switch(t.source){case"bitbucket.org":return"x-token-auth:"+t.token+"@";default:return t.token+"@"}}function pgt(t){switch(t.source){case"bitbucket-server":return"scm/"+t.full_name;default:return""+t.full_name}}lme.exports=kH});var Dme=_((B9t,vme)=>{var vgt=Cx(),Dgt=kS(),Pgt=jl(),Sgt=fy(),bgt=s8(),xgt=nE(),kgt=t2();function Qgt(t){return Pgt(t)?vgt(t,xgt):Sgt(t)?[t]:Dgt(bgt(kgt(t)))}vme.exports=Qgt});function Ngt(t,e){return e===1&&Tgt.has(t[0])}function q2(t){let e=Array.isArray(t)?t:(0,bme.default)(t);return e.map((o,a)=>Fgt.test(o)?`[${o}]`:Rgt.test(o)&&!Ngt(e,a)?`.${o}`:`[${JSON.stringify(o)}]`).join("").replace(/^\./,"")}function Lgt(t,e){let r=[];if(e.methodName!==null&&r.push(pe.pretty(t,e.methodName,pe.Type.CODE)),e.file!==null){let o=[];o.push(pe.pretty(t,e.file,pe.Type.PATH)),e.line!==null&&(o.push(pe.pretty(t,e.line,pe.Type.NUMBER)),e.column!==null&&o.push(pe.pretty(t,e.column,pe.Type.NUMBER))),r.push(`(${o.join(pe.pretty(t,":","grey"))})`)}return r.join(" ")}function Vk(t,{manifestUpdates:e,reportedErrors:r},{fix:o}={}){let a=new Map,n=new Map,u=[...r.keys()].map(A=>[A,new Map]);for(let[A,p]of[...u,...e]){let h=r.get(A)?.map(x=>({text:x,fixable:!1}))??[],E=!1,I=t.getWorkspaceByCwd(A),D=I.manifest.exportTo({});for(let[x,C]of p){if(C.size>1){let T=[...C].map(([L,U])=>{let z=pe.pretty(t.configuration,L,pe.Type.INSPECT),te=U.size>0?Lgt(t.configuration,U.values().next().value):null;return te!==null?` +${z} at ${te}`:` +${z}`}).join("");h.push({text:`Conflict detected in constraint targeting ${pe.pretty(t.configuration,x,pe.Type.CODE)}; conflicting values are:${T}`,fixable:!1})}else{let[[T]]=C,L=(0,Pme.default)(D,x);if(JSON.stringify(L)===JSON.stringify(T))continue;if(!o){let U=typeof L>"u"?`Missing field ${pe.pretty(t.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,T,pe.Type.INSPECT)}`:typeof T>"u"?`Extraneous field ${pe.pretty(t.configuration,x,pe.Type.CODE)} currently set to ${pe.pretty(t.configuration,L,pe.Type.INSPECT)}`:`Invalid field ${pe.pretty(t.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,T,pe.Type.INSPECT)}, found ${pe.pretty(t.configuration,L,pe.Type.INSPECT)}`;h.push({text:U,fixable:!0});continue}typeof T>"u"?(0,xme.default)(D,x):(0,Sme.default)(D,x,T),E=!0}E&&a.set(I,D)}h.length>0&&n.set(I,h)}return{changedWorkspaces:a,remainingErrors:n}}function kme(t,{configuration:e}){let r={children:[]};for(let[o,a]of t){let n=[];for(let A of a){let p=A.text.split(/\n/);A.fixable&&(p[0]=`${pe.pretty(e,"\u2699","gray")} ${p[0]}`),n.push({value:pe.tuple(pe.Type.NO_HINT,p[0]),children:p.slice(1).map(h=>({value:pe.tuple(pe.Type.NO_HINT,h)}))})}let u={value:pe.tuple(pe.Type.LOCATOR,o.anchoredLocator),children:qe.sortMap(n,A=>A.value[1])};r.children.push(u)}return r.children=qe.sortMap(r.children,o=>o.value[1]),r}var Pme,Sme,bme,xme,ZE,Fgt,Rgt,Tgt,j2=wt(()=>{Ke();Pme=et(N2()),Sme=et(dH()),bme=et(Dme()),xme=et(EH()),ZE=class{constructor(e){this.indexedFields=e;this.items=[];this.indexes={};this.clear()}clear(){this.items=[];for(let e of this.indexedFields)this.indexes[e]=new Map}insert(e){this.items.push(e);for(let r of this.indexedFields){let o=Object.hasOwn(e,r)?e[r]:void 0;if(typeof o>"u")continue;qe.getArrayWithDefault(this.indexes[r],o).push(e)}return e}find(e){if(typeof e>"u")return this.items;let r=Object.entries(e);if(r.length===0)return this.items;let o=[],a;for(let[u,A]of r){let p=u,h=Object.hasOwn(this.indexes,p)?this.indexes[p]:void 0;if(typeof h>"u"){o.push([p,A]);continue}let E=new Set(h.get(A)??[]);if(E.size===0)return[];if(typeof a>"u")a=E;else for(let I of a)E.has(I)||a.delete(I);if(a.size===0)break}let n=[...a??[]];return o.length>0&&(n=n.filter(u=>{for(let[A,p]of o)if(!(typeof p<"u"?Object.hasOwn(u,A)&&u[A]===p:Object.hasOwn(u,A)===!1))return!1;return!0})),n}},Fgt=/^[0-9]+$/,Rgt=/^[a-zA-Z0-9_]+$/,Tgt=new Set(["scripts",..._t.allDependencies])});var Qme=_((N9t,GH)=>{var Mgt;(function(t){var e=function(){return{"append/2":[new t.type.Rule(new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("L")]),new t.type.Term("foldl",[new t.type.Term("append",[]),new t.type.Var("X"),new t.type.Term("[]",[]),new t.type.Var("L")]))],"append/3":[new t.type.Rule(new t.type.Term("append",[new t.type.Term("[]",[]),new t.type.Var("X"),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("append",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("S")])]),new t.type.Term("append",[new t.type.Var("T"),new t.type.Var("X"),new t.type.Var("S")]))],"member/2":[new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("_")])]),null),new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("Xs")])]),new t.type.Term("member",[new t.type.Var("X"),new t.type.Var("Xs")]))],"permutation/2":[new t.type.Rule(new t.type.Term("permutation",[new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("permutation",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("permutation",[new t.type.Var("T"),new t.type.Var("P")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("P")]),new t.type.Term("append",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("Y")]),new t.type.Var("S")])])]))],"maplist/2":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("X")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("Xs")])]))],"maplist/3":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs")])]))],"maplist/4":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs")])]))],"maplist/5":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds")])]))],"maplist/6":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es")])]))],"maplist/7":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")]),new t.type.Term(".",[new t.type.Var("F"),new t.type.Var("Fs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E"),new t.type.Var("F")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es"),new t.type.Var("Fs")])]))],"maplist/8":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")]),new t.type.Term(".",[new t.type.Var("F"),new t.type.Var("Fs")]),new t.type.Term(".",[new t.type.Var("G"),new t.type.Var("Gs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E"),new t.type.Var("F"),new t.type.Var("G")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es"),new t.type.Var("Fs"),new t.type.Var("Gs")])]))],"include/3":[new t.type.Rule(new t.type.Term("include",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("include",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("A")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("A"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term("[]",[])]),new t.type.Var("B")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("F"),new t.type.Var("B")]),new t.type.Term(",",[new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("F")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("S")])]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("L"),new t.type.Var("S")])]),new t.type.Term("include",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("S")])])])])]))],"exclude/3":[new t.type.Rule(new t.type.Term("exclude",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("exclude",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("exclude",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("E")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term("[]",[])]),new t.type.Var("Q")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("R"),new t.type.Var("Q")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("R")]),new t.type.Term(",",[new t.type.Term("!",[]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("E")])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("E")])])])])])])]))],"foldl/4":[new t.type.Rule(new t.type.Term("foldl",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Var("I"),new t.type.Var("I")]),null),new t.type.Rule(new t.type.Term("foldl",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("I"),new t.type.Var("R")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("I"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])])])]),new t.type.Var("L2")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P2"),new t.type.Var("L2")]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P2")]),new t.type.Term("foldl",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("X"),new t.type.Var("R")])])])])]))],"select/3":[new t.type.Rule(new t.type.Term("select",[new t.type.Var("E"),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Xs")]),new t.type.Var("Xs")]),null),new t.type.Rule(new t.type.Term("select",[new t.type.Var("E"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Ys")])]),new t.type.Term("select",[new t.type.Var("E"),new t.type.Var("Xs"),new t.type.Var("Ys")]))],"sum_list/2":[new t.type.Rule(new t.type.Term("sum_list",[new t.type.Term("[]",[]),new t.type.Num(0,!1)]),null),new t.type.Rule(new t.type.Term("sum_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("sum_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term("is",[new t.type.Var("S"),new t.type.Term("+",[new t.type.Var("X"),new t.type.Var("Y")])])]))],"max_list/2":[new t.type.Rule(new t.type.Term("max_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("max_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("max_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Var("Y")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("X")]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("Y")])])]))],"min_list/2":[new t.type.Rule(new t.type.Term("min_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("min_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("min_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("=<",[new t.type.Var("X"),new t.type.Var("Y")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("X")]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("Y")])])]))],"prod_list/2":[new t.type.Rule(new t.type.Term("prod_list",[new t.type.Term("[]",[]),new t.type.Num(1,!1)]),null),new t.type.Rule(new t.type.Term("prod_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("prod_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term("is",[new t.type.Var("S"),new t.type.Term("*",[new t.type.Var("X"),new t.type.Var("Y")])])]))],"last/2":[new t.type.Rule(new t.type.Term("last",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("last",[new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("Xs")]),new t.type.Var("X")]),new t.type.Term("last",[new t.type.Var("Xs"),new t.type.Var("X")]))],"prefix/2":[new t.type.Rule(new t.type.Term("prefix",[new t.type.Var("Part"),new t.type.Var("Whole")]),new t.type.Term("append",[new t.type.Var("Part"),new t.type.Var("_"),new t.type.Var("Whole")]))],"nth0/3":[new t.type.Rule(new t.type.Term("nth0",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")])]),new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")]),new t.type.Term("!",[])])])]))],"nth1/3":[new t.type.Rule(new t.type.Term("nth1",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")])]),new t.type.Term(",",[new t.type.Term(">",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")]),new t.type.Term("!",[])])])]))],"nth0/4":[new t.type.Rule(new t.type.Term("nth0",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")])]),new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term("!",[])])])]))],"nth1/4":[new t.type.Rule(new t.type.Term("nth1",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")])]),new t.type.Term(",",[new t.type.Term(">",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term("!",[])])])]))],"nth/5":[new t.type.Rule(new t.type.Term("nth",[new t.type.Var("N"),new t.type.Var("N"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("X"),new t.type.Var("Xs")]),null),new t.type.Rule(new t.type.Term("nth",[new t.type.Var("N"),new t.type.Var("O"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("Y"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Ys")])]),new t.type.Term(",",[new t.type.Term("is",[new t.type.Var("M"),new t.type.Term("+",[new t.type.Var("N"),new t.type.Num(1,!1)])]),new t.type.Term("nth",[new t.type.Var("M"),new t.type.Var("O"),new t.type.Var("Xs"),new t.type.Var("Y"),new t.type.Var("Ys")])]))],"length/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(!t.type.is_variable(A)&&!t.type.is_integer(A))o.throw_error(t.error.type("integer",A,n.indicator));else if(t.type.is_integer(A)&&A.value<0)o.throw_error(t.error.domain("not_less_than_zero",A,n.indicator));else{var p=new t.type.Term("length",[u,new t.type.Num(0,!1),A]);t.type.is_integer(A)&&(p=new t.type.Term(",",[p,new t.type.Term("!",[])])),o.prepend([new t.type.State(a.goal.replace(p),a.substitution,a)])}},"length/3":[new t.type.Rule(new t.type.Term("length",[new t.type.Term("[]",[]),new t.type.Var("N"),new t.type.Var("N")]),null),new t.type.Rule(new t.type.Term("length",[new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("X")]),new t.type.Var("A"),new t.type.Var("N")]),new t.type.Term(",",[new t.type.Term("succ",[new t.type.Var("A"),new t.type.Var("B")]),new t.type.Term("length",[new t.type.Var("X"),new t.type.Var("B"),new t.type.Var("N")])]))],"replicate/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_integer(A))o.throw_error(t.error.type("integer",A,n.indicator));else if(A.value<0)o.throw_error(t.error.domain("not_less_than_zero",A,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=new t.type.Term("[]"),E=0;E0;I--)E[I].equals(E[I-1])&&E.splice(I,1);for(var D=new t.type.Term("[]"),I=E.length-1;I>=0;I--)D=new t.type.Term(".",[E[I],D]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[D,A])),a.substitution,a)])}}},"msort/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else{for(var p=[],h=u;h.indicator==="./2";)p.push(h.args[0]),h=h.args[1];if(t.type.is_variable(h))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(h))o.throw_error(t.error.type("list",u,n.indicator));else{for(var E=p.sort(t.compare),I=new t.type.Term("[]"),D=E.length-1;D>=0;D--)I=new t.type.Term(".",[E[D],I]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,A])),a.substitution,a)])}}},"keysort/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else{for(var p=[],h,E=u;E.indicator==="./2";){if(h=E.args[0],t.type.is_variable(h)){o.throw_error(t.error.instantiation(n.indicator));return}else if(!t.type.is_term(h)||h.indicator!=="-/2"){o.throw_error(t.error.type("pair",h,n.indicator));return}h.args[0].pair=h.args[1],p.push(h.args[0]),E=E.args[1]}if(t.type.is_variable(E))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(E))o.throw_error(t.error.type("list",u,n.indicator));else{for(var I=p.sort(t.compare),D=new t.type.Term("[]"),x=I.length-1;x>=0;x--)D=new t.type.Term(".",[new t.type.Term("-",[I[x],I[x].pair]),D]),delete I[x].pair;o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[D,A])),a.substitution,a)])}}},"take/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type("integer",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=u.value,E=[],I=A;h>0&&I.indicator==="./2";)E.push(I.args[0]),I=I.args[1],h--;if(h===0){for(var D=new t.type.Term("[]"),h=E.length-1;h>=0;h--)D=new t.type.Term(".",[E[h],D]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[D,p])),a.substitution,a)])}}},"drop/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type("integer",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=u.value,E=[],I=A;h>0&&I.indicator==="./2";)E.push(I.args[0]),I=I.args[1],h--;h===0&&o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,p])),a.substitution,a)])}},"reverse/2":function(o,a,n){var u=n.args[0],A=n.args[1],p=t.type.is_instantiated_list(u),h=t.type.is_instantiated_list(A);if(t.type.is_variable(u)&&t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(u)&&!t.type.is_fully_list(u))o.throw_error(t.error.type("list",u,n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!p&&!h)o.throw_error(t.error.instantiation(n.indicator));else{for(var E=p?u:A,I=new t.type.Term("[]",[]);E.indicator==="./2";)I=new t.type.Term(".",[E.args[0],I]),E=E.args[1];o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,p?A:u])),a.substitution,a)])}},"list_to_set/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else{for(var p=u,h=[];p.indicator==="./2";)h.push(p.args[0]),p=p.args[1];if(t.type.is_variable(p))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_term(p)||p.indicator!=="[]/0")o.throw_error(t.error.type("list",u,n.indicator));else{for(var E=[],I=new t.type.Term("[]",[]),D,x=0;x=0;x--)I=new t.type.Term(".",[E[x],I]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[A,I])),a.substitution,a)])}}}}},r=["append/2","append/3","member/2","permutation/2","maplist/2","maplist/3","maplist/4","maplist/5","maplist/6","maplist/7","maplist/8","include/3","exclude/3","foldl/4","sum_list/2","max_list/2","min_list/2","prod_list/2","last/2","prefix/2","nth0/3","nth1/3","nth0/4","nth1/4","length/2","replicate/3","select/3","sort/2","msort/2","keysort/2","take/3","drop/3","reverse/2","list_to_set/2"];typeof GH<"u"?GH.exports=function(o){t=o,new t.type.Module("lists",e(),r)}:new t.type.Module("lists",e(),r)})(Mgt)});var Wme=_(Vr=>{"use strict";var Xg=process.platform==="win32",YH="aes-256-cbc",Ogt="sha256",Tme="The current environment doesn't support interactive reading from TTY.",Xn=ve("fs"),Fme=process.binding("tty_wrap").TTY,KH=ve("child_process"),Nh=ve("path"),VH={prompt:"> ",hideEchoBack:!1,mask:"*",limit:[],limitMessage:"Input another, please.$<( [)limit(])>",defaultInput:"",trueValue:[],falseValue:[],caseSensitive:!1,keepWhitespace:!1,encoding:"utf8",bufferSize:1024,print:void 0,history:!0,cd:!1,phContent:void 0,preCheck:void 0},Kf="none",iu,eC,Rme=!1,Th,Jk,WH,Ugt=0,$H="",Jg=[],Xk,Nme=!1,zH=!1,G2=!1;function Lme(t){function e(r){return r.replace(/[^\w\u0080-\uFFFF]/g,function(o){return"#"+o.charCodeAt(0)+";"})}return Jk.concat(function(r){var o=[];return Object.keys(r).forEach(function(a){r[a]==="boolean"?t[a]&&o.push("--"+a):r[a]==="string"&&t[a]&&o.push("--"+a,e(t[a]))}),o}({display:"string",displayOnly:"boolean",keyIn:"boolean",hideEchoBack:"boolean",mask:"string",limit:"string",caseSensitive:"boolean"}))}function _gt(t,e){function r(U){var z,te="",le;for(WH=WH||ve("os").tmpdir();;){z=Nh.join(WH,U+te);try{le=Xn.openSync(z,"wx")}catch(ce){if(ce.code==="EEXIST"){te++;continue}else throw ce}Xn.closeSync(le);break}return z}var o,a,n,u={},A,p,h=r("readline-sync.stdout"),E=r("readline-sync.stderr"),I=r("readline-sync.exit"),D=r("readline-sync.done"),x=ve("crypto"),C,T,L;C=x.createHash(Ogt),C.update(""+process.pid+Ugt+++Math.random()),L=C.digest("hex"),T=x.createDecipher(YH,L),o=Lme(t),Xg?(a=process.env.ComSpec||"cmd.exe",process.env.Q='"',n=["/V:ON","/S","/C","(%Q%"+a+"%Q% /V:ON /S /C %Q%%Q%"+Th+"%Q%"+o.map(function(U){return" %Q%"+U+"%Q%"}).join("")+" & (echo !ERRORLEVEL!)>%Q%"+I+"%Q%%Q%) 2>%Q%"+E+"%Q% |%Q%"+process.execPath+"%Q% %Q%"+__dirname+"\\encrypt.js%Q% %Q%"+YH+"%Q% %Q%"+L+"%Q% >%Q%"+h+"%Q% & (echo 1)>%Q%"+D+"%Q%"]):(a="/bin/sh",n=["-c",'("'+Th+'"'+o.map(function(U){return" '"+U.replace(/'/g,"'\\''")+"'"}).join("")+'; echo $?>"'+I+'") 2>"'+E+'" |"'+process.execPath+'" "'+__dirname+'/encrypt.js" "'+YH+'" "'+L+'" >"'+h+'"; echo 1 >"'+D+'"']),G2&&G2("_execFileSync",o);try{KH.spawn(a,n,e)}catch(U){u.error=new Error(U.message),u.error.method="_execFileSync - spawn",u.error.program=a,u.error.args=n}for(;Xn.readFileSync(D,{encoding:t.encoding}).trim()!=="1";);return(A=Xn.readFileSync(I,{encoding:t.encoding}).trim())==="0"?u.input=T.update(Xn.readFileSync(h,{encoding:"binary"}),"hex",t.encoding)+T.final(t.encoding):(p=Xn.readFileSync(E,{encoding:t.encoding}).trim(),u.error=new Error(Tme+(p?` +`+p:"")),u.error.method="_execFileSync",u.error.program=a,u.error.args=n,u.error.extMessage=p,u.error.exitCode=+A),Xn.unlinkSync(h),Xn.unlinkSync(E),Xn.unlinkSync(I),Xn.unlinkSync(D),u}function Hgt(t){var e,r={},o,a={env:process.env,encoding:t.encoding};if(Th||(Xg?process.env.PSModulePath?(Th="powershell.exe",Jk=["-ExecutionPolicy","Bypass","-File",__dirname+"\\read.ps1"]):(Th="cscript.exe",Jk=["//nologo",__dirname+"\\read.cs.js"]):(Th="/bin/sh",Jk=[__dirname+"/read.sh"])),Xg&&!process.env.PSModulePath&&(a.stdio=[process.stdin]),KH.execFileSync){e=Lme(t),G2&&G2("execFileSync",e);try{r.input=KH.execFileSync(Th,e,a)}catch(n){o=n.stderr?(n.stderr+"").trim():"",r.error=new Error(Tme+(o?` +`+o:"")),r.error.method="execFileSync",r.error.program=Th,r.error.args=e,r.error.extMessage=o,r.error.exitCode=n.status,r.error.code=n.code,r.error.signal=n.signal}}else r=_gt(t,a);return r.error||(r.input=r.input.replace(/^\s*'|'\s*$/g,""),t.display=""),r}function JH(t){var e="",r=t.display,o=!t.display&&t.keyIn&&t.hideEchoBack&&!t.mask;function a(){var n=Hgt(t);if(n.error)throw n.error;return n.input}return zH&&zH(t),function(){var n,u,A;function p(){return n||(n=process.binding("fs"),u=process.binding("constants")),n}if(typeof Kf=="string")if(Kf=null,Xg){if(A=function(h){var E=h.replace(/^\D+/,"").split("."),I=0;return(E[0]=+E[0])&&(I+=E[0]*1e4),(E[1]=+E[1])&&(I+=E[1]*100),(E[2]=+E[2])&&(I+=E[2]),I}(process.version),!(A>=20302&&A<40204||A>=5e4&&A<50100||A>=50600&&A<60200)&&process.stdin.isTTY)process.stdin.pause(),Kf=process.stdin.fd,eC=process.stdin._handle;else try{Kf=p().open("CONIN$",u.O_RDWR,parseInt("0666",8)),eC=new Fme(Kf,!0)}catch{}if(process.stdout.isTTY)iu=process.stdout.fd;else{try{iu=Xn.openSync("\\\\.\\CON","w")}catch{}if(typeof iu!="number")try{iu=p().open("CONOUT$",u.O_RDWR,parseInt("0666",8))}catch{}}}else{if(process.stdin.isTTY){process.stdin.pause();try{Kf=Xn.openSync("/dev/tty","r"),eC=process.stdin._handle}catch{}}else try{Kf=Xn.openSync("/dev/tty","r"),eC=new Fme(Kf,!1)}catch{}if(process.stdout.isTTY)iu=process.stdout.fd;else try{iu=Xn.openSync("/dev/tty","w")}catch{}}}(),function(){var n,u,A=!t.hideEchoBack&&!t.keyIn,p,h,E,I,D;Xk="";function x(C){return C===Rme?!0:eC.setRawMode(C)!==0?!1:(Rme=C,!0)}if(Nme||!eC||typeof iu!="number"&&(t.display||!A)){e=a();return}if(t.display&&(Xn.writeSync(iu,t.display),t.display=""),!t.displayOnly){if(!x(!A)){e=a();return}for(h=t.keyIn?1:t.bufferSize,p=Buffer.allocUnsafe&&Buffer.alloc?Buffer.alloc(h):new Buffer(h),t.keyIn&&t.limit&&(u=new RegExp("[^"+t.limit+"]","g"+(t.caseSensitive?"":"i")));;){E=0;try{E=Xn.readSync(Kf,p,0,h)}catch(C){if(C.code!=="EOF"){x(!1),e+=a();return}}if(E>0?(I=p.toString(t.encoding,0,E),Xk+=I):(I=` +`,Xk+="\0"),I&&typeof(D=(I.match(/^(.*?)[\r\n]/)||[])[1])=="string"&&(I=D,n=!0),I&&(I=I.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")),I&&u&&(I=I.replace(u,"")),I&&(A||(t.hideEchoBack?t.mask&&Xn.writeSync(iu,new Array(I.length+1).join(t.mask)):Xn.writeSync(iu,I)),e+=I),!t.keyIn&&n||t.keyIn&&e.length>=h)break}!A&&!o&&Xn.writeSync(iu,` +`),x(!1)}}(),t.print&&!o&&t.print(r+(t.displayOnly?"":(t.hideEchoBack?new Array(e.length+1).join(t.mask):e)+` +`),t.encoding),t.displayOnly?"":$H=t.keepWhitespace||t.keyIn?e:e.trim()}function qgt(t,e){var r=[];function o(a){a!=null&&(Array.isArray(a)?a.forEach(o):(!e||e(a))&&r.push(a))}return o(t),r}function e6(t){return t.replace(/[\x00-\x7f]/g,function(e){return"\\x"+("00"+e.charCodeAt().toString(16)).substr(-2)})}function xs(){var t=Array.prototype.slice.call(arguments),e,r;return t.length&&typeof t[0]=="boolean"&&(r=t.shift(),r&&(e=Object.keys(VH),t.unshift(VH))),t.reduce(function(o,a){return a==null||(a.hasOwnProperty("noEchoBack")&&!a.hasOwnProperty("hideEchoBack")&&(a.hideEchoBack=a.noEchoBack,delete a.noEchoBack),a.hasOwnProperty("noTrim")&&!a.hasOwnProperty("keepWhitespace")&&(a.keepWhitespace=a.noTrim,delete a.noTrim),r||(e=Object.keys(a)),e.forEach(function(n){var u;if(a.hasOwnProperty(n))switch(u=a[n],n){case"mask":case"limitMessage":case"defaultInput":case"encoding":u=u!=null?u+"":"",u&&n!=="limitMessage"&&(u=u.replace(/[\r\n]/g,"")),o[n]=u;break;case"bufferSize":!isNaN(u=parseInt(u,10))&&typeof u=="number"&&(o[n]=u);break;case"displayOnly":case"keyIn":case"hideEchoBack":case"caseSensitive":case"keepWhitespace":case"history":case"cd":o[n]=!!u;break;case"limit":case"trueValue":case"falseValue":o[n]=qgt(u,function(A){var p=typeof A;return p==="string"||p==="number"||p==="function"||A instanceof RegExp}).map(function(A){return typeof A=="string"?A.replace(/[\r\n]/g,""):A});break;case"print":case"phContent":case"preCheck":o[n]=typeof u=="function"?u:void 0;break;case"prompt":case"display":o[n]=u??"";break}})),o},{})}function XH(t,e,r){return e.some(function(o){var a=typeof o;return a==="string"?r?t===o:t.toLowerCase()===o.toLowerCase():a==="number"?parseFloat(t)===o:a==="function"?o(t):o instanceof RegExp?o.test(t):!1})}function t6(t,e){var r=Nh.normalize(Xg?(process.env.HOMEDRIVE||"")+(process.env.HOMEPATH||""):process.env.HOME||"").replace(/[\/\\]+$/,"");return t=Nh.normalize(t),e?t.replace(/^~(?=\/|\\|$)/,r):t.replace(new RegExp("^"+e6(r)+"(?=\\/|\\\\|$)",Xg?"i":""),"~")}function tC(t,e){var r="(?:\\(([\\s\\S]*?)\\))?(\\w+|.-.)(?:\\(([\\s\\S]*?)\\))?",o=new RegExp("(\\$)?(\\$<"+r+">)","g"),a=new RegExp("(\\$)?(\\$\\{"+r+"\\})","g");function n(u,A,p,h,E,I){var D;return A||typeof(D=e(E))!="string"?p:D?(h||"")+D+(I||""):""}return t.replace(o,n).replace(a,n)}function Mme(t,e,r){var o,a=[],n=-1,u=0,A="",p;function h(E,I){return I.length>3?(E.push(I[0]+"..."+I[I.length-1]),p=!0):I.length&&(E=E.concat(I)),E}return o=t.reduce(function(E,I){return E.concat((I+"").split(""))},[]).reduce(function(E,I){var D,x;return e||(I=I.toLowerCase()),D=/^\d$/.test(I)?1:/^[A-Z]$/.test(I)?2:/^[a-z]$/.test(I)?3:0,r&&D===0?A+=I:(x=I.charCodeAt(0),D&&D===n&&x===u+1?a.push(I):(E=h(E,a),a=[I],n=D),u=x),E},[]),o=h(o,a),A&&(o.push(A),p=!0),{values:o,suppressed:p}}function Ome(t,e){return t.join(t.length>2?", ":e?" / ":"/")}function Ume(t,e){var r,o,a={},n;if(e.phContent&&(r=e.phContent(t,e)),typeof r!="string")switch(t){case"hideEchoBack":case"mask":case"defaultInput":case"caseSensitive":case"keepWhitespace":case"encoding":case"bufferSize":case"history":case"cd":r=e.hasOwnProperty(t)?typeof e[t]=="boolean"?e[t]?"on":"off":e[t]+"":"";break;case"limit":case"trueValue":case"falseValue":o=e[e.hasOwnProperty(t+"Src")?t+"Src":t],e.keyIn?(a=Mme(o,e.caseSensitive),o=a.values):o=o.filter(function(u){var A=typeof u;return A==="string"||A==="number"}),r=Ome(o,a.suppressed);break;case"limitCount":case"limitCountNotZero":r=e[e.hasOwnProperty("limitSrc")?"limitSrc":"limit"].length,r=r||t!=="limitCountNotZero"?r+"":"";break;case"lastInput":r=$H;break;case"cwd":case"CWD":case"cwdHome":r=process.cwd(),t==="CWD"?r=Nh.basename(r):t==="cwdHome"&&(r=t6(r));break;case"date":case"time":case"localeDate":case"localeTime":r=new Date()["to"+t.replace(/^./,function(u){return u.toUpperCase()})+"String"]();break;default:typeof(n=(t.match(/^history_m(\d+)$/)||[])[1])=="string"&&(r=Jg[Jg.length-n]||"")}return r}function _me(t){var e=/^(.)-(.)$/.exec(t),r="",o,a,n,u;if(!e)return null;for(o=e[1].charCodeAt(0),a=e[2].charCodeAt(0),u=o +And the length must be: $`,trueValue:null,falseValue:null,caseSensitive:!0},e,{history:!1,cd:!1,phContent:function(x){return x==="charlist"?r.text:x==="length"?o+"..."+a:null}}),u,A,p,h,E,I,D;for(e=e||{},u=tC(e.charlist?e.charlist+"":"$",_me),(isNaN(o=parseInt(e.min,10))||typeof o!="number")&&(o=12),(isNaN(a=parseInt(e.max,10))||typeof a!="number")&&(a=24),h=new RegExp("^["+e6(u)+"]{"+o+","+a+"}$"),r=Mme([u],n.caseSensitive,!0),r.text=Ome(r.values,r.suppressed),A=e.confirmMessage!=null?e.confirmMessage:"Reinput a same one to confirm it: ",p=e.unmatchMessage!=null?e.unmatchMessage:"It differs from first one. Hit only the Enter key if you want to retry from first one.",t==null&&(t="Input new password: "),E=n.limitMessage;!D;)n.limit=h,n.limitMessage=E,I=Vr.question(t,n),n.limit=[I,""],n.limitMessage=p,D=Vr.question(A,n);return I};function jme(t,e,r){var o;function a(n){return o=r(n),!isNaN(o)&&typeof o=="number"}return Vr.question(t,xs({limitMessage:"Input valid number, please."},e,{limit:a,cd:!1})),o}Vr.questionInt=function(t,e){return jme(t,e,function(r){return parseInt(r,10)})};Vr.questionFloat=function(t,e){return jme(t,e,parseFloat)};Vr.questionPath=function(t,e){var r,o="",a=xs({hideEchoBack:!1,limitMessage:`$Input valid path, please.$<( Min:)min>$<( Max:)max>`,history:!0,cd:!0},e,{keepWhitespace:!1,limit:function(n){var u,A,p;n=t6(n,!0),o="";function h(E){E.split(/\/|\\/).reduce(function(I,D){var x=Nh.resolve(I+=D+Nh.sep);if(!Xn.existsSync(x))Xn.mkdirSync(x);else if(!Xn.statSync(x).isDirectory())throw new Error("Non directory already exists: "+x);return I},"")}try{if(u=Xn.existsSync(n),r=u?Xn.realpathSync(n):Nh.resolve(n),!e.hasOwnProperty("exists")&&!u||typeof e.exists=="boolean"&&e.exists!==u)return o=(u?"Already exists":"No such file or directory")+": "+r,!1;if(!u&&e.create&&(e.isDirectory?h(r):(h(Nh.dirname(r)),Xn.closeSync(Xn.openSync(r,"w"))),r=Xn.realpathSync(r)),u&&(e.min||e.max||e.isFile||e.isDirectory)){if(A=Xn.statSync(r),e.isFile&&!A.isFile())return o="Not file: "+r,!1;if(e.isDirectory&&!A.isDirectory())return o="Not directory: "+r,!1;if(e.min&&A.size<+e.min||e.max&&A.size>+e.max)return o="Size "+A.size+" is out of range: "+r,!1}if(typeof e.validate=="function"&&(p=e.validate(r))!==!0)return typeof p=="string"&&(o=p),!1}catch(E){return o=E+"",!1}return!0},phContent:function(n){return n==="error"?o:n!=="min"&&n!=="max"?null:e.hasOwnProperty(n)?e[n]+"":""}});return e=e||{},t==null&&(t='Input path (you can "cd" and "pwd"): '),Vr.question(t,a),r};function Gme(t,e){var r={},o={};return typeof t=="object"?(Object.keys(t).forEach(function(a){typeof t[a]=="function"&&(o[e.caseSensitive?a:a.toLowerCase()]=t[a])}),r.preCheck=function(a){var n;return r.args=ZH(a),n=r.args[0]||"",e.caseSensitive||(n=n.toLowerCase()),r.hRes=n!=="_"&&o.hasOwnProperty(n)?o[n].apply(a,r.args.slice(1)):o.hasOwnProperty("_")?o._.apply(a,r.args):null,{res:a,forceNext:!1}},o.hasOwnProperty("_")||(r.limit=function(){var a=r.args[0]||"";return e.caseSensitive||(a=a.toLowerCase()),o.hasOwnProperty(a)})):r.preCheck=function(a){return r.args=ZH(a),r.hRes=typeof t=="function"?t.apply(a,r.args):!0,{res:a,forceNext:!1}},r}Vr.promptCL=function(t,e){var r=xs({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),o=Gme(t,r);return r.limit=o.limit,r.preCheck=o.preCheck,Vr.prompt(r),o.args};Vr.promptLoop=function(t,e){for(var r=xs({hideEchoBack:!1,trueValue:null,falseValue:null,caseSensitive:!1,history:!0},e);!t(Vr.prompt(r)););};Vr.promptCLLoop=function(t,e){var r=xs({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),o=Gme(t,r);for(r.limit=o.limit,r.preCheck=o.preCheck;Vr.prompt(r),!o.hRes;);};Vr.promptSimShell=function(t){return Vr.prompt(xs({hideEchoBack:!1,history:!0},t,{prompt:function(){return Xg?"$>":(process.env.USER||"")+(process.env.HOSTNAME?"@"+process.env.HOSTNAME.replace(/\..*$/,""):"")+":$$ "}()}))};function Yme(t,e,r){var o;return t==null&&(t="Are you sure? "),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s*:?\s*$/,"")+" [y/n]: "),o=Vr.keyIn(t,xs(e,{hideEchoBack:!1,limit:r,trueValue:"y",falseValue:"n",caseSensitive:!1})),typeof o=="boolean"?o:""}Vr.keyInYN=function(t,e){return Yme(t,e)};Vr.keyInYNStrict=function(t,e){return Yme(t,e,"yn")};Vr.keyInPause=function(t,e){t==null&&(t="Continue..."),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s+$/,"")+" (Hit any key)"),Vr.keyIn(t,xs({limit:null},e,{hideEchoBack:!0,mask:""}))};Vr.keyInSelect=function(t,e,r){var o=xs({hideEchoBack:!1},r,{trueValue:null,falseValue:null,caseSensitive:!1,phContent:function(p){return p==="itemsCount"?t.length+"":p==="firstItem"?(t[0]+"").trim():p==="lastItem"?(t[t.length-1]+"").trim():null}}),a="",n={},u=49,A=` +`;if(!Array.isArray(t)||!t.length||t.length>35)throw"`items` must be Array (max length: 35).";return t.forEach(function(p,h){var E=String.fromCharCode(u);a+=E,n[E]=h,A+="["+E+"] "+(p+"").trim()+` +`,u=u===57?97:u+1}),(!r||r.cancel!==!1)&&(a+="0",n[0]=-1,A+="[0] "+(r&&r.cancel!=null&&typeof r.cancel!="boolean"?(r.cancel+"").trim():"CANCEL")+` +`),o.limit=a,A+=` +`,e==null&&(e="Choose one from list: "),(e+="")&&((!r||r.guide!==!1)&&(e=e.replace(/\s*:?\s*$/,"")+" [$]: "),A+=e),n[Vr.keyIn(A,o).toLowerCase()]};Vr.getRawInput=function(){return Xk};function Y2(t,e){var r;return e.length&&(r={},r[t]=e[0]),Vr.setDefaultOptions(r)[t]}Vr.setPrint=function(){return Y2("print",arguments)};Vr.setPrompt=function(){return Y2("prompt",arguments)};Vr.setEncoding=function(){return Y2("encoding",arguments)};Vr.setMask=function(){return Y2("mask",arguments)};Vr.setBufferSize=function(){return Y2("bufferSize",arguments)}});var r6=_((M9t,El)=>{(function(){var t={major:0,minor:2,patch:66,status:"beta"};tau_file_system={files:{},open:function(w,S,y){var R=tau_file_system.files[w];if(!R){if(y==="read")return null;R={path:w,text:"",type:S,get:function(J,X){return X===this.text.length||X>this.text.length?"end_of_file":this.text.substring(X,X+J)},put:function(J,X){return X==="end_of_file"?(this.text+=J,!0):X==="past_end_of_file"?null:(this.text=this.text.substring(0,X)+J+this.text.substring(X+J.length),!0)},get_byte:function(J){if(J==="end_of_stream")return-1;var X=Math.floor(J/2);if(this.text.length<=X)return-1;var $=n(this.text[Math.floor(J/2)],0);return J%2===0?$&255:$/256>>>0},put_byte:function(J,X){var $=X==="end_of_stream"?this.text.length:Math.floor(X/2);if(this.text.length<$)return null;var se=this.text.length===$?-1:n(this.text[Math.floor(X/2)],0);return X%2===0?(se=se/256>>>0,se=(se&255)<<8|J&255):(se=se&255,se=(J&255)<<8|se&255),this.text.length===$?this.text+=u(se):this.text=this.text.substring(0,$)+u(se)+this.text.substring($+1),!0},flush:function(){return!0},close:function(){var J=tau_file_system.files[this.path];return J?!0:null}},tau_file_system.files[w]=R}return y==="write"&&(R.text=""),R}},tau_user_input={buffer:"",get:function(w,S){for(var y;tau_user_input.buffer.length\?\@\^\~\\]+|'(?:[^']*?(?:\\(?:x?\d+)?\\)*(?:'')*(?:\\')*)*')/,number:/^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\[abfnrtv\\'"`]|\\x?\d+\\|[^\\])|\d+(?:\.\d+(?:[eE][+-]?\d+)?)?)/,string:/^(?:"([^"]|""|\\")*"|`([^`]|``|\\`)*`)/,l_brace:/^(?:\[)/,r_brace:/^(?:\])/,l_bracket:/^(?:\{)/,r_bracket:/^(?:\})/,bar:/^(?:\|)/,l_paren:/^(?:\()/,r_paren:/^(?:\))/};function L(w,S){return w.get_flag("char_conversion").id==="on"?S.replace(/./g,function(y){return w.get_char_conversion(y)}):S}function U(w){this.thread=w,this.text="",this.tokens=[]}U.prototype.set_last_tokens=function(w){return this.tokens=w},U.prototype.new_text=function(w){this.text=w,this.tokens=[]},U.prototype.get_tokens=function(w){var S,y=0,R=0,J=0,X=[],$=!1;if(w){var se=this.tokens[w-1];y=se.len,S=L(this.thread,this.text.substr(se.len)),R=se.line,J=se.start}else S=this.text;if(/^\s*$/.test(S))return null;for(;S!=="";){var be=[],Fe=!1;if(/^\n/.exec(S)!==null){R++,J=0,y++,S=S.replace(/\n/,""),$=!0;continue}for(var lt in T)if(T.hasOwnProperty(lt)){var Et=T[lt].exec(S);Et&&be.push({value:Et[0],name:lt,matches:Et})}if(!be.length)return this.set_last_tokens([{value:S,matches:[],name:"lexical",line:R,start:J}]);var se=r(be,function(Pr,yr){return Pr.value.length>=yr.value.length?Pr:yr});switch(se.start=J,se.line=R,S=S.replace(se.value,""),J+=se.value.length,y+=se.value.length,se.name){case"atom":se.raw=se.value,se.value.charAt(0)==="'"&&(se.value=D(se.value.substr(1,se.value.length-2),"'"),se.value===null&&(se.name="lexical",se.value="unknown escape sequence"));break;case"number":se.float=se.value.substring(0,2)!=="0x"&&se.value.match(/[.eE]/)!==null&&se.value!=="0'.",se.value=C(se.value),se.blank=Fe;break;case"string":var qt=se.value.charAt(0);se.value=D(se.value.substr(1,se.value.length-2),qt),se.value===null&&(se.name="lexical",se.value="unknown escape sequence");break;case"whitespace":var nr=X[X.length-1];nr&&(nr.space=!0),Fe=!0;continue;case"r_bracket":X.length>0&&X[X.length-1].name==="l_bracket"&&(se=X.pop(),se.name="atom",se.value="{}",se.raw="{}",se.space=!1);break;case"r_brace":X.length>0&&X[X.length-1].name==="l_brace"&&(se=X.pop(),se.name="atom",se.value="[]",se.raw="[]",se.space=!1);break}se.len=y,X.push(se),Fe=!1}var St=this.set_last_tokens(X);return St.length===0?null:St};function z(w,S,y,R,J){if(!S[y])return{type:A,value:b.error.syntax(S[y-1],"expression expected",!0)};var X;if(R==="0"){var $=S[y];switch($.name){case"number":return{type:p,len:y+1,value:new b.type.Num($.value,$.float)};case"variable":return{type:p,len:y+1,value:new b.type.Var($.value)};case"string":var se;switch(w.get_flag("double_quotes").id){case"atom":se=new q($.value,[]);break;case"codes":se=new q("[]",[]);for(var be=$.value.length-1;be>=0;be--)se=new q(".",[new b.type.Num(n($.value,be),!1),se]);break;case"chars":se=new q("[]",[]);for(var be=$.value.length-1;be>=0;be--)se=new q(".",[new b.type.Term($.value.charAt(be),[]),se]);break}return{type:p,len:y+1,value:se};case"l_paren":var St=z(w,S,y+1,w.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name==="r_paren"?(St.len++,St):{type:A,derived:!0,value:b.error.syntax(S[St.len]?S[St.len]:S[St.len-1],") or operator expected",!S[St.len])};case"l_bracket":var St=z(w,S,y+1,w.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name==="r_bracket"?(St.len++,St.value=new q("{}",[St.value]),St):{type:A,derived:!0,value:b.error.syntax(S[St.len]?S[St.len]:S[St.len-1],"} or operator expected",!S[St.len])}}var Fe=te(w,S,y,J);return Fe.type===p||Fe.derived||(Fe=le(w,S,y),Fe.type===p||Fe.derived)?Fe:{type:A,derived:!1,value:b.error.syntax(S[y],"unexpected token")}}var lt=w.__get_max_priority(),Et=w.__get_next_priority(R),qt=y;if(S[y].name==="atom"&&S[y+1]&&(S[y].space||S[y+1].name!=="l_paren")){var $=S[y++],nr=w.__lookup_operator_classes(R,$.value);if(nr&&nr.indexOf("fy")>-1){var St=z(w,S,y,R,J);if(St.type!==A)return $.value==="-"&&!$.space&&b.type.is_number(St.value)?{value:new b.type.Num(-St.value.value,St.value.is_float),len:St.len,type:p}:{value:new b.type.Term($.value,[St.value]),len:St.len,type:p};X=St}else if(nr&&nr.indexOf("fx")>-1){var St=z(w,S,y,Et,J);if(St.type!==A)return{value:new b.type.Term($.value,[St.value]),len:St.len,type:p};X=St}}y=qt;var St=z(w,S,y,Et,J);if(St.type===p){y=St.len;var $=S[y];if(S[y]&&(S[y].name==="atom"&&w.__lookup_operator_classes(R,$.value)||S[y].name==="bar"&&w.__lookup_operator_classes(R,"|"))){var cn=Et,Pr=R,nr=w.__lookup_operator_classes(R,$.value);if(nr.indexOf("xf")>-1)return{value:new b.type.Term($.value,[St.value]),len:++St.len,type:p};if(nr.indexOf("xfx")>-1){var yr=z(w,S,y+1,cn,J);return yr.type===p?{value:new b.type.Term($.value,[St.value,yr.value]),len:yr.len,type:p}:(yr.derived=!0,yr)}else if(nr.indexOf("xfy")>-1){var yr=z(w,S,y+1,Pr,J);return yr.type===p?{value:new b.type.Term($.value,[St.value,yr.value]),len:yr.len,type:p}:(yr.derived=!0,yr)}else if(St.type!==A)for(;;){y=St.len;var $=S[y];if($&&$.name==="atom"&&w.__lookup_operator_classes(R,$.value)){var nr=w.__lookup_operator_classes(R,$.value);if(nr.indexOf("yf")>-1)St={value:new b.type.Term($.value,[St.value]),len:++y,type:p};else if(nr.indexOf("yfx")>-1){var yr=z(w,S,++y,cn,J);if(yr.type===A)return yr.derived=!0,yr;y=yr.len,St={value:new b.type.Term($.value,[St.value,yr.value]),len:y,type:p}}else break}else break}}else X={type:A,value:b.error.syntax(S[St.len-1],"operator expected")};return St}return St}function te(w,S,y,R){if(!S[y]||S[y].name==="atom"&&S[y].raw==="."&&!R&&(S[y].space||!S[y+1]||S[y+1].name!=="l_paren"))return{type:A,derived:!1,value:b.error.syntax(S[y-1],"unfounded token")};var J=S[y],X=[];if(S[y].name==="atom"&&S[y].raw!==","){if(y++,S[y-1].space)return{type:p,len:y,value:new b.type.Term(J.value,X)};if(S[y]&&S[y].name==="l_paren"){if(S[y+1]&&S[y+1].name==="r_paren")return{type:A,derived:!0,value:b.error.syntax(S[y+1],"argument expected")};var $=z(w,S,++y,"999",!0);if($.type===A)return $.derived?$:{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],"argument expected",!S[y])};for(X.push($.value),y=$.len;S[y]&&S[y].name==="atom"&&S[y].value===",";){if($=z(w,S,y+1,"999",!0),$.type===A)return $.derived?$:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};X.push($.value),y=$.len}if(S[y]&&S[y].name==="r_paren")y++;else return{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],", or ) expected",!S[y])}}return{type:p,len:y,value:new b.type.Term(J.value,X)}}return{type:A,derived:!1,value:b.error.syntax(S[y],"term expected")}}function le(w,S,y){if(!S[y])return{type:A,derived:!1,value:b.error.syntax(S[y-1],"[ expected")};if(S[y]&&S[y].name==="l_brace"){var R=z(w,S,++y,"999",!0),J=[R.value],X=void 0;if(R.type===A)return S[y]&&S[y].name==="r_brace"?{type:p,len:y+1,value:new b.type.Term("[]",[])}:{type:A,derived:!0,value:b.error.syntax(S[y],"] expected")};for(y=R.len;S[y]&&S[y].name==="atom"&&S[y].value===",";){if(R=z(w,S,y+1,"999",!0),R.type===A)return R.derived?R:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};J.push(R.value),y=R.len}var $=!1;if(S[y]&&S[y].name==="bar"){if($=!0,R=z(w,S,y+1,"999",!0),R.type===A)return R.derived?R:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};X=R.value,y=R.len}return S[y]&&S[y].name==="r_brace"?{type:p,len:y+1,value:g(J,X)}:{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],$?"] expected":", or | or ] expected",!S[y])}}return{type:A,derived:!1,value:b.error.syntax(S[y],"list expected")}}function ce(w,S,y){var R=S[y].line,J=z(w,S,y,w.__get_max_priority(),!1),X=null,$;if(J.type!==A)if(y=J.len,S[y]&&S[y].name==="atom"&&S[y].raw===".")if(y++,b.type.is_term(J.value)){if(J.value.indicator===":-/2"?(X=new b.type.Rule(J.value.args[0],Ee(J.value.args[1])),$={value:X,len:y,type:p}):J.value.indicator==="-->/2"?(X=he(new b.type.Rule(J.value.args[0],J.value.args[1]),w),X.body=Ee(X.body),$={value:X,len:y,type:b.type.is_rule(X)?p:A}):(X=new b.type.Rule(J.value,null),$={value:X,len:y,type:p}),X){var se=X.singleton_variables();se.length>0&&w.throw_warning(b.warning.singleton(se,X.head.indicator,R))}return $}else return{type:A,value:b.error.syntax(S[y],"callable expected")};else return{type:A,value:b.error.syntax(S[y]?S[y]:S[y-1],". or operator expected")};return J}function ue(w,S,y){y=y||{},y.from=y.from?y.from:"$tau-js",y.reconsult=y.reconsult!==void 0?y.reconsult:!0;var R=new U(w),J={},X;R.new_text(S);var $=0,se=R.get_tokens($);do{if(se===null||!se[$])break;var be=ce(w,se,$);if(be.type===A)return new q("throw",[be.value]);if(be.value.body===null&&be.value.head.indicator==="?-/1"){var Fe=new tt(w.session);Fe.add_goal(be.value.head.args[0]),Fe.answer(function(Et){b.type.is_error(Et)?w.throw_warning(Et.args[0]):(Et===!1||Et===null)&&w.throw_warning(b.warning.failed_goal(be.value.head.args[0],be.len))}),$=be.len;var lt=!0}else if(be.value.body===null&&be.value.head.indicator===":-/1"){var lt=w.run_directive(be.value.head.args[0]);$=be.len,be.value.head.args[0].indicator==="char_conversion/2"&&(se=R.get_tokens($),$=0)}else{X=be.value.head.indicator,y.reconsult!==!1&&J[X]!==!0&&!w.is_multifile_predicate(X)&&(w.session.rules[X]=a(w.session.rules[X]||[],function(qt){return qt.dynamic}),J[X]=!0);var lt=w.add_rule(be.value,y);$=be.len}if(!lt)return lt}while(!0);return!0}function Ce(w,S){var y=new U(w);y.new_text(S);var R=0;do{var J=y.get_tokens(R);if(J===null)break;var X=z(w,J,0,w.__get_max_priority(),!1);if(X.type!==A){var $=X.len,se=$;if(J[$]&&J[$].name==="atom"&&J[$].raw===".")w.add_goal(Ee(X.value));else{var be=J[$];return new q("throw",[b.error.syntax(be||J[$-1],". or operator expected",!be)])}R=X.len+1}else return new q("throw",[X.value])}while(!0);return!0}function he(w,S){w=w.rename(S);var y=S.next_free_variable(),R=De(w.body,y,S);return R.error?R.value:(w.body=R.value,w.head.args=w.head.args.concat([y,R.variable]),w.head=new q(w.head.id,w.head.args),w)}function De(w,S,y){var R;if(b.type.is_term(w)&&w.indicator==="!/0")return{value:w,variable:S,error:!1};if(b.type.is_term(w)&&w.indicator===",/2"){var J=De(w.args[0],S,y);if(J.error)return J;var X=De(w.args[1],J.variable,y);return X.error?X:{value:new q(",",[J.value,X.value]),variable:X.variable,error:!1}}else{if(b.type.is_term(w)&&w.indicator==="{}/1")return{value:w.args[0],variable:S,error:!1};if(b.type.is_empty_list(w))return{value:new q("true",[]),variable:S,error:!1};if(b.type.is_list(w)){R=y.next_free_variable();for(var $=w,se;$.indicator==="./2";)se=$,$=$.args[1];return b.type.is_variable($)?{value:b.error.instantiation("DCG"),variable:S,error:!0}:b.type.is_empty_list($)?(se.args[1]=R,{value:new q("=",[S,w]),variable:R,error:!1}):{value:b.error.type("list",w,"DCG"),variable:S,error:!0}}else return b.type.is_callable(w)?(R=y.next_free_variable(),w.args=w.args.concat([S,R]),w=new q(w.id,w.args),{value:w,variable:R,error:!1}):{value:b.error.type("callable",w,"DCG"),variable:S,error:!0}}}function Ee(w){return b.type.is_variable(w)?new q("call",[w]):b.type.is_term(w)&&[",/2",";/2","->/2"].indexOf(w.indicator)!==-1?new q(w.id,[Ee(w.args[0]),Ee(w.args[1])]):w}function g(w,S){for(var y=S||new b.type.Term("[]",[]),R=w.length-1;R>=0;R--)y=new b.type.Term(".",[w[R],y]);return y}function me(w,S){for(var y=w.length-1;y>=0;y--)w[y]===S&&w.splice(y,1)}function we(w){for(var S={},y=[],R=0;R=0;S--)if(w.charAt(S)==="/")return new q("/",[new q(w.substring(0,S)),new Re(parseInt(w.substring(S+1)),!1)])}function xe(w){this.id=w}function Re(w,S){this.is_float=S!==void 0?S:parseInt(w)!==w,this.value=this.is_float?w:parseInt(w)}var gt=0;function q(w,S,y){this.ref=y||++gt,this.id=w,this.args=S||[],this.indicator=w+"/"+this.args.length}var nt=0;function Ne(w,S,y,R,J,X){this.id=nt++,this.stream=w,this.mode=S,this.alias=y,this.type=R!==void 0?R:"text",this.reposition=J!==void 0?J:!0,this.eof_action=X!==void 0?X:"eof_code",this.position=this.mode==="append"?"end_of_stream":0,this.output=this.mode==="write"||this.mode==="append",this.input=this.mode==="read"}function Te(w){w=w||{},this.links=w}function ke(w,S,y){S=S||new Te,y=y||null,this.goal=w,this.substitution=S,this.parent=y}function Ve(w,S,y){this.head=w,this.body=S,this.dynamic=y||!1}function Se(w){w=w===void 0||w<=0?1e3:w,this.rules={},this.src_predicates={},this.rename=0,this.modules=[],this.thread=new tt(this),this.total_threads=1,this.renamed_variables={},this.public_predicates={},this.multifile_predicates={},this.limit=w,this.streams={user_input:new Ne(typeof El<"u"&&El.exports?nodejs_user_input:tau_user_input,"read","user_input","text",!1,"reset"),user_output:new Ne(typeof El<"u"&&El.exports?nodejs_user_output:tau_user_output,"write","user_output","text",!1,"eof_code")},this.file_system=typeof El<"u"&&El.exports?nodejs_file_system:tau_file_system,this.standard_input=this.streams.user_input,this.standard_output=this.streams.user_output,this.current_input=this.streams.user_input,this.current_output=this.streams.user_output,this.format_success=function(S){return S.substitution},this.format_error=function(S){return S.goal},this.flag={bounded:b.flag.bounded.value,max_integer:b.flag.max_integer.value,min_integer:b.flag.min_integer.value,integer_rounding_function:b.flag.integer_rounding_function.value,char_conversion:b.flag.char_conversion.value,debug:b.flag.debug.value,max_arity:b.flag.max_arity.value,unknown:b.flag.unknown.value,double_quotes:b.flag.double_quotes.value,occurs_check:b.flag.occurs_check.value,dialect:b.flag.dialect.value,version_data:b.flag.version_data.value,nodejs:b.flag.nodejs.value},this.__loaded_modules=[],this.__char_conversion={},this.__operators={1200:{":-":["fx","xfx"],"-->":["xfx"],"?-":["fx"]},1100:{";":["xfy"]},1050:{"->":["xfy"]},1e3:{",":["xfy"]},900:{"\\+":["fy"]},700:{"=":["xfx"],"\\=":["xfx"],"==":["xfx"],"\\==":["xfx"],"@<":["xfx"],"@=<":["xfx"],"@>":["xfx"],"@>=":["xfx"],"=..":["xfx"],is:["xfx"],"=:=":["xfx"],"=\\=":["xfx"],"<":["xfx"],"=<":["xfx"],">":["xfx"],">=":["xfx"]},600:{":":["xfy"]},500:{"+":["yfx"],"-":["yfx"],"/\\":["yfx"],"\\/":["yfx"]},400:{"*":["yfx"],"/":["yfx"],"//":["yfx"],rem:["yfx"],mod:["yfx"],"<<":["yfx"],">>":["yfx"]},200:{"**":["xfx"],"^":["xfy"],"-":["fy"],"+":["fy"],"\\":["fy"]}}}function tt(w){this.epoch=Date.now(),this.session=w,this.session.total_threads++,this.total_steps=0,this.cpu_time=0,this.cpu_time_last=0,this.points=[],this.debugger=!1,this.debugger_states=[],this.level="top_level/0",this.__calls=[],this.current_limit=this.session.limit,this.warnings=[]}function He(w,S,y){this.id=w,this.rules=S,this.exports=y,b.module[w]=this}He.prototype.exports_predicate=function(w){return this.exports.indexOf(w)!==-1},xe.prototype.unify=function(w,S){if(S&&e(w.variables(),this.id)!==-1&&!b.type.is_variable(w))return null;var y={};return y[this.id]=w,new Te(y)},Re.prototype.unify=function(w,S){return b.type.is_number(w)&&this.value===w.value&&this.is_float===w.is_float?new Te:null},q.prototype.unify=function(w,S){if(b.type.is_term(w)&&this.indicator===w.indicator){for(var y=new Te,R=0;R=0){var R=this.args[0].value,J=Math.floor(R/26),X=R%26;return"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[X]+(J!==0?J:"")}switch(this.indicator){case"[]/0":case"{}/0":case"!/0":return this.id;case"{}/1":return"{"+this.args[0].toString(w)+"}";case"./2":for(var $="["+this.args[0].toString(w),se=this.args[1];se.indicator==="./2";)$+=", "+se.args[0].toString(w),se=se.args[1];return se.indicator!=="[]/0"&&($+="|"+se.toString(w)),$+="]",$;case",/2":return"("+this.args[0].toString(w)+", "+this.args[1].toString(w)+")";default:var be=this.id,Fe=w.session?w.session.lookup_operator(this.id,this.args.length):null;if(w.session===void 0||w.ignore_ops||Fe===null)return w.quoted&&!/^(!|,|;|[a-z][0-9a-zA-Z_]*)$/.test(be)&&be!=="{}"&&be!=="[]"&&(be="'"+x(be)+"'"),be+(this.args.length?"("+o(this.args,function(nr){return nr.toString(w)}).join(", ")+")":"");var lt=Fe.priority>S.priority||Fe.priority===S.priority&&(Fe.class==="xfy"&&this.indicator!==S.indicator||Fe.class==="yfx"&&this.indicator!==S.indicator||this.indicator===S.indicator&&Fe.class==="yfx"&&y==="right"||this.indicator===S.indicator&&Fe.class==="xfy"&&y==="left");Fe.indicator=this.indicator;var Et=lt?"(":"",qt=lt?")":"";return this.args.length===0?"("+this.id+")":["fy","fx"].indexOf(Fe.class)!==-1?Et+be+" "+this.args[0].toString(w,Fe)+qt:["yf","xf"].indexOf(Fe.class)!==-1?Et+this.args[0].toString(w,Fe)+" "+be+qt:Et+this.args[0].toString(w,Fe,"left")+" "+this.id+" "+this.args[1].toString(w,Fe,"right")+qt}},Ne.prototype.toString=function(w){return"("+this.id+")"},Te.prototype.toString=function(w){var S="{";for(var y in this.links)this.links.hasOwnProperty(y)&&(S!=="{"&&(S+=", "),S+=y+"/"+this.links[y].toString(w));return S+="}",S},ke.prototype.toString=function(w){return this.goal===null?"<"+this.substitution.toString(w)+">":"<"+this.goal.toString(w)+", "+this.substitution.toString(w)+">"},Ve.prototype.toString=function(w){return this.body?this.head.toString(w)+" :- "+this.body.toString(w)+".":this.head.toString(w)+"."},Se.prototype.toString=function(w){for(var S="",y=0;y=0;J--)R=new q(".",[S[J],R]);return R}return new q(this.id,o(this.args,function(X){return X.apply(w)}),this.ref)},Ne.prototype.apply=function(w){return this},Ve.prototype.apply=function(w){return new Ve(this.head.apply(w),this.body!==null?this.body.apply(w):null)},Te.prototype.apply=function(w){var S,y={};for(S in this.links)this.links.hasOwnProperty(S)&&(y[S]=this.links[S].apply(w));return new Te(y)},q.prototype.select=function(){for(var w=this;w.indicator===",/2";)w=w.args[0];return w},q.prototype.replace=function(w){return this.indicator===",/2"?this.args[0].indicator===",/2"?new q(",",[this.args[0].replace(w),this.args[1]]):w===null?this.args[1]:new q(",",[w,this.args[1]]):w},q.prototype.search=function(w){if(b.type.is_term(w)&&w.ref!==void 0&&this.ref===w.ref)return!0;for(var S=0;SS&&R0&&(S=this.head_point().substitution.domain());e(S,b.format_variable(this.session.rename))!==-1;)this.session.rename++;if(w.id==="_")return new xe(b.format_variable(this.session.rename));this.session.renamed_variables[w.id]=b.format_variable(this.session.rename)}return new xe(this.session.renamed_variables[w.id])},Se.prototype.next_free_variable=function(){return this.thread.next_free_variable()},tt.prototype.next_free_variable=function(){this.session.rename++;var w=[];for(this.points.length>0&&(w=this.head_point().substitution.domain());e(w,b.format_variable(this.session.rename))!==-1;)this.session.rename++;return new xe(b.format_variable(this.session.rename))},Se.prototype.is_public_predicate=function(w){return!this.public_predicates.hasOwnProperty(w)||this.public_predicates[w]===!0},tt.prototype.is_public_predicate=function(w){return this.session.is_public_predicate(w)},Se.prototype.is_multifile_predicate=function(w){return this.multifile_predicates.hasOwnProperty(w)&&this.multifile_predicates[w]===!0},tt.prototype.is_multifile_predicate=function(w){return this.session.is_multifile_predicate(w)},Se.prototype.prepend=function(w){return this.thread.prepend(w)},tt.prototype.prepend=function(w){for(var S=w.length-1;S>=0;S--)this.points.push(w[S])},Se.prototype.success=function(w,S){return this.thread.success(w,S)},tt.prototype.success=function(w,y){var y=typeof y>"u"?w:y;this.prepend([new ke(w.goal.replace(null),w.substitution,y)])},Se.prototype.throw_error=function(w){return this.thread.throw_error(w)},tt.prototype.throw_error=function(w){this.prepend([new ke(new q("throw",[w]),new Te,null,null)])},Se.prototype.step_rule=function(w,S){return this.thread.step_rule(w,S)},tt.prototype.step_rule=function(w,S){var y=S.indicator;if(w==="user"&&(w=null),w===null&&this.session.rules.hasOwnProperty(y))return this.session.rules[y];for(var R=w===null?this.session.modules:e(this.session.modules,w)===-1?[]:[w],J=0;J1)&&this.again()},Se.prototype.answers=function(w,S,y){return this.thread.answers(w,S,y)},tt.prototype.answers=function(w,S,y){var R=S||1e3,J=this;if(S<=0){y&&y();return}this.answer(function(X){w(X),X!==!1?setTimeout(function(){J.answers(w,S-1,y)},1):y&&y()})},Se.prototype.again=function(w){return this.thread.again(w)},tt.prototype.again=function(w){for(var S,y=Date.now();this.__calls.length>0;){for(this.warnings=[],w!==!1&&(this.current_limit=this.session.limit);this.current_limit>0&&this.points.length>0&&this.head_point().goal!==null&&!b.type.is_error(this.head_point().goal);)if(this.current_limit--,this.step()===!0)return;var R=Date.now();this.cpu_time_last=R-y,this.cpu_time+=this.cpu_time_last;var J=this.__calls.shift();this.current_limit<=0?J(null):this.points.length===0?J(!1):b.type.is_error(this.head_point().goal)?(S=this.session.format_error(this.points.pop()),this.points=[],J(S)):(this.debugger&&this.debugger_states.push(this.head_point()),S=this.session.format_success(this.points.pop()),J(S))}},Se.prototype.unfold=function(w){if(w.body===null)return!1;var S=w.head,y=w.body,R=y.select(),J=new tt(this),X=[];J.add_goal(R),J.step();for(var $=J.points.length-1;$>=0;$--){var se=J.points[$],be=S.apply(se.substitution),Fe=y.replace(se.goal);Fe!==null&&(Fe=Fe.apply(se.substitution)),X.push(new Ve(be,Fe))}var lt=this.rules[S.indicator],Et=e(lt,w);return X.length>0&&Et!==-1?(lt.splice.apply(lt,[Et,1].concat(X)),!0):!1},tt.prototype.unfold=function(w){return this.session.unfold(w)},xe.prototype.interpret=function(w){return b.error.instantiation(w.level)},Re.prototype.interpret=function(w){return this},q.prototype.interpret=function(w){return b.type.is_unitary_list(this)?this.args[0].interpret(w):b.operate(w,this)},xe.prototype.compare=function(w){return this.idw.id?1:0},Re.prototype.compare=function(w){if(this.value===w.value&&this.is_float===w.is_float)return 0;if(this.valuew.value)return 1},q.prototype.compare=function(w){if(this.args.lengthw.args.length||this.args.length===w.args.length&&this.id>w.id)return 1;for(var S=0;SR)return 1;if(w.constructor===Re){if(w.is_float&&S.is_float)return 0;if(w.is_float)return-1;if(S.is_float)return 1}return 0},is_substitution:function(w){return w instanceof Te},is_state:function(w){return w instanceof ke},is_rule:function(w){return w instanceof Ve},is_variable:function(w){return w instanceof xe},is_stream:function(w){return w instanceof Ne},is_anonymous_var:function(w){return w instanceof xe&&w.id==="_"},is_callable:function(w){return w instanceof q},is_number:function(w){return w instanceof Re},is_integer:function(w){return w instanceof Re&&!w.is_float},is_float:function(w){return w instanceof Re&&w.is_float},is_term:function(w){return w instanceof q},is_atom:function(w){return w instanceof q&&w.args.length===0},is_ground:function(w){if(w instanceof xe)return!1;if(w instanceof q){for(var S=0;S0},is_list:function(w){return w instanceof q&&(w.indicator==="[]/0"||w.indicator==="./2")},is_empty_list:function(w){return w instanceof q&&w.indicator==="[]/0"},is_non_empty_list:function(w){return w instanceof q&&w.indicator==="./2"},is_fully_list:function(w){for(;w instanceof q&&w.indicator==="./2";)w=w.args[1];return w instanceof xe||w instanceof q&&w.indicator==="[]/0"},is_instantiated_list:function(w){for(;w instanceof q&&w.indicator==="./2";)w=w.args[1];return w instanceof q&&w.indicator==="[]/0"},is_unitary_list:function(w){return w instanceof q&&w.indicator==="./2"&&w.args[1]instanceof q&&w.args[1].indicator==="[]/0"},is_character:function(w){return w instanceof q&&(w.id.length===1||w.id.length>0&&w.id.length<=2&&n(w.id,0)>=65536)},is_character_code:function(w){return w instanceof Re&&!w.is_float&&w.value>=0&&w.value<=1114111},is_byte:function(w){return w instanceof Re&&!w.is_float&&w.value>=0&&w.value<=255},is_operator:function(w){return w instanceof q&&b.arithmetic.evaluation[w.indicator]},is_directive:function(w){return w instanceof q&&b.directive[w.indicator]!==void 0},is_builtin:function(w){return w instanceof q&&b.predicate[w.indicator]!==void 0},is_error:function(w){return w instanceof q&&w.indicator==="throw/1"},is_predicate_indicator:function(w){return w instanceof q&&w.indicator==="//2"&&w.args[0]instanceof q&&w.args[0].args.length===0&&w.args[1]instanceof Re&&w.args[1].is_float===!1},is_flag:function(w){return w instanceof q&&w.args.length===0&&b.flag[w.id]!==void 0},is_value_flag:function(w,S){if(!b.type.is_flag(w))return!1;for(var y in b.flag[w.id].allowed)if(b.flag[w.id].allowed.hasOwnProperty(y)&&b.flag[w.id].allowed[y].equals(S))return!0;return!1},is_io_mode:function(w){return b.type.is_atom(w)&&["read","write","append"].indexOf(w.id)!==-1},is_stream_option:function(w){return b.type.is_term(w)&&(w.indicator==="alias/1"&&b.type.is_atom(w.args[0])||w.indicator==="reposition/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="type/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="text"||w.args[0].id==="binary")||w.indicator==="eof_action/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="error"||w.args[0].id==="eof_code"||w.args[0].id==="reset"))},is_stream_position:function(w){return b.type.is_integer(w)&&w.value>=0||b.type.is_atom(w)&&(w.id==="end_of_stream"||w.id==="past_end_of_stream")},is_stream_property:function(w){return b.type.is_term(w)&&(w.indicator==="input/0"||w.indicator==="output/0"||w.indicator==="alias/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0]))||w.indicator==="file_name/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0]))||w.indicator==="position/1"&&(b.type.is_variable(w.args[0])||b.type.is_stream_position(w.args[0]))||w.indicator==="reposition/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false"))||w.indicator==="type/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="text"||w.args[0].id==="binary"))||w.indicator==="mode/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="read"||w.args[0].id==="write"||w.args[0].id==="append"))||w.indicator==="eof_action/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="error"||w.args[0].id==="eof_code"||w.args[0].id==="reset"))||w.indicator==="end_of_stream/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="at"||w.args[0].id==="past"||w.args[0].id==="not")))},is_streamable:function(w){return w.__proto__.stream!==void 0},is_read_option:function(w){return b.type.is_term(w)&&["variables/1","variable_names/1","singletons/1"].indexOf(w.indicator)!==-1},is_write_option:function(w){return b.type.is_term(w)&&(w.indicator==="quoted/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="ignore_ops/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="numbervars/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false"))},is_close_option:function(w){return b.type.is_term(w)&&w.indicator==="force/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")},is_modifiable_flag:function(w){return b.type.is_flag(w)&&b.flag[w.id].changeable},is_module:function(w){return w instanceof q&&w.indicator==="library/1"&&w.args[0]instanceof q&&w.args[0].args.length===0&&b.module[w.args[0].id]!==void 0}},arithmetic:{evaluation:{"e/0":{type_args:null,type_result:!0,fn:function(w){return Math.E}},"pi/0":{type_args:null,type_result:!0,fn:function(w){return Math.PI}},"tau/0":{type_args:null,type_result:!0,fn:function(w){return 2*Math.PI}},"epsilon/0":{type_args:null,type_result:!0,fn:function(w){return Number.EPSILON}},"+/1":{type_args:null,type_result:null,fn:function(w,S){return w}},"-/1":{type_args:null,type_result:null,fn:function(w,S){return-w}},"\\/1":{type_args:!1,type_result:!1,fn:function(w,S){return~w}},"abs/1":{type_args:null,type_result:null,fn:function(w,S){return Math.abs(w)}},"sign/1":{type_args:null,type_result:null,fn:function(w,S){return Math.sign(w)}},"float_integer_part/1":{type_args:!0,type_result:!1,fn:function(w,S){return parseInt(w)}},"float_fractional_part/1":{type_args:!0,type_result:!0,fn:function(w,S){return w-parseInt(w)}},"float/1":{type_args:null,type_result:!0,fn:function(w,S){return parseFloat(w)}},"floor/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.floor(w)}},"truncate/1":{type_args:!0,type_result:!1,fn:function(w,S){return parseInt(w)}},"round/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.round(w)}},"ceiling/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.ceil(w)}},"sin/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.sin(w)}},"cos/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.cos(w)}},"tan/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.tan(w)}},"asin/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.asin(w)}},"acos/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.acos(w)}},"atan/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.atan(w)}},"atan2/2":{type_args:null,type_result:!0,fn:function(w,S,y){return Math.atan2(w,S)}},"exp/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.exp(w)}},"sqrt/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.sqrt(w)}},"log/1":{type_args:null,type_result:!0,fn:function(w,S){return w>0?Math.log(w):b.error.evaluation("undefined",S.__call_indicator)}},"+/2":{type_args:null,type_result:null,fn:function(w,S,y){return w+S}},"-/2":{type_args:null,type_result:null,fn:function(w,S,y){return w-S}},"*/2":{type_args:null,type_result:null,fn:function(w,S,y){return w*S}},"//2":{type_args:null,type_result:!0,fn:function(w,S,y){return S?w/S:b.error.evaluation("zero_division",y.__call_indicator)}},"///2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?parseInt(w/S):b.error.evaluation("zero_division",y.__call_indicator)}},"**/2":{type_args:null,type_result:!0,fn:function(w,S,y){return Math.pow(w,S)}},"^/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.pow(w,S)}},"<>/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w>>S}},"/\\/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w&S}},"\\//2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w|S}},"xor/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w^S}},"rem/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?w%S:b.error.evaluation("zero_division",y.__call_indicator)}},"mod/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?w-parseInt(w/S)*S:b.error.evaluation("zero_division",y.__call_indicator)}},"max/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.max(w,S)}},"min/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.min(w,S)}}}},directive:{"dynamic/1":function(w,S){var y=S.args[0];if(b.type.is_variable(y))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_compound(y)||y.indicator!=="//2")w.throw_error(b.error.type("predicate_indicator",y,S.indicator));else if(b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1]))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_atom(y.args[0]))w.throw_error(b.error.type("atom",y.args[0],S.indicator));else if(!b.type.is_integer(y.args[1]))w.throw_error(b.error.type("integer",y.args[1],S.indicator));else{var R=S.args[0].args[0].id+"/"+S.args[0].args[1].value;w.session.public_predicates[R]=!0,w.session.rules[R]||(w.session.rules[R]=[])}},"multifile/1":function(w,S){var y=S.args[0];b.type.is_variable(y)?w.throw_error(b.error.instantiation(S.indicator)):!b.type.is_compound(y)||y.indicator!=="//2"?w.throw_error(b.error.type("predicate_indicator",y,S.indicator)):b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1])?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_atom(y.args[0])?b.type.is_integer(y.args[1])?w.session.multifile_predicates[S.args[0].args[0].id+"/"+S.args[0].args[1].value]=!0:w.throw_error(b.error.type("integer",y.args[1],S.indicator)):w.throw_error(b.error.type("atom",y.args[0],S.indicator))},"set_prolog_flag/2":function(w,S){var y=S.args[0],R=S.args[1];b.type.is_variable(y)||b.type.is_variable(R)?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_atom(y)?b.type.is_flag(y)?b.type.is_value_flag(y,R)?b.type.is_modifiable_flag(y)?w.session.flag[y.id]=R:w.throw_error(b.error.permission("modify","flag",y)):w.throw_error(b.error.domain("flag_value",new q("+",[y,R]),S.indicator)):w.throw_error(b.error.domain("prolog_flag",y,S.indicator)):w.throw_error(b.error.type("atom",y,S.indicator))},"use_module/1":function(w,S){var y=S.args[0];if(b.type.is_variable(y))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_term(y))w.throw_error(b.error.type("term",y,S.indicator));else if(b.type.is_module(y)){var R=y.args[0].id;e(w.session.modules,R)===-1&&w.session.modules.push(R)}},"char_conversion/2":function(w,S){var y=S.args[0],R=S.args[1];b.type.is_variable(y)||b.type.is_variable(R)?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_character(y)?b.type.is_character(R)?y.id===R.id?delete w.session.__char_conversion[y.id]:w.session.__char_conversion[y.id]=R.id:w.throw_error(b.error.type("character",R,S.indicator)):w.throw_error(b.error.type("character",y,S.indicator))},"op/3":function(w,S){var y=S.args[0],R=S.args[1],J=S.args[2];if(b.type.is_variable(y)||b.type.is_variable(R)||b.type.is_variable(J))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_integer(y))w.throw_error(b.error.type("integer",y,S.indicator));else if(!b.type.is_atom(R))w.throw_error(b.error.type("atom",R,S.indicator));else if(!b.type.is_atom(J))w.throw_error(b.error.type("atom",J,S.indicator));else if(y.value<0||y.value>1200)w.throw_error(b.error.domain("operator_priority",y,S.indicator));else if(J.id===",")w.throw_error(b.error.permission("modify","operator",J,S.indicator));else if(J.id==="|"&&(y.value<1001||R.id.length!==3))w.throw_error(b.error.permission("modify","operator",J,S.indicator));else if(["fy","fx","yf","xf","xfx","yfx","xfy"].indexOf(R.id)===-1)w.throw_error(b.error.domain("operator_specifier",R,S.indicator));else{var X={prefix:null,infix:null,postfix:null};for(var $ in w.session.__operators)if(w.session.__operators.hasOwnProperty($)){var se=w.session.__operators[$][J.id];se&&(e(se,"fx")!==-1&&(X.prefix={priority:$,type:"fx"}),e(se,"fy")!==-1&&(X.prefix={priority:$,type:"fy"}),e(se,"xf")!==-1&&(X.postfix={priority:$,type:"xf"}),e(se,"yf")!==-1&&(X.postfix={priority:$,type:"yf"}),e(se,"xfx")!==-1&&(X.infix={priority:$,type:"xfx"}),e(se,"xfy")!==-1&&(X.infix={priority:$,type:"xfy"}),e(se,"yfx")!==-1&&(X.infix={priority:$,type:"yfx"}))}var be;switch(R.id){case"fy":case"fx":be="prefix";break;case"yf":case"xf":be="postfix";break;default:be="infix";break}if(((X.prefix&&be==="prefix"||X.postfix&&be==="postfix"||X.infix&&be==="infix")&&X[be].type!==R.id||X.infix&&be==="postfix"||X.postfix&&be==="infix")&&y.value!==0)w.throw_error(b.error.permission("create","operator",J,S.indicator));else return X[be]&&(me(w.session.__operators[X[be].priority][J.id],R.id),w.session.__operators[X[be].priority][J.id].length===0&&delete w.session.__operators[X[be].priority][J.id]),y.value>0&&(w.session.__operators[y.value]||(w.session.__operators[y.value.toString()]={}),w.session.__operators[y.value][J.id]||(w.session.__operators[y.value][J.id]=[]),w.session.__operators[y.value][J.id].push(R.id)),!0}}},predicate:{"op/3":function(w,S,y){b.directive["op/3"](w,y)&&w.success(S)},"current_op/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=[];for(var se in w.session.__operators)for(var be in w.session.__operators[se])for(var Fe=0;Fe/2"){var R=w.points,J=w.session.format_success,X=w.session.format_error;w.session.format_success=function(Fe){return Fe.substitution},w.session.format_error=function(Fe){return Fe.goal},w.points=[new ke(y.args[0].args[0],S.substitution,S)];var $=function(Fe){w.points=R,w.session.format_success=J,w.session.format_error=X,Fe===!1?w.prepend([new ke(S.goal.replace(y.args[1]),S.substitution,S)]):b.type.is_error(Fe)?w.throw_error(Fe.args[0]):Fe===null?(w.prepend([S]),w.__calls.shift()(null)):w.prepend([new ke(S.goal.replace(y.args[0].args[1]).apply(Fe),S.substitution.apply(Fe),S)])};w.__calls.unshift($)}else{var se=new ke(S.goal.replace(y.args[0]),S.substitution,S),be=new ke(S.goal.replace(y.args[1]),S.substitution,S);w.prepend([se,be])}},"!/0":function(w,S,y){var R,J,X=[];for(R=S,J=null;R.parent!==null&&R.parent.goal.search(y);)if(J=R,R=R.parent,R.goal!==null){var $=R.goal.select();if($&&$.id==="call"&&$.search(y)){R=J;break}}for(var se=w.points.length-1;se>=0;se--){for(var be=w.points[se],Fe=be.parent;Fe!==null&&Fe!==R.parent;)Fe=Fe.parent;Fe===null&&Fe!==R.parent&&X.push(be)}w.points=X.reverse(),w.success(S)},"\\+/1":function(w,S,y){var R=y.args[0];b.type.is_variable(R)?w.throw_error(b.error.instantiation(w.level)):b.type.is_callable(R)?w.prepend([new ke(S.goal.replace(new q(",",[new q(",",[new q("call",[R]),new q("!",[])]),new q("fail",[])])),S.substitution,S),new ke(S.goal.replace(null),S.substitution,S)]):w.throw_error(b.error.type("callable",R,w.level))},"->/2":function(w,S,y){var R=S.goal.replace(new q(",",[y.args[0],new q(",",[new q("!"),y.args[1]])]));w.prepend([new ke(R,S.substitution,S)])},"fail/0":function(w,S,y){},"false/0":function(w,S,y){},"true/0":function(w,S,y){w.success(S)},"call/1":ie(1),"call/2":ie(2),"call/3":ie(3),"call/4":ie(4),"call/5":ie(5),"call/6":ie(6),"call/7":ie(7),"call/8":ie(8),"once/1":function(w,S,y){var R=y.args[0];w.prepend([new ke(S.goal.replace(new q(",",[new q("call",[R]),new q("!",[])])),S.substitution,S)])},"forall/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q("\\+",[new q(",",[new q("call",[R]),new q("\\+",[new q("call",[J])])])])),S.substitution,S)])},"repeat/0":function(w,S,y){w.prepend([new ke(S.goal.replace(null),S.substitution,S),S])},"throw/1":function(w,S,y){b.type.is_variable(y.args[0])?w.throw_error(b.error.instantiation(w.level)):w.throw_error(y.args[0])},"catch/3":function(w,S,y){var R=w.points;w.points=[],w.prepend([new ke(y.args[0],S.substitution,S)]);var J=w.session.format_success,X=w.session.format_error;w.session.format_success=function(se){return se.substitution},w.session.format_error=function(se){return se.goal};var $=function(se){var be=w.points;if(w.points=R,w.session.format_success=J,w.session.format_error=X,b.type.is_error(se)){for(var Fe=[],lt=w.points.length-1;lt>=0;lt--){for(var nr=w.points[lt],Et=nr.parent;Et!==null&&Et!==S.parent;)Et=Et.parent;Et===null&&Et!==S.parent&&Fe.push(nr)}w.points=Fe;var qt=w.get_flag("occurs_check").indicator==="true/0",nr=new ke,St=b.unify(se.args[0],y.args[1],qt);St!==null?(nr.substitution=S.substitution.apply(St),nr.goal=S.goal.replace(y.args[2]).apply(St),nr.parent=S,w.prepend([nr])):w.throw_error(se.args[0])}else if(se!==!1){for(var cn=se===null?[]:[new ke(S.goal.apply(se).replace(null),S.substitution.apply(se),S)],Pr=[],lt=be.length-1;lt>=0;lt--){Pr.push(be[lt]);var yr=be[lt].goal!==null?be[lt].goal.select():null;if(b.type.is_term(yr)&&yr.indicator==="!/0")break}var Rr=o(Pr,function(Xr){return Xr.goal===null&&(Xr.goal=new q("true",[])),Xr=new ke(S.goal.replace(new q("catch",[Xr.goal,y.args[1],y.args[2]])),S.substitution.apply(Xr.substitution),Xr.parent),Xr.exclude=y.args[0].variables(),Xr}).reverse();w.prepend(Rr),w.prepend(cn),se===null&&(this.current_limit=0,w.__calls.shift()(null))}};w.__calls.unshift($)},"=/2":function(w,S,y){var R=w.get_flag("occurs_check").indicator==="true/0",J=new ke,X=b.unify(y.args[0],y.args[1],R);X!==null&&(J.goal=S.goal.apply(X).replace(null),J.substitution=S.substitution.apply(X),J.parent=S,w.prepend([J]))},"unify_with_occurs_check/2":function(w,S,y){var R=new ke,J=b.unify(y.args[0],y.args[1],!0);J!==null&&(R.goal=S.goal.apply(J).replace(null),R.substitution=S.substitution.apply(J),R.parent=S,w.prepend([R]))},"\\=/2":function(w,S,y){var R=w.get_flag("occurs_check").indicator==="true/0",J=b.unify(y.args[0],y.args[1],R);J===null&&w.success(S)},"subsumes_term/2":function(w,S,y){var R=w.get_flag("occurs_check").indicator==="true/0",J=b.unify(y.args[1],y.args[0],R);J!==null&&y.args[1].apply(J).equals(y.args[1])&&w.success(S)},"findall/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(J))w.throw_error(b.error.type("callable",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=w.next_free_variable(),se=new q(",",[J,new q("=",[$,R])]),be=w.points,Fe=w.session.limit,lt=w.session.format_success;w.session.format_success=function(nr){return nr.substitution},w.add_goal(se,!0,S);var Et=[],qt=function(nr){if(nr!==!1&&nr!==null&&!b.type.is_error(nr))w.__calls.unshift(qt),Et.push(nr.links[$.id]),w.session.limit=w.current_limit;else if(w.points=be,w.session.limit=Fe,w.session.format_success=lt,b.type.is_error(nr))w.throw_error(nr.args[0]);else if(w.current_limit>0){for(var St=new q("[]"),cn=Et.length-1;cn>=0;cn--)St=new q(".",[Et[cn],St]);w.prepend([new ke(S.goal.replace(new q("=",[X,St])),S.substitution,S)])}};w.__calls.unshift(qt)}},"bagof/3":function(w,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(X))w.throw_error(b.error.type("callable",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_list($))w.throw_error(b.error.type("list",$,y.indicator));else{var se=w.next_free_variable(),be;X.indicator==="^/2"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Fe=X.variables().filter(function(Rr){return e(be,Rr)===-1}),lt=new q("[]"),Et=Fe.length-1;Et>=0;Et--)lt=new q(".",[new xe(Fe[Et]),lt]);var qt=new q(",",[X,new q("=",[se,new q(",",[lt,J])])]),nr=w.points,St=w.session.limit,cn=w.session.format_success;w.session.format_success=function(Rr){return Rr.substitution},w.add_goal(qt,!0,S);var Pr=[],yr=function(Rr){if(Rr!==!1&&Rr!==null&&!b.type.is_error(Rr)){w.__calls.unshift(yr);var Xr=!1,$n=Rr.links[se.id].args[0],Xs=Rr.links[se.id].args[1];for(var Hi in Pr)if(Pr.hasOwnProperty(Hi)){var Qs=Pr[Hi];if(Qs.variables.equals($n)){Qs.answers.push(Xs),Xr=!0;break}}Xr||Pr.push({variables:$n,answers:[Xs]}),w.session.limit=w.current_limit}else if(w.points=nr,w.session.limit=St,w.session.format_success=cn,b.type.is_error(Rr))w.throw_error(Rr.args[0]);else if(w.current_limit>0){for(var Zs=[],xi=0;xi=0;$s--)Fs=new q(".",[Rr[$s],Fs]);Zs.push(new ke(S.goal.replace(new q(",",[new q("=",[lt,Pr[xi].variables]),new q("=",[$,Fs])])),S.substitution,S))}w.prepend(Zs)}};w.__calls.unshift(yr)}},"setof/3":function(w,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(X))w.throw_error(b.error.type("callable",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_list($))w.throw_error(b.error.type("list",$,y.indicator));else{var se=w.next_free_variable(),be;X.indicator==="^/2"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Fe=X.variables().filter(function(Rr){return e(be,Rr)===-1}),lt=new q("[]"),Et=Fe.length-1;Et>=0;Et--)lt=new q(".",[new xe(Fe[Et]),lt]);var qt=new q(",",[X,new q("=",[se,new q(",",[lt,J])])]),nr=w.points,St=w.session.limit,cn=w.session.format_success;w.session.format_success=function(Rr){return Rr.substitution},w.add_goal(qt,!0,S);var Pr=[],yr=function(Rr){if(Rr!==!1&&Rr!==null&&!b.type.is_error(Rr)){w.__calls.unshift(yr);var Xr=!1,$n=Rr.links[se.id].args[0],Xs=Rr.links[se.id].args[1];for(var Hi in Pr)if(Pr.hasOwnProperty(Hi)){var Qs=Pr[Hi];if(Qs.variables.equals($n)){Qs.answers.push(Xs),Xr=!0;break}}Xr||Pr.push({variables:$n,answers:[Xs]}),w.session.limit=w.current_limit}else if(w.points=nr,w.session.limit=St,w.session.format_success=cn,b.type.is_error(Rr))w.throw_error(Rr.args[0]);else if(w.current_limit>0){for(var Zs=[],xi=0;xi=0;$s--)Fs=new q(".",[Rr[$s],Fs]);Zs.push(new ke(S.goal.replace(new q(",",[new q("=",[lt,Pr[xi].variables]),new q("=",[$,Fs])])),S.substitution,S))}w.prepend(Zs)}};w.__calls.unshift(yr)}},"functor/3":function(w,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(J)&&(b.type.is_variable(X)||b.type.is_variable($)))w.throw_error(b.error.instantiation("functor/3"));else if(!b.type.is_variable($)&&!b.type.is_integer($))w.throw_error(b.error.type("integer",y.args[2],"functor/3"));else if(!b.type.is_variable(X)&&!b.type.is_atomic(X))w.throw_error(b.error.type("atomic",y.args[1],"functor/3"));else if(b.type.is_integer(X)&&b.type.is_integer($)&&$.value!==0)w.throw_error(b.error.type("atom",y.args[1],"functor/3"));else if(b.type.is_variable(J)){if(y.args[2].value>=0){for(var se=[],be=0;be<$.value;be++)se.push(w.next_free_variable());var Fe=b.type.is_integer(X)?X:new q(X.id,se);w.prepend([new ke(S.goal.replace(new q("=",[J,Fe])),S.substitution,S)])}}else{var lt=b.type.is_integer(J)?J:new q(J.id,[]),Et=b.type.is_integer(J)?new Re(0,!1):new Re(J.args.length,!1),qt=new q(",",[new q("=",[lt,X]),new q("=",[Et,$])]);w.prepend([new ke(S.goal.replace(qt),S.substitution,S)])}},"arg/3":function(w,S,y){if(b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1]))w.throw_error(b.error.instantiation(y.indicator));else if(y.args[0].value<0)w.throw_error(b.error.domain("not_less_than_zero",y.args[0],y.indicator));else if(!b.type.is_compound(y.args[1]))w.throw_error(b.error.type("compound",y.args[1],y.indicator));else{var R=y.args[0].value;if(R>0&&R<=y.args[1].args.length){var J=new q("=",[y.args[1].args[R-1],y.args[2]]);w.prepend([new ke(S.goal.replace(J),S.substitution,S)])}}},"=../2":function(w,S,y){var R;if(b.type.is_variable(y.args[0])&&(b.type.is_variable(y.args[1])||b.type.is_non_empty_list(y.args[1])&&b.type.is_variable(y.args[1].args[0])))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_fully_list(y.args[1]))w.throw_error(b.error.type("list",y.args[1],y.indicator));else if(b.type.is_variable(y.args[0])){if(!b.type.is_variable(y.args[1])){var X=[];for(R=y.args[1].args[1];R.indicator==="./2";)X.push(R.args[0]),R=R.args[1];b.type.is_variable(y.args[0])&&b.type.is_variable(R)?w.throw_error(b.error.instantiation(y.indicator)):X.length===0&&b.type.is_compound(y.args[1].args[0])?w.throw_error(b.error.type("atomic",y.args[1].args[0],y.indicator)):X.length>0&&(b.type.is_compound(y.args[1].args[0])||b.type.is_number(y.args[1].args[0]))?w.throw_error(b.error.type("atom",y.args[1].args[0],y.indicator)):X.length===0?w.prepend([new ke(S.goal.replace(new q("=",[y.args[1].args[0],y.args[0]],S)),S.substitution,S)]):w.prepend([new ke(S.goal.replace(new q("=",[new q(y.args[1].args[0].id,X),y.args[0]])),S.substitution,S)])}}else{if(b.type.is_atomic(y.args[0]))R=new q(".",[y.args[0],new q("[]")]);else{R=new q("[]");for(var J=y.args[0].args.length-1;J>=0;J--)R=new q(".",[y.args[0].args[J],R]);R=new q(".",[new q(y.args[0].id),R])}w.prepend([new ke(S.goal.replace(new q("=",[R,y.args[1]])),S.substitution,S)])}},"copy_term/2":function(w,S,y){var R=y.args[0].rename(w);w.prepend([new ke(S.goal.replace(new q("=",[R,y.args[1]])),S.substitution,S.parent)])},"term_variables/2":function(w,S,y){var R=y.args[0],J=y.args[1];if(!b.type.is_fully_list(J))w.throw_error(b.error.type("list",J,y.indicator));else{var X=g(o(we(R.variables()),function($){return new xe($)}));w.prepend([new ke(S.goal.replace(new q("=",[J,X])),S.substitution,S)])}},"clause/2":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else if(!b.type.is_variable(y.args[1])&&!b.type.is_callable(y.args[1]))w.throw_error(b.error.type("callable",y.args[1],y.indicator));else if(w.session.rules[y.args[0].indicator]!==void 0)if(w.is_public_predicate(y.args[0].indicator)){var R=[];for(var J in w.session.rules[y.args[0].indicator])if(w.session.rules[y.args[0].indicator].hasOwnProperty(J)){var X=w.session.rules[y.args[0].indicator][J];w.session.renamed_variables={},X=X.rename(w),X.body===null&&(X.body=new q("true"));var $=new q(",",[new q("=",[X.head,y.args[0]]),new q("=",[X.body,y.args[1]])]);R.push(new ke(S.goal.replace($),S.substitution,S))}w.prepend(R)}else w.throw_error(b.error.permission("access","private_procedure",y.args[0].indicator,y.indicator))},"current_predicate/1":function(w,S,y){var R=y.args[0];if(!b.type.is_variable(R)&&(!b.type.is_compound(R)||R.indicator!=="//2"))w.throw_error(b.error.type("predicate_indicator",R,y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_variable(R.args[0])&&!b.type.is_atom(R.args[0]))w.throw_error(b.error.type("atom",R.args[0],y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_variable(R.args[1])&&!b.type.is_integer(R.args[1]))w.throw_error(b.error.type("integer",R.args[1],y.indicator));else{var J=[];for(var X in w.session.rules)if(w.session.rules.hasOwnProperty(X)){var $=X.lastIndexOf("/"),se=X.substr(0,$),be=parseInt(X.substr($+1,X.length-($+1))),Fe=new q("/",[new q(se),new Re(be,!1)]),lt=new q("=",[Fe,R]);J.push(new ke(S.goal.replace(lt),S.substitution,S))}w.prepend(J)}},"asserta/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var R,J;y.args[0].indicator===":-/2"?(R=y.args[0].args[0],J=Ee(y.args[0].args[1])):(R=y.args[0],J=null),b.type.is_callable(R)?J!==null&&!b.type.is_callable(J)?w.throw_error(b.error.type("callable",J,y.indicator)):w.is_public_predicate(R.indicator)?(w.session.rules[R.indicator]===void 0&&(w.session.rules[R.indicator]=[]),w.session.public_predicates[R.indicator]=!0,w.session.rules[R.indicator]=[new Ve(R,J,!0)].concat(w.session.rules[R.indicator]),w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",R.indicator,y.indicator)):w.throw_error(b.error.type("callable",R,y.indicator))}},"assertz/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var R,J;y.args[0].indicator===":-/2"?(R=y.args[0].args[0],J=Ee(y.args[0].args[1])):(R=y.args[0],J=null),b.type.is_callable(R)?J!==null&&!b.type.is_callable(J)?w.throw_error(b.error.type("callable",J,y.indicator)):w.is_public_predicate(R.indicator)?(w.session.rules[R.indicator]===void 0&&(w.session.rules[R.indicator]=[]),w.session.public_predicates[R.indicator]=!0,w.session.rules[R.indicator].push(new Ve(R,J,!0)),w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",R.indicator,y.indicator)):w.throw_error(b.error.type("callable",R,y.indicator))}},"retract/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var R,J;if(y.args[0].indicator===":-/2"?(R=y.args[0].args[0],J=y.args[0].args[1]):(R=y.args[0],J=new q("true")),typeof S.retract>"u")if(w.is_public_predicate(R.indicator)){if(w.session.rules[R.indicator]!==void 0){for(var X=[],$=0;$w.get_flag("max_arity").value)w.throw_error(b.error.representation("max_arity",y.indicator));else{var R=y.args[0].args[0].id+"/"+y.args[0].args[1].value;w.is_public_predicate(R)?(delete w.session.rules[R],w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",R,y.indicator))}},"atom_length/2":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_atom(y.args[0]))w.throw_error(b.error.type("atom",y.args[0],y.indicator));else if(!b.type.is_variable(y.args[1])&&!b.type.is_integer(y.args[1]))w.throw_error(b.error.type("integer",y.args[1],y.indicator));else if(b.type.is_integer(y.args[1])&&y.args[1].value<0)w.throw_error(b.error.domain("not_less_than_zero",y.args[1],y.indicator));else{var R=new Re(y.args[0].id.length,!1);w.prepend([new ke(S.goal.replace(new q("=",[R,y.args[1]])),S.substitution,S)])}},"atom_concat/3":function(w,S,y){var R,J,X=y.args[0],$=y.args[1],se=y.args[2];if(b.type.is_variable(se)&&(b.type.is_variable(X)||b.type.is_variable($)))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_atom(X))w.throw_error(b.error.type("atom",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_atom($))w.throw_error(b.error.type("atom",$,y.indicator));else if(!b.type.is_variable(se)&&!b.type.is_atom(se))w.throw_error(b.error.type("atom",se,y.indicator));else{var be=b.type.is_variable(X),Fe=b.type.is_variable($);if(!be&&!Fe)J=new q("=",[se,new q(X.id+$.id)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]);else if(be&&!Fe)R=se.id.substr(0,se.id.length-$.id.length),R+$.id===se.id&&(J=new q("=",[X,new q(R)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else if(Fe&&!be)R=se.id.substr(X.id.length),X.id+R===se.id&&(J=new q("=",[$,new q(R)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else{for(var lt=[],Et=0;Et<=se.id.length;Et++){var qt=new q(se.id.substr(0,Et)),nr=new q(se.id.substr(Et));J=new q(",",[new q("=",[qt,X]),new q("=",[nr,$])]),lt.push(new ke(S.goal.replace(J),S.substitution,S))}w.prepend(lt)}}},"sub_atom/5":function(w,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2],se=y.args[3],be=y.args[4];if(b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_integer(X))w.throw_error(b.error.type("integer",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_integer($))w.throw_error(b.error.type("integer",$,y.indicator));else if(!b.type.is_variable(se)&&!b.type.is_integer(se))w.throw_error(b.error.type("integer",se,y.indicator));else if(b.type.is_integer(X)&&X.value<0)w.throw_error(b.error.domain("not_less_than_zero",X,y.indicator));else if(b.type.is_integer($)&&$.value<0)w.throw_error(b.error.domain("not_less_than_zero",$,y.indicator));else if(b.type.is_integer(se)&&se.value<0)w.throw_error(b.error.domain("not_less_than_zero",se,y.indicator));else{var Fe=[],lt=[],Et=[];if(b.type.is_variable(X))for(R=0;R<=J.id.length;R++)Fe.push(R);else Fe.push(X.value);if(b.type.is_variable($))for(R=0;R<=J.id.length;R++)lt.push(R);else lt.push($.value);if(b.type.is_variable(se))for(R=0;R<=J.id.length;R++)Et.push(R);else Et.push(se.value);var qt=[];for(var nr in Fe)if(Fe.hasOwnProperty(nr)){R=Fe[nr];for(var St in lt)if(lt.hasOwnProperty(St)){var cn=lt[St],Pr=J.id.length-R-cn;if(e(Et,Pr)!==-1&&R+cn+Pr===J.id.length){var yr=J.id.substr(R,cn);if(J.id===J.id.substr(0,R)+yr+J.id.substr(R+cn,Pr)){var Rr=new q("=",[new q(yr),be]),Xr=new q("=",[X,new Re(R)]),$n=new q("=",[$,new Re(cn)]),Xs=new q("=",[se,new Re(Pr)]),Hi=new q(",",[new q(",",[new q(",",[Xr,$n]),Xs]),Rr]);qt.push(new ke(S.goal.replace(Hi),S.substitution,S))}}}}w.prepend(qt)}},"atom_chars/2":function(w,S,y){var R=y.args[0],J=y.args[1];if(b.type.is_variable(R)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_atom(R))w.throw_error(b.error.type("atom",R,y.indicator));else if(b.type.is_variable(R)){for(var se=J,be=b.type.is_variable(R),Fe="";se.indicator==="./2";){if(b.type.is_character(se.args[0]))Fe+=se.args[0].id;else if(b.type.is_variable(se.args[0])&&be){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_variable(se.args[0])){w.throw_error(b.error.type("character",se.args[0],y.indicator));return}se=se.args[1]}b.type.is_variable(se)&&be?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_empty_list(se)&&!b.type.is_variable(se)?w.throw_error(b.error.type("list",J,y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[new q(Fe),R])),S.substitution,S)])}else{for(var X=new q("[]"),$=R.id.length-1;$>=0;$--)X=new q(".",[new q(R.id.charAt($)),X]);w.prepend([new ke(S.goal.replace(new q("=",[J,X])),S.substitution,S)])}},"atom_codes/2":function(w,S,y){var R=y.args[0],J=y.args[1];if(b.type.is_variable(R)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_atom(R))w.throw_error(b.error.type("atom",R,y.indicator));else if(b.type.is_variable(R)){for(var se=J,be=b.type.is_variable(R),Fe="";se.indicator==="./2";){if(b.type.is_character_code(se.args[0]))Fe+=u(se.args[0].value);else if(b.type.is_variable(se.args[0])&&be){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_variable(se.args[0])){w.throw_error(b.error.representation("character_code",y.indicator));return}se=se.args[1]}b.type.is_variable(se)&&be?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_empty_list(se)&&!b.type.is_variable(se)?w.throw_error(b.error.type("list",J,y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[new q(Fe),R])),S.substitution,S)])}else{for(var X=new q("[]"),$=R.id.length-1;$>=0;$--)X=new q(".",[new Re(n(R.id,$),!1),X]);w.prepend([new ke(S.goal.replace(new q("=",[J,X])),S.substitution,S)])}},"char_code/2":function(w,S,y){var R=y.args[0],J=y.args[1];if(b.type.is_variable(R)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_character(R))w.throw_error(b.error.type("character",R,y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_integer(J))w.throw_error(b.error.type("integer",J,y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_character_code(J))w.throw_error(b.error.representation("character_code",y.indicator));else if(b.type.is_variable(J)){var X=new Re(n(R.id,0),!1);w.prepend([new ke(S.goal.replace(new q("=",[X,J])),S.substitution,S)])}else{var $=new q(u(J.value));w.prepend([new ke(S.goal.replace(new q("=",[$,R])),S.substitution,S)])}},"number_chars/2":function(w,S,y){var R,J=y.args[0],X=y.args[1];if(b.type.is_variable(J)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_number(J))w.throw_error(b.error.type("number",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=b.type.is_variable(J);if(!b.type.is_variable(X)){var se=X,be=!0;for(R="";se.indicator==="./2";){if(b.type.is_character(se.args[0]))R+=se.args[0].id;else if(b.type.is_variable(se.args[0]))be=!1;else if(!b.type.is_variable(se.args[0])){w.throw_error(b.error.type("character",se.args[0],y.indicator));return}se=se.args[1]}if(be=be&&b.type.is_empty_list(se),!b.type.is_empty_list(se)&&!b.type.is_variable(se)){w.throw_error(b.error.type("list",X,y.indicator));return}if(!be&&$){w.throw_error(b.error.instantiation(y.indicator));return}else if(be)if(b.type.is_variable(se)&&$){w.throw_error(b.error.instantiation(y.indicator));return}else{var Fe=w.parse(R),lt=Fe.value;!b.type.is_number(lt)||Fe.tokens[Fe.tokens.length-1].space?w.throw_error(b.error.syntax_by_predicate("parseable_number",y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[J,lt])),S.substitution,S)]);return}}if(!$){R=J.toString();for(var Et=new q("[]"),qt=R.length-1;qt>=0;qt--)Et=new q(".",[new q(R.charAt(qt)),Et]);w.prepend([new ke(S.goal.replace(new q("=",[X,Et])),S.substitution,S)])}}},"number_codes/2":function(w,S,y){var R,J=y.args[0],X=y.args[1];if(b.type.is_variable(J)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_number(J))w.throw_error(b.error.type("number",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=b.type.is_variable(J);if(!b.type.is_variable(X)){var se=X,be=!0;for(R="";se.indicator==="./2";){if(b.type.is_character_code(se.args[0]))R+=u(se.args[0].value);else if(b.type.is_variable(se.args[0]))be=!1;else if(!b.type.is_variable(se.args[0])){w.throw_error(b.error.type("character_code",se.args[0],y.indicator));return}se=se.args[1]}if(be=be&&b.type.is_empty_list(se),!b.type.is_empty_list(se)&&!b.type.is_variable(se)){w.throw_error(b.error.type("list",X,y.indicator));return}if(!be&&$){w.throw_error(b.error.instantiation(y.indicator));return}else if(be)if(b.type.is_variable(se)&&$){w.throw_error(b.error.instantiation(y.indicator));return}else{var Fe=w.parse(R),lt=Fe.value;!b.type.is_number(lt)||Fe.tokens[Fe.tokens.length-1].space?w.throw_error(b.error.syntax_by_predicate("parseable_number",y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[J,lt])),S.substitution,S)]);return}}if(!$){R=J.toString();for(var Et=new q("[]"),qt=R.length-1;qt>=0;qt--)Et=new q(".",[new Re(n(R,qt),!1),Et]);w.prepend([new ke(S.goal.replace(new q("=",[X,Et])),S.substitution,S)])}}},"upcase_atom/2":function(w,S,y){var R=y.args[0],J=y.args[1];b.type.is_variable(R)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(R)?!b.type.is_variable(J)&&!b.type.is_atom(J)?w.throw_error(b.error.type("atom",J,y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[J,new q(R.id.toUpperCase(),[])])),S.substitution,S)]):w.throw_error(b.error.type("atom",R,y.indicator))},"downcase_atom/2":function(w,S,y){var R=y.args[0],J=y.args[1];b.type.is_variable(R)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(R)?!b.type.is_variable(J)&&!b.type.is_atom(J)?w.throw_error(b.error.type("atom",J,y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[J,new q(R.id.toLowerCase(),[])])),S.substitution,S)]):w.throw_error(b.error.type("atom",R,y.indicator))},"atomic_list_concat/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q("atomic_list_concat",[R,new q("",[]),J])),S.substitution,S)])},"atomic_list_concat/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(J)||b.type.is_variable(R)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_list(R))w.throw_error(b.error.type("list",R,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_atom(X))w.throw_error(b.error.type("atom",X,y.indicator));else if(b.type.is_variable(X)){for(var se="",be=R;b.type.is_term(be)&&be.indicator==="./2";){if(!b.type.is_atom(be.args[0])&&!b.type.is_number(be.args[0])){w.throw_error(b.error.type("atomic",be.args[0],y.indicator));return}se!==""&&(se+=J.id),b.type.is_atom(be.args[0])?se+=be.args[0].id:se+=""+be.args[0].value,be=be.args[1]}se=new q(se,[]),b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_term(be)||be.indicator!=="[]/0"?w.throw_error(b.error.type("list",R,y.indicator)):w.prepend([new ke(S.goal.replace(new q("=",[se,X])),S.substitution,S)])}else{var $=g(o(X.id.split(J.id),function(Fe){return new q(Fe,[])}));w.prepend([new ke(S.goal.replace(new q("=",[$,R])),S.substitution,S)])}},"@=/2":function(w,S,y){b.compare(y.args[0],y.args[1])>0&&w.success(S)},"@>=/2":function(w,S,y){b.compare(y.args[0],y.args[1])>=0&&w.success(S)},"compare/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(!b.type.is_variable(R)&&!b.type.is_atom(R))w.throw_error(b.error.type("atom",R,y.indicator));else if(b.type.is_atom(R)&&["<",">","="].indexOf(R.id)===-1)w.throw_error(b.type.domain("order",R,y.indicator));else{var $=b.compare(J,X);$=$===0?"=":$===-1?"<":">",w.prepend([new ke(S.goal.replace(new q("=",[R,new q($,[])])),S.substitution,S)])}},"is/2":function(w,S,y){var R=y.args[1].interpret(w);b.type.is_number(R)?w.prepend([new ke(S.goal.replace(new q("=",[y.args[0],R],w.level)),S.substitution,S)]):w.throw_error(R)},"between/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(R)||b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_integer(R))w.throw_error(b.error.type("integer",R,y.indicator));else if(!b.type.is_integer(J))w.throw_error(b.error.type("integer",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_integer(X))w.throw_error(b.error.type("integer",X,y.indicator));else if(b.type.is_variable(X)){var $=[new ke(S.goal.replace(new q("=",[X,R])),S.substitution,S)];R.value=X.value&&w.success(S)},"succ/2":function(w,S,y){var R=y.args[0],J=y.args[1];b.type.is_variable(R)&&b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_variable(R)&&!b.type.is_integer(R)?w.throw_error(b.error.type("integer",R,y.indicator)):!b.type.is_variable(J)&&!b.type.is_integer(J)?w.throw_error(b.error.type("integer",J,y.indicator)):!b.type.is_variable(R)&&R.value<0?w.throw_error(b.error.domain("not_less_than_zero",R,y.indicator)):!b.type.is_variable(J)&&J.value<0?w.throw_error(b.error.domain("not_less_than_zero",J,y.indicator)):(b.type.is_variable(J)||J.value>0)&&(b.type.is_variable(R)?w.prepend([new ke(S.goal.replace(new q("=",[R,new Re(J.value-1,!1)])),S.substitution,S)]):w.prepend([new ke(S.goal.replace(new q("=",[J,new Re(R.value+1,!1)])),S.substitution,S)]))},"=:=/2":function(w,S,y){var R=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(R)?w.throw_error(R):R===0&&w.success(S)},"=\\=/2":function(w,S,y){var R=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(R)?w.throw_error(R):R!==0&&w.success(S)},"/2":function(w,S,y){var R=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(R)?w.throw_error(R):R>0&&w.success(S)},">=/2":function(w,S,y){var R=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(R)?w.throw_error(R):R>=0&&w.success(S)},"var/1":function(w,S,y){b.type.is_variable(y.args[0])&&w.success(S)},"atom/1":function(w,S,y){b.type.is_atom(y.args[0])&&w.success(S)},"atomic/1":function(w,S,y){b.type.is_atomic(y.args[0])&&w.success(S)},"compound/1":function(w,S,y){b.type.is_compound(y.args[0])&&w.success(S)},"integer/1":function(w,S,y){b.type.is_integer(y.args[0])&&w.success(S)},"float/1":function(w,S,y){b.type.is_float(y.args[0])&&w.success(S)},"number/1":function(w,S,y){b.type.is_number(y.args[0])&&w.success(S)},"nonvar/1":function(w,S,y){b.type.is_variable(y.args[0])||w.success(S)},"ground/1":function(w,S,y){y.variables().length===0&&w.success(S)},"acyclic_term/1":function(w,S,y){for(var R=S.substitution.apply(S.substitution),J=y.args[0].variables(),X=0;X0?St[St.length-1]:null,St!==null&&(qt=z(w,St,0,w.__get_max_priority(),!1))}if(qt.type===p&&qt.len===St.length-1&&cn.value==="."){qt=qt.value.rename(w);var Pr=new q("=",[J,qt]);if(se.variables){var yr=g(o(we(qt.variables()),function(Rr){return new xe(Rr)}));Pr=new q(",",[Pr,new q("=",[se.variables,yr])])}if(se.variable_names){var yr=g(o(we(qt.variables()),function(Xr){var $n;for($n in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty($n)&&w.session.renamed_variables[$n]===Xr)break;return new q("=",[new q($n,[]),new xe(Xr)])}));Pr=new q(",",[Pr,new q("=",[se.variable_names,yr])])}if(se.singletons){var yr=g(o(new Ve(qt,null).singleton_variables(),function(Xr){var $n;for($n in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty($n)&&w.session.renamed_variables[$n]===Xr)break;return new q("=",[new q($n,[]),new xe(Xr)])}));Pr=new q(",",[Pr,new q("=",[se.singletons,yr])])}w.prepend([new ke(S.goal.replace(Pr),S.substitution,S)])}else qt.type===p?w.throw_error(b.error.syntax(St[qt.len],"unexpected token",!1)):w.throw_error(qt.value)}}},"write/1":function(w,S,y){var R=y.args[0];w.prepend([new ke(S.goal.replace(new q(",",[new q("current_output",[new xe("S")]),new q("write",[new xe("S"),R])])),S.substitution,S)])},"write/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q("write_term",[R,J,new q(".",[new q("quoted",[new q("false",[])]),new q(".",[new q("ignore_ops",[new q("false")]),new q(".",[new q("numbervars",[new q("true")]),new q("[]",[])])])])])),S.substitution,S)])},"writeq/1":function(w,S,y){var R=y.args[0];w.prepend([new ke(S.goal.replace(new q(",",[new q("current_output",[new xe("S")]),new q("writeq",[new xe("S"),R])])),S.substitution,S)])},"writeq/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q("write_term",[R,J,new q(".",[new q("quoted",[new q("true",[])]),new q(".",[new q("ignore_ops",[new q("false")]),new q(".",[new q("numbervars",[new q("true")]),new q("[]",[])])])])])),S.substitution,S)])},"write_canonical/1":function(w,S,y){var R=y.args[0];w.prepend([new ke(S.goal.replace(new q(",",[new q("current_output",[new xe("S")]),new q("write_canonical",[new xe("S"),R])])),S.substitution,S)])},"write_canonical/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q("write_term",[R,J,new q(".",[new q("quoted",[new q("true",[])]),new q(".",[new q("ignore_ops",[new q("true")]),new q(".",[new q("numbervars",[new q("false")]),new q("[]",[])])])])])),S.substitution,S)])},"write_term/2":function(w,S,y){var R=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new q(",",[new q("current_output",[new xe("S")]),new q("write_term",[new xe("S"),R,J])])),S.substitution,S)])},"write_term/3":function(w,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=b.type.is_stream(R)?R:w.get_stream_by_alias(R.id);if(b.type.is_variable(R)||b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else if(!b.type.is_stream(R)&&!b.type.is_atom(R))w.throw_error(b.error.domain("stream_or_alias",R,y.indicator));else if(!b.type.is_stream($)||$.stream===null)w.throw_error(b.error.existence("stream",R,y.indicator));else if($.input)w.throw_error(b.error.permission("output","stream",R,y.indicator));else if($.type==="binary")w.throw_error(b.error.permission("output","binary_stream",R,y.indicator));else if($.position==="past_end_of_stream"&&$.eof_action==="error")w.throw_error(b.error.permission("output","past_end_of_stream",R,y.indicator));else{for(var se={},be=X,Fe;b.type.is_term(be)&&be.indicator==="./2";){if(Fe=be.args[0],b.type.is_variable(Fe)){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_write_option(Fe)){w.throw_error(b.error.domain("write_option",Fe,y.indicator));return}se[Fe.id]=Fe.args[0].id==="true",be=be.args[1]}if(be.indicator!=="[]/0"){b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):w.throw_error(b.error.type("list",X,y.indicator));return}else{se.session=w.session;var lt=J.toString(se);$.stream.put(lt,$.position),typeof $.position=="number"&&($.position+=lt.length),w.success(S)}}},"halt/0":function(w,S,y){w.points=[]},"halt/1":function(w,S,y){var R=y.args[0];b.type.is_variable(R)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_integer(R)?w.points=[]:w.throw_error(b.error.type("integer",R,y.indicator))},"current_prolog_flag/2":function(w,S,y){var R=y.args[0],J=y.args[1];if(!b.type.is_variable(R)&&!b.type.is_atom(R))w.throw_error(b.error.type("atom",R,y.indicator));else if(!b.type.is_variable(R)&&!b.type.is_flag(R))w.throw_error(b.error.domain("prolog_flag",R,y.indicator));else{var X=[];for(var $ in b.flag)if(b.flag.hasOwnProperty($)){var se=new q(",",[new q("=",[new q($),R]),new q("=",[w.get_flag($),J])]);X.push(new ke(S.goal.replace(se),S.substitution,S))}w.prepend(X)}},"set_prolog_flag/2":function(w,S,y){var R=y.args[0],J=y.args[1];b.type.is_variable(R)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(R)?b.type.is_flag(R)?b.type.is_value_flag(R,J)?b.type.is_modifiable_flag(R)?(w.session.flag[R.id]=J,w.success(S)):w.throw_error(b.error.permission("modify","flag",R)):w.throw_error(b.error.domain("flag_value",new q("+",[R,J]),y.indicator)):w.throw_error(b.error.domain("prolog_flag",R,y.indicator)):w.throw_error(b.error.type("atom",R,y.indicator))}},flag:{bounded:{allowed:[new q("true"),new q("false")],value:new q("true"),changeable:!1},max_integer:{allowed:[new Re(Number.MAX_SAFE_INTEGER)],value:new Re(Number.MAX_SAFE_INTEGER),changeable:!1},min_integer:{allowed:[new Re(Number.MIN_SAFE_INTEGER)],value:new Re(Number.MIN_SAFE_INTEGER),changeable:!1},integer_rounding_function:{allowed:[new q("down"),new q("toward_zero")],value:new q("toward_zero"),changeable:!1},char_conversion:{allowed:[new q("on"),new q("off")],value:new q("on"),changeable:!0},debug:{allowed:[new q("on"),new q("off")],value:new q("off"),changeable:!0},max_arity:{allowed:[new q("unbounded")],value:new q("unbounded"),changeable:!1},unknown:{allowed:[new q("error"),new q("fail"),new q("warning")],value:new q("error"),changeable:!0},double_quotes:{allowed:[new q("chars"),new q("codes"),new q("atom")],value:new q("codes"),changeable:!0},occurs_check:{allowed:[new q("false"),new q("true")],value:new q("false"),changeable:!0},dialect:{allowed:[new q("tau")],value:new q("tau"),changeable:!1},version_data:{allowed:[new q("tau",[new Re(t.major,!1),new Re(t.minor,!1),new Re(t.patch,!1),new q(t.status)])],value:new q("tau",[new Re(t.major,!1),new Re(t.minor,!1),new Re(t.patch,!1),new q(t.status)]),changeable:!1},nodejs:{allowed:[new q("yes"),new q("no")],value:new q(typeof El<"u"&&El.exports?"yes":"no"),changeable:!1}},unify:function(w,S,y){y=y===void 0?!1:y;for(var R=[{left:w,right:S}],J={};R.length!==0;){var X=R.pop();if(w=X.left,S=X.right,b.type.is_term(w)&&b.type.is_term(S)){if(w.indicator!==S.indicator)return null;for(var $=0;$J.value?1:0:J}else return R},operate:function(w,S){if(b.type.is_operator(S)){for(var y=b.type.is_operator(S),R=[],J,X=!1,$=0;$w.get_flag("max_integer").value||J0?w.start+w.matches[0].length:w.start,J=y?new q("token_not_found"):new q("found",[new q(w.value.toString())]),X=new q(".",[new q("line",[new Re(w.line+1)]),new q(".",[new q("column",[new Re(R+1)]),new q(".",[J,new q("[]",[])])])]);return new q("error",[new q("syntax_error",[new q(S)]),X])},syntax_by_predicate:function(w,S){return new q("error",[new q("syntax_error",[new q(w)]),Z(S)])}},warning:{singleton:function(w,S,y){for(var R=new q("[]"),J=w.length-1;J>=0;J--)R=new q(".",[new xe(w[J]),R]);return new q("warning",[new q("singleton_variables",[R,Z(S)]),new q(".",[new q("line",[new Re(y,!1)]),new q("[]")])])},failed_goal:function(w,S){return new q("warning",[new q("failed_goal",[w]),new q(".",[new q("line",[new Re(S,!1)]),new q("[]")])])}},format_variable:function(w){return"_"+w},format_answer:function(w,S,R){S instanceof Se&&(S=S.thread);var R=R||{};if(R.session=S?S.session:void 0,b.type.is_error(w))return"uncaught exception: "+w.args[0].toString();if(w===!1)return"false.";if(w===null)return"limit exceeded ;";var J=0,X="";if(b.type.is_substitution(w)){var $=w.domain(!0);w=w.filter(function(Fe,lt){return!b.type.is_variable(lt)||$.indexOf(lt.id)!==-1&&Fe!==lt.id})}for(var se in w.links)w.links.hasOwnProperty(se)&&(J++,X!==""&&(X+=", "),X+=se.toString(R)+" = "+w.links[se].toString(R));var be=typeof S>"u"||S.points.length>0?" ;":".";return J===0?"true"+be:X+be},flatten_error:function(w){if(!b.type.is_error(w))return null;w=w.args[0];var S={};return S.type=w.args[0].id,S.thrown=S.type==="syntax_error"?null:w.args[1].id,S.expected=null,S.found=null,S.representation=null,S.existence=null,S.existence_type=null,S.line=null,S.column=null,S.permission_operation=null,S.permission_type=null,S.evaluation_type=null,S.type==="type_error"||S.type==="domain_error"?(S.expected=w.args[0].args[0].id,S.found=w.args[0].args[1].toString()):S.type==="syntax_error"?w.args[1].indicator==="./2"?(S.expected=w.args[0].args[0].id,S.found=w.args[1].args[1].args[1].args[0],S.found=S.found.id==="token_not_found"?S.found.id:S.found.args[0].id,S.line=w.args[1].args[0].args[0].value,S.column=w.args[1].args[1].args[0].args[0].value):S.thrown=w.args[1].id:S.type==="permission_error"?(S.found=w.args[0].args[2].toString(),S.permission_operation=w.args[0].args[0].id,S.permission_type=w.args[0].args[1].id):S.type==="evaluation_error"?S.evaluation_type=w.args[0].args[0].id:S.type==="representation_error"?S.representation=w.args[0].args[0].id:S.type==="existence_error"&&(S.existence=w.args[0].args[1].toString(),S.existence_type=w.args[0].args[0].id),S},create:function(w){return new b.type.Session(w)}};typeof El<"u"?El.exports=b:window.pl=b})()});function Kme(t,e,r){t.prepend(r.map(o=>new Ma.default.type.State(e.goal.replace(o),e.substitution,e)))}function n6(t){let e=zme.get(t.session);if(e==null)throw new Error("Assertion failed: A project should have been registered for the active session");return e}function Jme(t,e){zme.set(t,e),t.consult(`:- use_module(library(${Ygt.id})).`)}var i6,Ma,Vme,Lh,jgt,Ggt,zme,Ygt,Xme=wt(()=>{Ke();i6=et(N2()),Ma=et(r6()),Vme=et(ve("vm")),{is_atom:Lh,is_variable:jgt,is_instantiated_list:Ggt}=Ma.default.type;zme=new WeakMap;Ygt=new Ma.default.type.Module("constraints",{"project_workspaces_by_descriptor/3":(t,e,r)=>{let[o,a,n]=r.args;if(!Lh(o)||!Lh(a)){t.throw_error(Ma.default.error.instantiation(r.indicator));return}let u=G.parseIdent(o.id),A=G.makeDescriptor(u,a.id),h=n6(t).tryWorkspaceByDescriptor(A);jgt(n)&&h!==null&&Kme(t,e,[new Ma.default.type.Term("=",[n,new Ma.default.type.Term(String(h.relativeCwd))])]),Lh(n)&&h!==null&&h.relativeCwd===n.id&&t.success(e)},"workspace_field/3":(t,e,r)=>{let[o,a,n]=r.args;if(!Lh(o)||!Lh(a)){t.throw_error(Ma.default.error.instantiation(r.indicator));return}let A=n6(t).tryWorkspaceByCwd(o.id);if(A==null)return;let p=(0,i6.default)(A.manifest.raw,a.id);typeof p>"u"||Kme(t,e,[new Ma.default.type.Term("=",[n,new Ma.default.type.Term(typeof p=="object"?JSON.stringify(p):p)])])},"workspace_field_test/3":(t,e,r)=>{let[o,a,n]=r.args;t.prepend([new Ma.default.type.State(e.goal.replace(new Ma.default.type.Term("workspace_field_test",[o,a,n,new Ma.default.type.Term("[]",[])])),e.substitution,e)])},"workspace_field_test/4":(t,e,r)=>{let[o,a,n,u]=r.args;if(!Lh(o)||!Lh(a)||!Lh(n)||!Ggt(u)){t.throw_error(Ma.default.error.instantiation(r.indicator));return}let p=n6(t).tryWorkspaceByCwd(o.id);if(p==null)return;let h=(0,i6.default)(p.manifest.raw,a.id);if(typeof h>"u")return;let E={$$:h};for(let[D,x]of u.toJavaScript().entries())E[`$${D}`]=x;Vme.default.runInNewContext(n.id,E)&&t.success(e)}},["project_workspaces_by_descriptor/3","workspace_field/3","workspace_field_test/3","workspace_field_test/4"])});var W2={};Kt(W2,{Constraints:()=>o6,DependencyType:()=>tye});function Vs(t){if(t instanceof rC.default.type.Num)return t.value;if(t instanceof rC.default.type.Term)switch(t.indicator){case"throw/1":return Vs(t.args[0]);case"error/1":return Vs(t.args[0]);case"error/2":if(t.args[0]instanceof rC.default.type.Term&&t.args[0].indicator==="syntax_error/1")return Object.assign(Vs(t.args[0]),...Vs(t.args[1]));{let e=Vs(t.args[0]);return e.message+=` (in ${Vs(t.args[1])})`,e}case"syntax_error/1":return new zt(43,`Syntax error: ${Vs(t.args[0])}`);case"existence_error/2":return new zt(44,`Existence error: ${Vs(t.args[0])} ${Vs(t.args[1])} not found`);case"instantiation_error/0":return new zt(75,"Instantiation error: an argument is variable when an instantiated argument was expected");case"line/1":return{line:Vs(t.args[0])};case"column/1":return{column:Vs(t.args[0])};case"found/1":return{found:Vs(t.args[0])};case"./2":return[Vs(t.args[0])].concat(Vs(t.args[1]));case"//2":return`${Vs(t.args[0])}/${Vs(t.args[1])}`;default:return t.id}throw`couldn't pretty print because of unsupported node ${t}`}function $me(t){let e;try{e=Vs(t)}catch(r){throw typeof r=="string"?new zt(42,`Unknown error: ${t} (note: ${r})`):r}return typeof e.line<"u"&&typeof e.column<"u"&&(e.message+=` at line ${e.line}, column ${e.column}`),e}function Zg(t){return t.id==="null"?null:`${t.toJavaScript()}`}function Wgt(t){if(t.id==="null")return null;{let e=t.toJavaScript();if(typeof e!="string")return JSON.stringify(e);try{return JSON.stringify(JSON.parse(e))}catch{return JSON.stringify(e)}}}function Mh(t){return typeof t=="string"?`'${t}'`:"[]"}var eye,rC,tye,Zme,s6,o6,K2=wt(()=>{Ke();Ke();Pt();eye=et(Qme()),rC=et(r6());j2();Xme();(0,eye.default)(rC.default);tye=(o=>(o.Dependencies="dependencies",o.DevDependencies="devDependencies",o.PeerDependencies="peerDependencies",o))(tye||{}),Zme=["dependencies","devDependencies","peerDependencies"];s6=class{constructor(e,r){let o=1e3*e.workspaces.length;this.session=rC.default.create(o),Jme(this.session,e),this.session.consult(":- use_module(library(lists))."),this.session.consult(r)}fetchNextAnswer(){return new Promise(e=>{this.session.answer(r=>{e(r)})})}async*makeQuery(e){let r=this.session.query(e);if(r!==!0)throw $me(r);for(;;){let o=await this.fetchNextAnswer();if(o===null)throw new zt(79,"Resolution limit exceeded");if(!o)break;if(o.id==="throw")throw $me(o);yield o}}};o6=class t{constructor(e){this.source="";this.project=e;let r=e.configuration.get("constraintsPath");ae.existsSync(r)&&(this.source=ae.readFileSync(r,"utf8"))}static async find(e){return new t(e)}getProjectDatabase(){let e="";for(let r of Zme)e+=`dependency_type(${r}). +`;for(let r of this.project.workspacesByCwd.values()){let o=r.relativeCwd;e+=`workspace(${Mh(o)}). +`,e+=`workspace_ident(${Mh(o)}, ${Mh(G.stringifyIdent(r.anchoredLocator))}). +`,e+=`workspace_version(${Mh(o)}, ${Mh(r.manifest.version)}). +`;for(let a of Zme)for(let n of r.manifest[a].values())e+=`workspace_has_dependency(${Mh(o)}, ${Mh(G.stringifyIdent(n))}, ${Mh(n.range)}, ${a}). +`}return e+=`workspace(_) :- false. +`,e+=`workspace_ident(_, _) :- false. +`,e+=`workspace_version(_, _) :- false. +`,e+=`workspace_has_dependency(_, _, _, _) :- false. +`,e}getDeclarations(){let e="";return e+=`gen_enforced_dependency(_, _, _, _) :- false. +`,e+=`gen_enforced_field(_, _, _) :- false. +`,e}get fullSource(){return`${this.getProjectDatabase()} +${this.source} +${this.getDeclarations()}`}createSession(){return new s6(this.project,this.fullSource)}async processClassic(){let e=this.createSession();return{enforcedDependencies:await this.genEnforcedDependencies(e),enforcedFields:await this.genEnforcedFields(e)}}async process(){let{enforcedDependencies:e,enforcedFields:r}=await this.processClassic(),o=new Map;for(let{workspace:a,dependencyIdent:n,dependencyRange:u,dependencyType:A}of e){let p=q2([A,G.stringifyIdent(n)]),h=qe.getMapWithDefault(o,a.cwd);qe.getMapWithDefault(h,p).set(u??void 0,new Set)}for(let{workspace:a,fieldPath:n,fieldValue:u}of r){let A=q2(n),p=qe.getMapWithDefault(o,a.cwd);qe.getMapWithDefault(p,A).set(JSON.parse(u)??void 0,new Set)}return{manifestUpdates:o,reportedErrors:new Map}}async genEnforcedDependencies(e){let r=[];for await(let o of e.makeQuery("workspace(WorkspaceCwd), dependency_type(DependencyType), gen_enforced_dependency(WorkspaceCwd, DependencyIdent, DependencyRange, DependencyType).")){let a=K.resolve(this.project.cwd,Zg(o.links.WorkspaceCwd)),n=Zg(o.links.DependencyIdent),u=Zg(o.links.DependencyRange),A=Zg(o.links.DependencyType);if(a===null||n===null)throw new Error("Invalid rule");let p=this.project.getWorkspaceByCwd(a),h=G.parseIdent(n);r.push({workspace:p,dependencyIdent:h,dependencyRange:u,dependencyType:A})}return qe.sortMap(r,[({dependencyRange:o})=>o!==null?"0":"1",({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({dependencyIdent:o})=>G.stringifyIdent(o)])}async genEnforcedFields(e){let r=[];for await(let o of e.makeQuery("workspace(WorkspaceCwd), gen_enforced_field(WorkspaceCwd, FieldPath, FieldValue).")){let a=K.resolve(this.project.cwd,Zg(o.links.WorkspaceCwd)),n=Zg(o.links.FieldPath),u=Wgt(o.links.FieldValue);if(a===null||n===null)throw new Error("Invalid rule");let A=this.project.getWorkspaceByCwd(a);r.push({workspace:A,fieldPath:n,fieldValue:u})}return qe.sortMap(r,[({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({fieldPath:o})=>o])}async*query(e){let r=this.createSession();for await(let o of r.makeQuery(e)){let a={};for(let[n,u]of Object.entries(o.links))n!=="_"&&(a[n]=Zg(u));yield a}}}});var uye=_(tQ=>{"use strict";Object.defineProperty(tQ,"__esModule",{value:!0});function lB(t){let e=[...t.caches],r=e.shift();return r===void 0?cye():{get(o,a,n={miss:()=>Promise.resolve()}){return r.get(o,a,n).catch(()=>lB({caches:e}).get(o,a,n))},set(o,a){return r.set(o,a).catch(()=>lB({caches:e}).set(o,a))},delete(o){return r.delete(o).catch(()=>lB({caches:e}).delete(o))},clear(){return r.clear().catch(()=>lB({caches:e}).clear())}}}function cye(){return{get(t,e,r={miss:()=>Promise.resolve()}){return e().then(a=>Promise.all([a,r.miss(a)])).then(([a])=>a)},set(t,e){return Promise.resolve(e)},delete(t){return Promise.resolve()},clear(){return Promise.resolve()}}}tQ.createFallbackableCache=lB;tQ.createNullCache=cye});var fye=_((pWt,Aye)=>{Aye.exports=uye()});var pye=_(C6=>{"use strict";Object.defineProperty(C6,"__esModule",{value:!0});function Adt(t={serializable:!0}){let e={};return{get(r,o,a={miss:()=>Promise.resolve()}){let n=JSON.stringify(r);if(n in e)return Promise.resolve(t.serializable?JSON.parse(e[n]):e[n]);let u=o(),A=a&&a.miss||(()=>Promise.resolve());return u.then(p=>A(p)).then(()=>u)},set(r,o){return e[JSON.stringify(r)]=t.serializable?JSON.stringify(o):o,Promise.resolve(o)},delete(r){return delete e[JSON.stringify(r)],Promise.resolve()},clear(){return e={},Promise.resolve()}}}C6.createInMemoryCache=Adt});var gye=_((gWt,hye)=>{hye.exports=pye()});var mye=_(su=>{"use strict";Object.defineProperty(su,"__esModule",{value:!0});function fdt(t,e,r){let o={"x-algolia-api-key":r,"x-algolia-application-id":e};return{headers(){return t===w6.WithinHeaders?o:{}},queryParameters(){return t===w6.WithinQueryParameters?o:{}}}}function pdt(t){let e=0,r=()=>(e++,new Promise(o=>{setTimeout(()=>{o(t(r))},Math.min(100*e,1e3))}));return t(r)}function dye(t,e=(r,o)=>Promise.resolve()){return Object.assign(t,{wait(r){return dye(t.then(o=>Promise.all([e(o,r),o])).then(o=>o[1]))}})}function hdt(t){let e=t.length-1;for(e;e>0;e--){let r=Math.floor(Math.random()*(e+1)),o=t[e];t[e]=t[r],t[r]=o}return t}function gdt(t,e){return e&&Object.keys(e).forEach(r=>{t[r]=e[r](t)}),t}function ddt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}var mdt="4.22.1",ydt=t=>()=>t.transporter.requester.destroy(),w6={WithinQueryParameters:0,WithinHeaders:1};su.AuthMode=w6;su.addMethods=gdt;su.createAuth=fdt;su.createRetryablePromise=pdt;su.createWaitablePromise=dye;su.destroy=ydt;su.encode=ddt;su.shuffle=hdt;su.version=mdt});var cB=_((mWt,yye)=>{yye.exports=mye()});var Eye=_(I6=>{"use strict";Object.defineProperty(I6,"__esModule",{value:!0});var Edt={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};I6.MethodEnum=Edt});var uB=_((EWt,Cye)=>{Cye.exports=Eye()});var Nye=_(Ti=>{"use strict";Object.defineProperty(Ti,"__esModule",{value:!0});var Iye=uB();function B6(t,e){let r=t||{},o=r.data||{};return Object.keys(r).forEach(a=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(a)===-1&&(o[a]=r[a])}),{data:Object.entries(o).length>0?o:void 0,timeout:r.timeout||e,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var AB={Read:1,Write:2,Any:3},fC={Up:1,Down:2,Timeouted:3},Bye=2*60*1e3;function D6(t,e=fC.Up){return{...t,status:e,lastUpdate:Date.now()}}function vye(t){return t.status===fC.Up||Date.now()-t.lastUpdate>Bye}function Dye(t){return t.status===fC.Timeouted&&Date.now()-t.lastUpdate<=Bye}function P6(t){return typeof t=="string"?{protocol:"https",url:t,accept:AB.Any}:{protocol:t.protocol||"https",url:t.url,accept:t.accept||AB.Any}}function Cdt(t,e){return Promise.all(e.map(r=>t.get(r,()=>Promise.resolve(D6(r))))).then(r=>{let o=r.filter(A=>vye(A)),a=r.filter(A=>Dye(A)),n=[...o,...a],u=n.length>0?n.map(A=>P6(A)):e;return{getTimeout(A,p){return(a.length===0&&A===0?1:a.length+3+A)*p},statelessHosts:u}})}var wdt=({isTimedOut:t,status:e})=>!t&&~~e===0,Idt=t=>{let e=t.status;return t.isTimedOut||wdt(t)||~~(e/100)!==2&&~~(e/100)!==4},Bdt=({status:t})=>~~(t/100)===2,vdt=(t,e)=>Idt(t)?e.onRetry(t):Bdt(t)?e.onSuccess(t):e.onFail(t);function wye(t,e,r,o){let a=[],n=kye(r,o),u=Qye(t,o),A=r.method,p=r.method!==Iye.MethodEnum.Get?{}:{...r.data,...o.data},h={"x-algolia-agent":t.userAgent.value,...t.queryParameters,...p,...o.queryParameters},E=0,I=(D,x)=>{let C=D.pop();if(C===void 0)throw Tye(v6(a));let T={data:n,headers:u,method:A,url:bye(C,r.path,h),connectTimeout:x(E,t.timeouts.connect),responseTimeout:x(E,o.timeout)},L=z=>{let te={request:T,response:z,host:C,triesLeft:D.length};return a.push(te),te},U={onSuccess:z=>Pye(z),onRetry(z){let te=L(z);return z.isTimedOut&&E++,Promise.all([t.logger.info("Retryable failure",S6(te)),t.hostsCache.set(C,D6(C,z.isTimedOut?fC.Timeouted:fC.Down))]).then(()=>I(D,x))},onFail(z){throw L(z),Sye(z,v6(a))}};return t.requester.send(T).then(z=>vdt(z,U))};return Cdt(t.hostsCache,e).then(D=>I([...D.statelessHosts].reverse(),D.getTimeout))}function Ddt(t){let{hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,hosts:p,queryParameters:h,headers:E}=t,I={hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,headers:E,queryParameters:h,hosts:p.map(D=>P6(D)),read(D,x){let C=B6(x,I.timeouts.read),T=()=>wye(I,I.hosts.filter(z=>(z.accept&AB.Read)!==0),D,C);if((C.cacheable!==void 0?C.cacheable:D.cacheable)!==!0)return T();let U={request:D,mappedRequestOptions:C,transporter:{queryParameters:I.queryParameters,headers:I.headers}};return I.responsesCache.get(U,()=>I.requestsCache.get(U,()=>I.requestsCache.set(U,T()).then(z=>Promise.all([I.requestsCache.delete(U),z]),z=>Promise.all([I.requestsCache.delete(U),Promise.reject(z)])).then(([z,te])=>te)),{miss:z=>I.responsesCache.set(U,z)})},write(D,x){return wye(I,I.hosts.filter(C=>(C.accept&AB.Write)!==0),D,B6(x,I.timeouts.write))}};return I}function Pdt(t){let e={value:`Algolia for JavaScript (${t})`,add(r){let o=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return e.value.indexOf(o)===-1&&(e.value=`${e.value}${o}`),e}};return e}function Pye(t){try{return JSON.parse(t.content)}catch(e){throw Rye(e.message,t)}}function Sye({content:t,status:e},r){let o=t;try{o=JSON.parse(t).message}catch{}return Fye(o,e,r)}function Sdt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}function bye(t,e,r){let o=xye(r),a=`${t.protocol}://${t.url}/${e.charAt(0)==="/"?e.substr(1):e}`;return o.length&&(a+=`?${o}`),a}function xye(t){let e=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(t).map(r=>Sdt("%s=%s",r,e(t[r])?JSON.stringify(t[r]):t[r])).join("&")}function kye(t,e){if(t.method===Iye.MethodEnum.Get||t.data===void 0&&e.data===void 0)return;let r=Array.isArray(t.data)?t.data:{...t.data,...e.data};return JSON.stringify(r)}function Qye(t,e){let r={...t.headers,...e.headers},o={};return Object.keys(r).forEach(a=>{let n=r[a];o[a.toLowerCase()]=n}),o}function v6(t){return t.map(e=>S6(e))}function S6(t){let e=t.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...t,request:{...t.request,headers:{...t.request.headers,...e}}}}function Fye(t,e,r){return{name:"ApiError",message:t,status:e,transporterStackTrace:r}}function Rye(t,e){return{name:"DeserializationError",message:t,response:e}}function Tye(t){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:t}}Ti.CallEnum=AB;Ti.HostStatusEnum=fC;Ti.createApiError=Fye;Ti.createDeserializationError=Rye;Ti.createMappedRequestOptions=B6;Ti.createRetryError=Tye;Ti.createStatefulHost=D6;Ti.createStatelessHost=P6;Ti.createTransporter=Ddt;Ti.createUserAgent=Pdt;Ti.deserializeFailure=Sye;Ti.deserializeSuccess=Pye;Ti.isStatefulHostTimeouted=Dye;Ti.isStatefulHostUp=vye;Ti.serializeData=kye;Ti.serializeHeaders=Qye;Ti.serializeQueryParameters=xye;Ti.serializeUrl=bye;Ti.stackFrameWithoutCredentials=S6;Ti.stackTraceWithoutCredentials=v6});var fB=_((wWt,Lye)=>{Lye.exports=Nye()});var Mye=_(Oh=>{"use strict";Object.defineProperty(Oh,"__esModule",{value:!0});var pC=cB(),bdt=fB(),pB=uB(),xdt=t=>{let e=t.region||"us",r=pC.createAuth(pC.AuthMode.WithinHeaders,t.appId,t.apiKey),o=bdt.createTransporter({hosts:[{url:`analytics.${e}.algolia.com`}],...t,headers:{...r.headers(),"content-type":"application/json",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a=t.appId;return pC.addMethods({appId:a,transporter:o},t.methods)},kdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Post,path:"2/abtests",data:e},r),Qdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Delete,path:pC.encode("2/abtests/%s",e)},r),Fdt=t=>(e,r)=>t.transporter.read({method:pB.MethodEnum.Get,path:pC.encode("2/abtests/%s",e)},r),Rdt=t=>e=>t.transporter.read({method:pB.MethodEnum.Get,path:"2/abtests"},e),Tdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Post,path:pC.encode("2/abtests/%s/stop",e)},r);Oh.addABTest=kdt;Oh.createAnalyticsClient=xdt;Oh.deleteABTest=Qdt;Oh.getABTest=Fdt;Oh.getABTests=Rdt;Oh.stopABTest=Tdt});var Uye=_((BWt,Oye)=>{Oye.exports=Mye()});var Hye=_(hB=>{"use strict";Object.defineProperty(hB,"__esModule",{value:!0});var b6=cB(),Ndt=fB(),_ye=uB(),Ldt=t=>{let e=t.region||"us",r=b6.createAuth(b6.AuthMode.WithinHeaders,t.appId,t.apiKey),o=Ndt.createTransporter({hosts:[{url:`personalization.${e}.algolia.com`}],...t,headers:{...r.headers(),"content-type":"application/json",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}});return b6.addMethods({appId:t.appId,transporter:o},t.methods)},Mdt=t=>e=>t.transporter.read({method:_ye.MethodEnum.Get,path:"1/strategies/personalization"},e),Odt=t=>(e,r)=>t.transporter.write({method:_ye.MethodEnum.Post,path:"1/strategies/personalization",data:e},r);hB.createPersonalizationClient=Ldt;hB.getPersonalizationStrategy=Mdt;hB.setPersonalizationStrategy=Odt});var jye=_((DWt,qye)=>{qye.exports=Hye()});var nEe=_(Rt=>{"use strict";Object.defineProperty(Rt,"__esModule",{value:!0});var Yt=cB(),Oa=fB(),Dr=uB(),Udt=ve("crypto");function rQ(t){let e=r=>t.request(r).then(o=>{if(t.batch!==void 0&&t.batch(o.hits),!t.shouldStop(o))return o.cursor?e({cursor:o.cursor}):e({page:(r.page||0)+1})});return e({})}var _dt=t=>{let e=t.appId,r=Yt.createAuth(t.authMode!==void 0?t.authMode:Yt.AuthMode.WithinHeaders,e,t.apiKey),o=Oa.createTransporter({hosts:[{url:`${e}-dsn.algolia.net`,accept:Oa.CallEnum.Read},{url:`${e}.algolia.net`,accept:Oa.CallEnum.Write}].concat(Yt.shuffle([{url:`${e}-1.algolianet.com`},{url:`${e}-2.algolianet.com`},{url:`${e}-3.algolianet.com`}])),...t,headers:{...r.headers(),"content-type":"application/x-www-form-urlencoded",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a={transporter:o,appId:e,addAlgoliaAgent(n,u){o.userAgent.add({segment:n,version:u})},clearCache(){return Promise.all([o.requestsCache.clear(),o.responsesCache.clear()]).then(()=>{})}};return Yt.addMethods(a,t.methods)};function Gye(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function Yye(){return{name:"ObjectNotFoundError",message:"Object not found."}}function Wye(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Hdt=t=>(e,r)=>{let{queryParameters:o,...a}=r||{},n={acl:e,...o!==void 0?{queryParameters:o}:{}},u=(A,p)=>Yt.createRetryablePromise(h=>gB(t)(A.key,p).catch(E=>{if(E.status!==404)throw E;return h()}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:"1/keys",data:n},a),u)},qdt=t=>(e,r,o)=>{let a=Oa.createMappedRequestOptions(o);return a.queryParameters["X-Algolia-User-ID"]=e,t.transporter.write({method:Dr.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},a)},jdt=t=>(e,r,o)=>t.transporter.write({method:Dr.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:e,cluster:r}},o),Gdt=t=>(e,r)=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!0,requests:{action:"addEntry",body:[]}}},r),(o,a)=>hC(t)(o.taskID,a)),nQ=t=>(e,r,o)=>{let a=(n,u)=>dB(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/operation",e),data:{operation:"copy",destination:r}},o),a)},Ydt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Rules]}),Wdt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Settings]}),Kdt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Synonyms]}),Vdt=t=>(e,r)=>e.method===Dr.MethodEnum.Get?t.transporter.read(e,r):t.transporter.write(e,r),zdt=t=>(e,r)=>{let o=(a,n)=>Yt.createRetryablePromise(u=>gB(t)(e,n).then(u).catch(A=>{if(A.status!==404)throw A}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Yt.encode("1/keys/%s",e)},r),o)},Jdt=t=>(e,r,o)=>{let a=r.map(n=>({action:"deleteEntry",body:{objectID:n}}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},Xdt=()=>(t,e)=>{let r=Oa.serializeQueryParameters(e),o=Udt.createHmac("sha256",t).update(r).digest("hex");return Buffer.from(o+r).toString("base64")},gB=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/keys/%s",e)},r),Kye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/task/%s",e.toString())},r),Zdt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"/1/dictionaries/*/settings"},e),$dt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/logs"},e),emt=()=>t=>{let e=Buffer.from(t,"base64").toString("ascii"),r=/validUntil=(\d+)/,o=e.match(r);if(o===null)throw Wye();return parseInt(o[1],10)-Math.round(new Date().getTime()/1e3)},tmt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/clusters/mapping/top"},e),rmt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/clusters/mapping/%s",e)},r),nmt=t=>e=>{let{retrieveMappings:r,...o}=e||{};return r===!0&&(o.getClusters=!0),t.transporter.read({method:Dr.MethodEnum.Get,path:"1/clusters/mapping/pending"},o)},dB=t=>(e,r={})=>{let o={transporter:t.transporter,appId:t.appId,indexName:e};return Yt.addMethods(o,r.methods)},imt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/keys"},e),smt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/clusters"},e),omt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/indexes"},e),amt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:"1/clusters/mapping"},e),lmt=t=>(e,r,o)=>{let a=(n,u)=>dB(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/operation",e),data:{operation:"move",destination:r}},o),a)},cmt=t=>(e,r)=>{let o=(a,n)=>Promise.all(Object.keys(a.taskID).map(u=>dB(t)(u,{methods:{waitTask:es}}).waitTask(a.taskID[u],n)));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:e}},r),o)},umt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:e}},r),Amt=t=>(e,r)=>{let o=e.map(a=>({...a,params:Oa.serializeQueryParameters(a.params||{})}));return t.transporter.read({method:Dr.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:o},cacheable:!0},r)},fmt=t=>(e,r)=>Promise.all(e.map(o=>{let{facetName:a,facetQuery:n,...u}=o.params;return dB(t)(o.indexName,{methods:{searchForFacetValues:eEe}}).searchForFacetValues(a,n,{...r,...u})})),pmt=t=>(e,r)=>{let o=Oa.createMappedRequestOptions(r);return o.queryParameters["X-Algolia-User-ID"]=e,t.transporter.write({method:Dr.MethodEnum.Delete,path:"1/clusters/mapping"},o)},hmt=t=>(e,r,o)=>{let a=r.map(n=>({action:"addEntry",body:n}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!0,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},gmt=t=>(e,r)=>{let o=(a,n)=>Yt.createRetryablePromise(u=>gB(t)(e,n).catch(A=>{if(A.status!==404)throw A;return u()}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/keys/%s/restore",e)},r),o)},dmt=t=>(e,r,o)=>{let a=r.map(n=>({action:"addEntry",body:n}));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},mmt=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("/1/dictionaries/%s/search",e),data:{query:r},cacheable:!0},o),ymt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:e}},r),Emt=t=>(e,r)=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:"/1/dictionaries/*/settings",data:e},r),(o,a)=>hC(t)(o.taskID,a)),Cmt=t=>(e,r)=>{let o=Object.assign({},r),{queryParameters:a,...n}=r||{},u=a?{queryParameters:a}:{},A=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],p=E=>Object.keys(o).filter(I=>A.indexOf(I)!==-1).every(I=>{if(Array.isArray(E[I])&&Array.isArray(o[I])){let D=E[I];return D.length===o[I].length&&D.every((x,C)=>x===o[I][C])}else return E[I]===o[I]}),h=(E,I)=>Yt.createRetryablePromise(D=>gB(t)(e,I).then(x=>p(x)?Promise.resolve():D()));return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:Yt.encode("1/keys/%s",e),data:u},n),h)},hC=t=>(e,r)=>Yt.createRetryablePromise(o=>Kye(t)(e,r).then(a=>a.status!=="published"?o():void 0)),Vye=t=>(e,r)=>{let o=(a,n)=>es(t)(a.taskID,n);return Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/batch",t.indexName),data:{requests:e}},r),o)},wmt=t=>e=>rQ({shouldStop:r=>r.cursor===void 0,...e,request:r=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/browse",t.indexName),data:r},e)}),Imt=t=>e=>{let r={hitsPerPage:1e3,...e};return rQ({shouldStop:o=>o.hits.length({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},Bmt=t=>e=>{let r={hitsPerPage:1e3,...e};return rQ({shouldStop:o=>o.hits.length({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},iQ=t=>(e,r,o)=>{let{batchSize:a,...n}=o||{},u={taskIDs:[],objectIDs:[]},A=(p=0)=>{let h=[],E;for(E=p;E({action:r,body:I})),n).then(I=>(u.objectIDs=u.objectIDs.concat(I.objectIDs),u.taskIDs.push(I.taskID),E++,A(E)))};return Yt.createWaitablePromise(A(),(p,h)=>Promise.all(p.taskIDs.map(E=>es(t)(E,h))))},vmt=t=>e=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/clear",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),Dmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Oa.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/rules/clear",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Pmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Oa.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/synonyms/clear",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Smt=t=>(e,r)=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/deleteByQuery",t.indexName),data:e},r),(o,a)=>es(t)(o.taskID,a)),bmt=t=>e=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Yt.encode("1/indexes/%s",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),xmt=t=>(e,r)=>Yt.createWaitablePromise(zye(t)([e],r).then(o=>({taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),zye=t=>(e,r)=>{let o=e.map(a=>({objectID:a}));return iQ(t)(o,ed.DeleteObject,r)},kmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Oa.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Yt.encode("1/indexes/%s/rules/%s",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},Qmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Oa.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Yt.encode("1/indexes/%s/synonyms/%s",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},Fmt=t=>e=>Jye(t)(e).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),Rmt=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/answers/%s/prediction",t.indexName),data:{query:e,queryLanguages:r},cacheable:!0},o),Tmt=t=>(e,r)=>{let{query:o,paginate:a,...n}=r||{},u=0,A=()=>$ye(t)(o||"",{...n,page:u}).then(p=>{for(let[h,E]of Object.entries(p.hits))if(e(E))return{object:E,position:parseInt(h,10),page:u};if(u++,a===!1||u>=p.nbPages)throw Yye();return A()});return A()},Nmt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/indexes/%s/%s",t.indexName,e)},r),Lmt=()=>(t,e)=>{for(let[r,o]of Object.entries(t.hits))if(o.objectID===e)return parseInt(r,10);return-1},Mmt=t=>(e,r)=>{let{attributesToRetrieve:o,...a}=r||{},n=e.map(u=>({indexName:t.indexName,objectID:u,...o?{attributesToRetrieve:o}:{}}));return t.transporter.read({method:Dr.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:n}},a)},Omt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/indexes/%s/rules/%s",t.indexName,e)},r),Jye=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/indexes/%s/settings",t.indexName),data:{getVersion:2}},e),Umt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/indexes/%s/synonyms/%s",t.indexName,e)},r),Xye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Yt.encode("1/indexes/%s/task/%s",t.indexName,e.toString())},r),_mt=t=>(e,r)=>Yt.createWaitablePromise(Zye(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),Zye=t=>(e,r)=>{let{createIfNotExists:o,...a}=r||{},n=o?ed.PartialUpdateObject:ed.PartialUpdateObjectNoCreate;return iQ(t)(e,n,a)},Hmt=t=>(e,r)=>{let{safe:o,autoGenerateObjectIDIfNotExist:a,batchSize:n,...u}=r||{},A=(C,T,L,U)=>Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/operation",C),data:{operation:L,destination:T}},U),(z,te)=>es(t)(z.taskID,te)),p=Math.random().toString(36).substring(7),h=`${t.indexName}_tmp_${p}`,E=x6({appId:t.appId,transporter:t.transporter,indexName:h}),I=[],D=A(t.indexName,h,"copy",{...u,scope:["settings","synonyms","rules"]});I.push(D);let x=(o?D.wait(u):D).then(()=>{let C=E(e,{...u,autoGenerateObjectIDIfNotExist:a,batchSize:n});return I.push(C),o?C.wait(u):C}).then(()=>{let C=A(h,t.indexName,"move",u);return I.push(C),o?C.wait(u):C}).then(()=>Promise.all(I)).then(([C,T,L])=>({objectIDs:T.objectIDs,taskIDs:[C.taskID,...T.taskIDs,L.taskID]}));return Yt.createWaitablePromise(x,(C,T)=>Promise.all(I.map(L=>L.wait(T))))},qmt=t=>(e,r)=>k6(t)(e,{...r,clearExistingRules:!0}),jmt=t=>(e,r)=>Q6(t)(e,{...r,clearExistingSynonyms:!0}),Gmt=t=>(e,r)=>Yt.createWaitablePromise(x6(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),x6=t=>(e,r)=>{let{autoGenerateObjectIDIfNotExist:o,...a}=r||{},n=o?ed.AddObject:ed.UpdateObject;if(n===ed.UpdateObject){for(let u of e)if(u.objectID===void 0)return Yt.createWaitablePromise(Promise.reject(Gye()))}return iQ(t)(e,n,a)},Ymt=t=>(e,r)=>k6(t)([e],r),k6=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingRules:a,...n}=r||{},u=Oa.createMappedRequestOptions(n);return o&&(u.queryParameters.forwardToReplicas=1),a&&(u.queryParameters.clearExistingRules=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/rules/batch",t.indexName),data:e},u),(A,p)=>es(t)(A.taskID,p))},Wmt=t=>(e,r)=>Q6(t)([e],r),Q6=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingSynonyms:a,replaceExistingSynonyms:n,...u}=r||{},A=Oa.createMappedRequestOptions(u);return o&&(A.queryParameters.forwardToReplicas=1),(n||a)&&(A.queryParameters.replaceExistingSynonyms=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/synonyms/batch",t.indexName),data:e},A),(p,h)=>es(t)(p.taskID,h))},$ye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/query",t.indexName),data:{query:e},cacheable:!0},r),eEe=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/facets/%s/query",t.indexName,e),data:{facetQuery:r},cacheable:!0},o),tEe=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/rules/search",t.indexName),data:{query:e}},r),rEe=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Yt.encode("1/indexes/%s/synonyms/search",t.indexName),data:{query:e}},r),Kmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Oa.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Yt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:Yt.encode("1/indexes/%s/settings",t.indexName),data:e},n),(u,A)=>es(t)(u.taskID,A))},es=t=>(e,r)=>Yt.createRetryablePromise(o=>Xye(t)(e,r).then(a=>a.status!=="published"?o():void 0)),Vmt={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",Inference:"inference",ListIndexes:"listIndexes",Logs:"logs",Personalization:"personalization",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},ed={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject",DeleteIndex:"delete",ClearIndex:"clear"},sQ={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},zmt={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Jmt={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};Rt.ApiKeyACLEnum=Vmt;Rt.BatchActionEnum=ed;Rt.ScopeEnum=sQ;Rt.StrategyEnum=zmt;Rt.SynonymEnum=Jmt;Rt.addApiKey=Hdt;Rt.assignUserID=qdt;Rt.assignUserIDs=jdt;Rt.batch=Vye;Rt.browseObjects=wmt;Rt.browseRules=Imt;Rt.browseSynonyms=Bmt;Rt.chunkedBatch=iQ;Rt.clearDictionaryEntries=Gdt;Rt.clearObjects=vmt;Rt.clearRules=Dmt;Rt.clearSynonyms=Pmt;Rt.copyIndex=nQ;Rt.copyRules=Ydt;Rt.copySettings=Wdt;Rt.copySynonyms=Kdt;Rt.createBrowsablePromise=rQ;Rt.createMissingObjectIDError=Gye;Rt.createObjectNotFoundError=Yye;Rt.createSearchClient=_dt;Rt.createValidUntilNotFoundError=Wye;Rt.customRequest=Vdt;Rt.deleteApiKey=zdt;Rt.deleteBy=Smt;Rt.deleteDictionaryEntries=Jdt;Rt.deleteIndex=bmt;Rt.deleteObject=xmt;Rt.deleteObjects=zye;Rt.deleteRule=kmt;Rt.deleteSynonym=Qmt;Rt.exists=Fmt;Rt.findAnswers=Rmt;Rt.findObject=Tmt;Rt.generateSecuredApiKey=Xdt;Rt.getApiKey=gB;Rt.getAppTask=Kye;Rt.getDictionarySettings=Zdt;Rt.getLogs=$dt;Rt.getObject=Nmt;Rt.getObjectPosition=Lmt;Rt.getObjects=Mmt;Rt.getRule=Omt;Rt.getSecuredApiKeyRemainingValidity=emt;Rt.getSettings=Jye;Rt.getSynonym=Umt;Rt.getTask=Xye;Rt.getTopUserIDs=tmt;Rt.getUserID=rmt;Rt.hasPendingMappings=nmt;Rt.initIndex=dB;Rt.listApiKeys=imt;Rt.listClusters=smt;Rt.listIndices=omt;Rt.listUserIDs=amt;Rt.moveIndex=lmt;Rt.multipleBatch=cmt;Rt.multipleGetObjects=umt;Rt.multipleQueries=Amt;Rt.multipleSearchForFacetValues=fmt;Rt.partialUpdateObject=_mt;Rt.partialUpdateObjects=Zye;Rt.removeUserID=pmt;Rt.replaceAllObjects=Hmt;Rt.replaceAllRules=qmt;Rt.replaceAllSynonyms=jmt;Rt.replaceDictionaryEntries=hmt;Rt.restoreApiKey=gmt;Rt.saveDictionaryEntries=dmt;Rt.saveObject=Gmt;Rt.saveObjects=x6;Rt.saveRule=Ymt;Rt.saveRules=k6;Rt.saveSynonym=Wmt;Rt.saveSynonyms=Q6;Rt.search=$ye;Rt.searchDictionaryEntries=mmt;Rt.searchForFacetValues=eEe;Rt.searchRules=tEe;Rt.searchSynonyms=rEe;Rt.searchUserIDs=ymt;Rt.setDictionarySettings=Emt;Rt.setSettings=Kmt;Rt.updateApiKey=Cmt;Rt.waitAppTask=hC;Rt.waitTask=es});var sEe=_((SWt,iEe)=>{iEe.exports=nEe()});var oEe=_(oQ=>{"use strict";Object.defineProperty(oQ,"__esModule",{value:!0});function Xmt(){return{debug(t,e){return Promise.resolve()},info(t,e){return Promise.resolve()},error(t,e){return Promise.resolve()}}}var Zmt={Debug:1,Info:2,Error:3};oQ.LogLevelEnum=Zmt;oQ.createNullLogger=Xmt});var lEe=_((xWt,aEe)=>{aEe.exports=oEe()});var fEe=_(F6=>{"use strict";Object.defineProperty(F6,"__esModule",{value:!0});var cEe=ve("http"),uEe=ve("https"),$mt=ve("url"),AEe={keepAlive:!0},eyt=new cEe.Agent(AEe),tyt=new uEe.Agent(AEe);function ryt({agent:t,httpAgent:e,httpsAgent:r,requesterOptions:o={}}={}){let a=e||t||eyt,n=r||t||tyt;return{send(u){return new Promise(A=>{let p=$mt.parse(u.url),h=p.query===null?p.pathname:`${p.pathname}?${p.query}`,E={...o,agent:p.protocol==="https:"?n:a,hostname:p.hostname,path:h,method:u.method,headers:{...o&&o.headers?o.headers:{},...u.headers},...p.port!==void 0?{port:p.port||""}:{}},I=(p.protocol==="https:"?uEe:cEe).request(E,T=>{let L=[];T.on("data",U=>{L=L.concat(U)}),T.on("end",()=>{clearTimeout(x),clearTimeout(C),A({status:T.statusCode||0,content:Buffer.concat(L).toString(),isTimedOut:!1})})}),D=(T,L)=>setTimeout(()=>{I.abort(),A({status:0,content:L,isTimedOut:!0})},T*1e3),x=D(u.connectTimeout,"Connection timeout"),C;I.on("error",T=>{clearTimeout(x),clearTimeout(C),A({status:0,content:T.message,isTimedOut:!1})}),I.once("response",()=>{clearTimeout(x),C=D(u.responseTimeout,"Socket timeout")}),u.data!==void 0&&I.write(u.data),I.end()})},destroy(){return a.destroy(),n.destroy(),Promise.resolve()}}}F6.createNodeHttpRequester=ryt});var hEe=_((QWt,pEe)=>{pEe.exports=fEe()});var yEe=_((FWt,mEe)=>{"use strict";var gEe=fye(),nyt=gye(),gC=Uye(),T6=cB(),R6=jye(),Ht=sEe(),iyt=lEe(),syt=hEe(),oyt=fB();function dEe(t,e,r){let o={appId:t,apiKey:e,timeouts:{connect:2,read:5,write:30},requester:syt.createNodeHttpRequester(),logger:iyt.createNullLogger(),responsesCache:gEe.createNullCache(),requestsCache:gEe.createNullCache(),hostsCache:nyt.createInMemoryCache(),userAgent:oyt.createUserAgent(T6.version).add({segment:"Node.js",version:process.versions.node})},a={...o,...r},n=()=>u=>R6.createPersonalizationClient({...o,...u,methods:{getPersonalizationStrategy:R6.getPersonalizationStrategy,setPersonalizationStrategy:R6.setPersonalizationStrategy}});return Ht.createSearchClient({...a,methods:{search:Ht.multipleQueries,searchForFacetValues:Ht.multipleSearchForFacetValues,multipleBatch:Ht.multipleBatch,multipleGetObjects:Ht.multipleGetObjects,multipleQueries:Ht.multipleQueries,copyIndex:Ht.copyIndex,copySettings:Ht.copySettings,copyRules:Ht.copyRules,copySynonyms:Ht.copySynonyms,moveIndex:Ht.moveIndex,listIndices:Ht.listIndices,getLogs:Ht.getLogs,listClusters:Ht.listClusters,multipleSearchForFacetValues:Ht.multipleSearchForFacetValues,getApiKey:Ht.getApiKey,addApiKey:Ht.addApiKey,listApiKeys:Ht.listApiKeys,updateApiKey:Ht.updateApiKey,deleteApiKey:Ht.deleteApiKey,restoreApiKey:Ht.restoreApiKey,assignUserID:Ht.assignUserID,assignUserIDs:Ht.assignUserIDs,getUserID:Ht.getUserID,searchUserIDs:Ht.searchUserIDs,listUserIDs:Ht.listUserIDs,getTopUserIDs:Ht.getTopUserIDs,removeUserID:Ht.removeUserID,hasPendingMappings:Ht.hasPendingMappings,generateSecuredApiKey:Ht.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:Ht.getSecuredApiKeyRemainingValidity,destroy:T6.destroy,clearDictionaryEntries:Ht.clearDictionaryEntries,deleteDictionaryEntries:Ht.deleteDictionaryEntries,getDictionarySettings:Ht.getDictionarySettings,getAppTask:Ht.getAppTask,replaceDictionaryEntries:Ht.replaceDictionaryEntries,saveDictionaryEntries:Ht.saveDictionaryEntries,searchDictionaryEntries:Ht.searchDictionaryEntries,setDictionarySettings:Ht.setDictionarySettings,waitAppTask:Ht.waitAppTask,customRequest:Ht.customRequest,initIndex:u=>A=>Ht.initIndex(u)(A,{methods:{batch:Ht.batch,delete:Ht.deleteIndex,findAnswers:Ht.findAnswers,getObject:Ht.getObject,getObjects:Ht.getObjects,saveObject:Ht.saveObject,saveObjects:Ht.saveObjects,search:Ht.search,searchForFacetValues:Ht.searchForFacetValues,waitTask:Ht.waitTask,setSettings:Ht.setSettings,getSettings:Ht.getSettings,partialUpdateObject:Ht.partialUpdateObject,partialUpdateObjects:Ht.partialUpdateObjects,deleteObject:Ht.deleteObject,deleteObjects:Ht.deleteObjects,deleteBy:Ht.deleteBy,clearObjects:Ht.clearObjects,browseObjects:Ht.browseObjects,getObjectPosition:Ht.getObjectPosition,findObject:Ht.findObject,exists:Ht.exists,saveSynonym:Ht.saveSynonym,saveSynonyms:Ht.saveSynonyms,getSynonym:Ht.getSynonym,searchSynonyms:Ht.searchSynonyms,browseSynonyms:Ht.browseSynonyms,deleteSynonym:Ht.deleteSynonym,clearSynonyms:Ht.clearSynonyms,replaceAllObjects:Ht.replaceAllObjects,replaceAllSynonyms:Ht.replaceAllSynonyms,searchRules:Ht.searchRules,getRule:Ht.getRule,deleteRule:Ht.deleteRule,saveRule:Ht.saveRule,saveRules:Ht.saveRules,replaceAllRules:Ht.replaceAllRules,browseRules:Ht.browseRules,clearRules:Ht.clearRules}}),initAnalytics:()=>u=>gC.createAnalyticsClient({...o,...u,methods:{addABTest:gC.addABTest,getABTest:gC.getABTest,getABTests:gC.getABTests,stopABTest:gC.stopABTest,deleteABTest:gC.deleteABTest}}),initPersonalization:n,initRecommendation:()=>u=>(a.logger.info("The `initRecommendation` method is deprecated. Use `initPersonalization` instead."),n()(u))}})}dEe.version=T6.version;mEe.exports=dEe});var L6=_((RWt,N6)=>{var EEe=yEe();N6.exports=EEe;N6.exports.default=EEe});var U6=_((NWt,IEe)=>{"use strict";var wEe=Object.getOwnPropertySymbols,lyt=Object.prototype.hasOwnProperty,cyt=Object.prototype.propertyIsEnumerable;function uyt(t){if(t==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function Ayt(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de",Object.getOwnPropertyNames(t)[0]==="5")return!1;for(var e={},r=0;r<10;r++)e["_"+String.fromCharCode(r)]=r;var o=Object.getOwnPropertyNames(e).map(function(n){return e[n]});if(o.join("")!=="0123456789")return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach(function(n){a[n]=n}),Object.keys(Object.assign({},a)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}IEe.exports=Ayt()?Object.assign:function(t,e){for(var r,o=uyt(t),a,n=1;n{"use strict";var H6=U6(),dC=60103,DEe=60106;Cn.Fragment=60107;Cn.StrictMode=60108;Cn.Profiler=60114;var PEe=60109,SEe=60110,bEe=60112;Cn.Suspense=60113;var xEe=60115,kEe=60116;typeof Symbol=="function"&&Symbol.for&&(sc=Symbol.for,dC=sc("react.element"),DEe=sc("react.portal"),Cn.Fragment=sc("react.fragment"),Cn.StrictMode=sc("react.strict_mode"),Cn.Profiler=sc("react.profiler"),PEe=sc("react.provider"),SEe=sc("react.context"),bEe=sc("react.forward_ref"),Cn.Suspense=sc("react.suspense"),xEe=sc("react.memo"),kEe=sc("react.lazy"));var sc,BEe=typeof Symbol=="function"&&Symbol.iterator;function fyt(t){return t===null||typeof t!="object"?null:(t=BEe&&t[BEe]||t["@@iterator"],typeof t=="function"?t:null)}function mB(t){for(var e="https://reactjs.org/docs/error-decoder.html?invariant="+t,r=1;r{"use strict";UEe.exports=OEe()});var K6=_((OWt,W6)=>{"use strict";var gn=W6.exports;W6.exports.default=gn;var Gn="\x1B[",yB="\x1B]",yC="\x07",cQ=";",_Ee=process.env.TERM_PROGRAM==="Apple_Terminal";gn.cursorTo=(t,e)=>{if(typeof t!="number")throw new TypeError("The `x` argument is required");return typeof e!="number"?Gn+(t+1)+"G":Gn+(e+1)+";"+(t+1)+"H"};gn.cursorMove=(t,e)=>{if(typeof t!="number")throw new TypeError("The `x` argument is required");let r="";return t<0?r+=Gn+-t+"D":t>0&&(r+=Gn+t+"C"),e<0?r+=Gn+-e+"A":e>0&&(r+=Gn+e+"B"),r};gn.cursorUp=(t=1)=>Gn+t+"A";gn.cursorDown=(t=1)=>Gn+t+"B";gn.cursorForward=(t=1)=>Gn+t+"C";gn.cursorBackward=(t=1)=>Gn+t+"D";gn.cursorLeft=Gn+"G";gn.cursorSavePosition=_Ee?"\x1B7":Gn+"s";gn.cursorRestorePosition=_Ee?"\x1B8":Gn+"u";gn.cursorGetPosition=Gn+"6n";gn.cursorNextLine=Gn+"E";gn.cursorPrevLine=Gn+"F";gn.cursorHide=Gn+"?25l";gn.cursorShow=Gn+"?25h";gn.eraseLines=t=>{let e="";for(let r=0;r[yB,"8",cQ,cQ,e,yC,t,yB,"8",cQ,cQ,yC].join("");gn.image=(t,e={})=>{let r=`${yB}1337;File=inline=1`;return e.width&&(r+=`;width=${e.width}`),e.height&&(r+=`;height=${e.height}`),e.preserveAspectRatio===!1&&(r+=";preserveAspectRatio=0"),r+":"+t.toString("base64")+yC};gn.iTerm={setCwd:(t=process.cwd())=>`${yB}50;CurrentDir=${t}${yC}`,annotation:(t,e={})=>{let r=`${yB}1337;`,o=typeof e.x<"u",a=typeof e.y<"u";if((o||a)&&!(o&&a&&typeof e.length<"u"))throw new Error("`x`, `y` and `length` must be defined when `x` or `y` is defined");return t=t.replace(/\|/g,""),r+=e.isHidden?"AddHiddenAnnotation=":"AddAnnotation=",e.length>0?r+=(o?[t,e.length,e.x,e.y]:[e.length,t]).join("|"):r+=t,r+yC}}});var qEe=_((UWt,V6)=>{"use strict";var HEe=(t,e)=>{for(let r of Reflect.ownKeys(e))Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r));return t};V6.exports=HEe;V6.exports.default=HEe});var GEe=_((_Wt,AQ)=>{"use strict";var myt=qEe(),uQ=new WeakMap,jEe=(t,e={})=>{if(typeof t!="function")throw new TypeError("Expected a function");let r,o=0,a=t.displayName||t.name||"",n=function(...u){if(uQ.set(n,++o),o===1)r=t.apply(this,u),t=null;else if(e.throw===!0)throw new Error(`Function \`${a}\` can only be called once`);return r};return myt(n,t),uQ.set(n,o),n};AQ.exports=jEe;AQ.exports.default=jEe;AQ.exports.callCount=t=>{if(!uQ.has(t))throw new Error(`The given function \`${t.name}\` is not wrapped by the \`onetime\` package`);return uQ.get(t)}});var YEe=_((HWt,fQ)=>{fQ.exports=["SIGABRT","SIGALRM","SIGHUP","SIGINT","SIGTERM"];process.platform!=="win32"&&fQ.exports.push("SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&fQ.exports.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT","SIGUNUSED")});var X6=_((qWt,wC)=>{var Ii=global.process,td=function(t){return t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function"};td(Ii)?(WEe=ve("assert"),EC=YEe(),KEe=/^win/i.test(Ii.platform),EB=ve("events"),typeof EB!="function"&&(EB=EB.EventEmitter),Ii.__signal_exit_emitter__?ks=Ii.__signal_exit_emitter__:(ks=Ii.__signal_exit_emitter__=new EB,ks.count=0,ks.emitted={}),ks.infinite||(ks.setMaxListeners(1/0),ks.infinite=!0),wC.exports=function(t,e){if(!td(global.process))return function(){};WEe.equal(typeof t,"function","a callback must be provided for exit handler"),CC===!1&&z6();var r="exit";e&&e.alwaysLast&&(r="afterexit");var o=function(){ks.removeListener(r,t),ks.listeners("exit").length===0&&ks.listeners("afterexit").length===0&&pQ()};return ks.on(r,t),o},pQ=function(){!CC||!td(global.process)||(CC=!1,EC.forEach(function(e){try{Ii.removeListener(e,hQ[e])}catch{}}),Ii.emit=gQ,Ii.reallyExit=J6,ks.count-=1)},wC.exports.unload=pQ,rd=function(e,r,o){ks.emitted[e]||(ks.emitted[e]=!0,ks.emit(e,r,o))},hQ={},EC.forEach(function(t){hQ[t]=function(){if(td(global.process)){var r=Ii.listeners(t);r.length===ks.count&&(pQ(),rd("exit",null,t),rd("afterexit",null,t),KEe&&t==="SIGHUP"&&(t="SIGINT"),Ii.kill(Ii.pid,t))}}}),wC.exports.signals=function(){return EC},CC=!1,z6=function(){CC||!td(global.process)||(CC=!0,ks.count+=1,EC=EC.filter(function(e){try{return Ii.on(e,hQ[e]),!0}catch{return!1}}),Ii.emit=zEe,Ii.reallyExit=VEe)},wC.exports.load=z6,J6=Ii.reallyExit,VEe=function(e){td(global.process)&&(Ii.exitCode=e||0,rd("exit",Ii.exitCode,null),rd("afterexit",Ii.exitCode,null),J6.call(Ii,Ii.exitCode))},gQ=Ii.emit,zEe=function(e,r){if(e==="exit"&&td(global.process)){r!==void 0&&(Ii.exitCode=r);var o=gQ.apply(this,arguments);return rd("exit",Ii.exitCode,null),rd("afterexit",Ii.exitCode,null),o}else return gQ.apply(this,arguments)}):wC.exports=function(){return function(){}};var WEe,EC,KEe,EB,ks,pQ,rd,hQ,CC,z6,J6,VEe,gQ,zEe});var XEe=_((jWt,JEe)=>{"use strict";var yyt=GEe(),Eyt=X6();JEe.exports=yyt(()=>{Eyt(()=>{process.stderr.write("\x1B[?25h")},{alwaysLast:!0})})});var Z6=_(IC=>{"use strict";var Cyt=XEe(),dQ=!1;IC.show=(t=process.stderr)=>{t.isTTY&&(dQ=!1,t.write("\x1B[?25h"))};IC.hide=(t=process.stderr)=>{t.isTTY&&(Cyt(),dQ=!0,t.write("\x1B[?25l"))};IC.toggle=(t,e)=>{t!==void 0&&(dQ=t),dQ?IC.show(e):IC.hide(e)}});var tCe=_(CB=>{"use strict";var eCe=CB&&CB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(CB,"__esModule",{value:!0});var ZEe=eCe(K6()),$Ee=eCe(Z6()),wyt=(t,{showCursor:e=!1}={})=>{let r=0,o="",a=!1,n=u=>{!e&&!a&&($Ee.default.hide(),a=!0);let A=u+` +`;A!==o&&(o=A,t.write(ZEe.default.eraseLines(r)+A),r=A.split(` +`).length)};return n.clear=()=>{t.write(ZEe.default.eraseLines(r)),o="",r=0},n.done=()=>{o="",r=0,e||($Ee.default.show(),a=!1)},n};CB.default={create:wyt}});var rCe=_((WWt,Iyt)=>{Iyt.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var sCe=_(Cl=>{"use strict";var iCe=rCe(),gA=process.env;Object.defineProperty(Cl,"_vendors",{value:iCe.map(function(t){return t.constant})});Cl.name=null;Cl.isPR=null;iCe.forEach(function(t){var e=Array.isArray(t.env)?t.env:[t.env],r=e.every(function(o){return nCe(o)});if(Cl[t.constant]=r,r)switch(Cl.name=t.name,typeof t.pr){case"string":Cl.isPR=!!gA[t.pr];break;case"object":"env"in t.pr?Cl.isPR=t.pr.env in gA&&gA[t.pr.env]!==t.pr.ne:"any"in t.pr?Cl.isPR=t.pr.any.some(function(o){return!!gA[o]}):Cl.isPR=nCe(t.pr);break;default:Cl.isPR=null}});Cl.isCI=!!(gA.CI||gA.CONTINUOUS_INTEGRATION||gA.BUILD_NUMBER||gA.RUN_ID||Cl.name);function nCe(t){return typeof t=="string"?!!gA[t]:Object.keys(t).every(function(e){return gA[e]===t[e]})}});var aCe=_((VWt,oCe)=>{"use strict";oCe.exports=sCe().isCI});var cCe=_((zWt,lCe)=>{"use strict";var Byt=t=>{let e=new Set;do for(let r of Reflect.ownKeys(t))e.add([t,r]);while((t=Reflect.getPrototypeOf(t))&&t!==Object.prototype);return e};lCe.exports=(t,{include:e,exclude:r}={})=>{let o=a=>{let n=u=>typeof u=="string"?a===u:u.test(a);return e?e.some(n):r?!r.some(n):!0};for(let[a,n]of Byt(t.constructor.prototype)){if(n==="constructor"||!o(n))continue;let u=Reflect.getOwnPropertyDescriptor(a,n);u&&typeof u.value=="function"&&(t[n]=t[n].bind(t))}return t}});var gCe=_(Hn=>{"use strict";var vC,BB,CQ,sq;typeof performance=="object"&&typeof performance.now=="function"?(uCe=performance,Hn.unstable_now=function(){return uCe.now()}):($6=Date,ACe=$6.now(),Hn.unstable_now=function(){return $6.now()-ACe});var uCe,$6,ACe;typeof window>"u"||typeof MessageChannel!="function"?(BC=null,eq=null,tq=function(){if(BC!==null)try{var t=Hn.unstable_now();BC(!0,t),BC=null}catch(e){throw setTimeout(tq,0),e}},vC=function(t){BC!==null?setTimeout(vC,0,t):(BC=t,setTimeout(tq,0))},BB=function(t,e){eq=setTimeout(t,e)},CQ=function(){clearTimeout(eq)},Hn.unstable_shouldYield=function(){return!1},sq=Hn.unstable_forceFrameRate=function(){}):(fCe=window.setTimeout,pCe=window.clearTimeout,typeof console<"u"&&(hCe=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),typeof hCe!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")),wB=!1,IB=null,mQ=-1,rq=5,nq=0,Hn.unstable_shouldYield=function(){return Hn.unstable_now()>=nq},sq=function(){},Hn.unstable_forceFrameRate=function(t){0>t||125>>1,a=t[o];if(a!==void 0&&0EQ(u,r))p!==void 0&&0>EQ(p,u)?(t[o]=p,t[A]=r,o=A):(t[o]=u,t[n]=r,o=n);else if(p!==void 0&&0>EQ(p,r))t[o]=p,t[A]=r,o=A;else break e}}return e}return null}function EQ(t,e){var r=t.sortIndex-e.sortIndex;return r!==0?r:t.id-e.id}var dA=[],Uh=[],vyt=1,oc=null,xo=3,IQ=!1,nd=!1,vB=!1;function aq(t){for(var e=ou(Uh);e!==null;){if(e.callback===null)wQ(Uh);else if(e.startTime<=t)wQ(Uh),e.sortIndex=e.expirationTime,oq(dA,e);else break;e=ou(Uh)}}function lq(t){if(vB=!1,aq(t),!nd)if(ou(dA)!==null)nd=!0,vC(cq);else{var e=ou(Uh);e!==null&&BB(lq,e.startTime-t)}}function cq(t,e){nd=!1,vB&&(vB=!1,CQ()),IQ=!0;var r=xo;try{for(aq(e),oc=ou(dA);oc!==null&&(!(oc.expirationTime>e)||t&&!Hn.unstable_shouldYield());){var o=oc.callback;if(typeof o=="function"){oc.callback=null,xo=oc.priorityLevel;var a=o(oc.expirationTime<=e);e=Hn.unstable_now(),typeof a=="function"?oc.callback=a:oc===ou(dA)&&wQ(dA),aq(e)}else wQ(dA);oc=ou(dA)}if(oc!==null)var n=!0;else{var u=ou(Uh);u!==null&&BB(lq,u.startTime-e),n=!1}return n}finally{oc=null,xo=r,IQ=!1}}var Dyt=sq;Hn.unstable_IdlePriority=5;Hn.unstable_ImmediatePriority=1;Hn.unstable_LowPriority=4;Hn.unstable_NormalPriority=3;Hn.unstable_Profiling=null;Hn.unstable_UserBlockingPriority=2;Hn.unstable_cancelCallback=function(t){t.callback=null};Hn.unstable_continueExecution=function(){nd||IQ||(nd=!0,vC(cq))};Hn.unstable_getCurrentPriorityLevel=function(){return xo};Hn.unstable_getFirstCallbackNode=function(){return ou(dA)};Hn.unstable_next=function(t){switch(xo){case 1:case 2:case 3:var e=3;break;default:e=xo}var r=xo;xo=e;try{return t()}finally{xo=r}};Hn.unstable_pauseExecution=function(){};Hn.unstable_requestPaint=Dyt;Hn.unstable_runWithPriority=function(t,e){switch(t){case 1:case 2:case 3:case 4:case 5:break;default:t=3}var r=xo;xo=t;try{return e()}finally{xo=r}};Hn.unstable_scheduleCallback=function(t,e,r){var o=Hn.unstable_now();switch(typeof r=="object"&&r!==null?(r=r.delay,r=typeof r=="number"&&0o?(t.sortIndex=r,oq(Uh,t),ou(dA)===null&&t===ou(Uh)&&(vB?CQ():vB=!0,BB(lq,r-o))):(t.sortIndex=a,oq(dA,t),nd||IQ||(nd=!0,vC(cq))),t};Hn.unstable_wrapCallback=function(t){var e=xo;return function(){var r=xo;xo=e;try{return t.apply(this,arguments)}finally{xo=r}}}});var uq=_((XWt,dCe)=>{"use strict";dCe.exports=gCe()});var mCe=_((ZWt,DB)=>{DB.exports=function(e){var r={},o=U6(),a=ln(),n=uq();function u(v){for(var P="https://reactjs.org/docs/error-decoder.html?invariant="+v,Q=1;QUe||W[Be]!==ne[Ue])return` +`+W[Be].replace(" at new "," at ");while(1<=Be&&0<=Ue);break}}}finally{Ie=!1,Error.prepareStackTrace=Q}return(v=v?v.displayName||v.name:"")?wl(v):""}var Il=[],Bi=-1;function Ns(v){return{current:v}}function Ft(v){0>Bi||(v.current=Il[Bi],Il[Bi]=null,Bi--)}function Bn(v,P){Bi++,Il[Bi]=v.current,v.current=P}var No={},ki=Ns(No),vi=Ns(!1),sa=No;function un(v,P){var Q=v.type.contextTypes;if(!Q)return No;var H=v.stateNode;if(H&&H.__reactInternalMemoizedUnmaskedChildContext===P)return H.__reactInternalMemoizedMaskedChildContext;var W={},ne;for(ne in Q)W[ne]=P[ne];return H&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=P,v.__reactInternalMemoizedMaskedChildContext=W),W}function qn(v){return v=v.childContextTypes,v!=null}function Ec(){Ft(vi),Ft(ki)}function lp(v,P,Q){if(ki.current!==No)throw Error(u(168));Bn(ki,P),Bn(vi,Q)}function oa(v,P,Q){var H=v.stateNode;if(v=P.childContextTypes,typeof H.getChildContext!="function")return Q;H=H.getChildContext();for(var W in H)if(!(W in v))throw Error(u(108,g(P)||"Unknown",W));return o({},Q,H)}function aa(v){return v=(v=v.stateNode)&&v.__reactInternalMemoizedMergedChildContext||No,sa=ki.current,Bn(ki,v),Bn(vi,vi.current),!0}function la(v,P,Q){var H=v.stateNode;if(!H)throw Error(u(169));Q?(v=oa(v,P,sa),H.__reactInternalMemoizedMergedChildContext=v,Ft(vi),Ft(ki),Bn(ki,v)):Ft(vi),Bn(vi,Q)}var Ze=null,ca=null,mu=n.unstable_now;mu();var Bl=0,dn=8;function Lo(v){if(1&v)return dn=15,1;if(2&v)return dn=14,2;if(4&v)return dn=13,4;var P=24&v;return P!==0?(dn=12,P):v&32?(dn=11,32):(P=192&v,P!==0?(dn=10,P):v&256?(dn=9,256):(P=3584&v,P!==0?(dn=8,P):v&4096?(dn=7,4096):(P=4186112&v,P!==0?(dn=6,P):(P=62914560&v,P!==0?(dn=5,P):v&67108864?(dn=4,67108864):v&134217728?(dn=3,134217728):(P=805306368&v,P!==0?(dn=2,P):1073741824&v?(dn=1,1073741824):(dn=8,v))))))}function RA(v){switch(v){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}function TA(v){switch(v){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(u(358,v))}}function Mo(v,P){var Q=v.pendingLanes;if(Q===0)return dn=0;var H=0,W=0,ne=v.expiredLanes,Be=v.suspendedLanes,Ue=v.pingedLanes;if(ne!==0)H=ne,W=dn=15;else if(ne=Q&134217727,ne!==0){var ft=ne&~Be;ft!==0?(H=Lo(ft),W=dn):(Ue&=ne,Ue!==0&&(H=Lo(Ue),W=dn))}else ne=Q&~Be,ne!==0?(H=Lo(ne),W=dn):Ue!==0&&(H=Lo(Ue),W=dn);if(H===0)return 0;if(H=31-qi(H),H=Q&((0>H?0:1<Q;Q++)P.push(v);return P}function ua(v,P,Q){v.pendingLanes|=P;var H=P-1;v.suspendedLanes&=H,v.pingedLanes&=H,v=v.eventTimes,P=31-qi(P),v[P]=Q}var qi=Math.clz32?Math.clz32:Dl,vl=Math.log,Cc=Math.LN2;function Dl(v){return v===0?32:31-(vl(v)/Cc|0)|0}var Aa=n.unstable_runWithPriority,Di=n.unstable_scheduleCallback,rs=n.unstable_cancelCallback,ja=n.unstable_shouldYield,yu=n.unstable_requestPaint,Pl=n.unstable_now,pi=n.unstable_getCurrentPriorityLevel,Dn=n.unstable_ImmediatePriority,Sl=n.unstable_UserBlockingPriority,ze=n.unstable_NormalPriority,it=n.unstable_LowPriority,vt=n.unstable_IdlePriority,ar={},ee=yu!==void 0?yu:function(){},ye=null,Le=null,ht=!1,mt=Pl(),Dt=1e4>mt?Pl:function(){return Pl()-mt};function er(){switch(pi()){case Dn:return 99;case Sl:return 98;case ze:return 97;case it:return 96;case vt:return 95;default:throw Error(u(332))}}function sn(v){switch(v){case 99:return Dn;case 98:return Sl;case 97:return ze;case 96:return it;case 95:return vt;default:throw Error(u(332))}}function ei(v,P){return v=sn(v),Aa(v,P)}function Qi(v,P,Q){return v=sn(v),Di(v,P,Q)}function Pn(){if(Le!==null){var v=Le;Le=null,rs(v)}fa()}function fa(){if(!ht&&ye!==null){ht=!0;var v=0;try{var P=ye;ei(99,function(){for(;vSn?(Tn=br,br=null):Tn=br.sibling;var Wr=Xt($e,br,pt[Sn],Jt);if(Wr===null){br===null&&(br=Tn);break}v&&br&&Wr.alternate===null&&P($e,br),je=ne(Wr,je,Sn),Yn===null?Br=Wr:Yn.sibling=Wr,Yn=Wr,br=Tn}if(Sn===pt.length)return Q($e,br),Br;if(br===null){for(;SnSn?(Tn=br,br=null):Tn=br.sibling;var ti=Xt($e,br,Wr.value,Jt);if(ti===null){br===null&&(br=Tn);break}v&&br&&ti.alternate===null&&P($e,br),je=ne(ti,je,Sn),Yn===null?Br=ti:Yn.sibling=ti,Yn=ti,br=Tn}if(Wr.done)return Q($e,br),Br;if(br===null){for(;!Wr.done;Sn++,Wr=pt.next())Wr=Tr($e,Wr.value,Jt),Wr!==null&&(je=ne(Wr,je,Sn),Yn===null?Br=Wr:Yn.sibling=Wr,Yn=Wr);return Br}for(br=H($e,br);!Wr.done;Sn++,Wr=pt.next())Wr=jn(br,$e,Sn,Wr.value,Jt),Wr!==null&&(v&&Wr.alternate!==null&&br.delete(Wr.key===null?Sn:Wr.key),je=ne(Wr,je,Sn),Yn===null?Br=Wr:Yn.sibling=Wr,Yn=Wr);return v&&br.forEach(function(Rc){return P($e,Rc)}),Br}return function($e,je,pt,Jt){var Br=typeof pt=="object"&&pt!==null&&pt.type===E&&pt.key===null;Br&&(pt=pt.props.children);var Yn=typeof pt=="object"&&pt!==null;if(Yn)switch(pt.$$typeof){case p:e:{for(Yn=pt.key,Br=je;Br!==null;){if(Br.key===Yn){switch(Br.tag){case 7:if(pt.type===E){Q($e,Br.sibling),je=W(Br,pt.props.children),je.return=$e,$e=je;break e}break;default:if(Br.elementType===pt.type){Q($e,Br.sibling),je=W(Br,pt.props),je.ref=dt($e,Br,pt),je.return=$e,$e=je;break e}}Q($e,Br);break}else P($e,Br);Br=Br.sibling}pt.type===E?(je=Ru(pt.props.children,$e.mode,Jt,pt.key),je.return=$e,$e=je):(Jt=k0(pt.type,pt.key,pt.props,null,$e.mode,Jt),Jt.ref=dt($e,je,pt),Jt.return=$e,$e=Jt)}return Be($e);case h:e:{for(Br=pt.key;je!==null;){if(je.key===Br)if(je.tag===4&&je.stateNode.containerInfo===pt.containerInfo&&je.stateNode.implementation===pt.implementation){Q($e,je.sibling),je=W(je,pt.children||[]),je.return=$e,$e=je;break e}else{Q($e,je);break}else P($e,je);je=je.sibling}je=ao(pt,$e.mode,Jt),je.return=$e,$e=je}return Be($e)}if(typeof pt=="string"||typeof pt=="number")return pt=""+pt,je!==null&&je.tag===6?(Q($e,je.sibling),je=W(je,pt),je.return=$e,$e=je):(Q($e,je),je=Zw(pt,$e.mode,Jt),je.return=$e,$e=je),Be($e);if(Cu(pt))return li($e,je,pt,Jt);if(Ee(pt))return Ea($e,je,pt,Jt);if(Yn&&Ic($e,pt),typeof pt>"u"&&!Br)switch($e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(u(152,g($e.type)||"Component"))}return Q($e,je)}}var c0=bd(!0),Dw=bd(!1),hp={},cr=Ns(hp),Li=Ns(hp),wu=Ns(hp);function pa(v){if(v===hp)throw Error(u(174));return v}function u0(v,P){Bn(wu,P),Bn(Li,v),Bn(cr,hp),v=gt(P),Ft(cr),Bn(cr,v)}function Bc(){Ft(cr),Ft(Li),Ft(wu)}function Iu(v){var P=pa(wu.current),Q=pa(cr.current);P=q(Q,v.type,P),Q!==P&&(Bn(Li,v),Bn(cr,P))}function It(v){Li.current===v&&(Ft(cr),Ft(Li))}var oi=Ns(0);function UA(v){for(var P=v;P!==null;){if(P.tag===13){var Q=P.memoizedState;if(Q!==null&&(Q=Q.dehydrated,Q===null||pr(Q)||Oe(Q)))return P}else if(P.tag===19&&P.memoizedProps.revealOrder!==void 0){if(P.flags&64)return P}else if(P.child!==null){P.child.return=P,P=P.child;continue}if(P===v)break;for(;P.sibling===null;){if(P.return===null||P.return===v)return null;P=P.return}P.sibling.return=P.return,P=P.sibling}return null}var ha=null,Uo=null,ga=!1;function A0(v,P){var Q=ya(5,null,null,0);Q.elementType="DELETED",Q.type="DELETED",Q.stateNode=P,Q.return=v,Q.flags=8,v.lastEffect!==null?(v.lastEffect.nextEffect=Q,v.lastEffect=Q):v.firstEffect=v.lastEffect=Q}function gp(v,P){switch(v.tag){case 5:return P=To(P,v.type,v.pendingProps),P!==null?(v.stateNode=P,!0):!1;case 6:return P=kA(P,v.pendingProps),P!==null?(v.stateNode=P,!0):!1;case 13:return!1;default:return!1}}function f0(v){if(ga){var P=Uo;if(P){var Q=P;if(!gp(v,P)){if(P=ia(Q),!P||!gp(v,P)){v.flags=v.flags&-1025|2,ga=!1,ha=v;return}A0(ha,Q)}ha=v,Uo=dc(P)}else v.flags=v.flags&-1025|2,ga=!1,ha=v}}function xd(v){for(v=v.return;v!==null&&v.tag!==5&&v.tag!==3&&v.tag!==13;)v=v.return;ha=v}function _A(v){if(!X||v!==ha)return!1;if(!ga)return xd(v),ga=!0,!1;var P=v.type;if(v.tag!==5||P!=="head"&&P!=="body"&&!tt(P,v.memoizedProps))for(P=Uo;P;)A0(v,P),P=ia(P);if(xd(v),v.tag===13){if(!X)throw Error(u(316));if(v=v.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(u(317));Uo=QA(v)}else Uo=ha?ia(v.stateNode):null;return!0}function p0(){X&&(Uo=ha=null,ga=!1)}var vc=[];function Dc(){for(var v=0;vne))throw Error(u(301));ne+=1,Ci=ji=null,P.updateQueue=null,Bu.current=re,v=Q(H,W)}while(vu)}if(Bu.current=xt,P=ji!==null&&ji.next!==null,Pc=0,Ci=ji=Mn=null,HA=!1,P)throw Error(u(300));return v}function Gi(){var v={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return Ci===null?Mn.memoizedState=Ci=v:Ci=Ci.next=v,Ci}function Ka(){if(ji===null){var v=Mn.alternate;v=v!==null?v.memoizedState:null}else v=ji.next;var P=Ci===null?Mn.memoizedState:Ci.next;if(P!==null)Ci=P,ji=v;else{if(v===null)throw Error(u(310));ji=v,v={memoizedState:ji.memoizedState,baseState:ji.baseState,baseQueue:ji.baseQueue,queue:ji.queue,next:null},Ci===null?Mn.memoizedState=Ci=v:Ci=Ci.next=v}return Ci}function io(v,P){return typeof P=="function"?P(v):P}function Du(v){var P=Ka(),Q=P.queue;if(Q===null)throw Error(u(311));Q.lastRenderedReducer=v;var H=ji,W=H.baseQueue,ne=Q.pending;if(ne!==null){if(W!==null){var Be=W.next;W.next=ne.next,ne.next=Be}H.baseQueue=W=ne,Q.pending=null}if(W!==null){W=W.next,H=H.baseState;var Ue=Be=ne=null,ft=W;do{var jt=ft.lane;if((Pc&jt)===jt)Ue!==null&&(Ue=Ue.next={lane:0,action:ft.action,eagerReducer:ft.eagerReducer,eagerState:ft.eagerState,next:null}),H=ft.eagerReducer===v?ft.eagerState:v(H,ft.action);else{var Ir={lane:jt,action:ft.action,eagerReducer:ft.eagerReducer,eagerState:ft.eagerState,next:null};Ue===null?(Be=Ue=Ir,ne=H):Ue=Ue.next=Ir,Mn.lanes|=jt,B0|=jt}ft=ft.next}while(ft!==null&&ft!==W);Ue===null?ne=H:Ue.next=Be,eo(H,P.memoizedState)||(We=!0),P.memoizedState=H,P.baseState=ne,P.baseQueue=Ue,Q.lastRenderedState=H}return[P.memoizedState,Q.dispatch]}function Pu(v){var P=Ka(),Q=P.queue;if(Q===null)throw Error(u(311));Q.lastRenderedReducer=v;var H=Q.dispatch,W=Q.pending,ne=P.memoizedState;if(W!==null){Q.pending=null;var Be=W=W.next;do ne=v(ne,Be.action),Be=Be.next;while(Be!==W);eo(ne,P.memoizedState)||(We=!0),P.memoizedState=ne,P.baseQueue===null&&(P.baseState=ne),Q.lastRenderedState=ne}return[ne,H]}function Va(v,P,Q){var H=P._getVersion;H=H(P._source);var W=y?P._workInProgressVersionPrimary:P._workInProgressVersionSecondary;if(W!==null?v=W===H:(v=v.mutableReadLanes,(v=(Pc&v)===v)&&(y?P._workInProgressVersionPrimary=H:P._workInProgressVersionSecondary=H,vc.push(P))),v)return Q(P._source);throw vc.push(P),Error(u(350))}function fn(v,P,Q,H){var W=Ms;if(W===null)throw Error(u(349));var ne=P._getVersion,Be=ne(P._source),Ue=Bu.current,ft=Ue.useState(function(){return Va(W,P,Q)}),jt=ft[1],Ir=ft[0];ft=Ci;var Tr=v.memoizedState,Xt=Tr.refs,jn=Xt.getSnapshot,li=Tr.source;Tr=Tr.subscribe;var Ea=Mn;return v.memoizedState={refs:Xt,source:P,subscribe:H},Ue.useEffect(function(){Xt.getSnapshot=Q,Xt.setSnapshot=jt;var $e=ne(P._source);if(!eo(Be,$e)){$e=Q(P._source),eo(Ir,$e)||(jt($e),$e=ss(Ea),W.mutableReadLanes|=$e&W.pendingLanes),$e=W.mutableReadLanes,W.entangledLanes|=$e;for(var je=W.entanglements,pt=$e;0Q?98:Q,function(){v(!0)}),ei(97qw&&(P.flags|=64,W=!0,KA(H,!1),P.lanes=33554432)}else{if(!W)if(v=UA(ne),v!==null){if(P.flags|=64,W=!0,v=v.updateQueue,v!==null&&(P.updateQueue=v,P.flags|=4),KA(H,!0),H.tail===null&&H.tailMode==="hidden"&&!ne.alternate&&!ga)return P=P.lastEffect=H.lastEffect,P!==null&&(P.nextEffect=null),null}else 2*Dt()-H.renderingStartTime>qw&&Q!==1073741824&&(P.flags|=64,W=!0,KA(H,!1),P.lanes=33554432);H.isBackwards?(ne.sibling=P.child,P.child=ne):(v=H.last,v!==null?v.sibling=ne:P.child=ne,H.last=ne)}return H.tail!==null?(v=H.tail,H.rendering=v,H.tail=v.sibling,H.lastEffect=P.lastEffect,H.renderingStartTime=Dt(),v.sibling=null,P=oi.current,Bn(oi,W?P&1|2:P&1),v):null;case 23:case 24:return Vw(),v!==null&&v.memoizedState!==null!=(P.memoizedState!==null)&&H.mode!=="unstable-defer-without-hiding"&&(P.flags|=4),null}throw Error(u(156,P.tag))}function qF(v){switch(v.tag){case 1:qn(v.type)&&Ec();var P=v.flags;return P&4096?(v.flags=P&-4097|64,v):null;case 3:if(Bc(),Ft(vi),Ft(ki),Dc(),P=v.flags,P&64)throw Error(u(285));return v.flags=P&-4097|64,v;case 5:return It(v),null;case 13:return Ft(oi),P=v.flags,P&4096?(v.flags=P&-4097|64,v):null;case 19:return Ft(oi),null;case 4:return Bc(),null;case 10:return a0(v),null;case 23:case 24:return Vw(),null;default:return null}}function m0(v,P){try{var Q="",H=P;do Q+=vw(H),H=H.return;while(H);var W=Q}catch(ne){W=` +Error generating stack: `+ne.message+` +`+ne.stack}return{value:v,source:P,stack:W}}function y0(v,P){try{console.error(P.value)}catch(Q){setTimeout(function(){throw Q})}}var jF=typeof WeakMap=="function"?WeakMap:Map;function xw(v,P,Q){Q=Ya(-1,Q),Q.tag=3,Q.payload={element:null};var H=P.value;return Q.callback=function(){Yd||(Yd=!0,jw=H),y0(v,P)},Q}function E0(v,P,Q){Q=Ya(-1,Q),Q.tag=3;var H=v.type.getDerivedStateFromError;if(typeof H=="function"){var W=P.value;Q.payload=function(){return y0(v,P),H(W)}}var ne=v.stateNode;return ne!==null&&typeof ne.componentDidCatch=="function"&&(Q.callback=function(){typeof H!="function"&&(xl===null?xl=new Set([this]):xl.add(this),y0(v,P));var Be=P.stack;this.componentDidCatch(P.value,{componentStack:Be!==null?Be:""})}),Q}var GF=typeof WeakSet=="function"?WeakSet:Set;function kw(v){var P=v.ref;if(P!==null)if(typeof P=="function")try{P(null)}catch(Q){Fu(v,Q)}else P.current=null}function Td(v,P){switch(P.tag){case 0:case 11:case 15:case 22:return;case 1:if(P.flags&256&&v!==null){var Q=v.memoizedProps,H=v.memoizedState;v=P.stateNode,P=v.getSnapshotBeforeUpdate(P.elementType===P.type?Q:to(P.type,Q),H),v.__reactInternalSnapshotBeforeUpdate=P}return;case 3:R&&P.flags&256&&hs(P.stateNode.containerInfo);return;case 5:case 6:case 4:case 17:return}throw Error(u(163))}function Ip(v,P){if(P=P.updateQueue,P=P!==null?P.lastEffect:null,P!==null){var Q=P=P.next;do{if((Q.tag&v)===v){var H=Q.destroy;Q.destroy=void 0,H!==void 0&&H()}Q=Q.next}while(Q!==P)}}function uD(v,P,Q){switch(Q.tag){case 0:case 11:case 15:case 22:if(P=Q.updateQueue,P=P!==null?P.lastEffect:null,P!==null){v=P=P.next;do{if((v.tag&3)===3){var H=v.create;v.destroy=H()}v=v.next}while(v!==P)}if(P=Q.updateQueue,P=P!==null?P.lastEffect:null,P!==null){v=P=P.next;do{var W=v;H=W.next,W=W.tag,W&4&&W&1&&(vD(Q,v),$F(Q,v)),v=H}while(v!==P)}return;case 1:v=Q.stateNode,Q.flags&4&&(P===null?v.componentDidMount():(H=Q.elementType===Q.type?P.memoizedProps:to(Q.type,P.memoizedProps),v.componentDidUpdate(H,P.memoizedState,v.__reactInternalSnapshotBeforeUpdate))),P=Q.updateQueue,P!==null&&Pd(Q,P,v);return;case 3:if(P=Q.updateQueue,P!==null){if(v=null,Q.child!==null)switch(Q.child.tag){case 5:v=Re(Q.child.stateNode);break;case 1:v=Q.child.stateNode}Pd(Q,P,v)}return;case 5:v=Q.stateNode,P===null&&Q.flags&4&&Qs(v,Q.type,Q.memoizedProps,Q);return;case 6:return;case 4:return;case 12:return;case 13:X&&Q.memoizedState===null&&(Q=Q.alternate,Q!==null&&(Q=Q.memoizedState,Q!==null&&(Q=Q.dehydrated,Q!==null&&mc(Q))));return;case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(u(163))}function AD(v,P){if(R)for(var Q=v;;){if(Q.tag===5){var H=Q.stateNode;P?op(H):Rs(Q.stateNode,Q.memoizedProps)}else if(Q.tag===6)H=Q.stateNode,P?ap(H):Ln(H,Q.memoizedProps);else if((Q.tag!==23&&Q.tag!==24||Q.memoizedState===null||Q===v)&&Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===v)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===v)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}}function Nd(v,P){if(ca&&typeof ca.onCommitFiberUnmount=="function")try{ca.onCommitFiberUnmount(Ze,P)}catch{}switch(P.tag){case 0:case 11:case 14:case 15:case 22:if(v=P.updateQueue,v!==null&&(v=v.lastEffect,v!==null)){var Q=v=v.next;do{var H=Q,W=H.destroy;if(H=H.tag,W!==void 0)if(H&4)vD(P,Q);else{H=P;try{W()}catch(ne){Fu(H,ne)}}Q=Q.next}while(Q!==v)}break;case 1:if(kw(P),v=P.stateNode,typeof v.componentWillUnmount=="function")try{v.props=P.memoizedProps,v.state=P.memoizedState,v.componentWillUnmount()}catch(ne){Fu(P,ne)}break;case 5:kw(P);break;case 4:R?gD(v,P):J&&J&&(P=P.stateNode.containerInfo,v=pc(P),bA(P,v))}}function fD(v,P){for(var Q=P;;)if(Nd(v,Q),Q.child===null||R&&Q.tag===4){if(Q===P)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===P)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}else Q.child.return=Q,Q=Q.child}function Ld(v){v.alternate=null,v.child=null,v.dependencies=null,v.firstEffect=null,v.lastEffect=null,v.memoizedProps=null,v.memoizedState=null,v.pendingProps=null,v.return=null,v.updateQueue=null}function pD(v){return v.tag===5||v.tag===3||v.tag===4}function hD(v){if(R){e:{for(var P=v.return;P!==null;){if(pD(P))break e;P=P.return}throw Error(u(160))}var Q=P;switch(P=Q.stateNode,Q.tag){case 5:var H=!1;break;case 3:P=P.containerInfo,H=!0;break;case 4:P=P.containerInfo,H=!0;break;default:throw Error(u(161))}Q.flags&16&&(gu(P),Q.flags&=-17);e:t:for(Q=v;;){for(;Q.sibling===null;){if(Q.return===null||pD(Q.return)){Q=null;break e}Q=Q.return}for(Q.sibling.return=Q.return,Q=Q.sibling;Q.tag!==5&&Q.tag!==6&&Q.tag!==18;){if(Q.flags&2||Q.child===null||Q.tag===4)continue t;Q.child.return=Q,Q=Q.child}if(!(Q.flags&2)){Q=Q.stateNode;break e}}H?Qw(v,Q,P):Fw(v,Q,P)}}function Qw(v,P,Q){var H=v.tag,W=H===5||H===6;if(W)v=W?v.stateNode:v.stateNode.instance,P?Fs(Q,v,P):Xs(Q,v);else if(H!==4&&(v=v.child,v!==null))for(Qw(v,P,Q),v=v.sibling;v!==null;)Qw(v,P,Q),v=v.sibling}function Fw(v,P,Q){var H=v.tag,W=H===5||H===6;if(W)v=W?v.stateNode:v.stateNode.instance,P?xi(Q,v,P):$n(Q,v);else if(H!==4&&(v=v.child,v!==null))for(Fw(v,P,Q),v=v.sibling;v!==null;)Fw(v,P,Q),v=v.sibling}function gD(v,P){for(var Q=P,H=!1,W,ne;;){if(!H){H=Q.return;e:for(;;){if(H===null)throw Error(u(160));switch(W=H.stateNode,H.tag){case 5:ne=!1;break e;case 3:W=W.containerInfo,ne=!0;break e;case 4:W=W.containerInfo,ne=!0;break e}H=H.return}H=!0}if(Q.tag===5||Q.tag===6)fD(v,Q),ne?SA(W,Q.stateNode):$s(W,Q.stateNode);else if(Q.tag===4){if(Q.child!==null){W=Q.stateNode.containerInfo,ne=!0,Q.child.return=Q,Q=Q.child;continue}}else if(Nd(v,Q),Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===P)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===P)return;Q=Q.return,Q.tag===4&&(H=!1)}Q.sibling.return=Q.return,Q=Q.sibling}}function Rw(v,P){if(R){switch(P.tag){case 0:case 11:case 14:case 15:case 22:Ip(3,P);return;case 1:return;case 5:var Q=P.stateNode;if(Q!=null){var H=P.memoizedProps;v=v!==null?v.memoizedProps:H;var W=P.type,ne=P.updateQueue;P.updateQueue=null,ne!==null&&Zs(Q,ne,W,v,H,P)}return;case 6:if(P.stateNode===null)throw Error(u(162));Q=P.memoizedProps,Hi(P.stateNode,v!==null?v.memoizedProps:Q,Q);return;case 3:X&&(P=P.stateNode,P.hydrate&&(P.hydrate=!1,FA(P.containerInfo)));return;case 12:return;case 13:dD(P),C0(P);return;case 19:C0(P);return;case 17:return;case 23:case 24:AD(P,P.memoizedState!==null);return}throw Error(u(163))}switch(P.tag){case 0:case 11:case 14:case 15:case 22:Ip(3,P);return;case 12:return;case 13:dD(P),C0(P);return;case 19:C0(P);return;case 3:X&&(Q=P.stateNode,Q.hydrate&&(Q.hydrate=!1,FA(Q.containerInfo)));break;case 23:case 24:return}e:if(J){switch(P.tag){case 1:case 5:case 6:case 20:break e;case 3:case 4:P=P.stateNode,bA(P.containerInfo,P.pendingChildren);break e}throw Error(u(163))}}function dD(v){v.memoizedState!==null&&(Hw=Dt(),R&&AD(v.child,!0))}function C0(v){var P=v.updateQueue;if(P!==null){v.updateQueue=null;var Q=v.stateNode;Q===null&&(Q=v.stateNode=new GF),P.forEach(function(H){var W=tR.bind(null,v,H);Q.has(H)||(Q.add(H),H.then(W,W))})}}function YF(v,P){return v!==null&&(v=v.memoizedState,v===null||v.dehydrated!==null)?(P=P.memoizedState,P!==null&&P.dehydrated===null):!1}var Md=0,Od=1,Ud=2,w0=3,_d=4;if(typeof Symbol=="function"&&Symbol.for){var I0=Symbol.for;Md=I0("selector.component"),Od=I0("selector.has_pseudo_class"),Ud=I0("selector.role"),w0=I0("selector.test_id"),_d=I0("selector.text")}function Hd(v){var P=$(v);if(P!=null){if(typeof P.memoizedProps["data-testname"]!="string")throw Error(u(364));return P}if(v=nr(v),v===null)throw Error(u(362));return v.stateNode.current}function bu(v,P){switch(P.$$typeof){case Md:if(v.type===P.value)return!0;break;case Od:e:{P=P.value,v=[v,0];for(var Q=0;Q";case Od:return":has("+(xu(v)||"")+")";case Ud:return'[role="'+v.value+'"]';case _d:return'"'+v.value+'"';case w0:return'[data-testname="'+v.value+'"]';default:throw Error(u(365,v))}}function Tw(v,P){var Q=[];v=[v,0];for(var H=0;HW&&(W=Be),Q&=~ne}if(Q=W,Q=Dt()-Q,Q=(120>Q?120:480>Q?480:1080>Q?1080:1920>Q?1920:3e3>Q?3e3:4320>Q?4320:1960*KF(Q/1960))-Q,10 component higher in the tree to provide a loading indicator or placeholder to display.`)}is!==5&&(is=2),ft=m0(ft,Ue),Xt=Be;do{switch(Xt.tag){case 3:ne=ft,Xt.flags|=4096,P&=-P,Xt.lanes|=P;var Yn=xw(Xt,ne,P);Dd(Xt,Yn);break e;case 1:ne=ft;var br=Xt.type,Sn=Xt.stateNode;if(!(Xt.flags&64)&&(typeof br.getDerivedStateFromError=="function"||Sn!==null&&typeof Sn.componentDidCatch=="function"&&(xl===null||!xl.has(Sn)))){Xt.flags|=4096,P&=-P,Xt.lanes|=P;var Tn=E0(Xt,ne,P);Dd(Xt,Tn);break e}}Xt=Xt.return}while(Xt!==null)}BD(Q)}catch(Wr){P=Wr,Mi===Q&&Q!==null&&(Mi=Q=Q.return);continue}break}while(!0)}function wD(){var v=jd.current;return jd.current=xt,v===null?xt:v}function x0(v,P){var Q=Sr;Sr|=16;var H=wD();Ms===v&&ms===P||Pp(v,P);do try{zF();break}catch(W){CD(v,W)}while(!0);if(s0(),Sr=Q,jd.current=H,Mi!==null)throw Error(u(261));return Ms=null,ms=0,is}function zF(){for(;Mi!==null;)ID(Mi)}function JF(){for(;Mi!==null&&!ja();)ID(Mi)}function ID(v){var P=SD(v.alternate,v,VA);v.memoizedProps=v.pendingProps,P===null?BD(v):Mi=P,Lw.current=null}function BD(v){var P=v;do{var Q=P.alternate;if(v=P.return,P.flags&2048){if(Q=qF(P),Q!==null){Q.flags&=2047,Mi=Q;return}v!==null&&(v.firstEffect=v.lastEffect=null,v.flags|=2048)}else{if(Q=HF(Q,P,VA),Q!==null){Mi=Q;return}if(Q=P,Q.tag!==24&&Q.tag!==23||Q.memoizedState===null||VA&1073741824||!(Q.mode&4)){for(var H=0,W=Q.child;W!==null;)H|=W.lanes|W.childLanes,W=W.sibling;Q.childLanes=H}v!==null&&!(v.flags&2048)&&(v.firstEffect===null&&(v.firstEffect=P.firstEffect),P.lastEffect!==null&&(v.lastEffect!==null&&(v.lastEffect.nextEffect=P.firstEffect),v.lastEffect=P.lastEffect),1Dt()-Hw?Pp(v,0):Uw|=Q),qo(v,P)}function tR(v,P){var Q=v.stateNode;Q!==null&&Q.delete(P),P=0,P===0&&(P=v.mode,P&2?P&4?(kc===0&&(kc=Bp),P=vn(62914560&~kc),P===0&&(P=4194304)):P=er()===99?1:2:P=1),Q=oo(),v=Vd(v,P),v!==null&&(ua(v,P,Q),qo(v,Q))}var SD;SD=function(v,P,Q){var H=P.lanes;if(v!==null)if(v.memoizedProps!==P.pendingProps||vi.current)We=!0;else if(Q&H)We=!!(v.flags&16384);else{switch(We=!1,P.tag){case 3:Fd(P),p0();break;case 5:Iu(P);break;case 1:qn(P.type)&&aa(P);break;case 4:u0(P,P.stateNode.containerInfo);break;case 10:o0(P,P.memoizedProps.value);break;case 13:if(P.memoizedState!==null)return Q&P.child.childLanes?Sw(v,P,Q):(Bn(oi,oi.current&1),P=On(v,P,Q),P!==null?P.sibling:null);Bn(oi,oi.current&1);break;case 19:if(H=(Q&P.childLanes)!==0,v.flags&64){if(H)return cD(v,P,Q);P.flags|=64}var W=P.memoizedState;if(W!==null&&(W.rendering=null,W.tail=null,W.lastEffect=null),Bn(oi,oi.current),H)break;return null;case 23:case 24:return P.lanes=0,ai(v,P,Q)}return On(v,P,Q)}else We=!1;switch(P.lanes=0,P.tag){case 2:if(H=P.type,v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),v=P.pendingProps,W=un(P,ki.current),Eu(P,Q),W=g0(null,P,H,v,W,Q),P.flags|=1,typeof W=="object"&&W!==null&&typeof W.render=="function"&&W.$$typeof===void 0){if(P.tag=1,P.memoizedState=null,P.updateQueue=null,qn(H)){var ne=!0;aa(P)}else ne=!1;P.memoizedState=W.state!==null&&W.state!==void 0?W.state:null,pp(P);var Be=H.getDerivedStateFromProps;typeof Be=="function"&&LA(P,H,Be,v),W.updater=MA,P.stateNode=W,W._reactInternals=P,no(P,H,v,Q),P=Pw(null,P,H,!0,ne,Q)}else P.tag=0,At(null,P,W,Q),P=P.child;return P;case 16:W=P.elementType;e:{switch(v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),v=P.pendingProps,ne=W._init,W=ne(W._payload),P.type=W,ne=P.tag=nR(W),v=to(W,v),ne){case 0:P=GA(null,P,W,v,Q);break e;case 1:P=lD(null,P,W,v,Q);break e;case 11:P=hr(null,P,W,v,Q);break e;case 14:P=wr(null,P,W,to(W.type,v),H,Q);break e}throw Error(u(306,W,""))}return P;case 0:return H=P.type,W=P.pendingProps,W=P.elementType===H?W:to(H,W),GA(v,P,H,W,Q);case 1:return H=P.type,W=P.pendingProps,W=P.elementType===H?W:to(H,W),lD(v,P,H,W,Q);case 3:if(Fd(P),H=P.updateQueue,v===null||H===null)throw Error(u(282));if(H=P.pendingProps,W=P.memoizedState,W=W!==null?W.element:null,l0(v,P),NA(P,H,null,Q),H=P.memoizedState.element,H===W)p0(),P=On(v,P,Q);else{if(W=P.stateNode,(ne=W.hydrate)&&(X?(Uo=dc(P.stateNode.containerInfo),ha=P,ne=ga=!0):ne=!1),ne){if(X&&(v=W.mutableSourceEagerHydrationData,v!=null))for(W=0;W=jt&&ne>=Tr&&W<=Ir&&Be<=Xt){v.splice(P,1);break}else if(H!==jt||Q.width!==ft.width||XtBe){if(!(ne!==Tr||Q.height!==ft.height||IrW)){jt>H&&(ft.width+=jt-H,ft.x=H),Irne&&(ft.height+=Tr-ne,ft.y=ne),XtQ&&(Q=Be)),Be ")+` + +No matching component was found for: + `)+v.join(" > ")}return null},r.getPublicRootInstance=function(v){if(v=v.current,!v.child)return null;switch(v.child.tag){case 5:return Re(v.child.stateNode);default:return v.child.stateNode}},r.injectIntoDevTools=function(v){if(v={bundleType:v.bundleType,version:v.version,rendererPackageName:v.rendererPackageName,rendererConfig:v.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:A.ReactCurrentDispatcher,findHostInstanceByFiber:sR,findFiberByHostInstance:v.findFiberByHostInstance||oR,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")v=!1;else{var P=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!P.isDisabled&&P.supportsFiber)try{Ze=P.inject(v),ca=P}catch{}v=!0}return v},r.observeVisibleRects=function(v,P,Q,H){if(!qt)throw Error(u(363));v=Nw(v,P);var W=Xr(v,Q,H).disconnect;return{disconnect:function(){W()}}},r.registerMutableSourceForHydration=function(v,P){var Q=P._getVersion;Q=Q(P._source),v.mutableSourceEagerHydrationData==null?v.mutableSourceEagerHydrationData=[P,Q]:v.mutableSourceEagerHydrationData.push(P,Q)},r.runWithPriority=function(v,P){var Q=Bl;try{return Bl=v,P()}finally{Bl=Q}},r.shouldSuspend=function(){return!1},r.unbatchedUpdates=function(v,P){var Q=Sr;Sr&=-2,Sr|=8;try{return v(P)}finally{Sr=Q,Sr===0&&(ku(),Pn())}},r.updateContainer=function(v,P,Q,H){var W=P.current,ne=oo(),Be=ss(W);e:if(Q){Q=Q._reactInternals;t:{if(me(Q)!==Q||Q.tag!==1)throw Error(u(170));var Ue=Q;do{switch(Ue.tag){case 3:Ue=Ue.stateNode.context;break t;case 1:if(qn(Ue.type)){Ue=Ue.stateNode.__reactInternalMemoizedMergedChildContext;break t}}Ue=Ue.return}while(Ue!==null);throw Error(u(171))}if(Q.tag===1){var ft=Q.type;if(qn(ft)){Q=oa(Q,ft,Ue);break e}}Q=Ue}else Q=No;return P.context===null?P.context=Q:P.pendingContext=Q,P=Ya(ne,Be),P.payload={element:v},H=H===void 0?null:H,H!==null&&(P.callback=H),Wa(W,P),Xa(W,Be,ne),Be},r}});var ECe=_(($Wt,yCe)=>{"use strict";yCe.exports=mCe()});var wCe=_((eKt,CCe)=>{"use strict";var Pyt={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};CCe.exports=Pyt});var DCe=_((tKt,vCe)=>{"use strict";var Syt=Object.assign||function(t){for(var e=1;e"}}]),t}(),ICe=function(){BQ(t,null,[{key:"fromJS",value:function(r){var o=r.width,a=r.height;return new t(o,a)}}]);function t(e,r){fq(this,t),this.width=e,this.height=r}return BQ(t,[{key:"fromJS",value:function(r){r(this.width,this.height)}},{key:"toString",value:function(){return""}}]),t}(),BCe=function(){function t(e,r){fq(this,t),this.unit=e,this.value=r}return BQ(t,[{key:"fromJS",value:function(r){r(this.unit,this.value)}},{key:"toString",value:function(){switch(this.unit){case au.UNIT_POINT:return String(this.value);case au.UNIT_PERCENT:return this.value+"%";case au.UNIT_AUTO:return"auto";default:return this.value+"?"}}},{key:"valueOf",value:function(){return this.value}}]),t}();vCe.exports=function(t,e){function r(u,A,p){var h=u[A];u[A]=function(){for(var E=arguments.length,I=Array(E),D=0;D1?I-1:0),x=1;x1&&arguments[1]!==void 0?arguments[1]:NaN,p=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,h=arguments.length>3&&arguments[3]!==void 0?arguments[3]:au.DIRECTION_LTR;return u.call(this,A,p,h)}),Syt({Config:e.Config,Node:e.Node,Layout:t("Layout",byt),Size:t("Size",ICe),Value:t("Value",BCe),getInstanceCount:function(){return e.getInstanceCount.apply(e,arguments)}},au)}});var PCe=_((exports,module)=>{(function(t,e){typeof define=="function"&&define.amd?define([],function(){return e}):typeof module=="object"&&module.exports?module.exports=e:(t.nbind=t.nbind||{}).init=e})(exports,function(Module,cb){typeof Module=="function"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(t,e){return function(){t&&t.apply(this,arguments);try{Module.ccall("nbind_init")}catch(r){e(r);return}e(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<"u"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT==="WEB")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT==="WORKER")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT==="NODE")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT==="SHELL")ENVIRONMENT_IS_SHELL=!0;else throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ENVIRONMENT_IS_WEB=typeof window=="object",ENVIRONMENT_IS_WORKER=typeof importScripts=="function",ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof ve=="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(e,r){nodeFS||(nodeFS={}("")),nodePath||(nodePath={}("")),e=nodePath.normalize(e);var o=nodeFS.readFileSync(e);return r?o:o.toString()},Module.readBinary=function(e){var r=Module.read(e,!0);return r.buffer||(r=new Uint8Array(r)),assert(r.buffer),r},Module.load=function(e){globalEval(read(e))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\/g,"/"):Module.thisProgram="unknown-program"),Module.arguments=process.argv.slice(2),typeof module<"u"&&(module.exports=Module),Module.inspect=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<"u"&&(Module.printErr=printErr),typeof read<"u"?Module.read=read:Module.read=function(){throw"no read() available"},Module.readBinary=function(e){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(e));var r=read(e,"binary");return assert(typeof r=="object"),r},typeof scriptArgs<"u"?Module.arguments=scriptArgs:typeof arguments<"u"&&(Module.arguments=arguments),typeof quit=="function"&&(Module.quit=function(t,e){quit(t)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.send(null),r.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.responseType="arraybuffer",r.send(null),new Uint8Array(r.response)}),Module.readAsync=function(e,r,o){var a=new XMLHttpRequest;a.open("GET",e,!0),a.responseType="arraybuffer",a.onload=function(){a.status==200||a.status==0&&a.response?r(a.response):o()},a.onerror=o,a.send(null)},typeof arguments<"u"&&(Module.arguments=arguments),typeof console<"u")Module.print||(Module.print=function(e){console.log(e)}),Module.printErr||(Module.printErr=function(e){console.warn(e)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<"u"?function(t){dump(t)}:function(t){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>"u"&&(Module.setWindowTitle=function(t){document.title=t})}else throw"Unknown runtime environment. Where are we?";function globalEval(t){eval.call(null,t)}!Module.load&&Module.read&&(Module.load=function(e){globalEval(Module.read(e))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram="./this.program"),Module.quit||(Module.quit=function(t,e){throw e}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(t){return tempRet0=t,t},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(t){STACKTOP=t},getNativeTypeSize:function(t){switch(t){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(t[t.length-1]==="*")return Runtime.QUANTUM_SIZE;if(t[0]==="i"){var e=parseInt(t.substr(1));return assert(e%8===0),e/8}else return 0}}},getNativeFieldSize:function(t){return Math.max(Runtime.getNativeTypeSize(t),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(t,e){return e==="double"||e==="i64"?t&7&&(assert((t&7)===4),t+=4):assert((t&3)===0),t},getAlignSize:function(t,e,r){return!r&&(t=="i64"||t=="double")?8:t?Math.min(e||(t?Runtime.getNativeFieldSize(t):0),Runtime.QUANTUM_SIZE):Math.min(e,8)},dynCall:function(t,e,r){return r&&r.length?Module["dynCall_"+t].apply(null,[e].concat(r)):Module["dynCall_"+t].call(null,e)},functionPointers:[],addFunction:function(t){for(var e=0;e>2],r=(e+t+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=r,r>=TOTAL_MEMORY){var o=enlargeMemory();if(!o)return HEAP32[DYNAMICTOP_PTR>>2]=e,0}return e},alignMemory:function(t,e){var r=t=Math.ceil(t/(e||16))*(e||16);return r},makeBigInt:function(t,e,r){var o=r?+(t>>>0)+ +(e>>>0)*4294967296:+(t>>>0)+ +(e|0)*4294967296;return o},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(t,e){t||abort("Assertion failed: "+e)}function getCFunc(ident){var func=Module["_"+ident];if(!func)try{func=eval("_"+ident)}catch(t){}return assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(t){var e=Runtime.stackAlloc(t.length);return writeArrayToMemory(t,e),e},stringToC:function(t){var e=0;if(t!=null&&t!==0){var r=(t.length<<2)+1;e=Runtime.stackAlloc(r),stringToUTF8(t,e,r)}return e}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(e,r,o,a,n){var u=getCFunc(e),A=[],p=0;if(a)for(var h=0;h>0]=e;break;case"i8":HEAP8[t>>0]=e;break;case"i16":HEAP16[t>>1]=e;break;case"i32":HEAP32[t>>2]=e;break;case"i64":tempI64=[e>>>0,(tempDouble=e,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t>>2]=tempI64[0],HEAP32[t+4>>2]=tempI64[1];break;case"float":HEAPF32[t>>2]=e;break;case"double":HEAPF64[t>>3]=e;break;default:abort("invalid type for setValue: "+r)}}Module.setValue=setValue;function getValue(t,e,r){switch(e=e||"i8",e.charAt(e.length-1)==="*"&&(e="i32"),e){case"i1":return HEAP8[t>>0];case"i8":return HEAP8[t>>0];case"i16":return HEAP16[t>>1];case"i32":return HEAP32[t>>2];case"i64":return HEAP32[t>>2];case"float":return HEAPF32[t>>2];case"double":return HEAPF64[t>>3];default:abort("invalid type for setValue: "+e)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(t,e,r,o){var a,n;typeof t=="number"?(a=!0,n=t):(a=!1,n=t.length);var u=typeof e=="string"?e:null,A;if(r==ALLOC_NONE?A=o:A=[typeof _malloc=="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][r===void 0?ALLOC_STATIC:r](Math.max(n,u?1:e.length)),a){var o=A,p;for(assert((A&3)==0),p=A+(n&-4);o>2]=0;for(p=A+n;o>0]=0;return A}if(u==="i8")return t.subarray||t.slice?HEAPU8.set(t,A):HEAPU8.set(new Uint8Array(t),A),A;for(var h=0,E,I,D;h>0],r|=o,!(o==0&&!e||(a++,e&&a==e)););e||(e=a);var n="";if(r<128){for(var u=1024,A;e>0;)A=String.fromCharCode.apply(String,HEAPU8.subarray(t,t+Math.min(e,u))),n=n?n+A:A,t+=u,e-=u;return n}return Module.UTF8ToString(t)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(t){for(var e="";;){var r=HEAP8[t++>>0];if(!r)return e;e+=String.fromCharCode(r)}}Module.AsciiToString=AsciiToString;function stringToAscii(t,e){return writeAsciiToMemory(t,e,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0;function UTF8ArrayToString(t,e){for(var r=e;t[r];)++r;if(r-e>16&&t.subarray&&UTF8Decoder)return UTF8Decoder.decode(t.subarray(e,r));for(var o,a,n,u,A,p,h="";;){if(o=t[e++],!o)return h;if(!(o&128)){h+=String.fromCharCode(o);continue}if(a=t[e++]&63,(o&224)==192){h+=String.fromCharCode((o&31)<<6|a);continue}if(n=t[e++]&63,(o&240)==224?o=(o&15)<<12|a<<6|n:(u=t[e++]&63,(o&248)==240?o=(o&7)<<18|a<<12|n<<6|u:(A=t[e++]&63,(o&252)==248?o=(o&3)<<24|a<<18|n<<12|u<<6|A:(p=t[e++]&63,o=(o&1)<<30|a<<24|n<<18|u<<12|A<<6|p))),o<65536)h+=String.fromCharCode(o);else{var E=o-65536;h+=String.fromCharCode(55296|E>>10,56320|E&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(t){return UTF8ArrayToString(HEAPU8,t)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(t,e,r,o){if(!(o>0))return 0;for(var a=r,n=r+o-1,u=0;u=55296&&A<=57343&&(A=65536+((A&1023)<<10)|t.charCodeAt(++u)&1023),A<=127){if(r>=n)break;e[r++]=A}else if(A<=2047){if(r+1>=n)break;e[r++]=192|A>>6,e[r++]=128|A&63}else if(A<=65535){if(r+2>=n)break;e[r++]=224|A>>12,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=2097151){if(r+3>=n)break;e[r++]=240|A>>18,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=67108863){if(r+4>=n)break;e[r++]=248|A>>24,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else{if(r+5>=n)break;e[r++]=252|A>>30,e[r++]=128|A>>24&63,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}}return e[r]=0,r-a}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(t,e,r){return stringToUTF8Array(t,HEAPU8,e,r)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(t){for(var e=0,r=0;r=55296&&o<=57343&&(o=65536+((o&1023)<<10)|t.charCodeAt(++r)&1023),o<=127?++e:o<=2047?e+=2:o<=65535?e+=3:o<=2097151?e+=4:o<=67108863?e+=5:e+=6}return e}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0;function demangle(t){var e=Module.___cxa_demangle||Module.__cxa_demangle;if(e){try{var r=t.substr(1),o=lengthBytesUTF8(r)+1,a=_malloc(o);stringToUTF8(r,a,o);var n=_malloc(4),u=e(a,0,0,n);if(getValue(n,"i32")===0&&u)return Pointer_stringify(u)}catch{}finally{a&&_free(a),n&&_free(n),u&&_free(u)}return t}return Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"),t}function demangleAll(t){var e=/__Z[\w\d_]+/g;return t.replace(e,function(r){var o=demangle(r);return r===o?r:r+" ["+o+"]"})}function jsStackTrace(){var t=new Error;if(!t.stack){try{throw new Error(0)}catch(e){t=e}if(!t.stack)return"(no stack trace available)"}return t.stack.toString()}function stackTrace(){var t=jsStackTrace();return Module.extraStackTrace&&(t+=` +`+Module.extraStackTrace()),demangleAll(t)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY0;){var e=t.shift();if(typeof e=="function"){e();continue}var r=e.func;typeof r=="number"?e.arg===void 0?Module.dynCall_v(r):Module.dynCall_vi(r,e.arg):r(e.arg===void 0?null:e.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(t){__ATPRERUN__.unshift(t)}Module.addOnPreRun=addOnPreRun;function addOnInit(t){__ATINIT__.unshift(t)}Module.addOnInit=addOnInit;function addOnPreMain(t){__ATMAIN__.unshift(t)}Module.addOnPreMain=addOnPreMain;function addOnExit(t){__ATEXIT__.unshift(t)}Module.addOnExit=addOnExit;function addOnPostRun(t){__ATPOSTRUN__.unshift(t)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(t,e,r){var o=r>0?r:lengthBytesUTF8(t)+1,a=new Array(o),n=stringToUTF8Array(t,a,0,a.length);return e&&(a.length=n),a}Module.intArrayFromString=intArrayFromString;function intArrayToString(t){for(var e=[],r=0;r255&&(o&=255),e.push(String.fromCharCode(o))}return e.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(t,e,r){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var o,a;r&&(a=e+lengthBytesUTF8(t),o=HEAP8[a]),stringToUTF8(t,e,1/0),r&&(HEAP8[a]=o)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(t,e){HEAP8.set(t,e)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(t,e,r){for(var o=0;o>0]=t.charCodeAt(o);r||(HEAP8[e>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function t(e,r){var o=e>>>16,a=e&65535,n=r>>>16,u=r&65535;return a*u+(o*u+a*n<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(t){return froundBuffer[0]=t,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(t){t=t>>>0;for(var e=0;e<32;e++)if(t&1<<31-e)return e;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(t){return t<0?Math.ceil(t):Math.floor(t)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(t){return t}function addRunDependency(t){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(t){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var e=dependenciesFulfilled;dependenciesFulfilled=null,e()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(t,e,r,o,a,n,u,A){return _nbind.callbackSignatureList[t].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(t,e,r,o,a,n,u,A){return ASM_CONSTS[t](e,r,o,a,n,u,A)}function _emscripten_asm_const_iiiii(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiidddddd(t,e,r,o,a,n,u,A,p){return ASM_CONSTS[t](e,r,o,a,n,u,A,p)}function _emscripten_asm_const_iiididi(t,e,r,o,a,n,u){return ASM_CONSTS[t](e,r,o,a,n,u)}function _emscripten_asm_const_iiii(t,e,r,o){return ASM_CONSTS[t](e,r,o)}function _emscripten_asm_const_iiiid(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiiiii(t,e,r,o,a,n){return ASM_CONSTS[t](e,r,o,a,n)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(t,e){__ATEXIT__.unshift({func:t,arg:e})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr("missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj"),abort(-1)}function __decorate(t,e,r,o){var a=arguments.length,n=a<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,r):o,u;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")n=Reflect.decorate(t,e,r,o);else for(var A=t.length-1;A>=0;A--)(u=t[A])&&(n=(a<3?u(n):a>3?u(e,r,n):u(e,r))||n);return a>3&&n&&Object.defineProperty(e,r,n),n}function _defineHidden(t){return function(e,r){Object.defineProperty(e,r,{configurable:!1,enumerable:!1,value:t,writable:!0})}}var _nbind={};function __nbind_free_external(t){_nbind.externalList[t].dereference(t)}function __nbind_reference_external(t){_nbind.externalList[t].reference()}function _llvm_stackrestore(t){var e=_llvm_stacksave,r=e.LLVM_SAVEDSTACKS[t];e.LLVM_SAVEDSTACKS.splice(t,1),Runtime.stackRestore(r)}function __nbind_register_pool(t,e,r,o){_nbind.Pool.pageSize=t,_nbind.Pool.usedPtr=e/4,_nbind.Pool.rootPtr=r,_nbind.Pool.pagePtr=o/4,HEAP32[e/4]=16909060,HEAP8[e]==1&&(_nbind.bigEndian=!0),HEAP32[e/4]=0,_nbind.makeTypeKindTbl=(n={},n[1024]=_nbind.PrimitiveType,n[64]=_nbind.Int64Type,n[2048]=_nbind.BindClass,n[3072]=_nbind.BindClassPtr,n[4096]=_nbind.SharedClassPtr,n[5120]=_nbind.ArrayType,n[6144]=_nbind.ArrayType,n[7168]=_nbind.CStringType,n[9216]=_nbind.CallbackType,n[10240]=_nbind.BindType,n),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,"cbFunction &":_nbind.CallbackType,"const cbFunction &":_nbind.CallbackType,"const std::string &":_nbind.StringType,"std::string":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var a=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:""});a.proto=Module,_nbind.BindClass.list.push(a);var n}function _emscripten_set_main_loop_timing(t,e){if(Browser.mainLoop.timingMode=t,Browser.mainLoop.timingValue=e,!Browser.mainLoop.func)return 1;if(t==0)Browser.mainLoop.scheduler=function(){var u=Math.max(0,Browser.mainLoop.tickStartTime+e-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,u)},Browser.mainLoop.method="timeout";else if(t==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method="rAF";else if(t==2){if(!window.setImmediate){let n=function(u){u.source===window&&u.data===o&&(u.stopPropagation(),r.shift()())};var a=n,r=[],o="setimmediate";window.addEventListener("message",n,!0),window.setImmediate=function(A){r.push(A),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(A),window.postMessage({target:o})):window.postMessage(o,"*")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(t,e,r,o,a){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),Browser.mainLoop.func=t,Browser.mainLoop.arg=o;var n;typeof o<"u"?n=function(){Module.dynCall_vi(t,o)}:n=function(){Module.dynCall_v(t)};var u=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var p=Date.now(),h=Browser.mainLoop.queue.shift();if(h.func(h.arg),Browser.mainLoop.remainingBlockers){var E=Browser.mainLoop.remainingBlockers,I=E%1==0?E-1:Math.floor(E);h.counted?Browser.mainLoop.remainingBlockers=I:(I=I+.5,Browser.mainLoop.remainingBlockers=(8*E+I)/9)}if(console.log('main loop blocker "'+h.name+'" took '+(Date.now()-p)+" ms"),Browser.mainLoop.updateStatus(),u1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method==="timeout"&&Module.ctx&&(Module.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Browser.mainLoop.method=""),Browser.mainLoop.runIter(n),!(u0?_emscripten_set_main_loop_timing(0,1e3/e):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),r)throw"SimulateInfiniteLoop"}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var t=Browser.mainLoop.timingMode,e=Browser.mainLoop.timingValue,r=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(r,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(t,e),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var t=Module.statusMessage||"Please wait...",e=Browser.mainLoop.remainingBlockers,r=Browser.mainLoop.expectedBlockers;e?e"u"&&(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),Module.noImageDecoding=!0);var t={};t.canHandle=function(n){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(n)},t.handle=function(n,u,A,p){var h=null;if(Browser.hasBlobConstructor)try{h=new Blob([n],{type:Browser.getMimetype(u)}),h.size!==n.length&&(h=new Blob([new Uint8Array(n).buffer],{type:Browser.getMimetype(u)}))}catch(x){Runtime.warnOnce("Blob constructor present but fails: "+x+"; falling back to blob builder")}if(!h){var E=new Browser.BlobBuilder;E.append(new Uint8Array(n).buffer),h=E.getBlob()}var I=Browser.URLObject.createObjectURL(h),D=new Image;D.onload=function(){assert(D.complete,"Image "+u+" could not be decoded");var C=document.createElement("canvas");C.width=D.width,C.height=D.height;var T=C.getContext("2d");T.drawImage(D,0,0),Module.preloadedImages[u]=C,Browser.URLObject.revokeObjectURL(I),A&&A(n)},D.onerror=function(C){console.log("Image "+I+" could not be decoded"),p&&p()},D.src=I},Module.preloadPlugins.push(t);var e={};e.canHandle=function(n){return!Module.noAudioDecoding&&n.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},e.handle=function(n,u,A,p){var h=!1;function E(T){h||(h=!0,Module.preloadedAudios[u]=T,A&&A(n))}function I(){h||(h=!0,Module.preloadedAudios[u]=new Audio,p&&p())}if(Browser.hasBlobConstructor){try{var D=new Blob([n],{type:Browser.getMimetype(u)})}catch{return I()}var x=Browser.URLObject.createObjectURL(D),C=new Audio;C.addEventListener("canplaythrough",function(){E(C)},!1),C.onerror=function(L){if(h)return;console.log("warning: browser could not fully decode audio "+u+", trying slower base64 approach");function U(z){for(var te="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",le="=",ce="",ue=0,Ce=0,he=0;he=6;){var De=ue>>Ce-6&63;Ce-=6,ce+=te[De]}return Ce==2?(ce+=te[(ue&3)<<4],ce+=le+le):Ce==4&&(ce+=te[(ue&15)<<2],ce+=le),ce}C.src="data:audio/x-"+u.substr(-3)+";base64,"+U(n),E(C)},C.src=x,Browser.safeSetTimeout(function(){E(C)},1e4)}else return I()},Module.preloadPlugins.push(e);function r(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var o=Module.canvas;o&&(o.requestPointerLock=o.requestPointerLock||o.mozRequestPointerLock||o.webkitRequestPointerLock||o.msRequestPointerLock||function(){},o.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},o.exitPointerLock=o.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",r,!1),document.addEventListener("mozpointerlockchange",r,!1),document.addEventListener("webkitpointerlockchange",r,!1),document.addEventListener("mspointerlockchange",r,!1),Module.elementPointerLock&&o.addEventListener("click",function(a){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),a.preventDefault())},!1))},createContext:function(t,e,r,o){if(e&&Module.ctx&&t==Module.canvas)return Module.ctx;var a,n;if(e){var u={antialias:!1,alpha:!1};if(o)for(var A in o)u[A]=o[A];n=GL.createContext(t,u),n&&(a=GL.getContext(n).GLctx)}else a=t.getContext("2d");return a?(r&&(e||assert(typeof GLctx>"u","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),Module.ctx=a,e&&GL.makeContextCurrent(n),Module.useWebGL=e,Browser.moduleContextCreatedCallbacks.forEach(function(p){p()}),Browser.init()),a):null},destroyContext:function(t,e,r){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(t,e,r){Browser.lockPointer=t,Browser.resizeCanvas=e,Browser.vrDevice=r,typeof Browser.lockPointer>"u"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>"u"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>"u"&&(Browser.vrDevice=null);var o=Module.canvas;function a(){Browser.isFullscreen=!1;var u=o.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===u?(o.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},o.exitFullscreen=o.exitFullscreen.bind(document),Browser.lockPointer&&o.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(u.parentNode.insertBefore(o,u),u.parentNode.removeChild(u),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(o)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",a,!1),document.addEventListener("mozfullscreenchange",a,!1),document.addEventListener("webkitfullscreenchange",a,!1),document.addEventListener("MSFullscreenChange",a,!1));var n=document.createElement("div");o.parentNode.insertBefore(n,o),n.appendChild(o),n.requestFullscreen=n.requestFullscreen||n.mozRequestFullScreen||n.msRequestFullscreen||(n.webkitRequestFullscreen?function(){n.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(n.webkitRequestFullScreen?function(){n.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),r?n.requestFullscreen({vrDisplay:r}):n.requestFullscreen()},requestFullScreen:function(t,e,r){return Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."),Browser.requestFullScreen=function(o,a,n){return Browser.requestFullscreen(o,a,n)},Browser.requestFullscreen(t,e,r)},nextRAF:0,fakeRequestAnimationFrame:function(t){var e=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=e+1e3/60;else for(;e+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var r=Math.max(Browser.nextRAF-e,0);setTimeout(t,r)},requestAnimationFrame:function t(e){typeof window>"u"?Browser.fakeRequestAnimationFrame(e):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(e))},safeCallback:function(t){return function(){if(!ABORT)return t.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var t=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],t.forEach(function(e){e()})}},safeRequestAnimationFrame:function(t){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))})},safeSetTimeout:function(t,e){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))},e)},safeSetInterval:function(t,e){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&t()},e)},getMimetype:function(t){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[t.substr(t.lastIndexOf(".")+1)]},getUserMedia:function(t){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(t)},getMovementX:function(t){return t.movementX||t.mozMovementX||t.webkitMovementX||0},getMovementY:function(t){return t.movementY||t.mozMovementY||t.webkitMovementY||0},getMouseWheelDelta:function(t){var e=0;switch(t.type){case"DOMMouseScroll":e=t.detail;break;case"mousewheel":e=t.wheelDelta;break;case"wheel":e=t.deltaY;break;default:throw"unrecognized mouse wheel event: "+t.type}return e},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(t){if(Browser.pointerLock)t.type!="mousemove"&&"mozMovementX"in t?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(t),Browser.mouseMovementY=Browser.getMovementY(t)),typeof SDL<"u"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var e=Module.canvas.getBoundingClientRect(),r=Module.canvas.width,o=Module.canvas.height,a=typeof window.scrollX<"u"?window.scrollX:window.pageXOffset,n=typeof window.scrollY<"u"?window.scrollY:window.pageYOffset;if(t.type==="touchstart"||t.type==="touchend"||t.type==="touchmove"){var u=t.touch;if(u===void 0)return;var A=u.pageX-(a+e.left),p=u.pageY-(n+e.top);A=A*(r/e.width),p=p*(o/e.height);var h={x:A,y:p};if(t.type==="touchstart")Browser.lastTouches[u.identifier]=h,Browser.touches[u.identifier]=h;else if(t.type==="touchend"||t.type==="touchmove"){var E=Browser.touches[u.identifier];E||(E=h),Browser.lastTouches[u.identifier]=E,Browser.touches[u.identifier]=h}return}var I=t.pageX-(a+e.left),D=t.pageY-(n+e.top);I=I*(r/e.width),D=D*(o/e.height),Browser.mouseMovementX=I-Browser.mouseX,Browser.mouseMovementY=D-Browser.mouseY,Browser.mouseX=I,Browser.mouseY=D}},asyncLoad:function(t,e,r,o){var a=o?"":"al "+t;Module.readAsync(t,function(n){assert(n,'Loading data file "'+t+'" failed (no arrayBuffer).'),e(new Uint8Array(n)),a&&removeRunDependency(a)},function(n){if(r)r();else throw'Loading data file "'+t+'" failed.'}),a&&addRunDependency(a)},resizeListeners:[],updateResizeListeners:function(){var t=Module.canvas;Browser.resizeListeners.forEach(function(e){e(t.width,t.height)})},setCanvasSize:function(t,e,r){var o=Module.canvas;Browser.updateCanvasDimensions(o,t,e),r||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<"u"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<"u"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},updateCanvasDimensions:function(t,e,r){e&&r?(t.widthNative=e,t.heightNative=r):(e=t.widthNative,r=t.heightNative);var o=e,a=r;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(o/a>2];return e},getStr:function(){var t=Pointer_stringify(SYSCALLS.get());return t},get64:function(){var t=SYSCALLS.get(),e=SYSCALLS.get();return t>=0?assert(e===0):assert(e===-1),t},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD();return FS.close(r),0}catch(o){return(typeof FS>"u"||!(o instanceof FS.ErrnoError))&&abort(o),-o.errno}}function ___syscall54(t,e){SYSCALLS.varargs=e;try{return 0}catch(r){return(typeof FS>"u"||!(r instanceof FS.ErrnoError))&&abort(r),-r.errno}}function _typeModule(t){var e=[[0,1,"X"],[1,1,"const X"],[128,1,"X *"],[256,1,"X &"],[384,1,"X &&"],[512,1,"std::shared_ptr"],[640,1,"std::unique_ptr"],[5120,1,"std::vector"],[6144,2,"std::array"],[9216,-1,"std::function"]];function r(p,h,E,I,D,x){if(h==1){var C=I&896;(C==128||C==256||C==384)&&(p="X const")}var T;return x?T=E.replace("X",p).replace("Y",D):T=p.replace("X",E).replace("Y",D),T.replace(/([*&]) (?=[*&])/g,"$1")}function o(p,h,E,I,D){throw new Error(p+" type "+E.replace("X",h+"?")+(I?" with flag "+I:"")+" in "+D)}function a(p,h,E,I,D,x,C,T){x===void 0&&(x="X"),T===void 0&&(T=1);var L=E(p);if(L)return L;var U=I(p),z=U.placeholderFlag,te=e[z];C&&te&&(x=r(C[2],C[0],x,te[0],"?",!0));var le;z==0&&(le="Unbound"),z>=10&&(le="Corrupt"),T>20&&(le="Deeply nested"),le&&o(le,p,x,z,D||"?");var ce=U.paramList[0],ue=a(ce,h,E,I,D,x,te,T+1),Ce,he={flags:te[0],id:p,name:"",paramList:[ue]},De=[],Ee="?";switch(U.placeholderFlag){case 1:Ce=ue.spec;break;case 2:if((ue.flags&15360)==1024&&ue.spec.ptrSize==1){he.flags=7168;break}case 3:case 6:case 5:Ce=ue.spec,ue.flags&15360;break;case 8:Ee=""+U.paramList[1],he.paramList.push(U.paramList[1]);break;case 9:for(var g=0,me=U.paramList[1];g>2]=t),t}function _llvm_stacksave(){var t=_llvm_stacksave;return t.LLVM_SAVEDSTACKS||(t.LLVM_SAVEDSTACKS=[]),t.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),t.LLVM_SAVEDSTACKS.length-1}function ___syscall140(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=SYSCALLS.get(),u=SYSCALLS.get(),A=a;return FS.llseek(r,A,u),HEAP32[n>>2]=r.position,r.getdents&&A===0&&u===0&&(r.getdents=null),0}catch(p){return(typeof FS>"u"||!(p instanceof FS.ErrnoError))&&abort(p),-p.errno}}function ___syscall146(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.get(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(E,I){var D=___syscall146.buffers[E];assert(D),I===0||I===10?((E===1?Module.print:Module.printErr)(UTF8ArrayToString(D,0)),D.length=0):D.push(I)});for(var u=0;u>2],p=HEAP32[o+(u*8+4)>>2],h=0;h"u"||!(E instanceof FS.ErrnoError))&&abort(E),-E.errno}}function __nbind_finish(){for(var t=0,e=_nbind.BindClass.list;tt.pageSize/2||e>t.pageSize-r){var o=_nbind.typeNameTbl.NBind.proto;return o.lalloc(e)}else return HEAPU32[t.usedPtr]=r+e,t.rootPtr+r},t.lreset=function(e,r){var o=HEAPU32[t.pagePtr];if(o){var a=_nbind.typeNameTbl.NBind.proto;a.lreset(e,r)}else HEAPU32[t.usedPtr]=e},t}();_nbind.Pool=Pool;function constructType(t,e){var r=t==10240?_nbind.makeTypeNameTbl[e.name]||_nbind.BindType:_nbind.makeTypeKindTbl[t],o=new r(e);return typeIdTbl[e.id]=o,_nbind.typeNameTbl[e.name]=o,o}_nbind.constructType=constructType;function getType(t){return typeIdTbl[t]}_nbind.getType=getType;function queryType(t){var e=HEAPU8[t],r=_nbind.structureList[e][1];t/=4,r<0&&(++t,r=HEAPU32[t]+1);var o=Array.prototype.slice.call(HEAPU32.subarray(t+1,t+1+r));return e==9&&(o=[o[0],o.slice(1)]),{paramList:o,placeholderFlag:e}}_nbind.queryType=queryType;function getTypes(t,e){return t.map(function(r){return typeof r=="number"?_nbind.getComplexType(r,constructType,getType,queryType,e):_nbind.typeNameTbl[r]})}_nbind.getTypes=getTypes;function readTypeIdList(t,e){return Array.prototype.slice.call(HEAPU32,t/4,t/4+e)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(t){for(var e=t;HEAPU8[e++];);return String.fromCharCode.apply("",HEAPU8.subarray(t,e-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(t){var e={};if(t)for(;;){var r=HEAPU32[t/4];if(!r)break;e[readAsciiString(r)]=!0,t+=4}return e}_nbind.readPolicyList=readPolicyList;function getDynCall(t,e){var r={float32_t:"d",float64_t:"d",int64_t:"d",uint64_t:"d",void:"v"},o=t.map(function(n){return r[n.name]||"i"}).join(""),a=Module["dynCall_"+o];if(!a)throw new Error("dynCall_"+o+" not found for "+e+"("+t.map(function(n){return n.name}).join(", ")+")");return a}_nbind.getDynCall=getDynCall;function addMethod(t,e,r,o){var a=t[e];t.hasOwnProperty(e)&&a?((a.arity||a.arity===0)&&(a=_nbind.makeOverloader(a,a.arity),t[e]=a),a.addMethod(r,o)):(r.arity=o,t[e]=r)}_nbind.addMethod=addMethod;function throwError(t){throw new Error(t)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.heap=HEAPU32,r.ptrSize=4,r}return e.prototype.needsWireRead=function(r){return!!this.wireRead||!!this.makeWireRead},e.prototype.needsWireWrite=function(r){return!!this.wireWrite||!!this.makeWireWrite},e}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this,a=r.flags&32?{32:HEAPF32,64:HEAPF64}:r.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return o.heap=a[r.ptrSize*8],o.ptrSize=r.ptrSize,o}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a=="number")return a;throw new Error("Type mismatch")}},e}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(t,e){if(t==null){if(e&&e.Nullable)return 0;throw new Error("Type mismatch")}if(e&&e.Strict){if(typeof t!="string")throw new Error("Type mismatch")}else t=t.toString();var r=Module.lengthBytesUTF8(t)+1,o=_nbind.Pool.lalloc(r);return Module.stringToUTF8Array(t,HEAPU8,o,r),o}_nbind.pushCString=pushCString;function popCString(t){return t===0?null:Module.Pointer_stringify(t)}_nbind.popCString=popCString;var CStringType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popCString,r.wireWrite=pushCString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushCString(a,o)}},e}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=function(o){return!!o},r}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireRead=function(r){return"!!("+r+")"},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a=="boolean")return a;throw new Error("Type mismatch")}||r},e}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function t(){}return t.prototype.persist=function(){this.__nbindState|=1},t}();_nbind.Wrapper=Wrapper;function makeBound(t,e){var r=function(o){__extends(a,o);function a(n,u,A,p){var h=o.call(this)||this;if(!(h instanceof a))return new(Function.prototype.bind.apply(a,Array.prototype.concat.apply([null],arguments)));var E=u,I=A,D=p;if(n!==_nbind.ptrMarker){var x=h.__nbindConstructor.apply(h,arguments);E=4608,D=HEAPU32[x/4],I=HEAPU32[x/4+1]}var C={configurable:!0,enumerable:!1,value:null,writable:!1},T={__nbindFlags:E,__nbindPtr:I};D&&(T.__nbindShared=D,_nbind.mark(h));for(var L=0,U=Object.keys(T);L>=1;var r=_nbind.valueList[t];return _nbind.valueList[t]=firstFreeValue,firstFreeValue=t,r}else{if(e)return _nbind.popShared(t,e);throw new Error("Invalid value slot "+t)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(t){return typeof t=="number"?t:pushValue(t)*4096+valueBase}function pop64(t){return t=3?u=Buffer.from(n):u=new Buffer(n),u.copy(o)}else getBuffer(o).set(n)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var t=0,e=dirtyList;t>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(t,e,r,o,a,n){try{Module.dynCall_viiiii(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_vif(t,e,r){try{Module.dynCall_vif(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_vid(t,e,r){try{Module.dynCall_vid(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_fiff(t,e,r,o){try{return Module.dynCall_fiff(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_vi(t,e){try{Module.dynCall_vi(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_vii(t,e,r){try{Module.dynCall_vii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_ii(t,e){try{return Module.dynCall_ii(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_viddi(t,e,r,o,a){try{Module.dynCall_viddi(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}function invoke_vidd(t,e,r,o){try{Module.dynCall_vidd(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_iiii(t,e,r,o){try{return Module.dynCall_iiii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_diii(t,e,r,o){try{return Module.dynCall_diii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_di(t,e){try{return Module.dynCall_di(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_iid(t,e,r){try{return Module.dynCall_iid(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_iii(t,e,r){try{return Module.dynCall_iii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_viiddi(t,e,r,o,a,n){try{Module.dynCall_viiddi(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_viiiiii(t,e,r,o,a,n,u){try{Module.dynCall_viiiiii(t,e,r,o,a,n,u)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_dii(t,e,r){try{return Module.dynCall_dii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_i(t){try{return Module.dynCall_i(t)}catch(e){if(typeof e!="number"&&e!=="longjmp")throw e;Module.setThrew(1,0)}}function invoke_iiiiii(t,e,r,o,a,n){try{return Module.dynCall_iiiiii(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_viiid(t,e,r,o,a){try{Module.dynCall_viiid(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}function invoke_viififi(t,e,r,o,a,n,u){try{Module.dynCall_viififi(t,e,r,o,a,n,u)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_viii(t,e,r,o){try{Module.dynCall_viii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_v(t){try{Module.dynCall_v(t)}catch(e){if(typeof e!="number"&&e!=="longjmp")throw e;Module.setThrew(1,0)}}function invoke_viid(t,e,r,o){try{Module.dynCall_viid(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_idd(t,e,r){try{return Module.dynCall_idd(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_viiii(t,e,r,o,a){try{Module.dynCall_viiii(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(t,e,r){var o=new t.Int8Array(r),a=new t.Int16Array(r),n=new t.Int32Array(r),u=new t.Uint8Array(r),A=new t.Uint16Array(r),p=new t.Uint32Array(r),h=new t.Float32Array(r),E=new t.Float64Array(r),I=e.DYNAMICTOP_PTR|0,D=e.tempDoublePtr|0,x=e.ABORT|0,C=e.STACKTOP|0,T=e.STACK_MAX|0,L=e.cttz_i8|0,U=e.___dso_handle|0,z=0,te=0,le=0,ce=0,ue=t.NaN,Ce=t.Infinity,he=0,De=0,Ee=0,g=0,me=0,we=0,fe=t.Math.floor,ie=t.Math.abs,Z=t.Math.sqrt,xe=t.Math.pow,Re=t.Math.cos,gt=t.Math.sin,q=t.Math.tan,nt=t.Math.acos,Ne=t.Math.asin,Te=t.Math.atan,ke=t.Math.atan2,Ve=t.Math.exp,Se=t.Math.log,tt=t.Math.ceil,He=t.Math.imul,b=t.Math.min,w=t.Math.max,S=t.Math.clz32,y=t.Math.fround,R=e.abort,J=e.assert,X=e.enlargeMemory,$=e.getTotalMemory,se=e.abortOnCannotGrowMemory,be=e.invoke_viiiii,Fe=e.invoke_vif,lt=e.invoke_vid,Et=e.invoke_fiff,qt=e.invoke_vi,nr=e.invoke_vii,St=e.invoke_ii,cn=e.invoke_viddi,Pr=e.invoke_vidd,yr=e.invoke_iiii,Rr=e.invoke_diii,Xr=e.invoke_di,$n=e.invoke_iid,Xs=e.invoke_iii,Hi=e.invoke_viiddi,Qs=e.invoke_viiiiii,Zs=e.invoke_dii,xi=e.invoke_i,Fs=e.invoke_iiiiii,$s=e.invoke_viiid,SA=e.invoke_viififi,gu=e.invoke_viii,op=e.invoke_v,ap=e.invoke_viid,Rs=e.invoke_idd,Ln=e.invoke_viiii,hs=e._emscripten_asm_const_iiiii,Ts=e._emscripten_asm_const_iiidddddd,pc=e._emscripten_asm_const_iiiid,hc=e.__nbind_reference_external,gc=e._emscripten_asm_const_iiiiiiii,bA=e._removeAccessorPrefix,xA=e._typeModule,Ro=e.__nbind_register_pool,To=e.__decorate,kA=e._llvm_stackrestore,pr=e.___cxa_atexit,Oe=e.__extends,ia=e.__nbind_get_value_object,dc=e.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,Er=e._emscripten_set_main_loop_timing,du=e.__nbind_register_primitive,QA=e.__nbind_register_type,FA=e._emscripten_memcpy_big,mc=e.__nbind_register_function,yc=e.___setErrNo,wl=e.__nbind_register_class,Ie=e.__nbind_finish,Tt=e._abort,Il=e._nbind_value,Bi=e._llvm_stacksave,Ns=e.___syscall54,Ft=e._defineHidden,Bn=e._emscripten_set_main_loop,No=e._emscripten_get_now,ki=e.__nbind_register_callback_signature,vi=e._emscripten_asm_const_iiiiii,sa=e.__nbind_free_external,un=e._emscripten_asm_const_iiii,qn=e._emscripten_asm_const_iiididi,Ec=e.___syscall6,lp=e._atexit,oa=e.___syscall140,aa=e.___syscall146,la=y(0);let Ze=y(0);function ca(s){s=s|0;var l=0;return l=C,C=C+s|0,C=C+15&-16,l|0}function mu(){return C|0}function Bl(s){s=s|0,C=s}function dn(s,l){s=s|0,l=l|0,C=s,T=l}function Lo(s,l){s=s|0,l=l|0,z||(z=s,te=l)}function RA(s){s=s|0,we=s}function TA(){return we|0}function Mo(){var s=0,l=0;xr(8104,8,400)|0,xr(8504,408,540)|0,s=9044,l=s+44|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));o[9088]=0,o[9089]=1,n[2273]=0,n[2274]=948,n[2275]=948,pr(17,8104,U|0)|0}function qa(s){s=s|0,ht(s+948|0)}function Mt(s){return s=y(s),((AD(s)|0)&2147483647)>>>0>2139095040|0}function vn(s,l,c){s=s|0,l=l|0,c=c|0;e:do if(n[s+(l<<3)+4>>2]|0)s=s+(l<<3)|0;else{if((l|2|0)==3&&n[s+60>>2]|0){s=s+56|0;break}switch(l|0){case 0:case 2:case 4:case 5:{if(n[s+52>>2]|0){s=s+48|0;break e}break}default:}if(n[s+68>>2]|0){s=s+64|0;break}else{s=(l|1|0)==5?948:c;break}}while(!1);return s|0}function Oo(s){s=s|0;var l=0;return l=_D(1e3)|0,ua(s,(l|0)!=0,2456),n[2276]=(n[2276]|0)+1,xr(l|0,8104,1e3)|0,o[s+2>>0]|0&&(n[l+4>>2]=2,n[l+12>>2]=4),n[l+976>>2]=s,l|0}function ua(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,d0(s,5,3197,f)),C=d}function qi(){return Oo(956)|0}function vl(s){s=s|0;var l=0;return l=Wt(1e3)|0,Cc(l,s),ua(n[s+976>>2]|0,1,2456),n[2276]=(n[2276]|0)+1,n[l+944>>2]=0,l|0}function Cc(s,l){s=s|0,l=l|0;var c=0;xr(s|0,l|0,948)|0,Qd(s+948|0,l+948|0),c=s+960|0,s=l+960|0,l=c+40|0;do n[c>>2]=n[s>>2],c=c+4|0,s=s+4|0;while((c|0)<(l|0))}function Dl(s){s=s|0;var l=0,c=0,f=0,d=0;if(l=s+944|0,c=n[l>>2]|0,c|0&&(Aa(c+948|0,s)|0,n[l>>2]=0),c=Di(s)|0,c|0){l=0;do n[(rs(s,l)|0)+944>>2]=0,l=l+1|0;while((l|0)!=(c|0))}c=s+948|0,f=n[c>>2]|0,d=s+952|0,l=n[d>>2]|0,(l|0)!=(f|0)&&(n[d>>2]=l+(~((l+-4-f|0)>>>2)<<2)),ja(c),HD(s),n[2276]=(n[2276]|0)+-1}function Aa(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0;f=n[s>>2]|0,k=s+4|0,c=n[k>>2]|0,m=c;e:do if((f|0)==(c|0))d=f,B=4;else for(s=f;;){if((n[s>>2]|0)==(l|0)){d=s,B=4;break e}if(s=s+4|0,(s|0)==(c|0)){s=0;break}}while(!1);return(B|0)==4&&((d|0)!=(c|0)?(f=d+4|0,s=m-f|0,l=s>>2,l&&(rI(d|0,f|0,s|0)|0,c=n[k>>2]|0),s=d+(l<<2)|0,(c|0)==(s|0)||(n[k>>2]=c+(~((c+-4-s|0)>>>2)<<2)),s=1):s=0),s|0}function Di(s){return s=s|0,(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2|0}function rs(s,l){s=s|0,l=l|0;var c=0;return c=n[s+948>>2]|0,(n[s+952>>2]|0)-c>>2>>>0>l>>>0?s=n[c+(l<<2)>>2]|0:s=0,s|0}function ja(s){s=s|0;var l=0,c=0,f=0,d=0;f=C,C=C+32|0,l=f,d=n[s>>2]|0,c=(n[s+4>>2]|0)-d|0,((n[s+8>>2]|0)-d|0)>>>0>c>>>0&&(d=c>>2,Nd(l,d,d,s+8|0),fD(s,l),Ld(l)),C=f}function yu(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0;O=Di(s)|0;do if(O|0){if((n[(rs(s,0)|0)+944>>2]|0)==(s|0)){if(!(Aa(s+948|0,l)|0))break;xr(l+400|0,8504,540)|0,n[l+944>>2]=0,Le(s);break}B=n[(n[s+976>>2]|0)+12>>2]|0,k=s+948|0,F=(B|0)==0,c=0,m=0;do f=n[(n[k>>2]|0)+(m<<2)>>2]|0,(f|0)==(l|0)?Le(s):(d=vl(f)|0,n[(n[k>>2]|0)+(c<<2)>>2]=d,n[d+944>>2]=s,F||hT[B&15](f,d,s,c),c=c+1|0),m=m+1|0;while((m|0)!=(O|0));if(c>>>0>>0){F=s+948|0,k=s+952|0,B=c,c=n[k>>2]|0;do m=(n[F>>2]|0)+(B<<2)|0,f=m+4|0,d=c-f|0,l=d>>2,l&&(rI(m|0,f|0,d|0)|0,c=n[k>>2]|0),d=c,f=m+(l<<2)|0,(d|0)!=(f|0)&&(c=d+(~((d+-4-f|0)>>>2)<<2)|0,n[k>>2]=c),B=B+1|0;while((B|0)!=(O|0))}}while(!1)}function Pl(s){s=s|0;var l=0,c=0,f=0,d=0;pi(s,(Di(s)|0)==0,2491),pi(s,(n[s+944>>2]|0)==0,2545),l=s+948|0,c=n[l>>2]|0,f=s+952|0,d=n[f>>2]|0,(d|0)!=(c|0)&&(n[f>>2]=d+(~((d+-4-c|0)>>>2)<<2)),ja(l),l=s+976|0,c=n[l>>2]|0,xr(s|0,8104,1e3)|0,o[c+2>>0]|0&&(n[s+4>>2]=2,n[s+12>>2]=4),n[l>>2]=c}function pi(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,so(s,5,3197,f)),C=d}function Dn(){return n[2276]|0}function Sl(){var s=0;return s=_D(20)|0,ze((s|0)!=0,2592),n[2277]=(n[2277]|0)+1,n[s>>2]=n[239],n[s+4>>2]=n[240],n[s+8>>2]=n[241],n[s+12>>2]=n[242],n[s+16>>2]=n[243],s|0}function ze(s,l){s=s|0,l=l|0;var c=0,f=0;f=C,C=C+16|0,c=f,s||(n[c>>2]=l,so(0,5,3197,c)),C=f}function it(s){s=s|0,HD(s),n[2277]=(n[2277]|0)+-1}function vt(s,l){s=s|0,l=l|0;var c=0;l?(pi(s,(Di(s)|0)==0,2629),c=1):(c=0,l=0),n[s+964>>2]=l,n[s+988>>2]=c}function ar(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+8|0,d=f+4|0,B=f,n[d>>2]=l,pi(s,(n[l+944>>2]|0)==0,2709),pi(s,(n[s+964>>2]|0)==0,2763),ee(s),l=s+948|0,n[B>>2]=(n[l>>2]|0)+(c<<2),n[m>>2]=n[B>>2],ye(l,m,d)|0,n[(n[d>>2]|0)+944>>2]=s,Le(s),C=f}function ee(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;if(c=Di(s)|0,c|0&&(n[(rs(s,0)|0)+944>>2]|0)!=(s|0)){f=n[(n[s+976>>2]|0)+12>>2]|0,d=s+948|0,m=(f|0)==0,l=0;do B=n[(n[d>>2]|0)+(l<<2)>>2]|0,k=vl(B)|0,n[(n[d>>2]|0)+(l<<2)>>2]=k,n[k+944>>2]=s,m||hT[f&15](B,k,s,l),l=l+1|0;while((l|0)!=(c|0))}}function ye(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0;rt=C,C=C+64|0,j=rt+52|0,k=rt+48|0,oe=rt+28|0,Ye=rt+24|0,Me=rt+20|0,Qe=rt,f=n[s>>2]|0,m=f,l=f+((n[l>>2]|0)-m>>2<<2)|0,f=s+4|0,d=n[f>>2]|0,B=s+8|0;do if(d>>>0<(n[B>>2]|0)>>>0){if((l|0)==(d|0)){n[l>>2]=n[c>>2],n[f>>2]=(n[f>>2]|0)+4;break}pD(s,l,d,l+4|0),l>>>0<=c>>>0&&(c=(n[f>>2]|0)>>>0>c>>>0?c+4|0:c),n[l>>2]=n[c>>2]}else{f=(d-m>>2)+1|0,d=N(s)|0,d>>>0>>0&&Zr(s),M=n[s>>2]|0,O=(n[B>>2]|0)-M|0,m=O>>1,Nd(Qe,O>>2>>>0>>1>>>0?m>>>0>>0?f:m:d,l-M>>2,s+8|0),M=Qe+8|0,f=n[M>>2]|0,m=Qe+12|0,O=n[m>>2]|0,B=O,F=f;do if((f|0)==(O|0)){if(O=Qe+4|0,f=n[O>>2]|0,Xe=n[Qe>>2]|0,d=Xe,f>>>0<=Xe>>>0){f=B-d>>1,f=f|0?f:1,Nd(oe,f,f>>>2,n[Qe+16>>2]|0),n[Ye>>2]=n[O>>2],n[Me>>2]=n[M>>2],n[k>>2]=n[Ye>>2],n[j>>2]=n[Me>>2],Qw(oe,k,j),f=n[Qe>>2]|0,n[Qe>>2]=n[oe>>2],n[oe>>2]=f,f=oe+4|0,Xe=n[O>>2]|0,n[O>>2]=n[f>>2],n[f>>2]=Xe,f=oe+8|0,Xe=n[M>>2]|0,n[M>>2]=n[f>>2],n[f>>2]=Xe,f=oe+12|0,Xe=n[m>>2]|0,n[m>>2]=n[f>>2],n[f>>2]=Xe,Ld(oe),f=n[M>>2]|0;break}m=f,B=((m-d>>2)+1|0)/-2|0,k=f+(B<<2)|0,d=F-m|0,m=d>>2,m&&(rI(k|0,f|0,d|0)|0,f=n[O>>2]|0),Xe=k+(m<<2)|0,n[M>>2]=Xe,n[O>>2]=f+(B<<2),f=Xe}while(!1);n[f>>2]=n[c>>2],n[M>>2]=(n[M>>2]|0)+4,l=hD(s,Qe,l)|0,Ld(Qe)}while(!1);return C=rt,l|0}function Le(s){s=s|0;var l=0;do{if(l=s+984|0,o[l>>0]|0)break;o[l>>0]=1,h[s+504>>2]=y(ue),s=n[s+944>>2]|0}while(s|0)}function ht(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function mt(s){return s=s|0,n[s+944>>2]|0}function Dt(s){s=s|0,pi(s,(n[s+964>>2]|0)!=0,2832),Le(s)}function er(s){return s=s|0,(o[s+984>>0]|0)!=0|0}function sn(s,l){s=s|0,l=l|0,IUe(s,l,400)|0&&(xr(s|0,l|0,400)|0,Le(s))}function ei(s){s=s|0;var l=Ze;return l=y(h[s+44>>2]),s=Mt(l)|0,y(s?y(0):l)}function Qi(s){s=s|0;var l=Ze;return l=y(h[s+48>>2]),Mt(l)|0&&(l=o[(n[s+976>>2]|0)+2>>0]|0?y(1):y(0)),y(l)}function Pn(s,l){s=s|0,l=l|0,n[s+980>>2]=l}function fa(s){return s=s|0,n[s+980>>2]|0}function Id(s,l){s=s|0,l=l|0;var c=0;c=s+4|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function Bw(s){return s=s|0,n[s+4>>2]|0}function eo(s,l){s=s|0,l=l|0;var c=0;c=s+8|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function Bd(s){return s=s|0,n[s+8>>2]|0}function cp(s,l){s=s|0,l=l|0;var c=0;c=s+12|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function vw(s){return s=s|0,n[s+12>>2]|0}function to(s,l){s=s|0,l=l|0;var c=0;c=s+16|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function up(s){return s=s|0,n[s+16>>2]|0}function Ap(s,l){s=s|0,l=l|0;var c=0;c=s+20|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function wc(s){return s=s|0,n[s+20>>2]|0}function fp(s,l){s=s|0,l=l|0;var c=0;c=s+24|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function s0(s){return s=s|0,n[s+24>>2]|0}function o0(s,l){s=s|0,l=l|0;var c=0;c=s+28|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function a0(s){return s=s|0,n[s+28>>2]|0}function vd(s,l){s=s|0,l=l|0;var c=0;c=s+32|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function Eu(s){return s=s|0,n[s+32>>2]|0}function ro(s,l){s=s|0,l=l|0;var c=0;c=s+36|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function Ga(s){return s=s|0,n[s+36>>2]|0}function pp(s,l){s=s|0,l=y(l);var c=0;c=s+40|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function l0(s,l){s=s|0,l=y(l);var c=0;c=s+44|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function Ya(s,l){s=s|0,l=y(l);var c=0;c=s+48|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function Wa(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+52|0,d=s+56|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Dd(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+52|0,c=s+56|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Mt(l)|0,n[c>>2]=f?3:2,Le(s))}function NA(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+52|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Pd(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=(m^1)&1,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Sd(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=m?0:2,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function LA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+132+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function MA(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=(m^1)&1,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Y(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=m?0:2,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function bt(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+60+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function OA(s,l){s=s|0,l=l|0;var c=0;c=s+60+(l<<3)+4|0,(n[c>>2]|0)!=3&&(h[s+60+(l<<3)>>2]=y(ue),n[c>>2]=3,Le(s))}function no(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=(m^1)&1,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Cu(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=m?0:2,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function dt(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+204+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function Ic(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Mt(c)|0,f=(m^1)&1,d=s+276+(l<<3)|0,l=s+276+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function bd(s,l){return s=s|0,l=l|0,y(h[s+276+(l<<3)>>2])}function c0(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+348|0,d=s+352|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Dw(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+348|0,c=s+352|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Mt(l)|0,n[c>>2]=f?3:2,Le(s))}function hp(s){s=s|0;var l=0;l=s+352|0,(n[l>>2]|0)!=3&&(h[s+348>>2]=y(ue),n[l>>2]=3,Le(s))}function cr(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+348|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Li(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+356|0,d=s+360|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function wu(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+356|0,c=s+360|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Mt(l)|0,n[c>>2]=f?3:2,Le(s))}function pa(s){s=s|0;var l=0;l=s+360|0,(n[l>>2]|0)!=3&&(h[s+356>>2]=y(ue),n[l>>2]=3,Le(s))}function u0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+356|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Bc(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Iu(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=m?0:2,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function It(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+364|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function oi(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function UA(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=m?0:2,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function ha(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+372|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Uo(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function ga(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=m?0:2,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function A0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+380|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function gp(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=(m^1)&1,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function f0(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Mt(l)|0,c=m?0:2,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function xd(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+388|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function _A(s,l){s=s|0,l=y(l);var c=0;c=s+396|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function p0(s){return s=s|0,y(h[s+396>>2])}function vc(s){return s=s|0,y(h[s+400>>2])}function Dc(s){return s=s|0,y(h[s+404>>2])}function Bu(s){return s=s|0,y(h[s+408>>2])}function gs(s){return s=s|0,y(h[s+412>>2])}function Pc(s){return s=s|0,y(h[s+416>>2])}function Mn(s){return s=s|0,y(h[s+420>>2])}function ji(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+424+(l<<2)>>2])}function Ci(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+448+(l<<2)>>2])}function HA(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+472+(l<<2)>>2])}function vu(s,l){s=s|0,l=l|0;var c=0,f=Ze;return c=n[s+4>>2]|0,(c|0)==(n[l+4>>2]|0)?c?(f=y(h[s>>2]),s=y(ie(y(f-y(h[l>>2]))))>2]=0,n[f+4>>2]=0,n[f+8>>2]=0,dc(f|0,s|0,l|0,0),so(s,3,(o[f+11>>0]|0)<0?n[f>>2]|0:f,c),YUe(f),C=c}function Gi(s,l,c,f){s=y(s),l=y(l),c=c|0,f=f|0;var d=Ze;s=y(s*l),d=y(lT(s,y(1)));do if(An(d,y(0))|0)s=y(s-d);else{if(s=y(s-d),An(d,y(1))|0){s=y(s+y(1));break}if(c){s=y(s+y(1));break}f||(d>y(.5)?d=y(1):(f=An(d,y(.5))|0,d=y(f?1:0)),s=y(s+d))}while(!1);return y(s/l)}function Ka(s,l,c,f,d,m,B,k,F,O,M,j,oe){s=s|0,l=y(l),c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,k=y(k),F=y(F),O=y(O),M=y(M),j=y(j),oe=oe|0;var Ye=0,Me=Ze,Qe=Ze,rt=Ze,Xe=Ze,ct=Ze,_e=Ze;return F>2]),Me!=y(0))?(rt=y(Gi(l,Me,0,0)),Xe=y(Gi(f,Me,0,0)),Qe=y(Gi(m,Me,0,0)),Me=y(Gi(k,Me,0,0))):(Qe=m,rt=l,Me=k,Xe=f),(d|0)==(s|0)?Ye=An(Qe,rt)|0:Ye=0,(B|0)==(c|0)?oe=An(Me,Xe)|0:oe=0,!Ye&&(ct=y(l-M),!(io(s,ct,F)|0))&&!(Du(s,ct,d,F)|0)?Ye=Pu(s,ct,d,m,F)|0:Ye=1,!oe&&(_e=y(f-j),!(io(c,_e,O)|0))&&!(Du(c,_e,B,O)|0)?oe=Pu(c,_e,B,k,O)|0:oe=1,oe=Ye&oe),oe|0}function io(s,l,c){return s=s|0,l=y(l),c=y(c),(s|0)==1?s=An(l,c)|0:s=0,s|0}function Du(s,l,c,f){return s=s|0,l=y(l),c=c|0,f=y(f),(s|0)==2&(c|0)==0?l>=f?s=1:s=An(l,f)|0:s=0,s|0}function Pu(s,l,c,f,d){return s=s|0,l=y(l),c=c|0,f=y(f),d=y(d),(s|0)==2&(c|0)==2&f>l?d<=l?s=1:s=An(l,d)|0:s=0,s|0}function Va(s,l,c,f,d,m,B,k,F,O,M){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),F=F|0,O=O|0,M=M|0;var j=0,oe=0,Ye=0,Me=0,Qe=Ze,rt=Ze,Xe=0,ct=0,_e=0,Ge=0,Lt=0,_r=0,ur=0,Zt=0,kr=0,Mr=0,lr=0,Nn=Ze,lo=Ze,co=Ze,uo=0,wa=0;lr=C,C=C+160|0,Zt=lr+152|0,ur=lr+120|0,_r=lr+104|0,_e=lr+72|0,Me=lr+56|0,Lt=lr+8|0,ct=lr,Ge=(n[2279]|0)+1|0,n[2279]=Ge,kr=s+984|0,o[kr>>0]|0&&(n[s+512>>2]|0)!=(n[2278]|0)?Xe=4:(n[s+516>>2]|0)==(f|0)?Mr=0:Xe=4,(Xe|0)==4&&(n[s+520>>2]=0,n[s+924>>2]=-1,n[s+928>>2]=-1,h[s+932>>2]=y(-1),h[s+936>>2]=y(-1),Mr=1);e:do if(n[s+964>>2]|0)if(Qe=y(fn(s,2,B)),rt=y(fn(s,0,B)),j=s+916|0,co=y(h[j>>2]),lo=y(h[s+920>>2]),Nn=y(h[s+932>>2]),Ka(d,l,m,c,n[s+924>>2]|0,co,n[s+928>>2]|0,lo,Nn,y(h[s+936>>2]),Qe,rt,M)|0)Xe=22;else if(Ye=n[s+520>>2]|0,!Ye)Xe=21;else for(oe=0;;){if(j=s+524+(oe*24|0)|0,Nn=y(h[j>>2]),lo=y(h[s+524+(oe*24|0)+4>>2]),co=y(h[s+524+(oe*24|0)+16>>2]),Ka(d,l,m,c,n[s+524+(oe*24|0)+8>>2]|0,Nn,n[s+524+(oe*24|0)+12>>2]|0,lo,co,y(h[s+524+(oe*24|0)+20>>2]),Qe,rt,M)|0){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=Ye>>>0){Xe=21;break}}else{if(F){if(j=s+916|0,!(An(y(h[j>>2]),l)|0)){Xe=21;break}if(!(An(y(h[s+920>>2]),c)|0)){Xe=21;break}if((n[s+924>>2]|0)!=(d|0)){Xe=21;break}j=(n[s+928>>2]|0)==(m|0)?j:0,Xe=22;break}if(Ye=n[s+520>>2]|0,!Ye)Xe=21;else for(oe=0;;){if(j=s+524+(oe*24|0)|0,An(y(h[j>>2]),l)|0&&An(y(h[s+524+(oe*24|0)+4>>2]),c)|0&&(n[s+524+(oe*24|0)+8>>2]|0)==(d|0)&&(n[s+524+(oe*24|0)+12>>2]|0)==(m|0)){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=Ye>>>0){Xe=21;break}}}while(!1);do if((Xe|0)==21)o[11697]|0?(j=0,Xe=28):(j=0,Xe=31);else if((Xe|0)==22){if(oe=(o[11697]|0)!=0,!((j|0)!=0&(Mr^1)))if(oe){Xe=28;break}else{Xe=31;break}Me=j+16|0,n[s+908>>2]=n[Me>>2],Ye=j+20|0,n[s+912>>2]=n[Ye>>2],(o[11698]|0)==0|oe^1||(n[ct>>2]=Sc(Ge)|0,n[ct+4>>2]=Ge,so(s,4,2972,ct),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),d=_o(d,F)|0,m=_o(m,F)|0,wa=+y(h[Me>>2]),uo=+y(h[Ye>>2]),n[Lt>>2]=d,n[Lt+4>>2]=m,E[Lt+8>>3]=+l,E[Lt+16>>3]=+c,E[Lt+24>>3]=wa,E[Lt+32>>3]=uo,n[Lt+40>>2]=O,so(s,4,2989,Lt))}while(!1);return(Xe|0)==28&&(oe=Sc(Ge)|0,n[Me>>2]=oe,n[Me+4>>2]=Ge,n[Me+8>>2]=Mr?3047:11699,so(s,4,3038,Me),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),Lt=_o(d,F)|0,Xe=_o(m,F)|0,n[_e>>2]=Lt,n[_e+4>>2]=Xe,E[_e+8>>3]=+l,E[_e+16>>3]=+c,n[_e+24>>2]=O,so(s,4,3049,_e),Xe=31),(Xe|0)==31&&(ds(s,l,c,f,d,m,B,k,F,M),o[11697]|0&&(oe=n[2279]|0,Lt=Sc(oe)|0,n[_r>>2]=Lt,n[_r+4>>2]=oe,n[_r+8>>2]=Mr?3047:11699,so(s,4,3083,_r),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),Lt=_o(d,F)|0,_r=_o(m,F)|0,uo=+y(h[s+908>>2]),wa=+y(h[s+912>>2]),n[ur>>2]=Lt,n[ur+4>>2]=_r,E[ur+8>>3]=uo,E[ur+16>>3]=wa,n[ur+24>>2]=O,so(s,4,3092,ur)),n[s+516>>2]=f,j||(oe=s+520|0,j=n[oe>>2]|0,(j|0)==16&&(o[11697]|0&&so(s,4,3124,Zt),n[oe>>2]=0,j=0),F?j=s+916|0:(n[oe>>2]=j+1,j=s+524+(j*24|0)|0),h[j>>2]=l,h[j+4>>2]=c,n[j+8>>2]=d,n[j+12>>2]=m,n[j+16>>2]=n[s+908>>2],n[j+20>>2]=n[s+912>>2],j=0)),F&&(n[s+416>>2]=n[s+908>>2],n[s+420>>2]=n[s+912>>2],o[s+985>>0]=1,o[kr>>0]=0),n[2279]=(n[2279]|0)+-1,n[s+512>>2]=n[2278],C=lr,Mr|(j|0)==0|0}function fn(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(V(s,l,c)),y(f+y(re(s,l,c)))}function so(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=C,C=C+16|0,d=m,n[d>>2]=f,s?f=n[s+976>>2]|0:f=0,yp(f,s,l,c,d),C=m}function Sc(s){return s=s|0,(s>>>0>60?3201:3201+(60-s)|0)|0}function _o(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+32|0,c=d+12|0,f=d,n[c>>2]=n[254],n[c+4>>2]=n[255],n[c+8>>2]=n[256],n[f>>2]=n[257],n[f+4>>2]=n[258],n[f+8>>2]=n[259],(s|0)>2?s=11699:s=n[(l?f:c)+(s<<2)>>2]|0,C=d,s|0}function ds(s,l,c,f,d,m,B,k,F,O){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),F=F|0,O=O|0;var M=0,j=0,oe=0,Ye=0,Me=Ze,Qe=Ze,rt=Ze,Xe=Ze,ct=Ze,_e=Ze,Ge=Ze,Lt=0,_r=0,ur=0,Zt=Ze,kr=Ze,Mr=0,lr=Ze,Nn=0,lo=0,co=0,uo=0,wa=0,Np=0,Lp=0,kl=0,Mp=0,Lu=0,Mu=0,Op=0,Up=0,_p=0,$r=0,Ql=0,Hp=0,Nc=0,qp=Ze,jp=Ze,Ou=Ze,Uu=Ze,Lc=Ze,Os=0,rl=0,Go=0,Fl=0,rf=0,nf=Ze,_u=Ze,sf=Ze,of=Ze,Us=Ze,Cs=Ze,Rl=0,Un=Ze,af=Ze,Ao=Ze,Mc=Ze,fo=Ze,Oc=Ze,lf=0,cf=0,Uc=Ze,_s=Ze,Tl=0,uf=0,Af=0,ff=0,Fr=Ze,ri=0,ws=0,po=0,Hs=0,Nr=0,Ar=0,Nl=0,Vt=Ze,pf=0,hi=0;Nl=C,C=C+16|0,Os=Nl+12|0,rl=Nl+8|0,Go=Nl+4|0,Fl=Nl,pi(s,(d|0)==0|(Mt(l)|0)^1,3326),pi(s,(m|0)==0|(Mt(c)|0)^1,3406),ws=At(s,f)|0,n[s+496>>2]=ws,Nr=hr(2,ws)|0,Ar=hr(0,ws)|0,h[s+440>>2]=y(V(s,Nr,B)),h[s+444>>2]=y(re(s,Nr,B)),h[s+428>>2]=y(V(s,Ar,B)),h[s+436>>2]=y(re(s,Ar,B)),h[s+464>>2]=y(wr(s,Nr)),h[s+468>>2]=y(Rn(s,Nr)),h[s+452>>2]=y(wr(s,Ar)),h[s+460>>2]=y(Rn(s,Ar)),h[s+488>>2]=y(ai(s,Nr,B)),h[s+492>>2]=y(ns(s,Nr,B)),h[s+476>>2]=y(ai(s,Ar,B)),h[s+484>>2]=y(ns(s,Ar,B));do if(n[s+964>>2]|0)GA(s,l,c,d,m,B,k);else{if(po=s+948|0,Hs=(n[s+952>>2]|0)-(n[po>>2]|0)>>2,!Hs){lD(s,l,c,d,m,B,k);break}if(!F&&Pw(s,l,c,d,m,B,k)|0)break;ee(s),Ql=s+508|0,o[Ql>>0]=0,Nr=hr(n[s+4>>2]|0,ws)|0,Ar=Fd(Nr,ws)|0,ri=ge(Nr)|0,Hp=n[s+8>>2]|0,uf=s+28|0,Nc=(n[uf>>2]|0)!=0,fo=ri?B:k,Uc=ri?k:B,qp=y(Cp(s,Nr,B)),jp=y(Sw(s,Nr,B)),Me=y(Cp(s,Ar,B)),Oc=y(da(s,Nr,B)),_s=y(da(s,Ar,B)),ur=ri?d:m,Tl=ri?m:d,Fr=ri?Oc:_s,ct=ri?_s:Oc,Mc=y(fn(s,2,B)),Xe=y(fn(s,0,B)),Qe=y(y(Kr(s+364|0,B))-Fr),rt=y(y(Kr(s+380|0,B))-Fr),_e=y(y(Kr(s+372|0,k))-ct),Ge=y(y(Kr(s+388|0,k))-ct),Ou=ri?Qe:_e,Uu=ri?rt:Ge,Mc=y(l-Mc),l=y(Mc-Fr),Mt(l)|0?Fr=l:Fr=y(Wn(y(O0(l,rt)),Qe)),af=y(c-Xe),l=y(af-ct),Mt(l)|0?Ao=l:Ao=y(Wn(y(O0(l,Ge)),_e)),Qe=ri?Fr:Ao,Un=ri?Ao:Fr;e:do if((ur|0)==1)for(f=0,j=0;;){if(M=rs(s,j)|0,!f)y(YA(M))>y(0)&&y(wp(M))>y(0)?f=M:f=0;else if(bw(M)|0){Ye=0;break e}if(j=j+1|0,j>>>0>=Hs>>>0){Ye=f;break}}else Ye=0;while(!1);Lt=Ye+500|0,_r=Ye+504|0,f=0,M=0,l=y(0),oe=0;do{if(j=n[(n[po>>2]|0)+(oe<<2)>>2]|0,(n[j+36>>2]|0)==1)Rd(j),o[j+985>>0]=1,o[j+984>>0]=0;else{Su(j),F&&mp(j,At(j,ws)|0,Qe,Un,Fr);do if((n[j+24>>2]|0)!=1)if((j|0)==(Ye|0)){n[Lt>>2]=n[2278],h[_r>>2]=y(0);break}else{cD(s,j,Fr,d,Ao,Fr,Ao,m,ws,O);break}else M|0&&(n[M+960>>2]=j),n[j+960>>2]=0,M=j,f=f|0?f:j;while(!1);Cs=y(h[j+504>>2]),l=y(l+y(Cs+y(fn(j,Nr,Fr))))}oe=oe+1|0}while((oe|0)!=(Hs|0));for(co=l>Qe,Rl=Nc&((ur|0)==2&co)?1:ur,Nn=(Tl|0)==1,wa=Nn&(F^1),Np=(Rl|0)==1,Lp=(Rl|0)==2,kl=976+(Nr<<2)|0,Mp=(Tl|2|0)==2,_p=Nn&(Nc^1),Lu=1040+(Ar<<2)|0,Mu=1040+(Nr<<2)|0,Op=976+(Ar<<2)|0,Up=(Tl|0)!=1,co=Nc&((ur|0)!=0&co),lo=s+976|0,Nn=Nn^1,l=Qe,Mr=0,uo=0,Cs=y(0),Lc=y(0);;){e:do if(Mr>>>0>>0)for(_r=n[po>>2]|0,oe=0,Ge=y(0),_e=y(0),rt=y(0),Qe=y(0),j=0,M=0,Ye=Mr;;){if(Lt=n[_r+(Ye<<2)>>2]|0,(n[Lt+36>>2]|0)!=1&&(n[Lt+940>>2]=uo,(n[Lt+24>>2]|0)!=1)){if(Xe=y(fn(Lt,Nr,Fr)),$r=n[kl>>2]|0,c=y(Kr(Lt+380+($r<<3)|0,fo)),ct=y(h[Lt+504>>2]),c=y(O0(c,ct)),c=y(Wn(y(Kr(Lt+364+($r<<3)|0,fo)),c)),Nc&(oe|0)!=0&y(Xe+y(_e+c))>l){m=oe,Xe=Ge,ur=Ye;break e}Xe=y(Xe+c),c=y(_e+Xe),Xe=y(Ge+Xe),bw(Lt)|0&&(rt=y(rt+y(YA(Lt))),Qe=y(Qe-y(ct*y(wp(Lt))))),M|0&&(n[M+960>>2]=Lt),n[Lt+960>>2]=0,oe=oe+1|0,M=Lt,j=j|0?j:Lt}else Xe=Ge,c=_e;if(Ye=Ye+1|0,Ye>>>0>>0)Ge=Xe,_e=c;else{m=oe,ur=Ye;break}}else m=0,Xe=y(0),rt=y(0),Qe=y(0),j=0,ur=Mr;while(!1);$r=rt>y(0)&rty(0)&QeUu&((Mt(Uu)|0)^1))l=Uu,$r=51;else if(o[(n[lo>>2]|0)+3>>0]|0)$r=51;else{if(Zt!=y(0)&&y(YA(s))!=y(0)){$r=53;break}l=Xe,$r=53}while(!1);if(($r|0)==51&&($r=0,Mt(l)|0?$r=53:(kr=y(l-Xe),lr=l)),($r|0)==53&&($r=0,Xe>2]|0,Ye=kry(0),_e=y(kr/Zt),rt=y(0),Xe=y(0),l=y(0),M=j;do c=y(Kr(M+380+(oe<<3)|0,fo)),Qe=y(Kr(M+364+(oe<<3)|0,fo)),Qe=y(O0(c,y(Wn(Qe,y(h[M+504>>2]))))),Ye?(c=y(Qe*y(wp(M))),c!=y(-0)&&(Vt=y(Qe-y(ct*c)),nf=y(On(M,Nr,Vt,lr,Fr)),Vt!=nf)&&(rt=y(rt-y(nf-Qe)),l=y(l+c))):Lt&&(_u=y(YA(M)),_u!=y(0))&&(Vt=y(Qe+y(_e*_u)),sf=y(On(M,Nr,Vt,lr,Fr)),Vt!=sf)&&(rt=y(rt-y(sf-Qe)),Xe=y(Xe-_u)),M=n[M+960>>2]|0;while(M|0);if(l=y(Ge+l),Qe=y(kr+rt),rf)l=y(0);else{ct=y(Zt+Xe),Ye=n[kl>>2]|0,Lt=Qey(0),ct=y(Qe/ct),l=y(0);do{Vt=y(Kr(j+380+(Ye<<3)|0,fo)),rt=y(Kr(j+364+(Ye<<3)|0,fo)),rt=y(O0(Vt,y(Wn(rt,y(h[j+504>>2]))))),Lt?(Vt=y(rt*y(wp(j))),Qe=y(-Vt),Vt!=y(-0)?(Vt=y(_e*Qe),Qe=y(On(j,Nr,y(rt+(_r?Qe:Vt)),lr,Fr))):Qe=rt):oe&&(of=y(YA(j)),of!=y(0))?Qe=y(On(j,Nr,y(rt+y(ct*of)),lr,Fr)):Qe=rt,l=y(l-y(Qe-rt)),Xe=y(fn(j,Nr,Fr)),c=y(fn(j,Ar,Fr)),Qe=y(Qe+Xe),h[rl>>2]=Qe,n[Fl>>2]=1,rt=y(h[j+396>>2]);e:do if(Mt(rt)|0){M=Mt(Un)|0;do if(!M){if(co|(Ls(j,Ar,Un)|0|Nn)||(Yi(s,j)|0)!=4||(n[(za(j,Ar)|0)+4>>2]|0)==3||(n[(Ja(j,Ar)|0)+4>>2]|0)==3)break;h[Os>>2]=Un,n[Go>>2]=1;break e}while(!1);if(Ls(j,Ar,Un)|0){M=n[j+992+(n[Op>>2]<<2)>>2]|0,Vt=y(c+y(Kr(M,Un))),h[Os>>2]=Vt,M=Up&(n[M+4>>2]|0)==2,n[Go>>2]=((Mt(Vt)|0|M)^1)&1;break}else{h[Os>>2]=Un,n[Go>>2]=M?0:2;break}}else Vt=y(Qe-Xe),Zt=y(Vt/rt),Vt=y(rt*Vt),n[Go>>2]=1,h[Os>>2]=y(c+(ri?Zt:Vt));while(!1);bc(j,Nr,lr,Fr,Fl,rl),bc(j,Ar,Un,Fr,Go,Os);do if(!(Ls(j,Ar,Un)|0)&&(Yi(s,j)|0)==4){if((n[(za(j,Ar)|0)+4>>2]|0)==3){M=0;break}M=(n[(Ja(j,Ar)|0)+4>>2]|0)!=3}else M=0;while(!1);Vt=y(h[rl>>2]),Zt=y(h[Os>>2]),pf=n[Fl>>2]|0,hi=n[Go>>2]|0,Va(j,ri?Vt:Zt,ri?Zt:Vt,ws,ri?pf:hi,ri?hi:pf,Fr,Ao,F&(M^1),3488,O)|0,o[Ql>>0]=o[Ql>>0]|o[j+508>>0],j=n[j+960>>2]|0}while(j|0)}}else l=y(0);if(l=y(kr+l),hi=l>0]=hi|u[Ql>>0],Lp&l>y(0)?(M=n[kl>>2]|0,n[s+364+(M<<3)+4>>2]|0&&(Us=y(Kr(s+364+(M<<3)|0,fo)),Us>=y(0))?Qe=y(Wn(y(0),y(Us-y(lr-l)))):Qe=y(0)):Qe=l,Lt=Mr>>>0>>0,Lt){Ye=n[po>>2]|0,oe=Mr,M=0;do j=n[Ye+(oe<<2)>>2]|0,n[j+24>>2]|0||(M=((n[(za(j,Nr)|0)+4>>2]|0)==3&1)+M|0,M=M+((n[(Ja(j,Nr)|0)+4>>2]|0)==3&1)|0),oe=oe+1|0;while((oe|0)!=(ur|0));M?(Xe=y(0),c=y(0)):$r=101}else $r=101;e:do if(($r|0)==101)switch($r=0,Hp|0){case 1:{M=0,Xe=y(Qe*y(.5)),c=y(0);break e}case 2:{M=0,Xe=Qe,c=y(0);break e}case 3:{if(m>>>0<=1){M=0,Xe=y(0),c=y(0);break e}c=y((m+-1|0)>>>0),M=0,Xe=y(0),c=y(y(Wn(Qe,y(0)))/c);break e}case 5:{c=y(Qe/y((m+1|0)>>>0)),M=0,Xe=c;break e}case 4:{c=y(Qe/y(m>>>0)),M=0,Xe=y(c*y(.5));break e}default:{M=0,Xe=y(0),c=y(0);break e}}while(!1);if(l=y(qp+Xe),Lt){rt=y(Qe/y(M|0)),oe=n[po>>2]|0,j=Mr,Qe=y(0);do{M=n[oe+(j<<2)>>2]|0;e:do if((n[M+36>>2]|0)!=1){switch(n[M+24>>2]|0){case 1:{if(Ho(M,Nr)|0){if(!F)break e;Vt=y(WA(M,Nr,lr)),Vt=y(Vt+y(wr(s,Nr))),Vt=y(Vt+y(V(M,Nr,Fr))),h[M+400+(n[Mu>>2]<<2)>>2]=Vt;break e}break}case 0:if(hi=(n[(za(M,Nr)|0)+4>>2]|0)==3,Vt=y(rt+l),l=hi?Vt:l,F&&(hi=M+400+(n[Mu>>2]<<2)|0,h[hi>>2]=y(l+y(h[hi>>2]))),hi=(n[(Ja(M,Nr)|0)+4>>2]|0)==3,Vt=y(rt+l),l=hi?Vt:l,wa){Vt=y(c+y(fn(M,Nr,Fr))),Qe=Un,l=y(l+y(Vt+y(h[M+504>>2])));break e}else{l=y(l+y(c+y(KA(M,Nr,Fr)))),Qe=y(Wn(Qe,y(KA(M,Ar,Fr))));break e}default:}F&&(Vt=y(Xe+y(wr(s,Nr))),hi=M+400+(n[Mu>>2]<<2)|0,h[hi>>2]=y(Vt+y(h[hi>>2])))}while(!1);j=j+1|0}while((j|0)!=(ur|0))}else Qe=y(0);if(c=y(jp+l),Mp?Xe=y(y(On(s,Ar,y(_s+Qe),Uc,B))-_s):Xe=Un,rt=y(y(On(s,Ar,y(_s+(_p?Un:Qe)),Uc,B))-_s),Lt&F){j=Mr;do{oe=n[(n[po>>2]|0)+(j<<2)>>2]|0;do if((n[oe+36>>2]|0)!=1){if((n[oe+24>>2]|0)==1){if(Ho(oe,Ar)|0){if(Vt=y(WA(oe,Ar,Un)),Vt=y(Vt+y(wr(s,Ar))),Vt=y(Vt+y(V(oe,Ar,Fr))),M=n[Lu>>2]|0,h[oe+400+(M<<2)>>2]=Vt,!(Mt(Vt)|0))break}else M=n[Lu>>2]|0;Vt=y(wr(s,Ar)),h[oe+400+(M<<2)>>2]=y(Vt+y(V(oe,Ar,Fr)));break}M=Yi(s,oe)|0;do if((M|0)==4){if((n[(za(oe,Ar)|0)+4>>2]|0)==3){$r=139;break}if((n[(Ja(oe,Ar)|0)+4>>2]|0)==3){$r=139;break}if(Ls(oe,Ar,Un)|0){l=Me;break}pf=n[oe+908+(n[kl>>2]<<2)>>2]|0,n[Os>>2]=pf,l=y(h[oe+396>>2]),hi=Mt(l)|0,Qe=(n[D>>2]=pf,y(h[D>>2])),hi?l=rt:(kr=y(fn(oe,Ar,Fr)),Vt=y(Qe/l),l=y(l*Qe),l=y(kr+(ri?Vt:l))),h[rl>>2]=l,h[Os>>2]=y(y(fn(oe,Nr,Fr))+Qe),n[Go>>2]=1,n[Fl>>2]=1,bc(oe,Nr,lr,Fr,Go,Os),bc(oe,Ar,Un,Fr,Fl,rl),l=y(h[Os>>2]),kr=y(h[rl>>2]),Vt=ri?l:kr,l=ri?kr:l,hi=((Mt(Vt)|0)^1)&1,Va(oe,Vt,l,ws,hi,((Mt(l)|0)^1)&1,Fr,Ao,1,3493,O)|0,l=Me}else $r=139;while(!1);e:do if(($r|0)==139){$r=0,l=y(Xe-y(KA(oe,Ar,Fr)));do if((n[(za(oe,Ar)|0)+4>>2]|0)==3){if((n[(Ja(oe,Ar)|0)+4>>2]|0)!=3)break;l=y(Me+y(Wn(y(0),y(l*y(.5)))));break e}while(!1);if((n[(Ja(oe,Ar)|0)+4>>2]|0)==3){l=Me;break}if((n[(za(oe,Ar)|0)+4>>2]|0)==3){l=y(Me+y(Wn(y(0),l)));break}switch(M|0){case 1:{l=Me;break e}case 2:{l=y(Me+y(l*y(.5)));break e}default:{l=y(Me+l);break e}}}while(!1);Vt=y(Cs+l),hi=oe+400+(n[Lu>>2]<<2)|0,h[hi>>2]=y(Vt+y(h[hi>>2]))}while(!1);j=j+1|0}while((j|0)!=(ur|0))}if(Cs=y(Cs+rt),Lc=y(Wn(Lc,c)),m=uo+1|0,ur>>>0>=Hs>>>0)break;l=lr,Mr=ur,uo=m}do if(F){if(M=m>>>0>1,!M&&!(HF(s)|0))break;if(!(Mt(Un)|0)){l=y(Un-Cs);e:do switch(n[s+12>>2]|0){case 3:{Me=y(Me+l),_e=y(0);break}case 2:{Me=y(Me+y(l*y(.5))),_e=y(0);break}case 4:{Un>Cs?_e=y(l/y(m>>>0)):_e=y(0);break}case 7:if(Un>Cs){Me=y(Me+y(l/y(m<<1>>>0))),_e=y(l/y(m>>>0)),_e=M?_e:y(0);break e}else{Me=y(Me+y(l*y(.5))),_e=y(0);break e}case 6:{_e=y(l/y(uo>>>0)),_e=Un>Cs&M?_e:y(0);break}default:_e=y(0)}while(!1);if(m|0)for(Lt=1040+(Ar<<2)|0,_r=976+(Ar<<2)|0,Ye=0,j=0;;){e:do if(j>>>0>>0)for(Qe=y(0),rt=y(0),l=y(0),oe=j;;){M=n[(n[po>>2]|0)+(oe<<2)>>2]|0;do if((n[M+36>>2]|0)!=1&&!(n[M+24>>2]|0)){if((n[M+940>>2]|0)!=(Ye|0))break e;if(qF(M,Ar)|0&&(Vt=y(h[M+908+(n[_r>>2]<<2)>>2]),l=y(Wn(l,y(Vt+y(fn(M,Ar,Fr)))))),(Yi(s,M)|0)!=5)break;Us=y(m0(M)),Us=y(Us+y(V(M,0,Fr))),Vt=y(h[M+912>>2]),Vt=y(y(Vt+y(fn(M,0,Fr)))-Us),Us=y(Wn(rt,Us)),Vt=y(Wn(Qe,Vt)),Qe=Vt,rt=Us,l=y(Wn(l,y(Us+Vt)))}while(!1);if(M=oe+1|0,M>>>0>>0)oe=M;else{oe=M;break}}else rt=y(0),l=y(0),oe=j;while(!1);if(ct=y(_e+l),c=Me,Me=y(Me+ct),j>>>0>>0){Xe=y(c+rt),M=j;do{j=n[(n[po>>2]|0)+(M<<2)>>2]|0;e:do if((n[j+36>>2]|0)!=1&&!(n[j+24>>2]|0))switch(Yi(s,j)|0){case 1:{Vt=y(c+y(V(j,Ar,Fr))),h[j+400+(n[Lt>>2]<<2)>>2]=Vt;break e}case 3:{Vt=y(y(Me-y(re(j,Ar,Fr)))-y(h[j+908+(n[_r>>2]<<2)>>2])),h[j+400+(n[Lt>>2]<<2)>>2]=Vt;break e}case 2:{Vt=y(c+y(y(ct-y(h[j+908+(n[_r>>2]<<2)>>2]))*y(.5))),h[j+400+(n[Lt>>2]<<2)>>2]=Vt;break e}case 4:{if(Vt=y(c+y(V(j,Ar,Fr))),h[j+400+(n[Lt>>2]<<2)>>2]=Vt,Ls(j,Ar,Un)|0||(ri?(Qe=y(h[j+908>>2]),l=y(Qe+y(fn(j,Nr,Fr))),rt=ct):(rt=y(h[j+912>>2]),rt=y(rt+y(fn(j,Ar,Fr))),l=ct,Qe=y(h[j+908>>2])),An(l,Qe)|0&&An(rt,y(h[j+912>>2]))|0))break e;Va(j,l,rt,ws,1,1,Fr,Ao,1,3501,O)|0;break e}case 5:{h[j+404>>2]=y(y(Xe-y(m0(j)))+y(WA(j,0,Un)));break e}default:break e}while(!1);M=M+1|0}while((M|0)!=(oe|0))}if(Ye=Ye+1|0,(Ye|0)==(m|0))break;j=oe}}}while(!1);if(h[s+908>>2]=y(On(s,2,Mc,B,B)),h[s+912>>2]=y(On(s,0,af,k,B)),Rl|0&&(lf=n[s+32>>2]|0,cf=(Rl|0)==2,!(cf&(lf|0)!=2))?cf&(lf|0)==2&&(l=y(Oc+lr),l=y(Wn(y(O0(l,y(y0(s,Nr,Lc,fo)))),Oc)),$r=198):(l=y(On(s,Nr,Lc,fo,B)),$r=198),($r|0)==198&&(h[s+908+(n[976+(Nr<<2)>>2]<<2)>>2]=l),Tl|0&&(Af=n[s+32>>2]|0,ff=(Tl|0)==2,!(ff&(Af|0)!=2))?ff&(Af|0)==2&&(l=y(_s+Un),l=y(Wn(y(O0(l,y(y0(s,Ar,y(_s+Cs),Uc)))),_s)),$r=204):(l=y(On(s,Ar,y(_s+Cs),Uc,B)),$r=204),($r|0)==204&&(h[s+908+(n[976+(Ar<<2)>>2]<<2)>>2]=l),F){if((n[uf>>2]|0)==2){j=976+(Ar<<2)|0,oe=1040+(Ar<<2)|0,M=0;do Ye=rs(s,M)|0,n[Ye+24>>2]|0||(pf=n[j>>2]|0,Vt=y(h[s+908+(pf<<2)>>2]),hi=Ye+400+(n[oe>>2]<<2)|0,Vt=y(Vt-y(h[hi>>2])),h[hi>>2]=y(Vt-y(h[Ye+908+(pf<<2)>>2]))),M=M+1|0;while((M|0)!=(Hs|0))}if(f|0){M=ri?Rl:d;do jF(s,f,Fr,M,Ao,ws,O),f=n[f+960>>2]|0;while(f|0)}if(M=(Nr|2|0)==3,j=(Ar|2|0)==3,M|j){f=0;do oe=n[(n[po>>2]|0)+(f<<2)>>2]|0,(n[oe+36>>2]|0)!=1&&(M&&xw(s,oe,Nr),j&&xw(s,oe,Ar)),f=f+1|0;while((f|0)!=(Hs|0))}}}while(!1);C=Nl}function dp(s,l){s=s|0,l=y(l);var c=0;ua(s,l>=y(0),3147),c=l==y(0),h[s+4>>2]=c?y(0):l}function qA(s,l,c,f){s=s|0,l=y(l),c=y(c),f=f|0;var d=Ze,m=Ze,B=0,k=0,F=0;n[2278]=(n[2278]|0)+1,Su(s),Ls(s,2,l)|0?(d=y(Kr(n[s+992>>2]|0,l)),F=1,d=y(d+y(fn(s,2,l)))):(d=y(Kr(s+380|0,l)),d>=y(0)?F=2:(F=((Mt(l)|0)^1)&1,d=l)),Ls(s,0,c)|0?(m=y(Kr(n[s+996>>2]|0,c)),k=1,m=y(m+y(fn(s,0,l)))):(m=y(Kr(s+388|0,c)),m>=y(0)?k=2:(k=((Mt(c)|0)^1)&1,m=c)),B=s+976|0,Va(s,d,m,f,F,k,l,c,1,3189,n[B>>2]|0)|0&&(mp(s,n[s+496>>2]|0,l,c,l),jA(s,y(h[(n[B>>2]|0)+4>>2]),y(0),y(0)),o[11696]|0)&&h0(s,7)}function Su(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;k=C,C=C+32|0,B=k+24|0,m=k+16|0,f=k+8|0,d=k,c=0;do l=s+380+(c<<3)|0,n[s+380+(c<<3)+4>>2]|0&&(F=l,O=n[F+4>>2]|0,M=f,n[M>>2]=n[F>>2],n[M+4>>2]=O,M=s+364+(c<<3)|0,O=n[M+4>>2]|0,F=d,n[F>>2]=n[M>>2],n[F+4>>2]=O,n[m>>2]=n[f>>2],n[m+4>>2]=n[f+4>>2],n[B>>2]=n[d>>2],n[B+4>>2]=n[d+4>>2],vu(m,B)|0)||(l=s+348+(c<<3)|0),n[s+992+(c<<2)>>2]=l,c=c+1|0;while((c|0)!=2);C=k}function Ls(s,l,c){s=s|0,l=l|0,c=y(c);var f=0;switch(s=n[s+992+(n[976+(l<<2)>>2]<<2)>>2]|0,n[s+4>>2]|0){case 0:case 3:{s=0;break}case 1:{y(h[s>>2])>2])>2]|0){case 2:{l=y(y(y(h[s>>2])*l)/y(100));break}case 1:{l=y(h[s>>2]);break}default:l=y(ue)}return y(l)}function mp(s,l,c,f,d){s=s|0,l=l|0,c=y(c),f=y(f),d=y(d);var m=0,B=Ze;l=n[s+944>>2]|0?l:1,m=hr(n[s+4>>2]|0,l)|0,l=Fd(m,l)|0,c=y(uD(s,m,c)),f=y(uD(s,l,f)),B=y(c+y(V(s,m,d))),h[s+400+(n[1040+(m<<2)>>2]<<2)>>2]=B,c=y(c+y(re(s,m,d))),h[s+400+(n[1e3+(m<<2)>>2]<<2)>>2]=c,c=y(f+y(V(s,l,d))),h[s+400+(n[1040+(l<<2)>>2]<<2)>>2]=c,d=y(f+y(re(s,l,d))),h[s+400+(n[1e3+(l<<2)>>2]<<2)>>2]=d}function jA(s,l,c,f){s=s|0,l=y(l),c=y(c),f=y(f);var d=0,m=0,B=Ze,k=Ze,F=0,O=0,M=Ze,j=0,oe=Ze,Ye=Ze,Me=Ze,Qe=Ze;if(l!=y(0)&&(d=s+400|0,Qe=y(h[d>>2]),m=s+404|0,Me=y(h[m>>2]),j=s+416|0,Ye=y(h[j>>2]),O=s+420|0,B=y(h[O>>2]),oe=y(Qe+c),M=y(Me+f),f=y(oe+Ye),k=y(M+B),F=(n[s+988>>2]|0)==1,h[d>>2]=y(Gi(Qe,l,0,F)),h[m>>2]=y(Gi(Me,l,0,F)),c=y(lT(y(Ye*l),y(1))),An(c,y(0))|0?m=0:m=(An(c,y(1))|0)^1,c=y(lT(y(B*l),y(1))),An(c,y(0))|0?d=0:d=(An(c,y(1))|0)^1,Qe=y(Gi(f,l,F&m,F&(m^1))),h[j>>2]=y(Qe-y(Gi(oe,l,0,F))),Qe=y(Gi(k,l,F&d,F&(d^1))),h[O>>2]=y(Qe-y(Gi(M,l,0,F))),m=(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2,m|0)){d=0;do jA(rs(s,d)|0,l,oe,M),d=d+1|0;while((d|0)!=(m|0))}}function kd(s,l,c,f,d){switch(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,c|0){case 5:case 0:{s=O7(n[489]|0,f,d)|0;break}default:s=HUe(f,d)|0}return s|0}function d0(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;d=C,C=C+16|0,m=d,n[m>>2]=f,yp(s,0,l,c,m),C=d}function yp(s,l,c,f,d){if(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,s=s|0?s:956,sY[n[s+8>>2]&1](s,l,c,f,d)|0,(c|0)==5)Tt();else return}function bl(s,l,c){s=s|0,l=l|0,c=c|0,o[s+l>>0]=c&1}function Qd(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(Ep(s,f),xt(s,n[l>>2]|0,n[c>>2]|0,f))}function Ep(s,l){s=s|0,l=l|0;var c=0;if((N(s)|0)>>>0>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Wt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function xt(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(xr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function N(s){return s=s|0,1073741823}function V(s,l,c){return s=s|0,l=l|0,c=y(c),ge(l)|0&&n[s+96>>2]|0?s=s+92|0:s=vn(s+60|0,n[1040+(l<<2)>>2]|0,992)|0,y(We(s,c))}function re(s,l,c){return s=s|0,l=l|0,c=y(c),ge(l)|0&&n[s+104>>2]|0?s=s+100|0:s=vn(s+60|0,n[1e3+(l<<2)>>2]|0,992)|0,y(We(s,c))}function ge(s){return s=s|0,(s|1|0)==3|0}function We(s,l){return s=s|0,l=y(l),(n[s+4>>2]|0)==3?l=y(0):l=y(Kr(s,l)),y(l)}function At(s,l){return s=s|0,l=l|0,s=n[s>>2]|0,(s|0?s:(l|0)>1?l:1)|0}function hr(s,l){s=s|0,l=l|0;var c=0;e:do if((l|0)==2){switch(s|0){case 2:{s=3;break e}case 3:break;default:{c=4;break e}}s=2}else c=4;while(!1);return s|0}function wr(s,l){s=s|0,l=l|0;var c=Ze;return ge(l)|0&&n[s+312>>2]|0&&(c=y(h[s+308>>2]),c>=y(0))||(c=y(Wn(y(h[(vn(s+276|0,n[1040+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function Rn(s,l){s=s|0,l=l|0;var c=Ze;return ge(l)|0&&n[s+320>>2]|0&&(c=y(h[s+316>>2]),c>=y(0))||(c=y(Wn(y(h[(vn(s+276|0,n[1e3+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function ai(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return ge(l)|0&&n[s+240>>2]|0&&(f=y(Kr(s+236|0,c)),f>=y(0))||(f=y(Wn(y(Kr(vn(s+204|0,n[1040+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function ns(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return ge(l)|0&&n[s+248>>2]|0&&(f=y(Kr(s+244|0,c)),f>=y(0))||(f=y(Wn(y(Kr(vn(s+204|0,n[1e3+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function GA(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Ze,F=Ze,O=Ze,M=Ze,j=Ze,oe=Ze,Ye=0,Me=0,Qe=0;Qe=C,C=C+16|0,Ye=Qe,Me=s+964|0,pi(s,(n[Me>>2]|0)!=0,3519),k=y(da(s,2,l)),F=y(da(s,0,l)),O=y(fn(s,2,l)),M=y(fn(s,0,l)),Mt(l)|0?j=l:j=y(Wn(y(0),y(y(l-O)-k))),Mt(c)|0?oe=c:oe=y(Wn(y(0),y(y(c-M)-F))),(f|0)==1&(d|0)==1?(h[s+908>>2]=y(On(s,2,y(l-O),m,m)),l=y(On(s,0,y(c-M),B,m))):(oY[n[Me>>2]&1](Ye,s,j,f,oe,d),j=y(k+y(h[Ye>>2])),oe=y(l-O),h[s+908>>2]=y(On(s,2,(f|2|0)==2?j:oe,m,m)),oe=y(F+y(h[Ye+4>>2])),l=y(c-M),l=y(On(s,0,(d|2|0)==2?oe:l,B,m))),h[s+912>>2]=l,C=Qe}function lD(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Ze,F=Ze,O=Ze,M=Ze;O=y(da(s,2,m)),k=y(da(s,0,m)),M=y(fn(s,2,m)),F=y(fn(s,0,m)),l=y(l-M),h[s+908>>2]=y(On(s,2,(f|2|0)==2?O:l,m,m)),c=y(c-F),h[s+912>>2]=y(On(s,0,(d|2|0)==2?k:c,B,m))}function Pw(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=0,F=Ze,O=Ze;return k=(f|0)==2,!(l<=y(0)&k)&&!(c<=y(0)&(d|0)==2)&&!((f|0)==1&(d|0)==1)?s=0:(F=y(fn(s,0,m)),O=y(fn(s,2,m)),k=l>2]=y(On(s,2,k?y(0):l,m,m)),l=y(c-F),k=c>2]=y(On(s,0,k?y(0):l,B,m)),s=1),s|0}function Fd(s,l){return s=s|0,l=l|0,E0(s)|0?s=hr(2,l)|0:s=0,s|0}function Cp(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(ai(s,l,c)),y(c+y(wr(s,l)))}function Sw(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(ns(s,l,c)),y(c+y(Rn(s,l)))}function da(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(Cp(s,l,c)),y(f+y(Sw(s,l,c)))}function bw(s){return s=s|0,n[s+24>>2]|0?s=0:y(YA(s))!=y(0)?s=1:s=y(wp(s))!=y(0),s|0}function YA(s){s=s|0;var l=Ze;if(n[s+944>>2]|0){if(l=y(h[s+44>>2]),Mt(l)|0)return l=y(h[s+40>>2]),s=l>y(0)&((Mt(l)|0)^1),y(s?l:y(0))}else l=y(0);return y(l)}function wp(s){s=s|0;var l=Ze,c=0,f=Ze;do if(n[s+944>>2]|0){if(l=y(h[s+48>>2]),Mt(l)|0){if(c=o[(n[s+976>>2]|0)+2>>0]|0,!(c<<24>>24)&&(f=y(h[s+40>>2]),f>24?y(1):y(0)}}else l=y(0);while(!1);return y(l)}function Rd(s){s=s|0;var l=0,c=0;if(sm(s+400|0,0,540)|0,o[s+985>>0]=1,ee(s),c=Di(s)|0,c|0){l=s+948|0,s=0;do Rd(n[(n[l>>2]|0)+(s<<2)>>2]|0),s=s+1|0;while((s|0)!=(c|0))}}function cD(s,l,c,f,d,m,B,k,F,O){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=y(m),B=y(B),k=k|0,F=F|0,O=O|0;var M=0,j=Ze,oe=0,Ye=0,Me=Ze,Qe=Ze,rt=0,Xe=Ze,ct=0,_e=Ze,Ge=0,Lt=0,_r=0,ur=0,Zt=0,kr=0,Mr=0,lr=0,Nn=0,lo=0;Nn=C,C=C+16|0,_r=Nn+12|0,ur=Nn+8|0,Zt=Nn+4|0,kr=Nn,lr=hr(n[s+4>>2]|0,F)|0,Ge=ge(lr)|0,j=y(Kr(GF(l)|0,Ge?m:B)),Lt=Ls(l,2,m)|0,Mr=Ls(l,0,B)|0;do if(!(Mt(j)|0)&&!(Mt(Ge?c:d)|0)){if(M=l+504|0,!(Mt(y(h[M>>2]))|0)&&(!(kw(n[l+976>>2]|0,0)|0)||(n[l+500>>2]|0)==(n[2278]|0)))break;h[M>>2]=y(Wn(j,y(da(l,lr,m))))}else oe=7;while(!1);do if((oe|0)==7){if(ct=Ge^1,!(ct|Lt^1)){B=y(Kr(n[l+992>>2]|0,m)),h[l+504>>2]=y(Wn(B,y(da(l,2,m))));break}if(!(Ge|Mr^1)){B=y(Kr(n[l+996>>2]|0,B)),h[l+504>>2]=y(Wn(B,y(da(l,0,m))));break}h[_r>>2]=y(ue),h[ur>>2]=y(ue),n[Zt>>2]=0,n[kr>>2]=0,Xe=y(fn(l,2,m)),_e=y(fn(l,0,m)),Lt?(Me=y(Xe+y(Kr(n[l+992>>2]|0,m))),h[_r>>2]=Me,n[Zt>>2]=1,Ye=1):(Ye=0,Me=y(ue)),Mr?(j=y(_e+y(Kr(n[l+996>>2]|0,B))),h[ur>>2]=j,n[kr>>2]=1,M=1):(M=0,j=y(ue)),oe=n[s+32>>2]|0,Ge&(oe|0)==2?oe=2:Mt(Me)|0&&!(Mt(c)|0)&&(h[_r>>2]=c,n[Zt>>2]=2,Ye=2,Me=c),!((oe|0)==2&ct)&&Mt(j)|0&&!(Mt(d)|0)&&(h[ur>>2]=d,n[kr>>2]=2,M=2,j=d),Qe=y(h[l+396>>2]),rt=Mt(Qe)|0;do if(rt)oe=Ye;else{if((Ye|0)==1&ct){h[ur>>2]=y(y(Me-Xe)/Qe),n[kr>>2]=1,M=1,oe=1;break}Ge&(M|0)==1?(h[_r>>2]=y(Qe*y(j-_e)),n[Zt>>2]=1,M=1,oe=1):oe=Ye}while(!1);lo=Mt(c)|0,Ye=(Yi(s,l)|0)!=4,!(Ge|Lt|((f|0)!=1|lo)|(Ye|(oe|0)==1))&&(h[_r>>2]=c,n[Zt>>2]=1,!rt)&&(h[ur>>2]=y(y(c-Xe)/Qe),n[kr>>2]=1,M=1),!(Mr|ct|((k|0)!=1|(Mt(d)|0))|(Ye|(M|0)==1))&&(h[ur>>2]=d,n[kr>>2]=1,!rt)&&(h[_r>>2]=y(Qe*y(d-_e)),n[Zt>>2]=1),bc(l,2,m,m,Zt,_r),bc(l,0,B,m,kr,ur),c=y(h[_r>>2]),d=y(h[ur>>2]),Va(l,c,d,F,n[Zt>>2]|0,n[kr>>2]|0,m,B,0,3565,O)|0,B=y(h[l+908+(n[976+(lr<<2)>>2]<<2)>>2]),h[l+504>>2]=y(Wn(B,y(da(l,lr,m))))}while(!1);n[l+500>>2]=n[2278],C=Nn}function On(s,l,c,f,d){return s=s|0,l=l|0,c=y(c),f=y(f),d=y(d),f=y(y0(s,l,c,f)),y(Wn(f,y(da(s,l,d))))}function Yi(s,l){return s=s|0,l=l|0,l=l+20|0,l=n[(n[l>>2]|0?l:s+16|0)>>2]|0,(l|0)==5&&E0(n[s+4>>2]|0)|0&&(l=1),l|0}function za(s,l){return s=s|0,l=l|0,ge(l)|0&&n[s+96>>2]|0?l=4:l=n[1040+(l<<2)>>2]|0,s+60+(l<<3)|0}function Ja(s,l){return s=s|0,l=l|0,ge(l)|0&&n[s+104>>2]|0?l=5:l=n[1e3+(l<<2)>>2]|0,s+60+(l<<3)|0}function bc(s,l,c,f,d,m){switch(s=s|0,l=l|0,c=y(c),f=y(f),d=d|0,m=m|0,c=y(Kr(s+380+(n[976+(l<<2)>>2]<<3)|0,c)),c=y(c+y(fn(s,l,f))),n[d>>2]|0){case 2:case 1:{d=Mt(c)|0,f=y(h[m>>2]),h[m>>2]=d|f>2]=2,h[m>>2]=c);break}default:}}function Ho(s,l){return s=s|0,l=l|0,s=s+132|0,ge(l)|0&&n[(vn(s,4,948)|0)+4>>2]|0?s=1:s=(n[(vn(s,n[1040+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function WA(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,ge(l)|0&&(f=vn(s,4,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=vn(s,n[1040+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Kr(f,c))),y(c)}function KA(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),f=y(f+y(V(s,l,c))),y(f+y(re(s,l,c)))}function HF(s){s=s|0;var l=0,c=0,f=0;e:do if(E0(n[s+4>>2]|0)|0)l=0;else if((n[s+16>>2]|0)!=5)if(c=Di(s)|0,!c)l=0;else for(l=0;;){if(f=rs(s,l)|0,!(n[f+24>>2]|0)&&(n[f+20>>2]|0)==5){l=1;break e}if(l=l+1|0,l>>>0>=c>>>0){l=0;break}}else l=1;while(!1);return l|0}function qF(s,l){s=s|0,l=l|0;var c=Ze;return c=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),c>=y(0)&((Mt(c)|0)^1)|0}function m0(s){s=s|0;var l=Ze,c=0,f=0,d=0,m=0,B=0,k=0,F=Ze;if(c=n[s+968>>2]|0,c)F=y(h[s+908>>2]),l=y(h[s+912>>2]),l=y(tY[c&0](s,F,l)),pi(s,(Mt(l)|0)^1,3573);else{m=Di(s)|0;do if(m|0){for(c=0,d=0;;){if(f=rs(s,d)|0,n[f+940>>2]|0){B=8;break}if((n[f+24>>2]|0)!=1)if(k=(Yi(s,f)|0)==5,k){c=f;break}else c=c|0?c:f;if(d=d+1|0,d>>>0>=m>>>0){B=8;break}}if((B|0)==8&&!c)break;return l=y(m0(c)),y(l+y(h[c+404>>2]))}while(!1);l=y(h[s+912>>2])}return y(l)}function y0(s,l,c,f){s=s|0,l=l|0,c=y(c),f=y(f);var d=Ze,m=0;return E0(l)|0?(l=1,m=3):ge(l)|0?(l=0,m=3):(f=y(ue),d=y(ue)),(m|0)==3&&(d=y(Kr(s+364+(l<<3)|0,f)),f=y(Kr(s+380+(l<<3)|0,f))),m=f=y(0)&((Mt(f)|0)^1)),c=m?f:c,m=d>=y(0)&((Mt(d)|0)^1)&c>2]|0,m)|0,Me=Fd(rt,m)|0,Qe=ge(rt)|0,j=y(fn(l,2,c)),oe=y(fn(l,0,c)),Ls(l,2,c)|0?k=y(j+y(Kr(n[l+992>>2]|0,c))):Ho(l,2)|0&&Td(l,2)|0?(k=y(h[s+908>>2]),F=y(wr(s,2)),F=y(k-y(F+y(Rn(s,2)))),k=y(WA(l,2,c)),k=y(On(l,2,y(F-y(k+y(Ip(l,2,c)))),c,c))):k=y(ue),Ls(l,0,d)|0?F=y(oe+y(Kr(n[l+996>>2]|0,d))):Ho(l,0)|0&&Td(l,0)|0?(F=y(h[s+912>>2]),ct=y(wr(s,0)),ct=y(F-y(ct+y(Rn(s,0)))),F=y(WA(l,0,d)),F=y(On(l,0,y(ct-y(F+y(Ip(l,0,d)))),d,c))):F=y(ue),O=Mt(k)|0,M=Mt(F)|0;do if(O^M&&(Ye=y(h[l+396>>2]),!(Mt(Ye)|0)))if(O){k=y(j+y(y(F-oe)*Ye));break}else{ct=y(oe+y(y(k-j)/Ye)),F=M?ct:F;break}while(!1);M=Mt(k)|0,O=Mt(F)|0,M|O&&(_e=(M^1)&1,f=c>y(0)&((f|0)!=0&M),k=Qe?k:f?c:k,Va(l,k,F,m,Qe?_e:f?2:_e,M&(O^1)&1,k,F,0,3623,B)|0,k=y(h[l+908>>2]),k=y(k+y(fn(l,2,c))),F=y(h[l+912>>2]),F=y(F+y(fn(l,0,c)))),Va(l,k,F,m,1,1,k,F,1,3635,B)|0,Td(l,rt)|0&&!(Ho(l,rt)|0)?(_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),ct=y(ct-y(Rn(s,rt))),ct=y(ct-y(re(l,rt,c))),ct=y(ct-y(Ip(l,rt,Qe?c:d))),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct):Xe=21;do if((Xe|0)==21){if(!(Ho(l,rt)|0)&&(n[s+8>>2]|0)==1){_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(y(ct-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct;break}!(Ho(l,rt)|0)&&(n[s+8>>2]|0)==2&&(_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct)}while(!1);Td(l,Me)|0&&!(Ho(l,Me)|0)?(_e=n[976+(Me<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),ct=y(ct-y(Rn(s,Me))),ct=y(ct-y(re(l,Me,c))),ct=y(ct-y(Ip(l,Me,Qe?d:c))),h[l+400+(n[1040+(Me<<2)>>2]<<2)>>2]=ct):Xe=30;do if((Xe|0)==30&&!(Ho(l,Me)|0)){if((Yi(s,l)|0)==2){_e=n[976+(Me<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(y(ct-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+(Me<<2)>>2]<<2)>>2]=ct;break}_e=(Yi(s,l)|0)==3,_e^(n[s+28>>2]|0)==2&&(_e=n[976+(Me<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+(Me<<2)>>2]<<2)>>2]=ct)}while(!1)}function xw(s,l,c){s=s|0,l=l|0,c=c|0;var f=Ze,d=0;d=n[976+(c<<2)>>2]|0,f=y(h[l+908+(d<<2)>>2]),f=y(y(h[s+908+(d<<2)>>2])-f),f=y(f-y(h[l+400+(n[1040+(c<<2)>>2]<<2)>>2])),h[l+400+(n[1e3+(c<<2)>>2]<<2)>>2]=f}function E0(s){return s=s|0,(s|1|0)==1|0}function GF(s){s=s|0;var l=Ze;switch(n[s+56>>2]|0){case 0:case 3:{l=y(h[s+40>>2]),l>y(0)&((Mt(l)|0)^1)?s=o[(n[s+976>>2]|0)+2>>0]|0?1056:992:s=1056;break}default:s=s+52|0}return s|0}function kw(s,l){return s=s|0,l=l|0,(o[s+l>>0]|0)!=0|0}function Td(s,l){return s=s|0,l=l|0,s=s+132|0,ge(l)|0&&n[(vn(s,5,948)|0)+4>>2]|0?s=1:s=(n[(vn(s,n[1e3+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function Ip(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,ge(l)|0&&(f=vn(s,5,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=vn(s,n[1e3+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Kr(f,c))),y(c)}function uD(s,l,c){return s=s|0,l=l|0,c=y(c),Ho(s,l)|0?c=y(WA(s,l,c)):c=y(-y(Ip(s,l,c))),y(c)}function AD(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function Nd(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Wt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function fD(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Ld(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function pD(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;if(B=s+4|0,k=n[B>>2]|0,d=k-f|0,m=d>>2,s=l+(m<<2)|0,s>>>0>>0){f=k;do n[f>>2]=n[s>>2],s=s+4|0,f=(n[B>>2]|0)+4|0,n[B>>2]=f;while(s>>>0>>0)}m|0&&rI(k+(0-m<<2)|0,l|0,d|0)|0}function hD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0;return k=l+4|0,F=n[k>>2]|0,d=n[s>>2]|0,B=c,m=B-d|0,f=F+(0-(m>>2)<<2)|0,n[k>>2]=f,(m|0)>0&&xr(f|0,d|0,m|0)|0,d=s+4|0,m=l+8|0,f=(n[d>>2]|0)-B|0,(f|0)>0&&(xr(n[m>>2]|0,c|0,f|0)|0,n[m>>2]=(n[m>>2]|0)+(f>>>2<<2)),B=n[s>>2]|0,n[s>>2]=n[k>>2],n[k>>2]=B,B=n[d>>2]|0,n[d>>2]=n[m>>2],n[m>>2]=B,B=s+8|0,c=l+12|0,s=n[B>>2]|0,n[B>>2]=n[c>>2],n[c>>2]=s,n[l>>2]=n[k>>2],F|0}function Qw(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(B=n[l>>2]|0,m=n[c>>2]|0,(B|0)!=(m|0)){d=s+8|0,c=((m+-4-B|0)>>>2)+1|0,s=B,f=n[d>>2]|0;do n[f>>2]=n[s>>2],f=(n[d>>2]|0)+4|0,n[d>>2]=f,s=s+4|0;while((s|0)!=(m|0));n[l>>2]=B+(c<<2)}}function Fw(){Mo()}function gD(){var s=0;return s=Wt(4)|0,Rw(s),s|0}function Rw(s){s=s|0,n[s>>2]=Sl()|0}function dD(s){s=s|0,s|0&&(C0(s),yt(s))}function C0(s){s=s|0,it(n[s>>2]|0)}function YF(s,l,c){s=s|0,l=l|0,c=c|0,bl(n[s>>2]|0,l,c)}function Md(s,l){s=s|0,l=y(l),dp(n[s>>2]|0,l)}function Od(s,l){return s=s|0,l=l|0,kw(n[s>>2]|0,l)|0}function Ud(){var s=0;return s=Wt(8)|0,w0(s,0),s|0}function w0(s,l){s=s|0,l=l|0,l?l=Oo(n[l>>2]|0)|0:l=qi()|0,n[s>>2]=l,n[s+4>>2]=0,Pn(l,s)}function _d(s){s=s|0;var l=0;return l=Wt(8)|0,w0(l,s),l|0}function I0(s){s=s|0,s|0&&(Hd(s),yt(s))}function Hd(s){s=s|0;var l=0;Dl(n[s>>2]|0),l=s+4|0,s=n[l>>2]|0,n[l>>2]=0,s|0&&(bu(s),yt(s))}function bu(s){s=s|0,xu(s)}function xu(s){s=s|0,s=n[s>>2]|0,s|0&&sa(s|0)}function Tw(s){return s=s|0,fa(s)|0}function Nw(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(bu(l),yt(l)),Pl(n[s>>2]|0)}function qd(s,l){s=s|0,l=l|0,sn(n[s>>2]|0,n[l>>2]|0)}function WF(s,l){s=s|0,l=l|0,fp(n[s>>2]|0,l)}function KF(s,l,c){s=s|0,l=l|0,c=+c,Pd(n[s>>2]|0,l,y(c))}function jd(s,l,c){s=s|0,l=l|0,c=+c,Sd(n[s>>2]|0,l,y(c))}function Lw(s,l){s=s|0,l=l|0,cp(n[s>>2]|0,l)}function Mw(s,l){s=s|0,l=l|0,to(n[s>>2]|0,l)}function Sr(s,l){s=s|0,l=l|0,Ap(n[s>>2]|0,l)}function Ms(s,l){s=s|0,l=l|0,Id(n[s>>2]|0,l)}function Mi(s,l){s=s|0,l=l|0,o0(n[s>>2]|0,l)}function ms(s,l){s=s|0,l=l|0,eo(n[s>>2]|0,l)}function VA(s,l,c){s=s|0,l=l|0,c=+c,MA(n[s>>2]|0,l,y(c))}function Ow(s,l,c){s=s|0,l=l|0,c=+c,Y(n[s>>2]|0,l,y(c))}function is(s,l){s=s|0,l=l|0,OA(n[s>>2]|0,l)}function Gd(s,l){s=s|0,l=l|0,vd(n[s>>2]|0,l)}function Bp(s,l){s=s|0,l=l|0,ro(n[s>>2]|0,l)}function B0(s,l){s=s|0,l=+l,pp(n[s>>2]|0,y(l))}function vp(s,l){s=s|0,l=+l,Wa(n[s>>2]|0,y(l))}function Uw(s,l){s=s|0,l=+l,Dd(n[s>>2]|0,y(l))}function _w(s,l){s=s|0,l=+l,l0(n[s>>2]|0,y(l))}function Hw(s,l){s=s|0,l=+l,Ya(n[s>>2]|0,y(l))}function qw(s,l){s=s|0,l=+l,c0(n[s>>2]|0,y(l))}function ku(s,l){s=s|0,l=+l,Dw(n[s>>2]|0,y(l))}function ir(s){s=s|0,hp(n[s>>2]|0)}function Yd(s,l){s=s|0,l=+l,Li(n[s>>2]|0,y(l))}function jw(s,l){s=s|0,l=+l,wu(n[s>>2]|0,y(l))}function xl(s){s=s|0,pa(n[s>>2]|0)}function Qu(s,l){s=s|0,l=+l,Bc(n[s>>2]|0,y(l))}function v0(s,l){s=s|0,l=+l,Iu(n[s>>2]|0,y(l))}function D0(s,l){s=s|0,l=+l,oi(n[s>>2]|0,y(l))}function Gw(s,l){s=s|0,l=+l,UA(n[s>>2]|0,y(l))}function Yw(s,l){s=s|0,l=+l,Uo(n[s>>2]|0,y(l))}function xc(s,l){s=s|0,l=+l,ga(n[s>>2]|0,y(l))}function P0(s,l){s=s|0,l=+l,gp(n[s>>2]|0,y(l))}function Ww(s,l){s=s|0,l=+l,f0(n[s>>2]|0,y(l))}function Wd(s,l){s=s|0,l=+l,_A(n[s>>2]|0,y(l))}function kc(s,l,c){s=s|0,l=l|0,c=+c,Ic(n[s>>2]|0,l,y(c))}function Kd(s,l,c){s=s|0,l=l|0,c=+c,no(n[s>>2]|0,l,y(c))}function S0(s,l,c){s=s|0,l=l|0,c=+c,Cu(n[s>>2]|0,l,y(c))}function b0(s){return s=s|0,s0(n[s>>2]|0)|0}function oo(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,LA(d,n[l>>2]|0,c),ss(s,d),C=f}function ss(s,l){s=s|0,l=l|0,Xa(s,n[l+4>>2]|0,+y(h[l>>2]))}function Xa(s,l,c){s=s|0,l=l|0,c=+c,n[s>>2]=l,E[s+8>>3]=c}function Vd(s){return s=s|0,vw(n[s>>2]|0)|0}function qo(s){return s=s|0,up(n[s>>2]|0)|0}function mD(s){return s=s|0,wc(n[s>>2]|0)|0}function Dp(s){return s=s|0,Bw(n[s>>2]|0)|0}function Kw(s){return s=s|0,a0(n[s>>2]|0)|0}function VF(s){return s=s|0,Bd(n[s>>2]|0)|0}function yD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,bt(d,n[l>>2]|0,c),ss(s,d),C=f}function ED(s){return s=s|0,Eu(n[s>>2]|0)|0}function zd(s){return s=s|0,Ga(n[s>>2]|0)|0}function Vw(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,NA(f,n[l>>2]|0),ss(s,f),C=c}function Pp(s){return s=s|0,+ +y(ei(n[s>>2]|0))}function CD(s){return s=s|0,+ +y(Qi(n[s>>2]|0))}function wD(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,cr(f,n[l>>2]|0),ss(s,f),C=c}function x0(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,u0(f,n[l>>2]|0),ss(s,f),C=c}function zF(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,It(f,n[l>>2]|0),ss(s,f),C=c}function JF(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,ha(f,n[l>>2]|0),ss(s,f),C=c}function ID(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,A0(f,n[l>>2]|0),ss(s,f),C=c}function BD(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,xd(f,n[l>>2]|0),ss(s,f),C=c}function zA(s){return s=s|0,+ +y(p0(n[s>>2]|0))}function XF(s,l){return s=s|0,l=l|0,+ +y(bd(n[s>>2]|0,l))}function ZF(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,dt(d,n[l>>2]|0,c),ss(s,d),C=f}function Qc(s,l,c){s=s|0,l=l|0,c=c|0,ar(n[s>>2]|0,n[l>>2]|0,c)}function $F(s,l){s=s|0,l=l|0,yu(n[s>>2]|0,n[l>>2]|0)}function vD(s){return s=s|0,Di(n[s>>2]|0)|0}function eR(s){return s=s|0,s=mt(n[s>>2]|0)|0,s?s=Tw(s)|0:s=0,s|0}function DD(s,l){return s=s|0,l=l|0,s=rs(n[s>>2]|0,l)|0,s?s=Tw(s)|0:s=0,s|0}function Fu(s,l){s=s|0,l=l|0;var c=0,f=0;f=Wt(4)|0,PD(f,l),c=s+4|0,l=n[c>>2]|0,n[c>>2]=f,l|0&&(bu(l),yt(l)),vt(n[s>>2]|0,1)}function PD(s,l){s=s|0,l=l|0,iR(s,l)}function tR(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,SD(k,fa(l)|0,+c,f,+d,m),h[s>>2]=y(+E[k>>3]),h[s+4>>2]=y(+E[k+8>>3]),C=B}function SD(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0,k=0,F=0,O=0,M=0;B=C,C=C+32|0,M=B+8|0,O=B+20|0,F=B,k=B+16|0,E[M>>3]=c,n[O>>2]=f,E[F>>3]=d,n[k>>2]=m,Jd(s,n[l+4>>2]|0,M,O,F,k),C=B}function Jd(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,$a(k),l=ys(l)|0,bD(s,l,+E[c>>3],n[f>>2]|0,+E[d>>3],n[m>>2]|0),el(k),C=B}function ys(s){return s=s|0,n[s>>2]|0}function bD(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0;B=jo(zw()|0)|0,c=+ma(c),f=Xd(f)|0,d=+ma(d),rR(s,qn(0,B|0,l|0,+c,f|0,+d,Xd(m)|0)|0)}function zw(){var s=0;return o[7608]|0||(Xw(9120),s=7608,n[s>>2]=1,n[s+4>>2]=0),9120}function jo(s){return s=s|0,n[s+8>>2]|0}function ma(s){return s=+s,+ +Ru(s)}function Xd(s){return s=s|0,k0(s)|0}function rR(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=l,f&1?(ya(c,0),ia(f|0,c|0)|0,Jw(s,c),nR(c)):(n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]),C=d}function ya(s,l){s=s|0,l=l|0,Fc(s,l),n[s+8>>2]=0,o[s+24>>0]=0}function Jw(s,l){s=s|0,l=l|0,l=l+8|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]}function nR(s){s=s|0,o[s+24>>0]=0}function Fc(s,l){s=s|0,l=l|0,n[s>>2]=l}function k0(s){return s=s|0,s|0}function Ru(s){return s=+s,+s}function Xw(s){s=s|0,ao(s,Zw()|0,4)}function Zw(){return 1064}function ao(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=ki(l|0,c+1|0)|0}function iR(s,l){s=s|0,l=l|0,l=n[l>>2]|0,n[s>>2]=l,hc(l|0)}function xD(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(bu(l),yt(l)),vt(n[s>>2]|0,0)}function kD(s){s=s|0,Dt(n[s>>2]|0)}function Zd(s){return s=s|0,er(n[s>>2]|0)|0}function sR(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,qA(n[s>>2]|0,y(l),y(c),f)}function oR(s){return s=s|0,+ +y(vc(n[s>>2]|0))}function v(s){return s=s|0,+ +y(Bu(n[s>>2]|0))}function P(s){return s=s|0,+ +y(Dc(n[s>>2]|0))}function Q(s){return s=s|0,+ +y(gs(n[s>>2]|0))}function H(s){return s=s|0,+ +y(Pc(n[s>>2]|0))}function W(s){return s=s|0,+ +y(Mn(n[s>>2]|0))}function ne(s,l){s=s|0,l=l|0,E[s>>3]=+y(vc(n[l>>2]|0)),E[s+8>>3]=+y(Bu(n[l>>2]|0)),E[s+16>>3]=+y(Dc(n[l>>2]|0)),E[s+24>>3]=+y(gs(n[l>>2]|0)),E[s+32>>3]=+y(Pc(n[l>>2]|0)),E[s+40>>3]=+y(Mn(n[l>>2]|0))}function Be(s,l){return s=s|0,l=l|0,+ +y(ji(n[s>>2]|0,l))}function Ue(s,l){return s=s|0,l=l|0,+ +y(Ci(n[s>>2]|0,l))}function ft(s,l){return s=s|0,l=l|0,+ +y(HA(n[s>>2]|0,l))}function jt(){return Dn()|0}function Ir(){Tr(),Xt(),jn(),li(),Ea(),$e()}function Tr(){SNe(11713,4938,1)}function Xt(){WTe(10448)}function jn(){STe(10408)}function li(){JRe(10324)}function Ea(){iFe(10096)}function $e(){je(9132)}function je(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Lt=0,_r=0,ur=0,Zt=0,kr=0,Mr=0,lr=0,Nn=0,lo=0,co=0,uo=0,wa=0,Np=0,Lp=0,kl=0,Mp=0,Lu=0,Mu=0,Op=0,Up=0,_p=0,$r=0,Ql=0,Hp=0,Nc=0,qp=0,jp=0,Ou=0,Uu=0,Lc=0,Os=0,rl=0,Go=0,Fl=0,rf=0,nf=0,_u=0,sf=0,of=0,Us=0,Cs=0,Rl=0,Un=0,af=0,Ao=0,Mc=0,fo=0,Oc=0,lf=0,cf=0,Uc=0,_s=0,Tl=0,uf=0,Af=0,ff=0,Fr=0,ri=0,ws=0,po=0,Hs=0,Nr=0,Ar=0,Nl=0;l=C,C=C+672|0,c=l+656|0,Nl=l+648|0,Ar=l+640|0,Nr=l+632|0,Hs=l+624|0,po=l+616|0,ws=l+608|0,ri=l+600|0,Fr=l+592|0,ff=l+584|0,Af=l+576|0,uf=l+568|0,Tl=l+560|0,_s=l+552|0,Uc=l+544|0,cf=l+536|0,lf=l+528|0,Oc=l+520|0,fo=l+512|0,Mc=l+504|0,Ao=l+496|0,af=l+488|0,Un=l+480|0,Rl=l+472|0,Cs=l+464|0,Us=l+456|0,of=l+448|0,sf=l+440|0,_u=l+432|0,nf=l+424|0,rf=l+416|0,Fl=l+408|0,Go=l+400|0,rl=l+392|0,Os=l+384|0,Lc=l+376|0,Uu=l+368|0,Ou=l+360|0,jp=l+352|0,qp=l+344|0,Nc=l+336|0,Hp=l+328|0,Ql=l+320|0,$r=l+312|0,_p=l+304|0,Up=l+296|0,Op=l+288|0,Mu=l+280|0,Lu=l+272|0,Mp=l+264|0,kl=l+256|0,Lp=l+248|0,Np=l+240|0,wa=l+232|0,uo=l+224|0,co=l+216|0,lo=l+208|0,Nn=l+200|0,lr=l+192|0,Mr=l+184|0,kr=l+176|0,Zt=l+168|0,ur=l+160|0,_r=l+152|0,Lt=l+144|0,Ge=l+136|0,_e=l+128|0,ct=l+120|0,Xe=l+112|0,rt=l+104|0,Qe=l+96|0,Me=l+88|0,Ye=l+80|0,oe=l+72|0,j=l+64|0,M=l+56|0,O=l+48|0,F=l+40|0,k=l+32|0,B=l+24|0,m=l+16|0,d=l+8|0,f=l,pt(s,3646),Jt(s,3651,2)|0,Br(s,3665,2)|0,Yn(s,3682,18)|0,n[Nl>>2]=19,n[Nl+4>>2]=0,n[c>>2]=n[Nl>>2],n[c+4>>2]=n[Nl+4>>2],br(s,3690,c)|0,n[Ar>>2]=1,n[Ar+4>>2]=0,n[c>>2]=n[Ar>>2],n[c+4>>2]=n[Ar+4>>2],Sn(s,3696,c)|0,n[Nr>>2]=2,n[Nr+4>>2]=0,n[c>>2]=n[Nr>>2],n[c+4>>2]=n[Nr+4>>2],Tn(s,3706,c)|0,n[Hs>>2]=1,n[Hs+4>>2]=0,n[c>>2]=n[Hs>>2],n[c+4>>2]=n[Hs+4>>2],Wr(s,3722,c)|0,n[po>>2]=2,n[po+4>>2]=0,n[c>>2]=n[po>>2],n[c+4>>2]=n[po+4>>2],Wr(s,3734,c)|0,n[ws>>2]=3,n[ws+4>>2]=0,n[c>>2]=n[ws>>2],n[c+4>>2]=n[ws+4>>2],Tn(s,3753,c)|0,n[ri>>2]=4,n[ri+4>>2]=0,n[c>>2]=n[ri>>2],n[c+4>>2]=n[ri+4>>2],Tn(s,3769,c)|0,n[Fr>>2]=5,n[Fr+4>>2]=0,n[c>>2]=n[Fr>>2],n[c+4>>2]=n[Fr+4>>2],Tn(s,3783,c)|0,n[ff>>2]=6,n[ff+4>>2]=0,n[c>>2]=n[ff>>2],n[c+4>>2]=n[ff+4>>2],Tn(s,3796,c)|0,n[Af>>2]=7,n[Af+4>>2]=0,n[c>>2]=n[Af>>2],n[c+4>>2]=n[Af+4>>2],Tn(s,3813,c)|0,n[uf>>2]=8,n[uf+4>>2]=0,n[c>>2]=n[uf>>2],n[c+4>>2]=n[uf+4>>2],Tn(s,3825,c)|0,n[Tl>>2]=3,n[Tl+4>>2]=0,n[c>>2]=n[Tl>>2],n[c+4>>2]=n[Tl+4>>2],Wr(s,3843,c)|0,n[_s>>2]=4,n[_s+4>>2]=0,n[c>>2]=n[_s>>2],n[c+4>>2]=n[_s+4>>2],Wr(s,3853,c)|0,n[Uc>>2]=9,n[Uc+4>>2]=0,n[c>>2]=n[Uc>>2],n[c+4>>2]=n[Uc+4>>2],Tn(s,3870,c)|0,n[cf>>2]=10,n[cf+4>>2]=0,n[c>>2]=n[cf>>2],n[c+4>>2]=n[cf+4>>2],Tn(s,3884,c)|0,n[lf>>2]=11,n[lf+4>>2]=0,n[c>>2]=n[lf>>2],n[c+4>>2]=n[lf+4>>2],Tn(s,3896,c)|0,n[Oc>>2]=1,n[Oc+4>>2]=0,n[c>>2]=n[Oc>>2],n[c+4>>2]=n[Oc+4>>2],ti(s,3907,c)|0,n[fo>>2]=2,n[fo+4>>2]=0,n[c>>2]=n[fo>>2],n[c+4>>2]=n[fo+4>>2],ti(s,3915,c)|0,n[Mc>>2]=3,n[Mc+4>>2]=0,n[c>>2]=n[Mc>>2],n[c+4>>2]=n[Mc+4>>2],ti(s,3928,c)|0,n[Ao>>2]=4,n[Ao+4>>2]=0,n[c>>2]=n[Ao>>2],n[c+4>>2]=n[Ao+4>>2],ti(s,3948,c)|0,n[af>>2]=5,n[af+4>>2]=0,n[c>>2]=n[af>>2],n[c+4>>2]=n[af+4>>2],ti(s,3960,c)|0,n[Un>>2]=6,n[Un+4>>2]=0,n[c>>2]=n[Un>>2],n[c+4>>2]=n[Un+4>>2],ti(s,3974,c)|0,n[Rl>>2]=7,n[Rl+4>>2]=0,n[c>>2]=n[Rl>>2],n[c+4>>2]=n[Rl+4>>2],ti(s,3983,c)|0,n[Cs>>2]=20,n[Cs+4>>2]=0,n[c>>2]=n[Cs>>2],n[c+4>>2]=n[Cs+4>>2],br(s,3999,c)|0,n[Us>>2]=8,n[Us+4>>2]=0,n[c>>2]=n[Us>>2],n[c+4>>2]=n[Us+4>>2],ti(s,4012,c)|0,n[of>>2]=9,n[of+4>>2]=0,n[c>>2]=n[of>>2],n[c+4>>2]=n[of+4>>2],ti(s,4022,c)|0,n[sf>>2]=21,n[sf+4>>2]=0,n[c>>2]=n[sf>>2],n[c+4>>2]=n[sf+4>>2],br(s,4039,c)|0,n[_u>>2]=10,n[_u+4>>2]=0,n[c>>2]=n[_u>>2],n[c+4>>2]=n[_u+4>>2],ti(s,4053,c)|0,n[nf>>2]=11,n[nf+4>>2]=0,n[c>>2]=n[nf>>2],n[c+4>>2]=n[nf+4>>2],ti(s,4065,c)|0,n[rf>>2]=12,n[rf+4>>2]=0,n[c>>2]=n[rf>>2],n[c+4>>2]=n[rf+4>>2],ti(s,4084,c)|0,n[Fl>>2]=13,n[Fl+4>>2]=0,n[c>>2]=n[Fl>>2],n[c+4>>2]=n[Fl+4>>2],ti(s,4097,c)|0,n[Go>>2]=14,n[Go+4>>2]=0,n[c>>2]=n[Go>>2],n[c+4>>2]=n[Go+4>>2],ti(s,4117,c)|0,n[rl>>2]=15,n[rl+4>>2]=0,n[c>>2]=n[rl>>2],n[c+4>>2]=n[rl+4>>2],ti(s,4129,c)|0,n[Os>>2]=16,n[Os+4>>2]=0,n[c>>2]=n[Os>>2],n[c+4>>2]=n[Os+4>>2],ti(s,4148,c)|0,n[Lc>>2]=17,n[Lc+4>>2]=0,n[c>>2]=n[Lc>>2],n[c+4>>2]=n[Lc+4>>2],ti(s,4161,c)|0,n[Uu>>2]=18,n[Uu+4>>2]=0,n[c>>2]=n[Uu>>2],n[c+4>>2]=n[Uu+4>>2],ti(s,4181,c)|0,n[Ou>>2]=5,n[Ou+4>>2]=0,n[c>>2]=n[Ou>>2],n[c+4>>2]=n[Ou+4>>2],Wr(s,4196,c)|0,n[jp>>2]=6,n[jp+4>>2]=0,n[c>>2]=n[jp>>2],n[c+4>>2]=n[jp+4>>2],Wr(s,4206,c)|0,n[qp>>2]=7,n[qp+4>>2]=0,n[c>>2]=n[qp>>2],n[c+4>>2]=n[qp+4>>2],Wr(s,4217,c)|0,n[Nc>>2]=3,n[Nc+4>>2]=0,n[c>>2]=n[Nc>>2],n[c+4>>2]=n[Nc+4>>2],Rc(s,4235,c)|0,n[Hp>>2]=1,n[Hp+4>>2]=0,n[c>>2]=n[Hp>>2],n[c+4>>2]=n[Hp+4>>2],aR(s,4251,c)|0,n[Ql>>2]=4,n[Ql+4>>2]=0,n[c>>2]=n[Ql>>2],n[c+4>>2]=n[Ql+4>>2],Rc(s,4263,c)|0,n[$r>>2]=5,n[$r+4>>2]=0,n[c>>2]=n[$r>>2],n[c+4>>2]=n[$r+4>>2],Rc(s,4279,c)|0,n[_p>>2]=6,n[_p+4>>2]=0,n[c>>2]=n[_p>>2],n[c+4>>2]=n[_p+4>>2],Rc(s,4293,c)|0,n[Up>>2]=7,n[Up+4>>2]=0,n[c>>2]=n[Up>>2],n[c+4>>2]=n[Up+4>>2],Rc(s,4306,c)|0,n[Op>>2]=8,n[Op+4>>2]=0,n[c>>2]=n[Op>>2],n[c+4>>2]=n[Op+4>>2],Rc(s,4323,c)|0,n[Mu>>2]=9,n[Mu+4>>2]=0,n[c>>2]=n[Mu>>2],n[c+4>>2]=n[Mu+4>>2],Rc(s,4335,c)|0,n[Lu>>2]=2,n[Lu+4>>2]=0,n[c>>2]=n[Lu>>2],n[c+4>>2]=n[Lu+4>>2],aR(s,4353,c)|0,n[Mp>>2]=12,n[Mp+4>>2]=0,n[c>>2]=n[Mp>>2],n[c+4>>2]=n[Mp+4>>2],Q0(s,4363,c)|0,n[kl>>2]=1,n[kl+4>>2]=0,n[c>>2]=n[kl>>2],n[c+4>>2]=n[kl+4>>2],JA(s,4376,c)|0,n[Lp>>2]=2,n[Lp+4>>2]=0,n[c>>2]=n[Lp>>2],n[c+4>>2]=n[Lp+4>>2],JA(s,4388,c)|0,n[Np>>2]=13,n[Np+4>>2]=0,n[c>>2]=n[Np>>2],n[c+4>>2]=n[Np+4>>2],Q0(s,4402,c)|0,n[wa>>2]=14,n[wa+4>>2]=0,n[c>>2]=n[wa>>2],n[c+4>>2]=n[wa+4>>2],Q0(s,4411,c)|0,n[uo>>2]=15,n[uo+4>>2]=0,n[c>>2]=n[uo>>2],n[c+4>>2]=n[uo+4>>2],Q0(s,4421,c)|0,n[co>>2]=16,n[co+4>>2]=0,n[c>>2]=n[co>>2],n[c+4>>2]=n[co+4>>2],Q0(s,4433,c)|0,n[lo>>2]=17,n[lo+4>>2]=0,n[c>>2]=n[lo>>2],n[c+4>>2]=n[lo+4>>2],Q0(s,4446,c)|0,n[Nn>>2]=18,n[Nn+4>>2]=0,n[c>>2]=n[Nn>>2],n[c+4>>2]=n[Nn+4>>2],Q0(s,4458,c)|0,n[lr>>2]=3,n[lr+4>>2]=0,n[c>>2]=n[lr>>2],n[c+4>>2]=n[lr+4>>2],JA(s,4471,c)|0,n[Mr>>2]=1,n[Mr+4>>2]=0,n[c>>2]=n[Mr>>2],n[c+4>>2]=n[Mr+4>>2],QD(s,4486,c)|0,n[kr>>2]=10,n[kr+4>>2]=0,n[c>>2]=n[kr>>2],n[c+4>>2]=n[kr+4>>2],Rc(s,4496,c)|0,n[Zt>>2]=11,n[Zt+4>>2]=0,n[c>>2]=n[Zt>>2],n[c+4>>2]=n[Zt+4>>2],Rc(s,4508,c)|0,n[ur>>2]=3,n[ur+4>>2]=0,n[c>>2]=n[ur>>2],n[c+4>>2]=n[ur+4>>2],aR(s,4519,c)|0,n[_r>>2]=4,n[_r+4>>2]=0,n[c>>2]=n[_r>>2],n[c+4>>2]=n[_r+4>>2],Nve(s,4530,c)|0,n[Lt>>2]=19,n[Lt+4>>2]=0,n[c>>2]=n[Lt>>2],n[c+4>>2]=n[Lt+4>>2],Lve(s,4542,c)|0,n[Ge>>2]=12,n[Ge+4>>2]=0,n[c>>2]=n[Ge>>2],n[c+4>>2]=n[Ge+4>>2],Mve(s,4554,c)|0,n[_e>>2]=13,n[_e+4>>2]=0,n[c>>2]=n[_e>>2],n[c+4>>2]=n[_e+4>>2],Ove(s,4568,c)|0,n[ct>>2]=2,n[ct+4>>2]=0,n[c>>2]=n[ct>>2],n[c+4>>2]=n[ct+4>>2],Uve(s,4578,c)|0,n[Xe>>2]=20,n[Xe+4>>2]=0,n[c>>2]=n[Xe>>2],n[c+4>>2]=n[Xe+4>>2],_ve(s,4587,c)|0,n[rt>>2]=22,n[rt+4>>2]=0,n[c>>2]=n[rt>>2],n[c+4>>2]=n[rt+4>>2],br(s,4602,c)|0,n[Qe>>2]=23,n[Qe+4>>2]=0,n[c>>2]=n[Qe>>2],n[c+4>>2]=n[Qe+4>>2],br(s,4619,c)|0,n[Me>>2]=14,n[Me+4>>2]=0,n[c>>2]=n[Me>>2],n[c+4>>2]=n[Me+4>>2],Hve(s,4629,c)|0,n[Ye>>2]=1,n[Ye+4>>2]=0,n[c>>2]=n[Ye>>2],n[c+4>>2]=n[Ye+4>>2],qve(s,4637,c)|0,n[oe>>2]=4,n[oe+4>>2]=0,n[c>>2]=n[oe>>2],n[c+4>>2]=n[oe+4>>2],JA(s,4653,c)|0,n[j>>2]=5,n[j+4>>2]=0,n[c>>2]=n[j>>2],n[c+4>>2]=n[j+4>>2],JA(s,4669,c)|0,n[M>>2]=6,n[M+4>>2]=0,n[c>>2]=n[M>>2],n[c+4>>2]=n[M+4>>2],JA(s,4686,c)|0,n[O>>2]=7,n[O+4>>2]=0,n[c>>2]=n[O>>2],n[c+4>>2]=n[O+4>>2],JA(s,4701,c)|0,n[F>>2]=8,n[F+4>>2]=0,n[c>>2]=n[F>>2],n[c+4>>2]=n[F+4>>2],JA(s,4719,c)|0,n[k>>2]=9,n[k+4>>2]=0,n[c>>2]=n[k>>2],n[c+4>>2]=n[k+4>>2],JA(s,4736,c)|0,n[B>>2]=21,n[B+4>>2]=0,n[c>>2]=n[B>>2],n[c+4>>2]=n[B+4>>2],jve(s,4754,c)|0,n[m>>2]=2,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],QD(s,4772,c)|0,n[d>>2]=3,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],QD(s,4790,c)|0,n[f>>2]=4,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],QD(s,4808,c)|0,C=l}function pt(s,l){s=s|0,l=l|0;var c=0;c=zQe()|0,n[s>>2]=c,JQe(c,l),Fp(n[s>>2]|0)}function Jt(s,l,c){return s=s|0,l=l|0,c=c|0,NQe(s,mn(l)|0,c,0),s|0}function Br(s,l,c){return s=s|0,l=l|0,c=c|0,EQe(s,mn(l)|0,c,0),s|0}function Yn(s,l,c){return s=s|0,l=l|0,c=c|0,sQe(s,mn(l)|0,c,0),s|0}function br(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jke(s,l,d),C=f,s|0}function Sn(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vke(s,l,d),C=f,s|0}function Tn(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],lke(s,l,d),C=f,s|0}function Wr(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Wxe(s,l,d),C=f,s|0}function ti(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],kxe(s,l,d),C=f,s|0}function Rc(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hxe(s,l,d),C=f,s|0}function aR(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Zbe(s,l,d),C=f,s|0}function Q0(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vbe(s,l,d),C=f,s|0}function JA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],lbe(s,l,d),C=f,s|0}function QD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],WSe(s,l,d),C=f,s|0}function Nve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],kSe(s,l,d),C=f,s|0}function Lve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hSe(s,l,d),C=f,s|0}function Mve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],$Pe(s,l,d),C=f,s|0}function Ove(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],OPe(s,l,d),C=f,s|0}function Uve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],wPe(s,l,d),C=f,s|0}function _ve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],iPe(s,l,d),C=f,s|0}function Hve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qDe(s,l,d),C=f,s|0}function qve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vDe(s,l,d),C=f,s|0}function jve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Gve(s,l,d),C=f,s|0}function Gve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Yve(s,c,d,1),C=f}function mn(s){return s=s|0,s|0}function Yve(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=lR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Wve(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Kve(m,f)|0,f),C=d}function lR(){var s=0,l=0;if(o[7616]|0||(NG(9136),pr(24,9136,U|0)|0,l=7616,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9136)|0)){s=9136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));NG(9136)}return 9136}function Wve(s){return s=s|0,0}function Kve(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=lR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],TG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Jve(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function yn(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0;B=C,C=C+32|0,oe=B+24|0,j=B+20|0,F=B+16|0,M=B+12|0,O=B+8|0,k=B+4|0,Ye=B,n[j>>2]=l,n[F>>2]=c,n[M>>2]=f,n[O>>2]=d,n[k>>2]=m,m=s+28|0,n[Ye>>2]=n[m>>2],n[oe>>2]=n[Ye>>2],Vve(s+24|0,oe,j,M,O,F,k)|0,n[m>>2]=n[n[m>>2]>>2],C=B}function Vve(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,s=zve(l)|0,l=Wt(24)|0,RG(l+4|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0,n[B>>2]|0),n[l>>2]=n[s>>2],n[s>>2]=l,l|0}function zve(s){return s=s|0,n[s>>2]|0}function RG(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function dr(s,l){return s=s|0,l=l|0,l|s|0}function TG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Jve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Xve(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,Zve(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],TG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$ve(s,k),eDe(k),C=O;return}}function Xve(s){return s=s|0,357913941}function Zve(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $ve(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function NG(s){s=s|0,nDe(s)}function tDe(s){s=s|0,rDe(s+24|0)}function Lr(s){return s=s|0,n[s>>2]|0}function rDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nDe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,3,l,iDe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function zr(){return 9228}function iDe(){return 1140}function sDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=oDe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=aDe(l,f)|0,C=c,l|0}function Jr(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function oDe(s){return s=s|0,(n[(lR()|0)+24>>2]|0)+(s*12|0)|0}function aDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+48|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=lDe(f)|0,C=d,f|0}function lDe(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(LG()|0)|0,f?(uR(l,f),AR(c,l),cDe(s,c),s=fR(l)|0):s=uDe(s)|0,C=d,s|0}function LG(){var s=0;return o[7632]|0||(CDe(9184),pr(25,9184,U|0)|0,s=7632,n[s>>2]=1,n[s+4>>2]=0),9184}function cR(s){return s=s|0,n[s+36>>2]|0}function uR(s,l){s=s|0,l=l|0,n[s>>2]=l,n[s+4>>2]=s,n[s+8>>2]=0}function AR(s,l){s=s|0,l=l|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=0}function cDe(s,l){s=s|0,l=l|0,hDe(l,s,s+8|0,s+16|0,s+24|0,s+32|0,s+40|0)|0}function fR(s){return s=s|0,n[(n[s+4>>2]|0)+8>>2]|0}function uDe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0;F=C,C=C+16|0,c=F+4|0,f=F,d=Za(8)|0,m=d,B=Wt(48)|0,k=B,l=k+48|0;do n[k>>2]=n[s>>2],k=k+4|0,s=s+4|0;while((k|0)<(l|0));return l=m+4|0,n[l>>2]=B,k=Wt(8)|0,B=n[l>>2]|0,n[f>>2]=0,n[c>>2]=n[f>>2],MG(k,B,c),n[d>>2]=k,C=F,m|0}function MG(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Wt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1092,n[c+12>>2]=l,n[s+4>>2]=c}function ADe(s){s=s|0,im(s),yt(s)}function fDe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function pDe(s){s=s|0,yt(s)}function hDe(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,m=gDe(n[s>>2]|0,l,c,f,d,m,B)|0,B=s+4|0,n[(n[B>>2]|0)+8>>2]=m,n[(n[B>>2]|0)+8>>2]|0}function gDe(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0;var k=0,F=0;return k=C,C=C+16|0,F=k,$a(F),s=ys(s)|0,B=dDe(s,+E[l>>3],+E[c>>3],+E[f>>3],+E[d>>3],+E[m>>3],+E[B>>3])|0,el(F),C=k,B|0}function dDe(s,l,c,f,d,m,B){s=s|0,l=+l,c=+c,f=+f,d=+d,m=+m,B=+B;var k=0;return k=jo(mDe()|0)|0,l=+ma(l),c=+ma(c),f=+ma(f),d=+ma(d),m=+ma(m),Ts(0,k|0,s|0,+l,+c,+f,+d,+m,+ +ma(B))|0}function mDe(){var s=0;return o[7624]|0||(yDe(9172),s=7624,n[s>>2]=1,n[s+4>>2]=0),9172}function yDe(s){s=s|0,ao(s,EDe()|0,6)}function EDe(){return 1112}function CDe(s){s=s|0,Sp(s)}function wDe(s){s=s|0,OG(s+24|0),UG(s+16|0)}function OG(s){s=s|0,BDe(s)}function UG(s){s=s|0,IDe(s)}function IDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function BDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function Sp(s){s=s|0;var l=0;n[s+16>>2]=0,n[s+20>>2]=0,l=s+24|0,n[l>>2]=0,n[s+28>>2]=l,n[s+36>>2]=0,o[s+40>>0]=0,o[s+41>>0]=0}function vDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],DDe(s,c,d,0),C=f}function DDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=pR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=PDe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,SDe(m,f)|0,f),C=d}function pR(){var s=0,l=0;if(o[7640]|0||(HG(9232),pr(26,9232,U|0)|0,l=7640,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9232)|0)){s=9232,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));HG(9232)}return 9232}function PDe(s){return s=s|0,0}function SDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=pR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],_G(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(bDe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function _G(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function bDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=xDe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,kDe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],_G(m,f,c),n[F>>2]=(n[F>>2]|0)+12,QDe(s,k),FDe(k),C=O;return}}function xDe(s){return s=s|0,357913941}function kDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function QDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function FDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function HG(s){s=s|0,NDe(s)}function RDe(s){s=s|0,TDe(s+24|0)}function TDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function NDe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,LDe()|0,3),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function LDe(){return 1144}function MDe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+16|0,B=m+8|0,k=m,F=ODe(s)|0,s=n[F+4>>2]|0,n[k>>2]=n[F>>2],n[k+4>>2]=s,n[B>>2]=n[k>>2],n[B+4>>2]=n[k+4>>2],UDe(l,B,c,f,d),C=m}function ODe(s){return s=s|0,(n[(pR()|0)+24>>2]|0)+(s*12|0)|0}function UDe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,F=0,O=0;O=C,C=C+16|0,B=O+2|0,k=O+1|0,F=O,m=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(m=n[(n[s>>2]|0)+m>>2]|0),Tu(B,c),c=+Nu(B,c),Tu(k,f),f=+Nu(k,f),XA(F,d),F=ZA(F,d)|0,rY[m&1](s,c,f,F),C=O}function Tu(s,l){s=s|0,l=+l}function Nu(s,l){return s=s|0,l=+l,+ +HDe(l)}function XA(s,l){s=s|0,l=l|0}function ZA(s,l){return s=s|0,l=l|0,_De(l)|0}function _De(s){return s=s|0,s|0}function HDe(s){return s=+s,+s}function qDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jDe(s,c,d,1),C=f}function jDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=hR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=GDe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,YDe(m,f)|0,f),C=d}function hR(){var s=0,l=0;if(o[7648]|0||(jG(9268),pr(27,9268,U|0)|0,l=7648,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9268)|0)){s=9268,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));jG(9268)}return 9268}function GDe(s){return s=s|0,0}function YDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=hR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],qG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(WDe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function qG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function WDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=KDe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,VDe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],qG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,zDe(s,k),JDe(k),C=O;return}}function KDe(s){return s=s|0,357913941}function VDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function zDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function JDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function jG(s){s=s|0,$De(s)}function XDe(s){s=s|0,ZDe(s+24|0)}function ZDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function $De(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,4,l,ePe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ePe(){return 1160}function tPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=rPe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=nPe(l,f)|0,C=c,l|0}function rPe(s){return s=s|0,(n[(hR()|0)+24>>2]|0)+(s*12|0)|0}function nPe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),GG(_0[c&31](s)|0)|0}function GG(s){return s=s|0,s&1|0}function iPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],sPe(s,c,d,0),C=f}function sPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=gR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=oPe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,aPe(m,f)|0,f),C=d}function gR(){var s=0,l=0;if(o[7656]|0||(WG(9304),pr(28,9304,U|0)|0,l=7656,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9304)|0)){s=9304,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));WG(9304)}return 9304}function oPe(s){return s=s|0,0}function aPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=gR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],YG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lPe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function YG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cPe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,uPe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],YG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,APe(s,k),fPe(k),C=O;return}}function cPe(s){return s=s|0,357913941}function uPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function APe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function WG(s){s=s|0,gPe(s)}function pPe(s){s=s|0,hPe(s+24|0)}function hPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function gPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,dPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dPe(){return 1164}function mPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=yPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],EPe(l,d,c),C=f}function yPe(s){return s=s|0,(n[(gR()|0)+24>>2]|0)+(s*12|0)|0}function EPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),bp(d,c),c=xp(d,c)|0,tf[f&31](s,c),kp(d),C=m}function bp(s,l){s=s|0,l=l|0,CPe(s,l)}function xp(s,l){return s=s|0,l=l|0,s|0}function kp(s){s=s|0,bu(s)}function CPe(s,l){s=s|0,l=l|0,dR(s,l)}function dR(s,l){s=s|0,l=l|0,n[s>>2]=l}function wPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],IPe(s,c,d,0),C=f}function IPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=mR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=BPe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,vPe(m,f)|0,f),C=d}function mR(){var s=0,l=0;if(o[7664]|0||(VG(9340),pr(29,9340,U|0)|0,l=7664,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9340)|0)){s=9340,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));VG(9340)}return 9340}function BPe(s){return s=s|0,0}function vPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=mR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],KG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(DPe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function KG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function DPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=PPe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,SPe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],KG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,bPe(s,k),xPe(k),C=O;return}}function PPe(s){return s=s|0,357913941}function SPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function bPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function xPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function VG(s){s=s|0,FPe(s)}function kPe(s){s=s|0,QPe(s+24|0)}function QPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function FPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,4,l,RPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function RPe(){return 1180}function TPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=NPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=LPe(l,d,c)|0,C=f,c|0}function NPe(s){return s=s|0,(n[(mR()|0)+24>>2]|0)+(s*12|0)|0}function LPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),F0(d,c),d=R0(d,c)|0,d=FD(pT[f&15](s,d)|0)|0,C=m,d|0}function F0(s,l){s=s|0,l=l|0}function R0(s,l){return s=s|0,l=l|0,MPe(l)|0}function FD(s){return s=s|0,s|0}function MPe(s){return s=s|0,s|0}function OPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],UPe(s,c,d,0),C=f}function UPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=yR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=_Pe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,HPe(m,f)|0,f),C=d}function yR(){var s=0,l=0;if(o[7672]|0||(JG(9376),pr(30,9376,U|0)|0,l=7672,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9376)|0)){s=9376,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));JG(9376)}return 9376}function _Pe(s){return s=s|0,0}function HPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=yR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],zG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(qPe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function zG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function qPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=jPe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,GPe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],zG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,YPe(s,k),WPe(k),C=O;return}}function jPe(s){return s=s|0,357913941}function GPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function YPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function WPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function JG(s){s=s|0,zPe(s)}function KPe(s){s=s|0,VPe(s+24|0)}function VPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function zPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,XG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function XG(){return 1196}function JPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=XPe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=ZPe(l,f)|0,C=c,l|0}function XPe(s){return s=s|0,(n[(yR()|0)+24>>2]|0)+(s*12|0)|0}function ZPe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),FD(_0[c&31](s)|0)|0}function $Pe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],eSe(s,c,d,1),C=f}function eSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=ER()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=tSe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,rSe(m,f)|0,f),C=d}function ER(){var s=0,l=0;if(o[7680]|0||($G(9412),pr(31,9412,U|0)|0,l=7680,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9412)|0)){s=9412,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));$G(9412)}return 9412}function tSe(s){return s=s|0,0}function rSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=ER()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],ZG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(nSe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function ZG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function nSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=iSe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,sSe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],ZG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,oSe(s,k),aSe(k),C=O;return}}function iSe(s){return s=s|0,357913941}function sSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function oSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function aSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function $G(s){s=s|0,uSe(s)}function lSe(s){s=s|0,cSe(s+24|0)}function cSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function uSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,e9()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function e9(){return 1200}function ASe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=fSe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=pSe(l,f)|0,C=c,l|0}function fSe(s){return s=s|0,(n[(ER()|0)+24>>2]|0)+(s*12|0)|0}function pSe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),RD(_0[c&31](s)|0)|0}function RD(s){return s=s|0,s|0}function hSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gSe(s,c,d,0),C=f}function gSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=CR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=dSe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,mSe(m,f)|0,f),C=d}function CR(){var s=0,l=0;if(o[7688]|0||(r9(9448),pr(32,9448,U|0)|0,l=7688,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9448)|0)){s=9448,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));r9(9448)}return 9448}function dSe(s){return s=s|0,0}function mSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=CR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],t9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(ySe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function t9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function ySe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=ESe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,CSe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],t9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,wSe(s,k),ISe(k),C=O;return}}function ESe(s){return s=s|0,357913941}function CSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function wSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function ISe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function r9(s){s=s|0,DSe(s)}function BSe(s){s=s|0,vSe(s+24|0)}function vSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function DSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,n9()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function n9(){return 1204}function PSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=SSe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],bSe(l,d,c),C=f}function SSe(s){return s=s|0,(n[(CR()|0)+24>>2]|0)+(s*12|0)|0}function bSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),wR(d,c),d=IR(d,c)|0,tf[f&31](s,d),C=m}function wR(s,l){s=s|0,l=l|0}function IR(s,l){return s=s|0,l=l|0,xSe(l)|0}function xSe(s){return s=s|0,s|0}function kSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],QSe(s,c,d,0),C=f}function QSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=BR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=FSe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,RSe(m,f)|0,f),C=d}function BR(){var s=0,l=0;if(o[7696]|0||(s9(9484),pr(33,9484,U|0)|0,l=7696,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9484)|0)){s=9484,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));s9(9484)}return 9484}function FSe(s){return s=s|0,0}function RSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=BR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],i9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(TSe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function i9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function TSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=NSe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,LSe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],i9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,MSe(s,k),OSe(k),C=O;return}}function NSe(s){return s=s|0,357913941}function LSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function MSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function OSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function s9(s){s=s|0,HSe(s)}function USe(s){s=s|0,_Se(s+24|0)}function _Se(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function HSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,qSe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function qSe(){return 1212}function jSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=GSe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],YSe(l,m,c,f),C=d}function GSe(s){return s=s|0,(n[(BR()|0)+24>>2]|0)+(s*12|0)|0}function YSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),wR(m,c),m=IR(m,c)|0,F0(B,f),B=R0(B,f)|0,sI[d&15](s,m,B),C=k}function WSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],KSe(s,c,d,1),C=f}function KSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=vR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=VSe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zSe(m,f)|0,f),C=d}function vR(){var s=0,l=0;if(o[7704]|0||(a9(9520),pr(34,9520,U|0)|0,l=7704,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9520)|0)){s=9520,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));a9(9520)}return 9520}function VSe(s){return s=s|0,0}function zSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=vR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],o9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(JSe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function o9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function JSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=XSe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,ZSe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],o9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$Se(s,k),ebe(k),C=O;return}}function XSe(s){return s=s|0,357913941}function ZSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $Se(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function ebe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function a9(s){s=s|0,nbe(s)}function tbe(s){s=s|0,rbe(s+24|0)}function rbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nbe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,ibe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ibe(){return 1224}function sbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;return d=C,C=C+16|0,m=d+8|0,B=d,k=obe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],f=+abe(l,m,c),C=d,+f}function obe(s){return s=s|0,(n[(vR()|0)+24>>2]|0)+(s*12|0)|0}function abe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,B=+Ru(+iY[f&7](s,d)),C=m,+B}function lbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],cbe(s,c,d,1),C=f}function cbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=DR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=ube(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Abe(m,f)|0,f),C=d}function DR(){var s=0,l=0;if(o[7712]|0||(c9(9556),pr(35,9556,U|0)|0,l=7712,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9556)|0)){s=9556,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));c9(9556)}return 9556}function ube(s){return s=s|0,0}function Abe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=DR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],l9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(fbe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function l9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function fbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=pbe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,hbe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],l9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,gbe(s,k),dbe(k),C=O;return}}function pbe(s){return s=s|0,357913941}function hbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function gbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function dbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function c9(s){s=s|0,Ebe(s)}function mbe(s){s=s|0,ybe(s+24|0)}function ybe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Ebe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,Cbe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Cbe(){return 1232}function wbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=Ibe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=+Bbe(l,d),C=f,+c}function Ibe(s){return s=s|0,(n[(DR()|0)+24>>2]|0)+(s*12|0)|0}function Bbe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),+ +Ru(+nY[c&15](s))}function vbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Dbe(s,c,d,1),C=f}function Dbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=PR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Pbe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Sbe(m,f)|0,f),C=d}function PR(){var s=0,l=0;if(o[7720]|0||(A9(9592),pr(36,9592,U|0)|0,l=7720,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9592)|0)){s=9592,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));A9(9592)}return 9592}function Pbe(s){return s=s|0,0}function Sbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=PR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],u9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(bbe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function u9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function bbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=xbe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,kbe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],u9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Qbe(s,k),Fbe(k),C=O;return}}function xbe(s){return s=s|0,357913941}function kbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Qbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Fbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function A9(s){s=s|0,Nbe(s)}function Rbe(s){s=s|0,Tbe(s+24|0)}function Tbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Nbe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,7,l,Lbe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Lbe(){return 1276}function Mbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=Obe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=Ube(l,f)|0,C=c,l|0}function Obe(s){return s=s|0,(n[(PR()|0)+24>>2]|0)+(s*12|0)|0}function Ube(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+16|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=f9(f)|0,C=d,f|0}function f9(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(p9()|0)|0,f?(uR(l,f),AR(c,l),_be(s,c),s=fR(l)|0):s=Hbe(s)|0,C=d,s|0}function p9(){var s=0;return o[7736]|0||(Xbe(9640),pr(25,9640,U|0)|0,s=7736,n[s>>2]=1,n[s+4>>2]=0),9640}function _be(s,l){s=s|0,l=l|0,Ybe(l,s,s+8|0)|0}function Hbe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Wt(16)|0,n[k>>2]=n[s>>2],n[k+4>>2]=n[s+4>>2],n[k+8>>2]=n[s+8>>2],n[k+12>>2]=n[s+12>>2],m=l+4|0,n[m>>2]=k,s=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],SR(s,m,d),n[f>>2]=s,C=c,l|0}function SR(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Wt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1244,n[c+12>>2]=l,n[s+4>>2]=c}function qbe(s){s=s|0,im(s),yt(s)}function jbe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function Gbe(s){s=s|0,yt(s)}function Ybe(s,l,c){return s=s|0,l=l|0,c=c|0,l=Wbe(n[s>>2]|0,l,c)|0,c=s+4|0,n[(n[c>>2]|0)+8>>2]=l,n[(n[c>>2]|0)+8>>2]|0}function Wbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return f=C,C=C+16|0,d=f,$a(d),s=ys(s)|0,c=Kbe(s,n[l>>2]|0,+E[c>>3])|0,el(d),C=f,c|0}function Kbe(s,l,c){s=s|0,l=l|0,c=+c;var f=0;return f=jo(Vbe()|0)|0,l=Xd(l)|0,pc(0,f|0,s|0,l|0,+ +ma(c))|0}function Vbe(){var s=0;return o[7728]|0||(zbe(9628),s=7728,n[s>>2]=1,n[s+4>>2]=0),9628}function zbe(s){s=s|0,ao(s,Jbe()|0,2)}function Jbe(){return 1264}function Xbe(s){s=s|0,Sp(s)}function Zbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],$be(s,c,d,1),C=f}function $be(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=bR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=exe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,txe(m,f)|0,f),C=d}function bR(){var s=0,l=0;if(o[7744]|0||(g9(9684),pr(37,9684,U|0)|0,l=7744,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9684)|0)){s=9684,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));g9(9684)}return 9684}function exe(s){return s=s|0,0}function txe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=bR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],h9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(rxe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function h9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function rxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=nxe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,ixe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],h9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,sxe(s,k),oxe(k),C=O;return}}function nxe(s){return s=s|0,357913941}function ixe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function sxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function oxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function g9(s){s=s|0,cxe(s)}function axe(s){s=s|0,lxe(s+24|0)}function lxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function cxe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,uxe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function uxe(){return 1280}function Axe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=fxe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=pxe(l,d,c)|0,C=f,c|0}function fxe(s){return s=s|0,(n[(bR()|0)+24>>2]|0)+(s*12|0)|0}function pxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return B=C,C=C+32|0,d=B,m=B+16|0,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(m,c),m=ZA(m,c)|0,sI[f&15](d,s,m),m=f9(d)|0,C=B,m|0}function hxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gxe(s,c,d,1),C=f}function gxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=xR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=dxe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,mxe(m,f)|0,f),C=d}function xR(){var s=0,l=0;if(o[7752]|0||(m9(9720),pr(38,9720,U|0)|0,l=7752,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9720)|0)){s=9720,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));m9(9720)}return 9720}function dxe(s){return s=s|0,0}function mxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=xR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],d9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(yxe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function d9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function yxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Exe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,Cxe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],d9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,wxe(s,k),Ixe(k),C=O;return}}function Exe(s){return s=s|0,357913941}function Cxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function wxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Ixe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function m9(s){s=s|0,Dxe(s)}function Bxe(s){s=s|0,vxe(s+24|0)}function vxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Dxe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,Pxe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Pxe(){return 1288}function Sxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=bxe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=xxe(l,f)|0,C=c,l|0}function bxe(s){return s=s|0,(n[(xR()|0)+24>>2]|0)+(s*12|0)|0}function xxe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),k0(_0[c&31](s)|0)|0}function kxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Qxe(s,c,d,0),C=f}function Qxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=kR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Fxe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Rxe(m,f)|0,f),C=d}function kR(){var s=0,l=0;if(o[7760]|0||(E9(9756),pr(39,9756,U|0)|0,l=7760,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9756)|0)){s=9756,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));E9(9756)}return 9756}function Fxe(s){return s=s|0,0}function Rxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=kR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],y9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Txe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function y9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Txe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Nxe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,Lxe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],y9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Mxe(s,k),Oxe(k),C=O;return}}function Nxe(s){return s=s|0,357913941}function Lxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Mxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Oxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function E9(s){s=s|0,Hxe(s)}function Uxe(s){s=s|0,_xe(s+24|0)}function _xe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Hxe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,qxe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function qxe(){return 1292}function jxe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Gxe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Yxe(l,d,c),C=f}function Gxe(s){return s=s|0,(n[(kR()|0)+24>>2]|0)+(s*12|0)|0}function Yxe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),Tu(d,c),c=+Nu(d,c),eY[f&31](s,c),C=m}function Wxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Kxe(s,c,d,0),C=f}function Kxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=QR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Vxe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zxe(m,f)|0,f),C=d}function QR(){var s=0,l=0;if(o[7768]|0||(w9(9792),pr(40,9792,U|0)|0,l=7768,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9792)|0)){s=9792,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));w9(9792)}return 9792}function Vxe(s){return s=s|0,0}function zxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=QR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],C9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Jxe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function C9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Jxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Xxe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,Zxe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],C9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$xe(s,k),eke(k),C=O;return}}function Xxe(s){return s=s|0,357913941}function Zxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $xe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function w9(s){s=s|0,nke(s)}function tke(s){s=s|0,rke(s+24|0)}function rke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,ike()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ike(){return 1300}function ske(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=oke(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],ake(l,m,c,f),C=d}function oke(s){return s=s|0,(n[(QR()|0)+24>>2]|0)+(s*12|0)|0}function ake(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,Tu(B,f),f=+Nu(B,f),lY[d&15](s,m,f),C=k}function lke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],cke(s,c,d,0),C=f}function cke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=FR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=uke(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Ake(m,f)|0,f),C=d}function FR(){var s=0,l=0;if(o[7776]|0||(B9(9828),pr(41,9828,U|0)|0,l=7776,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9828)|0)){s=9828,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));B9(9828)}return 9828}function uke(s){return s=s|0,0}function Ake(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=FR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],I9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(fke(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function I9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function fke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=pke(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,hke(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],I9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,gke(s,k),dke(k),C=O;return}}function pke(s){return s=s|0,357913941}function hke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function gke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function dke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function B9(s){s=s|0,Eke(s)}function mke(s){s=s|0,yke(s+24|0)}function yke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Eke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,7,l,Cke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Cke(){return 1312}function wke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Ike(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Bke(l,d,c),C=f}function Ike(s){return s=s|0,(n[(FR()|0)+24>>2]|0)+(s*12|0)|0}function Bke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,tf[f&31](s,d),C=m}function vke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Dke(s,c,d,0),C=f}function Dke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=RR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Pke(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Ske(m,f)|0,f),C=d}function RR(){var s=0,l=0;if(o[7784]|0||(D9(9864),pr(42,9864,U|0)|0,l=7784,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9864)|0)){s=9864,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));D9(9864)}return 9864}function Pke(s){return s=s|0,0}function Ske(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=RR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],v9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(bke(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function v9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function bke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=xke(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,kke(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],v9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Qke(s,k),Fke(k),C=O;return}}function xke(s){return s=s|0,357913941}function kke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Qke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Fke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function D9(s){s=s|0,Nke(s)}function Rke(s){s=s|0,Tke(s+24|0)}function Tke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Nke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,Lke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Lke(){return 1320}function Mke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Oke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Uke(l,d,c),C=f}function Oke(s){return s=s|0,(n[(RR()|0)+24>>2]|0)+(s*12|0)|0}function Uke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),_ke(d,c),d=Hke(d,c)|0,tf[f&31](s,d),C=m}function _ke(s,l){s=s|0,l=l|0}function Hke(s,l){return s=s|0,l=l|0,qke(l)|0}function qke(s){return s=s|0,s|0}function jke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Gke(s,c,d,0),C=f}function Gke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=TR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Yke(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Wke(m,f)|0,f),C=d}function TR(){var s=0,l=0;if(o[7792]|0||(S9(9900),pr(43,9900,U|0)|0,l=7792,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9900)|0)){s=9900,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));S9(9900)}return 9900}function Yke(s){return s=s|0,0}function Wke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=TR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],P9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Kke(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function P9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Kke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Vke(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,zke(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],P9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Jke(s,k),Xke(k),C=O;return}}function Vke(s){return s=s|0,357913941}function zke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Jke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Xke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function S9(s){s=s|0,eQe(s)}function Zke(s){s=s|0,$ke(s+24|0)}function $ke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function eQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,22,l,tQe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function tQe(){return 1344}function rQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;c=C,C=C+16|0,f=c+8|0,d=c,m=nQe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],iQe(l,f),C=c}function nQe(s){return s=s|0,(n[(TR()|0)+24>>2]|0)+(s*12|0)|0}function iQe(s,l){s=s|0,l=l|0;var c=0;c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),ef[c&127](s)}function sQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=NR()|0,s=oQe(c)|0,yn(m,l,d,s,aQe(c,f)|0,f)}function NR(){var s=0,l=0;if(o[7800]|0||(x9(9936),pr(44,9936,U|0)|0,l=7800,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9936)|0)){s=9936,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));x9(9936)}return 9936}function oQe(s){return s=s|0,s|0}function aQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=NR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(b9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(lQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function b9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function lQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=cQe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,uQe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,b9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,AQe(s,d),fQe(d),C=k;return}}function cQe(s){return s=s|0,536870911}function uQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function AQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function x9(s){s=s|0,gQe(s)}function pQe(s){s=s|0,hQe(s+24|0)}function hQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function gQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,23,l,n9()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dQe(s,l){s=s|0,l=l|0,yQe(n[(mQe(s)|0)>>2]|0,l)}function mQe(s){return s=s|0,(n[(NR()|0)+24>>2]|0)+(s<<3)|0}function yQe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,wR(f,l),l=IR(f,l)|0,ef[s&127](l),C=c}function EQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=LR()|0,s=CQe(c)|0,yn(m,l,d,s,wQe(c,f)|0,f)}function LR(){var s=0,l=0;if(o[7808]|0||(Q9(9972),pr(45,9972,U|0)|0,l=7808,n[l>>2]=1,n[l+4>>2]=0),!(Lr(9972)|0)){s=9972,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));Q9(9972)}return 9972}function CQe(s){return s=s|0,s|0}function wQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=LR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(k9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(IQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function k9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function IQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=BQe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,vQe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,k9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,DQe(s,d),PQe(d),C=k;return}}function BQe(s){return s=s|0,536870911}function vQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function DQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function PQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function Q9(s){s=s|0,xQe(s)}function SQe(s){s=s|0,bQe(s+24|0)}function bQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function xQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,9,l,kQe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function kQe(){return 1348}function QQe(s,l){return s=s|0,l=l|0,RQe(n[(FQe(s)|0)>>2]|0,l)|0}function FQe(s){return s=s|0,(n[(LR()|0)+24>>2]|0)+(s<<3)|0}function RQe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,F9(f,l),l=R9(f,l)|0,l=FD(_0[s&31](l)|0)|0,C=c,l|0}function F9(s,l){s=s|0,l=l|0}function R9(s,l){return s=s|0,l=l|0,TQe(l)|0}function TQe(s){return s=s|0,s|0}function NQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=MR()|0,s=LQe(c)|0,yn(m,l,d,s,MQe(c,f)|0,f)}function MR(){var s=0,l=0;if(o[7816]|0||(N9(10008),pr(46,10008,U|0)|0,l=7816,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10008)|0)){s=10008,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));N9(10008)}return 10008}function LQe(s){return s=s|0,s|0}function MQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=MR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(T9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(OQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function T9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function OQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=UQe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,_Qe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,T9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,HQe(s,d),qQe(d),C=k;return}}function UQe(s){return s=s|0,536870911}function _Qe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function HQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function qQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function N9(s){s=s|0,YQe(s)}function jQe(s){s=s|0,GQe(s+24|0)}function GQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function YQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,15,l,XG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function WQe(s){return s=s|0,VQe(n[(KQe(s)|0)>>2]|0)|0}function KQe(s){return s=s|0,(n[(MR()|0)+24>>2]|0)+(s<<3)|0}function VQe(s){return s=s|0,FD(KD[s&7]()|0)|0}function zQe(){var s=0;return o[7832]|0||(nFe(10052),pr(25,10052,U|0)|0,s=7832,n[s>>2]=1,n[s+4>>2]=0),10052}function JQe(s,l){s=s|0,l=l|0,n[s>>2]=XQe()|0,n[s+4>>2]=ZQe()|0,n[s+12>>2]=l,n[s+8>>2]=$Qe()|0,n[s+32>>2]=2}function XQe(){return 11709}function ZQe(){return 1188}function $Qe(){return TD()|0}function eFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(tFe(c),yt(c)):l|0&&(Hd(l),yt(l))}function Qp(s,l){return s=s|0,l=l|0,l&s|0}function tFe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function TD(){var s=0;return o[7824]|0||(n[2511]=rFe()|0,n[2512]=0,s=7824,n[s>>2]=1,n[s+4>>2]=0),10044}function rFe(){return 0}function nFe(s){s=s|0,Sp(s)}function iFe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0;l=C,C=C+32|0,c=l+24|0,m=l+16|0,d=l+8|0,f=l,sFe(s,4827),oFe(s,4834,3)|0,aFe(s,3682,47)|0,n[m>>2]=9,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],lFe(s,4841,c)|0,n[d>>2]=1,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],cFe(s,4871,c)|0,n[f>>2]=10,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],uFe(s,4891,c)|0,C=l}function sFe(s,l){s=s|0,l=l|0;var c=0;c=qRe()|0,n[s>>2]=c,jRe(c,l),Fp(n[s>>2]|0)}function oFe(s,l,c){return s=s|0,l=l|0,c=c|0,PRe(s,mn(l)|0,c,0),s|0}function aFe(s,l,c){return s=s|0,l=l|0,c=c|0,ARe(s,mn(l)|0,c,0),s|0}function lFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],WFe(s,l,d),C=f,s|0}function cFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],SFe(s,l,d),C=f,s|0}function uFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],AFe(s,l,d),C=f,s|0}function AFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],fFe(s,c,d,1),C=f}function fFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=OR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=pFe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,hFe(m,f)|0,f),C=d}function OR(){var s=0,l=0;if(o[7840]|0||(M9(10100),pr(48,10100,U|0)|0,l=7840,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10100)|0)){s=10100,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));M9(10100)}return 10100}function pFe(s){return s=s|0,0}function hFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=OR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],L9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(gFe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function L9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function gFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=dFe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,mFe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],L9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,yFe(s,k),EFe(k),C=O;return}}function dFe(s){return s=s|0,357913941}function mFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function yFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function EFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function M9(s){s=s|0,IFe(s)}function CFe(s){s=s|0,wFe(s+24|0)}function wFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function IFe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,BFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function BFe(){return 1364}function vFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=DFe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=PFe(l,d,c)|0,C=f,c|0}function DFe(s){return s=s|0,(n[(OR()|0)+24>>2]|0)+(s*12|0)|0}function PFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,d=GG(pT[f&15](s,d)|0)|0,C=m,d|0}function SFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],bFe(s,c,d,0),C=f}function bFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=UR()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=xFe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,kFe(m,f)|0,f),C=d}function UR(){var s=0,l=0;if(o[7848]|0||(U9(10136),pr(49,10136,U|0)|0,l=7848,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10136)|0)){s=10136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));U9(10136)}return 10136}function xFe(s){return s=s|0,0}function kFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=UR()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],O9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(QFe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function O9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function QFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=FFe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,RFe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],O9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,TFe(s,k),NFe(k),C=O;return}}function FFe(s){return s=s|0,357913941}function RFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function TFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function NFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function U9(s){s=s|0,OFe(s)}function LFe(s){s=s|0,MFe(s+24|0)}function MFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function OFe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,9,l,UFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function UFe(){return 1372}function _Fe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=HFe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qFe(l,d,c),C=f}function HFe(s){return s=s|0,(n[(UR()|0)+24>>2]|0)+(s*12|0)|0}function qFe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=Ze;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),jFe(d,c),B=y(GFe(d,c)),$7[f&1](s,B),C=m}function jFe(s,l){s=s|0,l=+l}function GFe(s,l){return s=s|0,l=+l,y(YFe(l))}function YFe(s){return s=+s,y(s)}function WFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],KFe(s,c,d,0),C=f}function KFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=_R()|0,n[M>>2]=O,n[M+4>>2]=F,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=VFe(m)|0,n[k>>2]=O,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zFe(m,f)|0,f),C=d}function _R(){var s=0,l=0;if(o[7856]|0||(H9(10172),pr(50,10172,U|0)|0,l=7856,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10172)|0)){s=10172,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));H9(10172)}return 10172}function VFe(s){return s=s|0,0}function zFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,F=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=_R()|0,O=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],_9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(JFe(O,k,F),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function _9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function JFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=XFe(s)|0,m>>>0>>0)Zr(s);else{M=n[s>>2]|0,oe=((n[s+8>>2]|0)-M|0)/12|0,j=oe<<1,ZFe(k,oe>>>0>>1>>>0?j>>>0>>0?d:j:m,((n[F>>2]|0)-M|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],_9(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$Fe(s,k),eRe(k),C=O;return}}function XFe(s){return s=s|0,357913941}function ZFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Wt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $Fe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function H9(s){s=s|0,nRe(s)}function tRe(s){s=s|0,rRe(s+24|0)}function rRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,3,l,iRe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function iRe(){return 1380}function sRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=oRe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],aRe(l,m,c,f),C=d}function oRe(s){return s=s|0,(n[(_R()|0)+24>>2]|0)+(s*12|0)|0}function aRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,lRe(B,f),B=cRe(B,f)|0,sI[d&15](s,m,B),C=k}function lRe(s,l){s=s|0,l=l|0}function cRe(s,l){return s=s|0,l=l|0,uRe(l)|0}function uRe(s){return s=s|0,(s|0)!=0|0}function ARe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=HR()|0,s=fRe(c)|0,yn(m,l,d,s,pRe(c,f)|0,f)}function HR(){var s=0,l=0;if(o[7864]|0||(j9(10208),pr(51,10208,U|0)|0,l=7864,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10208)|0)){s=10208,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));j9(10208)}return 10208}function fRe(s){return s=s|0,s|0}function pRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=HR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(q9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(hRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function q9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function hRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=gRe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,dRe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,q9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,mRe(s,d),yRe(d),C=k;return}}function gRe(s){return s=s|0,536870911}function dRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function mRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function yRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function j9(s){s=s|0,wRe(s)}function ERe(s){s=s|0,CRe(s+24|0)}function CRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function wRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,24,l,IRe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function IRe(){return 1392}function BRe(s,l){s=s|0,l=l|0,DRe(n[(vRe(s)|0)>>2]|0,l)}function vRe(s){return s=s|0,(n[(HR()|0)+24>>2]|0)+(s<<3)|0}function DRe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,F9(f,l),l=R9(f,l)|0,ef[s&127](l),C=c}function PRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=qR()|0,s=SRe(c)|0,yn(m,l,d,s,bRe(c,f)|0,f)}function qR(){var s=0,l=0;if(o[7872]|0||(Y9(10244),pr(52,10244,U|0)|0,l=7872,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10244)|0)){s=10244,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));Y9(10244)}return 10244}function SRe(s){return s=s|0,s|0}function bRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=qR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(G9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(xRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function G9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function xRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=kRe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,QRe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,G9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,FRe(s,d),RRe(d),C=k;return}}function kRe(s){return s=s|0,536870911}function QRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function FRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function RRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function Y9(s){s=s|0,LRe(s)}function TRe(s){s=s|0,NRe(s+24|0)}function NRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function LRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,16,l,MRe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function MRe(){return 1400}function ORe(s){return s=s|0,_Re(n[(URe(s)|0)>>2]|0)|0}function URe(s){return s=s|0,(n[(qR()|0)+24>>2]|0)+(s<<3)|0}function _Re(s){return s=s|0,HRe(KD[s&7]()|0)|0}function HRe(s){return s=s|0,s|0}function qRe(){var s=0;return o[7880]|0||(zRe(10280),pr(25,10280,U|0)|0,s=7880,n[s>>2]=1,n[s+4>>2]=0),10280}function jRe(s,l){s=s|0,l=l|0,n[s>>2]=GRe()|0,n[s+4>>2]=YRe()|0,n[s+12>>2]=l,n[s+8>>2]=WRe()|0,n[s+32>>2]=4}function GRe(){return 11711}function YRe(){return 1356}function WRe(){return TD()|0}function KRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(VRe(c),yt(c)):l|0&&(C0(l),yt(l))}function VRe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function zRe(s){s=s|0,Sp(s)}function JRe(s){s=s|0,XRe(s,4920),ZRe(s)|0,$Re(s)|0}function XRe(s,l){s=s|0,l=l|0;var c=0;c=p9()|0,n[s>>2]=c,CTe(c,l),Fp(n[s>>2]|0)}function ZRe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,uTe()|0),s|0}function $Re(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,eTe()|0),s|0}function eTe(){var s=0;return o[7888]|0||(W9(10328),pr(53,10328,U|0)|0,s=7888,n[s>>2]=1,n[s+4>>2]=0),Lr(10328)|0||W9(10328),10328}function T0(s,l){s=s|0,l=l|0,yn(s,0,l,0,0,0)}function W9(s){s=s|0,nTe(s),N0(s,10)}function tTe(s){s=s|0,rTe(s+24|0)}function rTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function nTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,1,l,aTe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function iTe(s,l,c){s=s|0,l=l|0,c=+c,sTe(s,l,c)}function N0(s,l){s=s|0,l=l|0,n[s+20>>2]=l}function sTe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,m=f+8|0,k=f+13|0,d=f,B=f+12|0,XA(k,l),n[m>>2]=ZA(k,l)|0,Tu(B,c),E[d>>3]=+Nu(B,c),oTe(s,m,d),C=f}function oTe(s,l,c){s=s|0,l=l|0,c=c|0,Xa(s+8|0,n[l>>2]|0,+E[c>>3]),o[s+24>>0]=1}function aTe(){return 1404}function lTe(s,l){return s=s|0,l=+l,cTe(s,l)|0}function cTe(s,l){s=s|0,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+16|0,m=f+4|0,B=f+8|0,k=f,d=Za(8)|0,c=d,F=Wt(16)|0,XA(m,s),s=ZA(m,s)|0,Tu(B,l),Xa(F,s,+Nu(B,l)),B=c+4|0,n[B>>2]=F,s=Wt(8)|0,B=n[B>>2]|0,n[k>>2]=0,n[m>>2]=n[k>>2],SR(s,B,m),n[d>>2]=s,C=f,c|0}function uTe(){var s=0;return o[7896]|0||(K9(10364),pr(54,10364,U|0)|0,s=7896,n[s>>2]=1,n[s+4>>2]=0),Lr(10364)|0||K9(10364),10364}function K9(s){s=s|0,pTe(s),N0(s,55)}function ATe(s){s=s|0,fTe(s+24|0)}function fTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function pTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,4,l,mTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function hTe(s){s=s|0,gTe(s)}function gTe(s){s=s|0,dTe(s)}function dTe(s){s=s|0,V9(s+8|0),o[s+24>>0]=1}function V9(s){s=s|0,n[s>>2]=0,E[s+8>>3]=0}function mTe(){return 1424}function yTe(){return ETe()|0}function ETe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,f=Wt(16)|0,V9(f),m=s+4|0,n[m>>2]=f,f=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],SR(f,m,d),n[c>>2]=f,C=l,s|0}function CTe(s,l){s=s|0,l=l|0,n[s>>2]=wTe()|0,n[s+4>>2]=ITe()|0,n[s+12>>2]=l,n[s+8>>2]=BTe()|0,n[s+32>>2]=5}function wTe(){return 11710}function ITe(){return 1416}function BTe(){return ND()|0}function vTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(DTe(c),yt(c)):l|0&&yt(l)}function DTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function ND(){var s=0;return o[7904]|0||(n[2600]=PTe()|0,n[2601]=0,s=7904,n[s>>2]=1,n[s+4>>2]=0),10400}function PTe(){return n[357]|0}function STe(s){s=s|0,bTe(s,4926),xTe(s)|0}function bTe(s,l){s=s|0,l=l|0;var c=0;c=LG()|0,n[s>>2]=c,_Te(c,l),Fp(n[s>>2]|0)}function xTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,kTe()|0),s|0}function kTe(){var s=0;return o[7912]|0||(z9(10412),pr(56,10412,U|0)|0,s=7912,n[s>>2]=1,n[s+4>>2]=0),Lr(10412)|0||z9(10412),10412}function z9(s){s=s|0,RTe(s),N0(s,57)}function QTe(s){s=s|0,FTe(s+24|0)}function FTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function RTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,5,l,MTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function TTe(s){s=s|0,NTe(s)}function NTe(s){s=s|0,LTe(s)}function LTe(s){s=s|0;var l=0,c=0;l=s+8|0,c=l+48|0;do n[l>>2]=0,l=l+4|0;while((l|0)<(c|0));o[s+56>>0]=1}function MTe(){return 1432}function OTe(){return UTe()|0}function UTe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0;B=C,C=C+16|0,s=B+4|0,l=B,c=Za(8)|0,f=c,d=Wt(48)|0,m=d,k=m+48|0;do n[m>>2]=0,m=m+4|0;while((m|0)<(k|0));return m=f+4|0,n[m>>2]=d,k=Wt(8)|0,m=n[m>>2]|0,n[l>>2]=0,n[s>>2]=n[l>>2],MG(k,m,s),n[c>>2]=k,C=B,f|0}function _Te(s,l){s=s|0,l=l|0,n[s>>2]=HTe()|0,n[s+4>>2]=qTe()|0,n[s+12>>2]=l,n[s+8>>2]=jTe()|0,n[s+32>>2]=6}function HTe(){return 11704}function qTe(){return 1436}function jTe(){return ND()|0}function GTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(YTe(c),yt(c)):l|0&&yt(l)}function YTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function WTe(s){s=s|0,KTe(s,4933),VTe(s)|0,zTe(s)|0}function KTe(s,l){s=s|0,l=l|0;var c=0;c=ENe()|0,n[s>>2]=c,CNe(c,l),Fp(n[s>>2]|0)}function VTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,cNe()|0),s|0}function zTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,JTe()|0),s|0}function JTe(){var s=0;return o[7920]|0||(J9(10452),pr(58,10452,U|0)|0,s=7920,n[s>>2]=1,n[s+4>>2]=0),Lr(10452)|0||J9(10452),10452}function J9(s){s=s|0,$Te(s),N0(s,1)}function XTe(s){s=s|0,ZTe(s+24|0)}function ZTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function $Te(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,1,l,nNe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function eNe(s,l,c){s=s|0,l=+l,c=+c,tNe(s,l,c)}function tNe(s,l,c){s=s|0,l=+l,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,m=f+8|0,k=f+17|0,d=f,B=f+16|0,Tu(k,l),E[m>>3]=+Nu(k,l),Tu(B,c),E[d>>3]=+Nu(B,c),rNe(s,m,d),C=f}function rNe(s,l,c){s=s|0,l=l|0,c=c|0,X9(s+8|0,+E[l>>3],+E[c>>3]),o[s+24>>0]=1}function X9(s,l,c){s=s|0,l=+l,c=+c,E[s>>3]=l,E[s+8>>3]=c}function nNe(){return 1472}function iNe(s,l){return s=+s,l=+l,sNe(s,l)|0}function sNe(s,l){s=+s,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+16|0,B=f+4|0,k=f+8|0,F=f,d=Za(8)|0,c=d,m=Wt(16)|0,Tu(B,s),s=+Nu(B,s),Tu(k,l),X9(m,s,+Nu(k,l)),k=c+4|0,n[k>>2]=m,m=Wt(8)|0,k=n[k>>2]|0,n[F>>2]=0,n[B>>2]=n[F>>2],Z9(m,k,B),n[d>>2]=m,C=f,c|0}function Z9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Wt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1452,n[c+12>>2]=l,n[s+4>>2]=c}function oNe(s){s=s|0,im(s),yt(s)}function aNe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function lNe(s){s=s|0,yt(s)}function cNe(){var s=0;return o[7928]|0||($9(10488),pr(59,10488,U|0)|0,s=7928,n[s>>2]=1,n[s+4>>2]=0),Lr(10488)|0||$9(10488),10488}function $9(s){s=s|0,fNe(s),N0(s,60)}function uNe(s){s=s|0,ANe(s+24|0)}function ANe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function fNe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,6,l,dNe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function pNe(s){s=s|0,hNe(s)}function hNe(s){s=s|0,gNe(s)}function gNe(s){s=s|0,e7(s+8|0),o[s+24>>0]=1}function e7(s){s=s|0,n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,n[s+12>>2]=0}function dNe(){return 1492}function mNe(){return yNe()|0}function yNe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,f=Wt(16)|0,e7(f),m=s+4|0,n[m>>2]=f,f=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],Z9(f,m,d),n[c>>2]=f,C=l,s|0}function ENe(){var s=0;return o[7936]|0||(PNe(10524),pr(25,10524,U|0)|0,s=7936,n[s>>2]=1,n[s+4>>2]=0),10524}function CNe(s,l){s=s|0,l=l|0,n[s>>2]=wNe()|0,n[s+4>>2]=INe()|0,n[s+12>>2]=l,n[s+8>>2]=BNe()|0,n[s+32>>2]=7}function wNe(){return 11700}function INe(){return 1484}function BNe(){return ND()|0}function vNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(DNe(c),yt(c)):l|0&&yt(l)}function DNe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function PNe(s){s=s|0,Sp(s)}function SNe(s,l,c){s=s|0,l=l|0,c=c|0,s=mn(l)|0,l=bNe(c)|0,c=xNe(c,0)|0,sLe(s,l,c,jR()|0,0)}function bNe(s){return s=s|0,s|0}function xNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=jR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(r7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(LNe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function jR(){var s=0,l=0;if(o[7944]|0||(t7(10568),pr(61,10568,U|0)|0,l=7944,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10568)|0)){s=10568,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));t7(10568)}return 10568}function t7(s){s=s|0,FNe(s)}function kNe(s){s=s|0,QNe(s+24|0)}function QNe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function FNe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,17,l,e9()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function RNe(s){return s=s|0,NNe(n[(TNe(s)|0)>>2]|0)|0}function TNe(s){return s=s|0,(n[(jR()|0)+24>>2]|0)+(s<<3)|0}function NNe(s){return s=s|0,RD(KD[s&7]()|0)|0}function r7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function LNe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=MNe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,ONe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,r7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,UNe(s,d),_Ne(d),C=k;return}}function MNe(s){return s=s|0,536870911}function ONe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function UNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function _Ne(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function HNe(){qNe()}function qNe(){jNe(10604)}function jNe(s){s=s|0,GNe(s,4955)}function GNe(s,l){s=s|0,l=l|0;var c=0;c=YNe()|0,n[s>>2]=c,WNe(c,l),Fp(n[s>>2]|0)}function YNe(){var s=0;return o[7952]|0||(tLe(10612),pr(25,10612,U|0)|0,s=7952,n[s>>2]=1,n[s+4>>2]=0),10612}function WNe(s,l){s=s|0,l=l|0,n[s>>2]=JNe()|0,n[s+4>>2]=XNe()|0,n[s+12>>2]=l,n[s+8>>2]=ZNe()|0,n[s+32>>2]=8}function Fp(s){s=s|0;var l=0,c=0;l=C,C=C+16|0,c=l,$d()|0,n[c>>2]=s,KNe(10608,c),C=l}function $d(){return o[11714]|0||(n[2652]=0,pr(62,10608,U|0)|0,o[11714]=1),10608}function KNe(s,l){s=s|0,l=l|0;var c=0;c=Wt(8)|0,n[c+4>>2]=n[l>>2],n[c>>2]=n[s>>2],n[s>>2]=c}function VNe(s){s=s|0,zNe(s)}function zNe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function JNe(){return 11715}function XNe(){return 1496}function ZNe(){return TD()|0}function $Ne(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(eLe(c),yt(c)):l|0&&yt(l)}function eLe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function tLe(s){s=s|0,Sp(s)}function rLe(s,l){s=s|0,l=l|0;var c=0,f=0;$d()|0,c=n[2652]|0;e:do if(c|0){for(;f=n[c+4>>2]|0,!(f|0&&!(M7(GR(f)|0,s)|0));)if(c=n[c>>2]|0,!c)break e;nLe(f,l)}while(!1)}function GR(s){return s=s|0,n[s+12>>2]|0}function nLe(s,l){s=s|0,l=l|0;var c=0;s=s+36|0,c=n[s>>2]|0,c|0&&(bu(c),yt(c)),c=Wt(4)|0,PD(c,l),n[s>>2]=c}function YR(){return o[11716]|0||(n[2664]=0,pr(63,10656,U|0)|0,o[11716]=1),10656}function n7(){var s=0;return o[11717]|0?s=n[2665]|0:(iLe(),n[2665]=1504,o[11717]=1,s=1504),s|0}function iLe(){o[11740]|0||(o[11718]=dr(dr(8,0)|0,0)|0,o[11719]=dr(dr(0,0)|0,0)|0,o[11720]=dr(dr(0,16)|0,0)|0,o[11721]=dr(dr(8,0)|0,0)|0,o[11722]=dr(dr(0,0)|0,0)|0,o[11723]=dr(dr(8,0)|0,0)|0,o[11724]=dr(dr(0,0)|0,0)|0,o[11725]=dr(dr(8,0)|0,0)|0,o[11726]=dr(dr(0,0)|0,0)|0,o[11727]=dr(dr(8,0)|0,0)|0,o[11728]=dr(dr(0,0)|0,0)|0,o[11729]=dr(dr(0,0)|0,32)|0,o[11730]=dr(dr(0,0)|0,32)|0,o[11740]=1)}function i7(){return 1572}function sLe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0,M=0;m=C,C=C+32|0,M=m+16|0,O=m+12|0,F=m+8|0,k=m+4|0,B=m,n[M>>2]=s,n[O>>2]=l,n[F>>2]=c,n[k>>2]=f,n[B>>2]=d,YR()|0,oLe(10656,M,O,F,k,B),C=m}function oLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0;B=Wt(24)|0,RG(B+4|0,n[l>>2]|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0),n[B>>2]=n[s>>2],n[s>>2]=B}function s7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0,ct=0;if(ct=C,C=C+32|0,Me=ct+20|0,Qe=ct+8|0,rt=ct+4|0,Xe=ct,l=n[l>>2]|0,l|0){Ye=Me+4|0,F=Me+8|0,O=Qe+4|0,M=Qe+8|0,j=Qe+8|0,oe=Me+8|0;do{if(B=l+4|0,k=WR(B)|0,k|0){if(d=$w(k)|0,n[Me>>2]=0,n[Ye>>2]=0,n[F>>2]=0,f=(eI(k)|0)+1|0,aLe(Me,f),f|0)for(;f=f+-1|0,Tc(Qe,n[d>>2]|0),m=n[Ye>>2]|0,m>>>0<(n[oe>>2]|0)>>>0?(n[m>>2]=n[Qe>>2],n[Ye>>2]=(n[Ye>>2]|0)+4):KR(Me,Qe),f;)d=d+4|0;f=tI(k)|0,n[Qe>>2]=0,n[O>>2]=0,n[M>>2]=0;e:do if(n[f>>2]|0)for(d=0,m=0;;){if((d|0)==(m|0)?lLe(Qe,f):(n[d>>2]=n[f>>2],n[O>>2]=(n[O>>2]|0)+4),f=f+4|0,!(n[f>>2]|0))break e;d=n[O>>2]|0,m=n[j>>2]|0}while(!1);n[rt>>2]=LD(B)|0,n[Xe>>2]=Lr(k)|0,cLe(c,s,rt,Xe,Me,Qe),VR(Qe),$A(Me)}l=n[l>>2]|0}while(l|0)}C=ct}function WR(s){return s=s|0,n[s+12>>2]|0}function $w(s){return s=s|0,n[s+12>>2]|0}function eI(s){return s=s|0,n[s+16>>2]|0}function aLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=n[s>>2]|0,(n[s+8>>2]|0)-f>>2>>>0>>0&&(p7(c,l,(n[s+4>>2]|0)-f>>2,s+8|0),h7(s,c),g7(c)),C=d}function KR(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=f7(s)|0,m>>>0>>0)Zr(s);else{k=n[s>>2]|0,O=(n[s+8>>2]|0)-k|0,F=O>>1,p7(c,O>>2>>>0>>1>>>0?F>>>0>>0?d:F:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,h7(s,c),g7(c),C=B;return}}function tI(s){return s=s|0,n[s+8>>2]|0}function lLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=A7(s)|0,m>>>0>>0)Zr(s);else{k=n[s>>2]|0,O=(n[s+8>>2]|0)-k|0,F=O>>1,bLe(c,O>>2>>>0>>1>>>0?F>>>0>>0?d:F:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,xLe(s,c),kLe(c),C=B;return}}function LD(s){return s=s|0,n[s>>2]|0}function cLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,uLe(s,l,c,f,d,m)}function VR(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function $A(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function uLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,O=0,M=0,j=0;B=C,C=C+48|0,M=B+40|0,k=B+32|0,j=B+24|0,F=B+12|0,O=B,$a(k),s=ys(s)|0,n[j>>2]=n[l>>2],c=n[c>>2]|0,f=n[f>>2]|0,zR(F,d),ALe(O,m),n[M>>2]=n[j>>2],fLe(s,M,c,f,F,O),VR(O),$A(F),el(k),C=B}function zR(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(PLe(s,f),SLe(s,n[l>>2]|0,n[c>>2]|0,f))}function ALe(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(vLe(s,f),DLe(s,n[l>>2]|0,n[c>>2]|0,f))}function fLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,O=0,M=0,j=0;B=C,C=C+32|0,M=B+28|0,j=B+24|0,k=B+12|0,F=B,O=jo(pLe()|0)|0,n[j>>2]=n[l>>2],n[M>>2]=n[j>>2],l=L0(M)|0,c=o7(c)|0,f=JR(f)|0,n[k>>2]=n[d>>2],M=d+4|0,n[k+4>>2]=n[M>>2],j=d+8|0,n[k+8>>2]=n[j>>2],n[j>>2]=0,n[M>>2]=0,n[d>>2]=0,d=XR(k)|0,n[F>>2]=n[m>>2],M=m+4|0,n[F+4>>2]=n[M>>2],j=m+8|0,n[F+8>>2]=n[j>>2],n[j>>2]=0,n[M>>2]=0,n[m>>2]=0,gc(0,O|0,s|0,l|0,c|0,f|0,d|0,hLe(F)|0)|0,VR(F),$A(k),C=B}function pLe(){var s=0;return o[7968]|0||(ILe(10708),s=7968,n[s>>2]=1,n[s+4>>2]=0),10708}function L0(s){return s=s|0,l7(s)|0}function o7(s){return s=s|0,a7(s)|0}function JR(s){return s=s|0,RD(s)|0}function XR(s){return s=s|0,dLe(s)|0}function hLe(s){return s=s|0,gLe(s)|0}function gLe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Za(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=a7(n[(n[s>>2]|0)+(l<<2)>>2]|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function a7(s){return s=s|0,s|0}function dLe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Za(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=l7((n[s>>2]|0)+(l<<2)|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function l7(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(c7()|0)|0,f?(uR(l,f),AR(c,l),Z4e(s,c),s=fR(l)|0):s=mLe(s)|0,C=d,s|0}function c7(){var s=0;return o[7960]|0||(wLe(10664),pr(25,10664,U|0)|0,s=7960,n[s>>2]=1,n[s+4>>2]=0),10664}function mLe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Wt(4)|0,n[k>>2]=n[s>>2],m=l+4|0,n[m>>2]=k,s=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],u7(s,m,d),n[f>>2]=s,C=c,l|0}function u7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Wt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1656,n[c+12>>2]=l,n[s+4>>2]=c}function yLe(s){s=s|0,im(s),yt(s)}function ELe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function CLe(s){s=s|0,yt(s)}function wLe(s){s=s|0,Sp(s)}function ILe(s){s=s|0,ao(s,BLe()|0,5)}function BLe(){return 1676}function vLe(s,l){s=s|0,l=l|0;var c=0;if((A7(s)|0)>>>0>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Wt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function DLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(xr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function A7(s){return s=s|0,1073741823}function PLe(s,l){s=s|0,l=l|0;var c=0;if((f7(s)|0)>>>0>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Wt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function SLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(xr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function f7(s){return s=s|0,1073741823}function bLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Wt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function xLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function kLe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function p7(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Wt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function h7(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function g7(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function QLe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0;if(Qe=C,C=C+32|0,M=Qe+20|0,j=Qe+12|0,O=Qe+16|0,oe=Qe+4|0,Ye=Qe,Me=Qe+8|0,k=n7()|0,m=n[k>>2]|0,B=n[m>>2]|0,B|0)for(F=n[k+8>>2]|0,k=n[k+4>>2]|0;Tc(M,B),FLe(s,M,k,F),m=m+4|0,B=n[m>>2]|0,B;)F=F+1|0,k=k+1|0;if(m=i7()|0,B=n[m>>2]|0,B|0)do Tc(M,B),n[j>>2]=n[m+4>>2],RLe(l,M,j),m=m+8|0,B=n[m>>2]|0;while(B|0);if(m=n[($d()|0)>>2]|0,m|0)do l=n[m+4>>2]|0,Tc(M,n[(em(l)|0)>>2]|0),n[j>>2]=GR(l)|0,TLe(c,M,j),m=n[m>>2]|0;while(m|0);if(Tc(O,0),m=YR()|0,n[M>>2]=n[O>>2],s7(M,m,d),m=n[($d()|0)>>2]|0,m|0){s=M+4|0,l=M+8|0,c=M+8|0;do{if(F=n[m+4>>2]|0,Tc(j,n[(em(F)|0)>>2]|0),NLe(oe,d7(F)|0),B=n[oe>>2]|0,B|0){n[M>>2]=0,n[s>>2]=0,n[l>>2]=0;do Tc(Ye,n[(em(n[B+4>>2]|0)|0)>>2]|0),k=n[s>>2]|0,k>>>0<(n[c>>2]|0)>>>0?(n[k>>2]=n[Ye>>2],n[s>>2]=(n[s>>2]|0)+4):KR(M,Ye),B=n[B>>2]|0;while(B|0);LLe(f,j,M),$A(M)}n[Me>>2]=n[j>>2],O=m7(F)|0,n[M>>2]=n[Me>>2],s7(M,O,d),UG(oe),m=n[m>>2]|0}while(m|0)}C=Qe}function FLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,VLe(s,l,c,f)}function RLe(s,l,c){s=s|0,l=l|0,c=c|0,KLe(s,l,c)}function em(s){return s=s|0,s|0}function TLe(s,l,c){s=s|0,l=l|0,c=c|0,jLe(s,l,c)}function d7(s){return s=s|0,s+16|0}function NLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;if(m=C,C=C+16|0,d=m+8|0,c=m,n[s>>2]=0,f=n[l>>2]|0,n[d>>2]=f,n[c>>2]=s,c=qLe(c)|0,f|0){if(f=Wt(12)|0,B=(y7(d)|0)+4|0,s=n[B+4>>2]|0,l=f+4|0,n[l>>2]=n[B>>2],n[l+4>>2]=s,l=n[n[d>>2]>>2]|0,n[d>>2]=l,!l)s=f;else for(l=f;s=Wt(12)|0,F=(y7(d)|0)+4|0,k=n[F+4>>2]|0,B=s+4|0,n[B>>2]=n[F>>2],n[B+4>>2]=k,n[l>>2]=s,B=n[n[d>>2]>>2]|0,n[d>>2]=B,B;)l=s;n[s>>2]=n[c>>2],n[c>>2]=f}C=m}function LLe(s,l,c){s=s|0,l=l|0,c=c|0,MLe(s,l,c)}function m7(s){return s=s|0,s+24|0}function MLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+24|0,d=f+16|0,k=f+12|0,m=f,$a(d),s=ys(s)|0,n[k>>2]=n[l>>2],zR(m,c),n[B>>2]=n[k>>2],OLe(s,B,m),$A(m),el(d),C=f}function OLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+16|0,k=f+12|0,d=f,m=jo(ULe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=L0(B)|0,n[d>>2]=n[c>>2],B=c+4|0,n[d+4>>2]=n[B>>2],k=c+8|0,n[d+8>>2]=n[k>>2],n[k>>2]=0,n[B>>2]=0,n[c>>2]=0,hs(0,m|0,s|0,l|0,XR(d)|0)|0,$A(d),C=f}function ULe(){var s=0;return o[7976]|0||(_Le(10720),s=7976,n[s>>2]=1,n[s+4>>2]=0),10720}function _Le(s){s=s|0,ao(s,HLe()|0,2)}function HLe(){return 1732}function qLe(s){return s=s|0,n[s>>2]|0}function y7(s){return s=s|0,n[s>>2]|0}function jLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,$a(d),s=ys(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],E7(s,m,c),el(d),C=f}function E7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+4|0,B=f,d=jo(GLe()|0)|0,n[B>>2]=n[l>>2],n[m>>2]=n[B>>2],l=L0(m)|0,hs(0,d|0,s|0,l|0,o7(c)|0)|0,C=f}function GLe(){var s=0;return o[7984]|0||(YLe(10732),s=7984,n[s>>2]=1,n[s+4>>2]=0),10732}function YLe(s){s=s|0,ao(s,WLe()|0,2)}function WLe(){return 1744}function KLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,$a(d),s=ys(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],E7(s,m,c),el(d),C=f}function VLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,$a(m),s=ys(s)|0,n[k>>2]=n[l>>2],c=o[c>>0]|0,f=o[f>>0]|0,n[B>>2]=n[k>>2],zLe(s,B,c,f),el(m),C=d}function zLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,B=d+4|0,k=d,m=jo(JLe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=L0(B)|0,c=tm(c)|0,vi(0,m|0,s|0,l|0,c|0,tm(f)|0)|0,C=d}function JLe(){var s=0;return o[7992]|0||(ZLe(10744),s=7992,n[s>>2]=1,n[s+4>>2]=0),10744}function tm(s){return s=s|0,XLe(s)|0}function XLe(s){return s=s|0,s&255|0}function ZLe(s){s=s|0,ao(s,$Le()|0,3)}function $Le(){return 1756}function eMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;switch(oe=C,C=C+32|0,k=oe+8|0,F=oe+4|0,O=oe+20|0,M=oe,dR(s,0),f=X4e(l)|0,n[k>>2]=0,j=k+4|0,n[j>>2]=0,n[k+8>>2]=0,f<<24>>24){case 0:{o[O>>0]=0,tMe(F,c,O),MD(s,F)|0,xu(F);break}case 8:{j=nT(l)|0,o[O>>0]=8,Tc(M,n[j+4>>2]|0),rMe(F,c,O,M,j+8|0),MD(s,F)|0,xu(F);break}case 9:{if(m=nT(l)|0,l=n[m+4>>2]|0,l|0)for(B=k+8|0,d=m+12|0;l=l+-1|0,Tc(F,n[d>>2]|0),f=n[j>>2]|0,f>>>0<(n[B>>2]|0)>>>0?(n[f>>2]=n[F>>2],n[j>>2]=(n[j>>2]|0)+4):KR(k,F),l;)d=d+4|0;o[O>>0]=9,Tc(M,n[m+8>>2]|0),nMe(F,c,O,M,k),MD(s,F)|0,xu(F);break}default:j=nT(l)|0,o[O>>0]=f,Tc(M,n[j+4>>2]|0),iMe(F,c,O,M),MD(s,F)|0,xu(F)}$A(k),C=oe}function tMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,$a(d),l=ys(l)|0,mMe(s,l,o[c>>0]|0),el(d),C=f}function MD(s,l){s=s|0,l=l|0;var c=0;return c=n[s>>2]|0,c|0&&sa(c|0),n[s>>2]=n[l>>2],n[l>>2]=0,s|0}function rMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+32|0,k=m+16|0,B=m+8|0,F=m,$a(B),l=ys(l)|0,c=o[c>>0]|0,n[F>>2]=n[f>>2],d=n[d>>2]|0,n[k>>2]=n[F>>2],pMe(s,l,c,k,d),el(B),C=m}function nMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0;m=C,C=C+32|0,F=m+24|0,B=m+16|0,O=m+12|0,k=m,$a(B),l=ys(l)|0,c=o[c>>0]|0,n[O>>2]=n[f>>2],zR(k,d),n[F>>2]=n[O>>2],cMe(s,l,c,F,k),$A(k),el(B),C=m}function iMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,$a(m),l=ys(l)|0,c=o[c>>0]|0,n[k>>2]=n[f>>2],n[B>>2]=n[k>>2],sMe(s,l,c,B),el(m),C=d}function sMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+4|0,k=d,B=jo(oMe()|0)|0,c=tm(c)|0,n[k>>2]=n[f>>2],n[m>>2]=n[k>>2],OD(s,hs(0,B|0,l|0,c|0,L0(m)|0)|0),C=d}function oMe(){var s=0;return o[8e3]|0||(aMe(10756),s=8e3,n[s>>2]=1,n[s+4>>2]=0),10756}function OD(s,l){s=s|0,l=l|0,dR(s,l)}function aMe(s){s=s|0,ao(s,lMe()|0,2)}function lMe(){return 1772}function cMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0;m=C,C=C+32|0,F=m+16|0,O=m+12|0,B=m,k=jo(uMe()|0)|0,c=tm(c)|0,n[O>>2]=n[f>>2],n[F>>2]=n[O>>2],f=L0(F)|0,n[B>>2]=n[d>>2],F=d+4|0,n[B+4>>2]=n[F>>2],O=d+8|0,n[B+8>>2]=n[O>>2],n[O>>2]=0,n[F>>2]=0,n[d>>2]=0,OD(s,vi(0,k|0,l|0,c|0,f|0,XR(B)|0)|0),$A(B),C=m}function uMe(){var s=0;return o[8008]|0||(AMe(10768),s=8008,n[s>>2]=1,n[s+4>>2]=0),10768}function AMe(s){s=s|0,ao(s,fMe()|0,3)}function fMe(){return 1784}function pMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+16|0,k=m+4|0,F=m,B=jo(hMe()|0)|0,c=tm(c)|0,n[F>>2]=n[f>>2],n[k>>2]=n[F>>2],f=L0(k)|0,OD(s,vi(0,B|0,l|0,c|0,f|0,JR(d)|0)|0),C=m}function hMe(){var s=0;return o[8016]|0||(gMe(10780),s=8016,n[s>>2]=1,n[s+4>>2]=0),10780}function gMe(s){s=s|0,ao(s,dMe()|0,3)}function dMe(){return 1800}function mMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=jo(yMe()|0)|0,OD(s,un(0,f|0,l|0,tm(c)|0)|0)}function yMe(){var s=0;return o[8024]|0||(EMe(10792),s=8024,n[s>>2]=1,n[s+4>>2]=0),10792}function EMe(s){s=s|0,ao(s,CMe()|0,1)}function CMe(){return 1816}function wMe(){IMe(),BMe(),vMe()}function IMe(){n[2702]=K7(65536)|0}function BMe(){GMe(10856)}function vMe(){DMe(10816)}function DMe(s){s=s|0,PMe(s,5044),SMe(s)|0}function PMe(s,l){s=s|0,l=l|0;var c=0;c=c7()|0,n[s>>2]=c,OMe(c,l),Fp(n[s>>2]|0)}function SMe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,bMe()|0),s|0}function bMe(){var s=0;return o[8032]|0||(C7(10820),pr(64,10820,U|0)|0,s=8032,n[s>>2]=1,n[s+4>>2]=0),Lr(10820)|0||C7(10820),10820}function C7(s){s=s|0,QMe(s),N0(s,25)}function xMe(s){s=s|0,kMe(s+24|0)}function kMe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function QMe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,18,l,NMe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function FMe(s,l){s=s|0,l=l|0,RMe(s,l)}function RMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;c=C,C=C+16|0,f=c,d=c+4|0,F0(d,l),n[f>>2]=R0(d,l)|0,TMe(s,f),C=c}function TMe(s,l){s=s|0,l=l|0,w7(s+4|0,n[l>>2]|0),o[s+8>>0]=1}function w7(s,l){s=s|0,l=l|0,n[s>>2]=l}function NMe(){return 1824}function LMe(s){return s=s|0,MMe(s)|0}function MMe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Wt(4)|0,F0(d,s),w7(k,R0(d,s)|0),m=l+4|0,n[m>>2]=k,s=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],u7(s,m,d),n[f>>2]=s,C=c,l|0}function Za(s){s=s|0;var l=0,c=0;return s=s+7&-8,s>>>0<=32768&&(l=n[2701]|0,s>>>0<=(65536-l|0)>>>0)?(c=(n[2702]|0)+l|0,n[2701]=l+s,s=c):(s=K7(s+8|0)|0,n[s>>2]=n[2703],n[2703]=s,s=s+8|0),s|0}function OMe(s,l){s=s|0,l=l|0,n[s>>2]=UMe()|0,n[s+4>>2]=_Me()|0,n[s+12>>2]=l,n[s+8>>2]=HMe()|0,n[s+32>>2]=9}function UMe(){return 11744}function _Me(){return 1832}function HMe(){return ND()|0}function qMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(jMe(c),yt(c)):l|0&&yt(l)}function jMe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function GMe(s){s=s|0,YMe(s,5052),WMe(s)|0,KMe(s,5058,26)|0,VMe(s,5069,1)|0,zMe(s,5077,10)|0,JMe(s,5087,19)|0,XMe(s,5094,27)|0}function YMe(s,l){s=s|0,l=l|0;var c=0;c=j4e()|0,n[s>>2]=c,G4e(c,l),Fp(n[s>>2]|0)}function WMe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,x4e()|0),s|0}function KMe(s,l,c){return s=s|0,l=l|0,c=c|0,A4e(s,mn(l)|0,c,0),s|0}function VMe(s,l,c){return s=s|0,l=l|0,c=c|0,JOe(s,mn(l)|0,c,0),s|0}function zMe(s,l,c){return s=s|0,l=l|0,c=c|0,bOe(s,mn(l)|0,c,0),s|0}function JMe(s,l,c){return s=s|0,l=l|0,c=c|0,pOe(s,mn(l)|0,c,0),s|0}function I7(s,l){s=s|0,l=l|0;var c=0,f=0;e:for(;;){for(c=n[2703]|0;;){if((c|0)==(l|0))break e;if(f=n[c>>2]|0,n[2703]=f,!c)c=f;else break}yt(c)}n[2701]=s}function XMe(s,l,c){return s=s|0,l=l|0,c=c|0,ZMe(s,mn(l)|0,c,0),s|0}function ZMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=ZR()|0,s=$Me(c)|0,yn(m,l,d,s,eOe(c,f)|0,f)}function ZR(){var s=0,l=0;if(o[8040]|0||(v7(10860),pr(65,10860,U|0)|0,l=8040,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10860)|0)){s=10860,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));v7(10860)}return 10860}function $Me(s){return s=s|0,s|0}function eOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=ZR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(B7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(tOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function B7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function tOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=rOe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,nOe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,B7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,iOe(s,d),sOe(d),C=k;return}}function rOe(s){return s=s|0,536870911}function nOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function iOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function sOe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function v7(s){s=s|0,lOe(s)}function oOe(s){s=s|0,aOe(s+24|0)}function aOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function lOe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,11,l,cOe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function cOe(){return 1840}function uOe(s,l,c){s=s|0,l=l|0,c=c|0,fOe(n[(AOe(s)|0)>>2]|0,l,c)}function AOe(s){return s=s|0,(n[(ZR()|0)+24>>2]|0)+(s<<3)|0}function fOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+1|0,d=f,F0(m,l),l=R0(m,l)|0,F0(d,c),c=R0(d,c)|0,tf[s&31](l,c),C=f}function pOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=$R()|0,s=hOe(c)|0,yn(m,l,d,s,gOe(c,f)|0,f)}function $R(){var s=0,l=0;if(o[8048]|0||(P7(10896),pr(66,10896,U|0)|0,l=8048,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10896)|0)){s=10896,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));P7(10896)}return 10896}function hOe(s){return s=s|0,s|0}function gOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=$R()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(D7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(dOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function D7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function dOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=mOe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,yOe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,D7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,EOe(s,d),COe(d),C=k;return}}function mOe(s){return s=s|0,536870911}function yOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function EOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function COe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function P7(s){s=s|0,BOe(s)}function wOe(s){s=s|0,IOe(s+24|0)}function IOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function BOe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,11,l,vOe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function vOe(){return 1852}function DOe(s,l){return s=s|0,l=l|0,SOe(n[(POe(s)|0)>>2]|0,l)|0}function POe(s){return s=s|0,(n[($R()|0)+24>>2]|0)+(s<<3)|0}function SOe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,F0(f,l),l=R0(f,l)|0,l=RD(_0[s&31](l)|0)|0,C=c,l|0}function bOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=eT()|0,s=xOe(c)|0,yn(m,l,d,s,kOe(c,f)|0,f)}function eT(){var s=0,l=0;if(o[8056]|0||(b7(10932),pr(67,10932,U|0)|0,l=8056,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10932)|0)){s=10932,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));b7(10932)}return 10932}function xOe(s){return s=s|0,s|0}function kOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=eT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(S7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(QOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function S7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function QOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=FOe(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,ROe(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,S7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,TOe(s,d),NOe(d),C=k;return}}function FOe(s){return s=s|0,536870911}function ROe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function TOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function NOe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function b7(s){s=s|0,OOe(s)}function LOe(s){s=s|0,MOe(s+24|0)}function MOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function OOe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,7,l,UOe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function UOe(){return 1860}function _Oe(s,l,c){return s=s|0,l=l|0,c=c|0,qOe(n[(HOe(s)|0)>>2]|0,l,c)|0}function HOe(s){return s=s|0,(n[(eT()|0)+24>>2]|0)+(s<<3)|0}function qOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+32|0,B=f+12|0,m=f+8|0,k=f,F=f+16|0,d=f+4|0,jOe(F,l),GOe(k,F,l),bp(d,c),c=xp(d,c)|0,n[B>>2]=n[k>>2],sI[s&15](m,B,c),c=YOe(m)|0,xu(m),kp(d),C=f,c|0}function jOe(s,l){s=s|0,l=l|0}function GOe(s,l,c){s=s|0,l=l|0,c=c|0,WOe(s,c)}function YOe(s){return s=s|0,ys(s)|0}function WOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+16|0,c=d,f=l,f&1?(KOe(c,0),ia(f|0,c|0)|0,VOe(s,c),zOe(c)):n[s>>2]=n[l>>2],C=d}function KOe(s,l){s=s|0,l=l|0,Fc(s,l),n[s+4>>2]=0,o[s+8>>0]=0}function VOe(s,l){s=s|0,l=l|0,n[s>>2]=n[l+4>>2]}function zOe(s){s=s|0,o[s+8>>0]=0}function JOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=tT()|0,s=XOe(c)|0,yn(m,l,d,s,ZOe(c,f)|0,f)}function tT(){var s=0,l=0;if(o[8064]|0||(k7(10968),pr(68,10968,U|0)|0,l=8064,n[l>>2]=1,n[l+4>>2]=0),!(Lr(10968)|0)){s=10968,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));k7(10968)}return 10968}function XOe(s){return s=s|0,s|0}function ZOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=tT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(x7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):($Oe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function x7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function $Oe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=e4e(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,t4e(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,x7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,r4e(s,d),n4e(d),C=k;return}}function e4e(s){return s=s|0,536870911}function t4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function r4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function n4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function k7(s){s=s|0,o4e(s)}function i4e(s){s=s|0,s4e(s+24|0)}function s4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function o4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,1,l,a4e()|0,5),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function a4e(){return 1872}function l4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,u4e(n[(c4e(s)|0)>>2]|0,l,c,f,d,m)}function c4e(s){return s=s|0,(n[(tT()|0)+24>>2]|0)+(s<<3)|0}function u4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,O=0,M=0,j=0;B=C,C=C+32|0,k=B+16|0,F=B+12|0,O=B+8|0,M=B+4|0,j=B,bp(k,l),l=xp(k,l)|0,bp(F,c),c=xp(F,c)|0,bp(O,f),f=xp(O,f)|0,bp(M,d),d=xp(M,d)|0,bp(j,m),m=xp(j,m)|0,Z7[s&1](l,c,f,d,m),kp(j),kp(M),kp(O),kp(F),kp(k),C=B}function A4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=rT()|0,s=f4e(c)|0,yn(m,l,d,s,p4e(c,f)|0,f)}function rT(){var s=0,l=0;if(o[8072]|0||(F7(11004),pr(69,11004,U|0)|0,l=8072,n[l>>2]=1,n[l+4>>2]=0),!(Lr(11004)|0)){s=11004,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));F7(11004)}return 11004}function f4e(s){return s=s|0,s|0}function p4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=rT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(Q7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(h4e(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function Q7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function h4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=g4e(s)|0,f>>>0>>0)Zr(s);else{F=n[s>>2]|0,M=(n[s+8>>2]|0)-F|0,O=M>>2,d4e(d,M>>3>>>0>>1>>>0?O>>>0>>0?B:O:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,Q7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,m4e(s,d),y4e(d),C=k;return}}function g4e(s){return s=s|0,536870911}function d4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Wt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function m4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(xr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function y4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function F7(s){s=s|0,w4e(s)}function E4e(s){s=s|0,C4e(s+24|0)}function C4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function w4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,12,l,I4e()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function I4e(){return 1896}function B4e(s,l,c){s=s|0,l=l|0,c=c|0,D4e(n[(v4e(s)|0)>>2]|0,l,c)}function v4e(s){return s=s|0,(n[(rT()|0)+24>>2]|0)+(s<<3)|0}function D4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+4|0,d=f,P4e(m,l),l=S4e(m,l)|0,bp(d,c),c=xp(d,c)|0,tf[s&31](l,c),kp(d),C=f}function P4e(s,l){s=s|0,l=l|0}function S4e(s,l){return s=s|0,l=l|0,b4e(l)|0}function b4e(s){return s=s|0,s|0}function x4e(){var s=0;return o[8080]|0||(R7(11040),pr(70,11040,U|0)|0,s=8080,n[s>>2]=1,n[s+4>>2]=0),Lr(11040)|0||R7(11040),11040}function R7(s){s=s|0,F4e(s),N0(s,71)}function k4e(s){s=s|0,Q4e(s+24|0)}function Q4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function F4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,7,l,L4e()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function R4e(s){s=s|0,T4e(s)}function T4e(s){s=s|0,N4e(s)}function N4e(s){s=s|0,o[s+8>>0]=1}function L4e(){return 1936}function M4e(){return O4e()|0}function O4e(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,m=s+4|0,n[m>>2]=Wt(1)|0,f=Wt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],U4e(f,m,d),n[c>>2]=f,C=l,s|0}function U4e(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Wt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1916,n[c+12>>2]=l,n[s+4>>2]=c}function _4e(s){s=s|0,im(s),yt(s)}function H4e(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function q4e(s){s=s|0,yt(s)}function j4e(){var s=0;return o[8088]|0||(J4e(11076),pr(25,11076,U|0)|0,s=8088,n[s>>2]=1,n[s+4>>2]=0),11076}function G4e(s,l){s=s|0,l=l|0,n[s>>2]=Y4e()|0,n[s+4>>2]=W4e()|0,n[s+12>>2]=l,n[s+8>>2]=K4e()|0,n[s+32>>2]=10}function Y4e(){return 11745}function W4e(){return 1940}function K4e(){return TD()|0}function V4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(z4e(c),yt(c)):l|0&&yt(l)}function z4e(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function J4e(s){s=s|0,Sp(s)}function Tc(s,l){s=s|0,l=l|0,n[s>>2]=l}function nT(s){return s=s|0,n[s>>2]|0}function X4e(s){return s=s|0,o[n[s>>2]>>0]|0}function Z4e(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,n[f>>2]=n[s>>2],$4e(l,f)|0,C=c}function $4e(s,l){s=s|0,l=l|0;var c=0;return c=eUe(n[s>>2]|0,l)|0,l=s+4|0,n[(n[l>>2]|0)+8>>2]=c,n[(n[l>>2]|0)+8>>2]|0}function eUe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,$a(f),s=ys(s)|0,l=tUe(s,n[l>>2]|0)|0,el(f),C=c,l|0}function $a(s){s=s|0,n[s>>2]=n[2701],n[s+4>>2]=n[2703]}function tUe(s,l){s=s|0,l=l|0;var c=0;return c=jo(rUe()|0)|0,un(0,c|0,s|0,JR(l)|0)|0}function el(s){s=s|0,I7(n[s>>2]|0,n[s+4>>2]|0)}function rUe(){var s=0;return o[8096]|0||(nUe(11120),s=8096,n[s>>2]=1,n[s+4>>2]=0),11120}function nUe(s){s=s|0,ao(s,iUe()|0,1)}function iUe(){return 1948}function sUe(){oUe()}function oUe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0;if(Me=C,C=C+16|0,M=Me+4|0,j=Me,Ro(65536,10804,n[2702]|0,10812),c=n7()|0,l=n[c>>2]|0,s=n[l>>2]|0,s|0)for(f=n[c+8>>2]|0,c=n[c+4>>2]|0;du(s|0,u[c>>0]|0|0,o[f>>0]|0),l=l+4|0,s=n[l>>2]|0,s;)f=f+1|0,c=c+1|0;if(s=i7()|0,l=n[s>>2]|0,l|0)do QA(l|0,n[s+4>>2]|0),s=s+8|0,l=n[s>>2]|0;while(l|0);QA(aUe()|0,5167),O=$d()|0,s=n[O>>2]|0;e:do if(s|0){do lUe(n[s+4>>2]|0),s=n[s>>2]|0;while(s|0);if(s=n[O>>2]|0,s|0){F=O;do{for(;d=s,s=n[s>>2]|0,d=n[d+4>>2]|0,!!(cUe(d)|0);)if(n[j>>2]=F,n[M>>2]=n[j>>2],uUe(O,M)|0,!s)break e;if(AUe(d),F=n[F>>2]|0,l=T7(d)|0,m=Bi()|0,B=C,C=C+((1*(l<<2)|0)+15&-16)|0,k=C,C=C+((1*(l<<2)|0)+15&-16)|0,l=n[(d7(d)|0)>>2]|0,l|0)for(c=B,f=k;n[c>>2]=n[(em(n[l+4>>2]|0)|0)>>2],n[f>>2]=n[l+8>>2],l=n[l>>2]|0,l;)c=c+4|0,f=f+4|0;Qe=em(d)|0,l=fUe(d)|0,c=T7(d)|0,f=pUe(d)|0,wl(Qe|0,l|0,B|0,k|0,c|0,f|0,GR(d)|0),kA(m|0)}while(s|0)}}while(!1);if(s=n[(YR()|0)>>2]|0,s|0)do Qe=s+4|0,O=WR(Qe)|0,d=tI(O)|0,m=$w(O)|0,B=(eI(O)|0)+1|0,k=UD(O)|0,F=N7(Qe)|0,O=Lr(O)|0,M=LD(Qe)|0,j=iT(Qe)|0,mc(0,d|0,m|0,B|0,k|0,F|0,O|0,M|0,j|0,sT(Qe)|0),s=n[s>>2]|0;while(s|0);s=n[($d()|0)>>2]|0;e:do if(s|0){t:for(;;){if(l=n[s+4>>2]|0,l|0&&(oe=n[(em(l)|0)>>2]|0,Ye=n[(m7(l)|0)>>2]|0,Ye|0)){c=Ye;do{l=c+4|0,f=WR(l)|0;r:do if(f|0)switch(Lr(f)|0){case 0:break t;case 4:case 3:case 2:{k=tI(f)|0,F=$w(f)|0,O=(eI(f)|0)+1|0,M=UD(f)|0,j=Lr(f)|0,Qe=LD(l)|0,mc(oe|0,k|0,F|0,O|0,M|0,0,j|0,Qe|0,iT(l)|0,sT(l)|0);break r}case 1:{B=tI(f)|0,k=$w(f)|0,F=(eI(f)|0)+1|0,O=UD(f)|0,M=N7(l)|0,j=Lr(f)|0,Qe=LD(l)|0,mc(oe|0,B|0,k|0,F|0,O|0,M|0,j|0,Qe|0,iT(l)|0,sT(l)|0);break r}case 5:{O=tI(f)|0,M=$w(f)|0,j=(eI(f)|0)+1|0,Qe=UD(f)|0,mc(oe|0,O|0,M|0,j|0,Qe|0,hUe(f)|0,Lr(f)|0,0,0,0);break r}default:break r}while(!1);c=n[c>>2]|0}while(c|0)}if(s=n[s>>2]|0,!s)break e}Tt()}while(!1);Ie(),C=Me}function aUe(){return 11703}function lUe(s){s=s|0,o[s+40>>0]=0}function cUe(s){return s=s|0,(o[s+40>>0]|0)!=0|0}function uUe(s,l){return s=s|0,l=l|0,l=gUe(l)|0,s=n[l>>2]|0,n[l>>2]=n[s>>2],yt(s),n[l>>2]|0}function AUe(s){s=s|0,o[s+40>>0]=1}function T7(s){return s=s|0,n[s+20>>2]|0}function fUe(s){return s=s|0,n[s+8>>2]|0}function pUe(s){return s=s|0,n[s+32>>2]|0}function UD(s){return s=s|0,n[s+4>>2]|0}function N7(s){return s=s|0,n[s+4>>2]|0}function iT(s){return s=s|0,n[s+8>>2]|0}function sT(s){return s=s|0,n[s+16>>2]|0}function hUe(s){return s=s|0,n[s+20>>2]|0}function gUe(s){return s=s|0,n[s>>2]|0}function _D(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Lt=0;Lt=C,C=C+16|0,oe=Lt;do if(s>>>0<245){if(O=s>>>0<11?16:s+11&-8,s=O>>>3,j=n[2783]|0,c=j>>>s,c&3|0)return l=(c&1^1)+s|0,s=11172+(l<<1<<2)|0,c=s+8|0,f=n[c>>2]|0,d=f+8|0,m=n[d>>2]|0,(s|0)==(m|0)?n[2783]=j&~(1<>2]=s,n[c>>2]=m),Ge=l<<3,n[f+4>>2]=Ge|3,Ge=f+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1,Ge=d,C=Lt,Ge|0;if(M=n[2785]|0,O>>>0>M>>>0){if(c|0)return l=2<>>12&16,l=l>>>B,c=l>>>5&8,l=l>>>c,d=l>>>2&4,l=l>>>d,s=l>>>1&2,l=l>>>s,f=l>>>1&1,f=(c|B|d|s|f)+(l>>>f)|0,l=11172+(f<<1<<2)|0,s=l+8|0,d=n[s>>2]|0,B=d+8|0,c=n[B>>2]|0,(l|0)==(c|0)?(s=j&~(1<>2]=l,n[s>>2]=c,s=j),m=(f<<3)-O|0,n[d+4>>2]=O|3,f=d+O|0,n[f+4>>2]=m|1,n[f+m>>2]=m,M|0&&(d=n[2788]|0,l=M>>>3,c=11172+(l<<1<<2)|0,l=1<>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=d,n[l+12>>2]=d,n[d+8>>2]=l,n[d+12>>2]=c),n[2785]=m,n[2788]=f,Ge=B,C=Lt,Ge|0;if(k=n[2784]|0,k){if(c=(k&0-k)+-1|0,B=c>>>12&16,c=c>>>B,m=c>>>5&8,c=c>>>m,F=c>>>2&4,c=c>>>F,f=c>>>1&2,c=c>>>f,s=c>>>1&1,s=n[11436+((m|B|F|f|s)+(c>>>s)<<2)>>2]|0,c=(n[s+4>>2]&-8)-O|0,f=n[s+16+(((n[s+16>>2]|0)==0&1)<<2)>>2]|0,!f)F=s,m=c;else{do B=(n[f+4>>2]&-8)-O|0,F=B>>>0>>0,c=F?B:c,s=F?f:s,f=n[f+16+(((n[f+16>>2]|0)==0&1)<<2)>>2]|0;while(f|0);F=s,m=c}if(B=F+O|0,F>>>0>>0){d=n[F+24>>2]|0,l=n[F+12>>2]|0;do if((l|0)==(F|0)){if(s=F+20|0,l=n[s>>2]|0,!l&&(s=F+16|0,l=n[s>>2]|0,!l)){c=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0,c=l}else c=n[F+8>>2]|0,n[c+12>>2]=l,n[l+8>>2]=c,c=l;while(!1);do if(d|0){if(l=n[F+28>>2]|0,s=11436+(l<<2)|0,(F|0)==(n[s>>2]|0)){if(n[s>>2]=c,!c){n[2784]=k&~(1<>2]|0)!=(F|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=d,l=n[F+16>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),l=n[F+20>>2]|0,l|0&&(n[c+20>>2]=l,n[l+24>>2]=c)}while(!1);return m>>>0<16?(Ge=m+O|0,n[F+4>>2]=Ge|3,Ge=F+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1):(n[F+4>>2]=O|3,n[B+4>>2]=m|1,n[B+m>>2]=m,M|0&&(f=n[2788]|0,l=M>>>3,c=11172+(l<<1<<2)|0,l=1<>2]|0):(n[2783]=j|l,l=c,s=c+8|0),n[s>>2]=f,n[l+12>>2]=f,n[f+8>>2]=l,n[f+12>>2]=c),n[2785]=m,n[2788]=B),Ge=F+8|0,C=Lt,Ge|0}else j=O}else j=O}else j=O}else if(s>>>0<=4294967231)if(s=s+11|0,O=s&-8,F=n[2784]|0,F){f=0-O|0,s=s>>>8,s?O>>>0>16777215?k=31:(j=(s+1048320|0)>>>16&8,_e=s<>>16&4,_e=_e<>>16&2,k=14-(M|j|k)+(_e<>>15)|0,k=O>>>(k+7|0)&1|k<<1):k=0,c=n[11436+(k<<2)>>2]|0;e:do if(!c)c=0,s=0,_e=57;else for(s=0,B=O<<((k|0)==31?0:25-(k>>>1)|0),m=0;;){if(d=(n[c+4>>2]&-8)-O|0,d>>>0>>0)if(d)s=c,f=d;else{s=c,f=0,d=c,_e=61;break e}if(d=n[c+20>>2]|0,c=n[c+16+(B>>>31<<2)>>2]|0,m=(d|0)==0|(d|0)==(c|0)?m:d,d=(c|0)==0,d){c=m,_e=57;break}else B=B<<((d^1)&1)}while(!1);if((_e|0)==57){if((c|0)==0&(s|0)==0){if(s=2<>>12&16,j=j>>>B,m=j>>>5&8,j=j>>>m,k=j>>>2&4,j=j>>>k,M=j>>>1&2,j=j>>>M,c=j>>>1&1,s=0,c=n[11436+((m|B|k|M|c)+(j>>>c)<<2)>>2]|0}c?(d=c,_e=61):(k=s,B=f)}if((_e|0)==61)for(;;)if(_e=0,c=(n[d+4>>2]&-8)-O|0,j=c>>>0>>0,c=j?c:f,s=j?d:s,d=n[d+16+(((n[d+16>>2]|0)==0&1)<<2)>>2]|0,d)f=c,_e=61;else{k=s,B=c;break}if(k|0&&B>>>0<((n[2785]|0)-O|0)>>>0){if(m=k+O|0,k>>>0>=m>>>0)return Ge=0,C=Lt,Ge|0;d=n[k+24>>2]|0,l=n[k+12>>2]|0;do if((l|0)==(k|0)){if(s=k+20|0,l=n[s>>2]|0,!l&&(s=k+16|0,l=n[s>>2]|0,!l)){l=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0}else Ge=n[k+8>>2]|0,n[Ge+12>>2]=l,n[l+8>>2]=Ge;while(!1);do if(d){if(s=n[k+28>>2]|0,c=11436+(s<<2)|0,(k|0)==(n[c>>2]|0)){if(n[c>>2]=l,!l){f=F&~(1<>2]|0)!=(k|0)&1)<<2)>>2]=l,!l){f=F;break}n[l+24>>2]=d,s=n[k+16>>2]|0,s|0&&(n[l+16>>2]=s,n[s+24>>2]=l),s=n[k+20>>2]|0,s&&(n[l+20>>2]=s,n[s+24>>2]=l),f=F}else f=F;while(!1);do if(B>>>0>=16){if(n[k+4>>2]=O|3,n[m+4>>2]=B|1,n[m+B>>2]=B,l=B>>>3,B>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=m,n[l+12>>2]=m,n[m+8>>2]=l,n[m+12>>2]=c;break}if(l=B>>>8,l?B>>>0>16777215?l=31:(_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<>>16&2,l=14-(ct|_e|l)+(Ge<>>15)|0,l=B>>>(l+7|0)&1|l<<1):l=0,c=11436+(l<<2)|0,n[m+28>>2]=l,s=m+16|0,n[s+4>>2]=0,n[s>>2]=0,s=1<>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}for(s=B<<((l|0)==31?0:25-(l>>>1)|0),c=n[c>>2]|0;;){if((n[c+4>>2]&-8|0)==(B|0)){_e=97;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=96;break}}if((_e|0)==96){n[f>>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}else if((_e|0)==97){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=m,n[_e>>2]=m,n[m+8>>2]=Ge,n[m+12>>2]=c,n[m+24>>2]=0;break}}else Ge=B+O|0,n[k+4>>2]=Ge|3,Ge=k+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1;while(!1);return Ge=k+8|0,C=Lt,Ge|0}else j=O}else j=O;else j=-1;while(!1);if(c=n[2785]|0,c>>>0>=j>>>0)return l=c-j|0,s=n[2788]|0,l>>>0>15?(Ge=s+j|0,n[2788]=Ge,n[2785]=l,n[Ge+4>>2]=l|1,n[Ge+l>>2]=l,n[s+4>>2]=j|3):(n[2785]=0,n[2788]=0,n[s+4>>2]=c|3,Ge=s+c+4|0,n[Ge>>2]=n[Ge>>2]|1),Ge=s+8|0,C=Lt,Ge|0;if(B=n[2786]|0,B>>>0>j>>>0)return ct=B-j|0,n[2786]=ct,Ge=n[2789]|0,_e=Ge+j|0,n[2789]=_e,n[_e+4>>2]=ct|1,n[Ge+4>>2]=j|3,Ge=Ge+8|0,C=Lt,Ge|0;if(n[2901]|0?s=n[2903]|0:(n[2903]=4096,n[2902]=4096,n[2904]=-1,n[2905]=-1,n[2906]=0,n[2894]=0,s=oe&-16^1431655768,n[oe>>2]=s,n[2901]=s,s=4096),k=j+48|0,F=j+47|0,m=s+F|0,d=0-s|0,O=m&d,O>>>0<=j>>>0||(s=n[2893]|0,s|0&&(M=n[2891]|0,oe=M+O|0,oe>>>0<=M>>>0|oe>>>0>s>>>0)))return Ge=0,C=Lt,Ge|0;e:do if(n[2894]&4)l=0,_e=133;else{c=n[2789]|0;t:do if(c){for(f=11580;s=n[f>>2]|0,!(s>>>0<=c>>>0&&(Qe=f+4|0,(s+(n[Qe>>2]|0)|0)>>>0>c>>>0));)if(s=n[f+8>>2]|0,s)f=s;else{_e=118;break t}if(l=m-B&d,l>>>0<2147483647)if(s=Tp(l|0)|0,(s|0)==((n[f>>2]|0)+(n[Qe>>2]|0)|0)){if((s|0)!=-1){B=l,m=s,_e=135;break e}}else f=s,_e=126;else l=0}else _e=118;while(!1);do if((_e|0)==118)if(c=Tp(0)|0,(c|0)!=-1&&(l=c,Ye=n[2902]|0,Me=Ye+-1|0,l=(Me&l|0?(Me+l&0-Ye)-l|0:0)+O|0,Ye=n[2891]|0,Me=l+Ye|0,l>>>0>j>>>0&l>>>0<2147483647)){if(Qe=n[2893]|0,Qe|0&&Me>>>0<=Ye>>>0|Me>>>0>Qe>>>0){l=0;break}if(s=Tp(l|0)|0,(s|0)==(c|0)){B=l,m=c,_e=135;break e}else f=s,_e=126}else l=0;while(!1);do if((_e|0)==126){if(c=0-l|0,!(k>>>0>l>>>0&(l>>>0<2147483647&(f|0)!=-1)))if((f|0)==-1){l=0;break}else{B=l,m=f,_e=135;break e}if(s=n[2903]|0,s=F-l+s&0-s,s>>>0>=2147483647){B=l,m=f,_e=135;break e}if((Tp(s|0)|0)==-1){Tp(c|0)|0,l=0;break}else{B=s+l|0,m=f,_e=135;break e}}while(!1);n[2894]=n[2894]|4,_e=133}while(!1);if((_e|0)==133&&O>>>0<2147483647&&(ct=Tp(O|0)|0,Qe=Tp(0)|0,rt=Qe-ct|0,Xe=rt>>>0>(j+40|0)>>>0,!((ct|0)==-1|Xe^1|ct>>>0>>0&((ct|0)!=-1&(Qe|0)!=-1)^1))&&(B=Xe?rt:l,m=ct,_e=135),(_e|0)==135){l=(n[2891]|0)+B|0,n[2891]=l,l>>>0>(n[2892]|0)>>>0&&(n[2892]=l),F=n[2789]|0;do if(F){for(l=11580;;){if(s=n[l>>2]|0,c=l+4|0,f=n[c>>2]|0,(m|0)==(s+f|0)){_e=145;break}if(d=n[l+8>>2]|0,d)l=d;else break}if((_e|0)==145&&!(n[l+12>>2]&8|0)&&F>>>0>>0&F>>>0>=s>>>0){n[c>>2]=f+B,Ge=F+8|0,Ge=Ge&7|0?0-Ge&7:0,_e=F+Ge|0,Ge=(n[2786]|0)+(B-Ge)|0,n[2789]=_e,n[2786]=Ge,n[_e+4>>2]=Ge|1,n[_e+Ge+4>>2]=40,n[2790]=n[2905];break}for(m>>>0<(n[2787]|0)>>>0&&(n[2787]=m),c=m+B|0,l=11580;;){if((n[l>>2]|0)==(c|0)){_e=153;break}if(s=n[l+8>>2]|0,s)l=s;else break}if((_e|0)==153&&!(n[l+12>>2]&8|0)){n[l>>2]=m,M=l+4|0,n[M>>2]=(n[M>>2]|0)+B,M=m+8|0,M=m+(M&7|0?0-M&7:0)|0,l=c+8|0,l=c+(l&7|0?0-l&7:0)|0,O=M+j|0,k=l-M-j|0,n[M+4>>2]=j|3;do if((l|0)!=(F|0)){if((l|0)==(n[2788]|0)){Ge=(n[2785]|0)+k|0,n[2785]=Ge,n[2788]=O,n[O+4>>2]=Ge|1,n[O+Ge>>2]=Ge;break}if(s=n[l+4>>2]|0,(s&3|0)==1){B=s&-8,f=s>>>3;e:do if(s>>>0<256)if(s=n[l+8>>2]|0,c=n[l+12>>2]|0,(c|0)==(s|0)){n[2783]=n[2783]&~(1<>2]=c,n[c+8>>2]=s;break}else{m=n[l+24>>2]|0,s=n[l+12>>2]|0;do if((s|0)==(l|0)){if(f=l+16|0,c=f+4|0,s=n[c>>2]|0,!s)if(s=n[f>>2]|0,s)c=f;else{s=0;break}for(;;){if(f=s+20|0,d=n[f>>2]|0,d|0){s=d,c=f;continue}if(f=s+16|0,d=n[f>>2]|0,d)s=d,c=f;else break}n[c>>2]=0}else Ge=n[l+8>>2]|0,n[Ge+12>>2]=s,n[s+8>>2]=Ge;while(!1);if(!m)break;c=n[l+28>>2]|0,f=11436+(c<<2)|0;do if((l|0)!=(n[f>>2]|0)){if(n[m+16+(((n[m+16>>2]|0)!=(l|0)&1)<<2)>>2]=s,!s)break e}else{if(n[f>>2]=s,s|0)break;n[2784]=n[2784]&~(1<>2]=m,c=l+16|0,f=n[c>>2]|0,f|0&&(n[s+16>>2]=f,n[f+24>>2]=s),c=n[c+4>>2]|0,!c)break;n[s+20>>2]=c,n[c+24>>2]=s}while(!1);l=l+B|0,d=B+k|0}else d=k;if(l=l+4|0,n[l>>2]=n[l>>2]&-2,n[O+4>>2]=d|1,n[O+d>>2]=d,l=d>>>3,d>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=O,n[l+12>>2]=O,n[O+8>>2]=l,n[O+12>>2]=c;break}l=d>>>8;do if(!l)l=0;else{if(d>>>0>16777215){l=31;break}_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<>>16&2,l=14-(ct|_e|l)+(Ge<>>15)|0,l=d>>>(l+7|0)&1|l<<1}while(!1);if(f=11436+(l<<2)|0,n[O+28>>2]=l,s=O+16|0,n[s+4>>2]=0,n[s>>2]=0,s=n[2784]|0,c=1<>2]=O,n[O+24>>2]=f,n[O+12>>2]=O,n[O+8>>2]=O;break}for(s=d<<((l|0)==31?0:25-(l>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){_e=194;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=193;break}}if((_e|0)==193){n[f>>2]=O,n[O+24>>2]=c,n[O+12>>2]=O,n[O+8>>2]=O;break}else if((_e|0)==194){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=O,n[_e>>2]=O,n[O+8>>2]=Ge,n[O+12>>2]=c,n[O+24>>2]=0;break}}else Ge=(n[2786]|0)+k|0,n[2786]=Ge,n[2789]=O,n[O+4>>2]=Ge|1;while(!1);return Ge=M+8|0,C=Lt,Ge|0}for(l=11580;s=n[l>>2]|0,!(s>>>0<=F>>>0&&(Ge=s+(n[l+4>>2]|0)|0,Ge>>>0>F>>>0));)l=n[l+8>>2]|0;d=Ge+-47|0,s=d+8|0,s=d+(s&7|0?0-s&7:0)|0,d=F+16|0,s=s>>>0>>0?F:s,l=s+8|0,c=m+8|0,c=c&7|0?0-c&7:0,_e=m+c|0,c=B+-40-c|0,n[2789]=_e,n[2786]=c,n[_e+4>>2]=c|1,n[_e+c+4>>2]=40,n[2790]=n[2905],c=s+4|0,n[c>>2]=27,n[l>>2]=n[2895],n[l+4>>2]=n[2896],n[l+8>>2]=n[2897],n[l+12>>2]=n[2898],n[2895]=m,n[2896]=B,n[2898]=0,n[2897]=l,l=s+24|0;do _e=l,l=l+4|0,n[l>>2]=7;while((_e+8|0)>>>0>>0);if((s|0)!=(F|0)){if(m=s-F|0,n[c>>2]=n[c>>2]&-2,n[F+4>>2]=m|1,n[s>>2]=m,l=m>>>3,m>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=F,n[l+12>>2]=F,n[F+8>>2]=l,n[F+12>>2]=c;break}if(l=m>>>8,l?m>>>0>16777215?c=31:(_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<>>16&2,c=14-(ct|_e|c)+(Ge<>>15)|0,c=m>>>(c+7|0)&1|c<<1):c=0,f=11436+(c<<2)|0,n[F+28>>2]=c,n[F+20>>2]=0,n[d>>2]=0,l=n[2784]|0,s=1<>2]=F,n[F+24>>2]=f,n[F+12>>2]=F,n[F+8>>2]=F;break}for(s=m<<((c|0)==31?0:25-(c>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(m|0)){_e=216;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=215;break}}if((_e|0)==215){n[f>>2]=F,n[F+24>>2]=c,n[F+12>>2]=F,n[F+8>>2]=F;break}else if((_e|0)==216){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=F,n[_e>>2]=F,n[F+8>>2]=Ge,n[F+12>>2]=c,n[F+24>>2]=0;break}}}else{Ge=n[2787]|0,(Ge|0)==0|m>>>0>>0&&(n[2787]=m),n[2895]=m,n[2896]=B,n[2898]=0,n[2792]=n[2901],n[2791]=-1,l=0;do Ge=11172+(l<<1<<2)|0,n[Ge+12>>2]=Ge,n[Ge+8>>2]=Ge,l=l+1|0;while((l|0)!=32);Ge=m+8|0,Ge=Ge&7|0?0-Ge&7:0,_e=m+Ge|0,Ge=B+-40-Ge|0,n[2789]=_e,n[2786]=Ge,n[_e+4>>2]=Ge|1,n[_e+Ge+4>>2]=40,n[2790]=n[2905]}while(!1);if(l=n[2786]|0,l>>>0>j>>>0)return ct=l-j|0,n[2786]=ct,Ge=n[2789]|0,_e=Ge+j|0,n[2789]=_e,n[_e+4>>2]=ct|1,n[Ge+4>>2]=j|3,Ge=Ge+8|0,C=Lt,Ge|0}return n[(rm()|0)>>2]=12,Ge=0,C=Lt,Ge|0}function HD(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0;if(s){c=s+-8|0,d=n[2787]|0,s=n[s+-4>>2]|0,l=s&-8,F=c+l|0;do if(s&1)k=c,B=c;else{if(f=n[c>>2]|0,!(s&3)||(B=c+(0-f)|0,m=f+l|0,B>>>0>>0))return;if((B|0)==(n[2788]|0)){if(s=F+4|0,l=n[s>>2]|0,(l&3|0)!=3){k=B,l=m;break}n[2785]=m,n[s>>2]=l&-2,n[B+4>>2]=m|1,n[B+m>>2]=m;return}if(c=f>>>3,f>>>0<256)if(s=n[B+8>>2]|0,l=n[B+12>>2]|0,(l|0)==(s|0)){n[2783]=n[2783]&~(1<>2]=l,n[l+8>>2]=s,k=B,l=m;break}d=n[B+24>>2]|0,s=n[B+12>>2]|0;do if((s|0)==(B|0)){if(c=B+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{s=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0}else k=n[B+8>>2]|0,n[k+12>>2]=s,n[s+8>>2]=k;while(!1);if(d){if(l=n[B+28>>2]|0,c=11436+(l<<2)|0,(B|0)==(n[c>>2]|0)){if(n[c>>2]=s,!s){n[2784]=n[2784]&~(1<>2]|0)!=(B|0)&1)<<2)>>2]=s,!s){k=B,l=m;break}n[s+24>>2]=d,l=B+16|0,c=n[l>>2]|0,c|0&&(n[s+16>>2]=c,n[c+24>>2]=s),l=n[l+4>>2]|0,l?(n[s+20>>2]=l,n[l+24>>2]=s,k=B,l=m):(k=B,l=m)}else k=B,l=m}while(!1);if(!(B>>>0>=F>>>0)&&(s=F+4|0,f=n[s>>2]|0,!!(f&1))){if(f&2)n[s>>2]=f&-2,n[k+4>>2]=l|1,n[B+l>>2]=l,d=l;else{if(s=n[2788]|0,(F|0)==(n[2789]|0)){if(F=(n[2786]|0)+l|0,n[2786]=F,n[2789]=k,n[k+4>>2]=F|1,(k|0)!=(s|0))return;n[2788]=0,n[2785]=0;return}if((F|0)==(s|0)){F=(n[2785]|0)+l|0,n[2785]=F,n[2788]=B,n[k+4>>2]=F|1,n[B+F>>2]=F;return}d=(f&-8)+l|0,c=f>>>3;do if(f>>>0<256)if(l=n[F+8>>2]|0,s=n[F+12>>2]|0,(s|0)==(l|0)){n[2783]=n[2783]&~(1<>2]=s,n[s+8>>2]=l;break}else{m=n[F+24>>2]|0,s=n[F+12>>2]|0;do if((s|0)==(F|0)){if(c=F+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{c=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0,c=s}else c=n[F+8>>2]|0,n[c+12>>2]=s,n[s+8>>2]=c,c=s;while(!1);if(m|0){if(s=n[F+28>>2]|0,l=11436+(s<<2)|0,(F|0)==(n[l>>2]|0)){if(n[l>>2]=c,!c){n[2784]=n[2784]&~(1<>2]|0)!=(F|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=m,s=F+16|0,l=n[s>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),s=n[s+4>>2]|0,s|0&&(n[c+20>>2]=s,n[s+24>>2]=c)}}while(!1);if(n[k+4>>2]=d|1,n[B+d>>2]=d,(k|0)==(n[2788]|0)){n[2785]=d;return}}if(s=d>>>3,d>>>0<256){c=11172+(s<<1<<2)|0,l=n[2783]|0,s=1<>2]|0):(n[2783]=l|s,s=c,l=c+8|0),n[l>>2]=k,n[s+12>>2]=k,n[k+8>>2]=s,n[k+12>>2]=c;return}s=d>>>8,s?d>>>0>16777215?s=31:(B=(s+1048320|0)>>>16&8,F=s<>>16&4,F=F<>>16&2,s=14-(m|B|s)+(F<>>15)|0,s=d>>>(s+7|0)&1|s<<1):s=0,f=11436+(s<<2)|0,n[k+28>>2]=s,n[k+20>>2]=0,n[k+16>>2]=0,l=n[2784]|0,c=1<>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){s=73;break}if(f=c+16+(l>>>31<<2)|0,s=n[f>>2]|0,s)l=l<<1,c=s;else{s=72;break}}if((s|0)==72){n[f>>2]=k,n[k+24>>2]=c,n[k+12>>2]=k,n[k+8>>2]=k;break}else if((s|0)==73){B=c+8|0,F=n[B>>2]|0,n[F+12>>2]=k,n[B>>2]=k,n[k+8>>2]=F,n[k+12>>2]=c,n[k+24>>2]=0;break}}else n[2784]=l|c,n[f>>2]=k,n[k+24>>2]=f,n[k+12>>2]=k,n[k+8>>2]=k;while(!1);if(F=(n[2791]|0)+-1|0,n[2791]=F,!F)s=11588;else return;for(;s=n[s>>2]|0,s;)s=s+8|0;n[2791]=-1}}}function dUe(){return 11628}function mUe(s){s=s|0;var l=0,c=0;return l=C,C=C+16|0,c=l,n[c>>2]=CUe(n[s+60>>2]|0)|0,s=qD(Ec(6,c|0)|0)|0,C=l,s|0}function L7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0;j=C,C=C+48|0,O=j+16|0,m=j,d=j+32|0,k=s+28|0,f=n[k>>2]|0,n[d>>2]=f,F=s+20|0,f=(n[F>>2]|0)-f|0,n[d+4>>2]=f,n[d+8>>2]=l,n[d+12>>2]=c,f=f+c|0,B=s+60|0,n[m>>2]=n[B>>2],n[m+4>>2]=d,n[m+8>>2]=2,m=qD(aa(146,m|0)|0)|0;e:do if((f|0)!=(m|0)){for(l=2;!((m|0)<0);)if(f=f-m|0,Ye=n[d+4>>2]|0,oe=m>>>0>Ye>>>0,d=oe?d+8|0:d,l=(oe<<31>>31)+l|0,Ye=m-(oe?Ye:0)|0,n[d>>2]=(n[d>>2]|0)+Ye,oe=d+4|0,n[oe>>2]=(n[oe>>2]|0)-Ye,n[O>>2]=n[B>>2],n[O+4>>2]=d,n[O+8>>2]=l,m=qD(aa(146,O|0)|0)|0,(f|0)==(m|0)){M=3;break e}n[s+16>>2]=0,n[k>>2]=0,n[F>>2]=0,n[s>>2]=n[s>>2]|32,(l|0)==2?c=0:c=c-(n[d+4>>2]|0)|0}else M=3;while(!1);return(M|0)==3&&(Ye=n[s+44>>2]|0,n[s+16>>2]=Ye+(n[s+48>>2]|0),n[k>>2]=Ye,n[F>>2]=Ye),C=j,c|0}function yUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return d=C,C=C+32|0,m=d,f=d+20|0,n[m>>2]=n[s+60>>2],n[m+4>>2]=0,n[m+8>>2]=l,n[m+12>>2]=f,n[m+16>>2]=c,(qD(oa(140,m|0)|0)|0)<0?(n[f>>2]=-1,s=-1):s=n[f>>2]|0,C=d,s|0}function qD(s){return s=s|0,s>>>0>4294963200&&(n[(rm()|0)>>2]=0-s,s=-1),s|0}function rm(){return(EUe()|0)+64|0}function EUe(){return oT()|0}function oT(){return 2084}function CUe(s){return s=s|0,s|0}function wUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return d=C,C=C+32|0,f=d,n[s+36>>2]=1,!(n[s>>2]&64|0)&&(n[f>>2]=n[s+60>>2],n[f+4>>2]=21523,n[f+8>>2]=d+16,Ns(54,f|0)|0)&&(o[s+75>>0]=-1),f=L7(s,l,c)|0,C=d,f|0}function M7(s,l){s=s|0,l=l|0;var c=0,f=0;if(c=o[s>>0]|0,f=o[l>>0]|0,!(c<<24>>24)||c<<24>>24!=f<<24>>24)s=f;else{do s=s+1|0,l=l+1|0,c=o[s>>0]|0,f=o[l>>0]|0;while(!(!(c<<24>>24)||c<<24>>24!=f<<24>>24));s=f}return(c&255)-(s&255)|0}function IUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;e:do if(!c)s=0;else{for(;f=o[s>>0]|0,d=o[l>>0]|0,f<<24>>24==d<<24>>24;)if(c=c+-1|0,c)s=s+1|0,l=l+1|0;else{s=0;break e}s=(f&255)-(d&255)|0}while(!1);return s|0}function O7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0;Qe=C,C=C+224|0,M=Qe+120|0,j=Qe+80|0,Ye=Qe,Me=Qe+136|0,f=j,d=f+40|0;do n[f>>2]=0,f=f+4|0;while((f|0)<(d|0));return n[M>>2]=n[c>>2],(aT(0,l,M,Ye,j)|0)<0?c=-1:((n[s+76>>2]|0)>-1?oe=BUe(s)|0:oe=0,c=n[s>>2]|0,O=c&32,(o[s+74>>0]|0)<1&&(n[s>>2]=c&-33),f=s+48|0,n[f>>2]|0?c=aT(s,l,M,Ye,j)|0:(d=s+44|0,m=n[d>>2]|0,n[d>>2]=Me,B=s+28|0,n[B>>2]=Me,k=s+20|0,n[k>>2]=Me,n[f>>2]=80,F=s+16|0,n[F>>2]=Me+80,c=aT(s,l,M,Ye,j)|0,m&&(WD[n[s+36>>2]&7](s,0,0)|0,c=n[k>>2]|0?c:-1,n[d>>2]=m,n[f>>2]=0,n[F>>2]=0,n[B>>2]=0,n[k>>2]=0)),f=n[s>>2]|0,n[s>>2]=f|O,oe|0&&vUe(s),c=f&32|0?-1:c),C=Qe,c|0}function aT(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Lt=0,_r=0,ur=0,Zt=0,kr=0,Mr=0,lr=0;lr=C,C=C+64|0,ur=lr+16|0,Zt=lr,Lt=lr+24|0,kr=lr+8|0,Mr=lr+20|0,n[ur>>2]=l,ct=(s|0)!=0,_e=Lt+40|0,Ge=_e,Lt=Lt+39|0,_r=kr+4|0,B=0,m=0,M=0;e:for(;;){do if((m|0)>-1)if((B|0)>(2147483647-m|0)){n[(rm()|0)>>2]=75,m=-1;break}else{m=B+m|0;break}while(!1);if(B=o[l>>0]|0,B<<24>>24)k=l;else{Xe=87;break}t:for(;;){switch(B<<24>>24){case 37:{B=k,Xe=9;break t}case 0:{B=k;break t}default:}rt=k+1|0,n[ur>>2]=rt,B=o[rt>>0]|0,k=rt}t:do if((Xe|0)==9)for(;;){if(Xe=0,(o[k+1>>0]|0)!=37)break t;if(B=B+1|0,k=k+2|0,n[ur>>2]=k,(o[k>>0]|0)==37)Xe=9;else break}while(!1);if(B=B-l|0,ct&&os(s,l,B),B|0){l=k;continue}F=k+1|0,B=(o[F>>0]|0)+-48|0,B>>>0<10?(rt=(o[k+2>>0]|0)==36,Qe=rt?B:-1,M=rt?1:M,F=rt?k+3|0:F):Qe=-1,n[ur>>2]=F,B=o[F>>0]|0,k=(B<<24>>24)+-32|0;t:do if(k>>>0<32)for(O=0,j=B;;){if(B=1<>2]=F,B=o[F>>0]|0,k=(B<<24>>24)+-32|0,k>>>0>=32)break;j=B}else O=0;while(!1);if(B<<24>>24==42){if(k=F+1|0,B=(o[k>>0]|0)+-48|0,B>>>0<10&&(o[F+2>>0]|0)==36)n[d+(B<<2)>>2]=10,B=n[f+((o[k>>0]|0)+-48<<3)>>2]|0,M=1,F=F+3|0;else{if(M|0){m=-1;break}ct?(M=(n[c>>2]|0)+3&-4,B=n[M>>2]|0,n[c>>2]=M+4,M=0,F=k):(B=0,M=0,F=k)}n[ur>>2]=F,rt=(B|0)<0,B=rt?0-B|0:B,O=rt?O|8192:O}else{if(B=U7(ur)|0,(B|0)<0){m=-1;break}F=n[ur>>2]|0}do if((o[F>>0]|0)==46){if((o[F+1>>0]|0)!=42){n[ur>>2]=F+1,k=U7(ur)|0,F=n[ur>>2]|0;break}if(j=F+2|0,k=(o[j>>0]|0)+-48|0,k>>>0<10&&(o[F+3>>0]|0)==36){n[d+(k<<2)>>2]=10,k=n[f+((o[j>>0]|0)+-48<<3)>>2]|0,F=F+4|0,n[ur>>2]=F;break}if(M|0){m=-1;break e}ct?(rt=(n[c>>2]|0)+3&-4,k=n[rt>>2]|0,n[c>>2]=rt+4):k=0,n[ur>>2]=j,F=j}else k=-1;while(!1);for(Me=0;;){if(((o[F>>0]|0)+-65|0)>>>0>57){m=-1;break e}if(rt=F+1|0,n[ur>>2]=rt,j=o[(o[F>>0]|0)+-65+(5178+(Me*58|0))>>0]|0,oe=j&255,(oe+-1|0)>>>0<8)Me=oe,F=rt;else break}if(!(j<<24>>24)){m=-1;break}Ye=(Qe|0)>-1;do if(j<<24>>24==19)if(Ye){m=-1;break e}else Xe=49;else{if(Ye){n[d+(Qe<<2)>>2]=oe,Ye=f+(Qe<<3)|0,Qe=n[Ye+4>>2]|0,Xe=Zt,n[Xe>>2]=n[Ye>>2],n[Xe+4>>2]=Qe,Xe=49;break}if(!ct){m=0;break e}_7(Zt,oe,c)}while(!1);if((Xe|0)==49&&(Xe=0,!ct)){B=0,l=rt;continue}F=o[F>>0]|0,F=(Me|0)!=0&(F&15|0)==3?F&-33:F,Ye=O&-65537,Qe=O&8192|0?Ye:O;t:do switch(F|0){case 110:switch((Me&255)<<24>>24){case 0:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 1:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 2:{B=n[Zt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=rt;continue e}case 3:{a[n[Zt>>2]>>1]=m,B=0,l=rt;continue e}case 4:{o[n[Zt>>2]>>0]=m,B=0,l=rt;continue e}case 6:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 7:{B=n[Zt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=rt;continue e}default:{B=0,l=rt;continue e}}case 112:{F=120,k=k>>>0>8?k:8,l=Qe|8,Xe=61;break}case 88:case 120:{l=Qe,Xe=61;break}case 111:{F=Zt,l=n[F>>2]|0,F=n[F+4>>2]|0,oe=PUe(l,F,_e)|0,Ye=Ge-oe|0,O=0,j=5642,k=(Qe&8|0)==0|(k|0)>(Ye|0)?k:Ye+1|0,Ye=Qe,Xe=67;break}case 105:case 100:if(F=Zt,l=n[F>>2]|0,F=n[F+4>>2]|0,(F|0)<0){l=jD(0,0,l|0,F|0)|0,F=we,O=Zt,n[O>>2]=l,n[O+4>>2]=F,O=1,j=5642,Xe=66;break t}else{O=(Qe&2049|0)!=0&1,j=Qe&2048|0?5643:Qe&1|0?5644:5642,Xe=66;break t}case 117:{F=Zt,O=0,j=5642,l=n[F>>2]|0,F=n[F+4>>2]|0,Xe=66;break}case 99:{o[Lt>>0]=n[Zt>>2],l=Lt,O=0,j=5642,oe=_e,F=1,k=Ye;break}case 109:{F=SUe(n[(rm()|0)>>2]|0)|0,Xe=71;break}case 115:{F=n[Zt>>2]|0,F=F|0?F:5652,Xe=71;break}case 67:{n[kr>>2]=n[Zt>>2],n[_r>>2]=0,n[Zt>>2]=kr,oe=-1,F=kr,Xe=75;break}case 83:{l=n[Zt>>2]|0,k?(oe=k,F=l,Xe=75):(Es(s,32,B,0,Qe),l=0,Xe=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{B=xUe(s,+E[Zt>>3],B,k,Qe,F)|0,l=rt;continue e}default:O=0,j=5642,oe=_e,F=k,k=Qe}while(!1);t:do if((Xe|0)==61)Qe=Zt,Me=n[Qe>>2]|0,Qe=n[Qe+4>>2]|0,oe=DUe(Me,Qe,_e,F&32)|0,j=(l&8|0)==0|(Me|0)==0&(Qe|0)==0,O=j?0:2,j=j?5642:5642+(F>>4)|0,Ye=l,l=Me,F=Qe,Xe=67;else if((Xe|0)==66)oe=nm(l,F,_e)|0,Ye=Qe,Xe=67;else if((Xe|0)==71)Xe=0,Qe=bUe(F,0,k)|0,Me=(Qe|0)==0,l=F,O=0,j=5642,oe=Me?F+k|0:Qe,F=Me?k:Qe-F|0,k=Ye;else if((Xe|0)==75){for(Xe=0,j=F,l=0,k=0;O=n[j>>2]|0,!(!O||(k=H7(Mr,O)|0,(k|0)<0|k>>>0>(oe-l|0)>>>0));)if(l=k+l|0,oe>>>0>l>>>0)j=j+4|0;else break;if((k|0)<0){m=-1;break e}if(Es(s,32,B,l,Qe),!l)l=0,Xe=84;else for(O=0;;){if(k=n[F>>2]|0,!k){Xe=84;break t}if(k=H7(Mr,k)|0,O=k+O|0,(O|0)>(l|0)){Xe=84;break t}if(os(s,Mr,k),O>>>0>=l>>>0){Xe=84;break}else F=F+4|0}}while(!1);if((Xe|0)==67)Xe=0,F=(l|0)!=0|(F|0)!=0,Qe=(k|0)!=0|F,F=((F^1)&1)+(Ge-oe)|0,l=Qe?oe:_e,oe=_e,F=Qe?(k|0)>(F|0)?k:F:k,k=(k|0)>-1?Ye&-65537:Ye;else if((Xe|0)==84){Xe=0,Es(s,32,B,l,Qe^8192),B=(B|0)>(l|0)?B:l,l=rt;continue}Me=oe-l|0,Ye=(F|0)<(Me|0)?Me:F,Qe=Ye+O|0,B=(B|0)<(Qe|0)?Qe:B,Es(s,32,B,Qe,k),os(s,j,O),Es(s,48,B,Qe,k^65536),Es(s,48,Ye,Me,0),os(s,l,Me),Es(s,32,B,Qe,k^8192),l=rt}e:do if((Xe|0)==87&&!s)if(!M)m=0;else{for(m=1;l=n[d+(m<<2)>>2]|0,!!l;)if(_7(f+(m<<3)|0,l,c),m=m+1|0,(m|0)>=10){m=1;break e}for(;;){if(n[d+(m<<2)>>2]|0){m=-1;break e}if(m=m+1|0,(m|0)>=10){m=1;break}}}while(!1);return C=lr,m|0}function BUe(s){return s=s|0,0}function vUe(s){s=s|0}function os(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]&32||OUe(l,c,s)|0}function U7(s){s=s|0;var l=0,c=0,f=0;if(c=n[s>>2]|0,f=(o[c>>0]|0)+-48|0,f>>>0<10){l=0;do l=f+(l*10|0)|0,c=c+1|0,n[s>>2]=c,f=(o[c>>0]|0)+-48|0;while(f>>>0<10)}else l=0;return l|0}function _7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;e:do if(l>>>0<=20)do switch(l|0){case 9:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,n[s>>2]=l;break e}case 10:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=((l|0)<0)<<31>>31;break e}case 11:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=0;break e}case 12:{f=(n[c>>2]|0)+7&-8,l=f,d=n[l>>2]|0,l=n[l+4>>2]|0,n[c>>2]=f+8,f=s,n[f>>2]=d,n[f+4>>2]=l;break e}case 13:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&65535)<<16>>16,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 14:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&65535,n[d+4>>2]=0;break e}case 15:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&255)<<24>>24,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 16:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&255,n[d+4>>2]=0;break e}case 17:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}case 18:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}default:break e}while(!1);while(!1)}function DUe(s,l,c,f){if(s=s|0,l=l|0,c=c|0,f=f|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=u[5694+(s&15)>>0]|0|f,s=GD(s|0,l|0,4)|0,l=we;while(!((s|0)==0&(l|0)==0));return c|0}function PUe(s,l,c){if(s=s|0,l=l|0,c=c|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=s&7|48,s=GD(s|0,l|0,3)|0,l=we;while(!((s|0)==0&(l|0)==0));return c|0}function nm(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if(l>>>0>0|(l|0)==0&s>>>0>4294967295){for(;f=AT(s|0,l|0,10,0)|0,c=c+-1|0,o[c>>0]=f&255|48,f=s,s=uT(s|0,l|0,10,0)|0,l>>>0>9|(l|0)==9&f>>>0>4294967295;)l=we;l=s}else l=s;if(l)for(;c=c+-1|0,o[c>>0]=(l>>>0)%10|0|48,!(l>>>0<10);)l=(l>>>0)/10|0;return c|0}function SUe(s){return s=s|0,TUe(s,n[(RUe()|0)+188>>2]|0)|0}function bUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;m=l&255,f=(c|0)!=0;e:do if(f&(s&3|0)!=0)for(d=l&255;;){if((o[s>>0]|0)==d<<24>>24){B=6;break e}if(s=s+1|0,c=c+-1|0,f=(c|0)!=0,!(f&(s&3|0)!=0)){B=5;break}}else B=5;while(!1);(B|0)==5&&(f?B=6:c=0);e:do if((B|0)==6&&(d=l&255,(o[s>>0]|0)!=d<<24>>24)){f=He(m,16843009)|0;t:do if(c>>>0>3){for(;m=n[s>>2]^f,!((m&-2139062144^-2139062144)&m+-16843009|0);)if(s=s+4|0,c=c+-4|0,c>>>0<=3){B=11;break t}}else B=11;while(!1);if((B|0)==11&&!c){c=0;break}for(;;){if((o[s>>0]|0)==d<<24>>24)break e;if(s=s+1|0,c=c+-1|0,!c){c=0;break}}}while(!1);return(c|0?s:0)|0}function Es(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0;if(B=C,C=C+256|0,m=B,(c|0)>(f|0)&(d&73728|0)==0){if(d=c-f|0,sm(m|0,l|0,(d>>>0<256?d:256)|0)|0,d>>>0>255){l=c-f|0;do os(s,m,256),d=d+-256|0;while(d>>>0>255);d=l&255}os(s,m,d)}C=B}function H7(s,l){return s=s|0,l=l|0,s?s=QUe(s,l,0)|0:s=0,s|0}function xUe(s,l,c,f,d,m){s=s|0,l=+l,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Lt=0,_r=0,ur=0,Zt=0,kr=0,Mr=0,lr=0,Nn=0;Nn=C,C=C+560|0,F=Nn+8|0,rt=Nn,lr=Nn+524|0,Mr=lr,O=Nn+512|0,n[rt>>2]=0,kr=O+12|0,q7(l)|0,(we|0)<0?(l=-l,ur=1,_r=5659):(ur=(d&2049|0)!=0&1,_r=d&2048|0?5662:d&1|0?5665:5660),q7(l)|0,Zt=we&2146435072;do if(Zt>>>0<2146435072|(Zt|0)==2146435072&!1){if(Ye=+kUe(l,rt)*2,B=Ye!=0,B&&(n[rt>>2]=(n[rt>>2]|0)+-1),ct=m|32,(ct|0)==97){Me=m&32,oe=Me|0?_r+9|0:_r,j=ur|2,B=12-f|0;do if(f>>>0>11|(B|0)==0)l=Ye;else{l=8;do B=B+-1|0,l=l*16;while(B|0);if((o[oe>>0]|0)==45){l=-(l+(-Ye-l));break}else{l=Ye+l-l;break}}while(!1);k=n[rt>>2]|0,B=(k|0)<0?0-k|0:k,B=nm(B,((B|0)<0)<<31>>31,kr)|0,(B|0)==(kr|0)&&(B=O+11|0,o[B>>0]=48),o[B+-1>>0]=(k>>31&2)+43,M=B+-2|0,o[M>>0]=m+15,O=(f|0)<1,F=(d&8|0)==0,B=lr;do Zt=~~l,k=B+1|0,o[B>>0]=u[5694+Zt>>0]|Me,l=(l-+(Zt|0))*16,(k-Mr|0)==1&&!(F&(O&l==0))?(o[k>>0]=46,B=B+2|0):B=k;while(l!=0);Zt=B-Mr|0,Mr=kr-M|0,kr=(f|0)!=0&(Zt+-2|0)<(f|0)?f+2|0:Zt,B=Mr+j+kr|0,Es(s,32,c,B,d),os(s,oe,j),Es(s,48,c,B,d^65536),os(s,lr,Zt),Es(s,48,kr-Zt|0,0,0),os(s,M,Mr),Es(s,32,c,B,d^8192);break}k=(f|0)<0?6:f,B?(B=(n[rt>>2]|0)+-28|0,n[rt>>2]=B,l=Ye*268435456):(l=Ye,B=n[rt>>2]|0),Zt=(B|0)<0?F:F+288|0,F=Zt;do Ge=~~l>>>0,n[F>>2]=Ge,F=F+4|0,l=(l-+(Ge>>>0))*1e9;while(l!=0);if((B|0)>0)for(O=Zt,j=F;;){if(M=(B|0)<29?B:29,B=j+-4|0,B>>>0>=O>>>0){F=0;do _e=V7(n[B>>2]|0,0,M|0)|0,_e=cT(_e|0,we|0,F|0,0)|0,Ge=we,Xe=AT(_e|0,Ge|0,1e9,0)|0,n[B>>2]=Xe,F=uT(_e|0,Ge|0,1e9,0)|0,B=B+-4|0;while(B>>>0>=O>>>0);F&&(O=O+-4|0,n[O>>2]=F)}for(F=j;!(F>>>0<=O>>>0);)if(B=F+-4|0,!(n[B>>2]|0))F=B;else break;if(B=(n[rt>>2]|0)-M|0,n[rt>>2]=B,(B|0)>0)j=F;else break}else O=Zt;if((B|0)<0){f=((k+25|0)/9|0)+1|0,Qe=(ct|0)==102;do{if(Me=0-B|0,Me=(Me|0)<9?Me:9,O>>>0>>0){M=(1<>>Me,oe=0,B=O;do Ge=n[B>>2]|0,n[B>>2]=(Ge>>>Me)+oe,oe=He(Ge&M,j)|0,B=B+4|0;while(B>>>0>>0);B=n[O>>2]|0?O:O+4|0,oe?(n[F>>2]=oe,O=B,B=F+4|0):(O=B,B=F)}else O=n[O>>2]|0?O:O+4|0,B=F;F=Qe?Zt:O,F=(B-F>>2|0)>(f|0)?F+(f<<2)|0:B,B=(n[rt>>2]|0)+Me|0,n[rt>>2]=B}while((B|0)<0);B=O,f=F}else B=O,f=F;if(Ge=Zt,B>>>0>>0){if(F=(Ge-B>>2)*9|0,M=n[B>>2]|0,M>>>0>=10){O=10;do O=O*10|0,F=F+1|0;while(M>>>0>=O>>>0)}}else F=0;if(Qe=(ct|0)==103,Xe=(k|0)!=0,O=k-((ct|0)!=102?F:0)+((Xe&Qe)<<31>>31)|0,(O|0)<(((f-Ge>>2)*9|0)+-9|0)){if(O=O+9216|0,Me=Zt+4+(((O|0)/9|0)+-1024<<2)|0,O=((O|0)%9|0)+1|0,(O|0)<9){M=10;do M=M*10|0,O=O+1|0;while((O|0)!=9)}else M=10;if(j=n[Me>>2]|0,oe=(j>>>0)%(M>>>0)|0,O=(Me+4|0)==(f|0),O&(oe|0)==0)O=Me;else if(Ye=((j>>>0)/(M>>>0)|0)&1|0?9007199254740994:9007199254740992,_e=(M|0)/2|0,l=oe>>>0<_e>>>0?.5:O&(oe|0)==(_e|0)?1:1.5,ur&&(_e=(o[_r>>0]|0)==45,l=_e?-l:l,Ye=_e?-Ye:Ye),O=j-oe|0,n[Me>>2]=O,Ye+l!=Ye){if(_e=O+M|0,n[Me>>2]=_e,_e>>>0>999999999)for(F=Me;O=F+-4|0,n[F>>2]=0,O>>>0>>0&&(B=B+-4|0,n[B>>2]=0),_e=(n[O>>2]|0)+1|0,n[O>>2]=_e,_e>>>0>999999999;)F=O;else O=Me;if(F=(Ge-B>>2)*9|0,j=n[B>>2]|0,j>>>0>=10){M=10;do M=M*10|0,F=F+1|0;while(j>>>0>=M>>>0)}}else O=Me;O=O+4|0,O=f>>>0>O>>>0?O:f,_e=B}else O=f,_e=B;for(ct=O;;){if(ct>>>0<=_e>>>0){rt=0;break}if(B=ct+-4|0,!(n[B>>2]|0))ct=B;else{rt=1;break}}f=0-F|0;do if(Qe)if(B=((Xe^1)&1)+k|0,(B|0)>(F|0)&(F|0)>-5?(M=m+-1|0,k=B+-1-F|0):(M=m+-2|0,k=B+-1|0),B=d&8,B)Me=B;else{if(rt&&(Lt=n[ct+-4>>2]|0,(Lt|0)!=0))if((Lt>>>0)%10|0)O=0;else{O=0,B=10;do B=B*10|0,O=O+1|0;while(!((Lt>>>0)%(B>>>0)|0|0))}else O=9;if(B=((ct-Ge>>2)*9|0)+-9|0,(M|32|0)==102){Me=B-O|0,Me=(Me|0)>0?Me:0,k=(k|0)<(Me|0)?k:Me,Me=0;break}else{Me=B+F-O|0,Me=(Me|0)>0?Me:0,k=(k|0)<(Me|0)?k:Me,Me=0;break}}else M=m,Me=d&8;while(!1);if(Qe=k|Me,j=(Qe|0)!=0&1,oe=(M|32|0)==102,oe)Xe=0,B=(F|0)>0?F:0;else{if(B=(F|0)<0?f:F,B=nm(B,((B|0)<0)<<31>>31,kr)|0,O=kr,(O-B|0)<2)do B=B+-1|0,o[B>>0]=48;while((O-B|0)<2);o[B+-1>>0]=(F>>31&2)+43,B=B+-2|0,o[B>>0]=M,Xe=B,B=O-B|0}if(B=ur+1+k+j+B|0,Es(s,32,c,B,d),os(s,_r,ur),Es(s,48,c,B,d^65536),oe){M=_e>>>0>Zt>>>0?Zt:_e,Me=lr+9|0,j=Me,oe=lr+8|0,O=M;do{if(F=nm(n[O>>2]|0,0,Me)|0,(O|0)==(M|0))(F|0)==(Me|0)&&(o[oe>>0]=48,F=oe);else if(F>>>0>lr>>>0){sm(lr|0,48,F-Mr|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}os(s,F,j-F|0),O=O+4|0}while(O>>>0<=Zt>>>0);if(Qe|0&&os(s,5710,1),O>>>0>>0&(k|0)>0)for(;;){if(F=nm(n[O>>2]|0,0,Me)|0,F>>>0>lr>>>0){sm(lr|0,48,F-Mr|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}if(os(s,F,(k|0)<9?k:9),O=O+4|0,F=k+-9|0,O>>>0>>0&(k|0)>9)k=F;else{k=F;break}}Es(s,48,k+9|0,9,0)}else{if(Qe=rt?ct:_e+4|0,(k|0)>-1){rt=lr+9|0,Me=(Me|0)==0,f=rt,j=0-Mr|0,oe=lr+8|0,M=_e;do{F=nm(n[M>>2]|0,0,rt)|0,(F|0)==(rt|0)&&(o[oe>>0]=48,F=oe);do if((M|0)==(_e|0)){if(O=F+1|0,os(s,F,1),Me&(k|0)<1){F=O;break}os(s,5710,1),F=O}else{if(F>>>0<=lr>>>0)break;sm(lr|0,48,F+j|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}while(!1);Mr=f-F|0,os(s,F,(k|0)>(Mr|0)?Mr:k),k=k-Mr|0,M=M+4|0}while(M>>>0>>0&(k|0)>-1)}Es(s,48,k+18|0,18,0),os(s,Xe,kr-Xe|0)}Es(s,32,c,B,d^8192)}else lr=(m&32|0)!=0,B=ur+3|0,Es(s,32,c,B,d&-65537),os(s,_r,ur),os(s,l!=l|!1?lr?5686:5690:lr?5678:5682,3),Es(s,32,c,B,d^8192);while(!1);return C=Nn,((B|0)<(c|0)?c:B)|0}function q7(s){s=+s;var l=0;return E[D>>3]=s,l=n[D>>2]|0,we=n[D+4>>2]|0,l|0}function kUe(s,l){return s=+s,l=l|0,+ +j7(s,l)}function j7(s,l){s=+s,l=l|0;var c=0,f=0,d=0;switch(E[D>>3]=s,c=n[D>>2]|0,f=n[D+4>>2]|0,d=GD(c|0,f|0,52)|0,d&2047){case 0:{s!=0?(s=+j7(s*18446744073709552e3,l),c=(n[l>>2]|0)+-64|0):c=0,n[l>>2]=c;break}case 2047:break;default:n[l>>2]=(d&2047)+-1022,n[D>>2]=c,n[D+4>>2]=f&-2146435073|1071644672,s=+E[D>>3]}return+s}function QUe(s,l,c){s=s|0,l=l|0,c=c|0;do if(s){if(l>>>0<128){o[s>>0]=l,s=1;break}if(!(n[n[(FUe()|0)+188>>2]>>2]|0))if((l&-128|0)==57216){o[s>>0]=l,s=1;break}else{n[(rm()|0)>>2]=84,s=-1;break}if(l>>>0<2048){o[s>>0]=l>>>6|192,o[s+1>>0]=l&63|128,s=2;break}if(l>>>0<55296|(l&-8192|0)==57344){o[s>>0]=l>>>12|224,o[s+1>>0]=l>>>6&63|128,o[s+2>>0]=l&63|128,s=3;break}if((l+-65536|0)>>>0<1048576){o[s>>0]=l>>>18|240,o[s+1>>0]=l>>>12&63|128,o[s+2>>0]=l>>>6&63|128,o[s+3>>0]=l&63|128,s=4;break}else{n[(rm()|0)>>2]=84,s=-1;break}}else s=1;while(!1);return s|0}function FUe(){return oT()|0}function RUe(){return oT()|0}function TUe(s,l){s=s|0,l=l|0;var c=0,f=0;for(f=0;;){if((u[5712+f>>0]|0)==(s|0)){s=2;break}if(c=f+1|0,(c|0)==87){c=5800,f=87,s=5;break}else f=c}if((s|0)==2&&(f?(c=5800,s=5):c=5800),(s|0)==5)for(;;){do s=c,c=c+1|0;while(o[s>>0]|0);if(f=f+-1|0,f)s=5;else break}return NUe(c,n[l+20>>2]|0)|0}function NUe(s,l){return s=s|0,l=l|0,LUe(s,l)|0}function LUe(s,l){return s=s|0,l=l|0,l?l=MUe(n[l>>2]|0,n[l+4>>2]|0,s)|0:l=0,(l|0?l:s)|0}function MUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0;oe=(n[s>>2]|0)+1794895138|0,m=M0(n[s+8>>2]|0,oe)|0,f=M0(n[s+12>>2]|0,oe)|0,d=M0(n[s+16>>2]|0,oe)|0;e:do if(m>>>0>>2>>>0&&(j=l-(m<<2)|0,f>>>0>>0&d>>>0>>0)&&!((d|f)&3|0)){for(j=f>>>2,M=d>>>2,O=0;;){if(k=m>>>1,F=O+k|0,B=F<<1,d=B+j|0,f=M0(n[s+(d<<2)>>2]|0,oe)|0,d=M0(n[s+(d+1<<2)>>2]|0,oe)|0,!(d>>>0>>0&f>>>0<(l-d|0)>>>0)){f=0;break e}if(o[s+(d+f)>>0]|0){f=0;break e}if(f=M7(c,s+d|0)|0,!f)break;if(f=(f|0)<0,(m|0)==1){f=0;break e}else O=f?O:F,m=f?k:m-k|0}f=B+M|0,d=M0(n[s+(f<<2)>>2]|0,oe)|0,f=M0(n[s+(f+1<<2)>>2]|0,oe)|0,f>>>0>>0&d>>>0<(l-f|0)>>>0?f=o[s+(f+d)>>0]|0?0:s+f|0:f=0}else f=0;while(!1);return f|0}function M0(s,l){s=s|0,l=l|0;var c=0;return c=X7(s|0)|0,(l|0?c:s)|0}function OUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=c+16|0,d=n[f>>2]|0,d?m=5:UUe(c)|0?f=0:(d=n[f>>2]|0,m=5);e:do if((m|0)==5){if(k=c+20|0,B=n[k>>2]|0,f=B,(d-B|0)>>>0>>0){f=WD[n[c+36>>2]&7](c,s,l)|0;break}t:do if((o[c+75>>0]|0)>-1){for(B=l;;){if(!B){m=0,d=s;break t}if(d=B+-1|0,(o[s+d>>0]|0)==10)break;B=d}if(f=WD[n[c+36>>2]&7](c,s,B)|0,f>>>0>>0)break e;m=B,d=s+B|0,l=l-B|0,f=n[k>>2]|0}else m=0,d=s;while(!1);xr(f|0,d|0,l|0)|0,n[k>>2]=(n[k>>2]|0)+l,f=m+l|0}while(!1);return f|0}function UUe(s){s=s|0;var l=0,c=0;return l=s+74|0,c=o[l>>0]|0,o[l>>0]=c+255|c,l=n[s>>2]|0,l&8?(n[s>>2]=l|32,s=-1):(n[s+8>>2]=0,n[s+4>>2]=0,c=n[s+44>>2]|0,n[s+28>>2]=c,n[s+20>>2]=c,n[s+16>>2]=c+(n[s+48>>2]|0),s=0),s|0}function Wn(s,l){s=y(s),l=y(l);var c=0,f=0;c=G7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=G7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?l:s;break}else{s=s>2]=s,n[D>>2]|0|0}function O0(s,l){s=y(s),l=y(l);var c=0,f=0;c=Y7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=Y7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?s:l;break}else{s=s>2]=s,n[D>>2]|0|0}function lT(s,l){s=y(s),l=y(l);var c=0,f=0,d=0,m=0,B=0,k=0,F=0,O=0;m=(h[D>>2]=s,n[D>>2]|0),k=(h[D>>2]=l,n[D>>2]|0),c=m>>>23&255,B=k>>>23&255,F=m&-2147483648,d=k<<1;e:do if(d|0&&!((c|0)==255|((_Ue(l)|0)&2147483647)>>>0>2139095040)){if(f=m<<1,f>>>0<=d>>>0)return l=y(s*y(0)),y((f|0)==(d|0)?l:s);if(c)f=m&8388607|8388608;else{if(c=m<<9,(c|0)>-1){f=c,c=0;do c=c+-1|0,f=f<<1;while((f|0)>-1)}else c=0;f=m<<1-c}if(B)k=k&8388607|8388608;else{if(m=k<<9,(m|0)>-1){d=0;do d=d+-1|0,m=m<<1;while((m|0)>-1)}else d=0;B=d,k=k<<1-d}d=f-k|0,m=(d|0)>-1;t:do if((c|0)>(B|0)){for(;;){if(m)if(d)f=d;else break;if(f=f<<1,c=c+-1|0,d=f-k|0,m=(d|0)>-1,(c|0)<=(B|0))break t}l=y(s*y(0));break e}while(!1);if(m)if(d)f=d;else{l=y(s*y(0));break}if(f>>>0<8388608)do f=f<<1,c=c+-1|0;while(f>>>0<8388608);(c|0)>0?c=f+-8388608|c<<23:c=f>>>(1-c|0),l=(n[D>>2]=c|F,y(h[D>>2]))}else O=3;while(!1);return(O|0)==3&&(l=y(s*l),l=y(l/l)),y(l)}function _Ue(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function HUe(s,l){return s=s|0,l=l|0,O7(n[582]|0,s,l)|0}function Zr(s){s=s|0,Tt()}function im(s){s=s|0}function qUe(s,l){return s=s|0,l=l|0,0}function jUe(s){return s=s|0,(W7(s+4|0)|0)==-1?(ef[n[(n[s>>2]|0)+8>>2]&127](s),s=1):s=0,s|0}function W7(s){s=s|0;var l=0;return l=n[s>>2]|0,n[s>>2]=l+-1,l+-1|0}function Rp(s){s=s|0,jUe(s)|0&&GUe(s)}function GUe(s){s=s|0;var l=0;l=s+8|0,n[l>>2]|0&&(W7(l)|0)!=-1||ef[n[(n[s>>2]|0)+16>>2]&127](s)}function Wt(s){s=s|0;var l=0;for(l=s|0?s:1;s=_D(l)|0,!(s|0);){if(s=WUe()|0,!s){s=0;break}aY[s&0]()}return s|0}function K7(s){return s=s|0,Wt(s)|0}function yt(s){s=s|0,HD(s)}function YUe(s){s=s|0,(o[s+11>>0]|0)<0&&yt(n[s>>2]|0)}function WUe(){var s=0;return s=n[2923]|0,n[2923]=s+0,s|0}function KUe(){}function jD(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,f=l-f-(c>>>0>s>>>0|0)>>>0,we=f,s-c>>>0|0|0}function cT(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,c=s+c>>>0,we=l+f+(c>>>0>>0|0)>>>0,c|0|0}function sm(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(m=s+c|0,l=l&255,(c|0)>=67){for(;s&3;)o[s>>0]=l,s=s+1|0;for(f=m&-4|0,d=f-64|0,B=l|l<<8|l<<16|l<<24;(s|0)<=(d|0);)n[s>>2]=B,n[s+4>>2]=B,n[s+8>>2]=B,n[s+12>>2]=B,n[s+16>>2]=B,n[s+20>>2]=B,n[s+24>>2]=B,n[s+28>>2]=B,n[s+32>>2]=B,n[s+36>>2]=B,n[s+40>>2]=B,n[s+44>>2]=B,n[s+48>>2]=B,n[s+52>>2]=B,n[s+56>>2]=B,n[s+60>>2]=B,s=s+64|0;for(;(s|0)<(f|0);)n[s>>2]=B,s=s+4|0}for(;(s|0)<(m|0);)o[s>>0]=l,s=s+1|0;return m-c|0}function V7(s,l,c){return s=s|0,l=l|0,c=c|0,(c|0)<32?(we=l<>>32-c,s<>>c,s>>>c|(l&(1<>>c-32|0)}function xr(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;if((c|0)>=8192)return FA(s|0,l|0,c|0)|0;if(m=s|0,d=s+c|0,(s&3)==(l&3)){for(;s&3;){if(!c)return m|0;o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0,c=c-1|0}for(c=d&-4|0,f=c-64|0;(s|0)<=(f|0);)n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2],n[s+16>>2]=n[l+16>>2],n[s+20>>2]=n[l+20>>2],n[s+24>>2]=n[l+24>>2],n[s+28>>2]=n[l+28>>2],n[s+32>>2]=n[l+32>>2],n[s+36>>2]=n[l+36>>2],n[s+40>>2]=n[l+40>>2],n[s+44>>2]=n[l+44>>2],n[s+48>>2]=n[l+48>>2],n[s+52>>2]=n[l+52>>2],n[s+56>>2]=n[l+56>>2],n[s+60>>2]=n[l+60>>2],s=s+64|0,l=l+64|0;for(;(s|0)<(c|0);)n[s>>2]=n[l>>2],s=s+4|0,l=l+4|0}else for(c=d-4|0;(s|0)<(c|0);)o[s>>0]=o[l>>0]|0,o[s+1>>0]=o[l+1>>0]|0,o[s+2>>0]=o[l+2>>0]|0,o[s+3>>0]=o[l+3>>0]|0,s=s+4|0,l=l+4|0;for(;(s|0)<(d|0);)o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0;return m|0}function z7(s){s=s|0;var l=0;return l=o[L+(s&255)>>0]|0,(l|0)<8?l|0:(l=o[L+(s>>8&255)>>0]|0,(l|0)<8?l+8|0:(l=o[L+(s>>16&255)>>0]|0,(l|0)<8?l+16|0:(o[L+(s>>>24)>>0]|0)+24|0))}function J7(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,O=0,M=0,j=0,oe=0,Ye=0,Me=0;if(M=s,F=l,O=F,B=c,oe=f,k=oe,!O)return m=(d|0)!=0,k?m?(n[d>>2]=s|0,n[d+4>>2]=l&0,oe=0,d=0,we=oe,d|0):(oe=0,d=0,we=oe,d|0):(m&&(n[d>>2]=(M>>>0)%(B>>>0),n[d+4>>2]=0),oe=0,d=(M>>>0)/(B>>>0)>>>0,we=oe,d|0);m=(k|0)==0;do if(B){if(!m){if(m=(S(k|0)|0)-(S(O|0)|0)|0,m>>>0<=31){j=m+1|0,k=31-m|0,l=m-31>>31,B=j,s=M>>>(j>>>0)&l|O<>>(j>>>0)&l,m=0,k=M<>2]=s|0,n[d+4>>2]=F|l&0,oe=0,d=0,we=oe,d|0):(oe=0,d=0,we=oe,d|0)}if(m=B-1|0,m&B|0){k=(S(B|0)|0)+33-(S(O|0)|0)|0,Me=64-k|0,j=32-k|0,F=j>>31,Ye=k-32|0,l=Ye>>31,B=k,s=j-1>>31&O>>>(Ye>>>0)|(O<>>(k>>>0))&l,l=l&O>>>(k>>>0),m=M<>>(Ye>>>0))&F|M<>31;break}return d|0&&(n[d>>2]=m&M,n[d+4>>2]=0),(B|0)==1?(Ye=F|l&0,Me=s|0|0,we=Ye,Me|0):(Me=z7(B|0)|0,Ye=O>>>(Me>>>0)|0,Me=O<<32-Me|M>>>(Me>>>0)|0,we=Ye,Me|0)}else{if(m)return d|0&&(n[d>>2]=(O>>>0)%(B>>>0),n[d+4>>2]=0),Ye=0,Me=(O>>>0)/(B>>>0)>>>0,we=Ye,Me|0;if(!M)return d|0&&(n[d>>2]=0,n[d+4>>2]=(O>>>0)%(k>>>0)),Ye=0,Me=(O>>>0)/(k>>>0)>>>0,we=Ye,Me|0;if(m=k-1|0,!(m&k))return d|0&&(n[d>>2]=s|0,n[d+4>>2]=m&O|l&0),Ye=0,Me=O>>>((z7(k|0)|0)>>>0),we=Ye,Me|0;if(m=(S(k|0)|0)-(S(O|0)|0)|0,m>>>0<=30){l=m+1|0,k=31-m|0,B=l,s=O<>>(l>>>0),l=O>>>(l>>>0),m=0,k=M<>2]=s|0,n[d+4>>2]=F|l&0,Ye=0,Me=0,we=Ye,Me|0):(Ye=0,Me=0,we=Ye,Me|0)}while(!1);if(!B)O=k,F=0,k=0;else{j=c|0|0,M=oe|f&0,O=cT(j|0,M|0,-1,-1)|0,c=we,F=k,k=0;do f=F,F=m>>>31|F<<1,m=k|m<<1,f=s<<1|f>>>31|0,oe=s>>>31|l<<1|0,jD(O|0,c|0,f|0,oe|0)|0,Me=we,Ye=Me>>31|((Me|0)<0?-1:0)<<1,k=Ye&1,s=jD(f|0,oe|0,Ye&j|0,(((Me|0)<0?-1:0)>>31|((Me|0)<0?-1:0)<<1)&M|0)|0,l=we,B=B-1|0;while(B|0);O=F,F=0}return B=0,d|0&&(n[d>>2]=s,n[d+4>>2]=l),Ye=(m|0)>>>31|(O|B)<<1|(B<<1|m>>>31)&0|F,Me=(m<<1|0)&-2|k,we=Ye,Me|0}function uT(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,J7(s,l,c,f,0)|0}function Tp(s){s=s|0;var l=0,c=0;return c=s+15&-16|0,l=n[I>>2]|0,s=l+c|0,(c|0)>0&(s|0)<(l|0)|(s|0)<0?(se()|0,yc(12),-1):(n[I>>2]=s,(s|0)>($()|0)&&!(X()|0)?(n[I>>2]=l,yc(12),-1):l|0)}function rI(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if((l|0)<(s|0)&(s|0)<(l+c|0)){for(f=s,l=l+c|0,s=s+c|0;(c|0)>0;)s=s-1|0,l=l-1|0,c=c-1|0,o[s>>0]=o[l>>0]|0;s=f}else xr(s,l,c)|0;return s|0}function AT(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;return m=C,C=C+16|0,d=m|0,J7(s,l,c,f,d)|0,C=m,we=n[d+4>>2]|0,n[d>>2]|0|0}function X7(s){return s=s|0,(s&255)<<24|(s>>8&255)<<16|(s>>16&255)<<8|s>>>24|0}function VUe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,Z7[s&1](l|0,c|0,f|0,d|0,m|0)}function zUe(s,l,c){s=s|0,l=l|0,c=y(c),$7[s&1](l|0,y(c))}function JUe(s,l,c){s=s|0,l=l|0,c=+c,eY[s&31](l|0,+c)}function XUe(s,l,c,f){return s=s|0,l=l|0,c=y(c),f=y(f),y(tY[s&0](l|0,y(c),y(f)))}function ZUe(s,l){s=s|0,l=l|0,ef[s&127](l|0)}function $Ue(s,l,c){s=s|0,l=l|0,c=c|0,tf[s&31](l|0,c|0)}function e3e(s,l){return s=s|0,l=l|0,_0[s&31](l|0)|0}function t3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,rY[s&1](l|0,+c,+f,d|0)}function r3e(s,l,c,f){s=s|0,l=l|0,c=+c,f=+f,L3e[s&1](l|0,+c,+f)}function n3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,WD[s&7](l|0,c|0,f|0)|0}function i3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,+M3e[s&1](l|0,c|0,f|0)}function s3e(s,l){return s=s|0,l=l|0,+nY[s&15](l|0)}function o3e(s,l,c){return s=s|0,l=l|0,c=+c,O3e[s&1](l|0,+c)|0}function a3e(s,l,c){return s=s|0,l=l|0,c=c|0,pT[s&15](l|0,c|0)|0}function l3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=+f,d=+d,m=m|0,U3e[s&1](l|0,c|0,+f,+d,m|0)}function c3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,_3e[s&1](l|0,c|0,f|0,d|0,m|0,B|0)}function u3e(s,l,c){return s=s|0,l=l|0,c=c|0,+iY[s&7](l|0,c|0)}function A3e(s){return s=s|0,KD[s&7]()|0}function f3e(s,l,c,f,d,m){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,sY[s&1](l|0,c|0,f|0,d|0,m|0)|0}function p3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=+d,H3e[s&1](l|0,c|0,f|0,+d)}function h3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,oY[s&1](l|0,c|0,y(f),d|0,y(m),B|0)}function g3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,sI[s&15](l|0,c|0,f|0)}function d3e(s){s=s|0,aY[s&0]()}function m3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,lY[s&15](l|0,c|0,+f)}function y3e(s,l,c){return s=s|0,l=+l,c=+c,q3e[s&1](+l,+c)|0}function E3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,hT[s&15](l|0,c|0,f|0,d|0)}function C3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,R(0)}function w3e(s,l){s=s|0,l=y(l),R(1)}function Ca(s,l){s=s|0,l=+l,R(2)}function I3e(s,l,c){return s=s|0,l=y(l),c=y(c),R(3),Ze}function Cr(s){s=s|0,R(4)}function nI(s,l){s=s|0,l=l|0,R(5)}function tl(s){return s=s|0,R(6),0}function B3e(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,R(7)}function v3e(s,l,c){s=s|0,l=+l,c=+c,R(8)}function D3e(s,l,c){return s=s|0,l=l|0,c=c|0,R(9),0}function P3e(s,l,c){return s=s|0,l=l|0,c=c|0,R(10),0}function U0(s){return s=s|0,R(11),0}function S3e(s,l){return s=s|0,l=+l,R(12),0}function iI(s,l){return s=s|0,l=l|0,R(13),0}function b3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,R(14)}function x3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,R(15)}function fT(s,l){return s=s|0,l=l|0,R(16),0}function k3e(){return R(17),0}function Q3e(s,l,c,f,d){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,R(18),0}function F3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,R(19)}function R3e(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0,R(20)}function YD(s,l,c){s=s|0,l=l|0,c=c|0,R(21)}function T3e(){R(22)}function om(s,l,c){s=s|0,l=l|0,c=+c,R(23)}function N3e(s,l){return s=+s,l=+l,R(24),0}function am(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,R(25)}var Z7=[C3e,QLe],$7=[w3e,Md],eY=[Ca,B0,vp,Uw,_w,Hw,qw,ku,Yd,jw,Qu,v0,D0,Gw,Yw,xc,P0,Ww,Wd,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca],tY=[I3e],ef=[Cr,im,ADe,fDe,pDe,qbe,jbe,Gbe,oNe,aNe,lNe,yLe,ELe,CLe,_4e,H4e,q4e,qa,I0,Nw,ir,xl,xD,kD,tDe,wDe,RDe,XDe,pPe,kPe,KPe,lSe,BSe,USe,tbe,mbe,Rbe,axe,Bxe,Uxe,tke,mke,Rke,Zke,pQe,SQe,jQe,dD,CFe,LFe,tRe,ERe,TRe,tTe,ATe,hTe,QTe,TTe,XTe,uNe,pNe,kNe,VNe,OG,xMe,oOe,wOe,LOe,i4e,E4e,k4e,R4e,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr],tf=[nI,qd,WF,Lw,Mw,Sr,Ms,Mi,ms,is,Gd,Bp,Vw,wD,x0,zF,JF,ID,BD,$F,Fu,ne,rQe,dQe,BRe,FMe,rLe,I7,nI,nI,nI,nI],_0=[tl,mUe,_d,b0,Vd,qo,mD,Dp,Kw,VF,ED,zd,vD,eR,Zd,WQe,ORe,RNe,LMe,Za,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl],rY=[B3e,sR],L3e=[v3e,eNe],WD=[D3e,L7,yUe,wUe,TPe,Axe,vFe,_Oe],M3e=[P3e,sbe],nY=[U0,Pp,CD,zA,oR,v,P,Q,H,W,U0,U0,U0,U0,U0,U0],O3e=[S3e,lTe],pT=[iI,qUe,DD,sDe,tPe,JPe,ASe,Mbe,Sxe,QQe,Od,DOe,iI,iI,iI,iI],U3e=[b3e,MDe],_3e=[x3e,l4e],iY=[fT,XF,Be,Ue,ft,wbe,fT,fT],KD=[k3e,jt,Ud,gD,yTe,OTe,mNe,M4e],sY=[Q3e,kd],H3e=[F3e,ske],oY=[R3e,tR],sI=[YD,oo,yD,ZF,Qc,mPe,PSe,wke,Mke,YF,eMe,uOe,B4e,YD,YD,YD],aY=[T3e],lY=[om,KF,jd,VA,Ow,kc,Kd,S0,jxe,_Fe,iTe,om,om,om,om,om],q3e=[N3e,iNe],hT=[am,jSe,eFe,sRe,KRe,vTe,GTe,vNe,$Ne,qMe,V4e,am,am,am,am,am];return{_llvm_bswap_i32:X7,dynCall_idd:y3e,dynCall_i:A3e,_i64Subtract:jD,___udivdi3:uT,dynCall_vif:zUe,setThrew:Lo,dynCall_viii:g3e,_bitshift64Lshr:GD,_bitshift64Shl:V7,dynCall_vi:ZUe,dynCall_viiddi:l3e,dynCall_diii:i3e,dynCall_iii:a3e,_memset:sm,_sbrk:Tp,_memcpy:xr,__GLOBAL__sub_I_Yoga_cpp:Fw,dynCall_vii:$Ue,___uremdi3:AT,dynCall_vid:JUe,stackAlloc:ca,_nbind_init:sUe,getTempRet0:TA,dynCall_di:s3e,dynCall_iid:o3e,setTempRet0:RA,_i64Add:cT,dynCall_fiff:XUe,dynCall_iiii:n3e,_emscripten_get_global_libc:dUe,dynCall_viid:m3e,dynCall_viiid:p3e,dynCall_viififi:h3e,dynCall_ii:e3e,__GLOBAL__sub_I_Binding_cc:wMe,dynCall_viiii:E3e,dynCall_iiiiii:f3e,stackSave:mu,dynCall_viiiii:VUe,__GLOBAL__sub_I_nbind_cc:Ir,dynCall_vidd:r3e,_free:HD,runPostSets:KUe,dynCall_viiiiii:c3e,establishStackSpace:dn,_memmove:rI,stackRestore:Bl,_malloc:_D,__GLOBAL__sub_I_common_cc:HNe,dynCall_viddi:t3e,dynCall_dii:u3e,dynCall_v:d3e}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(t){this.name="ExitStatus",this.message="Program terminated with exit("+t+")",this.status=t}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function t(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=t)},Module.callMain=Module.callMain=function t(e){e=e||[],ensureInitRuntime();var r=e.length+1;function o(){for(var p=0;p<3;p++)a.push(0)}var a=[allocate(intArrayFromString(Module.thisProgram),"i8",ALLOC_NORMAL)];o();for(var n=0;n0||(preRun(),runDependencies>0)||Module.calledRun)return;function e(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(t),postRun()))}Module.setStatus?(Module.setStatus("Running..."),setTimeout(function(){setTimeout(function(){Module.setStatus("")},1),e()},1)):e()}Module.run=Module.run=run;function exit(t,e){e&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=t,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(t)),ENVIRONMENT_IS_NODE&&process.exit(t),Module.quit(t,new ExitStatus(t)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(t){Module.onAbort&&Module.onAbort(t),t!==void 0?(Module.print(t),Module.printErr(t),t=JSON.stringify(t)):t="",ABORT=!0,EXITSTATUS=1;var e=` +If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,r="abort("+t+") at "+stackTrace()+e;throw abortDecorators&&abortDecorators.forEach(function(o){r=o(r,t)}),r}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var id=_((nKt,SCe)=>{"use strict";var xyt=DCe(),kyt=PCe(),pq=!1,hq=null;kyt({},function(t,e){if(!pq){if(pq=!0,t)throw t;hq=e}});if(!pq)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");SCe.exports=xyt(hq.bind,hq.lib)});var dq=_((iKt,gq)=>{"use strict";var bCe=t=>Number.isNaN(t)?!1:t>=4352&&(t<=4447||t===9001||t===9002||11904<=t&&t<=12871&&t!==12351||12880<=t&&t<=19903||19968<=t&&t<=42182||43360<=t&&t<=43388||44032<=t&&t<=55203||63744<=t&&t<=64255||65040<=t&&t<=65049||65072<=t&&t<=65131||65281<=t&&t<=65376||65504<=t&&t<=65510||110592<=t&&t<=110593||127488<=t&&t<=127569||131072<=t&&t<=262141);gq.exports=bCe;gq.exports.default=bCe});var kCe=_((sKt,xCe)=>{"use strict";xCe.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var PB=_((oKt,mq)=>{"use strict";var Qyt=pS(),Fyt=dq(),Ryt=kCe(),QCe=t=>{if(typeof t!="string"||t.length===0||(t=Qyt(t),t.length===0))return 0;t=t.replace(Ryt()," ");let e=0;for(let r=0;r=127&&o<=159||o>=768&&o<=879||(o>65535&&r++,e+=Fyt(o)?2:1)}return e};mq.exports=QCe;mq.exports.default=QCe});var Eq=_((aKt,yq)=>{"use strict";var Tyt=PB(),FCe=t=>{let e=0;for(let r of t.split(` +`))e=Math.max(e,Tyt(r));return e};yq.exports=FCe;yq.exports.default=FCe});var RCe=_(SB=>{"use strict";var Nyt=SB&&SB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(SB,"__esModule",{value:!0});var Lyt=Nyt(Eq()),Cq={};SB.default=t=>{if(t.length===0)return{width:0,height:0};if(Cq[t])return Cq[t];let e=Lyt.default(t),r=t.split(` +`).length;return Cq[t]={width:e,height:r},{width:e,height:r}}});var TCe=_(bB=>{"use strict";var Myt=bB&&bB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(bB,"__esModule",{value:!0});var wn=Myt(id()),Oyt=(t,e)=>{"position"in e&&t.setPositionType(e.position==="absolute"?wn.default.POSITION_TYPE_ABSOLUTE:wn.default.POSITION_TYPE_RELATIVE)},Uyt=(t,e)=>{"marginLeft"in e&&t.setMargin(wn.default.EDGE_START,e.marginLeft||0),"marginRight"in e&&t.setMargin(wn.default.EDGE_END,e.marginRight||0),"marginTop"in e&&t.setMargin(wn.default.EDGE_TOP,e.marginTop||0),"marginBottom"in e&&t.setMargin(wn.default.EDGE_BOTTOM,e.marginBottom||0)},_yt=(t,e)=>{"paddingLeft"in e&&t.setPadding(wn.default.EDGE_LEFT,e.paddingLeft||0),"paddingRight"in e&&t.setPadding(wn.default.EDGE_RIGHT,e.paddingRight||0),"paddingTop"in e&&t.setPadding(wn.default.EDGE_TOP,e.paddingTop||0),"paddingBottom"in e&&t.setPadding(wn.default.EDGE_BOTTOM,e.paddingBottom||0)},Hyt=(t,e)=>{var r;"flexGrow"in e&&t.setFlexGrow((r=e.flexGrow)!==null&&r!==void 0?r:0),"flexShrink"in e&&t.setFlexShrink(typeof e.flexShrink=="number"?e.flexShrink:1),"flexDirection"in e&&(e.flexDirection==="row"&&t.setFlexDirection(wn.default.FLEX_DIRECTION_ROW),e.flexDirection==="row-reverse"&&t.setFlexDirection(wn.default.FLEX_DIRECTION_ROW_REVERSE),e.flexDirection==="column"&&t.setFlexDirection(wn.default.FLEX_DIRECTION_COLUMN),e.flexDirection==="column-reverse"&&t.setFlexDirection(wn.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in e&&(typeof e.flexBasis=="number"?t.setFlexBasis(e.flexBasis):typeof e.flexBasis=="string"?t.setFlexBasisPercent(Number.parseInt(e.flexBasis,10)):t.setFlexBasis(NaN)),"alignItems"in e&&((e.alignItems==="stretch"||!e.alignItems)&&t.setAlignItems(wn.default.ALIGN_STRETCH),e.alignItems==="flex-start"&&t.setAlignItems(wn.default.ALIGN_FLEX_START),e.alignItems==="center"&&t.setAlignItems(wn.default.ALIGN_CENTER),e.alignItems==="flex-end"&&t.setAlignItems(wn.default.ALIGN_FLEX_END)),"alignSelf"in e&&((e.alignSelf==="auto"||!e.alignSelf)&&t.setAlignSelf(wn.default.ALIGN_AUTO),e.alignSelf==="flex-start"&&t.setAlignSelf(wn.default.ALIGN_FLEX_START),e.alignSelf==="center"&&t.setAlignSelf(wn.default.ALIGN_CENTER),e.alignSelf==="flex-end"&&t.setAlignSelf(wn.default.ALIGN_FLEX_END)),"justifyContent"in e&&((e.justifyContent==="flex-start"||!e.justifyContent)&&t.setJustifyContent(wn.default.JUSTIFY_FLEX_START),e.justifyContent==="center"&&t.setJustifyContent(wn.default.JUSTIFY_CENTER),e.justifyContent==="flex-end"&&t.setJustifyContent(wn.default.JUSTIFY_FLEX_END),e.justifyContent==="space-between"&&t.setJustifyContent(wn.default.JUSTIFY_SPACE_BETWEEN),e.justifyContent==="space-around"&&t.setJustifyContent(wn.default.JUSTIFY_SPACE_AROUND))},qyt=(t,e)=>{var r,o;"width"in e&&(typeof e.width=="number"?t.setWidth(e.width):typeof e.width=="string"?t.setWidthPercent(Number.parseInt(e.width,10)):t.setWidthAuto()),"height"in e&&(typeof e.height=="number"?t.setHeight(e.height):typeof e.height=="string"?t.setHeightPercent(Number.parseInt(e.height,10)):t.setHeightAuto()),"minWidth"in e&&(typeof e.minWidth=="string"?t.setMinWidthPercent(Number.parseInt(e.minWidth,10)):t.setMinWidth((r=e.minWidth)!==null&&r!==void 0?r:0)),"minHeight"in e&&(typeof e.minHeight=="string"?t.setMinHeightPercent(Number.parseInt(e.minHeight,10)):t.setMinHeight((o=e.minHeight)!==null&&o!==void 0?o:0))},jyt=(t,e)=>{"display"in e&&t.setDisplay(e.display==="flex"?wn.default.DISPLAY_FLEX:wn.default.DISPLAY_NONE)},Gyt=(t,e)=>{if("borderStyle"in e){let r=typeof e.borderStyle=="string"?1:0;t.setBorder(wn.default.EDGE_TOP,r),t.setBorder(wn.default.EDGE_BOTTOM,r),t.setBorder(wn.default.EDGE_LEFT,r),t.setBorder(wn.default.EDGE_RIGHT,r)}};bB.default=(t,e={})=>{Oyt(t,e),Uyt(t,e),_yt(t,e),Hyt(t,e),qyt(t,e),jyt(t,e),Gyt(t,e)}});var MCe=_((uKt,LCe)=>{"use strict";var xB=PB(),Yyt=pS(),Wyt=qI(),Iq=new Set(["\x1B","\x9B"]),Kyt=39,NCe=t=>`${Iq.values().next().value}[${t}m`,Vyt=t=>t.split(" ").map(e=>xB(e)),wq=(t,e,r)=>{let o=[...e],a=!1,n=xB(Yyt(t[t.length-1]));for(let[u,A]of o.entries()){let p=xB(A);if(n+p<=r?t[t.length-1]+=A:(t.push(A),n=0),Iq.has(A))a=!0;else if(a&&A==="m"){a=!1;continue}a||(n+=p,n===r&&u0&&t.length>1&&(t[t.length-2]+=t.pop())},zyt=t=>{let e=t.split(" "),r=e.length;for(;r>0&&!(xB(e[r-1])>0);)r--;return r===e.length?t:e.slice(0,r).join(" ")+e.slice(r).join("")},Jyt=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let o="",a="",n,u=Vyt(t),A=[""];for(let[p,h]of t.split(" ").entries()){r.trim!==!1&&(A[A.length-1]=A[A.length-1].trimLeft());let E=xB(A[A.length-1]);if(p!==0&&(E>=e&&(r.wordWrap===!1||r.trim===!1)&&(A.push(""),E=0),(E>0||r.trim===!1)&&(A[A.length-1]+=" ",E++)),r.hard&&u[p]>e){let I=e-E,D=1+Math.floor((u[p]-I-1)/e);Math.floor((u[p]-1)/e)e&&E>0&&u[p]>0){if(r.wordWrap===!1&&Ee&&r.wordWrap===!1){wq(A,h,e);continue}A[A.length-1]+=h}r.trim!==!1&&(A=A.map(zyt)),o=A.join(` +`);for(let[p,h]of[...o].entries()){if(a+=h,Iq.has(h)){let I=parseFloat(/\d[^m]*/.exec(o.slice(p,p+4)));n=I===Kyt?null:I}let E=Wyt.codes.get(Number(n));n&&E&&(o[p+1]===` +`?a+=NCe(E):h===` +`&&(a+=NCe(n)))}return a};LCe.exports=(t,e,r)=>String(t).normalize().replace(/\r\n/g,` +`).split(` +`).map(o=>Jyt(o,e,r)).join(` +`)});var _Ce=_((AKt,UCe)=>{"use strict";var OCe="[\uD800-\uDBFF][\uDC00-\uDFFF]",Xyt=t=>t&&t.exact?new RegExp(`^${OCe}$`):new RegExp(OCe,"g");UCe.exports=Xyt});var Bq=_((fKt,GCe)=>{"use strict";var Zyt=dq(),$yt=_Ce(),HCe=qI(),jCe=["\x1B","\x9B"],vQ=t=>`${jCe[0]}[${t}m`,qCe=(t,e,r)=>{let o=[];t=[...t];for(let a of t){let n=a;a.match(";")&&(a=a.split(";")[0][0]+"0");let u=HCe.codes.get(parseInt(a,10));if(u){let A=t.indexOf(u.toString());A>=0?t.splice(A,1):o.push(vQ(e?u:n))}else if(e){o.push(vQ(0));break}else o.push(vQ(n))}if(e&&(o=o.filter((a,n)=>o.indexOf(a)===n),r!==void 0)){let a=vQ(HCe.codes.get(parseInt(r,10)));o=o.reduce((n,u)=>u===a?[u,...n]:[...n,u],[])}return o.join("")};GCe.exports=(t,e,r)=>{let o=[...t.normalize()],a=[];r=typeof r=="number"?r:o.length;let n=!1,u,A=0,p="";for(let[h,E]of o.entries()){let I=!1;if(jCe.includes(E)){let D=/\d[^m]*/.exec(t.slice(h,h+18));u=D&&D.length>0?D[0]:void 0,Ae&&A<=r)p+=E;else if(A===e&&!n&&u!==void 0)p=qCe(a);else if(A>=r){p+=qCe(a,!0,u);break}}return p}});var WCe=_((pKt,YCe)=>{"use strict";var _h=Bq(),eEt=PB();function DQ(t,e,r){if(t.charAt(e)===" ")return e;for(let o=1;o<=3;o++)if(r){if(t.charAt(e+o)===" ")return e+o}else if(t.charAt(e-o)===" ")return e-o;return e}YCe.exports=(t,e,r)=>{r={position:"end",preferTruncationOnSpace:!1,...r};let{position:o,space:a,preferTruncationOnSpace:n}=r,u="\u2026",A=1;if(typeof t!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof t}`);if(typeof e!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof e}`);if(e<1)return"";if(e===1)return u;let p=eEt(t);if(p<=e)return t;if(o==="start"){if(n){let h=DQ(t,p-e+1,!0);return u+_h(t,h,p).trim()}return a===!0&&(u+=" ",A=2),u+_h(t,p-e+A,p)}if(o==="middle"){a===!0&&(u=" "+u+" ",A=3);let h=Math.floor(e/2);if(n){let E=DQ(t,h),I=DQ(t,p-(e-h)+1,!0);return _h(t,0,E)+u+_h(t,I,p).trim()}return _h(t,0,h)+u+_h(t,p-(e-h)+A,p)}if(o==="end"){if(n){let h=DQ(t,e-1);return _h(t,0,h)+u}return a===!0&&(u=" "+u,A=2),_h(t,0,e-A)+u}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${o}`)}});var Dq=_(kB=>{"use strict";var KCe=kB&&kB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(kB,"__esModule",{value:!0});var tEt=KCe(MCe()),rEt=KCe(WCe()),vq={};kB.default=(t,e,r)=>{let o=t+String(e)+String(r);if(vq[o])return vq[o];let a=t;if(r==="wrap"&&(a=tEt.default(t,e,{trim:!1,hard:!0})),r.startsWith("truncate")){let n="end";r==="truncate-middle"&&(n="middle"),r==="truncate-start"&&(n="start"),a=rEt.default(t,e,{position:n})}return vq[o]=a,a}});var Sq=_(Pq=>{"use strict";Object.defineProperty(Pq,"__esModule",{value:!0});var VCe=t=>{let e="";if(t.childNodes.length>0)for(let r of t.childNodes){let o="";r.nodeName==="#text"?o=r.nodeValue:((r.nodeName==="ink-text"||r.nodeName==="ink-virtual-text")&&(o=VCe(r)),o.length>0&&typeof r.internal_transform=="function"&&(o=r.internal_transform(o))),e+=o}return e};Pq.default=VCe});var bq=_(Ei=>{"use strict";var QB=Ei&&Ei.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ei,"__esModule",{value:!0});Ei.setTextNodeValue=Ei.createTextNode=Ei.setStyle=Ei.setAttribute=Ei.removeChildNode=Ei.insertBeforeNode=Ei.appendChildNode=Ei.createNode=Ei.TEXT_NAME=void 0;var nEt=QB(id()),zCe=QB(RCe()),iEt=QB(TCe()),sEt=QB(Dq()),oEt=QB(Sq());Ei.TEXT_NAME="#text";Ei.createNode=t=>{var e;let r={nodeName:t,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:t==="ink-virtual-text"?void 0:nEt.default.Node.create()};return t==="ink-text"&&((e=r.yogaNode)===null||e===void 0||e.setMeasureFunc(aEt.bind(null,r))),r};Ei.appendChildNode=(t,e)=>{var r;e.parentNode&&Ei.removeChildNode(e.parentNode,e),e.parentNode=t,t.childNodes.push(e),e.yogaNode&&((r=t.yogaNode)===null||r===void 0||r.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PQ(t)};Ei.insertBeforeNode=(t,e,r)=>{var o,a;e.parentNode&&Ei.removeChildNode(e.parentNode,e),e.parentNode=t;let n=t.childNodes.indexOf(r);if(n>=0){t.childNodes.splice(n,0,e),e.yogaNode&&((o=t.yogaNode)===null||o===void 0||o.insertChild(e.yogaNode,n));return}t.childNodes.push(e),e.yogaNode&&((a=t.yogaNode)===null||a===void 0||a.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PQ(t)};Ei.removeChildNode=(t,e)=>{var r,o;e.yogaNode&&((o=(r=e.parentNode)===null||r===void 0?void 0:r.yogaNode)===null||o===void 0||o.removeChild(e.yogaNode)),e.parentNode=null;let a=t.childNodes.indexOf(e);a>=0&&t.childNodes.splice(a,1),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PQ(t)};Ei.setAttribute=(t,e,r)=>{t.attributes[e]=r};Ei.setStyle=(t,e)=>{t.style=e,t.yogaNode&&iEt.default(t.yogaNode,e)};Ei.createTextNode=t=>{let e={nodeName:"#text",nodeValue:t,yogaNode:void 0,parentNode:null,style:{}};return Ei.setTextNodeValue(e,t),e};var aEt=function(t,e){var r,o;let a=t.nodeName==="#text"?t.nodeValue:oEt.default(t),n=zCe.default(a);if(n.width<=e||n.width>=1&&e>0&&e<1)return n;let u=(o=(r=t.style)===null||r===void 0?void 0:r.textWrap)!==null&&o!==void 0?o:"wrap",A=sEt.default(a,e,u);return zCe.default(A)},JCe=t=>{var e;if(!(!t||!t.parentNode))return(e=t.yogaNode)!==null&&e!==void 0?e:JCe(t.parentNode)},PQ=t=>{let e=JCe(t);e?.markDirty()};Ei.setTextNodeValue=(t,e)=>{typeof e!="string"&&(e=String(e)),t.nodeValue=e,PQ(t)}});var twe=_(FB=>{"use strict";var ewe=FB&&FB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(FB,"__esModule",{value:!0});var XCe=uq(),lEt=ewe(ECe()),ZCe=ewe(id()),ko=bq(),$Ce=t=>{t?.unsetMeasureFunc(),t?.freeRecursive()};FB.default=lEt.default({schedulePassiveEffects:XCe.unstable_scheduleCallback,cancelPassiveEffects:XCe.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>null,preparePortalMount:()=>null,clearContainer:()=>!1,shouldDeprioritizeSubtree:()=>!1,resetAfterCommit:t=>{if(t.isStaticDirty){t.isStaticDirty=!1,typeof t.onImmediateRender=="function"&&t.onImmediateRender();return}typeof t.onRender=="function"&&t.onRender()},getChildHostContext:(t,e)=>{let r=t.isInsideText,o=e==="ink-text"||e==="ink-virtual-text";return r===o?t:{isInsideText:o}},shouldSetTextContent:()=>!1,createInstance:(t,e,r,o)=>{if(o.isInsideText&&t==="ink-box")throw new Error(" can\u2019t be nested inside component");let a=t==="ink-text"&&o.isInsideText?"ink-virtual-text":t,n=ko.createNode(a);for(let[u,A]of Object.entries(e))u!=="children"&&(u==="style"?ko.setStyle(n,A):u==="internal_transform"?n.internal_transform=A:u==="internal_static"?n.internal_static=!0:ko.setAttribute(n,u,A));return n},createTextInstance:(t,e,r)=>{if(!r.isInsideText)throw new Error(`Text string "${t}" must be rendered inside component`);return ko.createTextNode(t)},resetTextContent:()=>{},hideTextInstance:t=>{ko.setTextNodeValue(t,"")},unhideTextInstance:(t,e)=>{ko.setTextNodeValue(t,e)},getPublicInstance:t=>t,hideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ZCe.default.DISPLAY_NONE)},unhideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ZCe.default.DISPLAY_FLEX)},appendInitialChild:ko.appendChildNode,appendChild:ko.appendChildNode,insertBefore:ko.insertBeforeNode,finalizeInitialChildren:(t,e,r,o)=>(t.internal_static&&(o.isStaticDirty=!0,o.staticNode=t),!1),supportsMutation:!0,appendChildToContainer:ko.appendChildNode,insertInContainerBefore:ko.insertBeforeNode,removeChildFromContainer:(t,e)=>{ko.removeChildNode(t,e),$Ce(e.yogaNode)},prepareUpdate:(t,e,r,o,a)=>{t.internal_static&&(a.isStaticDirty=!0);let n={},u=Object.keys(o);for(let A of u)if(o[A]!==r[A]){if(A==="style"&&typeof o.style=="object"&&typeof r.style=="object"){let h=o.style,E=r.style,I=Object.keys(h);for(let D of I){if(D==="borderStyle"||D==="borderColor"){if(typeof n.style!="object"){let x={};n.style=x}n.style.borderStyle=h.borderStyle,n.style.borderColor=h.borderColor}if(h[D]!==E[D]){if(typeof n.style!="object"){let x={};n.style=x}n.style[D]=h[D]}}continue}n[A]=o[A]}return n},commitUpdate:(t,e)=>{for(let[r,o]of Object.entries(e))r!=="children"&&(r==="style"?ko.setStyle(t,o):r==="internal_transform"?t.internal_transform=o:r==="internal_static"?t.internal_static=!0:ko.setAttribute(t,r,o))},commitTextUpdate:(t,e,r)=>{ko.setTextNodeValue(t,r)},removeChild:(t,e)=>{ko.removeChildNode(t,e),$Ce(e.yogaNode)}})});var nwe=_((yKt,rwe)=>{"use strict";rwe.exports=(t,e=1,r)=>{if(r={indent:" ",includeEmptyLines:!1,...r},typeof t!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof t}\``);if(typeof e!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof e}\``);if(typeof r.indent!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof r.indent}\``);if(e===0)return t;let o=r.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return t.replace(o,r.indent.repeat(e))}});var iwe=_(RB=>{"use strict";var cEt=RB&&RB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(RB,"__esModule",{value:!0});var SQ=cEt(id());RB.default=t=>t.getComputedWidth()-t.getComputedPadding(SQ.default.EDGE_LEFT)-t.getComputedPadding(SQ.default.EDGE_RIGHT)-t.getComputedBorder(SQ.default.EDGE_LEFT)-t.getComputedBorder(SQ.default.EDGE_RIGHT)});var swe=_((CKt,uEt)=>{uEt.exports={single:{topLeft:"\u250C",topRight:"\u2510",bottomRight:"\u2518",bottomLeft:"\u2514",vertical:"\u2502",horizontal:"\u2500"},double:{topLeft:"\u2554",topRight:"\u2557",bottomRight:"\u255D",bottomLeft:"\u255A",vertical:"\u2551",horizontal:"\u2550"},round:{topLeft:"\u256D",topRight:"\u256E",bottomRight:"\u256F",bottomLeft:"\u2570",vertical:"\u2502",horizontal:"\u2500"},bold:{topLeft:"\u250F",topRight:"\u2513",bottomRight:"\u251B",bottomLeft:"\u2517",vertical:"\u2503",horizontal:"\u2501"},singleDouble:{topLeft:"\u2553",topRight:"\u2556",bottomRight:"\u255C",bottomLeft:"\u2559",vertical:"\u2551",horizontal:"\u2500"},doubleSingle:{topLeft:"\u2552",topRight:"\u2555",bottomRight:"\u255B",bottomLeft:"\u2558",vertical:"\u2502",horizontal:"\u2550"},classic:{topLeft:"+",topRight:"+",bottomRight:"+",bottomLeft:"+",vertical:"|",horizontal:"-"}}});var awe=_((wKt,xq)=>{"use strict";var owe=swe();xq.exports=owe;xq.exports.default=owe});var cwe=_((IKt,lwe)=>{"use strict";var AEt=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u="";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},fEt=(t,e,r,o)=>{let a=0,n="";do{let u=t[o-1]==="\r";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\r +`:` +`)+r,a=o+1,o=t.indexOf(` +`,a)}while(o!==-1);return n+=t.substr(a),n};lwe.exports={stringReplaceAll:AEt,stringEncaseCRLFWithFirstIndex:fEt}});var hwe=_((BKt,pwe)=>{"use strict";var pEt=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,uwe=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,hEt=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,gEt=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,dEt=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function fwe(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5||t[0]==="x"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):dEt.get(t)||t}function mEt(t,e){let r=[],o=e.trim().split(/\s*,\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(hEt))r.push(a[2].replace(gEt,(A,p,h)=>p?fwe(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function yEt(t){uwe.lastIndex=0;let e=[],r;for(;(r=uwe.exec(t))!==null;){let o=r[1];if(r[2]){let a=mEt(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function Awe(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}pwe.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(pEt,(n,u,A,p,h,E)=>{if(u)a.push(fwe(u));else if(p){let I=a.join("");a=[],o.push(r.length===0?I:Awe(t,r)(I)),r.push({inverse:A,styles:yEt(p)})}else if(h){if(r.length===0)throw new Error("Found extraneous } in Chalk template literal");o.push(Awe(t,r)(a.join(""))),a=[],r.pop()}else a.push(E)}),o.push(a.join("")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?"":"s"} (\`}\`)`;throw new Error(n)}return o.join("")}});var FQ=_((vKt,Cwe)=>{"use strict";var TB=qI(),{stdout:Qq,stderr:Fq}=ZN(),{stringReplaceAll:EEt,stringEncaseCRLFWithFirstIndex:CEt}=cwe(),{isArray:bQ}=Array,dwe=["ansi","ansi","ansi256","ansi16m"],DC=Object.create(null),wEt=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let r=Qq?Qq.level:0;t.level=e.level===void 0?r:e.level},Rq=class{constructor(e){return mwe(e)}},mwe=t=>{let e={};return wEt(e,t),e.template=(...r)=>Ewe(e.template,...r),Object.setPrototypeOf(e,xQ.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=Rq,e.template};function xQ(t){return mwe(t)}for(let[t,e]of Object.entries(TB))DC[t]={get(){let r=kQ(this,Tq(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};DC.visible={get(){let t=kQ(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:t}),t}};var ywe=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let t of ywe)DC[t]={get(){let{level:e}=this;return function(...r){let o=Tq(TB.color[dwe[e]][t](...r),TB.color.close,this._styler);return kQ(this,o,this._isEmpty)}}};for(let t of ywe){let e="bg"+t[0].toUpperCase()+t.slice(1);DC[e]={get(){let{level:r}=this;return function(...o){let a=Tq(TB.bgColor[dwe[r]][t](...o),TB.bgColor.close,this._styler);return kQ(this,a,this._isEmpty)}}}}var IEt=Object.defineProperties(()=>{},{...DC,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),Tq=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},kQ=(t,e,r)=>{let o=(...a)=>bQ(a[0])&&bQ(a[0].raw)?gwe(o,Ewe(o,...a)):gwe(o,a.length===1?""+a[0]:a.join(" "));return Object.setPrototypeOf(o,IEt),o._generator=t,o._styler=e,o._isEmpty=r,o},gwe=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?"":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf("\x1B")!==-1)for(;r!==void 0;)e=EEt(e,r.close,r.open),r=r.parent;let n=e.indexOf(` +`);return n!==-1&&(e=CEt(e,a,o,n)),o+e+a},kq,Ewe=(t,...e)=>{let[r]=e;if(!bQ(r)||!bQ(r.raw))return e.join(" ");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n{"use strict";var BEt=LB&&LB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(LB,"__esModule",{value:!0});var NB=BEt(FQ()),vEt=/^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/,DEt=/^(ansi|ansi256)\(\s?(\d+)\s?\)$/,RQ=(t,e)=>e==="foreground"?t:"bg"+t[0].toUpperCase()+t.slice(1);LB.default=(t,e,r)=>{if(!e)return t;if(e in NB.default){let a=RQ(e,r);return NB.default[a](t)}if(e.startsWith("#")){let a=RQ("hex",r);return NB.default[a](e)(t)}if(e.startsWith("ansi")){let a=DEt.exec(e);if(!a)return t;let n=RQ(a[1],r),u=Number(a[2]);return NB.default[n](u)(t)}if(e.startsWith("rgb")||e.startsWith("hsl")||e.startsWith("hsv")||e.startsWith("hwb")){let a=vEt.exec(e);if(!a)return t;let n=RQ(a[1],r),u=Number(a[2]),A=Number(a[3]),p=Number(a[4]);return NB.default[n](u,A,p)(t)}return t}});var Iwe=_(MB=>{"use strict";var wwe=MB&&MB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(MB,"__esModule",{value:!0});var PEt=wwe(awe()),Lq=wwe(Nq());MB.default=(t,e,r,o)=>{if(typeof r.style.borderStyle=="string"){let a=r.yogaNode.getComputedWidth(),n=r.yogaNode.getComputedHeight(),u=r.style.borderColor,A=PEt.default[r.style.borderStyle],p=Lq.default(A.topLeft+A.horizontal.repeat(a-2)+A.topRight,u,"foreground"),h=(Lq.default(A.vertical,u,"foreground")+` +`).repeat(n-2),E=Lq.default(A.bottomLeft+A.horizontal.repeat(a-2)+A.bottomRight,u,"foreground");o.write(t,e,p,{transformers:[]}),o.write(t,e+1,h,{transformers:[]}),o.write(t+a-1,e+1,h,{transformers:[]}),o.write(t,e+n-1,E,{transformers:[]})}}});var vwe=_(OB=>{"use strict";var sd=OB&&OB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(OB,"__esModule",{value:!0});var SEt=sd(id()),bEt=sd(Eq()),xEt=sd(nwe()),kEt=sd(Dq()),QEt=sd(iwe()),FEt=sd(Sq()),REt=sd(Iwe()),TEt=(t,e)=>{var r;let o=(r=t.childNodes[0])===null||r===void 0?void 0:r.yogaNode;if(o){let a=o.getComputedLeft(),n=o.getComputedTop();e=` +`.repeat(n)+xEt.default(e,a)}return e},Bwe=(t,e,r)=>{var o;let{offsetX:a=0,offsetY:n=0,transformers:u=[],skipStaticElements:A}=r;if(A&&t.internal_static)return;let{yogaNode:p}=t;if(p){if(p.getDisplay()===SEt.default.DISPLAY_NONE)return;let h=a+p.getComputedLeft(),E=n+p.getComputedTop(),I=u;if(typeof t.internal_transform=="function"&&(I=[t.internal_transform,...u]),t.nodeName==="ink-text"){let D=FEt.default(t);if(D.length>0){let x=bEt.default(D),C=QEt.default(p);if(x>C){let T=(o=t.style.textWrap)!==null&&o!==void 0?o:"wrap";D=kEt.default(D,C,T)}D=TEt(t,D),e.write(h,E,D,{transformers:I})}return}if(t.nodeName==="ink-box"&&REt.default(h,E,t,e),t.nodeName==="ink-root"||t.nodeName==="ink-box")for(let D of t.childNodes)Bwe(D,e,{offsetX:h,offsetY:E,transformers:I,skipStaticElements:A})}};OB.default=Bwe});var Swe=_(UB=>{"use strict";var Pwe=UB&&UB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(UB,"__esModule",{value:!0});var Dwe=Pwe(Bq()),NEt=Pwe(PB()),Mq=class{constructor(e){this.writes=[];let{width:r,height:o}=e;this.width=r,this.height=o}write(e,r,o,a){let{transformers:n}=a;o&&this.writes.push({x:e,y:r,text:o,transformers:n})}get(){let e=[];for(let o=0;oo.trimRight()).join(` +`),height:e.length}}};UB.default=Mq});var kwe=_(_B=>{"use strict";var Oq=_B&&_B.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(_B,"__esModule",{value:!0});var LEt=Oq(id()),bwe=Oq(vwe()),xwe=Oq(Swe());_B.default=(t,e)=>{var r;if(t.yogaNode.setWidth(e),t.yogaNode){t.yogaNode.calculateLayout(void 0,void 0,LEt.default.DIRECTION_LTR);let o=new xwe.default({width:t.yogaNode.getComputedWidth(),height:t.yogaNode.getComputedHeight()});bwe.default(t,o,{skipStaticElements:!0});let a;!((r=t.staticNode)===null||r===void 0)&&r.yogaNode&&(a=new xwe.default({width:t.staticNode.yogaNode.getComputedWidth(),height:t.staticNode.yogaNode.getComputedHeight()}),bwe.default(t.staticNode,a,{skipStaticElements:!1}));let{output:n,height:u}=o.get();return{output:n,outputHeight:u,staticOutput:a?`${a.get().output} +`:""}}return{output:"",outputHeight:0,staticOutput:""}}});var Twe=_((kKt,Rwe)=>{"use strict";var Qwe=ve("stream"),Fwe=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],Uq={},MEt=t=>{let e=new Qwe.PassThrough,r=new Qwe.PassThrough;e.write=a=>t("stdout",a),r.write=a=>t("stderr",a);let o=new console.Console(e,r);for(let a of Fwe)Uq[a]=console[a],console[a]=o[a];return()=>{for(let a of Fwe)console[a]=Uq[a];Uq={}}};Rwe.exports=MEt});var Hq=_(_q=>{"use strict";Object.defineProperty(_q,"__esModule",{value:!0});_q.default=new WeakMap});var jq=_(qq=>{"use strict";Object.defineProperty(qq,"__esModule",{value:!0});var OEt=ln(),Nwe=OEt.createContext({exit:()=>{}});Nwe.displayName="InternalAppContext";qq.default=Nwe});var Yq=_(Gq=>{"use strict";Object.defineProperty(Gq,"__esModule",{value:!0});var UEt=ln(),Lwe=UEt.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});Lwe.displayName="InternalStdinContext";Gq.default=Lwe});var Kq=_(Wq=>{"use strict";Object.defineProperty(Wq,"__esModule",{value:!0});var _Et=ln(),Mwe=_Et.createContext({stdout:void 0,write:()=>{}});Mwe.displayName="InternalStdoutContext";Wq.default=Mwe});var zq=_(Vq=>{"use strict";Object.defineProperty(Vq,"__esModule",{value:!0});var HEt=ln(),Owe=HEt.createContext({stderr:void 0,write:()=>{}});Owe.displayName="InternalStderrContext";Vq.default=Owe});var TQ=_(Jq=>{"use strict";Object.defineProperty(Jq,"__esModule",{value:!0});var qEt=ln(),Uwe=qEt.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{},focus:()=>{}});Uwe.displayName="InternalFocusContext";Jq.default=Uwe});var Hwe=_((MKt,_we)=>{"use strict";var jEt=/[|\\{}()[\]^$+*?.-]/g;_we.exports=t=>{if(typeof t!="string")throw new TypeError("Expected a string");return t.replace(jEt,"\\$&")}});var Ywe=_((OKt,Gwe)=>{"use strict";var GEt=Hwe(),YEt=typeof process=="object"&&process&&typeof process.cwd=="function"?process.cwd():".",jwe=[].concat(ve("module").builtinModules,"bootstrap_node","node").map(t=>new RegExp(`(?:\\((?:node:)?${t}(?:\\.js)?:\\d+:\\d+\\)$|^\\s*at (?:node:)?${t}(?:\\.js)?:\\d+:\\d+$)`));jwe.push(/\((?:node:)?internal\/[^:]+:\d+:\d+\)$/,/\s*at (?:node:)?internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var Xq=class t{constructor(e){e={ignoredPackages:[],...e},"internals"in e||(e.internals=t.nodeInternals()),"cwd"in e||(e.cwd=YEt),this._cwd=e.cwd.replace(/\\/g,"/"),this._internals=[].concat(e.internals,WEt(e.ignoredPackages)),this._wrapCallSite=e.wrapCallSite||!1}static nodeInternals(){return[...jwe]}clean(e,r=0){r=" ".repeat(r),Array.isArray(e)||(e=e.split(` +`)),!/^\s*at /.test(e[0])&&/^\s*at /.test(e[1])&&(e=e.slice(1));let o=!1,a=null,n=[];return e.forEach(u=>{if(u=u.replace(/\\/g,"/"),this._internals.some(p=>p.test(u)))return;let A=/^\s*at /.test(u);o?u=u.trimEnd().replace(/^(\s+)at /,"$1"):(u=u.trim(),A&&(u=u.slice(3))),u=u.replace(`${this._cwd}/`,""),u&&(A?(a&&(n.push(a),a=null),n.push(u)):(o=!0,a=u))}),n.map(u=>`${r}${u} +`).join("")}captureString(e,r=this.captureString){typeof e=="function"&&(r=e,e=1/0);let{stackTraceLimit:o}=Error;e&&(Error.stackTraceLimit=e);let a={};Error.captureStackTrace(a,r);let{stack:n}=a;return Error.stackTraceLimit=o,this.clean(n)}capture(e,r=this.capture){typeof e=="function"&&(r=e,e=1/0);let{prepareStackTrace:o,stackTraceLimit:a}=Error;Error.prepareStackTrace=(A,p)=>this._wrapCallSite?p.map(this._wrapCallSite):p,e&&(Error.stackTraceLimit=e);let n={};Error.captureStackTrace(n,r);let{stack:u}=n;return Object.assign(Error,{prepareStackTrace:o,stackTraceLimit:a}),u}at(e=this.at){let[r]=this.capture(1,e);if(!r)return{};let o={line:r.getLineNumber(),column:r.getColumnNumber()};qwe(o,r.getFileName(),this._cwd),r.isConstructor()&&(o.constructor=!0),r.isEval()&&(o.evalOrigin=r.getEvalOrigin()),r.isNative()&&(o.native=!0);let a;try{a=r.getTypeName()}catch{}a&&a!=="Object"&&a!=="[object Object]"&&(o.type=a);let n=r.getFunctionName();n&&(o.function=n);let u=r.getMethodName();return u&&n!==u&&(o.method=u),o}parseLine(e){let r=e&&e.match(KEt);if(!r)return null;let o=r[1]==="new",a=r[2],n=r[3],u=r[4],A=Number(r[5]),p=Number(r[6]),h=r[7],E=r[8],I=r[9],D=r[10]==="native",x=r[11]===")",C,T={};if(E&&(T.line=Number(E)),I&&(T.column=Number(I)),x&&h){let L=0;for(let U=h.length-1;U>0;U--)if(h.charAt(U)===")")L++;else if(h.charAt(U)==="("&&h.charAt(U-1)===" "&&(L--,L===-1&&h.charAt(U-1)===" ")){let z=h.slice(0,U-1);h=h.slice(U+1),a+=` (${z}`;break}}if(a){let L=a.match(VEt);L&&(a=L[1],C=L[2])}return qwe(T,h,this._cwd),o&&(T.constructor=!0),n&&(T.evalOrigin=n,T.evalLine=A,T.evalColumn=p,T.evalFile=u&&u.replace(/\\/g,"/")),D&&(T.native=!0),a&&(T.function=a),C&&a!==C&&(T.method=C),T}};function qwe(t,e,r){e&&(e=e.replace(/\\/g,"/"),e.startsWith(`${r}/`)&&(e=e.slice(r.length+1)),t.file=e)}function WEt(t){if(t.length===0)return[];let e=t.map(r=>GEt(r));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${e.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var KEt=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),VEt=/^(.*?) \[as (.*?)\]$/;Gwe.exports=Xq});var Kwe=_((UKt,Wwe)=>{"use strict";Wwe.exports=(t,e)=>t.replace(/^\t+/gm,r=>" ".repeat(r.length*(e||2)))});var zwe=_((_Kt,Vwe)=>{"use strict";var zEt=Kwe(),JEt=(t,e)=>{let r=[],o=t-e,a=t+e;for(let n=o;n<=a;n++)r.push(n);return r};Vwe.exports=(t,e,r)=>{if(typeof t!="string")throw new TypeError("Source code is missing.");if(!e||e<1)throw new TypeError("Line number must start from `1`.");if(t=zEt(t).split(/\r?\n/),!(e>t.length))return r={around:3,...r},JEt(e,r.around).filter(o=>t[o-1]!==void 0).map(o=>({line:o,value:t[o-1]}))}});var NQ=_(lu=>{"use strict";var XEt=lu&&lu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ZEt=lu&&lu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),$Et=lu&&lu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&XEt(e,t,r);return ZEt(e,t),e},eCt=lu&&lu.__rest||function(t,e){var r={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(r[o]=t[o]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var a=0,o=Object.getOwnPropertySymbols(t);a{var{children:r}=t,o=eCt(t,["children"]);let a=Object.assign(Object.assign({},o),{marginLeft:o.marginLeft||o.marginX||o.margin||0,marginRight:o.marginRight||o.marginX||o.margin||0,marginTop:o.marginTop||o.marginY||o.margin||0,marginBottom:o.marginBottom||o.marginY||o.margin||0,paddingLeft:o.paddingLeft||o.paddingX||o.padding||0,paddingRight:o.paddingRight||o.paddingX||o.padding||0,paddingTop:o.paddingTop||o.paddingY||o.padding||0,paddingBottom:o.paddingBottom||o.paddingY||o.padding||0});return Jwe.default.createElement("ink-box",{ref:e,style:a},r)});Zq.displayName="Box";Zq.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};lu.default=Zq});var tj=_(HB=>{"use strict";var $q=HB&&HB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(HB,"__esModule",{value:!0});var tCt=$q(ln()),PC=$q(FQ()),Xwe=$q(Nq()),ej=({color:t,backgroundColor:e,dimColor:r,bold:o,italic:a,underline:n,strikethrough:u,inverse:A,wrap:p,children:h})=>{if(h==null)return null;let E=I=>(r&&(I=PC.default.dim(I)),t&&(I=Xwe.default(I,t,"foreground")),e&&(I=Xwe.default(I,e,"background")),o&&(I=PC.default.bold(I)),a&&(I=PC.default.italic(I)),n&&(I=PC.default.underline(I)),u&&(I=PC.default.strikethrough(I)),A&&(I=PC.default.inverse(I)),I);return tCt.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row",textWrap:p},internal_transform:E},h)};ej.displayName="Text";ej.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:"wrap"};HB.default=ej});var tIe=_(cu=>{"use strict";var rCt=cu&&cu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),nCt=cu&&cu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),iCt=cu&&cu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&rCt(e,t,r);return nCt(e,t),e},qB=cu&&cu.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(cu,"__esModule",{value:!0});var Zwe=iCt(ve("fs")),ps=qB(ln()),$we=qB(Ywe()),sCt=qB(zwe()),zf=qB(NQ()),mA=qB(tj()),eIe=new $we.default({cwd:process.cwd(),internals:$we.default.nodeInternals()}),oCt=({error:t})=>{let e=t.stack?t.stack.split(` +`).slice(1):void 0,r=e?eIe.parseLine(e[0]):void 0,o,a=0;if(r?.file&&r?.line&&Zwe.existsSync(r.file)){let n=Zwe.readFileSync(r.file,"utf8");if(o=sCt.default(n,r.line),o)for(let{line:u}of o)a=Math.max(a,String(u).length)}return ps.default.createElement(zf.default,{flexDirection:"column",padding:1},ps.default.createElement(zf.default,null,ps.default.createElement(mA.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),ps.default.createElement(mA.default,null," ",t.message)),r&&ps.default.createElement(zf.default,{marginTop:1},ps.default.createElement(mA.default,{dimColor:!0},r.file,":",r.line,":",r.column)),r&&o&&ps.default.createElement(zf.default,{marginTop:1,flexDirection:"column"},o.map(({line:n,value:u})=>ps.default.createElement(zf.default,{key:n},ps.default.createElement(zf.default,{width:a+1},ps.default.createElement(mA.default,{dimColor:n!==r.line,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0},String(n).padStart(a," "),":")),ps.default.createElement(mA.default,{key:n,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0}," "+u)))),t.stack&&ps.default.createElement(zf.default,{marginTop:1,flexDirection:"column"},t.stack.split(` +`).slice(1).map(n=>{let u=eIe.parseLine(n);return u?ps.default.createElement(zf.default,{key:n},ps.default.createElement(mA.default,{dimColor:!0},"- "),ps.default.createElement(mA.default,{dimColor:!0,bold:!0},u.function),ps.default.createElement(mA.default,{dimColor:!0,color:"gray"}," ","(",u.file,":",u.line,":",u.column,")")):ps.default.createElement(zf.default,{key:n},ps.default.createElement(mA.default,{dimColor:!0},"- "),ps.default.createElement(mA.default,{dimColor:!0,bold:!0},n))})))};cu.default=oCt});var nIe=_(uu=>{"use strict";var aCt=uu&&uu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),lCt=uu&&uu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),cCt=uu&&uu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&aCt(e,t,r);return lCt(e,t),e},ad=uu&&uu.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(uu,"__esModule",{value:!0});var od=cCt(ln()),rIe=ad(Z6()),uCt=ad(jq()),ACt=ad(Yq()),fCt=ad(Kq()),pCt=ad(zq()),hCt=ad(TQ()),gCt=ad(tIe()),dCt=" ",mCt="\x1B[Z",yCt="\x1B",LQ=class extends od.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=e=>{let{stdin:r}=this.props;if(!this.isRawModeSupported())throw r===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(r.setEncoding("utf8"),e){this.rawModeEnabledCount===0&&(r.addListener("data",this.handleInput),r.resume(),r.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(r.setRawMode(!1),r.removeListener("data",this.handleInput),r.pause())},this.handleInput=e=>{e===""&&this.props.exitOnCtrlC&&this.handleExit(),e===yCt&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(e===dCt&&this.focusNext(),e===mCt&&this.focusPrevious())},this.handleExit=e=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(e)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focus=e=>{this.setState(r=>r.focusables.some(a=>a?.id===e)?{activeFocusId:e}:r)},this.focusNext=()=>{this.setState(e=>{var r;let o=(r=e.focusables[0])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findNextFocusable(e)||o}})},this.focusPrevious=()=>{this.setState(e=>{var r;let o=(r=e.focusables[e.focusables.length-1])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findPreviousFocusable(e)||o}})},this.addFocusable=(e,{autoFocus:r})=>{this.setState(o=>{let a=o.activeFocusId;return!a&&r&&(a=e),{activeFocusId:a,focusables:[...o.focusables,{id:e,isActive:!0}]}})},this.removeFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.filter(o=>o.id!==e)}))},this.activateFocusable=e=>{this.setState(r=>({focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!0})}))},this.deactivateFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!1})}))},this.findNextFocusable=e=>{var r;let o=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=o+1;a{var r;let o=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=o-1;a>=0;a--)if(!((r=e.focusables[a])===null||r===void 0)&&r.isActive)return e.focusables[a].id}}static getDerivedStateFromError(e){return{error:e}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return od.default.createElement(uCt.default.Provider,{value:{exit:this.handleExit}},od.default.createElement(ACt.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},od.default.createElement(fCt.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},od.default.createElement(pCt.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},od.default.createElement(hCt.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious,focus:this.focus}},this.state.error?od.default.createElement(gCt.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){rIe.default.hide(this.props.stdout)}componentWillUnmount(){rIe.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(e){this.handleExit(e)}};uu.default=LQ;LQ.displayName="InternalApp"});var oIe=_(Au=>{"use strict";var ECt=Au&&Au.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),CCt=Au&&Au.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),wCt=Au&&Au.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&ECt(e,t,r);return CCt(e,t),e},fu=Au&&Au.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Au,"__esModule",{value:!0});var ICt=fu(ln()),iIe=YO(),BCt=fu(tCe()),vCt=fu(K6()),DCt=fu(aCe()),PCt=fu(cCe()),rj=fu(twe()),SCt=fu(kwe()),bCt=fu(X6()),xCt=fu(Twe()),kCt=wCt(bq()),QCt=fu(Hq()),FCt=fu(nIe()),SC=process.env.CI==="false"?!1:DCt.default,sIe=()=>{},nj=class{constructor(e){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:r,outputHeight:o,staticOutput:a}=SCt.default(this.rootNode,this.options.stdout.columns||80),n=a&&a!==` +`;if(this.options.debug){n&&(this.fullStaticOutput+=a),this.options.stdout.write(this.fullStaticOutput+r);return}if(SC){n&&this.options.stdout.write(a),this.lastOutput=r;return}if(n&&(this.fullStaticOutput+=a),o>=this.options.stdout.rows){this.options.stdout.write(vCt.default.clearTerminal+this.fullStaticOutput+r),this.lastOutput=r;return}n&&(this.log.clear(),this.options.stdout.write(a),this.log(r)),!n&&r!==this.lastOutput&&this.throttledLog(r),this.lastOutput=r},PCt.default(this),this.options=e,this.rootNode=kCt.createNode("ink-root"),this.rootNode.onRender=e.debug?this.onRender:iIe(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=BCt.default.create(e.stdout),this.throttledLog=e.debug?this.log:iIe(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=rj.default.createContainer(this.rootNode,0,!1,null),this.unsubscribeExit=bCt.default(this.unmount,{alwaysLast:!1}),e.patchConsole&&this.patchConsole(),SC||(e.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{e.stdout.off("resize",this.onRender)})}render(e){let r=ICt.default.createElement(FCt.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},e);rj.default.updateContainer(r,this.container,null,sIe)}writeToStdout(e){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(e+this.fullStaticOutput+this.lastOutput);return}if(SC){this.options.stdout.write(e);return}this.log.clear(),this.options.stdout.write(e),this.log(this.lastOutput)}}writeToStderr(e){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(e),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(SC){this.options.stderr.write(e);return}this.log.clear(),this.options.stderr.write(e),this.log(this.lastOutput)}}unmount(e){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),SC?this.options.stdout.write(this.lastOutput+` +`):this.options.debug||this.log.done(),this.isUnmounted=!0,rj.default.updateContainer(null,this.container,null,sIe),QCt.default.delete(this.options.stdout),e instanceof Error?this.rejectExitPromise(e):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((e,r)=>{this.resolveExitPromise=e,this.rejectExitPromise=r})),this.exitPromise}clear(){!SC&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=xCt.default((e,r)=>{e==="stdout"&&this.writeToStdout(r),e==="stderr"&&(r.startsWith("The above error occurred")||this.writeToStderr(r))}))}};Au.default=nj});var lIe=_(jB=>{"use strict";var aIe=jB&&jB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(jB,"__esModule",{value:!0});var RCt=aIe(oIe()),MQ=aIe(Hq()),TCt=ve("stream"),NCt=(t,e)=>{let r=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},LCt(e)),o=MCt(r.stdout,()=>new RCt.default(r));return o.render(t),{rerender:o.render,unmount:()=>o.unmount(),waitUntilExit:o.waitUntilExit,cleanup:()=>MQ.default.delete(r.stdout),clear:o.clear}};jB.default=NCt;var LCt=(t={})=>t instanceof TCt.Stream?{stdout:t,stdin:process.stdin}:t,MCt=(t,e)=>{let r;return MQ.default.has(t)?r=MQ.default.get(t):(r=e(),MQ.default.set(t,r)),r}});var uIe=_(Jf=>{"use strict";var OCt=Jf&&Jf.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),UCt=Jf&&Jf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),_Ct=Jf&&Jf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&OCt(e,t,r);return UCt(e,t),e};Object.defineProperty(Jf,"__esModule",{value:!0});var GB=_Ct(ln()),cIe=t=>{let{items:e,children:r,style:o}=t,[a,n]=GB.useState(0),u=GB.useMemo(()=>e.slice(a),[e,a]);GB.useLayoutEffect(()=>{n(e.length)},[e.length]);let A=u.map((h,E)=>r(h,a+E)),p=GB.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},o),[o]);return GB.default.createElement("ink-box",{internal_static:!0,style:p},A)};cIe.displayName="Static";Jf.default=cIe});var fIe=_(YB=>{"use strict";var HCt=YB&&YB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(YB,"__esModule",{value:!0});var qCt=HCt(ln()),AIe=({children:t,transform:e})=>t==null?null:qCt.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:e},t);AIe.displayName="Transform";YB.default=AIe});var hIe=_(WB=>{"use strict";var jCt=WB&&WB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(WB,"__esModule",{value:!0});var GCt=jCt(ln()),pIe=({count:t=1})=>GCt.default.createElement("ink-text",null,` +`.repeat(t));pIe.displayName="Newline";WB.default=pIe});var mIe=_(KB=>{"use strict";var gIe=KB&&KB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(KB,"__esModule",{value:!0});var YCt=gIe(ln()),WCt=gIe(NQ()),dIe=()=>YCt.default.createElement(WCt.default,{flexGrow:1});dIe.displayName="Spacer";KB.default=dIe});var OQ=_(VB=>{"use strict";var KCt=VB&&VB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(VB,"__esModule",{value:!0});var VCt=ln(),zCt=KCt(Yq()),JCt=()=>VCt.useContext(zCt.default);VB.default=JCt});var EIe=_(zB=>{"use strict";var XCt=zB&&zB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(zB,"__esModule",{value:!0});var yIe=ln(),ZCt=XCt(OQ()),$Ct=(t,e={})=>{let{stdin:r,setRawMode:o,internal_exitOnCtrlC:a}=ZCt.default();yIe.useEffect(()=>{if(e.isActive!==!1)return o(!0),()=>{o(!1)}},[e.isActive,o]),yIe.useEffect(()=>{if(e.isActive===!1)return;let n=u=>{let A=String(u),p={upArrow:A==="\x1B[A",downArrow:A==="\x1B[B",leftArrow:A==="\x1B[D",rightArrow:A==="\x1B[C",pageDown:A==="\x1B[6~",pageUp:A==="\x1B[5~",return:A==="\r",escape:A==="\x1B",ctrl:!1,shift:!1,tab:A===" "||A==="\x1B[Z",backspace:A==="\b",delete:A==="\x7F"||A==="\x1B[3~",meta:!1};A<=""&&!p.return&&(A=String.fromCharCode(A.charCodeAt(0)+97-1),p.ctrl=!0),A.startsWith("\x1B")&&(A=A.slice(1),p.meta=!0);let h=A>="A"&&A<="Z",E=A>="\u0410"&&A<="\u042F";A.length===1&&(h||E)&&(p.shift=!0),p.tab&&A==="[Z"&&(p.shift=!0),(p.tab||p.backspace||p.delete)&&(A=""),(!(A==="c"&&p.ctrl)||!a)&&t(A,p)};return r?.on("data",n),()=>{r?.off("data",n)}},[e.isActive,r,a,t])};zB.default=$Ct});var CIe=_(JB=>{"use strict";var ewt=JB&&JB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(JB,"__esModule",{value:!0});var twt=ln(),rwt=ewt(jq()),nwt=()=>twt.useContext(rwt.default);JB.default=nwt});var wIe=_(XB=>{"use strict";var iwt=XB&&XB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(XB,"__esModule",{value:!0});var swt=ln(),owt=iwt(Kq()),awt=()=>swt.useContext(owt.default);XB.default=awt});var IIe=_(ZB=>{"use strict";var lwt=ZB&&ZB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ZB,"__esModule",{value:!0});var cwt=ln(),uwt=lwt(zq()),Awt=()=>cwt.useContext(uwt.default);ZB.default=Awt});var vIe=_(ev=>{"use strict";var BIe=ev&&ev.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ev,"__esModule",{value:!0});var $B=ln(),fwt=BIe(TQ()),pwt=BIe(OQ()),hwt=({isActive:t=!0,autoFocus:e=!1,id:r}={})=>{let{isRawModeSupported:o,setRawMode:a}=pwt.default(),{activeId:n,add:u,remove:A,activate:p,deactivate:h,focus:E}=$B.useContext(fwt.default),I=$B.useMemo(()=>r??Math.random().toString().slice(2,7),[r]);return $B.useEffect(()=>(u(I,{autoFocus:e}),()=>{A(I)}),[I,e]),$B.useEffect(()=>{t?p(I):h(I)},[t,I]),$B.useEffect(()=>{if(!(!o||!t))return a(!0),()=>{a(!1)}},[t]),{isFocused:!!I&&n===I,focus:E}};ev.default=hwt});var DIe=_(tv=>{"use strict";var gwt=tv&&tv.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(tv,"__esModule",{value:!0});var dwt=ln(),mwt=gwt(TQ()),ywt=()=>{let t=dwt.useContext(mwt.default);return{enableFocus:t.enableFocus,disableFocus:t.disableFocus,focusNext:t.focusNext,focusPrevious:t.focusPrevious,focus:t.focus}};tv.default=ywt});var PIe=_(ij=>{"use strict";Object.defineProperty(ij,"__esModule",{value:!0});ij.default=t=>{var e,r,o,a;return{width:(r=(e=t.yogaNode)===null||e===void 0?void 0:e.getComputedWidth())!==null&&r!==void 0?r:0,height:(a=(o=t.yogaNode)===null||o===void 0?void 0:o.getComputedHeight())!==null&&a!==void 0?a:0}}});var ac=_(zs=>{"use strict";Object.defineProperty(zs,"__esModule",{value:!0});var Ewt=lIe();Object.defineProperty(zs,"render",{enumerable:!0,get:function(){return Ewt.default}});var Cwt=NQ();Object.defineProperty(zs,"Box",{enumerable:!0,get:function(){return Cwt.default}});var wwt=tj();Object.defineProperty(zs,"Text",{enumerable:!0,get:function(){return wwt.default}});var Iwt=uIe();Object.defineProperty(zs,"Static",{enumerable:!0,get:function(){return Iwt.default}});var Bwt=fIe();Object.defineProperty(zs,"Transform",{enumerable:!0,get:function(){return Bwt.default}});var vwt=hIe();Object.defineProperty(zs,"Newline",{enumerable:!0,get:function(){return vwt.default}});var Dwt=mIe();Object.defineProperty(zs,"Spacer",{enumerable:!0,get:function(){return Dwt.default}});var Pwt=EIe();Object.defineProperty(zs,"useInput",{enumerable:!0,get:function(){return Pwt.default}});var Swt=CIe();Object.defineProperty(zs,"useApp",{enumerable:!0,get:function(){return Swt.default}});var bwt=OQ();Object.defineProperty(zs,"useStdin",{enumerable:!0,get:function(){return bwt.default}});var xwt=wIe();Object.defineProperty(zs,"useStdout",{enumerable:!0,get:function(){return xwt.default}});var kwt=IIe();Object.defineProperty(zs,"useStderr",{enumerable:!0,get:function(){return kwt.default}});var Qwt=vIe();Object.defineProperty(zs,"useFocus",{enumerable:!0,get:function(){return Qwt.default}});var Fwt=DIe();Object.defineProperty(zs,"useFocusManager",{enumerable:!0,get:function(){return Fwt.default}});var Rwt=PIe();Object.defineProperty(zs,"measureElement",{enumerable:!0,get:function(){return Rwt.default}})});var oj={};Kt(oj,{Gem:()=>sj});var SIe,ld,sj,UQ=wt(()=>{SIe=et(ac()),ld=et(ln()),sj=(0,ld.memo)(({active:t})=>{let e=(0,ld.useMemo)(()=>t?"\u25C9":"\u25EF",[t]),r=(0,ld.useMemo)(()=>t?"green":"yellow",[t]);return ld.default.createElement(SIe.Text,{color:r},e)})});var xIe={};Kt(xIe,{useKeypress:()=>cd});function cd({active:t},e,r){let{stdin:o}=(0,bIe.useStdin)(),a=(0,_Q.useCallback)((n,u)=>e(n,u),r);(0,_Q.useEffect)(()=>{if(!(!t||!o))return o.on("keypress",a),()=>{o.off("keypress",a)}},[t,a,o])}var bIe,_Q,rv=wt(()=>{bIe=et(ac()),_Q=et(ln())});var QIe={};Kt(QIe,{FocusRequest:()=>kIe,useFocusRequest:()=>aj});var kIe,aj,lj=wt(()=>{rv();kIe=(r=>(r.BEFORE="before",r.AFTER="after",r))(kIe||{}),aj=function({active:t},e,r){cd({active:t},(o,a)=>{a.name==="tab"&&(a.shift?e("before"):e("after"))},r)}});var FIe={};Kt(FIe,{useListInput:()=>nv});var nv,HQ=wt(()=>{rv();nv=function(t,e,{active:r,minus:o,plus:a,set:n,loop:u=!0}){cd({active:r},(A,p)=>{let h=e.indexOf(t);switch(p.name){case o:{let E=h-1;if(u){n(e[(e.length+E)%e.length]);return}if(E<0)return;n(e[E])}break;case a:{let E=h+1;if(u){n(e[E%e.length]);return}if(E>=e.length)return;n(e[E])}break}},[e,t,a,n,u])}});var qQ={};Kt(qQ,{ScrollableItems:()=>Twt});var Hh,Ua,Twt,jQ=wt(()=>{Hh=et(ac()),Ua=et(ln());lj();HQ();Twt=({active:t=!0,children:e=[],radius:r=10,size:o=1,loop:a=!0,onFocusRequest:n,willReachEnd:u})=>{let A=L=>{if(L.key===null)throw new Error("Expected all children to have a key");return L.key},p=Ua.default.Children.map(e,L=>A(L)),h=p[0],[E,I]=(0,Ua.useState)(h),D=p.indexOf(E);(0,Ua.useEffect)(()=>{p.includes(E)||I(h)},[e]),(0,Ua.useEffect)(()=>{u&&D>=p.length-2&&u()},[D]),aj({active:t&&!!n},L=>{n?.(L)},[n]),nv(E,p,{active:t,minus:"up",plus:"down",set:I,loop:a});let x=D-r,C=D+r;C>p.length&&(x-=C-p.length,C=p.length),x<0&&(C+=-x,x=0),C>=p.length&&(C=p.length-1);let T=[];for(let L=x;L<=C;++L){let U=p[L],z=t&&U===E;T.push(Ua.default.createElement(Hh.Box,{key:U,height:o},Ua.default.createElement(Hh.Box,{marginLeft:1,marginRight:1},Ua.default.createElement(Hh.Text,null,z?Ua.default.createElement(Hh.Text,{color:"cyan",bold:!0},">"):" ")),Ua.default.createElement(Hh.Box,null,Ua.default.cloneElement(e[L],{active:z}))))}return Ua.default.createElement(Hh.Box,{flexDirection:"column",width:"100%"},T)}});var RIe,Xf,TIe,cj,NIe,uj=wt(()=>{RIe=et(ac()),Xf=et(ln()),TIe=ve("readline"),cj=Xf.default.createContext(null),NIe=({children:t})=>{let{stdin:e,setRawMode:r}=(0,RIe.useStdin)();(0,Xf.useEffect)(()=>{r&&r(!0),e&&(0,TIe.emitKeypressEvents)(e)},[e,r]);let[o,a]=(0,Xf.useState)(new Map),n=(0,Xf.useMemo)(()=>({getAll:()=>o,get:u=>o.get(u),set:(u,A)=>a(new Map([...o,[u,A]]))}),[o,a]);return Xf.default.createElement(cj.Provider,{value:n,children:t})}});var Aj={};Kt(Aj,{useMinistore:()=>Nwt});function Nwt(t,e){let r=(0,GQ.useContext)(cj);if(r===null)throw new Error("Expected this hook to run with a ministore context attached");if(typeof t>"u")return r.getAll();let o=(0,GQ.useCallback)(n=>{r.set(t,n)},[t,r.set]),a=r.get(t);return typeof a>"u"&&(a=e),[a,o]}var GQ,fj=wt(()=>{GQ=et(ln());uj()});var WQ={};Kt(WQ,{renderForm:()=>Lwt});async function Lwt(t,e,{stdin:r,stdout:o,stderr:a}){let n,u=p=>{let{exit:h}=(0,YQ.useApp)();cd({active:!0},(E,I)=>{I.name==="return"&&(n=p,h())},[h,p])},{waitUntilExit:A}=(0,YQ.render)(pj.default.createElement(NIe,null,pj.default.createElement(t,{...e,useSubmit:u})),{stdin:r,stdout:o,stderr:a});return await A(),n}var YQ,pj,KQ=wt(()=>{YQ=et(ac()),pj=et(ln());uj();rv()});var UIe=_(iv=>{"use strict";Object.defineProperty(iv,"__esModule",{value:!0});iv.UncontrolledTextInput=void 0;var MIe=ln(),hj=ln(),LIe=ac(),ud=FQ(),OIe=({value:t,placeholder:e="",focus:r=!0,mask:o,highlightPastedText:a=!1,showCursor:n=!0,onChange:u,onSubmit:A})=>{let[{cursorOffset:p,cursorWidth:h},E]=hj.useState({cursorOffset:(t||"").length,cursorWidth:0});hj.useEffect(()=>{E(T=>{if(!r||!n)return T;let L=t||"";return T.cursorOffset>L.length-1?{cursorOffset:L.length,cursorWidth:0}:T})},[t,r,n]);let I=a?h:0,D=o?o.repeat(t.length):t,x=D,C=e?ud.grey(e):void 0;if(n&&r){C=e.length>0?ud.inverse(e[0])+ud.grey(e.slice(1)):ud.inverse(" "),x=D.length>0?"":ud.inverse(" ");let T=0;for(let L of D)T>=p-I&&T<=p?x+=ud.inverse(L):x+=L,T++;D.length>0&&p===D.length&&(x+=ud.inverse(" "))}return LIe.useInput((T,L)=>{if(L.upArrow||L.downArrow||L.ctrl&&T==="c"||L.tab||L.shift&&L.tab)return;if(L.return){A&&A(t);return}let U=p,z=t,te=0;L.leftArrow?n&&U--:L.rightArrow?n&&U++:L.backspace||L.delete?p>0&&(z=t.slice(0,p-1)+t.slice(p,t.length),U--):(z=t.slice(0,p)+T+t.slice(p,t.length),U+=T.length,T.length>1&&(te=T.length)),p<0&&(U=0),p>t.length&&(U=t.length),E({cursorOffset:U,cursorWidth:te}),z!==t&&u(z)},{isActive:r}),MIe.createElement(LIe.Text,null,e?D.length>0?x:C:x)};iv.default=OIe;iv.UncontrolledTextInput=({initialValue:t="",...e})=>{let[r,o]=hj.useState(t);return MIe.createElement(OIe,Object.assign({},e,{value:r,onChange:o}))}});var qIe={};Kt(qIe,{Pad:()=>gj});var _Ie,HIe,gj,dj=wt(()=>{_Ie=et(ac()),HIe=et(ln()),gj=({length:t,active:e})=>{if(t===0)return null;let r=t>1?` ${"-".repeat(t-1)}`:" ";return HIe.default.createElement(_Ie.Text,{dimColor:!e},r)}});var jIe={};Kt(jIe,{ItemOptions:()=>Mwt});var ov,qh,Mwt,GIe=wt(()=>{ov=et(ac()),qh=et(ln());HQ();UQ();dj();Mwt=function({active:t,skewer:e,options:r,value:o,onChange:a,sizes:n=[]}){let u=r.filter(({label:p})=>!!p).map(({value:p})=>p),A=r.findIndex(p=>p.value===o&&p.label!="");return nv(o,u,{active:t,minus:"left",plus:"right",set:a}),qh.default.createElement(qh.default.Fragment,null,r.map(({label:p},h)=>{let E=h===A,I=n[h]-1||0,D=p.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),x=Math.max(0,I-D.length-2);return p?qh.default.createElement(ov.Box,{key:p,width:I,marginLeft:1},qh.default.createElement(ov.Text,{wrap:"truncate"},qh.default.createElement(sj,{active:E})," ",p),e?qh.default.createElement(gj,{active:t,length:x}):null):qh.default.createElement(ov.Box,{key:`spacer-${h}`,width:I,marginLeft:1})}))}});var s1e=_((bzt,i1e)=>{var Dj;i1e.exports=()=>(typeof Dj>"u"&&(Dj=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),Dj)});var P1e=_(($zt,D1e)=>{var Tj=Symbol("arg flag"),lc=class t extends Error{constructor(e,r){super(e),this.name="ArgError",this.code=r,Object.setPrototypeOf(this,t.prototype)}};function Iv(t,{argv:e=process.argv.slice(2),permissive:r=!1,stopAtPositional:o=!1}={}){if(!t)throw new lc("argument specification object is required","ARG_CONFIG_NO_SPEC");let a={_:[]},n={},u={};for(let A of Object.keys(t)){if(!A)throw new lc("argument key cannot be an empty string","ARG_CONFIG_EMPTY_KEY");if(A[0]!=="-")throw new lc(`argument key must start with '-' but found: '${A}'`,"ARG_CONFIG_NONOPT_KEY");if(A.length===1)throw new lc(`argument key must have a name; singular '-' keys are not allowed: ${A}`,"ARG_CONFIG_NONAME_KEY");if(typeof t[A]=="string"){n[A]=t[A];continue}let p=t[A],h=!1;if(Array.isArray(p)&&p.length===1&&typeof p[0]=="function"){let[E]=p;p=(I,D,x=[])=>(x.push(E(I,D,x[x.length-1])),x),h=E===Boolean||E[Tj]===!0}else if(typeof p=="function")h=p===Boolean||p[Tj]===!0;else throw new lc(`type missing or not a function or valid array type: ${A}`,"ARG_CONFIG_VAD_TYPE");if(A[1]!=="-"&&A.length>2)throw new lc(`short argument keys (with a single hyphen) must have only one character: ${A}`,"ARG_CONFIG_SHORTOPT_TOOLONG");u[A]=[p,h]}for(let A=0,p=e.length;A0){a._=a._.concat(e.slice(A));break}if(h==="--"){a._=a._.concat(e.slice(A+1));break}if(h.length>1&&h[0]==="-"){let E=h[1]==="-"||h.length===2?[h]:h.slice(1).split("").map(I=>`-${I}`);for(let I=0;I1&&e[A+1][0]==="-"&&!(e[A+1].match(/^-?\d*(\.(?=\d))?\d*$/)&&(L===Number||typeof BigInt<"u"&&L===BigInt))){let z=x===T?"":` (alias for ${T})`;throw new lc(`option requires argument: ${x}${z}`,"ARG_MISSING_REQUIRED_LONGARG")}a[T]=L(e[A+1],T,a[T]),++A}else a[T]=L(C,T,a[T])}}else a._.push(h)}return a}Iv.flag=t=>(t[Tj]=!0,t);Iv.COUNT=Iv.flag((t,e,r)=>(r||0)+1);Iv.ArgError=lc;D1e.exports=Iv});var T1e=_((xJt,R1e)=>{var Oj;R1e.exports=()=>(typeof Oj>"u"&&(Oj=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),Oj)});var U1e=_((Gj,Yj)=>{(function(t){Gj&&typeof Gj=="object"&&typeof Yj<"u"?Yj.exports=t():typeof define=="function"&&define.amd?define([],t):typeof window<"u"?window.isWindows=t():typeof global<"u"?global.isWindows=t():typeof self<"u"?self.isWindows=t():this.isWindows=t()})(function(){"use strict";return function(){return process&&(process.platform==="win32"||/^(msys|cygwin)$/.test(process.env.OSTYPE))}})});var j1e=_((SXt,q1e)=>{"use strict";Wj.ifExists=TIt;var FC=ve("util"),cc=ve("path"),_1e=U1e(),QIt=/^#!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+)(.*)$/,FIt={createPwshFile:!0,createCmdFile:_1e(),fs:ve("fs")},RIt=new Map([[".js","node"],[".cjs","node"],[".mjs","node"],[".cmd","cmd"],[".bat","cmd"],[".ps1","pwsh"],[".sh","sh"]]);function H1e(t){let e={...FIt,...t},r=e.fs;return e.fs_={chmod:r.chmod?FC.promisify(r.chmod):async()=>{},mkdir:FC.promisify(r.mkdir),readFile:FC.promisify(r.readFile),stat:FC.promisify(r.stat),unlink:FC.promisify(r.unlink),writeFile:FC.promisify(r.writeFile)},e}async function Wj(t,e,r){let o=H1e(r);await o.fs_.stat(t),await LIt(t,e,o)}function TIt(t,e,r){return Wj(t,e,r).catch(()=>{})}function NIt(t,e){return e.fs_.unlink(t).catch(()=>{})}async function LIt(t,e,r){let o=await HIt(t,r);return await MIt(e,r),OIt(t,e,o,r)}function MIt(t,e){return e.fs_.mkdir(cc.dirname(t),{recursive:!0})}function OIt(t,e,r,o){let a=H1e(o),n=[{generator:GIt,extension:""}];return a.createCmdFile&&n.push({generator:jIt,extension:".cmd"}),a.createPwshFile&&n.push({generator:YIt,extension:".ps1"}),Promise.all(n.map(u=>qIt(t,e+u.extension,r,u.generator,a)))}function UIt(t,e){return NIt(t,e)}function _It(t,e){return WIt(t,e)}async function HIt(t,e){let a=(await e.fs_.readFile(t,"utf8")).trim().split(/\r*\n/)[0].match(QIt);if(!a){let n=cc.extname(t).toLowerCase();return{program:RIt.get(n)||null,additionalArgs:""}}return{program:a[1],additionalArgs:a[2]}}async function qIt(t,e,r,o,a){let n=a.preserveSymlinks?"--preserve-symlinks":"",u=[r.additionalArgs,n].filter(A=>A).join(" ");return a=Object.assign({},a,{prog:r.program,args:u}),await UIt(e,a),await a.fs_.writeFile(e,o(t,e,a),"utf8"),_It(e,a)}function jIt(t,e,r){let a=cc.relative(cc.dirname(e),t).split("/").join("\\"),n=cc.isAbsolute(a)?`"${a}"`:`"%~dp0\\${a}"`,u,A=r.prog,p=r.args||"",h=Kj(r.nodePath).win32;A?(u=`"%~dp0\\${A}.exe"`,a=n):(A=n,p="",a="");let E=r.progArgs?`${r.progArgs.join(" ")} `:"",I=h?`@SET NODE_PATH=${h}\r +`:"";return u?I+=`@IF EXIST ${u} (\r + ${u} ${p} ${a} ${E}%*\r +) ELSE (\r + @SETLOCAL\r + @SET PATHEXT=%PATHEXT:;.JS;=;%\r + ${A} ${p} ${a} ${E}%*\r +)\r +`:I+=`@${A} ${p} ${a} ${E}%*\r +`,I}function GIt(t,e,r){let o=cc.relative(cc.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n;o=o.split("\\").join("/");let u=cc.isAbsolute(o)?`"${o}"`:`"$basedir/${o}"`,A=r.args||"",p=Kj(r.nodePath).posix;a?(n=`"$basedir/${r.prog}"`,o=u):(a=u,A="",o="");let h=r.progArgs?`${r.progArgs.join(" ")} `:"",E=`#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") + +case \`uname\` in + *CYGWIN*) basedir=\`cygpath -w "$basedir"\`;; +esac + +`,I=r.nodePath?`export NODE_PATH="${p}" +`:"";return n?E+=`${I}if [ -x ${n} ]; then + exec ${n} ${A} ${o} ${h}"$@" +else + exec ${a} ${A} ${o} ${h}"$@" +fi +`:E+=`${I}${a} ${A} ${o} ${h}"$@" +exit $? +`,E}function YIt(t,e,r){let o=cc.relative(cc.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n=a&&`"${a}$exe"`,u;o=o.split("\\").join("/");let A=cc.isAbsolute(o)?`"${o}"`:`"$basedir/${o}"`,p=r.args||"",h=Kj(r.nodePath),E=h.win32,I=h.posix;n?(u=`"$basedir/${r.prog}$exe"`,o=A):(n=A,p="",o="");let D=r.progArgs?`${r.progArgs.join(" ")} `:"",x=`#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +${r.nodePath?`$env_node_path=$env:NODE_PATH +$env:NODE_PATH="${E}" +`:""}if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +}`;return r.nodePath&&(x+=` else { + $env:NODE_PATH="${I}" +}`),u?x+=` +$ret=0 +if (Test-Path ${u}) { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & ${u} ${p} ${o} ${D}$args + } else { + & ${u} ${p} ${o} ${D}$args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & ${n} ${p} ${o} ${D}$args + } else { + & ${n} ${p} ${o} ${D}$args + } + $ret=$LASTEXITCODE +} +${r.nodePath?`$env:NODE_PATH=$env_node_path +`:""}exit $ret +`:x+=` +# Support pipeline input +if ($MyInvocation.ExpectingInput) { + $input | & ${n} ${p} ${o} ${D}$args +} else { + & ${n} ${p} ${o} ${D}$args +} +${r.nodePath?`$env:NODE_PATH=$env_node_path +`:""}exit $LASTEXITCODE +`,x}function WIt(t,e){return e.fs_.chmod(t,493)}function Kj(t){if(!t)return{win32:"",posix:""};let e=typeof t=="string"?t.split(cc.delimiter):Array.from(t),r={};for(let o=0;o`/mnt/${A.toLowerCase()}`):e[o];r.win32=r.win32?`${r.win32};${a}`:a,r.posix=r.posix?`${r.posix}:${n}`:n,r[o]={win32:a,posix:n}}return r}q1e.exports=Wj});var a5=_((VZt,c2e)=>{c2e.exports=ve("stream")});var p2e=_((zZt,f2e)=>{"use strict";function u2e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function E1t(t){for(var e=1;e0?this.tail.next=o:this.head=o,this.tail=o,++this.length}},{key:"unshift",value:function(r){var o={data:r,next:this.head};this.length===0&&(this.tail=o),this.head=o,++this.length}},{key:"shift",value:function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(r){if(this.length===0)return"";for(var o=this.head,a=""+o.data;o=o.next;)a+=r+o.data;return a}},{key:"concat",value:function(r){if(this.length===0)return sF.alloc(0);for(var o=sF.allocUnsafe(r>>>0),a=this.head,n=0;a;)P1t(a.data,o,n),n+=a.data.length,a=a.next;return o}},{key:"consume",value:function(r,o){var a;return ru.length?u.length:r;if(A===u.length?n+=u:n+=u.slice(0,r),r-=A,r===0){A===u.length?(++a,o.next?this.head=o.next:this.head=this.tail=null):(this.head=o,o.data=u.slice(A));break}++a}return this.length-=a,n}},{key:"_getBuffer",value:function(r){var o=sF.allocUnsafe(r),a=this.head,n=1;for(a.data.copy(o),r-=a.data.length;a=a.next;){var u=a.data,A=r>u.length?u.length:r;if(u.copy(o,o.length-r,0,A),r-=A,r===0){A===u.length?(++n,a.next?this.head=a.next:this.head=this.tail=null):(this.head=a,a.data=u.slice(A));break}++n}return this.length-=n,o}},{key:D1t,value:function(r,o){return l5(this,E1t({},o,{depth:0,customInspect:!1}))}}]),t}()});var u5=_((JZt,g2e)=>{"use strict";function S1t(t,e){var r=this,o=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return o||a?(e?e(t):t&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(c5,this,t)):process.nextTick(c5,this,t)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(t||null,function(n){!e&&n?r._writableState?r._writableState.errorEmitted?process.nextTick(oF,r):(r._writableState.errorEmitted=!0,process.nextTick(h2e,r,n)):process.nextTick(h2e,r,n):e?(process.nextTick(oF,r),e(n)):process.nextTick(oF,r)}),this)}function h2e(t,e){c5(t,e),oF(t)}function oF(t){t._writableState&&!t._writableState.emitClose||t._readableState&&!t._readableState.emitClose||t.emit("close")}function b1t(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function c5(t,e){t.emit("error",e)}function x1t(t,e){var r=t._readableState,o=t._writableState;r&&r.autoDestroy||o&&o.autoDestroy?t.destroy(e):t.emit("error",e)}g2e.exports={destroy:S1t,undestroy:b1t,errorOrDestroy:x1t}});var zh=_((XZt,y2e)=>{"use strict";var m2e={};function Ac(t,e,r){r||(r=Error);function o(n,u,A){return typeof e=="string"?e:e(n,u,A)}class a extends r{constructor(u,A,p){super(o(u,A,p))}}a.prototype.name=r.name,a.prototype.code=t,m2e[t]=a}function d2e(t,e){if(Array.isArray(t)){let r=t.length;return t=t.map(o=>String(o)),r>2?`one of ${e} ${t.slice(0,r-1).join(", ")}, or `+t[r-1]:r===2?`one of ${e} ${t[0]} or ${t[1]}`:`of ${e} ${t[0]}`}else return`of ${e} ${String(t)}`}function k1t(t,e,r){return t.substr(!r||r<0?0:+r,e.length)===e}function Q1t(t,e,r){return(r===void 0||r>t.length)&&(r=t.length),t.substring(r-e.length,r)===e}function F1t(t,e,r){return typeof r!="number"&&(r=0),r+e.length>t.length?!1:t.indexOf(e,r)!==-1}Ac("ERR_INVALID_OPT_VALUE",function(t,e){return'The value "'+e+'" is invalid for option "'+t+'"'},TypeError);Ac("ERR_INVALID_ARG_TYPE",function(t,e,r){let o;typeof e=="string"&&k1t(e,"not ")?(o="must not be",e=e.replace(/^not /,"")):o="must be";let a;if(Q1t(t," argument"))a=`The ${t} ${o} ${d2e(e,"type")}`;else{let n=F1t(t,".")?"property":"argument";a=`The "${t}" ${n} ${o} ${d2e(e,"type")}`}return a+=`. Received type ${typeof r}`,a},TypeError);Ac("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF");Ac("ERR_METHOD_NOT_IMPLEMENTED",function(t){return"The "+t+" method is not implemented"});Ac("ERR_STREAM_PREMATURE_CLOSE","Premature close");Ac("ERR_STREAM_DESTROYED",function(t){return"Cannot call "+t+" after a stream was destroyed"});Ac("ERR_MULTIPLE_CALLBACK","Callback called multiple times");Ac("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable");Ac("ERR_STREAM_WRITE_AFTER_END","write after end");Ac("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError);Ac("ERR_UNKNOWN_ENCODING",function(t){return"Unknown encoding: "+t},TypeError);Ac("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event");y2e.exports.codes=m2e});var A5=_((ZZt,E2e)=>{"use strict";var R1t=zh().codes.ERR_INVALID_OPT_VALUE;function T1t(t,e,r){return t.highWaterMark!=null?t.highWaterMark:e?t[r]:null}function N1t(t,e,r,o){var a=T1t(e,o,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var n=o?r:"highWaterMark";throw new R1t(n,a)}return Math.floor(a)}return t.objectMode?16:16*1024}E2e.exports={getHighWaterMark:N1t}});var C2e=_(($Zt,f5)=>{typeof Object.create=="function"?f5.exports=function(e,r){r&&(e.super_=r,e.prototype=Object.create(r.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:f5.exports=function(e,r){if(r){e.super_=r;var o=function(){};o.prototype=r.prototype,e.prototype=new o,e.prototype.constructor=e}}});var Jh=_((e$t,h5)=>{try{if(p5=ve("util"),typeof p5.inherits!="function")throw"";h5.exports=p5.inherits}catch{h5.exports=C2e()}var p5});var I2e=_((t$t,w2e)=>{w2e.exports=ve("util").deprecate});var m5=_((r$t,b2e)=>{"use strict";b2e.exports=Ni;function v2e(t){var e=this;this.next=null,this.entry=null,this.finish=function(){l2t(e,t)}}var MC;Ni.WritableState=Tv;var L1t={deprecate:I2e()},D2e=a5(),lF=ve("buffer").Buffer,M1t=global.Uint8Array||function(){};function O1t(t){return lF.from(t)}function U1t(t){return lF.isBuffer(t)||t instanceof M1t}var d5=u5(),_1t=A5(),H1t=_1t.getHighWaterMark,Xh=zh().codes,q1t=Xh.ERR_INVALID_ARG_TYPE,j1t=Xh.ERR_METHOD_NOT_IMPLEMENTED,G1t=Xh.ERR_MULTIPLE_CALLBACK,Y1t=Xh.ERR_STREAM_CANNOT_PIPE,W1t=Xh.ERR_STREAM_DESTROYED,K1t=Xh.ERR_STREAM_NULL_VALUES,V1t=Xh.ERR_STREAM_WRITE_AFTER_END,z1t=Xh.ERR_UNKNOWN_ENCODING,OC=d5.errorOrDestroy;Jh()(Ni,D2e);function J1t(){}function Tv(t,e,r){MC=MC||dd(),t=t||{},typeof r!="boolean"&&(r=e instanceof MC),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.writableObjectMode),this.highWaterMark=H1t(this,t,"writableHighWaterMark",r),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var o=t.decodeStrings===!1;this.decodeStrings=!o,this.defaultEncoding=t.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(a){n2t(e,a)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new v2e(this)}Tv.prototype.getBuffer=function(){for(var e=this.bufferedRequest,r=[];e;)r.push(e),e=e.next;return r};(function(){try{Object.defineProperty(Tv.prototype,"buffer",{get:L1t.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch{}})();var aF;typeof Symbol=="function"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]=="function"?(aF=Function.prototype[Symbol.hasInstance],Object.defineProperty(Ni,Symbol.hasInstance,{value:function(e){return aF.call(this,e)?!0:this!==Ni?!1:e&&e._writableState instanceof Tv}})):aF=function(e){return e instanceof this};function Ni(t){MC=MC||dd();var e=this instanceof MC;if(!e&&!aF.call(Ni,this))return new Ni(t);this._writableState=new Tv(t,this,e),this.writable=!0,t&&(typeof t.write=="function"&&(this._write=t.write),typeof t.writev=="function"&&(this._writev=t.writev),typeof t.destroy=="function"&&(this._destroy=t.destroy),typeof t.final=="function"&&(this._final=t.final)),D2e.call(this)}Ni.prototype.pipe=function(){OC(this,new Y1t)};function X1t(t,e){var r=new V1t;OC(t,r),process.nextTick(e,r)}function Z1t(t,e,r,o){var a;return r===null?a=new K1t:typeof r!="string"&&!e.objectMode&&(a=new q1t("chunk",["string","Buffer"],r)),a?(OC(t,a),process.nextTick(o,a),!1):!0}Ni.prototype.write=function(t,e,r){var o=this._writableState,a=!1,n=!o.objectMode&&U1t(t);return n&&!lF.isBuffer(t)&&(t=O1t(t)),typeof e=="function"&&(r=e,e=null),n?e="buffer":e||(e=o.defaultEncoding),typeof r!="function"&&(r=J1t),o.ending?X1t(this,r):(n||Z1t(this,o,t,r))&&(o.pendingcb++,a=e2t(this,o,n,t,e,r)),a};Ni.prototype.cork=function(){this._writableState.corked++};Ni.prototype.uncork=function(){var t=this._writableState;t.corked&&(t.corked--,!t.writing&&!t.corked&&!t.bufferProcessing&&t.bufferedRequest&&P2e(this,t))};Ni.prototype.setDefaultEncoding=function(e){if(typeof e=="string"&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new z1t(e);return this._writableState.defaultEncoding=e,this};Object.defineProperty(Ni.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function $1t(t,e,r){return!t.objectMode&&t.decodeStrings!==!1&&typeof e=="string"&&(e=lF.from(e,r)),e}Object.defineProperty(Ni.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function e2t(t,e,r,o,a,n){if(!r){var u=$1t(e,o,a);o!==u&&(r=!0,a="buffer",o=u)}var A=e.objectMode?1:o.length;e.length+=A;var p=e.length{"use strict";var c2t=Object.keys||function(t){var e=[];for(var r in t)e.push(r);return e};k2e.exports=wA;var x2e=C5(),E5=m5();Jh()(wA,x2e);for(y5=c2t(E5.prototype),cF=0;cF{var AF=ve("buffer"),np=AF.Buffer;function Q2e(t,e){for(var r in t)e[r]=t[r]}np.from&&np.alloc&&np.allocUnsafe&&np.allocUnsafeSlow?F2e.exports=AF:(Q2e(AF,w5),w5.Buffer=UC);function UC(t,e,r){return np(t,e,r)}Q2e(np,UC);UC.from=function(t,e,r){if(typeof t=="number")throw new TypeError("Argument must not be a number");return np(t,e,r)};UC.alloc=function(t,e,r){if(typeof t!="number")throw new TypeError("Argument must be a number");var o=np(t);return e!==void 0?typeof r=="string"?o.fill(e,r):o.fill(e):o.fill(0),o};UC.allocUnsafe=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return np(t)};UC.allocUnsafeSlow=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return AF.SlowBuffer(t)}});var v5=_(N2e=>{"use strict";var B5=R2e().Buffer,T2e=B5.isEncoding||function(t){switch(t=""+t,t&&t.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function f2t(t){if(!t)return"utf8";for(var e;;)switch(t){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return t;default:if(e)return;t=(""+t).toLowerCase(),e=!0}}function p2t(t){var e=f2t(t);if(typeof e!="string"&&(B5.isEncoding===T2e||!T2e(t)))throw new Error("Unknown encoding: "+t);return e||t}N2e.StringDecoder=Nv;function Nv(t){this.encoding=p2t(t);var e;switch(this.encoding){case"utf16le":this.text=E2t,this.end=C2t,e=4;break;case"utf8":this.fillLast=d2t,e=4;break;case"base64":this.text=w2t,this.end=I2t,e=3;break;default:this.write=B2t,this.end=v2t;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=B5.allocUnsafe(e)}Nv.prototype.write=function(t){if(t.length===0)return"";var e,r;if(this.lastNeed){if(e=this.fillLast(t),e===void 0)return"";r=this.lastNeed,this.lastNeed=0}else r=0;return r>5===6?2:t>>4===14?3:t>>3===30?4:t>>6===2?-1:-2}function h2t(t,e,r){var o=e.length-1;if(o=0?(a>0&&(t.lastNeed=a-1),a):--o=0?(a>0&&(t.lastNeed=a-2),a):--o=0?(a>0&&(a===2?a=0:t.lastNeed=a-3),a):0))}function g2t(t,e,r){if((e[0]&192)!==128)return t.lastNeed=0,"\uFFFD";if(t.lastNeed>1&&e.length>1){if((e[1]&192)!==128)return t.lastNeed=1,"\uFFFD";if(t.lastNeed>2&&e.length>2&&(e[2]&192)!==128)return t.lastNeed=2,"\uFFFD"}}function d2t(t){var e=this.lastTotal-this.lastNeed,r=g2t(this,t,e);if(r!==void 0)return r;if(this.lastNeed<=t.length)return t.copy(this.lastChar,e,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,e,0,t.length),this.lastNeed-=t.length}function m2t(t,e){var r=h2t(this,t,e);if(!this.lastNeed)return t.toString("utf8",e);this.lastTotal=r;var o=t.length-(r-this.lastNeed);return t.copy(this.lastChar,0,o),t.toString("utf8",e,o)}function y2t(t){var e=t&&t.length?this.write(t):"";return this.lastNeed?e+"\uFFFD":e}function E2t(t,e){if((t.length-e)%2===0){var r=t.toString("utf16le",e);if(r){var o=r.charCodeAt(r.length-1);if(o>=55296&&o<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=t[t.length-1],t.toString("utf16le",e,t.length-1)}function C2t(t){var e=t&&t.length?this.write(t):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return e+this.lastChar.toString("utf16le",0,r)}return e}function w2t(t,e){var r=(t.length-e)%3;return r===0?t.toString("base64",e):(this.lastNeed=3-r,this.lastTotal=3,r===1?this.lastChar[0]=t[t.length-1]:(this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1]),t.toString("base64",e,t.length-r))}function I2t(t){var e=t&&t.length?this.write(t):"";return this.lastNeed?e+this.lastChar.toString("base64",0,3-this.lastNeed):e}function B2t(t){return t.toString(this.encoding)}function v2t(t){return t&&t.length?this.write(t):""}});var fF=_((s$t,O2e)=>{"use strict";var L2e=zh().codes.ERR_STREAM_PREMATURE_CLOSE;function D2t(t){var e=!1;return function(){if(!e){e=!0;for(var r=arguments.length,o=new Array(r),a=0;a{"use strict";var pF;function Zh(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var b2t=fF(),$h=Symbol("lastResolve"),md=Symbol("lastReject"),Lv=Symbol("error"),hF=Symbol("ended"),yd=Symbol("lastPromise"),D5=Symbol("handlePromise"),Ed=Symbol("stream");function e0(t,e){return{value:t,done:e}}function x2t(t){var e=t[$h];if(e!==null){var r=t[Ed].read();r!==null&&(t[yd]=null,t[$h]=null,t[md]=null,e(e0(r,!1)))}}function k2t(t){process.nextTick(x2t,t)}function Q2t(t,e){return function(r,o){t.then(function(){if(e[hF]){r(e0(void 0,!0));return}e[D5](r,o)},o)}}var F2t=Object.getPrototypeOf(function(){}),R2t=Object.setPrototypeOf((pF={get stream(){return this[Ed]},next:function(){var e=this,r=this[Lv];if(r!==null)return Promise.reject(r);if(this[hF])return Promise.resolve(e0(void 0,!0));if(this[Ed].destroyed)return new Promise(function(u,A){process.nextTick(function(){e[Lv]?A(e[Lv]):u(e0(void 0,!0))})});var o=this[yd],a;if(o)a=new Promise(Q2t(o,this));else{var n=this[Ed].read();if(n!==null)return Promise.resolve(e0(n,!1));a=new Promise(this[D5])}return this[yd]=a,a}},Zh(pF,Symbol.asyncIterator,function(){return this}),Zh(pF,"return",function(){var e=this;return new Promise(function(r,o){e[Ed].destroy(null,function(a){if(a){o(a);return}r(e0(void 0,!0))})})}),pF),F2t),T2t=function(e){var r,o=Object.create(R2t,(r={},Zh(r,Ed,{value:e,writable:!0}),Zh(r,$h,{value:null,writable:!0}),Zh(r,md,{value:null,writable:!0}),Zh(r,Lv,{value:null,writable:!0}),Zh(r,hF,{value:e._readableState.endEmitted,writable:!0}),Zh(r,D5,{value:function(n,u){var A=o[Ed].read();A?(o[yd]=null,o[$h]=null,o[md]=null,n(e0(A,!1))):(o[$h]=n,o[md]=u)},writable:!0}),r));return o[yd]=null,b2t(e,function(a){if(a&&a.code!=="ERR_STREAM_PREMATURE_CLOSE"){var n=o[md];n!==null&&(o[yd]=null,o[$h]=null,o[md]=null,n(a)),o[Lv]=a;return}var u=o[$h];u!==null&&(o[yd]=null,o[$h]=null,o[md]=null,u(e0(void 0,!0))),o[hF]=!0}),e.on("readable",k2t.bind(null,o)),o};U2e.exports=T2t});var G2e=_((a$t,j2e)=>{"use strict";function H2e(t,e,r,o,a,n,u){try{var A=t[n](u),p=A.value}catch(h){r(h);return}A.done?e(p):Promise.resolve(p).then(o,a)}function N2t(t){return function(){var e=this,r=arguments;return new Promise(function(o,a){var n=t.apply(e,r);function u(p){H2e(n,o,a,u,A,"next",p)}function A(p){H2e(n,o,a,u,A,"throw",p)}u(void 0)})}}function q2e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function L2t(t){for(var e=1;e{"use strict";eBe.exports=In;var _C;In.ReadableState=V2e;var l$t=ve("events").EventEmitter,K2e=function(e,r){return e.listeners(r).length},Ov=a5(),gF=ve("buffer").Buffer,_2t=global.Uint8Array||function(){};function H2t(t){return gF.from(t)}function q2t(t){return gF.isBuffer(t)||t instanceof _2t}var P5=ve("util"),tn;P5&&P5.debuglog?tn=P5.debuglog("stream"):tn=function(){};var j2t=p2e(),R5=u5(),G2t=A5(),Y2t=G2t.getHighWaterMark,dF=zh().codes,W2t=dF.ERR_INVALID_ARG_TYPE,K2t=dF.ERR_STREAM_PUSH_AFTER_EOF,V2t=dF.ERR_METHOD_NOT_IMPLEMENTED,z2t=dF.ERR_STREAM_UNSHIFT_AFTER_END_EVENT,HC,S5,b5;Jh()(In,Ov);var Mv=R5.errorOrDestroy,x5=["error","close","destroy","pause","resume"];function J2t(t,e,r){if(typeof t.prependListener=="function")return t.prependListener(e,r);!t._events||!t._events[e]?t.on(e,r):Array.isArray(t._events[e])?t._events[e].unshift(r):t._events[e]=[r,t._events[e]]}function V2e(t,e,r){_C=_C||dd(),t=t||{},typeof r!="boolean"&&(r=e instanceof _C),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.readableObjectMode),this.highWaterMark=Y2t(this,t,"readableHighWaterMark",r),this.buffer=new j2t,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.destroyed=!1,this.defaultEncoding=t.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(HC||(HC=v5().StringDecoder),this.decoder=new HC(t.encoding),this.encoding=t.encoding)}function In(t){if(_C=_C||dd(),!(this instanceof In))return new In(t);var e=this instanceof _C;this._readableState=new V2e(t,this,e),this.readable=!0,t&&(typeof t.read=="function"&&(this._read=t.read),typeof t.destroy=="function"&&(this._destroy=t.destroy)),Ov.call(this)}Object.defineProperty(In.prototype,"destroyed",{enumerable:!1,get:function(){return this._readableState===void 0?!1:this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}});In.prototype.destroy=R5.destroy;In.prototype._undestroy=R5.undestroy;In.prototype._destroy=function(t,e){e(t)};In.prototype.push=function(t,e){var r=this._readableState,o;return r.objectMode?o=!0:typeof t=="string"&&(e=e||r.defaultEncoding,e!==r.encoding&&(t=gF.from(t,e),e=""),o=!0),z2e(this,t,e,!1,o)};In.prototype.unshift=function(t){return z2e(this,t,null,!0,!1)};function z2e(t,e,r,o,a){tn("readableAddChunk",e);var n=t._readableState;if(e===null)n.reading=!1,$2t(t,n);else{var u;if(a||(u=X2t(n,e)),u)Mv(t,u);else if(n.objectMode||e&&e.length>0)if(typeof e!="string"&&!n.objectMode&&Object.getPrototypeOf(e)!==gF.prototype&&(e=H2t(e)),o)n.endEmitted?Mv(t,new z2t):k5(t,n,e,!0);else if(n.ended)Mv(t,new K2t);else{if(n.destroyed)return!1;n.reading=!1,n.decoder&&!r?(e=n.decoder.write(e),n.objectMode||e.length!==0?k5(t,n,e,!1):F5(t,n)):k5(t,n,e,!1)}else o||(n.reading=!1,F5(t,n))}return!n.ended&&(n.length=Y2e?t=Y2e:(t--,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,t|=t>>>16,t++),t}function W2e(t,e){return t<=0||e.length===0&&e.ended?0:e.objectMode?1:t!==t?e.flowing&&e.length?e.buffer.head.data.length:e.length:(t>e.highWaterMark&&(e.highWaterMark=Z2t(t)),t<=e.length?t:e.ended?e.length:(e.needReadable=!0,0))}In.prototype.read=function(t){tn("read",t),t=parseInt(t,10);var e=this._readableState,r=t;if(t!==0&&(e.emittedReadable=!1),t===0&&e.needReadable&&((e.highWaterMark!==0?e.length>=e.highWaterMark:e.length>0)||e.ended))return tn("read: emitReadable",e.length,e.ended),e.length===0&&e.ended?Q5(this):mF(this),null;if(t=W2e(t,e),t===0&&e.ended)return e.length===0&&Q5(this),null;var o=e.needReadable;tn("need readable",o),(e.length===0||e.length-t0?a=Z2e(t,e):a=null,a===null?(e.needReadable=e.length<=e.highWaterMark,t=0):(e.length-=t,e.awaitDrain=0),e.length===0&&(e.ended||(e.needReadable=!0),r!==t&&e.ended&&Q5(this)),a!==null&&this.emit("data",a),a};function $2t(t,e){if(tn("onEofChunk"),!e.ended){if(e.decoder){var r=e.decoder.end();r&&r.length&&(e.buffer.push(r),e.length+=e.objectMode?1:r.length)}e.ended=!0,e.sync?mF(t):(e.needReadable=!1,e.emittedReadable||(e.emittedReadable=!0,J2e(t)))}}function mF(t){var e=t._readableState;tn("emitReadable",e.needReadable,e.emittedReadable),e.needReadable=!1,e.emittedReadable||(tn("emitReadable",e.flowing),e.emittedReadable=!0,process.nextTick(J2e,t))}function J2e(t){var e=t._readableState;tn("emitReadable_",e.destroyed,e.length,e.ended),!e.destroyed&&(e.length||e.ended)&&(t.emit("readable"),e.emittedReadable=!1),e.needReadable=!e.flowing&&!e.ended&&e.length<=e.highWaterMark,T5(t)}function F5(t,e){e.readingMore||(e.readingMore=!0,process.nextTick(eBt,t,e))}function eBt(t,e){for(;!e.reading&&!e.ended&&(e.length1&&$2e(o.pipes,t)!==-1)&&!h&&(tn("false write response, pause",o.awaitDrain),o.awaitDrain++),r.pause())}function D(L){tn("onerror",L),T(),t.removeListener("error",D),K2e(t,"error")===0&&Mv(t,L)}J2t(t,"error",D);function x(){t.removeListener("finish",C),T()}t.once("close",x);function C(){tn("onfinish"),t.removeListener("close",x),T()}t.once("finish",C);function T(){tn("unpipe"),r.unpipe(t)}return t.emit("pipe",r),o.flowing||(tn("pipe resume"),r.resume()),t};function tBt(t){return function(){var r=t._readableState;tn("pipeOnDrain",r.awaitDrain),r.awaitDrain&&r.awaitDrain--,r.awaitDrain===0&&K2e(t,"data")&&(r.flowing=!0,T5(t))}}In.prototype.unpipe=function(t){var e=this._readableState,r={hasUnpiped:!1};if(e.pipesCount===0)return this;if(e.pipesCount===1)return t&&t!==e.pipes?this:(t||(t=e.pipes),e.pipes=null,e.pipesCount=0,e.flowing=!1,t&&t.emit("unpipe",this,r),this);if(!t){var o=e.pipes,a=e.pipesCount;e.pipes=null,e.pipesCount=0,e.flowing=!1;for(var n=0;n0,o.flowing!==!1&&this.resume()):t==="readable"&&!o.endEmitted&&!o.readableListening&&(o.readableListening=o.needReadable=!0,o.flowing=!1,o.emittedReadable=!1,tn("on readable",o.length,o.reading),o.length?mF(this):o.reading||process.nextTick(rBt,this)),r};In.prototype.addListener=In.prototype.on;In.prototype.removeListener=function(t,e){var r=Ov.prototype.removeListener.call(this,t,e);return t==="readable"&&process.nextTick(X2e,this),r};In.prototype.removeAllListeners=function(t){var e=Ov.prototype.removeAllListeners.apply(this,arguments);return(t==="readable"||t===void 0)&&process.nextTick(X2e,this),e};function X2e(t){var e=t._readableState;e.readableListening=t.listenerCount("readable")>0,e.resumeScheduled&&!e.paused?e.flowing=!0:t.listenerCount("data")>0&&t.resume()}function rBt(t){tn("readable nexttick read 0"),t.read(0)}In.prototype.resume=function(){var t=this._readableState;return t.flowing||(tn("resume"),t.flowing=!t.readableListening,nBt(this,t)),t.paused=!1,this};function nBt(t,e){e.resumeScheduled||(e.resumeScheduled=!0,process.nextTick(iBt,t,e))}function iBt(t,e){tn("resume",e.reading),e.reading||t.read(0),e.resumeScheduled=!1,t.emit("resume"),T5(t),e.flowing&&!e.reading&&t.read(0)}In.prototype.pause=function(){return tn("call pause flowing=%j",this._readableState.flowing),this._readableState.flowing!==!1&&(tn("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState.paused=!0,this};function T5(t){var e=t._readableState;for(tn("flow",e.flowing);e.flowing&&t.read()!==null;);}In.prototype.wrap=function(t){var e=this,r=this._readableState,o=!1;t.on("end",function(){if(tn("wrapped end"),r.decoder&&!r.ended){var u=r.decoder.end();u&&u.length&&e.push(u)}e.push(null)}),t.on("data",function(u){if(tn("wrapped data"),r.decoder&&(u=r.decoder.write(u)),!(r.objectMode&&u==null)&&!(!r.objectMode&&(!u||!u.length))){var A=e.push(u);A||(o=!0,t.pause())}});for(var a in t)this[a]===void 0&&typeof t[a]=="function"&&(this[a]=function(A){return function(){return t[A].apply(t,arguments)}}(a));for(var n=0;n=e.length?(e.decoder?r=e.buffer.join(""):e.buffer.length===1?r=e.buffer.first():r=e.buffer.concat(e.length),e.buffer.clear()):r=e.buffer.consume(t,e.decoder),r}function Q5(t){var e=t._readableState;tn("endReadable",e.endEmitted),e.endEmitted||(e.ended=!0,process.nextTick(sBt,e,t))}function sBt(t,e){if(tn("endReadableNT",t.endEmitted,t.length),!t.endEmitted&&t.length===0&&(t.endEmitted=!0,e.readable=!1,e.emit("end"),t.autoDestroy)){var r=e._writableState;(!r||r.autoDestroy&&r.finished)&&e.destroy()}}typeof Symbol=="function"&&(In.from=function(t,e){return b5===void 0&&(b5=G2e()),b5(In,t,e)});function $2e(t,e){for(var r=0,o=t.length;r{"use strict";rBe.exports=ip;var yF=zh().codes,oBt=yF.ERR_METHOD_NOT_IMPLEMENTED,aBt=yF.ERR_MULTIPLE_CALLBACK,lBt=yF.ERR_TRANSFORM_ALREADY_TRANSFORMING,cBt=yF.ERR_TRANSFORM_WITH_LENGTH_0,EF=dd();Jh()(ip,EF);function uBt(t,e){var r=this._transformState;r.transforming=!1;var o=r.writecb;if(o===null)return this.emit("error",new aBt);r.writechunk=null,r.writecb=null,e!=null&&this.push(e),o(t);var a=this._readableState;a.reading=!1,(a.needReadable||a.length{"use strict";iBe.exports=Uv;var nBe=N5();Jh()(Uv,nBe);function Uv(t){if(!(this instanceof Uv))return new Uv(t);nBe.call(this,t)}Uv.prototype._transform=function(t,e,r){r(null,t)}});var uBe=_((f$t,cBe)=>{"use strict";var L5;function fBt(t){var e=!1;return function(){e||(e=!0,t.apply(void 0,arguments))}}var lBe=zh().codes,pBt=lBe.ERR_MISSING_ARGS,hBt=lBe.ERR_STREAM_DESTROYED;function oBe(t){if(t)throw t}function gBt(t){return t.setHeader&&typeof t.abort=="function"}function dBt(t,e,r,o){o=fBt(o);var a=!1;t.on("close",function(){a=!0}),L5===void 0&&(L5=fF()),L5(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,gBt(t))return t.abort();if(typeof t.destroy=="function")return t.destroy();o(u||new hBt("pipe"))}}}function aBe(t){t()}function mBt(t,e){return t.pipe(e)}function yBt(t){return!t.length||typeof t[t.length-1]!="function"?oBe:t.pop()}function EBt(){for(var t=arguments.length,e=new Array(t),r=0;r0;return dBt(u,p,h,function(E){a||(a=E),E&&n.forEach(aBe),!p&&(n.forEach(aBe),o(a))})});return e.reduce(mBt)}cBe.exports=EBt});var qC=_((fc,Hv)=>{var _v=ve("stream");process.env.READABLE_STREAM==="disable"&&_v?(Hv.exports=_v.Readable,Object.assign(Hv.exports,_v),Hv.exports.Stream=_v):(fc=Hv.exports=C5(),fc.Stream=_v||fc,fc.Readable=fc,fc.Writable=m5(),fc.Duplex=dd(),fc.Transform=N5(),fc.PassThrough=sBe(),fc.finished=fF(),fc.pipeline=uBe())});var pBe=_((p$t,fBe)=>{"use strict";var{Buffer:hu}=ve("buffer"),ABe=Symbol.for("BufferList");function fi(t){if(!(this instanceof fi))return new fi(t);fi._init.call(this,t)}fi._init=function(e){Object.defineProperty(this,ABe,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e)};fi.prototype._new=function(e){return new fi(e)};fi.prototype._offset=function(e){if(e===0)return[0,0];let r=0;for(let o=0;othis.length||e<0)return;let r=this._offset(e);return this._bufs[r[0]][r[1]]};fi.prototype.slice=function(e,r){return typeof e=="number"&&e<0&&(e+=this.length),typeof r=="number"&&r<0&&(r+=this.length),this.copy(null,0,e,r)};fi.prototype.copy=function(e,r,o,a){if((typeof o!="number"||o<0)&&(o=0),(typeof a!="number"||a>this.length)&&(a=this.length),o>=this.length||a<=0)return e||hu.alloc(0);let n=!!e,u=this._offset(o),A=a-o,p=A,h=n&&r||0,E=u[1];if(o===0&&a===this.length){if(!n)return this._bufs.length===1?this._bufs[0]:hu.concat(this._bufs,this.length);for(let I=0;ID)this._bufs[I].copy(e,h,E),h+=D;else{this._bufs[I].copy(e,h,E,E+p),h+=D;break}p-=D,E&&(E=0)}return e.length>h?e.slice(0,h):e};fi.prototype.shallowSlice=function(e,r){if(e=e||0,r=typeof r!="number"?this.length:r,e<0&&(e+=this.length),r<0&&(r+=this.length),e===r)return this._new();let o=this._offset(e),a=this._offset(r),n=this._bufs.slice(o[0],a[0]+1);return a[1]===0?n.pop():n[n.length-1]=n[n.length-1].slice(0,a[1]),o[1]!==0&&(n[0]=n[0].slice(o[1])),this._new(n)};fi.prototype.toString=function(e,r,o){return this.slice(r,o).toString(e)};fi.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;)if(e>=this._bufs[0].length)e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift();else{this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}return this};fi.prototype.duplicate=function(){let e=this._new();for(let r=0;rthis.length?this.length:e;let o=this._offset(e),a=o[0],n=o[1];for(;a=t.length){let p=u.indexOf(t,n);if(p!==-1)return this._reverseOffset([a,p]);n=u.length-t.length+1}else{let p=this._reverseOffset([a,n]);if(this._match(p,t))return p;n++}n=0}return-1};fi.prototype._match=function(t,e){if(this.length-t{"use strict";var M5=qC().Duplex,CBt=Jh(),qv=pBe();function Fo(t){if(!(this instanceof Fo))return new Fo(t);if(typeof t=="function"){this._callback=t;let e=function(o){this._callback&&(this._callback(o),this._callback=null)}.bind(this);this.on("pipe",function(o){o.on("error",e)}),this.on("unpipe",function(o){o.removeListener("error",e)}),t=null}qv._init.call(this,t),M5.call(this)}CBt(Fo,M5);Object.assign(Fo.prototype,qv.prototype);Fo.prototype._new=function(e){return new Fo(e)};Fo.prototype._write=function(e,r,o){this._appendBuffer(e),typeof o=="function"&&o()};Fo.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)};Fo.prototype.end=function(e){M5.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)};Fo.prototype._destroy=function(e,r){this._bufs.length=0,this.length=0,r(e)};Fo.prototype._isBufferList=function(e){return e instanceof Fo||e instanceof qv||Fo.isBufferList(e)};Fo.isBufferList=qv.isBufferList;CF.exports=Fo;CF.exports.BufferListStream=Fo;CF.exports.BufferList=qv});var _5=_(GC=>{var wBt=Buffer.alloc,IBt="0000000000000000000",BBt="7777777777777777777",gBe=48,dBe=Buffer.from("ustar\0","binary"),vBt=Buffer.from("00","binary"),DBt=Buffer.from("ustar ","binary"),PBt=Buffer.from(" \0","binary"),SBt=parseInt("7777",8),jv=257,U5=263,bBt=function(t,e,r){return typeof t!="number"?r:(t=~~t,t>=e?e:t>=0||(t+=e,t>=0)?t:0)},xBt=function(t){switch(t){case 0:return"file";case 1:return"link";case 2:return"symlink";case 3:return"character-device";case 4:return"block-device";case 5:return"directory";case 6:return"fifo";case 7:return"contiguous-file";case 72:return"pax-header";case 55:return"pax-global-header";case 27:return"gnu-long-link-path";case 28:case 30:return"gnu-long-path"}return null},kBt=function(t){switch(t){case"file":return 0;case"link":return 1;case"symlink":return 2;case"character-device":return 3;case"block-device":return 4;case"directory":return 5;case"fifo":return 6;case"contiguous-file":return 7;case"pax-header":return 72}return 0},mBe=function(t,e,r,o){for(;re?BBt.slice(0,e)+" ":IBt.slice(0,e-t.length)+t+" "};function QBt(t){var e;if(t[0]===128)e=!0;else if(t[0]===255)e=!1;else return null;for(var r=[],o=t.length-1;o>0;o--){var a=t[o];e?r.push(a):r.push(255-a)}var n=0,u=r.length;for(o=0;o=Math.pow(10,r)&&r++,e+r+t};GC.decodeLongPath=function(t,e){return jC(t,0,t.length,e)};GC.encodePax=function(t){var e="";t.name&&(e+=O5(" path="+t.name+` +`)),t.linkname&&(e+=O5(" linkpath="+t.linkname+` +`));var r=t.pax;if(r)for(var o in r)e+=O5(" "+o+"="+r[o]+` +`);return Buffer.from(e)};GC.decodePax=function(t){for(var e={};t.length;){for(var r=0;r100;){var a=r.indexOf("/");if(a===-1)return null;o+=o?"/"+r.slice(0,a):r.slice(0,a),r=r.slice(a+1)}return Buffer.byteLength(r)>100||Buffer.byteLength(o)>155||t.linkname&&Buffer.byteLength(t.linkname)>100?null:(e.write(r),e.write(t0(t.mode&SBt,6),100),e.write(t0(t.uid,6),108),e.write(t0(t.gid,6),116),e.write(t0(t.size,11),124),e.write(t0(t.mtime.getTime()/1e3|0,11),136),e[156]=gBe+kBt(t.type),t.linkname&&e.write(t.linkname,157),dBe.copy(e,jv),vBt.copy(e,U5),t.uname&&e.write(t.uname,265),t.gname&&e.write(t.gname,297),e.write(t0(t.devmajor||0,6),329),e.write(t0(t.devminor||0,6),337),o&&e.write(o,345),e.write(t0(yBe(e),6),148),e)};GC.decode=function(t,e,r){var o=t[156]===0?0:t[156]-gBe,a=jC(t,0,100,e),n=r0(t,100,8),u=r0(t,108,8),A=r0(t,116,8),p=r0(t,124,12),h=r0(t,136,12),E=xBt(o),I=t[157]===0?null:jC(t,157,100,e),D=jC(t,265,32),x=jC(t,297,32),C=r0(t,329,8),T=r0(t,337,8),L=yBe(t);if(L===8*32)return null;if(L!==r0(t,148,8))throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");if(dBe.compare(t,jv,jv+6)===0)t[345]&&(a=jC(t,345,155,e)+"/"+a);else if(!(DBt.compare(t,jv,jv+6)===0&&PBt.compare(t,U5,U5+2)===0)){if(!r)throw new Error("Invalid tar header: unknown format.")}return o===0&&a&&a[a.length-1]==="/"&&(o=5),{name:a,mode:n,uid:u,gid:A,size:p,mtime:new Date(1e3*h),type:E,linkname:I,uname:D,gname:x,devmajor:C,devminor:T}}});var DBe=_((d$t,vBe)=>{var CBe=ve("util"),FBt=hBe(),Gv=_5(),wBe=qC().Writable,IBe=qC().PassThrough,BBe=function(){},EBe=function(t){return t&=511,t&&512-t},RBt=function(t,e){var r=new wF(t,e);return r.end(),r},TBt=function(t,e){return e.path&&(t.name=e.path),e.linkpath&&(t.linkname=e.linkpath),e.size&&(t.size=parseInt(e.size,10)),t.pax=e,t},wF=function(t,e){this._parent=t,this.offset=e,IBe.call(this,{autoDestroy:!1})};CBe.inherits(wF,IBe);wF.prototype.destroy=function(t){this._parent.destroy(t)};var sp=function(t){if(!(this instanceof sp))return new sp(t);wBe.call(this,t),t=t||{},this._offset=0,this._buffer=FBt(),this._missing=0,this._partial=!1,this._onparse=BBe,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var e=this,r=e._buffer,o=function(){e._continue()},a=function(D){if(e._locked=!1,D)return e.destroy(D);e._stream||o()},n=function(){e._stream=null;var D=EBe(e._header.size);D?e._parse(D,u):e._parse(512,I),e._locked||o()},u=function(){e._buffer.consume(EBe(e._header.size)),e._parse(512,I),o()},A=function(){var D=e._header.size;e._paxGlobal=Gv.decodePax(r.slice(0,D)),r.consume(D),n()},p=function(){var D=e._header.size;e._pax=Gv.decodePax(r.slice(0,D)),e._paxGlobal&&(e._pax=Object.assign({},e._paxGlobal,e._pax)),r.consume(D),n()},h=function(){var D=e._header.size;this._gnuLongPath=Gv.decodeLongPath(r.slice(0,D),t.filenameEncoding),r.consume(D),n()},E=function(){var D=e._header.size;this._gnuLongLinkPath=Gv.decodeLongPath(r.slice(0,D),t.filenameEncoding),r.consume(D),n()},I=function(){var D=e._offset,x;try{x=e._header=Gv.decode(r.slice(0,512),t.filenameEncoding,t.allowUnknownFormat)}catch(C){e.emit("error",C)}if(r.consume(512),!x){e._parse(512,I),o();return}if(x.type==="gnu-long-path"){e._parse(x.size,h),o();return}if(x.type==="gnu-long-link-path"){e._parse(x.size,E),o();return}if(x.type==="pax-global-header"){e._parse(x.size,A),o();return}if(x.type==="pax-header"){e._parse(x.size,p),o();return}if(e._gnuLongPath&&(x.name=e._gnuLongPath,e._gnuLongPath=null),e._gnuLongLinkPath&&(x.linkname=e._gnuLongLinkPath,e._gnuLongLinkPath=null),e._pax&&(e._header=x=TBt(x,e._pax),e._pax=null),e._locked=!0,!x.size||x.type==="directory"){e._parse(512,I),e.emit("entry",x,RBt(e,D),a);return}e._stream=new wF(e,D),e.emit("entry",x,e._stream,a),e._parse(x.size,n),o()};this._onheader=I,this._parse(512,I)};CBe.inherits(sp,wBe);sp.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit("error",t),this.emit("close"),this._stream&&this._stream.emit("close"))};sp.prototype._parse=function(t,e){this._destroyed||(this._offset+=t,this._missing=t,e===this._onheader&&(this._partial=!1),this._onparse=e)};sp.prototype._continue=function(){if(!this._destroyed){var t=this._cb;this._cb=BBe,this._overflow?this._write(this._overflow,void 0,t):t()}};sp.prototype._write=function(t,e,r){if(!this._destroyed){var o=this._stream,a=this._buffer,n=this._missing;if(t.length&&(this._partial=!0),t.lengthn&&(u=t.slice(n),t=t.slice(0,n)),o?o.end(t):a.append(t),this._overflow=u,this._onparse()}};sp.prototype._final=function(t){if(this._partial)return this.destroy(new Error("Unexpected end of data"));t()};vBe.exports=sp});var SBe=_((m$t,PBe)=>{PBe.exports=ve("fs").constants||ve("constants")});var FBe=_((y$t,QBe)=>{var YC=SBe(),bBe=E4(),BF=Jh(),NBt=Buffer.alloc,xBe=qC().Readable,WC=qC().Writable,LBt=ve("string_decoder").StringDecoder,IF=_5(),MBt=parseInt("755",8),OBt=parseInt("644",8),kBe=NBt(1024),q5=function(){},H5=function(t,e){e&=511,e&&t.push(kBe.slice(0,512-e))};function UBt(t){switch(t&YC.S_IFMT){case YC.S_IFBLK:return"block-device";case YC.S_IFCHR:return"character-device";case YC.S_IFDIR:return"directory";case YC.S_IFIFO:return"fifo";case YC.S_IFLNK:return"symlink"}return"file"}var vF=function(t){WC.call(this),this.written=0,this._to=t,this._destroyed=!1};BF(vF,WC);vF.prototype._write=function(t,e,r){if(this.written+=t.length,this._to.push(t))return r();this._to._drain=r};vF.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var DF=function(){WC.call(this),this.linkname="",this._decoder=new LBt("utf-8"),this._destroyed=!1};BF(DF,WC);DF.prototype._write=function(t,e,r){this.linkname+=this._decoder.write(t),r()};DF.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var Yv=function(){WC.call(this),this._destroyed=!1};BF(Yv,WC);Yv.prototype._write=function(t,e,r){r(new Error("No body allowed for this entry"))};Yv.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var IA=function(t){if(!(this instanceof IA))return new IA(t);xBe.call(this,t),this._drain=q5,this._finalized=!1,this._finalizing=!1,this._destroyed=!1,this._stream=null};BF(IA,xBe);IA.prototype.entry=function(t,e,r){if(this._stream)throw new Error("already piping an entry");if(!(this._finalized||this._destroyed)){typeof e=="function"&&(r=e,e=null),r||(r=q5);var o=this;if((!t.size||t.type==="symlink")&&(t.size=0),t.type||(t.type=UBt(t.mode)),t.mode||(t.mode=t.type==="directory"?MBt:OBt),t.uid||(t.uid=0),t.gid||(t.gid=0),t.mtime||(t.mtime=new Date),typeof e=="string"&&(e=Buffer.from(e)),Buffer.isBuffer(e)){t.size=e.length,this._encode(t);var a=this.push(e);return H5(o,t.size),a?process.nextTick(r):this._drain=r,new Yv}if(t.type==="symlink"&&!t.linkname){var n=new DF;return bBe(n,function(A){if(A)return o.destroy(),r(A);t.linkname=n.linkname,o._encode(t),r()}),n}if(this._encode(t),t.type!=="file"&&t.type!=="contiguous-file")return process.nextTick(r),new Yv;var u=new vF(this);return this._stream=u,bBe(u,function(A){if(o._stream=null,A)return o.destroy(),r(A);if(u.written!==t.size)return o.destroy(),r(new Error("size mismatch"));H5(o,t.size),o._finalizing&&o.finalize(),r()}),u}};IA.prototype.finalize=function(){if(this._stream){this._finalizing=!0;return}this._finalized||(this._finalized=!0,this.push(kBe),this.push(null))};IA.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit("error",t),this.emit("close"),this._stream&&this._stream.destroy&&this._stream.destroy())};IA.prototype._encode=function(t){if(!t.pax){var e=IF.encode(t);if(e){this.push(e);return}}this._encodePax(t)};IA.prototype._encodePax=function(t){var e=IF.encodePax({name:t.name,linkname:t.linkname,pax:t.pax}),r={name:"PaxHeader",mode:t.mode,uid:t.uid,gid:t.gid,size:e.length,mtime:t.mtime,type:"pax-header",linkname:t.linkname&&"PaxHeader",uname:t.uname,gname:t.gname,devmajor:t.devmajor,devminor:t.devminor};this.push(IF.encode(r)),this.push(e),H5(this,e.length),r.size=t.size,r.type=t.type,this.push(IF.encode(r))};IA.prototype._read=function(t){var e=this._drain;this._drain=q5,e()};QBe.exports=IA});var RBe=_(j5=>{j5.extract=DBe();j5.pack=FBe()});var YBe=_((O$t,GBe)=>{"use strict";var Wv=class t{constructor(e,r,o){this.__specs=e||{},Object.keys(this.__specs).forEach(a=>{if(typeof this.__specs[a]=="string"){let n=this.__specs[a],u=this.__specs[n];if(u){let A=u.aliases||[];A.push(a,n),u.aliases=[...new Set(A)],this.__specs[a]=u}else throw new Error(`Alias refers to invalid key: ${n} -> ${a}`)}}),this.__opts=r||{},this.__providers=qBe(o.filter(a=>a!=null&&typeof a=="object")),this.__isFiggyPudding=!0}get(e){return z5(this,e,!0)}get[Symbol.toStringTag](){return"FiggyPudding"}forEach(e,r=this){for(let[o,a]of this.entries())e.call(r,a,o,this)}toJSON(){let e={};return this.forEach((r,o)=>{e[o]=r}),e}*entries(e){for(let o of Object.keys(this.__specs))yield[o,this.get(o)];let r=e||this.__opts.other;if(r){let o=new Set;for(let a of this.__providers){let n=a.entries?a.entries(r):evt(a);for(let[u,A]of n)r(u)&&!o.has(u)&&(o.add(u),yield[u,A])}}}*[Symbol.iterator](){for(let[e,r]of this.entries())yield[e,r]}*keys(){for(let[e]of this.entries())yield e}*values(){for(let[,e]of this.entries())yield e}concat(...e){return new Proxy(new t(this.__specs,this.__opts,qBe(this.__providers).concat(e)),jBe)}};try{let t=ve("util");Wv.prototype[t.inspect.custom]=function(e,r){return this[Symbol.toStringTag]+" "+t.inspect(this.toJSON(),r)}}catch{}function ZBt(t){throw Object.assign(new Error(`invalid config key requested: ${t}`),{code:"EBADKEY"})}function z5(t,e,r){let o=t.__specs[e];if(r&&!o&&(!t.__opts.other||!t.__opts.other(e)))ZBt(e);else{o||(o={});let a;for(let n of t.__providers){if(a=HBe(e,n),a===void 0&&o.aliases&&o.aliases.length){for(let u of o.aliases)if(u!==e&&(a=HBe(u,n),a!==void 0))break}if(a!==void 0)break}return a===void 0&&o.default!==void 0?typeof o.default=="function"?o.default(t):o.default:a}}function HBe(t,e){let r;return e.__isFiggyPudding?r=z5(e,t,!1):typeof e.get=="function"?r=e.get(t):r=e[t],r}var jBe={has(t,e){return e in t.__specs&&z5(t,e,!1)!==void 0},ownKeys(t){return Object.keys(t.__specs)},get(t,e){return typeof e=="symbol"||e.slice(0,2)==="__"||e in Wv.prototype?t[e]:t.get(e)},set(t,e,r){if(typeof e=="symbol"||e.slice(0,2)==="__")return t[e]=r,!0;throw new Error("figgyPudding options cannot be modified. Use .concat() instead.")},deleteProperty(){throw new Error("figgyPudding options cannot be deleted. Use .concat() and shadow them instead.")}};GBe.exports=$Bt;function $Bt(t,e){function r(...o){return new Proxy(new Wv(t,e,o),jBe)}return r}function qBe(t){let e=[];return t.forEach(r=>e.unshift(r)),e}function evt(t){return Object.keys(t).map(e=>[e,t[e]])}});var VBe=_((U$t,DA)=>{"use strict";var Vv=ve("crypto"),tvt=YBe(),rvt=ve("stream").Transform,WBe=["sha256","sha384","sha512"],nvt=/^[a-z0-9+/]+(?:=?=?)$/i,ivt=/^([^-]+)-([^?]+)([?\S*]*)$/,svt=/^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/,ovt=/^[\x21-\x7E]+$/,na=tvt({algorithms:{default:["sha512"]},error:{default:!1},integrity:{},options:{default:[]},pickAlgorithm:{default:()=>hvt},Promise:{default:()=>Promise},sep:{default:" "},single:{default:!1},size:{},strict:{default:!1}}),n0=class{get isHash(){return!0}constructor(e,r){r=na(r);let o=!!r.strict;this.source=e.trim();let a=this.source.match(o?svt:ivt);if(!a||o&&!WBe.some(u=>u===a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];this.options=n?n.slice(1).split("?"):[]}hexDigest(){return this.digest&&Buffer.from(this.digest,"base64").toString("hex")}toJSON(){return this.toString()}toString(e){if(e=na(e),e.strict&&!(WBe.some(o=>o===this.algorithm)&&this.digest.match(nvt)&&(this.options||[]).every(o=>o.match(ovt))))return"";let r=this.options&&this.options.length?`?${this.options.join("?")}`:"";return`${this.algorithm}-${this.digest}${r}`}},Cd=class{get isIntegrity(){return!0}toJSON(){return this.toString()}toString(e){e=na(e);let r=e.sep||" ";return e.strict&&(r=r.replace(/\S+/g," ")),Object.keys(this).map(o=>this[o].map(a=>n0.prototype.toString.call(a,e)).filter(a=>a.length).join(r)).filter(o=>o.length).join(r)}concat(e,r){r=na(r);let o=typeof e=="string"?e:Kv(e,r);return vA(`${this.toString(r)} ${o}`,r)}hexDigest(){return vA(this,{single:!0}).hexDigest()}match(e,r){r=na(r);let o=vA(e,r),a=o.pickAlgorithm(r);return this[a]&&o[a]&&this[a].find(n=>o[a].find(u=>n.digest===u.digest))||!1}pickAlgorithm(e){e=na(e);let r=e.pickAlgorithm,o=Object.keys(this);if(!o.length)throw new Error(`No algorithms available for ${JSON.stringify(this.toString())}`);return o.reduce((a,n)=>r(a,n)||a)}};DA.exports.parse=vA;function vA(t,e){if(e=na(e),typeof t=="string")return J5(t,e);if(t.algorithm&&t.digest){let r=new Cd;return r[t.algorithm]=[t],J5(Kv(r,e),e)}else return J5(Kv(t,e),e)}function J5(t,e){return e.single?new n0(t,e):t.trim().split(/\s+/).reduce((r,o)=>{let a=new n0(o,e);if(a.algorithm&&a.digest){let n=a.algorithm;r[n]||(r[n]=[]),r[n].push(a)}return r},new Cd)}DA.exports.stringify=Kv;function Kv(t,e){return e=na(e),t.algorithm&&t.digest?n0.prototype.toString.call(t,e):typeof t=="string"?Kv(vA(t,e),e):Cd.prototype.toString.call(t,e)}DA.exports.fromHex=avt;function avt(t,e,r){r=na(r);let o=r.options&&r.options.length?`?${r.options.join("?")}`:"";return vA(`${e}-${Buffer.from(t,"hex").toString("base64")}${o}`,r)}DA.exports.fromData=lvt;function lvt(t,e){e=na(e);let r=e.algorithms,o=e.options&&e.options.length?`?${e.options.join("?")}`:"";return r.reduce((a,n)=>{let u=Vv.createHash(n).update(t).digest("base64"),A=new n0(`${n}-${u}${o}`,e);if(A.algorithm&&A.digest){let p=A.algorithm;a[p]||(a[p]=[]),a[p].push(A)}return a},new Cd)}DA.exports.fromStream=cvt;function cvt(t,e){e=na(e);let r=e.Promise||Promise,o=X5(e);return new r((a,n)=>{t.pipe(o),t.on("error",n),o.on("error",n);let u;o.on("integrity",A=>{u=A}),o.on("end",()=>a(u)),o.on("data",()=>{})})}DA.exports.checkData=uvt;function uvt(t,e,r){if(r=na(r),e=vA(e,r),!Object.keys(e).length){if(r.error)throw Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"});return!1}let o=e.pickAlgorithm(r),a=Vv.createHash(o).update(t).digest("base64"),n=vA({algorithm:o,digest:a}),u=n.match(e,r);if(u||!r.error)return u;if(typeof r.size=="number"&&t.length!==r.size){let A=new Error(`data size mismatch when checking ${e}. + Wanted: ${r.size} + Found: ${t.length}`);throw A.code="EBADSIZE",A.found=t.length,A.expected=r.size,A.sri=e,A}else{let A=new Error(`Integrity checksum failed when using ${o}: Wanted ${e}, but got ${n}. (${t.length} bytes)`);throw A.code="EINTEGRITY",A.found=n,A.expected=e,A.algorithm=o,A.sri=e,A}}DA.exports.checkStream=Avt;function Avt(t,e,r){r=na(r);let o=r.Promise||Promise,a=X5(r.concat({integrity:e}));return new o((n,u)=>{t.pipe(a),t.on("error",u),a.on("error",u);let A;a.on("verified",p=>{A=p}),a.on("end",()=>n(A)),a.on("data",()=>{})})}DA.exports.integrityStream=X5;function X5(t){t=na(t);let e=t.integrity&&vA(t.integrity,t),r=e&&Object.keys(e).length,o=r&&e.pickAlgorithm(t),a=r&&e[o],n=Array.from(new Set(t.algorithms.concat(o?[o]:[]))),u=n.map(Vv.createHash),A=0,p=new rvt({transform(h,E,I){A+=h.length,u.forEach(D=>D.update(h,E)),I(null,h,E)}}).on("end",()=>{let h=t.options&&t.options.length?`?${t.options.join("?")}`:"",E=vA(u.map((D,x)=>`${n[x]}-${D.digest("base64")}${h}`).join(" "),t),I=r&&E.match(e,t);if(typeof t.size=="number"&&A!==t.size){let D=new Error(`stream size mismatch when checking ${e}. + Wanted: ${t.size} + Found: ${A}`);D.code="EBADSIZE",D.found=A,D.expected=t.size,D.sri=e,p.emit("error",D)}else if(t.integrity&&!I){let D=new Error(`${e} integrity checksum failed when using ${o}: wanted ${a} but got ${E}. (${A} bytes)`);D.code="EINTEGRITY",D.found=E,D.expected=a,D.algorithm=o,D.sri=e,p.emit("error",D)}else p.emit("size",A),p.emit("integrity",E),I&&p.emit("verified",I)});return p}DA.exports.create=fvt;function fvt(t){t=na(t);let e=t.algorithms,r=t.options.length?`?${t.options.join("?")}`:"",o=e.map(Vv.createHash);return{update:function(a,n){return o.forEach(u=>u.update(a,n)),this},digest:function(a){return e.reduce((u,A)=>{let p=o.shift().digest("base64"),h=new n0(`${A}-${p}${r}`,t);if(h.algorithm&&h.digest){let E=h.algorithm;u[E]||(u[E]=[]),u[E].push(h)}return u},new Cd)}}}var pvt=new Set(Vv.getHashes()),KBe=["md5","whirlpool","sha1","sha224","sha256","sha384","sha512","sha3","sha3-256","sha3-384","sha3-512","sha3_256","sha3_384","sha3_512"].filter(t=>pvt.has(t));function hvt(t,e){return KBe.indexOf(t.toLowerCase())>=KBe.indexOf(e.toLowerCase())?t:e}});var Bve=_((qnr,Ive)=>{var hDt=YL();function gDt(t){return hDt(t)?void 0:t}Ive.exports=gDt});var Dve=_((jnr,vve)=>{var dDt=Cx(),mDt=hH(),yDt=yH(),EDt=Yg(),CDt=Eg(),wDt=Bve(),IDt=l8(),BDt=pH(),vDt=1,DDt=2,PDt=4,SDt=IDt(function(t,e){var r={};if(t==null)return r;var o=!1;e=dDt(e,function(n){return n=EDt(n,t),o||(o=n.length>1),n}),CDt(t,BDt(t),r),o&&(r=mDt(r,vDt|DDt|PDt,wDt));for(var a=e.length;a--;)yDt(r,e[a]);return r});vve.exports=SDt});Pt();Ke();Pt();var kve=ve("child_process"),Qve=et(sg());Gt();var oE=new Map([]);var S2={};Kt(S2,{BaseCommand:()=>ut,WorkspaceRequiredError:()=>or,getCli:()=>qhe,getDynamicLibs:()=>Hhe,getPluginConfiguration:()=>lE,openWorkspace:()=>aE,pluginCommands:()=>oE,runExit:()=>Lk});Gt();var ut=class extends st{constructor(){super(...arguments);this.cwd=de.String("--cwd",{hidden:!0})}validateAndExecute(){if(typeof this.cwd<"u")throw new ot("The --cwd option is ambiguous when used anywhere else than the very first parameter provided in the command line, before even the command path");return super.validateAndExecute()}};Ke();Pt();Gt();var or=class extends ot{constructor(e,r){let o=K.relative(e,r),a=K.join(e,_t.fileName);super(`This command can only be run from within a workspace of your project (${o} isn't a workspace of ${a}).`)}};Ke();Pt();sA();Ml();J1();Gt();var SAt=et(ni());il();var Hhe=()=>new Map([["@yarnpkg/cli",S2],["@yarnpkg/core",P2],["@yarnpkg/fslib",AI],["@yarnpkg/libzip",V1],["@yarnpkg/parsers",EI],["@yarnpkg/shell",e2],["clipanion",QI],["semver",SAt],["typanion",Wo]]);Ke();async function aE(t,e){let{project:r,workspace:o}=await Qt.find(t,e);if(!o)throw new or(r.cwd,e);return o}Ke();Pt();sA();Ml();J1();Gt();var LDt=et(ni());il();var OH={};Kt(OH,{AddCommand:()=>fE,BinCommand:()=>pE,CacheCleanCommand:()=>hE,ClipanionCommand:()=>CE,ConfigCommand:()=>yE,ConfigGetCommand:()=>gE,ConfigSetCommand:()=>dE,ConfigUnsetCommand:()=>mE,DedupeCommand:()=>EE,EntryCommand:()=>IE,ExecCommand:()=>vE,ExplainCommand:()=>SE,ExplainPeerRequirementsCommand:()=>DE,HelpCommand:()=>wE,InfoCommand:()=>bE,LinkCommand:()=>kE,NodeCommand:()=>QE,PluginCheckCommand:()=>FE,PluginImportCommand:()=>NE,PluginImportSourcesCommand:()=>LE,PluginListCommand:()=>RE,PluginRemoveCommand:()=>ME,PluginRuntimeCommand:()=>OE,RebuildCommand:()=>UE,RemoveCommand:()=>_E,RunCommand:()=>qE,RunIndexCommand:()=>HE,SetResolutionCommand:()=>jE,SetVersionCommand:()=>PE,SetVersionSourcesCommand:()=>TE,UnlinkCommand:()=>GE,UpCommand:()=>YE,VersionCommand:()=>BE,WhyCommand:()=>WE,WorkspaceCommand:()=>XE,WorkspacesListCommand:()=>JE,YarnCommand:()=>xE,dedupeUtils:()=>Wk,default:()=>wgt,suggestUtils:()=>nu});var Eme=et(sg());Ke();Ke();Ke();Gt();var xge=et(Q2());il();var nu={};Kt(nu,{Modifier:()=>lH,Strategy:()=>jk,Target:()=>F2,WorkspaceModifier:()=>vge,applyModifier:()=>Kft,extractDescriptorFromPath:()=>cH,extractRangeModifier:()=>Dge,fetchDescriptorFrom:()=>uH,findProjectDescriptors:()=>bge,getModifier:()=>R2,getSuggestedDescriptors:()=>T2,makeWorkspaceDescriptor:()=>Sge,toWorkspaceModifier:()=>Pge});Ke();Ke();Pt();var aH=et(ni()),Yft="workspace:",F2=(o=>(o.REGULAR="dependencies",o.DEVELOPMENT="devDependencies",o.PEER="peerDependencies",o))(F2||{}),lH=(o=>(o.CARET="^",o.TILDE="~",o.EXACT="",o))(lH||{}),vge=(o=>(o.CARET="^",o.TILDE="~",o.EXACT="*",o))(vge||{}),jk=(n=>(n.KEEP="keep",n.REUSE="reuse",n.PROJECT="project",n.LATEST="latest",n.CACHE="cache",n))(jk||{});function R2(t,e){return t.exact?"":t.caret?"^":t.tilde?"~":e.configuration.get("defaultSemverRangePrefix")}var Wft=/^([\^~]?)[0-9]+(?:\.[0-9]+){0,2}(?:-\S+)?$/;function Dge(t,{project:e}){let r=t.match(Wft);return r?r[1]:e.configuration.get("defaultSemverRangePrefix")}function Kft(t,e){let{protocol:r,source:o,params:a,selector:n}=G.parseRange(t.range);return aH.default.valid(n)&&(n=`${e}${t.range}`),G.makeDescriptor(t,G.makeRange({protocol:r,source:o,params:a,selector:n}))}function Pge(t){switch(t){case"^":return"^";case"~":return"~";case"":return"*";default:throw new Error(`Assertion failed: Unknown modifier: "${t}"`)}}function Sge(t,e){return G.makeDescriptor(t.anchoredDescriptor,`${Yft}${Pge(e)}`)}async function bge(t,{project:e,target:r}){let o=new Map,a=n=>{let u=o.get(n.descriptorHash);return u||o.set(n.descriptorHash,u={descriptor:n,locators:[]}),u};for(let n of e.workspaces)if(r==="peerDependencies"){let u=n.manifest.peerDependencies.get(t.identHash);u!==void 0&&a(u).locators.push(n.anchoredLocator)}else{let u=n.manifest.dependencies.get(t.identHash),A=n.manifest.devDependencies.get(t.identHash);r==="devDependencies"?A!==void 0?a(A).locators.push(n.anchoredLocator):u!==void 0&&a(u).locators.push(n.anchoredLocator):u!==void 0?a(u).locators.push(n.anchoredLocator):A!==void 0&&a(A).locators.push(n.anchoredLocator)}return o}async function cH(t,{cwd:e,workspace:r}){return await Vft(async o=>{K.isAbsolute(t)||(t=K.relative(r.cwd,K.resolve(e,t)),t.match(/^\.{0,2}\//)||(t=`./${t}`));let{project:a}=r,n=await uH(G.makeIdent(null,"archive"),t,{project:r.project,cache:o,workspace:r});if(!n)throw new Error("Assertion failed: The descriptor should have been found");let u=new Ri,A=a.configuration.makeResolver(),p=a.configuration.makeFetcher(),h={checksums:a.storedChecksums,project:a,cache:o,fetcher:p,report:u,resolver:A},E=A.bindDescriptor(n,r.anchoredLocator,h),I=G.convertDescriptorToLocator(E),D=await p.fetch(I,h),x=await _t.find(D.prefixPath,{baseFs:D.packageFs});if(!x.name)throw new Error("Target path doesn't have a name");return G.makeDescriptor(x.name,t)})}async function T2(t,{project:e,workspace:r,cache:o,target:a,fixed:n,modifier:u,strategies:A,maxResults:p=1/0}){if(!(p>=0))throw new Error(`Invalid maxResults (${p})`);let[h,E]=t.range!=="unknown"?n||Ur.validRange(t.range)||!t.range.match(/^[a-z0-9._-]+$/i)?[t.range,"latest"]:["unknown",t.range]:["unknown","latest"];if(h!=="unknown")return{suggestions:[{descriptor:t,name:`Use ${G.prettyDescriptor(e.configuration,t)}`,reason:"(unambiguous explicit request)"}],rejections:[]};let I=typeof r<"u"&&r!==null&&r.manifest[a].get(t.identHash)||null,D=[],x=[],C=async T=>{try{await T()}catch(L){x.push(L)}};for(let T of A){if(D.length>=p)break;switch(T){case"keep":await C(async()=>{I&&D.push({descriptor:I,name:`Keep ${G.prettyDescriptor(e.configuration,I)}`,reason:"(no changes)"})});break;case"reuse":await C(async()=>{for(let{descriptor:L,locators:U}of(await bge(t,{project:e,target:a})).values()){if(U.length===1&&U[0].locatorHash===r.anchoredLocator.locatorHash&&A.includes("keep"))continue;let z=`(originally used by ${G.prettyLocator(e.configuration,U[0])}`;z+=U.length>1?` and ${U.length-1} other${U.length>2?"s":""})`:")",D.push({descriptor:L,name:`Reuse ${G.prettyDescriptor(e.configuration,L)}`,reason:z})}});break;case"cache":await C(async()=>{for(let L of e.storedDescriptors.values())L.identHash===t.identHash&&D.push({descriptor:L,name:`Reuse ${G.prettyDescriptor(e.configuration,L)}`,reason:"(already used somewhere in the lockfile)"})});break;case"project":await C(async()=>{if(r.manifest.name!==null&&t.identHash===r.manifest.name.identHash)return;let L=e.tryWorkspaceByIdent(t);if(L===null)return;let U=Sge(L,u);D.push({descriptor:U,name:`Attach ${G.prettyDescriptor(e.configuration,U)}`,reason:`(local workspace at ${pe.pretty(e.configuration,L.relativeCwd,pe.Type.PATH)})`})});break;case"latest":{let L=e.configuration.get("enableNetwork"),U=e.configuration.get("enableOfflineMode");await C(async()=>{if(a==="peerDependencies")D.push({descriptor:G.makeDescriptor(t,"*"),name:"Use *",reason:"(catch-all peer dependency pattern)"});else if(!L&&!U)D.push({descriptor:null,name:"Resolve from latest",reason:pe.pretty(e.configuration,"(unavailable because enableNetwork is toggled off)","grey")});else{let z=await uH(t,E,{project:e,cache:o,workspace:r,modifier:u});z&&D.push({descriptor:z,name:`Use ${G.prettyDescriptor(e.configuration,z)}`,reason:`(resolved from ${U?"the cache":"latest"})`})}})}break}}return{suggestions:D.slice(0,p),rejections:x.slice(0,p)}}async function uH(t,e,{project:r,cache:o,workspace:a,preserveModifier:n=!0,modifier:u}){let A=r.configuration.normalizeDependency(G.makeDescriptor(t,e)),p=new Ri,h=r.configuration.makeFetcher(),E=r.configuration.makeResolver(),I={project:r,fetcher:h,cache:o,checksums:r.storedChecksums,report:p,cacheOptions:{skipIntegrityCheck:!0}},D={...I,resolver:E,fetchOptions:I},x=E.bindDescriptor(A,a.anchoredLocator,D),C=await E.getCandidates(x,{},D);if(C.length===0)return null;let T=C[0],{protocol:L,source:U,params:z,selector:te}=G.parseRange(G.convertToManifestRange(T.reference));if(L===r.configuration.get("defaultProtocol")&&(L=null),aH.default.valid(te)){let le=te;if(typeof u<"u")te=u+te;else if(n!==!1){let Ce=typeof n=="string"?n:A.range;te=Dge(Ce,{project:r})+te}let ce=G.makeDescriptor(T,G.makeRange({protocol:L,source:U,params:z,selector:te}));(await E.getCandidates(r.configuration.normalizeDependency(ce),{},D)).length!==1&&(te=le)}return G.makeDescriptor(T,G.makeRange({protocol:L,source:U,params:z,selector:te}))}async function Vft(t){return await ae.mktempPromise(async e=>{let r=Je.create(e);return r.useWithSource(e,{enableMirror:!1,compressionLevel:0},e,{overwrite:!0}),await t(new Yr(e,{configuration:r,check:!1,immutable:!1}))})}var fE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.fixed=de.Boolean("-F,--fixed",!1,{description:"Store dependency tags as-is instead of resolving them"});this.exact=de.Boolean("-E,--exact",!1,{description:"Don't use any semver modifier on the resolved range"});this.tilde=de.Boolean("-T,--tilde",!1,{description:"Use the `~` semver modifier on the resolved range"});this.caret=de.Boolean("-C,--caret",!1,{description:"Use the `^` semver modifier on the resolved range"});this.dev=de.Boolean("-D,--dev",!1,{description:"Add a package as a dev dependency"});this.peer=de.Boolean("-P,--peer",!1,{description:"Add a package as a peer dependency"});this.optional=de.Boolean("-O,--optional",!1,{description:"Add / upgrade a package to an optional regular / peer dependency"});this.preferDev=de.Boolean("--prefer-dev",!1,{description:"Add / upgrade a package to a dev dependency"});this.interactive=de.Boolean("-i,--interactive",{description:"Reuse the specified package from other workspaces in the project"});this.cached=de.Boolean("--cached",!1,{description:"Reuse the highest version already used somewhere within the project"});this.mode=de.String("--mode",{description:"Change what artifacts installs generate",validator:js(yl)});this.silent=de.Boolean("--silent",{hidden:!0});this.packages=de.Rest()}static{this.paths=[["add"]]}static{this.usage=st.Usage({description:"add dependencies to the project",details:"\n This command adds a package to the package.json for the nearest workspace.\n\n - If it didn't exist before, the package will by default be added to the regular `dependencies` field, but this behavior can be overriden thanks to the `-D,--dev` flag (which will cause the dependency to be added to the `devDependencies` field instead) and the `-P,--peer` flag (which will do the same but for `peerDependencies`).\n\n - If the package was already listed in your dependencies, it will by default be upgraded whether it's part of your `dependencies` or `devDependencies` (it won't ever update `peerDependencies`, though).\n\n - If set, the `--prefer-dev` flag will operate as a more flexible `-D,--dev` in that it will add the package to your `devDependencies` if it isn't already listed in either `dependencies` or `devDependencies`, but it will also happily upgrade your `dependencies` if that's what you already use (whereas `-D,--dev` would throw an exception).\n\n - If set, the `-O,--optional` flag will add the package to the `optionalDependencies` field and, in combination with the `-P,--peer` flag, it will add the package as an optional peer dependency. If the package was already listed in your `dependencies`, it will be upgraded to `optionalDependencies`. If the package was already listed in your `peerDependencies`, in combination with the `-P,--peer` flag, it will be upgraded to an optional peer dependency: `\"peerDependenciesMeta\": { \"\": { \"optional\": true } }`\n\n - If the added package doesn't specify a range at all its `latest` tag will be resolved and the returned version will be used to generate a new semver range (using the `^` modifier by default unless otherwise configured via the `defaultSemverRangePrefix` configuration, or the `~` modifier if `-T,--tilde` is specified, or no modifier at all if `-E,--exact` is specified). Two exceptions to this rule: the first one is that if the package is a workspace then its local version will be used, and the second one is that if you use `-P,--peer` the default range will be `*` and won't be resolved at all.\n\n - If the added package specifies a range (such as `^1.0.0`, `latest`, or `rc`), Yarn will add this range as-is in the resulting package.json entry (in particular, tags such as `rc` will be encoded as-is rather than being converted into a semver range).\n\n If the `--cached` option is used, Yarn will preferably reuse the highest version already used somewhere within the project, even if through a transitive dependency.\n\n If the `-i,--interactive` option is used (or if the `preferInteractive` settings is toggled on) the command will first try to check whether other workspaces in the project use the specified package and, if so, will offer to reuse them.\n\n If the `--mode=` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n For a compilation of all the supported protocols, please consult the dedicated page from our website: https://yarnpkg.com/protocols.\n ",examples:[["Add a regular package to the current workspace","$0 add lodash"],["Add a specific version for a package to the current workspace","$0 add lodash@1.2.3"],["Add a package from a GitHub repository (the master branch) to the current workspace using a URL","$0 add lodash@https://github.com/lodash/lodash"],["Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol","$0 add lodash@github:lodash/lodash"],["Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol (shorthand)","$0 add lodash@lodash/lodash"],["Add a package from a specific branch of a GitHub repository to the current workspace using the GitHub protocol (shorthand)","$0 add lodash-es@lodash/lodash#es"],["Add a local package (gzipped tarball format) to the current workspace","$0 add local-package-name@file:../path/to/local-package-name-v0.1.2.tgz"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=A||r.get("preferReuse"),h=R2(this,o),E=[p?"reuse":void 0,"project",this.cached?"cache":void 0,"latest"].filter(U=>typeof U<"u"),I=A?1/0:1,D=await Promise.all(this.packages.map(async U=>{let z=U.match(/^\.{0,2}\//)?await cH(U,{cwd:this.context.cwd,workspace:a}):G.tryParseDescriptor(U),te=U.match(/^(https?:|git@github)/);if(te)throw new ot(`It seems you are trying to add a package using a ${pe.pretty(r,`${te[0]}...`,pe.Type.RANGE)} url; we now require package names to be explicitly specified. +Try running the command again with the package name prefixed: ${pe.pretty(r,"yarn add",pe.Type.CODE)} ${pe.pretty(r,G.makeDescriptor(G.makeIdent(null,"my-package"),`${te[0]}...`),pe.Type.DESCRIPTOR)}`);if(!z)throw new ot(`The ${pe.pretty(r,U,pe.Type.CODE)} string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?`);let le=zft(a,z,{dev:this.dev,peer:this.peer,preferDev:this.preferDev,optional:this.optional});return await Promise.all(le.map(async ue=>{let Ce=await T2(z,{project:o,workspace:a,cache:n,fixed:u,target:ue,modifier:h,strategies:E,maxResults:I});return{request:z,suggestedDescriptors:Ce,target:ue}}))})).then(U=>U.flat()),x=await pA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async U=>{for(let{request:z,suggestedDescriptors:{suggestions:te,rejections:le}}of D)if(te.filter(ue=>ue.descriptor!==null).length===0){let[ue]=le;if(typeof ue>"u")throw new Error("Assertion failed: Expected an error to have been set");o.configuration.get("enableNetwork")?U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range`):U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range (note: network resolution has been disabled)`),U.reportSeparator(),U.reportExceptionOnce(ue)}});if(x.hasErrors())return x.exitCode();let C=!1,T=[],L=[];for(let{suggestedDescriptors:{suggestions:U},target:z}of D){let te,le=U.filter(he=>he.descriptor!==null),ce=le[0].descriptor,ue=le.every(he=>G.areDescriptorsEqual(he.descriptor,ce));le.length===1||ue?te=ce:(C=!0,{answer:te}=await(0,xge.prompt)({type:"select",name:"answer",message:"Which range do you want to use?",choices:U.map(({descriptor:he,name:De,reason:Ee})=>he?{name:De,hint:Ee,descriptor:he}:{name:De,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(he){return this.find(he,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ce=a.manifest[z].get(te.identHash);(typeof Ce>"u"||Ce.descriptorHash!==te.descriptorHash)&&(a.manifest[z].set(te.identHash,te),this.optional&&(z==="dependencies"?a.manifest.ensureDependencyMeta({...te,range:"unknown"}).optional=!0:z==="peerDependencies"&&(a.manifest.ensurePeerDependencyMeta({...te,range:"unknown"}).optional=!0)),typeof Ce>"u"?T.push([a,z,te,E]):L.push([a,z,Ce,te]))}return await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyAddition,T),await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyReplacement,L),C&&this.context.stdout.write(` +`),await o.installWithNewReport({json:this.json,stdout:this.context.stdout,quiet:this.context.quiet},{cache:n,mode:this.mode})}};function zft(t,e,{dev:r,peer:o,preferDev:a,optional:n}){let u=t.manifest.dependencies.has(e.identHash),A=t.manifest.devDependencies.has(e.identHash),p=t.manifest.peerDependencies.has(e.identHash);if((r||o)&&u)throw new ot(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a regular dependency - remove the -D,-P flags or remove it from your dependencies first`);if(!r&&!o&&p)throw new ot(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - use either of -D or -P, or remove it from your peer dependencies first`);if(n&&A)throw new ot(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a dev dependency - remove the -O flag or remove it from your dev dependencies first`);if(n&&!o&&p)throw new ot(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - remove the -O flag or add the -P flag or remove it from your peer dependencies first`);if((r||a)&&n)throw new ot(`Package "${G.prettyIdent(t.project.configuration,e)}" cannot simultaneously be a dev dependency and an optional dependency`);let h=[];return o&&h.push("peerDependencies"),(r||a)&&h.push("devDependencies"),n&&h.push("dependencies"),h.length>0?h:A?["devDependencies"]:p?["peerDependencies"]:["dependencies"]}Ke();Ke();Gt();var pE=class extends ut{constructor(){super(...arguments);this.verbose=de.Boolean("-v,--verbose",!1,{description:"Print both the binary name and the locator of the package that provides the binary"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.name=de.String({required:!1})}static{this.paths=[["bin"]]}static{this.usage=st.Usage({description:"get the path to a binary script",details:` + When used without arguments, this command will print the list of all the binaries available in the current workspace. Adding the \`-v,--verbose\` flag will cause the output to contain both the binary name and the locator of the package that provides the binary. + + When an argument is specified, this command will just print the path to the binary on the standard output and exit. Note that the reported path may be stored within a zip archive. + `,examples:[["List all the available binaries","$0 bin"],["Print the path to a specific binary","$0 bin eslint"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await Qt.find(r,this.context.cwd);if(await o.restoreInstallState(),this.name){let A=(await hn.getPackageAccessibleBinaries(a,{project:o})).get(this.name);if(!A)throw new ot(`Couldn't find a binary named "${this.name}" for package "${G.prettyLocator(r,a)}"`);let[,p]=A;return this.context.stdout.write(`${p} +`),0}return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async u=>{let A=await hn.getPackageAccessibleBinaries(a,{project:o}),h=Array.from(A.keys()).reduce((E,I)=>Math.max(E,I.length),0);for(let[E,[I,D]]of A)u.reportJson({name:E,source:G.stringifyIdent(I),path:D});if(this.verbose)for(let[E,[I]]of A)u.reportInfo(null,`${E.padEnd(h," ")} ${G.prettyLocator(r,I)}`);else for(let E of A.keys())u.reportInfo(null,E)})).exitCode()}};Ke();Pt();Gt();var hE=class extends ut{constructor(){super(...arguments);this.mirror=de.Boolean("--mirror",!1,{description:"Remove the global cache files instead of the local cache files"});this.all=de.Boolean("--all",!1,{description:"Remove both the global cache files and the local cache files of the current project"})}static{this.paths=[["cache","clean"],["cache","clear"]]}static{this.usage=st.Usage({description:"remove the shared cache files",details:` + This command will remove all the files from the cache. + `,examples:[["Remove all the local archives","$0 cache clean"],["Remove all the archives stored in the ~/.yarn directory","$0 cache clean --mirror"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await Yr.find(r);return(await Nt.start({configuration:r,stdout:this.context.stdout},async()=>{let n=(this.all||this.mirror)&&o.mirrorCwd!==null,u=!this.mirror;n&&(await ae.removePromise(o.mirrorCwd),await r.triggerHook(A=>A.cleanGlobalArtifacts,r)),u&&await ae.removePromise(o.cwd)})).exitCode()}};Ke();Gt();var Qge=et(N2()),AH=ve("util"),gE=class extends ut{constructor(){super(...arguments);this.why=de.Boolean("--why",!1,{description:"Print the explanation for why a setting has its value"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.unsafe=de.Boolean("--no-redacted",!1,{description:"Don't redact secrets (such as tokens) from the output"});this.name=de.String()}static{this.paths=[["config","get"]]}static{this.usage=st.Usage({description:"read a configuration settings",details:` + This command will print a configuration setting. + + Secrets (such as tokens) will be redacted from the output by default. If this behavior isn't desired, set the \`--no-redacted\` to get the untransformed value. + `,examples:[["Print a simple configuration setting","yarn config get yarnPath"],["Print a complex configuration setting","yarn config get packageExtensions"],["Print a nested field from the configuration",`yarn config get 'npmScopes["my-company"].npmRegistryServer'`],["Print a token from the configuration","yarn config get npmAuthToken --no-redacted"],["Print a configuration setting as JSON","yarn config get packageExtensions --json"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=this.name.replace(/[.[].*$/,""),a=this.name.replace(/^[^.[]*/,"");if(typeof r.settings.get(o)>"u")throw new ot(`Couldn't find a configuration settings named "${o}"`);let u=r.getSpecial(o,{hideSecrets:!this.unsafe,getNativePaths:!0}),A=qe.convertMapsToIndexableObjects(u),p=a?(0,Qge.default)(A,a):A,h=await Nt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async E=>{E.reportJson(p)});if(!this.json){if(typeof p=="string")return this.context.stdout.write(`${p} +`),h.exitCode();AH.inspect.styles.name="cyan",this.context.stdout.write(`${(0,AH.inspect)(p,{depth:1/0,colors:r.get("enableColors"),compact:!1})} +`)}return h.exitCode()}};Ke();Gt();var wde=et(gH()),Ide=et(N2()),Bde=et(dH()),mH=ve("util"),dE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Set complex configuration settings to JSON values"});this.home=de.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=de.String();this.value=de.String()}static{this.paths=[["config","set"]]}static{this.usage=st.Usage({description:"change a configuration settings",details:` + This command will set a configuration setting. + + When used without the \`--json\` flag, it can only set a simple configuration setting (a string, a number, or a boolean). + + When used with the \`--json\` flag, it can set both simple and complex configuration settings, including Arrays and Objects. + `,examples:[["Set a simple configuration setting (a string, a number, or a boolean)","yarn config set initScope myScope"],["Set a simple configuration setting (a string, a number, or a boolean) using the `--json` flag",'yarn config set initScope --json \\"myScope\\"'],["Set a complex configuration setting (an Array) using the `--json` flag",`yarn config set unsafeHttpWhitelist --json '["*.example.com", "example.com"]'`],["Set a complex configuration setting (an Object) using the `--json` flag",`yarn config set packageExtensions --json '{ "@babel/parser@*": { "dependencies": { "@babel/types": "*" } } }'`],["Set a nested configuration setting",'yarn config set npmScopes.company.npmRegistryServer "https://npm.example.com"'],["Set a nested configuration setting using indexed access for non-simple keys",`yarn config set 'npmRegistries["//npm.example.com"].npmAuthToken' "ffffffff-ffff-ffff-ffff-ffffffffffff"`]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new ot("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new ot(`Couldn't find a configuration settings named "${a}"`);if(a==="enableStrictSettings")throw new ot("This setting only affects the file it's in, and thus cannot be set from the CLI");let A=this.json?JSON.parse(this.value):this.value;await(this.home?C=>Je.updateHomeConfiguration(C):C=>Je.updateConfiguration(o(),C))(C=>{if(n){let T=(0,wde.default)(C);return(0,Bde.default)(T,this.name,A),T}else return{...C,[a]:A}});let E=(await Je.find(this.context.cwd,this.context.plugins)).getSpecial(a,{hideSecrets:!0,getNativePaths:!0}),I=qe.convertMapsToIndexableObjects(E),D=n?(0,Ide.default)(I,n):I;return(await Nt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async C=>{mH.inspect.styles.name="cyan",C.reportInfo(0,`Successfully set ${this.name} to ${(0,mH.inspect)(D,{depth:1/0,colors:r.get("enableColors"),compact:!1})}`)})).exitCode()}};Ke();Gt();var Tde=et(gH()),Nde=et(Sde()),Lde=et(EH()),mE=class extends ut{constructor(){super(...arguments);this.home=de.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=de.String()}static{this.paths=[["config","unset"]]}static{this.usage=st.Usage({description:"unset a configuration setting",details:` + This command will unset a configuration setting. + `,examples:[["Unset a simple configuration setting","yarn config unset initScope"],["Unset a complex configuration setting","yarn config unset packageExtensions"],["Unset a nested configuration setting","yarn config unset npmScopes.company.npmRegistryServer"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new ot("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new ot(`Couldn't find a configuration settings named "${a}"`);let A=this.home?h=>Je.updateHomeConfiguration(h):h=>Je.updateConfiguration(o(),h);return(await Nt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async h=>{let E=!1;await A(I=>{if(!(0,Nde.default)(I,this.name))return h.reportWarning(0,`Configuration doesn't contain setting ${this.name}; there is nothing to unset`),E=!0,I;let D=n?(0,Tde.default)(I):{...I};return(0,Lde.default)(D,this.name),D}),E||h.reportInfo(0,`Successfully unset ${this.name}`)})).exitCode()}};Ke();Pt();Gt();var Yk=ve("util"),yE=class extends ut{constructor(){super(...arguments);this.noDefaults=de.Boolean("--no-defaults",!1,{description:"Omit the default values from the display"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.verbose=de.Boolean("-v,--verbose",{hidden:!0});this.why=de.Boolean("--why",{hidden:!0});this.names=de.Rest()}static{this.paths=[["config"]]}static{this.usage=st.Usage({description:"display the current configuration",details:` + This command prints the current active configuration settings. + `,examples:[["Print the active configuration settings","$0 config"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins,{strict:!1}),o=await Qy({configuration:r,stdout:this.context.stdout,forceError:this.json},[{option:this.verbose,message:"The --verbose option is deprecated, the settings' descriptions are now always displayed"},{option:this.why,message:"The --why option is deprecated, the settings' sources are now always displayed"}]);if(o!==null)return o;let a=this.names.length>0?[...new Set(this.names)].sort():[...r.settings.keys()].sort(),n,u=await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async A=>{if(r.invalid.size>0&&!this.json){for(let[p,h]of r.invalid)A.reportError(34,`Invalid configuration key "${p}" in ${h}`);A.reportSeparator()}if(this.json)for(let p of a){let h=r.settings.get(p);typeof h>"u"&&A.reportError(34,`No configuration key named "${p}"`);let E=r.getSpecial(p,{hideSecrets:!0,getNativePaths:!0}),I=r.sources.get(p)??"",D=I&&I[0]!=="<"?Ae.fromPortablePath(I):I;A.reportJson({key:p,effective:E,source:D,...h})}else{let p={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},h={},E={children:h};for(let I of a){if(this.noDefaults&&!r.sources.has(I))continue;let D=r.settings.get(I),x=r.sources.get(I)??"",C=r.getSpecial(I,{hideSecrets:!0,getNativePaths:!0}),T={Description:{label:"Description",value:pe.tuple(pe.Type.MARKDOWN,{text:D.description,format:this.cli.format(),paragraphs:!1})},Source:{label:"Source",value:pe.tuple(x[0]==="<"?pe.Type.CODE:pe.Type.PATH,x)}};h[I]={value:pe.tuple(pe.Type.CODE,I),children:T};let L=(U,z)=>{for(let[te,le]of z)if(le instanceof Map){let ce={};U[te]={children:ce},L(ce,le)}else U[te]={label:te,value:pe.tuple(pe.Type.NO_HINT,(0,Yk.inspect)(le,p))}};C instanceof Map?L(T,C):T.Value={label:"Value",value:pe.tuple(pe.Type.NO_HINT,(0,Yk.inspect)(C,p))}}a.length!==1&&(n=void 0),As.emitTree(E,{configuration:r,json:this.json,stdout:this.context.stdout,separators:2})}});if(!this.json&&typeof n<"u"){let A=a[0],p=(0,Yk.inspect)(r.getSpecial(A,{hideSecrets:!0,getNativePaths:!0}),{colors:r.get("enableColors")});this.context.stdout.write(` +`),this.context.stdout.write(`${p} +`)}return u.exitCode()}};Ke();Gt();il();var Wk={};Kt(Wk,{Strategy:()=>L2,acceptedStrategies:()=>Q0t,dedupe:()=>CH});Ke();Ke();var Mde=et(Xo()),L2=(e=>(e.HIGHEST="highest",e))(L2||{}),Q0t=new Set(Object.values(L2)),F0t={highest:async(t,e,{resolver:r,fetcher:o,resolveOptions:a,fetchOptions:n})=>{let u=new Map;for(let[p,h]of t.storedResolutions){let E=t.storedDescriptors.get(p);if(typeof E>"u")throw new Error(`Assertion failed: The descriptor (${p}) should have been registered`);qe.getSetWithDefault(u,E.identHash).add(h)}let A=new Map(qe.mapAndFilter(t.storedDescriptors.values(),p=>G.isVirtualDescriptor(p)?qe.mapAndFilter.skip:[p.descriptorHash,qe.makeDeferred()]));for(let p of t.storedDescriptors.values()){let h=A.get(p.descriptorHash);if(typeof h>"u")throw new Error(`Assertion failed: The descriptor (${p.descriptorHash}) should have been registered`);let E=t.storedResolutions.get(p.descriptorHash);if(typeof E>"u")throw new Error(`Assertion failed: The resolution (${p.descriptorHash}) should have been registered`);let I=t.originalPackages.get(E);if(typeof I>"u")throw new Error(`Assertion failed: The package (${E}) should have been registered`);Promise.resolve().then(async()=>{let D=r.getResolutionDependencies(p,a),x=Object.fromEntries(await qe.allSettledSafe(Object.entries(D).map(async([te,le])=>{let ce=A.get(le.descriptorHash);if(typeof ce>"u")throw new Error(`Assertion failed: The descriptor (${le.descriptorHash}) should have been registered`);let ue=await ce.promise;if(!ue)throw new Error("Assertion failed: Expected the dependency to have been through the dedupe process itself");return[te,ue.updatedPackage]})));if(e.length&&!Mde.default.isMatch(G.stringifyIdent(p),e)||!r.shouldPersistResolution(I,a))return I;let C=u.get(p.identHash);if(typeof C>"u")throw new Error(`Assertion failed: The resolutions (${p.identHash}) should have been registered`);if(C.size===1)return I;let T=[...C].map(te=>{let le=t.originalPackages.get(te);if(typeof le>"u")throw new Error(`Assertion failed: The package (${te}) should have been registered`);return le}),L=await r.getSatisfying(p,x,T,a),U=L.locators?.[0];if(typeof U>"u"||!L.sorted)return I;let z=t.originalPackages.get(U.locatorHash);if(typeof z>"u")throw new Error(`Assertion failed: The package (${U.locatorHash}) should have been registered`);return z}).then(async D=>{let x=await t.preparePackage(D,{resolver:r,resolveOptions:a});h.resolve({descriptor:p,currentPackage:I,updatedPackage:D,resolvedPackage:x})}).catch(D=>{h.reject(D)})}return[...A.values()].map(p=>p.promise)}};async function CH(t,{strategy:e,patterns:r,cache:o,report:a}){let{configuration:n}=t,u=new Ri,A=n.makeResolver(),p=n.makeFetcher(),h={cache:o,checksums:t.storedChecksums,fetcher:p,project:t,report:u,cacheOptions:{skipIntegrityCheck:!0}},E={project:t,resolver:A,report:u,fetchOptions:h};return await a.startTimerPromise("Deduplication step",async()=>{let I=F0t[e],D=await I(t,r,{resolver:A,resolveOptions:E,fetcher:p,fetchOptions:h}),x=Ys.progressViaCounter(D.length);await a.reportProgress(x);let C=0;await Promise.all(D.map(U=>U.then(z=>{if(z===null||z.currentPackage.locatorHash===z.updatedPackage.locatorHash)return;C++;let{descriptor:te,currentPackage:le,updatedPackage:ce}=z;a.reportInfo(0,`${G.prettyDescriptor(n,te)} can be deduped from ${G.prettyLocator(n,le)} to ${G.prettyLocator(n,ce)}`),a.reportJson({descriptor:G.stringifyDescriptor(te),currentResolution:G.stringifyLocator(le),updatedResolution:G.stringifyLocator(ce)}),t.storedResolutions.set(te.descriptorHash,ce.locatorHash)}).finally(()=>x.tick())));let T;switch(C){case 0:T="No packages";break;case 1:T="One package";break;default:T=`${C} packages`}let L=pe.pretty(n,e,pe.Type.CODE);return a.reportInfo(0,`${T} can be deduped using the ${L} strategy`),C})}var EE=class extends ut{constructor(){super(...arguments);this.strategy=de.String("-s,--strategy","highest",{description:"The strategy to use when deduping dependencies",validator:js(L2)});this.check=de.Boolean("-c,--check",!1,{description:"Exit with exit code 1 when duplicates are found, without persisting the dependency tree"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.mode=de.String("--mode",{description:"Change what artifacts installs generate",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[["dedupe"]]}static{this.usage=st.Usage({description:"deduplicate dependencies with overlapping ranges",details:"\n Duplicates are defined as descriptors with overlapping ranges being resolved and locked to different locators. They are a natural consequence of Yarn's deterministic installs, but they can sometimes pile up and unnecessarily increase the size of your project.\n\n This command dedupes dependencies in the current project using different strategies (only one is implemented at the moment):\n\n - `highest`: Reuses (where possible) the locators with the highest versions. This means that dependencies can only be upgraded, never downgraded. It's also guaranteed that it never takes more than a single pass to dedupe the entire dependency tree.\n\n **Note:** Even though it never produces a wrong dependency tree, this command should be used with caution, as it modifies the dependency tree, which can sometimes cause problems when packages don't strictly follow semver recommendations. Because of this, it is recommended to also review the changes manually.\n\n If set, the `-c,--check` flag will only report the found duplicates, without persisting the modified dependency tree. If changes are found, the command will exit with a non-zero exit code, making it suitable for CI purposes.\n\n If the `--mode=` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n ### In-depth explanation:\n\n Yarn doesn't deduplicate dependencies by default, otherwise installs wouldn't be deterministic and the lockfile would be useless. What it actually does is that it tries to not duplicate dependencies in the first place.\n\n **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@*`will cause Yarn to reuse `foo@2.3.4`, even if the latest `foo` is actually `foo@2.10.14`, thus preventing unnecessary duplication.\n\n Duplication happens when Yarn can't unlock dependencies that have already been locked inside the lockfile.\n\n **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@2.10.14` will cause Yarn to install `foo@2.10.14` because the existing resolution doesn't satisfy the range `2.10.14`. This behavior can lead to (sometimes) unwanted duplication, since now the lockfile contains 2 separate resolutions for the 2 `foo` descriptors, even though they have overlapping ranges, which means that the lockfile can be simplified so that both descriptors resolve to `foo@2.10.14`.\n ",examples:[["Dedupe all packages","$0 dedupe"],["Dedupe all packages using a specific strategy","$0 dedupe --strategy highest"],["Dedupe a specific package","$0 dedupe lodash"],["Dedupe all packages with the `@babel/*` scope","$0 dedupe '@babel/*'"],["Check for duplicates (can be used as a CI step)","$0 dedupe --check"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=await Yr.find(r);await o.restoreInstallState({restoreResolutions:!1});let n=0,u=await Nt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout,json:this.json},async A=>{n=await CH(o,{strategy:this.strategy,patterns:this.patterns,cache:a,report:A})});return u.hasErrors()?u.exitCode():this.check?n?1:0:await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:a,mode:this.mode})}};Ke();Gt();var CE=class extends ut{static{this.paths=[["--clipanion=definitions"]]}async execute(){let{plugins:e}=await Je.find(this.context.cwd,this.context.plugins),r=[];for(let u of e){let{commands:A}=u[1];if(A){let h=Vo.from(A).definitions();r.push([u[0],h])}}let o=this.cli.definitions(),a=(u,A)=>u.split(" ").slice(1).join()===A.split(" ").slice(1).join(),n=Ode()["@yarnpkg/builder"].bundles.standard;for(let u of r){let A=u[1];for(let p of A)o.find(h=>a(h.path,p.path)).plugin={name:u[0],isDefault:n.includes(u[0])}}this.context.stdout.write(`${JSON.stringify(o,null,2)} +`)}};var wE=class extends ut{static{this.paths=[["help"],["--help"],["-h"]]}async execute(){this.context.stdout.write(this.cli.usage(null))}};Ke();Pt();Gt();var IE=class extends ut{constructor(){super(...arguments);this.leadingArgument=de.String();this.args=de.Proxy()}async execute(){if(this.leadingArgument.match(/[\\/]/)&&!G.tryParseIdent(this.leadingArgument)){let r=K.resolve(this.context.cwd,Ae.toPortablePath(this.leadingArgument));return await this.cli.run(this.args,{cwd:r})}else return await this.cli.run(["run",this.leadingArgument,...this.args])}};Ke();var BE=class extends ut{static{this.paths=[["-v"],["--version"]]}async execute(){this.context.stdout.write(`${nn||""} +`)}};Ke();Ke();Gt();var vE=class extends ut{constructor(){super(...arguments);this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[["exec"]]}static{this.usage=st.Usage({description:"execute a shell script",details:` + This command simply executes a shell script within the context of the root directory of the active workspace using the portable shell. + + It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment). + `,examples:[["Execute a single shell command","$0 exec echo Hello World"],["Execute a shell script",'$0 exec "tsc & babel src --out-dir lib"']]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await Qt.find(r,this.context.cwd);return await o.restoreInstallState(),await hn.executePackageShellcode(a,this.commandName,this.args,{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,project:o})}};Ke();Gt();il();var DE=class extends ut{constructor(){super(...arguments);this.hash=de.String({required:!1,validator:NP(Sm(),[BI(/^p[0-9a-f]{5}$/)])})}static{this.paths=[["explain","peer-requirements"]]}static{this.usage=st.Usage({description:"explain a set of peer requirements",details:` + A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters. + + When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not. + + When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement. + + **Note:** A hash is a six-letter p-prefixed code that can be obtained from peer dependency warnings or from the list of all peer requirements (\`yarn explain peer-requirements\`). + `,examples:[["Explain the corresponding peer requirement for a hash","$0 explain peer-requirements p1a4ed"],["List all peer requirements","$0 explain peer-requirements"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return await o.restoreInstallState({restoreResolutions:!1}),await o.applyLightResolution(),typeof this.hash<"u"?await T0t(this.hash,o,{stdout:this.context.stdout}):await N0t(o,{stdout:this.context.stdout})}};async function T0t(t,e,r){let o=e.peerRequirementNodes.get(t);if(typeof o>"u")throw new Error(`No peerDependency requirements found for hash: "${t}"`);let a=new Set,n=p=>a.has(p.requester.locatorHash)?{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:p.children.size>0?[{value:pe.tuple(pe.Type.NO_HINT,"...")}]:[]}:(a.add(p.requester.locatorHash),{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:Object.fromEntries(Array.from(p.children.values(),h=>[G.stringifyLocator(h.requester),n(h)]))}),u=e.peerWarnings.find(p=>p.hash===t);return(await Nt.start({configuration:e.configuration,stdout:r.stdout,includeFooter:!1,includePrefix:!1},async p=>{let h=pe.mark(e.configuration),E=u?h.Cross:h.Check;if(p.reportInfo(0,`Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} is requested to provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} by its descendants`),p.reportSeparator(),p.reportInfo(0,pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)),As.emitTree({children:Object.fromEntries(Array.from(o.requests.values(),I=>[G.stringifyLocator(I.requester),n(I)]))},{configuration:e.configuration,stdout:r.stdout,json:!1}),p.reportSeparator(),o.provided.range==="missing:"){let I=u?"":" , but all peer requests are optional";p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} does not provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)}${I}.`)}else{let I=e.storedResolutions.get(o.provided.descriptorHash);if(!I)throw new Error("Assertion failed: Expected the descriptor to be registered");let D=e.storedPackages.get(I);if(!D)throw new Error("Assertion failed: Expected the package to be registered");p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} provides ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} with version ${G.prettyReference(e.configuration,D.version??"0.0.0")}, ${u?"which does not satisfy all requests.":"which satisfies all requests"}`),u?.type===3&&(u.range?p.reportInfo(0,` The combined requested range is ${pe.pretty(e.configuration,u.range,pe.Type.RANGE)}`):p.reportInfo(0," Unfortunately, the requested ranges have no overlap"))}})).exitCode()}async function N0t(t,e){return(await Nt.start({configuration:t.configuration,stdout:e.stdout,includeFooter:!1,includePrefix:!1},async o=>{let a=pe.mark(t.configuration),n=qe.sortMap(t.peerRequirementNodes,[([,u])=>G.stringifyLocator(u.subject),([,u])=>G.stringifyIdent(u.ident)]);for(let[,u]of n.values()){if(!u.root)continue;let A=t.peerWarnings.find(E=>E.hash===u.hash),p=[...G.allPeerRequests(u)],h;if(p.length>2?h=` and ${p.length-1} other dependencies`:p.length===2?h=" and 1 other dependency":h="",u.provided.range!=="missing:"){let E=t.storedResolutions.get(u.provided.descriptorHash);if(!E)throw new Error("Assertion failed: Expected the resolution to have been registered");let I=t.storedPackages.get(E);if(!I)throw new Error("Assertion failed: Expected the provided package to have been registered");let D=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} provides ${G.prettyLocator(t.configuration,I)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,D):o.reportInfo(0,D)}else{let E=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} doesn't provide ${G.prettyIdent(t.configuration,u.ident)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,E):o.reportInfo(0,E)}}})).exitCode()}Ke();Gt();il();Ke();Ke();Pt();Gt();var Ude=et(ni()),PE=class extends ut{constructor(){super(...arguments);this.useYarnPath=de.Boolean("--yarn-path",{description:"Set the yarnPath setting even if the version can be accessed by Corepack"});this.onlyIfNeeded=de.Boolean("--only-if-needed",!1,{description:"Only lock the Yarn version if it isn't already locked"});this.version=de.String()}static{this.paths=[["set","version"]]}static{this.usage=st.Usage({description:"lock the Yarn version used by the project",details:"\n This command will set a specific release of Yarn to be used by Corepack: https://nodejs.org/api/corepack.html.\n\n By default it only will set the `packageManager` field at the root of your project, but if the referenced release cannot be represented this way, if you already have `yarnPath` configured, or if you set the `--yarn-path` command line flag, then the release will also be downloaded from the Yarn GitHub repository, stored inside your project, and referenced via the `yarnPath` settings from your project `.yarnrc.yml` file.\n\n A very good use case for this command is to enforce the version of Yarn used by any single member of your team inside the same project - by doing this you ensure that you have control over Yarn upgrades and downgrades (including on your deployment servers), and get rid of most of the headaches related to someone using a slightly different version and getting different behavior.\n\n The version specifier can be:\n\n - a tag:\n - `latest` / `berry` / `stable` -> the most recent stable berry (`>=2.0.0`) release\n - `canary` -> the most recent canary (release candidate) berry (`>=2.0.0`) release\n - `classic` -> the most recent classic (`^0.x || ^1.x`) release\n\n - a semver range (e.g. `2.x`) -> the most recent version satisfying the range (limited to berry releases)\n\n - a semver version (e.g. `2.4.1`, `1.22.1`)\n\n - a local file referenced through either a relative or absolute path\n\n - `self` -> the version used to invoke the command\n ",examples:[["Download the latest release from the Yarn repository","$0 set version latest"],["Download the latest canary release from the Yarn repository","$0 set version canary"],["Download the latest classic release from the Yarn repository","$0 set version classic"],["Download the most recent Yarn 3 build","$0 set version 3.x"],["Download a specific Yarn 2 build","$0 set version 2.0.0-rc.30"],["Switch back to a specific Yarn 1 release","$0 set version 1.22.1"],["Use a release from the local filesystem","$0 set version ./yarn.cjs"],["Use a release from a URL","$0 set version https://repo.yarnpkg.com/3.1.0/packages/yarnpkg-cli/bin/yarn.js"],["Download the version used to invoke the command","$0 set version self"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);if(this.onlyIfNeeded&&r.get("yarnPath")){let A=r.sources.get("yarnPath");if(!A)throw new Error("Assertion failed: Expected 'yarnPath' to have a source");let p=r.projectCwd??r.startingCwd;if(K.contains(p,A))return 0}let o=()=>{if(typeof nn>"u")throw new ot("The --install flag can only be used without explicit version specifier from the Yarn CLI");return`file://${process.argv[1]}`},a,n=(A,p)=>({version:p,url:A.replace(/\{\}/g,p)});if(this.version==="self")a={url:o(),version:nn??"self"};else if(this.version==="latest"||this.version==="berry"||this.version==="stable")a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await M2(r,"stable"));else if(this.version==="canary")a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await M2(r,"canary"));else if(this.version==="classic")a={url:"https://classic.yarnpkg.com/latest.js",version:"classic"};else if(this.version.match(/^https?:/))a={url:this.version,version:"remote"};else if(this.version.match(/^\.{0,2}[\\/]/)||Ae.isAbsolute(this.version))a={url:`file://${K.resolve(Ae.toPortablePath(this.version))}`,version:"file"};else if(Ur.satisfiesWithPrereleases(this.version,">=2.0.0"))a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",this.version);else if(Ur.satisfiesWithPrereleases(this.version,"^0.x || ^1.x"))a=n("https://github.com/yarnpkg/yarn/releases/download/v{}/yarn-{}.js",this.version);else if(Ur.validRange(this.version))a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await L0t(r,this.version));else throw new ot(`Invalid version descriptor "${this.version}"`);return(await Nt.start({configuration:r,stdout:this.context.stdout,includeLogs:!this.context.quiet},async A=>{let p=async()=>{let h="file://";return a.url.startsWith(h)?(A.reportInfo(0,`Retrieving ${pe.pretty(r,a.url,pe.Type.PATH)}`),await ae.readFilePromise(a.url.slice(h.length))):(A.reportInfo(0,`Downloading ${pe.pretty(r,a.url,pe.Type.URL)}`),await on.get(a.url,{configuration:r}))};await wH(r,a.version,p,{report:A,useYarnPath:this.useYarnPath})})).exitCode()}};async function L0t(t,e){let o=(await on.get("https://repo.yarnpkg.com/tags",{configuration:t,jsonResponse:!0})).tags.filter(a=>Ur.satisfiesWithPrereleases(a,e));if(o.length===0)throw new ot(`No matching release found for range ${pe.pretty(t,e,pe.Type.RANGE)}.`);return o[0]}async function M2(t,e){let r=await on.get("https://repo.yarnpkg.com/tags",{configuration:t,jsonResponse:!0});if(!r.latest[e])throw new ot(`Tag ${pe.pretty(t,e,pe.Type.RANGE)} not found`);return r.latest[e]}async function wH(t,e,r,{report:o,useYarnPath:a}){let n,u=async()=>(typeof n>"u"&&(n=await r()),n);if(e===null){let te=await u();await ae.mktempPromise(async le=>{let ce=K.join(le,"yarn.cjs");await ae.writeFilePromise(ce,te);let{stdout:ue}=await Hr.execvp(process.execPath,[Ae.fromPortablePath(ce),"--version"],{cwd:le,env:{...t.env,YARN_IGNORE_PATH:"1"}});if(e=ue.trim(),!Ude.default.valid(e))throw new Error(`Invalid semver version. ${pe.pretty(t,"yarn --version",pe.Type.CODE)} returned: +${e}`)})}let A=t.projectCwd??t.startingCwd,p=K.resolve(A,".yarn/releases"),h=K.resolve(p,`yarn-${e}.cjs`),E=K.relative(t.startingCwd,h),I=qe.isTaggedYarnVersion(e),D=t.get("yarnPath"),x=!I,C=x||!!D||!!a;if(a===!1){if(x)throw new zt(0,"You explicitly opted out of yarnPath usage in your command line, but the version you specified cannot be represented by Corepack");C=!1}else!C&&!process.env.COREPACK_ROOT&&(o.reportWarning(0,`You don't seem to have ${pe.applyHyperlink(t,"Corepack","https://nodejs.org/api/corepack.html")} enabled; we'll have to rely on ${pe.applyHyperlink(t,"yarnPath","https://yarnpkg.com/configuration/yarnrc#yarnPath")} instead`),C=!0);if(C){let te=await u();o.reportInfo(0,`Saving the new release in ${pe.pretty(t,E,"magenta")}`),await ae.removePromise(K.dirname(h)),await ae.mkdirPromise(K.dirname(h),{recursive:!0}),await ae.writeFilePromise(h,te,{mode:493}),await Je.updateConfiguration(A,{yarnPath:K.relative(A,h)})}else await ae.removePromise(K.dirname(h)),await Je.updateConfiguration(A,{yarnPath:Je.deleteProperty});let T=await _t.tryFind(A)||new _t;T.packageManager=`yarn@${I?e:await M2(t,"stable")}`;let L={};T.exportTo(L);let U=K.join(A,_t.fileName),z=`${JSON.stringify(L,null,T.indent)} +`;return await ae.changeFilePromise(U,z,{automaticNewlines:!0}),{bundleVersion:e}}function _de(t){return vr[qP(t)]}var M0t=/## (?YN[0-9]{4}) - `(?[A-Z_]+)`\n\n(?

(?:.(?!##))+)/gs;async function O0t(t){let r=`https://repo.yarnpkg.com/${qe.isTaggedYarnVersion(nn)?nn:await M2(t,"canary")}/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx`,o=await on.get(r,{configuration:t});return new Map(Array.from(o.toString().matchAll(M0t),({groups:a})=>{if(!a)throw new Error("Assertion failed: Expected the match to have been successful");let n=_de(a.code);if(a.name!==n)throw new Error(`Assertion failed: Invalid error code data: Expected "${a.name}" to be named "${n}"`);return[a.code,a.details]}))}var SE=class extends ut{constructor(){super(...arguments);this.code=de.String({required:!1,validator:vI(Sm(),[BI(/^YN[0-9]{4}$/)])});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["explain"]]}static{this.usage=st.Usage({description:"explain an error code",details:` + When the code argument is specified, this command prints its name and its details. + + When used without arguments, this command lists all error codes and their names. + `,examples:[["Explain an error code","$0 explain YN0006"],["List all error codes","$0 explain"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);if(typeof this.code<"u"){let o=_de(this.code),a=pe.pretty(r,o,pe.Type.CODE),n=this.cli.format().header(`${this.code} - ${a}`),A=(await O0t(r)).get(this.code),p=typeof A<"u"?pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.MARKDOWN,{text:A,format:this.cli.format(),paragraphs:!0})):`This error code does not have a description. + +You can help us by editing this page on GitHub \u{1F642}: +${pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.URL,"https://github.com/yarnpkg/berry/blob/master/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx"))} +`;this.json?this.context.stdout.write(`${JSON.stringify({code:this.code,name:o,details:p})} +`):this.context.stdout.write(`${n} + +${p} +`)}else{let o={children:qe.mapAndFilter(Object.entries(vr),([a,n])=>Number.isNaN(Number(a))?qe.mapAndFilter.skip:{label:zu(Number(a)),value:pe.tuple(pe.Type.CODE,n)})};As.emitTree(o,{configuration:r,stdout:this.context.stdout,json:this.json})}}};Ke();Pt();Gt();var Hde=et(Xo()),bE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Print versions of a package from the whole project"});this.recursive=de.Boolean("-R,--recursive",!1,{description:"Print information for all packages, including transitive dependencies"});this.extra=de.Array("-X,--extra",[],{description:"An array of requests of extra data provided by plugins"});this.cache=de.Boolean("--cache",!1,{description:"Print information about the cache entry of a package (path, size, checksum)"});this.dependents=de.Boolean("--dependents",!1,{description:"Print all dependents for each matching package"});this.manifest=de.Boolean("--manifest",!1,{description:"Print data obtained by looking at the package archive (license, homepage, ...)"});this.nameOnly=de.Boolean("--name-only",!1,{description:"Only print the name for the matching packages"});this.virtuals=de.Boolean("--virtuals",!1,{description:"Print each instance of the virtual packages"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.patterns=de.Rest()}static{this.paths=[["info"]]}static{this.usage=st.Usage({description:"see information related to packages",details:"\n This command prints various information related to the specified packages, accepting glob patterns.\n\n By default, if the locator reference is missing, Yarn will default to print the information about all the matching direct dependencies of the package for the active workspace. To instead print all versions of the package that are direct dependencies of any of your workspaces, use the `-A,--all` flag. Adding the `-R,--recursive` flag will also report transitive dependencies.\n\n Some fields will be hidden by default in order to keep the output readable, but can be selectively displayed by using additional options (`--dependents`, `--manifest`, `--virtuals`, ...) described in the option descriptions.\n\n Note that this command will only print the information directly related to the selected packages - if you wish to know why the package is there in the first place, use `yarn why` which will do just that (it also provides a `-R,--recursive` flag that may be of some help).\n ",examples:[["Show information about Lodash","$0 info lodash"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a&&!this.all)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let u=new Set(this.extra);this.cache&&u.add("cache"),this.dependents&&u.add("dependents"),this.manifest&&u.add("manifest");let A=(le,{recursive:ce})=>{let ue=le.anchoredLocator.locatorHash,Ce=new Map,he=[ue];for(;he.length>0;){let De=he.shift();if(Ce.has(De))continue;let Ee=o.storedPackages.get(De);if(typeof Ee>"u")throw new Error("Assertion failed: Expected the package to be registered");if(Ce.set(De,Ee),G.isVirtualLocator(Ee)&&he.push(G.devirtualizeLocator(Ee).locatorHash),!(!ce&&De!==ue))for(let g of Ee.dependencies.values()){let me=o.storedResolutions.get(g.descriptorHash);if(typeof me>"u")throw new Error("Assertion failed: Expected the resolution to be registered");he.push(me)}}return Ce.values()},p=({recursive:le})=>{let ce=new Map;for(let ue of o.workspaces)for(let Ce of A(ue,{recursive:le}))ce.set(Ce.locatorHash,Ce);return ce.values()},h=({all:le,recursive:ce})=>le&&ce?o.storedPackages.values():le?p({recursive:ce}):A(a,{recursive:ce}),E=({all:le,recursive:ce})=>{let ue=h({all:le,recursive:ce}),Ce=this.patterns.map(Ee=>{let g=G.parseLocator(Ee),me=Hde.default.makeRe(G.stringifyIdent(g)),we=G.isVirtualLocator(g),fe=we?G.devirtualizeLocator(g):g;return ie=>{let Z=G.stringifyIdent(ie);if(!me.test(Z))return!1;if(g.reference==="unknown")return!0;let xe=G.isVirtualLocator(ie),Re=xe?G.devirtualizeLocator(ie):ie;return!(we&&xe&&g.reference!==ie.reference||fe.reference!==Re.reference)}}),he=qe.sortMap([...ue],Ee=>G.stringifyLocator(Ee));return{selection:he.filter(Ee=>Ce.length===0||Ce.some(g=>g(Ee))),sortedLookup:he}},{selection:I,sortedLookup:D}=E({all:this.all,recursive:this.recursive});if(I.length===0)throw new ot("No package matched your request");let x=new Map;if(this.dependents)for(let le of D)for(let ce of le.dependencies.values()){let ue=o.storedResolutions.get(ce.descriptorHash);if(typeof ue>"u")throw new Error("Assertion failed: Expected the resolution to be registered");qe.getArrayWithDefault(x,ue).push(le)}let C=new Map;for(let le of D){if(!G.isVirtualLocator(le))continue;let ce=G.devirtualizeLocator(le);qe.getArrayWithDefault(C,ce.locatorHash).push(le)}let T={},L={children:T},U=r.makeFetcher(),z={project:o,fetcher:U,cache:n,checksums:o.storedChecksums,report:new Ri,cacheOptions:{skipIntegrityCheck:!0}},te=[async(le,ce,ue)=>{if(!ce.has("manifest"))return;let Ce=await U.fetch(le,z),he;try{he=await _t.find(Ce.prefixPath,{baseFs:Ce.packageFs})}finally{Ce.releaseFs?.()}ue("Manifest",{License:pe.tuple(pe.Type.NO_HINT,he.license),Homepage:pe.tuple(pe.Type.URL,he.raw.homepage??null)})},async(le,ce,ue)=>{if(!ce.has("cache"))return;let Ce=o.storedChecksums.get(le.locatorHash)??null,he=n.getLocatorPath(le,Ce),De;if(he!==null)try{De=await ae.statPromise(he)}catch{}let Ee=typeof De<"u"?[De.size,pe.Type.SIZE]:void 0;ue("Cache",{Checksum:pe.tuple(pe.Type.NO_HINT,Ce),Path:pe.tuple(pe.Type.PATH,he),Size:Ee})}];for(let le of I){let ce=G.isVirtualLocator(le);if(!this.virtuals&&ce)continue;let ue={},Ce={value:[le,pe.Type.LOCATOR],children:ue};if(T[G.stringifyLocator(le)]=Ce,this.nameOnly){delete Ce.children;continue}let he=C.get(le.locatorHash);typeof he<"u"&&(ue.Instances={label:"Instances",value:pe.tuple(pe.Type.NUMBER,he.length)}),ue.Version={label:"Version",value:pe.tuple(pe.Type.NO_HINT,le.version)};let De=(g,me)=>{let we={};if(ue[g]=we,Array.isArray(me))we.children=me.map(fe=>({value:fe}));else{let fe={};we.children=fe;for(let[ie,Z]of Object.entries(me))typeof Z>"u"||(fe[ie]={label:ie,value:Z})}};if(!ce){for(let g of te)await g(le,u,De);await r.triggerHook(g=>g.fetchPackageInfo,le,u,De)}le.bin.size>0&&!ce&&De("Exported Binaries",[...le.bin.keys()].map(g=>pe.tuple(pe.Type.PATH,g)));let Ee=x.get(le.locatorHash);typeof Ee<"u"&&Ee.length>0&&De("Dependents",Ee.map(g=>pe.tuple(pe.Type.LOCATOR,g))),le.dependencies.size>0&&!ce&&De("Dependencies",[...le.dependencies.values()].map(g=>{let me=o.storedResolutions.get(g.descriptorHash),we=typeof me<"u"?o.storedPackages.get(me)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:we})})),le.peerDependencies.size>0&&ce&&De("Peer dependencies",[...le.peerDependencies.values()].map(g=>{let me=le.dependencies.get(g.identHash),we=typeof me<"u"?o.storedResolutions.get(me.descriptorHash)??null:null,fe=we!==null?o.storedPackages.get(we)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:fe})}))}As.emitTree(L,{configuration:r,json:this.json,stdout:this.context.stdout,separators:this.nameOnly?0:2})}};Ke();Pt();Ml();var Kk=et(sg());Gt();var IH=et(ni());il();var U0t=[{selector:t=>t===-1,name:"nodeLinker",value:"node-modules"},{selector:t=>t!==-1&&t<8,name:"enableGlobalCache",value:!1},{selector:t=>t!==-1&&t<8,name:"compressionLevel",value:"mixed"}],xE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.immutable=de.Boolean("--immutable",{description:"Abort with an error exit code if the lockfile was to be modified"});this.immutableCache=de.Boolean("--immutable-cache",{description:"Abort with an error exit code if the cache folder was to be modified"});this.refreshLockfile=de.Boolean("--refresh-lockfile",{description:"Refresh the package metadata stored in the lockfile"});this.checkCache=de.Boolean("--check-cache",{description:"Always refetch the packages and ensure that their checksums are consistent"});this.checkResolutions=de.Boolean("--check-resolutions",{description:"Validates that the package resolutions are coherent"});this.inlineBuilds=de.Boolean("--inline-builds",{description:"Verbosely print the output of the build steps of dependencies"});this.mode=de.String("--mode",{description:"Change what artifacts installs generate",validator:js(yl)});this.cacheFolder=de.String("--cache-folder",{hidden:!0});this.frozenLockfile=de.Boolean("--frozen-lockfile",{hidden:!0});this.ignoreEngines=de.Boolean("--ignore-engines",{hidden:!0});this.nonInteractive=de.Boolean("--non-interactive",{hidden:!0});this.preferOffline=de.Boolean("--prefer-offline",{hidden:!0});this.production=de.Boolean("--production",{hidden:!0});this.registry=de.String("--registry",{hidden:!0});this.silent=de.Boolean("--silent",{hidden:!0});this.networkTimeout=de.String("--network-timeout",{hidden:!0})}static{this.paths=[["install"],st.Default]}static{this.usage=st.Usage({description:"install the project dependencies",details:"\n This command sets up your project if needed. The installation is split into four different steps that each have their own characteristics:\n\n - **Resolution:** First the package manager will resolve your dependencies. The exact way a dependency version is privileged over another isn't standardized outside of the regular semver guarantees. If a package doesn't resolve to what you would expect, check that all dependencies are correctly declared (also check our website for more information: ).\n\n - **Fetch:** Then we download all the dependencies if needed, and make sure that they're all stored within our cache (check the value of `cacheFolder` in `yarn config` to see where the cache files are stored).\n\n - **Link:** Then we send the dependency tree information to internal plugins tasked with writing them on the disk in some form (for example by generating the `.pnp.cjs` file you might know).\n\n - **Build:** Once the dependency tree has been written on the disk, the package manager will now be free to run the build scripts for all packages that might need it, in a topological order compatible with the way they depend on one another. See https://yarnpkg.com/advanced/lifecycle-scripts for detail.\n\n Note that running this command is not part of the recommended workflow. Yarn supports zero-installs, which means that as long as you store your cache and your `.pnp.cjs` file inside your repository, everything will work without requiring any install right after cloning your repository or switching branches.\n\n If the `--immutable` option is set (defaults to true on CI), Yarn will abort with an error exit code if the lockfile was to be modified (other paths can be added using the `immutablePatterns` configuration setting). For backward compatibility we offer an alias under the name of `--frozen-lockfile`, but it will be removed in a later release.\n\n If the `--immutable-cache` option is set, Yarn will abort with an error exit code if the cache folder was to be modified (either because files would be added, or because they'd be removed).\n\n If the `--refresh-lockfile` option is set, Yarn will keep the same resolution for the packages currently in the lockfile but will refresh their metadata. If used together with `--immutable`, it can validate that the lockfile information are consistent. This flag is enabled by default when Yarn detects it runs within a pull request context.\n\n If the `--check-cache` option is set, Yarn will always refetch the packages and will ensure that their checksum matches what's 1/ described in the lockfile 2/ inside the existing cache files (if present). This is recommended as part of your CI workflow if you're both following the Zero-Installs model and accepting PRs from third-parties, as they'd otherwise have the ability to alter the checked-in packages before submitting them.\n\n If the `--inline-builds` option is set, Yarn will verbosely print the output of the build steps of your dependencies (instead of writing them into individual files). This is likely useful mostly for debug purposes only when using Docker-like environments.\n\n If the `--mode=` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n ",examples:[["Install the project","$0 install"],["Validate a project when using Zero-Installs","$0 install --immutable --immutable-cache"],["Validate a project when using Zero-Installs (slightly safer if you accept external PRs)","$0 install --immutable --immutable-cache --check-cache"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);typeof this.inlineBuilds<"u"&&r.useWithSource("",{enableInlineBuilds:this.inlineBuilds},r.startingCwd,{overwrite:!0});let o=!!process.env.FUNCTION_TARGET||!!process.env.GOOGLE_RUNTIME,a=await Qy({configuration:r,stdout:this.context.stdout},[{option:this.ignoreEngines,message:"The --ignore-engines option is deprecated; engine checking isn't a core feature anymore",error:!Kk.default.VERCEL},{option:this.registry,message:"The --registry option is deprecated; prefer setting npmRegistryServer in your .yarnrc.yml file"},{option:this.preferOffline,message:"The --prefer-offline flag is deprecated; use the --cached flag with 'yarn add' instead",error:!Kk.default.VERCEL},{option:this.production,message:"The --production option is deprecated on 'install'; use 'yarn workspaces focus' instead",error:!0},{option:this.nonInteractive,message:"The --non-interactive option is deprecated",error:!o},{option:this.frozenLockfile,message:"The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead",callback:()=>this.immutable=this.frozenLockfile},{option:this.cacheFolder,message:"The cache-folder option has been deprecated; use rc settings instead",error:!Kk.default.NETLIFY}]);if(a!==null)return a;let n=this.mode==="update-lockfile";if(n&&(this.immutable||this.immutableCache))throw new ot(`${pe.pretty(r,"--immutable",pe.Type.CODE)} and ${pe.pretty(r,"--immutable-cache",pe.Type.CODE)} cannot be used with ${pe.pretty(r,"--mode=update-lockfile",pe.Type.CODE)}`);let u=(this.immutable??r.get("enableImmutableInstalls"))&&!n,A=this.immutableCache&&!n;if(r.projectCwd!==null){let T=await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{let U=!1;await q0t(r,u)&&(L.reportInfo(48,"Automatically removed core plugins that are now builtins \u{1F44D}"),U=!0),await H0t(r,u)&&(L.reportInfo(48,"Automatically fixed merge conflicts \u{1F44D}"),U=!0),U&&L.reportSeparator()});if(T.hasErrors())return T.exitCode()}if(r.projectCwd!==null){let T=await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{if(Je.telemetry?.isNew)Je.telemetry.commitTips(),L.reportInfo(65,"Yarn will periodically gather anonymous telemetry: https://yarnpkg.com/advanced/telemetry"),L.reportInfo(65,`Run ${pe.pretty(r,"yarn config set --home enableTelemetry 0",pe.Type.CODE)} to disable`),L.reportSeparator();else if(Je.telemetry?.shouldShowTips){let U=await on.get("https://repo.yarnpkg.com/tags",{configuration:r,jsonResponse:!0}).catch(()=>null);if(U!==null){let z=null;if(nn!==null){let le=IH.default.prerelease(nn)?"canary":"stable",ce=U.latest[le];IH.default.gt(ce,nn)&&(z=[le,ce])}if(z)Je.telemetry.commitTips(),L.reportInfo(88,`${pe.applyStyle(r,`A new ${z[0]} version of Yarn is available:`,pe.Style.BOLD)} ${G.prettyReference(r,z[1])}!`),L.reportInfo(88,`Upgrade now by running ${pe.pretty(r,`yarn set version ${z[1]}`,pe.Type.CODE)}`),L.reportSeparator();else{let te=Je.telemetry.selectTip(U.tips);te&&(L.reportInfo(89,pe.pretty(r,te.message,pe.Type.MARKDOWN_INLINE)),te.url&&L.reportInfo(89,`Learn more at ${te.url}`),L.reportSeparator())}}}});if(T.hasErrors())return T.exitCode()}let{project:p,workspace:h}=await Qt.find(r,this.context.cwd),E=p.lockfileLastVersion;if(E!==null){let T=await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{let U={};for(let z of U0t)z.selector(E)&&typeof r.sources.get(z.name)>"u"&&(r.use("",{[z.name]:z.value},p.cwd,{overwrite:!0}),U[z.name]=z.value);Object.keys(U).length>0&&(await Je.updateConfiguration(p.cwd,U),L.reportInfo(87,"Migrated your project to the latest Yarn version \u{1F680}"),L.reportSeparator())});if(T.hasErrors())return T.exitCode()}let I=await Yr.find(r,{immutable:A,check:this.checkCache});if(!h)throw new or(p.cwd,this.context.cwd);await p.restoreInstallState({restoreResolutions:!1});let D=r.get("enableHardenedMode");D&&typeof r.sources.get("enableHardenedMode")>"u"&&await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async T=>{T.reportWarning(0,"Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled."),T.reportWarning(0,`It will prevent malicious lockfile manipulations, in exchange for a slower install time. You can opt-out if necessary; check our ${pe.applyHyperlink(r,"documentation","https://yarnpkg.com/features/security#hardened-mode")} for more details.`),T.reportSeparator()}),(this.refreshLockfile??D)&&(p.lockfileNeedsRefresh=!0);let x=this.checkResolutions??D;return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout,forceSectionAlignment:!0,includeLogs:!0,includeVersion:!0},async T=>{await p.install({cache:I,report:T,immutable:u,checkResolutions:x,mode:this.mode})})).exitCode()}},_0t="<<<<<<<";async function H0t(t,e){if(!t.projectCwd)return!1;let r=K.join(t.projectCwd,mr.lockfile);if(!await ae.existsPromise(r)||!(await ae.readFilePromise(r,"utf8")).includes(_0t))return!1;if(e)throw new zt(47,"Cannot autofix a lockfile when running an immutable install");let a=await Hr.execvp("git",["rev-parse","MERGE_HEAD","HEAD"],{cwd:t.projectCwd});if(a.code!==0&&(a=await Hr.execvp("git",["rev-parse","REBASE_HEAD","HEAD"],{cwd:t.projectCwd})),a.code!==0&&(a=await Hr.execvp("git",["rev-parse","CHERRY_PICK_HEAD","HEAD"],{cwd:t.projectCwd})),a.code!==0)throw new zt(83,"Git returned an error when trying to find the commits pertaining to the conflict");let n=await Promise.all(a.stdout.trim().split(/\n/).map(async A=>{let p=await Hr.execvp("git",["show",`${A}:./${mr.lockfile}`],{cwd:t.projectCwd});if(p.code!==0)throw new zt(83,`Git returned an error when trying to access the lockfile content in ${A}`);try{return Ki(p.stdout)}catch{throw new zt(46,"A variant of the conflicting lockfile failed to parse")}}));n=n.filter(A=>!!A.__metadata);for(let A of n){if(A.__metadata.version<7)for(let p of Object.keys(A)){if(p==="__metadata")continue;let h=G.parseDescriptor(p,!0),E=t.normalizeDependency(h),I=G.stringifyDescriptor(E);I!==p&&(A[I]=A[p],delete A[p])}for(let p of Object.keys(A)){if(p==="__metadata")continue;let h=A[p].checksum;typeof h=="string"&&h.includes("/")||(A[p].checksum=`${A.__metadata.cacheKey}/${h}`)}}let u=Object.assign({},...n);u.__metadata.version=`${Math.min(...n.map(A=>parseInt(A.__metadata.version??0)))}`,u.__metadata.cacheKey="merged";for(let[A,p]of Object.entries(u))typeof p=="string"&&delete u[A];return await ae.changeFilePromise(r,Pa(u),{automaticNewlines:!0}),!0}async function q0t(t,e){if(!t.projectCwd)return!1;let r=[],o=K.join(t.projectCwd,".yarn/plugins/@yarnpkg");return await Je.updateConfiguration(t.projectCwd,{plugins:n=>{if(!Array.isArray(n))return n;let u=n.filter(A=>{if(!A.path)return!0;let p=K.resolve(t.projectCwd,A.path),h=j1.has(A.spec)&&K.contains(o,p);return h&&r.push(p),!h});return u.length===0?Je.deleteProperty:u.length===n.length?n:u}},{immutable:e})?(await Promise.all(r.map(async n=>{await ae.removePromise(n)})),!0):!1}Ke();Pt();Gt();var kE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Link all workspaces belonging to the target projects to the current one"});this.private=de.Boolean("-p,--private",!1,{description:"Also link private workspaces belonging to the target projects to the current one"});this.relative=de.Boolean("-r,--relative",!1,{description:"Link workspaces using relative paths instead of absolute paths"});this.destinations=de.Rest()}static{this.paths=[["link"]]}static{this.usage=st.Usage({description:"connect the local project to another one",details:"\n This command will set a new `resolutions` field in the project-level manifest and point it to the workspace at the specified location (even if part of another project).\n ",examples:[["Register one or more remote workspaces for use in the current project","$0 link ~/ts-loader ~/jest"],["Register all workspaces from a remote project for use in the current project","$0 link ~/jest --all"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=o.topLevelWorkspace,A=[];for(let p of this.destinations){let h=K.resolve(this.context.cwd,Ae.toPortablePath(p)),E=await Je.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:I,workspace:D}=await Qt.find(E,h);if(o.cwd===I.cwd)throw new ot(`Invalid destination '${p}'; Can't link the project to itself`);if(!D)throw new or(I.cwd,h);if(this.all){let x=!1;for(let C of I.workspaces)C.manifest.name&&(!C.manifest.private||this.private)&&(A.push(C),x=!0);if(!x)throw new ot(`No workspace found to be linked in the target project: ${p}`)}else{if(!D.manifest.name)throw new ot(`The target workspace at '${p}' doesn't have a name and thus cannot be linked`);if(D.manifest.private&&!this.private)throw new ot(`The target workspace at '${p}' is marked private - use the --private flag to link it anyway`);A.push(D)}}for(let p of A){let h=G.stringifyIdent(p.anchoredLocator),E=this.relative?K.relative(o.cwd,p.cwd):p.cwd;u.manifest.resolutions.push({pattern:{descriptor:{fullName:h}},reference:`portal:${E}`})}return await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Gt();var QE=class extends ut{constructor(){super(...arguments);this.args=de.Proxy()}static{this.paths=[["node"]]}static{this.usage=st.Usage({description:"run node with the hook already setup",details:` + This command simply runs Node. It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment). + + The Node process will use the exact same version of Node as the one used to run Yarn itself, which might be a good way to ensure that your commands always use a consistent Node version. + `,examples:[["Run a Node script","$0 node ./my-script.js"]]})}async execute(){return this.cli.run(["exec","node",...this.args])}};Ke();Gt();var FE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","check"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"find all third-party plugins that differ from their own spec",details:` + Check only the plugins from https. + + If this command detects any plugin differences in the CI environment, it will throw an error. + `,examples:[["find all third-party plugins that differ from their own spec","$0 plugin check"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await Je.findRcFiles(this.context.cwd);return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{for(let u of o)if(u.data?.plugins)for(let A of u.data.plugins){if(!A.checksum||!A.spec.match(/^https?:/))continue;let p=await on.get(A.spec,{configuration:r}),h=xn.makeHash(p);if(A.checksum===h)continue;let E=pe.pretty(r,A.path,pe.Type.PATH),I=pe.pretty(r,A.spec,pe.Type.URL),D=`${E} is different from the file provided by ${I}`;n.reportJson({...A,newChecksum:h}),n.reportError(0,D)}})).exitCode()}};Ke();Ke();Pt();Gt();var Wde=ve("os");Ke();Pt();Gt();var qde=ve("os");Ke();Ml();Gt();var j0t="https://raw.githubusercontent.com/yarnpkg/berry/master/plugins.yml";async function zg(t,e){let r=await on.get(j0t,{configuration:t}),o=Ki(r.toString());return Object.fromEntries(Object.entries(o).filter(([a,n])=>!e||Ur.satisfiesWithPrereleases(e,n.range??"<4.0.0-rc.1")))}var RE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","list"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"list the available official plugins",details:"\n This command prints the plugins available directly from the Yarn repository. Only those plugins can be referenced by name in `yarn plugin import`.\n ",examples:[["List the official plugins","$0 plugin list"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{let n=await zg(r,nn);for(let[u,{experimental:A,...p}]of Object.entries(n)){let h=u;A&&(h+=" [experimental]"),a.reportJson({name:u,experimental:A,...p}),a.reportInfo(null,h)}})).exitCode()}};var G0t=/^[0-9]+$/,Y0t=process.platform==="win32";function jde(t){return G0t.test(t)?`pull/${t}/head`:t}var W0t=({repository:t,branch:e},r)=>[["git","init",Ae.fromPortablePath(r)],["git","remote","add","origin",t],["git","fetch","origin","--depth=1",jde(e)],["git","reset","--hard","FETCH_HEAD"]],K0t=({branch:t})=>[["git","fetch","origin","--depth=1",jde(t),"--force"],["git","reset","--hard","FETCH_HEAD"],["git","clean","-dfx","-e","packages/yarnpkg-cli/bundles"]],V0t=({plugins:t,noMinify:e},r,o)=>[["yarn","build:cli",...new Array().concat(...t.map(a=>["--plugin",K.resolve(o,a)])),...e?["--no-minify"]:[],"|"],[Y0t?"move":"mv","packages/yarnpkg-cli/bundles/yarn.js",Ae.fromPortablePath(r),"|"]],TE=class extends ut{constructor(){super(...arguments);this.installPath=de.String("--path",{description:"The path where the repository should be cloned to"});this.repository=de.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=de.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.plugins=de.Array("--plugin",[],{description:"An array of additional plugins that should be included in the bundle"});this.dryRun=de.Boolean("-n,--dry-run",!1,{description:"If set, the bundle will be built but not added to the project"});this.noMinify=de.Boolean("--no-minify",!1,{description:"Build a bundle for development (debugging) - non-minified and non-mangled"});this.force=de.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.skipPlugins=de.Boolean("--skip-plugins",!1,{description:"Skip updating the contrib plugins"})}static{this.paths=[["set","version","from","sources"]]}static{this.usage=st.Usage({description:"build Yarn from master",details:` + This command will clone the Yarn repository into a temporary folder, then build it. The resulting bundle will then be copied into the local project. + + By default, it also updates all contrib plugins to the same commit the bundle is built from. This behavior can be disabled by using the \`--skip-plugins\` flag. + `,examples:[["Build Yarn from master","$0 set version from sources"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=typeof this.installPath<"u"?K.resolve(this.context.cwd,Ae.toPortablePath(this.installPath)):K.resolve(Ae.toPortablePath((0,qde.tmpdir)()),"yarnpkg-sources",xn.makeHash(this.repository).slice(0,6));return(await Nt.start({configuration:r,stdout:this.context.stdout},async u=>{await BH(this,{configuration:r,report:u,target:a}),u.reportSeparator(),u.reportInfo(0,"Building a fresh bundle"),u.reportSeparator();let A=await Hr.execvp("git",["rev-parse","--short","HEAD"],{cwd:a,strict:!0}),p=K.join(a,`packages/yarnpkg-cli/bundles/yarn-${A.stdout.trim()}.js`);ae.existsSync(p)||(await O2(V0t(this,p,a),{configuration:r,context:this.context,target:a}),u.reportSeparator());let h=await ae.readFilePromise(p);if(!this.dryRun){let{bundleVersion:E}=await wH(r,null,async()=>h,{report:u});this.skipPlugins||await z0t(this,E,{project:o,report:u,target:a})}})).exitCode()}};async function O2(t,{configuration:e,context:r,target:o}){for(let[a,...n]of t){let u=n[n.length-1]==="|";if(u&&n.pop(),u)await Hr.pipevp(a,n,{cwd:o,stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,strict:!0});else{r.stdout.write(`${pe.pretty(e,` $ ${[a,...n].join(" ")}`,"grey")} +`);try{await Hr.execvp(a,n,{cwd:o,strict:!0})}catch(A){throw r.stdout.write(A.stdout||A.stack),A}}}}async function BH(t,{configuration:e,report:r,target:o}){let a=!1;if(!t.force&&ae.existsSync(K.join(o,".git"))){r.reportInfo(0,"Fetching the latest commits"),r.reportSeparator();try{await O2(K0t(t),{configuration:e,context:t.context,target:o}),a=!0}catch{r.reportSeparator(),r.reportWarning(0,"Repository update failed; we'll try to regenerate it")}}a||(r.reportInfo(0,"Cloning the remote repository"),r.reportSeparator(),await ae.removePromise(o),await ae.mkdirPromise(o,{recursive:!0}),await O2(W0t(t,o),{configuration:e,context:t.context,target:o}))}async function z0t(t,e,{project:r,report:o,target:a}){let n=await zg(r.configuration,e),u=new Set(Object.keys(n));for(let A of r.configuration.plugins.keys())u.has(A)&&await vH(A,t,{project:r,report:o,target:a})}Ke();Ke();Pt();Gt();var Gde=et(ni()),Yde=ve("vm");var NE=class extends ut{constructor(){super(...arguments);this.name=de.String();this.checksum=de.Boolean("--checksum",!0,{description:"Whether to care if this plugin is modified"})}static{this.paths=[["plugin","import"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"download a plugin",details:` + This command downloads the specified plugin from its remote location and updates the configuration to reference it in further CLI invocations. + + Three types of plugin references are accepted: + + - If the plugin is stored within the Yarn repository, it can be referenced by name. + - Third-party plugins can be referenced directly through their public urls. + - Local plugins can be referenced by their path on the disk. + + If the \`--no-checksum\` option is set, Yarn will no longer care if the plugin is modified. + + Plugins cannot be downloaded from the npm registry, and aren't allowed to have dependencies (they need to be bundled into a single file, possibly thanks to the \`@yarnpkg/builder\` package). + `,examples:[['Download and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import @yarnpkg/plugin-exec"],['Download and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import exec"],["Download and activate a community plugin","$0 plugin import https://example.org/path/to/plugin.js"],["Activate a local plugin","$0 plugin import ./path/to/plugin.js"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Nt.start({configuration:r,stdout:this.context.stdout},async a=>{let{project:n}=await Qt.find(r,this.context.cwd),u,A;if(this.name.match(/^\.{0,2}[\\/]/)||Ae.isAbsolute(this.name)){let p=K.resolve(this.context.cwd,Ae.toPortablePath(this.name));a.reportInfo(0,`Reading ${pe.pretty(r,p,pe.Type.PATH)}`),u=K.relative(n.cwd,p),A=await ae.readFilePromise(p)}else{let p;if(this.name.match(/^https?:/)){try{new URL(this.name)}catch{throw new zt(52,`Plugin specifier "${this.name}" is neither a plugin name nor a valid url`)}u=this.name,p=this.name}else{let h=G.parseLocator(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-"));if(h.reference!=="unknown"&&!Gde.default.valid(h.reference))throw new zt(0,"Official plugins only accept strict version references. Use an explicit URL if you wish to download them from another location.");let E=G.stringifyIdent(h),I=await zg(r,nn);if(!Object.hasOwn(I,E)){let D=`Couldn't find a plugin named ${G.prettyIdent(r,h)} on the remote registry. +`;throw r.plugins.has(E)?D+=`A plugin named ${G.prettyIdent(r,h)} is already installed; possibly attempting to import a built-in plugin.`:D+=`Note that only the plugins referenced on our website (${pe.pretty(r,"https://github.com/yarnpkg/berry/blob/master/plugins.yml",pe.Type.URL)}) can be referenced by their name; any other plugin will have to be referenced through its public url (for example ${pe.pretty(r,"https://github.com/yarnpkg/berry/raw/master/packages/plugin-typescript/bin/%40yarnpkg/plugin-typescript.js",pe.Type.URL)}).`,new zt(51,D)}u=E,p=I[E].url,h.reference!=="unknown"?p=p.replace(/\/master\//,`/${E}/${h.reference}/`):nn!==null&&(p=p.replace(/\/master\//,`/@yarnpkg/cli/${nn}/`))}a.reportInfo(0,`Downloading ${pe.pretty(r,p,"green")}`),A=await on.get(p,{configuration:r})}await DH(u,A,{checksum:this.checksum,project:n,report:a})})).exitCode()}};async function DH(t,e,{checksum:r=!0,project:o,report:a}){let{configuration:n}=o,u={},A={exports:u};(0,Yde.runInNewContext)(e.toString(),{module:A,exports:u});let h=`.yarn/plugins/${A.exports.name}.cjs`,E=K.resolve(o.cwd,h);a.reportInfo(0,`Saving the new plugin in ${pe.pretty(n,h,"magenta")}`),await ae.mkdirPromise(K.dirname(E),{recursive:!0}),await ae.writeFilePromise(E,e);let I={path:h,spec:t};r&&(I.checksum=xn.makeHash(e)),await Je.addPlugin(o.cwd,[I])}var J0t=({pluginName:t,noMinify:e},r)=>[["yarn",`build:${t}`,...e?["--no-minify"]:[],"|"]],LE=class extends ut{constructor(){super(...arguments);this.installPath=de.String("--path",{description:"The path where the repository should be cloned to"});this.repository=de.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=de.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.noMinify=de.Boolean("--no-minify",!1,{description:"Build a plugin for development (debugging) - non-minified and non-mangled"});this.force=de.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.name=de.String()}static{this.paths=[["plugin","import","from","sources"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"build a plugin from sources",details:` + This command clones the Yarn repository into a temporary folder, builds the specified contrib plugin and updates the configuration to reference it in further CLI invocations. + + The plugins can be referenced by their short name if sourced from the official Yarn repository. + `,examples:[['Build and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import from sources @yarnpkg/plugin-exec"],['Build and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import from sources exec"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=typeof this.installPath<"u"?K.resolve(this.context.cwd,Ae.toPortablePath(this.installPath)):K.resolve(Ae.toPortablePath((0,Wde.tmpdir)()),"yarnpkg-sources",xn.makeHash(this.repository).slice(0,6));return(await Nt.start({configuration:r,stdout:this.context.stdout},async n=>{let{project:u}=await Qt.find(r,this.context.cwd),A=G.parseIdent(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-")),p=G.stringifyIdent(A),h=await zg(r,nn);if(!Object.hasOwn(h,p))throw new zt(51,`Couldn't find a plugin named "${p}" on the remote registry. Note that only the plugins referenced on our website (https://github.com/yarnpkg/berry/blob/master/plugins.yml) can be built and imported from sources.`);let E=p;await BH(this,{configuration:r,report:n,target:o}),await vH(E,this,{project:u,report:n,target:o})})).exitCode()}};async function vH(t,{context:e,noMinify:r},{project:o,report:a,target:n}){let u=t.replace(/@yarnpkg\//,""),{configuration:A}=o;a.reportSeparator(),a.reportInfo(0,`Building a fresh ${u}`),a.reportSeparator(),await O2(J0t({pluginName:u,noMinify:r},n),{configuration:A,context:e,target:n}),a.reportSeparator();let p=K.resolve(n,`packages/${u}/bundles/${t}.js`),h=await ae.readFilePromise(p);await DH(t,h,{project:o,report:a})}Ke();Pt();Gt();var ME=class extends ut{constructor(){super(...arguments);this.name=de.String()}static{this.paths=[["plugin","remove"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"remove a plugin",details:` + This command deletes the specified plugin from the .yarn/plugins folder and removes it from the configuration. + + **Note:** The plugins have to be referenced by their name property, which can be obtained using the \`yarn plugin runtime\` command. Shorthands are not allowed. + `,examples:[["Remove a plugin imported from the Yarn repository","$0 plugin remove @yarnpkg/plugin-typescript"],["Remove a plugin imported from a local file","$0 plugin remove my-local-plugin"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return(await Nt.start({configuration:r,stdout:this.context.stdout},async n=>{let u=this.name,A=G.parseIdent(u);if(!r.plugins.has(u))throw new ot(`${G.prettyIdent(r,A)} isn't referenced by the current configuration`);let p=`.yarn/plugins/${u}.cjs`,h=K.resolve(o.cwd,p);ae.existsSync(h)&&(n.reportInfo(0,`Removing ${pe.pretty(r,p,pe.Type.PATH)}...`),await ae.removePromise(h)),n.reportInfo(0,"Updating the configuration..."),await Je.updateConfiguration(o.cwd,{plugins:E=>{if(!Array.isArray(E))return E;let I=E.filter(D=>D.path!==p);return I.length===0?Je.deleteProperty:I.length===E.length?E:I}})})).exitCode()}};Ke();Gt();var OE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","runtime"]]}static{this.usage=st.Usage({category:"Plugin-related commands",description:"list the active plugins",details:` + This command prints the currently active plugins. Will be displayed both builtin plugins and external plugins. + `,examples:[["List the currently active plugins","$0 plugin runtime"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{for(let n of r.plugins.keys()){let u=this.context.plugins.plugins.has(n),A=n;u&&(A+=" [builtin]"),a.reportJson({name:n,builtin:u}),a.reportInfo(null,`${A}`)}})).exitCode()}};Ke();Ke();Gt();var UE=class extends ut{constructor(){super(...arguments);this.idents=de.Rest()}static{this.paths=[["rebuild"]]}static{this.usage=st.Usage({description:"rebuild the project's native packages",details:` + This command will automatically cause Yarn to forget about previous compilations of the given packages and to run them again. + + Note that while Yarn forgets the compilation, the previous artifacts aren't erased from the filesystem and may affect the next builds (in good or bad). To avoid this, you may remove the .yarn/unplugged folder, or any other relevant location where packages might have been stored (Yarn may offer a way to do that automatically in the future). + + By default all packages will be rebuilt, but you can filter the list by specifying the names of the packages you want to clear from memory. + `,examples:[["Rebuild all packages","$0 rebuild"],["Rebuild fsevents only","$0 rebuild fsevents"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);let u=new Set;for(let A of this.idents)u.add(G.parseIdent(A).identHash);if(await o.restoreInstallState({restoreResolutions:!1}),await o.resolveEverything({cache:n,report:new Ri}),u.size>0)for(let A of o.storedPackages.values())u.has(A.identHash)&&(o.storedBuildState.delete(A.locatorHash),o.skippedBuilds.delete(A.locatorHash));else o.storedBuildState.clear(),o.skippedBuilds.clear();return await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ke();Ke();Ke();Gt();var PH=et(Xo());il();var _E=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Apply the operation to all workspaces from the current project"});this.mode=de.String("--mode",{description:"Change what artifacts installs generate",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[["remove"]]}static{this.usage=st.Usage({description:"remove dependencies from the project",details:` + This command will remove the packages matching the specified patterns from the current workspace. + + If the \`--mode=\` option is set, Yarn will change which artifacts are generated. The modes currently supported are: + + - \`skip-build\` will not run the build scripts at all. Note that this is different from setting \`enableScripts\` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run. + + - \`update-lockfile\` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost. + + This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them. + `,examples:[["Remove a dependency from the current project","$0 remove lodash"],["Remove a dependency from all workspaces at once","$0 remove lodash --all"],["Remove all dependencies starting with `eslint-`","$0 remove 'eslint-*'"],["Remove all dependencies with the `@babel` scope","$0 remove '@babel/*'"],["Remove all dependencies matching `react-dom` or `react-helmet`","$0 remove 'react-{dom,helmet}'"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.all?o.workspaces:[a],A=["dependencies","devDependencies","peerDependencies"],p=[],h=!1,E=[];for(let C of this.patterns){let T=!1,L=G.parseIdent(C);for(let U of u){let z=[...U.manifest.peerDependenciesMeta.keys()];for(let te of(0,PH.default)(z,C))U.manifest.peerDependenciesMeta.delete(te),h=!0,T=!0;for(let te of A){let le=U.manifest.getForScope(te),ce=[...le.values()].map(ue=>G.stringifyIdent(ue));for(let ue of(0,PH.default)(ce,G.stringifyIdent(L))){let{identHash:Ce}=G.parseIdent(ue),he=le.get(Ce);if(typeof he>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");U.manifest[te].delete(Ce),E.push([U,te,he]),h=!0,T=!0}}}T||p.push(C)}let I=p.length>1?"Patterns":"Pattern",D=p.length>1?"don't":"doesn't",x=this.all?"any":"this";if(p.length>0)throw new ot(`${I} ${pe.prettyList(r,p,pe.Type.CODE)} ${D} match any packages referenced by ${x} workspace`);return h?(await r.triggerMultipleHooks(C=>C.afterWorkspaceDependencyRemoval,E),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})):0}};Ke();Ke();Gt();var Kde=ve("util"),HE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["run"]]}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);return(await Nt.start({configuration:r,stdout:this.context.stdout,json:this.json},async u=>{let A=a.manifest.scripts,p=qe.sortMap(A.keys(),I=>I),h={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},E=p.reduce((I,D)=>Math.max(I,D.length),0);for(let[I,D]of A.entries())u.reportInfo(null,`${I.padEnd(E," ")} ${(0,Kde.inspect)(D,h)}`),u.reportJson({name:I,script:D})})).exitCode()}};Ke();Ke();Gt();var qE=class extends ut{constructor(){super(...arguments);this.inspect=de.String("--inspect",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.inspectBrk=de.String("--inspect-brk",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.topLevel=de.Boolean("-T,--top-level",!1,{description:"Check the root workspace for scripts and/or binaries instead of the current one"});this.binariesOnly=de.Boolean("-B,--binaries-only",!1,{description:"Ignore any user defined scripts and only check for binaries"});this.require=de.String("--require",{description:"Forwarded to the underlying Node process when executing a binary"});this.silent=de.Boolean("--silent",{hidden:!0});this.scriptName=de.String();this.args=de.Proxy()}static{this.paths=[["run"]]}static{this.usage=st.Usage({description:"run a script defined in the package.json",details:` + This command will run a tool. The exact tool that will be executed will depend on the current state of your workspace: + + - If the \`scripts\` field from your local package.json contains a matching script name, its definition will get executed. + + - Otherwise, if one of the local workspace's dependencies exposes a binary with a matching name, this binary will get executed. + + - Otherwise, if the specified name contains a colon character and if one of the workspaces in the project contains exactly one script with a matching name, then this script will get executed. + + Whatever happens, the cwd of the spawned process will be the workspace that declares the script (which makes it possible to call commands cross-workspaces using the third syntax). + `,examples:[["Run the tests from the local workspace","$0 run test"],['Same thing, but without the "run" keyword',"$0 test"],["Inspect Webpack while running","$0 run --inspect-brk webpack"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a,locator:n}=await Qt.find(r,this.context.cwd);await o.restoreInstallState();let u=this.topLevel?o.topLevelWorkspace.anchoredLocator:n;if(!this.binariesOnly&&await hn.hasPackageScript(u,this.scriptName,{project:o}))return await hn.executePackageScript(u,this.scriptName,this.args,{project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});let A=await hn.getPackageAccessibleBinaries(u,{project:o});if(A.get(this.scriptName)){let h=[];return this.inspect&&(typeof this.inspect=="string"?h.push(`--inspect=${this.inspect}`):h.push("--inspect")),this.inspectBrk&&(typeof this.inspectBrk=="string"?h.push(`--inspect-brk=${this.inspectBrk}`):h.push("--inspect-brk")),this.require&&h.push(`--require=${this.require}`),await hn.executePackageAccessibleBinary(u,this.scriptName,this.args,{cwd:this.context.cwd,project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,nodeArgs:h,packageAccessibleBinaries:A})}if(!this.topLevel&&!this.binariesOnly&&a&&this.scriptName.includes(":")){let E=(await Promise.all(o.workspaces.map(async I=>I.manifest.scripts.has(this.scriptName)?I:null))).filter(I=>I!==null);if(E.length===1)return await hn.executeWorkspaceScript(E[0],this.scriptName,this.args,{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}if(this.topLevel)throw this.scriptName==="node-gyp"?new ot(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}). This typically happens because some package depends on "node-gyp" to build itself, but didn't list it in their dependencies. To fix that, please run "yarn add node-gyp" into your top-level workspace. You also can open an issue on the repository of the specified package to suggest them to use an optional peer dependency.`):new ot(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}).`);{if(this.scriptName==="global")throw new ot("The 'yarn global' commands have been removed in 2.x - consider using 'yarn dlx' or a third-party plugin instead");let h=[this.scriptName].concat(this.args);for(let[E,I]of oE)for(let D of I)if(h.length>=D.length&&JSON.stringify(h.slice(0,D.length))===JSON.stringify(D))throw new ot(`Couldn't find a script named "${this.scriptName}", but a matching command can be found in the ${E} plugin. You can install it with "yarn plugin import ${E}".`);throw new ot(`Couldn't find a script named "${this.scriptName}".`)}}};Ke();Ke();Gt();var jE=class extends ut{constructor(){super(...arguments);this.descriptor=de.String();this.resolution=de.String()}static{this.paths=[["set","resolution"]]}static{this.usage=st.Usage({description:"enforce a package resolution",details:'\n This command updates the resolution table so that `descriptor` is resolved by `resolution`.\n\n Note that by default this command only affect the current resolution table - meaning that this "manual override" will disappear if you remove the lockfile, or if the package disappear from the table. If you wish to make the enforced resolution persist whatever happens, edit the `resolutions` field in your top-level manifest.\n\n Note that no attempt is made at validating that `resolution` is a valid resolution entry for `descriptor`.\n ',examples:[["Force all instances of lodash@npm:^1.2.3 to resolve to 1.5.0","$0 set resolution lodash@npm:^1.2.3 1.5.0"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(await o.restoreInstallState({restoreResolutions:!1}),!a)throw new or(o.cwd,this.context.cwd);let u=G.parseDescriptor(this.descriptor,!0),A=G.makeDescriptor(u,this.resolution);return o.storedDescriptors.set(u.descriptorHash,u),o.storedDescriptors.set(A.descriptorHash,A),o.resolutionAliases.set(u.descriptorHash,A.descriptorHash),await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Ke();Pt();Gt();var Vde=et(Xo()),GE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Unlink all workspaces belonging to the target project from the current one"});this.leadingArguments=de.Rest()}static{this.paths=[["unlink"]]}static{this.usage=st.Usage({description:"disconnect the local project from another one",details:` + This command will remove any resolutions in the project-level manifest that would have been added via a yarn link with similar arguments. + `,examples:[["Unregister a remote workspace in the current project","$0 unlink ~/ts-loader"],["Unregister all workspaces from a remote project in the current project","$0 unlink ~/jest --all"],["Unregister all previously linked workspaces","$0 unlink --all"],["Unregister all workspaces matching a glob","$0 unlink '@babel/*' 'pkg-{a,b}'"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);let u=o.topLevelWorkspace,A=new Set;if(this.leadingArguments.length===0&&this.all)for(let{pattern:p,reference:h}of u.manifest.resolutions)h.startsWith("portal:")&&A.add(p.descriptor.fullName);if(this.leadingArguments.length>0)for(let p of this.leadingArguments){let h=K.resolve(this.context.cwd,Ae.toPortablePath(p));if(qe.isPathLike(p)){let E=await Je.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:I,workspace:D}=await Qt.find(E,h);if(!D)throw new or(I.cwd,h);if(this.all){for(let x of I.workspaces)x.manifest.name&&A.add(G.stringifyIdent(x.anchoredLocator));if(A.size===0)throw new ot("No workspace found to be unlinked in the target project")}else{if(!D.manifest.name)throw new ot("The target workspace doesn't have a name and thus cannot be unlinked");A.add(G.stringifyIdent(D.anchoredLocator))}}else{let E=[...u.manifest.resolutions.map(({pattern:I})=>I.descriptor.fullName)];for(let I of(0,Vde.default)(E,p))A.add(I)}}return u.manifest.resolutions=u.manifest.resolutions.filter(({pattern:p})=>!A.has(p.descriptor.fullName)),await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ke();Ke();Ke();Gt();var zde=et(Q2()),SH=et(Xo());il();var YE=class extends ut{constructor(){super(...arguments);this.interactive=de.Boolean("-i,--interactive",{description:"Offer various choices, depending on the detected upgrade paths"});this.fixed=de.Boolean("-F,--fixed",!1,{description:"Store dependency tags as-is instead of resolving them"});this.exact=de.Boolean("-E,--exact",!1,{description:"Don't use any semver modifier on the resolved range"});this.tilde=de.Boolean("-T,--tilde",!1,{description:"Use the `~` semver modifier on the resolved range"});this.caret=de.Boolean("-C,--caret",!1,{description:"Use the `^` semver modifier on the resolved range"});this.recursive=de.Boolean("-R,--recursive",!1,{description:"Resolve again ALL resolutions for those packages"});this.mode=de.String("--mode",{description:"Change what artifacts installs generate",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[["up"]]}static{this.usage=st.Usage({description:"upgrade dependencies across the project",details:"\n This command upgrades the packages matching the list of specified patterns to their latest available version across the whole project (regardless of whether they're part of `dependencies` or `devDependencies` - `peerDependencies` won't be affected). This is a project-wide command: all workspaces will be upgraded in the process.\n\n If `-R,--recursive` is set the command will change behavior and no other switch will be allowed. When operating under this mode `yarn up` will force all ranges matching the selected packages to be resolved again (often to the highest available versions) before being stored in the lockfile. It however won't touch your manifests anymore, so depending on your needs you might want to run both `yarn up` and `yarn up -R` to cover all bases.\n\n If `-i,--interactive` is set (or if the `preferInteractive` settings is toggled on) the command will offer various choices, depending on the detected upgrade paths. Some upgrades require this flag in order to resolve ambiguities.\n\n The, `-C,--caret`, `-E,--exact` and `-T,--tilde` options have the same meaning as in the `add` command (they change the modifier used when the range is missing or a tag, and are ignored when the range is explicitly set).\n\n If the `--mode=` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n Generally you can see `yarn up` as a counterpart to what was `yarn upgrade --latest` in Yarn 1 (ie it ignores the ranges previously listed in your manifests), but unlike `yarn upgrade` which only upgraded dependencies in the current workspace, `yarn up` will upgrade all workspaces at the same time.\n\n This command accepts glob patterns as arguments (if valid Descriptors and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n **Note:** The ranges have to be static, only the package scopes and names can contain glob patterns.\n ",examples:[["Upgrade all instances of lodash to the latest release","$0 up lodash"],["Upgrade all instances of lodash to the latest release, but ask confirmation for each","$0 up lodash -i"],["Upgrade all instances of lodash to 1.2.3","$0 up lodash@1.2.3"],["Upgrade all instances of packages with the `@babel` scope to the latest release","$0 up '@babel/*'"],["Upgrade all instances of packages containing the word `jest` to the latest release","$0 up '*jest*'"],["Upgrade all instances of packages with the `@babel` scope to 7.0.0","$0 up '@babel/*@7.0.0'"]]})}static{this.schema=[PI("recursive",Ku.Forbids,["interactive","exact","tilde","caret"],{ignore:[void 0,!1]})]}async execute(){return this.recursive?await this.executeUpRecursive():await this.executeUpClassic()}async executeUpRecursive(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=[...o.storedDescriptors.values()],A=u.map(E=>G.stringifyIdent(E)),p=new Set;for(let E of this.patterns){if(G.parseDescriptor(E).range!=="unknown")throw new ot("Ranges aren't allowed when using --recursive");for(let I of(0,SH.default)(A,E)){let D=G.parseIdent(I);p.add(D.identHash)}}let h=u.filter(E=>p.has(E.identHash));for(let E of h)o.storedDescriptors.delete(E.descriptorHash),o.storedResolutions.delete(E.descriptorHash);return await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}async executeUpClassic(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=R2(this,o),h=A?["keep","reuse","project","latest"]:["project","latest"],E=[],I=[];for(let L of this.patterns){let U=!1,z=G.parseDescriptor(L),te=G.stringifyIdent(z);for(let le of o.workspaces)for(let ce of["dependencies","devDependencies"]){let Ce=[...le.manifest.getForScope(ce).values()].map(De=>G.stringifyIdent(De)),he=te==="*"?Ce:(0,SH.default)(Ce,te);for(let De of he){let Ee=G.parseIdent(De),g=le.manifest[ce].get(Ee.identHash);if(typeof g>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let me=G.makeDescriptor(Ee,z.range);E.push(Promise.resolve().then(async()=>[le,ce,g,await T2(me,{project:o,workspace:le,cache:n,target:ce,fixed:u,modifier:p,strategies:h})])),U=!0}}U||I.push(L)}if(I.length>1)throw new ot(`Patterns ${pe.prettyList(r,I,pe.Type.CODE)} don't match any packages referenced by any workspace`);if(I.length>0)throw new ot(`Pattern ${pe.prettyList(r,I,pe.Type.CODE)} doesn't match any packages referenced by any workspace`);let D=await Promise.all(E),x=await pA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async L=>{for(let[,,U,{suggestions:z,rejections:te}]of D){let le=z.filter(ce=>ce.descriptor!==null);if(le.length===0){let[ce]=te;if(typeof ce>"u")throw new Error("Assertion failed: Expected an error to have been set");let ue=this.cli.error(ce);o.configuration.get("enableNetwork")?L.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range + +${ue}`):L.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range (note: network resolution has been disabled) + +${ue}`)}else le.length>1&&!A&&L.reportError(27,`${G.prettyDescriptor(r,U)} has multiple possible upgrade strategies; use -i to disambiguate manually`)}});if(x.hasErrors())return x.exitCode();let C=!1,T=[];for(let[L,U,,{suggestions:z}]of D){let te,le=z.filter(he=>he.descriptor!==null),ce=le[0].descriptor,ue=le.every(he=>G.areDescriptorsEqual(he.descriptor,ce));le.length===1||ue?te=ce:(C=!0,{answer:te}=await(0,zde.prompt)({type:"select",name:"answer",message:`Which range do you want to use in ${G.prettyWorkspace(r,L)} \u276F ${U}?`,choices:z.map(({descriptor:he,name:De,reason:Ee})=>he?{name:De,hint:Ee,descriptor:he}:{name:De,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(he){return this.find(he,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ce=L.manifest[U].get(te.identHash);if(typeof Ce>"u")throw new Error("Assertion failed: This descriptor should have a matching entry");if(Ce.descriptorHash!==te.descriptorHash)L.manifest[U].set(te.identHash,te),T.push([L,U,Ce,te]);else{let he=r.makeResolver(),De={project:o,resolver:he},Ee=r.normalizeDependency(Ce),g=he.bindDescriptor(Ee,L.anchoredLocator,De);o.forgetResolution(g)}}return await r.triggerMultipleHooks(L=>L.afterWorkspaceDependencyReplacement,T),C&&this.context.stdout.write(` +`),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}};Ke();Ke();Ke();Gt();var WE=class extends ut{constructor(){super(...arguments);this.recursive=de.Boolean("-R,--recursive",!1,{description:"List, for each workspace, what are all the paths that lead to the dependency"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.peers=de.Boolean("--peers",!1,{description:"Also print the peer dependencies that match the specified name"});this.package=de.String()}static{this.paths=[["why"]]}static{this.usage=st.Usage({description:"display the reason why a package is needed",details:` + This command prints the exact reasons why a package appears in the dependency tree. + + If \`-R,--recursive\` is set, the listing will go in depth and will list, for each workspaces, what are all the paths that lead to the dependency. Note that the display is somewhat optimized in that it will not print the package listing twice for a single package, so if you see a leaf named "Foo" when looking for "Bar", it means that "Foo" already got printed higher in the tree. + `,examples:[["Explain why lodash is used in your project","$0 why lodash"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=G.parseIdent(this.package).identHash,u=this.recursive?Z0t(o,n,{configuration:r,peers:this.peers}):X0t(o,n,{configuration:r,peers:this.peers});As.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1})}};function X0t(t,e,{configuration:r,peers:o}){let a=qe.sortMap(t.storedPackages.values(),A=>G.stringifyLocator(A)),n={},u={children:n};for(let A of a){let p={};for(let E of A.dependencies.values()){if(!o&&A.peerDependencies.has(E.identHash))continue;let I=t.storedResolutions.get(E.descriptorHash);if(!I)throw new Error("Assertion failed: The resolution should have been registered");let D=t.storedPackages.get(I);if(!D)throw new Error("Assertion failed: The package should have been registered");if(D.identHash!==e)continue;{let C=G.stringifyLocator(A);n[C]={value:[A,pe.Type.LOCATOR],children:p}}let x=G.stringifyLocator(D);p[x]={value:[{descriptor:E,locator:D},pe.Type.DEPENDENT]}}}return u}function Z0t(t,e,{configuration:r,peers:o}){let a=qe.sortMap(t.workspaces,D=>G.stringifyLocator(D.anchoredLocator)),n=new Set,u=new Set,A=D=>{if(n.has(D.locatorHash))return u.has(D.locatorHash);if(n.add(D.locatorHash),D.identHash===e)return u.add(D.locatorHash),!0;let x=!1;D.identHash===e&&(x=!0);for(let C of D.dependencies.values()){if(!o&&D.peerDependencies.has(C.identHash))continue;let T=t.storedResolutions.get(C.descriptorHash);if(!T)throw new Error("Assertion failed: The resolution should have been registered");let L=t.storedPackages.get(T);if(!L)throw new Error("Assertion failed: The package should have been registered");A(L)&&(x=!0)}return x&&u.add(D.locatorHash),x};for(let D of a)A(D.anchoredPackage);let p=new Set,h={},E={children:h},I=(D,x,C)=>{if(!u.has(D.locatorHash))return;let T=C!==null?pe.tuple(pe.Type.DEPENDENT,{locator:D,descriptor:C}):pe.tuple(pe.Type.LOCATOR,D),L={},U={value:T,children:L},z=G.stringifyLocator(D);if(x[z]=U,!(C!==null&&t.tryWorkspaceByLocator(D))&&!p.has(D.locatorHash)){p.add(D.locatorHash);for(let te of D.dependencies.values()){if(!o&&D.peerDependencies.has(te.identHash))continue;let le=t.storedResolutions.get(te.descriptorHash);if(!le)throw new Error("Assertion failed: The resolution should have been registered");let ce=t.storedPackages.get(le);if(!ce)throw new Error("Assertion failed: The package should have been registered");I(ce,L,te)}}};for(let D of a)I(D.anchoredPackage,h,null);return E}Ke();var MH={};Kt(MH,{GitFetcher:()=>_2,GitResolver:()=>H2,default:()=>Egt,gitUtils:()=>ra});Ke();Pt();var ra={};Kt(ra,{TreeishProtocols:()=>U2,clone:()=>LH,fetchBase:()=>mme,fetchChangedFiles:()=>yme,fetchChangedWorkspaces:()=>mgt,fetchRoot:()=>dme,isGitUrl:()=>zE,lsRemote:()=>gme,normalizeLocator:()=>dgt,normalizeRepoUrl:()=>KE,resolveUrl:()=>NH,splitRepoUrl:()=>Rh,validateRepoUrl:()=>TH});Ke();Pt();Gt();var fme=et(cme()),pme=et(t3()),VE=et(ve("querystring")),FH=et(ni());function QH(t,e,r){let o=t.indexOf(r);return t.lastIndexOf(e,o>-1?o:1/0)}function ume(t){try{return new URL(t)}catch{return}}function hgt(t){let e=QH(t,"@","#"),r=QH(t,":","#");return r>e&&(t=`${t.slice(0,r)}/${t.slice(r+1)}`),QH(t,":","#")===-1&&t.indexOf("//")===-1&&(t=`ssh://${t}`),t}function Ame(t){return ume(t)||ume(hgt(t))}function KE(t,{git:e=!1}={}){if(t=t.replace(/^git\+https:/,"https:"),t=t.replace(/^(?:github:|https:\/\/github\.com\/|git:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)(?:\.git)?(#.*)?$/,"https://github.com/$1/$2.git$3"),t=t.replace(/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/,"https://github.com/$1/$2.git#$3"),e){let r=Ame(t);r&&(t=r.href),t=t.replace(/^git\+([^:]+):/,"$1:")}return t}function hme(){return{...process.env,GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||`${process.env.GIT_SSH||"ssh"} -o BatchMode=yes`}}var ggt=[/^ssh:/,/^git(?:\+[^:]+)?:/,/^(?:git\+)?https?:[^#]+\/[^#]+(?:\.git)(?:#.*)?$/,/^git@[^#]+\/[^#]+\.git(?:#.*)?$/,/^(?:github:|https:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z._0-9-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z._0-9-]+?)(?:\.git)?(?:#.*)?$/,/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/],U2=(a=>(a.Commit="commit",a.Head="head",a.Tag="tag",a.Semver="semver",a))(U2||{});function zE(t){return t?ggt.some(e=>!!t.match(e)):!1}function Rh(t){t=KE(t);let e=t.indexOf("#");if(e===-1)return{repo:t,treeish:{protocol:"head",request:"HEAD"},extra:{}};let r=t.slice(0,e),o=t.slice(e+1);if(o.match(/^[a-z]+=/)){let a=VE.default.parse(o);for(let[p,h]of Object.entries(a))if(typeof h!="string")throw new Error(`Assertion failed: The ${p} parameter must be a literal string`);let n=Object.values(U2).find(p=>Object.hasOwn(a,p)),[u,A]=typeof n<"u"?[n,a[n]]:["head","HEAD"];for(let p of Object.values(U2))delete a[p];return{repo:r,treeish:{protocol:u,request:A},extra:a}}else{let a=o.indexOf(":"),[n,u]=a===-1?[null,o]:[o.slice(0,a),o.slice(a+1)];return{repo:r,treeish:{protocol:n,request:u},extra:{}}}}function dgt(t){return G.makeLocator(t,KE(t.reference))}function TH(t,{configuration:e}){let r=KE(t,{git:!0});if(!on.getNetworkSettings(`https://${(0,fme.default)(r).resource}`,{configuration:e}).enableNetwork)throw new zt(80,`Request to '${r}' has been blocked because of your configuration settings`);return r}async function gme(t,e){let r=TH(t,{configuration:e}),o=await RH("listing refs",["ls-remote",r],{cwd:e.startingCwd,env:hme()},{configuration:e,normalizedRepoUrl:r}),a=new Map,n=/^([a-f0-9]{40})\t([^\n]+)/gm,u;for(;(u=n.exec(o.stdout))!==null;)a.set(u[2],u[1]);return a}async function NH(t,e){let{repo:r,treeish:{protocol:o,request:a},extra:n}=Rh(t),u=await gme(r,e),A=(h,E)=>{switch(h){case"commit":{if(!E.match(/^[a-f0-9]{40}$/))throw new Error("Invalid commit hash");return VE.default.stringify({...n,commit:E})}case"head":{let I=u.get(E==="HEAD"?E:`refs/heads/${E}`);if(typeof I>"u")throw new Error(`Unknown head ("${E}")`);return VE.default.stringify({...n,commit:I})}case"tag":{let I=u.get(`refs/tags/${E}`);if(typeof I>"u")throw new Error(`Unknown tag ("${E}")`);return VE.default.stringify({...n,commit:I})}case"semver":{let I=Ur.validRange(E);if(!I)throw new Error(`Invalid range ("${E}")`);let D=new Map([...u.entries()].filter(([C])=>C.startsWith("refs/tags/")).map(([C,T])=>[FH.default.parse(C.slice(10)),T]).filter(C=>C[0]!==null)),x=FH.default.maxSatisfying([...D.keys()],I);if(x===null)throw new Error(`No matching range ("${E}")`);return VE.default.stringify({...n,commit:D.get(x)})}case null:{let I;if((I=p("commit",E))!==null||(I=p("tag",E))!==null||(I=p("head",E))!==null)return I;throw E.match(/^[a-f0-9]+$/)?new Error(`Couldn't resolve "${E}" as either a commit, a tag, or a head - if a commit, use the 40-characters commit hash`):new Error(`Couldn't resolve "${E}" as either a commit, a tag, or a head`)}default:throw new Error(`Invalid Git resolution protocol ("${h}")`)}},p=(h,E)=>{try{return A(h,E)}catch{return null}};return KE(`${r}#${A(o,a)}`)}async function LH(t,e){return await e.getLimit("cloneConcurrency")(async()=>{let{repo:r,treeish:{protocol:o,request:a}}=Rh(t);if(o!=="commit")throw new Error("Invalid treeish protocol when cloning");let n=TH(r,{configuration:e}),u=await ae.mktempPromise(),A={cwd:u,env:hme()};return await RH("cloning the repository",["clone","-c core.autocrlf=false",n,Ae.fromPortablePath(u)],A,{configuration:e,normalizedRepoUrl:n}),await RH("switching branch",["checkout",`${a}`],A,{configuration:e,normalizedRepoUrl:n}),u})}async function dme(t){let e,r=t;do{if(e=r,await ae.existsPromise(K.join(e,".git")))return e;r=K.dirname(e)}while(r!==e);return null}async function mme(t,{baseRefs:e}){if(e.length===0)throw new ot("Can't run this command with zero base refs specified.");let r=[];for(let A of e){let{code:p}=await Hr.execvp("git",["merge-base",A,"HEAD"],{cwd:t});p===0&&r.push(A)}if(r.length===0)throw new ot(`No ancestor could be found between any of HEAD and ${e.join(", ")}`);let{stdout:o}=await Hr.execvp("git",["merge-base","HEAD",...r],{cwd:t,strict:!0}),a=o.trim(),{stdout:n}=await Hr.execvp("git",["show","--quiet","--pretty=format:%s",a],{cwd:t,strict:!0}),u=n.trim();return{hash:a,title:u}}async function yme(t,{base:e,project:r}){let o=qe.buildIgnorePattern(r.configuration.get("changesetIgnorePatterns")),{stdout:a}=await Hr.execvp("git",["diff","--name-only",`${e}`],{cwd:t,strict:!0}),n=a.split(/\r\n|\r|\n/).filter(h=>h.length>0).map(h=>K.resolve(t,Ae.toPortablePath(h))),{stdout:u}=await Hr.execvp("git",["ls-files","--others","--exclude-standard"],{cwd:t,strict:!0}),A=u.split(/\r\n|\r|\n/).filter(h=>h.length>0).map(h=>K.resolve(t,Ae.toPortablePath(h))),p=[...new Set([...n,...A].sort())];return o?p.filter(h=>!K.relative(r.cwd,h).match(o)):p}async function mgt({ref:t,project:e}){if(e.configuration.projectCwd===null)throw new ot("This command can only be run from within a Yarn project");let r=[K.resolve(e.cwd,mr.lockfile),K.resolve(e.cwd,e.configuration.get("cacheFolder")),K.resolve(e.cwd,e.configuration.get("installStatePath")),K.resolve(e.cwd,e.configuration.get("virtualFolder"))];await e.configuration.triggerHook(u=>u.populateYarnPaths,e,u=>{u!=null&&r.push(u)});let o=await dme(e.configuration.projectCwd);if(o==null)throw new ot("This command can only be run on Git repositories");let a=await mme(o,{baseRefs:typeof t=="string"?[t]:e.configuration.get("changesetBaseRefs")}),n=await yme(o,{base:a.hash,project:e});return new Set(qe.mapAndFilter(n,u=>{let A=e.tryWorkspaceByFilePath(u);return A===null?qe.mapAndFilter.skip:r.some(p=>u.startsWith(p))?qe.mapAndFilter.skip:A}))}async function RH(t,e,r,{configuration:o,normalizedRepoUrl:a}){try{return await Hr.execvp("git",e,{...r,strict:!0})}catch(n){if(!(n instanceof Hr.ExecError))throw n;let u=n.reportExtra,A=n.stderr.toString();throw new zt(1,`Failed ${t}`,p=>{p.reportError(1,` ${pe.prettyField(o,{label:"Repository URL",value:pe.tuple(pe.Type.URL,a)})}`);for(let h of A.matchAll(/^(.+?): (.*)$/gm)){let[,E,I]=h;E=E.toLowerCase();let D=E==="error"?"Error":`${(0,pme.default)(E)} Error`;p.reportError(1,` ${pe.prettyField(o,{label:D,value:pe.tuple(pe.Type.NO_HINT,I)})}`)}u?.(p)})}}var _2=class{supports(e,r){return zE(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,a=new Map(r.checksums);a.set(e.locatorHash,o);let n={...r,checksums:a},u=await this.downloadHosted(e,n);if(u!==null)return u;let[A,p,h]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote repository`),loader:()=>this.cloneFromRemote(e,n),...r.cacheOptions});return{packageFs:A,releaseFs:p,prefixPath:G.getIdentVendorPath(e),checksum:h}}async downloadHosted(e,r){return r.project.configuration.reduceHook(o=>o.fetchHostedRepository,null,e,r)}async cloneFromRemote(e,r){let o=Rh(e.reference),a=await LH(e.reference,r.project.configuration),n=K.resolve(a,o.extra.cwd??Bt.dot),u=K.join(n,"package.tgz");await hn.prepareExternalProject(n,u,{configuration:r.project.configuration,report:r.report,workspace:o.extra.workspace,locator:e});let A=await ae.readFilePromise(u);return await qe.releaseAfterUseAsync(async()=>await $i.convertToZip(A,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1}))}};Ke();Ke();var H2=class{supportsDescriptor(e,r){return zE(e.range)}supportsLocator(e,r){return zE(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=await NH(e.range,o.project.configuration);return[G.makeLocator(e,a)]}async getSatisfying(e,r,o,a){let n=Rh(e.range);return{locators:o.filter(A=>{if(A.identHash!==e.identHash)return!1;let p=Rh(A.reference);return!(n.repo!==p.repo||n.treeish.protocol==="commit"&&n.treeish.request!==p.treeish.request)}),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var ygt={configuration:{changesetBaseRefs:{description:"The base git refs that the current HEAD is compared against when detecting changes. Supports git branches, tags, and commits.",type:"STRING",isArray:!0,isNullable:!1,default:["master","origin/master","upstream/master","main","origin/main","upstream/main"]},changesetIgnorePatterns:{description:"Array of glob patterns; files matching them will be ignored when fetching the changed files",type:"STRING",default:[],isArray:!0},cloneConcurrency:{description:"Maximal number of concurrent clones",type:"NUMBER",default:2}},fetchers:[_2],resolvers:[H2]};var Egt=ygt;Gt();var JE=class extends ut{constructor(){super(...arguments);this.since=de.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.recursive=de.Boolean("-R,--recursive",!1,{description:"Find packages via dependencies/devDependencies instead of using the workspaces field"});this.noPrivate=de.Boolean("--no-private",{description:"Exclude workspaces that have the private field set to true"});this.verbose=de.Boolean("-v,--verbose",!1,{description:"Also return the cross-dependencies between workspaces"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["workspaces","list"]]}static{this.usage=st.Usage({category:"Workspace-related commands",description:"list all available workspaces",details:"\n This command will print the list of all workspaces in the project.\n\n - If `--since` is set, Yarn will only list workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `--no-private` is set, Yarn will not list any workspaces that have the `private` field set to `true`.\n\n - If both the `-v,--verbose` and `--json` options are set, Yarn will also return the cross-dependencies between each workspaces (useful when you wish to automatically generate Buck / Bazel rules).\n "})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return(await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{let u=this.since?await ra.fetchChangedWorkspaces({ref:this.since,project:o}):o.workspaces,A=new Set(u);if(this.recursive)for(let p of[...u].map(h=>h.getRecursiveWorkspaceDependents()))for(let h of p)A.add(h);for(let p of A){let{manifest:h}=p;if(h.private&&this.noPrivate)continue;let E;if(this.verbose){let I=new Set,D=new Set;for(let x of _t.hardDependencies)for(let[C,T]of h.getForScope(x)){let L=o.tryWorkspaceByDescriptor(T);L===null?o.workspacesByIdent.has(C)&&D.add(T):I.add(L)}E={workspaceDependencies:Array.from(I).map(x=>x.relativeCwd),mismatchedWorkspaceDependencies:Array.from(D).map(x=>G.stringifyDescriptor(x))}}n.reportInfo(null,`${p.relativeCwd}`),n.reportJson({location:p.relativeCwd,name:h.name?G.stringifyIdent(h.name):null,...E})}})).exitCode()}};Ke();Ke();Gt();var XE=class extends ut{constructor(){super(...arguments);this.workspaceName=de.String();this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[["workspace"]]}static{this.usage=st.Usage({category:"Workspace-related commands",description:"run a command within the specified workspace",details:` + This command will run a given sub-command on a single workspace. + `,examples:[["Add a package to a single workspace","yarn workspace components add -D react"],["Run build script on a single workspace","yarn workspace components run build"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=o.workspaces,u=new Map(n.map(p=>[G.stringifyIdent(p.anchoredLocator),p])),A=u.get(this.workspaceName);if(A===void 0){let p=Array.from(u.keys()).sort();throw new ot(`Workspace '${this.workspaceName}' not found. Did you mean any of the following: + - ${p.join(` + - `)}?`)}return this.cli.run([this.commandName,...this.args],{cwd:A.cwd})}};var Cgt={configuration:{enableImmutableInstalls:{description:"If true (the default on CI), prevents the install command from modifying the lockfile",type:"BOOLEAN",default:Eme.isCI},defaultSemverRangePrefix:{description:"The default save prefix: '^', '~' or ''",type:"STRING",values:["^","~",""],default:"^"},preferReuse:{description:"If true, `yarn add` will attempt to reuse the most common dependency range in other workspaces.",type:"BOOLEAN",default:!1}},commands:[hE,gE,dE,mE,jE,TE,PE,JE,CE,wE,IE,BE,fE,pE,yE,EE,vE,DE,SE,bE,xE,kE,GE,QE,FE,LE,NE,ME,RE,OE,UE,_E,HE,qE,YE,WE,XE]},wgt=Cgt;var jH={};Kt(jH,{default:()=>Bgt});Ke();var kt={optional:!0},UH=[["@tailwindcss/aspect-ratio@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@tailwindcss/line-clamp@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@fullhuman/postcss-purgecss@3.1.3 || 3.1.3-alpha.0",{peerDependencies:{postcss:"^8.0.0"}}],["@samverschueren/stream-to-observable@<0.3.1",{peerDependenciesMeta:{rxjs:kt,zenObservable:kt}}],["any-observable@<0.5.1",{peerDependenciesMeta:{rxjs:kt,zenObservable:kt}}],["@pm2/agent@<1.0.4",{dependencies:{debug:"*"}}],["debug@<4.2.0",{peerDependenciesMeta:{"supports-color":kt}}],["got@<11",{dependencies:{"@types/responselike":"^1.0.0","@types/keyv":"^3.1.1"}}],["cacheable-lookup@<4.1.2",{dependencies:{"@types/keyv":"^3.1.1"}}],["http-link-dataloader@*",{peerDependencies:{graphql:"^0.13.1 || ^14.0.0"}}],["typescript-language-server@*",{dependencies:{"vscode-jsonrpc":"^5.0.1","vscode-languageserver-protocol":"^3.15.0"}}],["postcss-syntax@*",{peerDependenciesMeta:{"postcss-html":kt,"postcss-jsx":kt,"postcss-less":kt,"postcss-markdown":kt,"postcss-scss":kt}}],["jss-plugin-rule-value-function@<=10.1.1",{dependencies:{"tiny-warning":"^1.0.2"}}],["ink-select-input@<4.1.0",{peerDependencies:{react:"^16.8.2"}}],["license-webpack-plugin@<2.3.18",{peerDependenciesMeta:{webpack:kt}}],["snowpack@>=3.3.0",{dependencies:{"node-gyp":"^7.1.0"}}],["promise-inflight@*",{peerDependenciesMeta:{bluebird:kt}}],["reactcss@*",{peerDependencies:{react:"*"}}],["react-color@<=2.19.0",{peerDependencies:{react:"*"}}],["gatsby-plugin-i18n@*",{dependencies:{ramda:"^0.24.1"}}],["useragent@^2.0.0",{dependencies:{request:"^2.88.0",yamlparser:"0.0.x",semver:"5.5.x"}}],["@apollographql/apollo-tools@<=0.5.2",{peerDependencies:{graphql:"^14.2.1 || ^15.0.0"}}],["material-table@^2.0.0",{dependencies:{"@babel/runtime":"^7.11.2"}}],["@babel/parser@*",{dependencies:{"@babel/types":"^7.8.3"}}],["fork-ts-checker-webpack-plugin@<=6.3.4",{peerDependencies:{eslint:">= 6",typescript:">= 2.7",webpack:">= 4","vue-template-compiler":"*"},peerDependenciesMeta:{eslint:kt,"vue-template-compiler":kt}}],["rc-animate@<=3.1.1",{peerDependencies:{react:">=16.9.0","react-dom":">=16.9.0"}}],["react-bootstrap-table2-paginator@*",{dependencies:{classnames:"^2.2.6"}}],["react-draggable@<=4.4.3",{peerDependencies:{react:">= 16.3.0","react-dom":">= 16.3.0"}}],["apollo-upload-client@<14",{peerDependencies:{graphql:"14 - 15"}}],["react-instantsearch-core@<=6.7.0",{peerDependencies:{algoliasearch:">= 3.1 < 5"}}],["react-instantsearch-dom@<=6.7.0",{dependencies:{"react-fast-compare":"^3.0.0"}}],["ws@<7.2.1",{peerDependencies:{bufferutil:"^4.0.1","utf-8-validate":"^5.0.2"},peerDependenciesMeta:{bufferutil:kt,"utf-8-validate":kt}}],["react-portal@<4.2.2",{peerDependencies:{"react-dom":"^15.0.0-0 || ^16.0.0-0 || ^17.0.0-0"}}],["react-scripts@<=4.0.1",{peerDependencies:{react:"*"}}],["testcafe@<=1.10.1",{dependencies:{"@babel/plugin-transform-for-of":"^7.12.1","@babel/runtime":"^7.12.5"}}],["testcafe-legacy-api@<=4.2.0",{dependencies:{"testcafe-hammerhead":"^17.0.1","read-file-relative":"^1.2.0"}}],["@google-cloud/firestore@<=4.9.3",{dependencies:{protobufjs:"^6.8.6"}}],["gatsby-source-apiserver@*",{dependencies:{"babel-polyfill":"^6.26.0"}}],["@webpack-cli/package-utils@<=1.0.1-alpha.4",{dependencies:{"cross-spawn":"^7.0.3"}}],["gatsby-remark-prismjs@<3.3.28",{dependencies:{lodash:"^4"}}],["gatsby-plugin-favicon@*",{peerDependencies:{webpack:"*"}}],["gatsby-plugin-sharp@<=4.6.0-next.3",{dependencies:{debug:"^4.3.1"}}],["gatsby-react-router-scroll@<=5.6.0-next.0",{dependencies:{"prop-types":"^15.7.2"}}],["@rebass/forms@*",{dependencies:{"@styled-system/should-forward-prop":"^5.0.0"},peerDependencies:{react:"^16.8.6"}}],["rebass@*",{peerDependencies:{react:"^16.8.6"}}],["@ant-design/react-slick@<=0.28.3",{peerDependencies:{react:">=16.0.0"}}],["mqtt@<4.2.7",{dependencies:{duplexify:"^4.1.1"}}],["vue-cli-plugin-vuetify@<=2.0.3",{dependencies:{semver:"^6.3.0"},peerDependenciesMeta:{"sass-loader":kt,"vuetify-loader":kt}}],["vue-cli-plugin-vuetify@<=2.0.4",{dependencies:{"null-loader":"^3.0.0"}}],["vue-cli-plugin-vuetify@>=2.4.3",{peerDependencies:{vue:"*"}}],["@vuetify/cli-plugin-utils@<=0.0.4",{dependencies:{semver:"^6.3.0"},peerDependenciesMeta:{"sass-loader":kt}}],["@vue/cli-plugin-typescript@<=5.0.0-alpha.0",{dependencies:{"babel-loader":"^8.1.0"}}],["@vue/cli-plugin-typescript@<=5.0.0-beta.0",{dependencies:{"@babel/core":"^7.12.16"},peerDependencies:{"vue-template-compiler":"^2.0.0"},peerDependenciesMeta:{"vue-template-compiler":kt}}],["cordova-ios@<=6.3.0",{dependencies:{underscore:"^1.9.2"}}],["cordova-lib@<=10.0.1",{dependencies:{underscore:"^1.9.2"}}],["git-node-fs@*",{peerDependencies:{"js-git":"^0.7.8"},peerDependenciesMeta:{"js-git":kt}}],["consolidate@<0.16.0",{peerDependencies:{mustache:"^3.0.0"},peerDependenciesMeta:{mustache:kt}}],["consolidate@<=0.16.0",{peerDependencies:{velocityjs:"^2.0.1",tinyliquid:"^0.2.34","liquid-node":"^3.0.1",jade:"^1.11.0","then-jade":"*",dust:"^0.3.0","dustjs-helpers":"^1.7.4","dustjs-linkedin":"^2.7.5",swig:"^1.4.2","swig-templates":"^2.0.3","razor-tmpl":"^1.3.1",atpl:">=0.7.6",liquor:"^0.0.5",twig:"^1.15.2",ejs:"^3.1.5",eco:"^1.1.0-rc-3",jazz:"^0.0.18",jqtpl:"~1.1.0",hamljs:"^0.6.2",hamlet:"^0.3.3",whiskers:"^0.4.0","haml-coffee":"^1.14.1","hogan.js":"^3.0.2",templayed:">=0.2.3",handlebars:"^4.7.6",underscore:"^1.11.0",lodash:"^4.17.20",pug:"^3.0.0","then-pug":"*",qejs:"^3.0.5",walrus:"^0.10.1",mustache:"^4.0.1",just:"^0.1.8",ect:"^0.5.9",mote:"^0.2.0",toffee:"^0.3.6",dot:"^1.1.3","bracket-template":"^1.1.5",ractive:"^1.3.12",nunjucks:"^3.2.2",htmling:"^0.0.8","babel-core":"^6.26.3",plates:"~0.4.11","react-dom":"^16.13.1",react:"^16.13.1","arc-templates":"^0.5.3",vash:"^0.13.0",slm:"^2.0.0",marko:"^3.14.4",teacup:"^2.0.0","coffee-script":"^1.12.7",squirrelly:"^5.1.0",twing:"^5.0.2"},peerDependenciesMeta:{velocityjs:kt,tinyliquid:kt,"liquid-node":kt,jade:kt,"then-jade":kt,dust:kt,"dustjs-helpers":kt,"dustjs-linkedin":kt,swig:kt,"swig-templates":kt,"razor-tmpl":kt,atpl:kt,liquor:kt,twig:kt,ejs:kt,eco:kt,jazz:kt,jqtpl:kt,hamljs:kt,hamlet:kt,whiskers:kt,"haml-coffee":kt,"hogan.js":kt,templayed:kt,handlebars:kt,underscore:kt,lodash:kt,pug:kt,"then-pug":kt,qejs:kt,walrus:kt,mustache:kt,just:kt,ect:kt,mote:kt,toffee:kt,dot:kt,"bracket-template":kt,ractive:kt,nunjucks:kt,htmling:kt,"babel-core":kt,plates:kt,"react-dom":kt,react:kt,"arc-templates":kt,vash:kt,slm:kt,marko:kt,teacup:kt,"coffee-script":kt,squirrelly:kt,twing:kt}}],["vue-loader@<=16.3.3",{peerDependencies:{"@vue/compiler-sfc":"^3.0.8",webpack:"^4.1.0 || ^5.0.0-0"},peerDependenciesMeta:{"@vue/compiler-sfc":kt}}],["vue-loader@^16.7.0",{peerDependencies:{"@vue/compiler-sfc":"^3.0.8",vue:"^3.2.13"},peerDependenciesMeta:{"@vue/compiler-sfc":kt,vue:kt}}],["scss-parser@<=1.0.5",{dependencies:{lodash:"^4.17.21"}}],["query-ast@<1.0.5",{dependencies:{lodash:"^4.17.21"}}],["redux-thunk@<=2.3.0",{peerDependencies:{redux:"^4.0.0"}}],["skypack@<=0.3.2",{dependencies:{tar:"^6.1.0"}}],["@npmcli/metavuln-calculator@<2.0.0",{dependencies:{"json-parse-even-better-errors":"^2.3.1"}}],["bin-links@<2.3.0",{dependencies:{"mkdirp-infer-owner":"^1.0.2"}}],["rollup-plugin-polyfill-node@<=0.8.0",{peerDependencies:{rollup:"^1.20.0 || ^2.0.0"}}],["snowpack@<3.8.6",{dependencies:{"magic-string":"^0.25.7"}}],["elm-webpack-loader@*",{dependencies:{temp:"^0.9.4"}}],["winston-transport@<=4.4.0",{dependencies:{logform:"^2.2.0"}}],["jest-vue-preprocessor@*",{dependencies:{"@babel/core":"7.8.7","@babel/template":"7.8.6"},peerDependencies:{pug:"^2.0.4"},peerDependenciesMeta:{pug:kt}}],["redux-persist@*",{peerDependencies:{react:">=16"},peerDependenciesMeta:{react:kt}}],["sodium@>=3",{dependencies:{"node-gyp":"^3.8.0"}}],["babel-plugin-graphql-tag@<=3.1.0",{peerDependencies:{graphql:"^14.0.0 || ^15.0.0"}}],["@playwright/test@<=1.14.1",{dependencies:{"jest-matcher-utils":"^26.4.2"}}],...["babel-plugin-remove-graphql-queries@<3.14.0-next.1","babel-preset-gatsby-package@<1.14.0-next.1","create-gatsby@<1.14.0-next.1","gatsby-admin@<0.24.0-next.1","gatsby-cli@<3.14.0-next.1","gatsby-core-utils@<2.14.0-next.1","gatsby-design-tokens@<3.14.0-next.1","gatsby-legacy-polyfills@<1.14.0-next.1","gatsby-plugin-benchmark-reporting@<1.14.0-next.1","gatsby-plugin-graphql-config@<0.23.0-next.1","gatsby-plugin-image@<1.14.0-next.1","gatsby-plugin-mdx@<2.14.0-next.1","gatsby-plugin-netlify-cms@<5.14.0-next.1","gatsby-plugin-no-sourcemaps@<3.14.0-next.1","gatsby-plugin-page-creator@<3.14.0-next.1","gatsby-plugin-preact@<5.14.0-next.1","gatsby-plugin-preload-fonts@<2.14.0-next.1","gatsby-plugin-schema-snapshot@<2.14.0-next.1","gatsby-plugin-styletron@<6.14.0-next.1","gatsby-plugin-subfont@<3.14.0-next.1","gatsby-plugin-utils@<1.14.0-next.1","gatsby-recipes@<0.25.0-next.1","gatsby-source-shopify@<5.6.0-next.1","gatsby-source-wikipedia@<3.14.0-next.1","gatsby-transformer-screenshot@<3.14.0-next.1","gatsby-worker@<0.5.0-next.1"].map(t=>[t,{dependencies:{"@babel/runtime":"^7.14.8"}}]),["gatsby-core-utils@<2.14.0-next.1",{dependencies:{got:"8.3.2"}}],["gatsby-plugin-gatsby-cloud@<=3.1.0-next.0",{dependencies:{"gatsby-core-utils":"^2.13.0-next.0"}}],["gatsby-plugin-gatsby-cloud@<=3.2.0-next.1",{peerDependencies:{webpack:"*"}}],["babel-plugin-remove-graphql-queries@<=3.14.0-next.1",{dependencies:{"gatsby-core-utils":"^2.8.0-next.1"}}],["gatsby-plugin-netlify@3.13.0-next.1",{dependencies:{"gatsby-core-utils":"^2.13.0-next.0"}}],["clipanion-v3-codemod@<=0.2.0",{peerDependencies:{jscodeshift:"^0.11.0"}}],["react-live@*",{peerDependencies:{"react-dom":"*",react:"*"}}],["webpack@<4.44.1",{peerDependenciesMeta:{"webpack-cli":kt,"webpack-command":kt}}],["webpack@<5.0.0-beta.23",{peerDependenciesMeta:{"webpack-cli":kt}}],["webpack-dev-server@<3.10.2",{peerDependenciesMeta:{"webpack-cli":kt}}],["@docusaurus/responsive-loader@<1.5.0",{peerDependenciesMeta:{sharp:kt,jimp:kt}}],["eslint-module-utils@*",{peerDependenciesMeta:{"eslint-import-resolver-node":kt,"eslint-import-resolver-typescript":kt,"eslint-import-resolver-webpack":kt,"@typescript-eslint/parser":kt}}],["eslint-plugin-import@*",{peerDependenciesMeta:{"@typescript-eslint/parser":kt}}],["critters-webpack-plugin@<3.0.2",{peerDependenciesMeta:{"html-webpack-plugin":kt}}],["terser@<=5.10.0",{dependencies:{acorn:"^8.5.0"}}],["babel-preset-react-app@10.0.x <10.0.2",{dependencies:{"@babel/plugin-proposal-private-property-in-object":"^7.16.7"}}],["eslint-config-react-app@*",{peerDependenciesMeta:{typescript:kt}}],["@vue/eslint-config-typescript@<11.0.0",{peerDependenciesMeta:{typescript:kt}}],["unplugin-vue2-script-setup@<0.9.1",{peerDependencies:{"@vue/composition-api":"^1.4.3","@vue/runtime-dom":"^3.2.26"}}],["@cypress/snapshot@*",{dependencies:{debug:"^3.2.7"}}],["auto-relay@<=0.14.0",{peerDependencies:{"reflect-metadata":"^0.1.13"}}],["vue-template-babel-compiler@<1.2.0",{peerDependencies:{"vue-template-compiler":"^2.6.0"}}],["@parcel/transformer-image@<2.5.0",{peerDependencies:{"@parcel/core":"*"}}],["@parcel/transformer-js@<2.5.0",{peerDependencies:{"@parcel/core":"*"}}],["parcel@*",{peerDependenciesMeta:{"@parcel/core":kt}}],["react-scripts@*",{peerDependencies:{eslint:"*"}}],["focus-trap-react@^8.0.0",{dependencies:{tabbable:"^5.3.2"}}],["react-rnd@<10.3.7",{peerDependencies:{react:">=16.3.0","react-dom":">=16.3.0"}}],["connect-mongo@<5.0.0",{peerDependencies:{"express-session":"^1.17.1"}}],["vue-i18n@<9",{peerDependencies:{vue:"^2"}}],["vue-router@<4",{peerDependencies:{vue:"^2"}}],["unified@<10",{dependencies:{"@types/unist":"^2.0.0"}}],["react-github-btn@<=1.3.0",{peerDependencies:{react:">=16.3.0"}}],["react-dev-utils@*",{peerDependencies:{typescript:">=2.7",webpack:">=4"},peerDependenciesMeta:{typescript:kt}}],["@asyncapi/react-component@<=1.0.0-next.39",{peerDependencies:{react:">=16.8.0","react-dom":">=16.8.0"}}],["xo@*",{peerDependencies:{webpack:">=1.11.0"},peerDependenciesMeta:{webpack:kt}}],["babel-plugin-remove-graphql-queries@<=4.20.0-next.0",{dependencies:{"@babel/types":"^7.15.4"}}],["gatsby-plugin-page-creator@<=4.20.0-next.1",{dependencies:{"fs-extra":"^10.1.0"}}],["gatsby-plugin-utils@<=3.14.0-next.1",{dependencies:{fastq:"^1.13.0"},peerDependencies:{graphql:"^15.0.0"}}],["gatsby-plugin-mdx@<3.1.0-next.1",{dependencies:{mkdirp:"^1.0.4"}}],["gatsby-plugin-mdx@^2",{peerDependencies:{gatsby:"^3.0.0-next"}}],["fdir@<=5.2.0",{peerDependencies:{picomatch:"2.x"},peerDependenciesMeta:{picomatch:kt}}],["babel-plugin-transform-typescript-metadata@<=0.3.2",{peerDependencies:{"@babel/core":"^7","@babel/traverse":"^7"},peerDependenciesMeta:{"@babel/traverse":kt}}],["graphql-compose@>=9.0.10",{peerDependencies:{graphql:"^14.2.0 || ^15.0.0 || ^16.0.0"}}],["vite-plugin-vuetify@<=1.0.2",{peerDependencies:{vue:"^3.0.0"}}],["webpack-plugin-vuetify@<=2.0.1",{peerDependencies:{vue:"^3.2.6"}}],["eslint-import-resolver-vite@<2.0.1",{dependencies:{debug:"^4.3.4",resolve:"^1.22.8"}}]];var _H;function Cme(){return typeof _H>"u"&&(_H=ve("zlib").brotliDecompressSync(Buffer.from("G7weAByFTVk3Vs7UfHhq4yykgEM7pbW7TI43SG2S5tvGrwHBAzdz+s/npQ6tgEvobvxisrPIadkXeUAJotBn5bDZ5kAhcRqsIHe3F75Walet5hNalwgFDtxb0BiDUjiUQkjG0yW2hto9HPgiCkm316d6bC0kST72YN7D7rfkhCE9x4J0XwB0yavalxpUu2t9xszHrmtwalOxT7VslsxWcB1qpqZwERUra4psWhTV8BgwWeizurec82Caf1ABL11YMfbf8FJ9JBceZOkgmvrQPbC9DUldX/yMbmX06UQluCEjSwUoyO+EZPIjofr+/oAZUck2enraRD+oWLlnlYnj8xB+gwSo9lmmks4fXv574qSqcWA6z21uYkzMu3EWj+K23RxeQlLqiE35/rC8GcS4CGkKHKKq+zAIQwD9iRDNfiAqueLLpicFFrNsAI4zeTD/eO9MHcnRa5m8UT+M2+V+AkFST4BlKneiAQRSdST8KEAIyFlULt6wa9EBd0Ds28VmpaxquJdVt+nwdEs5xUskI13OVtFyY0UrQIRAlCuvvWivvlSKQfTO+2Q8OyUR1W5RvetaPz4jD27hdtwHFFA1Ptx6Ee/t2cY2rg2G46M1pNDRf2pWhvpy8pqMnuI3++4OF3+7OFIWXGjh+o7Nr2jNvbiYcQdQS1h903/jVFgOpA0yJ78z+x759bFA0rq+6aY5qPB4FzS3oYoLupDUhD9nDz6F6H7hpnlMf18KNKDu4IKjTWwrAnY6MFQw1W6ymOALHlFyCZmQhldg1MQHaMVVQTVgDC60TfaBqG++Y8PEoFhN/PBTZT175KNP/BlHDYGOOBmnBdzqJKplZ/ljiVG0ZBzfqeBRrrUkn6rA54462SgiliKoYVnbeptMdXNfAuaupIEi0bApF10TlgHfmEJAPUVidRVFyDupSem5po5vErPqWKhKbUIp0LozpYsIKK57dM/HKr+nguF+7924IIWMICkQ8JUigs9D+W+c4LnNoRtPPKNRUiCYmP+Jfo2lfKCKw8qpraEeWU3uiNRO6zcyKQoXPR5htmzzLznke7b4YbXW3I1lIRzmgG02Udb58U+7TpwyN7XymCgH+wuPDthZVQvRZuEP+SnLtMicz9m5zASWOBiAcLmkuFlTKuHspSIhCBD0yUPKcxu81A+4YD78rA2vtwsUEday9WNyrShyrl60rWmA+SmbYZkQOwFJWArxRYYc5jGhA5ikxYw1rx3ei4NmeX/lKiwpZ9Ln1tV2Ae7sArvxuVLbJjqJRjW1vFXAyHpvLG+8MJ6T2Ubx5M2KDa2SN6vuIGxJ9WQM9Mk3Q7aCNiZONXllhqq24DmoLbQfW2rYWsOgHWjtOmIQMyMKdiHZDjoyIq5+U700nZ6odJAoYXPQBvFNiQ78d5jaXliBqLTJEqUCwi+LiH2mx92EmNKDsJL74Z613+3lf20pxkV1+erOrjj8pW00vsPaahKUM+05ssd5uwM7K482KWEf3TCwlg/o3e5ngto7qSMz7YteIgCsF1UOcsLk7F7MxWbvrPMY473ew0G+noVL8EPbkmEMftMSeL6HFub/zy+2JQ==","base64")).toString()),_H}var HH;function wme(){return typeof HH>"u"&&(HH=ve("zlib").brotliDecompressSync(Buffer.from("G8MSIIzURnVBnObTcvb3XE6v2S9Qgc2K801Oa5otNKEtK8BINZNcaQHy+9/vf/WXBimwutXC33P2DPc64pps5rz7NGGWaOKNSPL4Y2KRE8twut2lFOIN+OXPtRmPMRhMTILib2bEQx43az2I5d3YS8Roa5UZpF/ujHb3Djd3GDvYUfvFYSUQ39vb2cmifp/rgB4J/65JK3wRBTvMBoNBmn3mbXC63/gbBkW/2IRPri0O8bcsRBsmarF328pAln04nyJFkwUAvNu934supAqLtyerZZpJ8I8suJHhf/ocMV+scKwa8NOiDKIPXw6Ex/EEZD6TEGaW8N5zvNHYF10l6Lfooj7D5W2k3dgvQSbp2Wv8TGOayS978gxlOLVjTGXs66ozewbrjwElLtyrYNnWTfzzdEutgROUFPVMhnMoy8EjJLLlWwIEoySxliim9kYW30JUHiPVyjt0iAw/ZpPmCbUCltYPnq6ZNblIKhTNhqS/oqC9iya5sGKZTOVsTEg34n92uZTf2iPpcZih8rPW8CzA+adIGmyCPcKdLMsBLShd+zuEbTrqpwuh+DLmracZcjPC5Sdf5odDAhKpFuOsQS67RT+1VgWWygSv3YwxDnylc04/PYuaMeIzhBkLrvs7e/OUzRTF56MmfY6rI63QtEjEQzq637zQqJ39nNhu3NmoRRhW/086bHGBUtx0PE0j3aEGvkdh9WJC8y8j8mqqke9/dQ5la+Q3ba4RlhvTbnfQhPDDab3tUifkjKuOsp13mXEmO00Mu88F/M67R7LXfoFDFLNtgCSWjWX+3Jn1371pJTK9xPBiMJafvDjtFyAzu8rxeQ0TKMQXNPs5xxiBOd+BRJP8KP88XPtJIbZKh/cdW8KvBUkpqKpGoiIaA32c3/JnQr4efXt85mXvidOvn/eU3Pase1typLYBalJ14mCso9h79nuMOuCa/kZAOkJHmTjP5RM2WNoPasZUAnT1TAE/NH25hUxcQv6hQWR/m1PKk4ooXMcM4SR1iYU3fUohvqk4RY2hbmTVVIXv6TvqO+0doOjgeVFAcom+RlwJQmOVH7pr1Q9LoJT6n1DeQEB+NHygsATbIwTcOKZlJsY8G4+suX1uQLjUWwLjjs0mvSvZcLTpIGAekeR7GCgl8eo3ndAqEe2XCav4huliHjdbIPBsGJuPX7lrO9HX1UbXRH5opOe1x6JsOSgHZR+EaxuXVhpLLxm6jk1LJtZfHSc6BKPun3CpYYVMJGwEUyk8MTGG0XL5MfEwaXpnc9TKnBmlGn6nHiGREc3ysn47XIBDzA+YvFdjZzVIEDcKGpS6PbUJehFRjEne8D0lVU1XuRtlgszq6pTNlQ/3MzNOEgCWPyTct22V2mEi2krizn5VDo9B19/X2DB3hCGRMM7ONbtnAcIx/OWB1u5uPbW1gsH8irXxT/IzG0PoXWYjhbMsH3KTuoOl5o17PulcgvsfTSnKFM354GWI8luqZnrswWjiXy3G+Vbyo1KMopFmmvBwNELgaS8z8dNZchx/Cl/xjddxhMcyqtzFyONb2Zdu90NkI8pAeufe7YlXrp53v8Dj/l8vWeVspRKBGXScBBPI/HinSTGmLDOGGOCIyH0JFdOZx0gWsacNlQLJMIrBhqRxXxHF/5pseWwejlAAvZ3klZSDSYY8mkToaWejXhgNomeGtx1DTLEUFMRkgF5yFB22WYdJnaWN14r1YJj81hGi45+jrADS5nYRhCiSlCJJ1nL8pYX+HDSMhdTEWyRcgHVp/IsUIZYMfT+YYncUQPgcxNGCHfZ88vDdrcUuaGIl6zhAsiaq7R5dfqrqXH/JcBhfjT8D0azayIyEz75Nxp6YkcyDxlJq3EXnJUpqDohJJOysL1t1uNiHESlvsxPb5cpbW0+ICZqJmUZus1BMW0F5IVBODLIo2zHHjA0=","base64")).toString()),HH}var qH;function Ime(){return typeof qH>"u"&&(qH=ve("zlib").brotliDecompressSync(Buffer.from("m5Q1PpNxi6fbELoeTdPeFsfNhDte5xADtAVxOt3/ozoRxrgbH5bsGl68oohpnQVUb8eNIYI/kOWqEKxUK3YpWObGFrI7vOhkIOHILMjV0PAXmV2IxyQMrTtF6PlrsYUry99vr/+43Qgl0A8jbLVcPTqQT6BFr5jusOg+7N3h5PqWz59E0mMAJ7fqBxDjpIoeTCkWpnc4lBx8afLypdvjs8bpegqgso3V9XulBQSobzX177mc9DtOFmw26bdeTx0jlpAPYkdPrvc29bv7chqUJsD2UFJ5X594a/VWJ1+MkJyV+wN5OZDxo3eu//x8PXymN50gmj1bTIPpttcMZRHbAIdR1M5PaDWOv0m8VH/8f8mHoKtF2/ZolNhx7KiIfufzlrA+lP3btFYFDaSqJ74ZIVCT908Mvp+LVHbdcXCsOqiu0JFHxWwZ2IE0D/IbEYjcRGVRExjC3wF9NSU/aVfjZhNrlc3lAvMBXamuPhuVyl78CmB4c7KiRqzitU36//tLq1St7pY8Cz0Elhfs5UgbZG5eIIgwG1Dd9+67nlJVacaSrDOSYQCbFuldeq9UVVKPZDfg9hJSEm2SAmfLWfyrLPe6hyhaQAyCZI90VqVHu+xZko+6fWAd/UcTpIfRh4hB8jwudbfmCCmTm2qemOP446xFXrIXPYvSYcvzRPdN65M6qcphuuR3o9alHaeEegH76N4BZMTWr1v/fuSOac8hARhHOnTMNmEG7GsAQWZ87OmWHLpaYFRqsho7E+S/N9UqncIuR1O16B6D91Cz+u+vQUtnbLPyM46MLnQuCQZVv1sUNWeMJ9aJmso3kiE/1io6V/kF8WULBkl0WQ4S3cCYhnjm/8aV8N/vO7E/cEY7e4bnaRw1r2oR9vZ88Rj6vR25v9a7GECWaDSr9mdc9czFnv5BkkrS6ukldqJ5DLX058zAGWMFrHLYbWzdzNgAexZ+BsK/iGq+L5/qzHY725muSQqCQPAGBRDXDmkiT9r60WRMq/25lGkiBBlW2j+JIlR1NoLC9ELRTQVP/+EAuvkylvXtdtx/dm8VQjgExIgy4vNjzH39OZ3IkgM9iUj0CeH7ajljpzS/+0v6lapgLYIEoSWIlY7EMrZXagHbLsdTf/X/Ey4xm73FQMM249yqo98F830xw/pTAvvV23J/bfH3V/uOkddPn5RX7cw3uHs1xdCDX8No7/j4a3/H50P53d/S2QzDZ5FJUyw/wp9hVkDeh/6kr540+UyBPG4I5dovOzj748cLpbWtFxTwHbp5fXYJyjoANl1iJyRE46UPXeIoDT8FeX2RjHFie+grFw+xtGXAoIyA/rajNXTxC/G4UTzlKkAz6YlVqCeGAF3BVER9B3oWfY5uCz7nXbdXka8ZV4Zb9wwoKxiJ2+sB7Vy27qX05kuK//E0H1VsOS5JlJcej19bktmmDDMiOkT/7UL5d3SbX1oyLqvLKtE2QMBM6Zc+yYLP4v0dJENWmH1GgkLcy/6mT2JqvgxnMZPrYYKjzSktkx5BjD9l1uisbIuUKx/d27W9QjwfoBDzxHX8TpYj6jZZBWn1Ez1eooeL141TydkF5ZrRxy9FLDEHJ7DTY3MwKJikxp/qNB7bMZLKxGfpY5MkC2OkWmdrjxvA1VLg4eI6V+tlVF9lpCBQIIwb/rSOHE0qk06sABmIiF/y20RFAk7Hur3dIilBeELYkKqtM/vRs/fRROrk9fAESDT4ODVB1mN22z7+w0oByWet/dqayAKSKdNan/qi/dtw09atJ5lP1rJxlyu4WtGfk0maAdvFB/MAz64vaByyJh6BL4RPDOB6pKYnAhElEtazWeu+S4zzHd8fsHNKmQA1QaZi3iVEkQISJ0FxuodYeJGCBeWWAPX4b24t9NLoGi4yQ+F6C5r+a+Y/qxWL5IO6f46nZPmoWTEBczmiAW5BMlLYuv4RmTePQPkqk39a0Tr2C/bUSzCXBMwQdl/ohYmL6LDgB9UW4tcvPk4tCavgqBdZiAs3lIyhXOQUqHOKsQkIlaMkcAg1sY/oF1Q89t7ZJaDEem6tBhQYoF2zrufli9/zu0Uv44i6uAOqrVrzhmQbx4LkhlDaoJd6VCJgUOqxb+WhXq4TCTFm7u0QAkF3xABd5mG8wQ6D3mYRTvbkIdeP/nH7zGZBYiyfTPnUItofH/r8H3+JMio366Mf7tGZwoD8JemcM1tiEUyf5F/WawgEJS6EsQut9zOixiPjVkKfZ1ZyUhfSei4sKPDY+8J12fhNCVqj0SrfCGv4rhW+5MZrfAXrYt4BrOVyFxJ2Epfzo4XSoxT1/QPqWCY99iyGj+sfo/8GG5tCRLkcQiW5E+qcTwohj4IkVj9ylqIEMon1nZ7WbzjzYWjKj1727uOQW/OsI5ok15sXTuG4OaHmb3C/UKFUvVhGIWi4PQt+y/VbbekMWtDdZyuuXilcee01qSEU6goPR9BkCMk8dcLyZ8yxanqt0d3Y6LLxuLvmGjB2Dh/euTl6S5efBDEgZU8PU1sPBfpi+gEEClKkQIGbetf5i4MTv/1gq++NKH65deDRP11IOXHE67ASgnXaY3a8hvFLdy/JazMqVGXlIadoAoDvsuC1K6fTiJyI41HEIkSq9qnAcL5ud8TPM/nJP8AGWjuGzbmdYZRu03OGGIxWjzM5pT0NGE/wLOe1vQuxYlxUHz0pxk7cYXzgiShpb+npmavZYR/ubaUmckdnXkAwW4sflHkrc1fe3GbRV/7DkAwfvFlE2DhvKdV2YpU7NKIzqgkgfMmzEGrRmzOmgVeNq+CVoWEhI7t1VNJLAwIYI8qRyIgF9V2sW5gy3q4e7Kg8YGd8lVudZOiRBSss+kqFAzReS+US9yFDeW6pDqjnUKzvEQDKurSRwX46rgtEnuEvCDUjAAVFjnsQoOppSkuBqt7qMjSY3C0JZZGjO2SyRuiEMDB+zVByrSRnDqFfZXOJPadQtiBHzFlDzx62k/1tM4A+ATQ0OMh3XDpFb2c4yUxt08uF3r6gkSi7lQt9B0VcgobfiUiiDMlDWwnTM//2q9iyr7KafmzO5K9iZPeDIBO6h++JFZNPaV89zCf93w7hew0Mz/SOY5L851pI4DfzS8BB9ANanj146eQNYksYizDsru8SyiM74PZ0JRcoC4LkGcr1pFjmnefLEP0U0+VpCAuJolVvFPWhw9N/gyYwqa8UXXUU8Vjex5aNbRDG+ybSInA5MDb4CAGdp9z3gkrGe30fiOBwG6VudsTYTntntJv9sNYPpPu2uvm/z9VCmLF62uIzMWxnJNPue69SDfrGiq3TDK60DN/DwRuI9LJnm/t3c7pVzatoOdQIb9VDQ7qSr4gcLj2JyoL4CDCbWSGN54Scp64trv0/Bd0MArsP3cfuVGJ3R/YvuM4TIuFc3OEkUr3Z+Opoc4OK8xI+wFyMvZn6Q1bxG6xQNVqPqVYRWWctJdOMziOh02TPVAxJvKtztZ3LBsK5Reagpf3X2WUDz83H/mXcHQF6exT1UxUqsdrdygc0nhO8+BZsQuaKZcZg+AD4erdkCMsmOVlh7vZRb0skvCeQOY0/g/FdOgcMJO84yr1VrbBWAyNfAz6QXxsM7waLDNVey5kloY7/UcrYT4CLbFy34U2QDVAYLya9j1wCGFcU2k8lfcDgf8/D9s9J/JP34UvgMiCAgJMd1vruwXEY4plcWWM9sffMyJC2bhfiaT82IjyHao4qaa8FfYvpgH1P/k0iQBbkbj9m05YE3ZvD+B7FxE/HJyfH50e/LRpDNB8kTGQNmG3g4NeveG4MEcTVMtXZJj5ZLmypcmlDJyP/IWGV5Z2EXJ7/yIBn30SDx4UOvCAiyAHCMesHEKp5HkU5XAAgMtsruf9w4bXKEO222abg8qlGAMAWF5q0AmUgYZnZdkIwzzffdyumPvYGvhh+KxJswi3L+witjE1IFhcAQIwipfC0Ub2yXWtUO/cIAOgMGI3QTEMv035CM88PaL56AY878MDU9G+RGxZ0Mx3zO4IVAGjnZ7x6/+IwGT16DmZ1L6Gc56/NmxYyHls7BK6zIrtAOXmjH4JusGg3hwsA7FLt3Vp40yiOaGdQ7t1NFi5rBACikzXhOP3UIrkbDcefk3X4xQvOrh7LXIu2eeufFjIAADpsBPL/z5X9+4yjc003Fj3a8LNnhUD1hOwoGQFNba6HAtIXM8lPcrKdQ+cDfgrP6a/FuHzrnxZvAQB62AllxUSTjcVMxU3McMlpyhUSW5eQfbuDWN9uywQAdlCkuRDc96tJYJGPNt+JymO8zjcxk6FS1hYAKAHHhge4oL2pxk4xU5cAQMsoyZHIuxfE3v+qLIe2g+uXR+H9fxqxBQBOTtbOSmEYtcvaqxJTS62nGgGAUhdNNDYLH6D1Q30wMxk2T17u7nrMqwA4ubndphm/hT9ga/e8lj8D+n8mfWU7uv75k5lRY7YAQOHY5LBhABu2m8rKgh1vBACkfKImGadxdO+J/290FzAydqnaC6PanqxAMbf+aSEDAKCZ1KDG0CT/7Cn+CK6WGdvtJlFcY58j/Wt6P6qPTO6EuST3Dyf0nP5GbG3f+qfFWwCAChZ7GkOveTCK/NGOG2hstc/Ru3YWLs0EAKL0j4QM8P+Vtp9MvGZOWx6vOY3j2lW4AEAtsL1MeFH0dozoKms/ba/tTFwCAKfrbW8uvqZn/HmF/mCfvtzFFZVzuABAme32uMqEo+2OHNa+2l7LmdgEAFbmJmy64nnmVWpNaFd/2t3VKFgBcKpzu7o28kloup/NNcK9j71/69qWxtuaaqhxXACgxOxixHAHEHNfQFONAMCSL+ZWgSpUPGYu10rNZHqvkixnxyUBfzY1gvEkfYa1Dp5Bo6k3TEnpm5L+Xjh0T4IR28FFkkbVwICppEML4Yk37LIEU4WFpp7AE/GuzZdqKnTkSlJcDbjy648qhsgY/SFUed9dmpQ/6Hqhv4/edKEpn8WfU3BPbdAxrPtWw1en4AtQy/yoiPIWHL43jQE4P2RdL6Dw0L/2zm2uzRbntqOIc7sPeoHMGqRIoEb6MZG2o3K1sJagb+CxF7gykP/u5U0ZLiB4eMhj53P12LdCzunUShJG/MIbXlj1qj51CerFzKlLX/jZkXWaIykFyBAG3q7Kq/gbdruRGxwoZEhprvX3jeHvCEOsRvJ7xq2WbHp3srYPTsw0JnMgPRbexzTV1ag5Ji+F04V9mTvxZtPfm+V2C5BuDerejtNeMaopxMOlHTHSNETXYojolQZZJm6H/mKAIssd+64v9Hvt8gwrYkR0HyeueLsKFe7bQQ2RdRuqNJGubWnCP+PWkI4UY3jIwPmoumOdPY7joI9YOZsS5A6+jbh04E29vv44lFyHuPzaPZ6IOoSVM+eeHipJByUxlWs3zXL2FknUEIMYrjIw58ElaOuT9VEqZYERxZdtlv3obxEjgNfDZAQyMrsvKZaFCWEFhEzsUPp60zJiIjUcIoUbCwdjfhK+5OIeDfbJSCGvdRWh49uwuTrjxWNC5+G3G3fl+SSEf7/M6Sb5+EoRYXlX88nreKWJgwFex1IAkQCIFLTjRk4CRAT6kcV/UYs880NqTGnkcyIruU8kahRNBz6motSLMJLZmyO/uReDgcBnSvXxgglOx+ucDftK8r1mX/uFImMmJBXZvUzKswSC14N5mvyPSN5Ovy6yNrledNZO8Qaasz94/qx972we7dfJ/7UN1IoKc1x9t3SoMSF/jonjOOpyHE3dD7daAgAy7F18sIvrpXXR9c24uHXlqJ3XPT3AmxZNxv3XJHFgfozluo/7uxbelH7tWkT4NjzYO+EBJSTM0xO13/Kawf9uuwnAjCbLNVU5qUkdarMjgBm8cC1XJs+PTjS40crPmVrTCcqbhldQRslyFkuARwkbF4npEuk6aJzZMiobMqpSGBCSSsCA0Q2ly2/LcvA8r/uT5pgyH6IqVMP5NkFP9dgsJYNpWLtIo9Yo+wgac9ys/CMof6xdgdpKaM19D2OE+NLZhuLHaWxiybWdVPzwtb+QN85DOZqs9bchavxttzWhJWGzNMHEwhTXg4mg3yUHhYXzZsW3tCjSMYlcsmeTd3rdiGfwXgREAru8FldAwrfQJgsZiKHlSuDPegCE9AYnCEmJ83YM4JBqYVFd4oa3oXBE5vlRsxaw5ZzVgB+m4Rrsm5a43hULXjRTekyLUXYG+tTbryQk5S8b49KldCcZo/LFfqOnZoUANk8JlVuhY9lJ1JCEn90Qmss8FMd5TThArcFyTz4sjF768a2h2pMKk6dl3y4P6MIVXiiGnQUtqclpWXIynEHfnowirSlUqtOWRry8ZuRV99svR1zIUKQecVfQU1KAx+fQ13B/NCrCq8K5yYEPSG9jOnflyFmfLXvfa7VTk8wVONZV9sPQDyvnnoExNEvclhRg9UhZgCPLDsznc1MzdQ4Xcp1t2NN1QpnWfN9MIhFLafM3v25bBUY7/O1Y6hcUdmr0loXoXOPsj13eY1Y5XrvCldQjWDZRiq7M3zbLDaOKo18UgJbGl+Cjjj/HONVmOdqoZD3Gzp3Q26ZposcMZzXgG29fpdPZfUs+lKYLGFZgFHjAx2cWMgMAut9paJaFV/dpqT26X5doAgBRlDPlc0TDOoEFH5F2PH3eIKU7T1PaaHZko+FQ52PCT3Z2r5MfbaZbZ1jriHGrmQEAivucImnp+FhqtzH57tcKTQDA2UU7pnyLCF0r0MvLk9q+MfFu3VOJ8Tjq1nAm9ub3oevs/mUhpgJwtpqxOSLccLIH/tZOO7s/uXN2mm7ZsJaJZ1YyAwCzPODUcmVh3ZHVrtJ9WqEJAFwpMk15SOSpB0jQZVuW3az9ZZ6fDwXswQvkC/nh0Kuuo0KOFyESvLksrTQDABYSqqGbUNd6Zy7OFUl2u4TQbjbm6yA4ysao7ozTY/nfwK7Ritnj/KwtGBPoWCFzboZudmClIjWWy8LoPemIPCzBDThsprvLH94dlVpV1E/a6m5+kPawkI8RmnmYjOQ0zgXX3SNWPNoiZy+zX6aU4FTmqcIPvygj2IKVr9gp+uSQR6fBIYkKuH83+0jDSZQXrWE0SfQlv3dsUSDkhMt+y8MELeh4Zh5fongsUAwTVpBg3LkvhByav+65gLZcARnOAkoZ6qKXr8oKJQjej/Zxpmef+FYGuE/MvbneN5NGzQsOMttZyQRqmRUYUnOGWuQRUvYLtYZUFjXYmWW2PTSd2YWdRB4S/ay7srVUVjRiUeHolw6IDi+wR7g0a1dX8PIQ7iF33H4HKg+OZN0ECeN5jU4b6+t01tkBhWmNBtyxFLWOXlqXLgJMXhTd4LMd/qIWusY2EIan1iLI3Db7LkivHthWASxeVIS5p1tt2eKrr06IHahOddTCuyfjwKgeI/cVhjxfIWYIBK+ECKxxBA1sKpfB8WAqt6l6JMc1HRy9K9bdeLmi3A7skIGcaGUqPsntE0JsbWf/y5ZWkUHQ/OInUz14/vS3Zepf5AiCHthvHzxG6997qnZ/VIBXL44ZABi7P678HuFYQi9+VG7nz7JThb42D1Ja/UOZAABl2Dxjlpb94X9xz9Le8Xvze4KxRqwirrH6fE3zCR1z0orhTYPx3BDDYh2+/b0WgDvmBcGgRz74aCT/kd6vzMlW7acZWFcsbjcI3PDk4m7lpX5p0rJwFMehTSj+jxVE+dzgun/lfT3S0quML0qTuLywMO1NcPXBbmxAnlbfO8dn46p7fSEc5lCBQOH/3enX+aR5zSkP97OBnUPfNzJ7OWw2cSD83eEFQgGutlK+xfDUW31j2c/uTXHsTFppSU1IlqMmFrvTxqPo3TvjnmrAbCXOEjiyxoPXSU6KE1+h660zW+DCTDJXdIWHgW9rjAZRFldhGDf8kMnHZ7Z3xv8VHvk8koW+oB9jLM49RJfWUk97J/APnJ/fSGXpsL5qOHYC9zr4DVhAoIh6VVl7Wdf8gZ+z9o3f+u9t1R0AJUVU1YOvsPTMelVuBNl5ZgDARo2Z8Kwope9STcn2XtQwpwkAzELxpXuXoNzfRwkA3EW9qguTt0CvcaEp1bRhXT4zgMIXW/oH1x8r6S4tYn+NVjkAZUS0aEpN89/8qbkTzx4hZf/Hy4zoTuNTDkAZEu3aDdeM7ju37D37+PJ2ELn8iI713Kgb3K/aM0Iz/XeZAQBm0IqZMF1F0VI7sr2FWmY0AYAWz2+8dH9HicmbBABaxHVZszr9W8rn2OaNlx4Hj89rvmpP+rVR53gBooTyKE8vMwMAVgNqfNkoKJyMuzCfBnThsmKxDzWgta14813RHxC10l+y8pc4+sJf7hyfl4+S0VBwAxFSK2JrXyjBNrqGpwraAra7rzmHkv0SRzXAdAQFwPByYY5jm/AFcNoN5+kCRsHn1S3j5MVkyXTJpqAvgKjm15ita1aFDGH/yLiFSW4RMuQQlP2CblggAwDZIxBJ9u2V4AG86DbtNM04Vf5HOxqwNx2YFj+hwJVod5dk3YOPwdUjHsN9i6GJVD1DqPaAYFynCr+hoEOfQN8tOYI6t6hzrv8Eghnk1QauewwbHXT9hMz5u/uvM5hjjyup9o77i/oFOZ3sZ1zYczNE6VBNct+Ipz7y1rq2oSL19577yDqKR8eTTs7dqQuvAFGI9SJKhyWhTxbIUAmlQzcUCifbYDQCm5ZgTM8BgxtPEofWXx5xR3vb6x6mAABfq4OZ2Bf3QWmwDsKoPH0t7zwsT67ljpRKtdRKD6LhVt9j+jC1B57ljuCM4KFeM74Owz9Tt+YjHliCIXGVQf/hNAj9kTYwCv3CYVsMA3mxl/Tv4bBsaIGQkA5MYvSBGprX2ZZsMDEGn0f3gWt1iNNitzEmt4rFaahhilttembKTlIe3KG1FYnrH3yT9/RKY2ftAODo6BjXYmBNnMhipcBIuuSIykTnuBTzT1+KK3DYQgWEsHtmp61VpHgGsUqFAQdN9c+pbihqB1aNbs7ddtqtMCuNBgl+QYLuXz4fcRieV1bsDtGFDLl7FNpgRoAIuFVTpSB7CGOBufDPtS09cAHw8Ee7Vi9P9PserSl3LM0VW6Y4wA7Z8n67Ub0b4HEusEk2lLcLZdUCohNiwRcsyGbFWD9B4pQAxHAf74qaxK5boelshEZYkbKBRzLD8/WsK1sBkBJjoS0CbzvDzaESCdKvaLl5ljKgFTljxu955plTnlwV6udHpob30isCdvyn+cjy70SrMOQd5UzT9XSGKSQo5pNwkR8fe2EttpUHtW4JDWgChqR56n60hyNkgLYMtgUZ5JJYMBgX8WVNBOOI351ZZ4eOJr4PUxHnEwn88CCW5B1VdAyC4mYZ3phpN+829Fdmar42/6h0NXmEaUVTwRkxSFlRKJHmhFQmEf/kMaBkDKiQnJF1MZDuM1w63sT13Ns7ja0SbdvW5XK0NW9GMEQU8OLRz9Oza9c2iQjDSj0gWpzDfeSM3/FWA+9ezG8kPs8DMzTLMwNksUzN8UF9UHM6xJURLxbl6AowZO647mE+vhqljohpf8HUjF0G0WXHA88uf5SM/rQPthVU7gUYzesF7K78ijuTut0GlD/L+Os1d25SWrhC8eETRevlOnXXRkttG/fUImX7RUrE2c9jGIV+GdFGSRQH5J+TBhhgowvF6D5dlPcZizwZzUfdYWL8pooHn6MwXyot6OHLHB6EaNLU+v4Ah18Vq9JJ8yDprHi/+BqP3K/8XWbgnh9WzVXz0DuWUT3eus0IL/K/FjEDAIPARjYKiv/XuFLFeUBQyspS+1SqFnFBWZUJAAzvaP0os9pVD/DXoCud2vzK9yiwRgCuzaC1+ETnFL36Em4oRiTuA0QdBsRzDMWT8nKe4OtG1/HnnshAdbndO+KspikAtuo4lr/pAVOasQo/Eg0P3gmI+oAIF6xcccAwRFCSKLoAAUoSWXjOuv3novf6sav5S3J6Q1sAsFt2zubmEtdw4IMu4a6x9LwBHjgDDUFk6BLG7oBkxQG2PVe82XmW294CRBqr6E00PsKefiEwnSZ1x8RzaadZDWKcM9eb8c8XdNrDaInjnJ8enL+uAmE91L98hb7X3T4Jl7/28potOYED6MPO2lxJfP9QQr+bN3ILJUDSuannVwh7P4A3LlHvnnyUTFzcdtHfZo9lMMkdWsaAKBLa9ViF0wNTvPffgMlHw8Zz31uLKmKnPaOgj5Oa2rSJ0S2zoodeqhFs9g04rLVTebv8EfHOveSA/ck4WZJynSiHmohE3Z2i8Decm5uva269GpCb8DXQFObjhRYE1r2Nspv0eUijSFm7EdHm40ZtMwAP48rBuo116oNXwZFdCqwbkbI2qIZypvpF/li+Y/kfynCLY4OhnTKrayvJjWYd8U4SYTSccDY3Xj0gzw31MHSd9Sfn9aJu0tFxDhNbucJJC1GOb1LEeUjdV1+8mhbx0F/b4R7WYVsjxpFhk3vzc0baTVfCZlu7Gme0TBFUNpz2NToaHhKYzAa9vDF+AavEFB5wwLNO0E1sFQyzGFvR3MWYlluG1NedBGdwDc7s10P5+a16lBmw07ZdCkauJAKiRSE/jpecRvz43joXTJVnXQYV00NQMFAmQpqHA7+Izcw6JiAKPSlZNeaadipRkKC5EcfHDRaX0bIq0jv59fwJbWMjFJwGE83KkL2MvjzvzOn8MacrZUz3Xs+BHT2N/8pL9MddHVm03z4LpjK5B5mwzJwJ+zLtdEahWW0LLHKBs/NDpbNkYg+oatx1T9mU1BLhCp2ud2FcYU0hwX7y7fufvhf7QpoXy4C3ohRmZsAbooFl/+EUza5ywROE/DFeX8XxDrEpe11AejgeiQVxPrcxvJNr27zNTgR95bZBrtyIf/lQHwiP9LSGtqZx6Mqwi8fpCwV3/CbUagNVtE2JY5/6j8dXk9ZtlODZJhyUryaQIuk5tPougUzZopSA+wDvicXXMFmbhlUQfRE89yGP2HGFlzNSL9yPGdsdPXhqjMjFlbAsqG3zRuZrEpcojwJnHAEGZ1y+Sezakpt3MMBAF8kJadJHejHMsRlh7IYG1C3IPzcZtPcQdrEqNb25BacnOUHMER/WbFWl1WBOghWhgR1GCTuJdWsB067bvoTpGdfvyzLKUzjfV1aCJvzU9WJuhJGWAQixI7jxotnriyiGpoInh8NFw7mM3p27YhYTl92aFoYMV9BVtFwUkUMIIGAJsf/yhmH8mqYwXLDvqdhQfB1JKkBsxZwKrRt3lWJGt5E7xac9wWT8mP84g5+7/LXx7eU+mJ/lCKENf27FQsEHXUn42HiS0t3hd3hHnBOFNHvovDHwdTRhJ8YshADipQOS6ILAGJquSC6EX+WEBcffmD2/Y40qMQZiRyfoWH+Q25eFnkSuwU5tDhqlAYkzEct7j/zZLhvG0kFFuifwMl1/UDqwAkh8qckuUmp5ZY8McoQDTNMcChIbLDfAO/VRkGT+eAX2tm5N+PaZk/ydNYBP/K8bu8Ej8PvHFKm7spSw28o/LmEGAC5pMmCvNxvVhPebQiWLUR+Adza72GN7CuxlZSYAcNyekTO4J2ZzO3CuPHq71t92Uz8AcDSUwqE8hO5zfHFDU644U9Ay+8sCjmgT7F6dzQyO13xf/Xg7eFebJdUcpCpsUlInMLvObAeQK2fhHFQ1z/YOFMZ9pwkp+4pM0lH4tvQqXh1Mm8BajX0E4zycPgsNJIA1909He0x8Vph+bw7eMptDl97t/rvxZeGCBLCKRL1lS02j9Wdrc09AS5nYntHjMaeXPqOabnUYYlNZuowZAOgIdnq4GzxY+RDXJ0uyg4dHjh9zuZ7h44wmAECosydtFmi9pLel7Mr2AwAspBZRWdSa+xSEm41jpJJ/M4grDMaU6e7OOxe6qnKcTnNNHsThXOD7wY53ei9wXS2y6yKkv5yIhrLzUjMAwBE0lY3lz8mAnk7GYndnANqXqc2/yR8qU+bgwEWjrcqxyET/vrKifEl89qjFcd5xJYjWeNL4cuM5b15gtSA6vjLXdTf+CbN7DxkT6pe+ezx8Pk3InwQXD3lRkjH8x/xSmatfpeNbb8U6v1cd5jNZTDkqsCcFtTkeZAmTNZNHZpAlQXHCNvKJLPmSYY2FGWQFqwIjGF7uZUW8fNkJqaTtrDuD38dgPu2P+fPCrqfP9VO+ivU0KWzCqZFTi5gBgA3VUnDubCwJOyJVpSyzs20XB0S3SnMmAGDe3W+Tk/sb1lDu0fvpMEPHwfl6Yf/Zccz+vLeUy9qvaxrrcDy7rnXhrVnHatqN10+Yd6p/XFgMANTq+Jyvo2Q0625cVtX5U8Vj+Cdd1a260WutpyQfpIT8uRrOjzlvxBzLbzSGf9IFWnVGwEFyDotdxvuYW5ede7SReg1slnSGyObWJHl2x023krjXeV5mlArRnraCIyB6FGRzUoipar05GyQDm4o0XfRX6Dit3pnvOxtO8oL09NPpfcdr48nxwippC+9PaOdsPo9X6FxOTp/rB2ZuF6qhS0Wdq5gBgO6Imy43caOrw1euiEifltzzvjZ8IR/AC1mgCQBsk0VEG4ENI4/9gJr2yjnRd3VzQQAQtJtdTVhQ8JZZpCDKZo+MgkAZYjoKgm37MVFQOKvAiYKSTLk3/dR5JgPBdHmUgrhnlCvODBQct7M4Bk6WZ58F5+S+bwtOx1d0JTrqdJze3YWy8xsSL/F0R6f3DgsQJID1909HtY7TmuHNr+RwdD4u73fS6f3DggYJYEWJmg/rEKl4ibx68QSfVgfTzBGC/u/Rv3NKO/PHM6sWVU8xAwDVZriOKvNg5cfc7YW1Y/sst9ROThMAwCKNtFGhZFEu7XlcsgYBQAdhRJSFquY+ArVnYzdC5F+IIGGQRrzZe6Gtyh1ft2P99By/kU3rmJ234RXhZjCPDOg5vncubBZK6RxrJIzq4nuOgCgpOCyRFIPzqFjwHL8kPkMoTeggQnWOETf7XcWi3gP9yXWrVzHnzh1L4x8HiccTB5kXaM/+6IAZGQWEtItMgOUX3RLY6oWh3fWZ+AlfrdqGt3RwV9zslpDqLZZQ7vVkAS3CI1X8KqHdknKDWu5IGZNl3kQ3okR/COZ27K5klYjlfFQtGGlRlh1zNsXM+4dqpYu3Zu46Q3qiC2BNV5SxCmBY0CmnC7Z0zzl+9TAo3yA+63yJ97ERlYtAhGJuEx/H3/rtxEc70i91qBQ40GZZuHjJDqsfRvQn+mwtIktMQOQ6oOdUKqocG0CT8zOO4DwrSgqGXY/aeXfTtptCG4hA68MXfQdsanJGpjQpJyowWRLjMMTk8j9ipy8AgXSHfRYU0xI8D+N07lH6hj4Kcsc5sz9e0eWnvPAJ4eT1A86qHzcmMjHgJSXd46y8J58Uvp5PkrrECE7EBdGaEHISNfJZvqd7GcIJwyfXW1HbyAj4oRHEHD5nWCBqXDBI4Cb2u3NTc1YGxTdnMRVK5Bx38b+/2hbfAJAJXYQSeEc5aA6bJMvNLxRd94I+nUTyN2xeQx9Y6Yni6tmOqHKimDeV/fiLddJUnCg35ooMRX38HwYveIlTNzd3e5Ri0XiuGPtvj+2272m2ev1fUNzlDGzKy22fTXY0fnk1ejBYNCOwlcp7nDtgKn6CQdhmZCxB85VZuFngdHaI6xRaR8G+vln4PSwVx82UtpSI79V+/n2aS/bsL3s24luuNdaOJH17sZXv+puBi/9hdUNwoVZZu3S2hNk7viDb1nUAgAmBL3sopmm2FmNOKa924TBPjSiF1SZI9HwTs6Lx+CmjZofW+VvVjQ6t/FrjH6EqpTZBln4YW+M65C4Z88d6Q7C5JgHuhGBXzQRW2/TAgbREe8eky+sG5DkIZzBXQuNVCE2xD08xW0IYmHmdslxSVPuSYlgoTFF3J6wpxKTJ5PF6mQRpjuvSgGGj2JFks4nE7oqQJH3juwRMbJQsZN2QnNAQzq0eF/NBRBM+AGqQfh3RwaiNUfbxcoE+jfqPDf7X5YF+OJbmU2+vrUyQDjSGVo+Q3/1t+m1VWboNNmBgW4x5Wi880ERUe8DfQRs2nNbGCHmA+nZnUzJxeCUPjhMJJPJyDY4KAW+G6ObqgmCLKjaM4jMOGHCQDuA6HwSGZx9O/RpXhK7MZiwHkJQEcyT/fh0TSRWjQYAO8zIuqdAeCJ4ekflW9/Sar0O0qxpMhbqIpVICNCkpJUplMqm/EtXU1gmkbrX2R+wV4RjA7o3YNI1vgaE60se59FU9y7k45x8AkWv61Lr0GLB0Id+RZ7vX/4/Yzj6WICdHupPEMvzRQh7X7bpjujM1Sj2PweHXpHba27r9uIaqmi1YWlicYZWWKGT5NbhXLhxYIr15Hgvz3rCMuqzkNub7qSuxRJFinQA3n5k74MKmOsMTvz9GbJzBun1yguhSH5jTogfN6pvm7taYwFLyBiEHCQsNPc2xUXsLoJXF0F0P34Qo20NxZ1hGJMOFPaBIDukTRP034x/yAs8ZKi5CRO8ULjXmrtzk3VJeyxIBSKQVcUalYkpeXmJCIinuKjCAUp4zND3L/18ScrTJVIAyLV/ks7ZQunR1bMzLHZYmCuO24o6K5UxWr1MRG1FJFMImjRlEGudOYm735TMcfL0fR6IuWQLl/kTyBi6OIttKtc31nd9/UOopvhvHFm08cxa53StEcLu2tLup/ShhOqQxuGp2hRY7CT+v2sdlt1eF6dYuniBWNgkkIW3sC++DIlfmlCMahCH68YDGoKCo4mB30nqeQglOZ8mhchkJMDjdk+7tobgprjWL9YZUPDfz+QpjZb/TFQbkvuMZwevhS8V73MHPzsi3Bv/r5ay+F3yjWz7cdB0Wunpus9VRCGOfVp4o/xztJbcGcLuXZUYyHk6/uYflTvgCs0V0X2yvLjdtD3MX2avQlLvAmmf8RkDv6GPw2wlYv20vX5fSi9FiOhYkMbDeK6YxMsh0vt6sSutrzrSc96TcILkfKqmLB60RkG7P5vv2fdFmmc6Gsg/+gCdnR1qSUejN9VGDmEgM+OIQlWL/U/hjddtcPOKG1OZXQ2nnnmyQLsjnK2TaBsQG7tDkCcwkAdPj0+on9F3cG2uIHiBA18kEMhciZSUAF0EwOkPVTMeOWtwKzBgvev58NlALIpp6R6JrrCxKRHdHP1kFP8k6WlG6/E5Pfor38oKvXy8/Cxc/6HzMHv5PdfXx/TJmSt/NXX3C1x8vGP/5zZHYNzOR8+Q97kc+2o+GDLx/QChDS2rZhYj1J6PRaj3cmjSlyc4Kk3ZaUrQ+9TT/t2zhC87GMtXdVPzb6dt3rsZAdhhveiUHBO2Y8/VXbMDNxJwghXnVwxB8DpZao3DtmxaomEvx6pN5JrkiOXmeNlW8YG0lxzqanzm5Bi7cpjVzAXe4+gu5aZN0Qee3bXJVlaNHW+MrvhpTA8d42SZvX3s2VW5NXOG7JMC8Sc9MFAALjQE9Hl4XAVKs6xwjmlEE7XbgrlFWIoF0ox4TRmXzRcDNxvmFPqWD52pY7gxlAR1o4QGfLgGORKXUXjKZIQfis+pdSZNokJ1+jCm87uFL7ry+IakKAi1aSJrsGYY8NW2zm7wCwm1S1Iuuemil28IApUMWXKzAHPGIoFcUQoohXnn5Pqu3OaPlYuqYIAwik7l4jf4UVkb/DumkaTrMXETTecrfQAJpylxAtlnAtFAgTwtUrZ8vgqDDJg5sU9kwTFBUsbdEkUkU3TjEzslTGq3z4vYiK8piF9K60+1h9rDW5Seu1/aj2zheTe9g2Ye6+UOPBTTWB7lYf7HbrrUvmnaHrTc7G/D7pKl1z1nE+Pimi9X3UfUX3HGEtsB0k8X3LRGXGa/HLO//ZGECPrir8NWkAlWtH0b5yhc55K4y9+utiJFmee5eXRUyq/YATNQVdIp5Sw23eQSFqyvcvvP6EBQ/bZYWV9xK99PZn1HqQNrYMwevTgQdJ3v9C1pb3ZD71I6Ojzd2d8y4OXqsPS3N/inEGXaMrSlHTKphjrlGVEYLb+X6/HS2PP3gijW5Qb8E6nDFA4AuS393LBIvhKOgHp27plvEKUrPUIgVH41Mpefx4E79cTLtgwd1SVN4O8i6WUL+15UR9w7hf99tIf9n8pheYs4ytZHX3Fzxs1eD/eySpVmYxDLSrkudXm4Fq/x7LLebKccve/RHdg6p0XczOFATkFwVYJLIo/cPkAZI6xu7sewj4D+kz3xypeNtyl5PaiTw3BHsQvA2vQUw3ZVEwwXhuIjK8nGGkVjZ7LPdJkMQcGHdd4SSRgHYMsGbamIMCJPJpu6xAPB+IyjUZJrLyEfQt4/6vcYBhIu3EHor0QSxjChw1KQm5zRg7ylFoaPtLdhH2mwYa1M3MTxn5+KQhgwr3QHDM+XQOQkd/BHMGS07YpEzKLWw1nQuerEF8s8gh2Rl2YiNWj5hZ+8lbddG6AVumSgvs7C1LC+BYklg2iD4XEQsT1EYN3zJXSmWWkUR3TaFobIGq8049AEjXt3mONE/PWY2REoCvH0EDtakNusdHTHrZ2PQQsdOShYiJmiCXbIxA0TiRxPVQSg59cJtDANPdTrB5LCAih3pA8K8o9wYke+2YsAQY3vukF8Q+YPmdl+6iQZjxgyo433r7xiHjNTo1437jaS0Dk8fcZp5Zo1TnRht8kpk86vtOQz4K+ZzUnyHAK/riUWO1Gz1pDwlSboudyGVVodpeXVLBxENsdw4AvsKqh6sJ5aAZtYLzSDF/eJeE3tLFr2wC5nWfV7WZoMAlJUCRFwT+m+LRXGLv9APGAK0VtMaHbhV2CCj8GwQ31iG+iVfVxf/UH/D6C+onSLFWvJI8QjyEtC/tnuK0QCbC897/E89vWyHI8j+2yqdJVKGhhnBzUNwFG1IObNRqFqKPKp09tIm9i2zaRW7vovGPp92WwCrB3OQ9y1jPE5L2qVSMrZPAwCbmNrdJMswmV9bOvNscI8N5zF0e9Bha28dB8RHzM5OzwZg57r/7581T/SHAKfBmBf0SuWTLo6v0dq1A5OBuRMEwBfzadrKdm5WuZMnpNiZUO/ORQ3Zj8IKh5S0QxDg27nZRGL5nzi0Gv0qwLmknSlACJ0PLavqs13CsgV9wb+ewXelBgv4hUM5XyvXaW2jOVmLIvj41Eur0Eq/q/eTLcqzmVddYYHwak7Qqz1D7GZ5IlDF8Mvhptk9JCzGobhVJXZhBGjjS8iySKnNlIUB/PuS/3uADWJ76cljU0kKDUScyDqgcGO3zG2NGXPAj3YxGepOsSsQrvk0qY3jgt7Nz9FNP5S4d5HtIrkqxbeHPi84xUY7QbCAP7Re61fnh5zSY5aIxeQXFWyeQki6/iUO6A2FBtoZ2en29lkHkLeZDLdU/A7ikW5qrtdeSODhOVbQ4LB9DKIj1nBEVAHc3WeZjrQ1k4gk55IcVdA+IHOqhSkA7HaAjqga8ckzMv+hvtZpf23kYyb/i8fC43EaVzcfdbuz8GvjE8KSM+NsNC9krJ9U7nQ4PXdY+FzQzh0Wvp4zXIEcqR8Z2HH6WqWTotUJSirlSj5f7qqQUv12+PxhKcVdOF/WnFXOPSeGj7M//cTzBZKuZFYlKIC3dQMAAavxYkCcoWPciaQ4F2zT2K03DoNyhQZWM1morZjVDavdRh21WH6lBgG7rQgmRMjNdRemyiaYcruW8y3coffvtsArbv0HAFAUmBP7WTY4Oed2XeDsmuFjxN7KeSO+s/7kCe4mKGCLEKsRCLAjcEHHe3Pg0nzsDsC6v2Y7AICqWnoXPu9DNZfeTecDtd5OI3mo3Xx5PEAH1IamEwo4JVSZTpCum8Y8AIA94CAu7rZARW5m+kAtePZwQNfyhglB7XigRgLI7G9Ud/AhnNmeNZLpt7XuuG5Tv14L3QHYH/h9NzjWwDkFTWMq4VJX80+Yx+OZb/u5MhUx+Chu1++otgE0g8nt3Hx3kjPbs1qY5zMF37ljPC4pKty6H38odhfnY0w5oVZmjf79l54C/1zRG45U58fETwf7x4VvG0CtzZo7c5fUJcTQN8nwDXua76qr1e9ppd0wNGhWQUQKlVOXdQMAXr8G0FBV1ymfZnEuSG11l3RQs1yhATl2FmorhhqQUzJ1EhdBV6yIdkRMmOsu5NkmcDm16/kWJuv9mzGY263/AEAvDtQe+wkCOnJuUwa9dMWDBX1if6MC5hAU4LgQtqbtx/nQ5fiuaX8/4fG+hlScNbe0w73RzlUih4A3OXVZFwBwOvAi9vPh/66AqR85jOyvX53+Mf7qXrAVPs/eNetZsAvl64VR4VO+2RFq2HCmURCmsUABAMAEkBTp8dMQ/IQ3N6+JDE1aUTpQ2b2wDgCghBBjq+ZiXuklKCKm+3mkNU186WtT4XMR5soa+mH0L3Foh7Y4GKsq4zMvni7s+Lrb0iGDQHi1MJem2PaT18g02ja3vrw4+n+oneVQ5x/bt2eqzgFolPa807QJcltr/XHam+OX+Z6+0e89r2n1wp74DGdKa1i/1OEeq0dutcqGMiVWFXPqcm4AYCWsZhYqhinlpoA35MRUlpQzsLJu7axBX4pXrtDALiILT64Yx3kVdinzJIkTNEq5DBEAiGhZywlW3QUTnWuRct70py0gNfC2fwBA60A2xH6c+J8FOYX20iMWKpcPcKL+XBWPk72iI0fvOU5R5tyM18om8sq8wHfbjhB5U+4k1cwsHmyB+wx00+84H4HGDsUtddZwZbeXgWrmwOvOMOqPhBDwtVj7hW6ue0tcNneVUmqQDMZCMLgfGp6ziKs6i1RwahAKzj5kglP39AqKdkuvotlxbc3npw6BYJgsoCEObIw0MDrCwKjIAludV88YSWADBIGh96KvzXzH1mS+ZYSAoXscVlONkQDGQQBYbRPCgGZ8NV0XFtgjBly877eSU091o5qQ2RulH5mw7VaXVeN1IQNgMTlL2GIo3QRWDCBYDJdNAQBwAzi73WMn3AQu3GjHHvMXLrk2gSxxlYxdp4Ku7W15AMBxjLgJWripap9vTaa9eR4zvWremk7pJWFj+zSYDiufEtgMayWD1GyCGmxcp+JANPQEPhMKmvSEVbO3pAeeH9V7DQe+uZprusN9V2+7cnxsOrC71Hl0/daDR6Cg8wDX1Jp/djqGM349x1gd7qt6JoyqmQZPJFbffK1uAMBCoQFeQCxvZgzsXHV3eRVw2UIAxGOBLAB1nQTO+VuhVU2IAEDL0LrACTbVG36d7wl3r/bvbqs16uu68R8AcBny9AY/Xls4F6d5HHCxFfF167IZXJ6hv3UU15lWlOKxgvSGW+97nbJkTlCaYdSfav/cesBp+h52jSRXbtcTJHlhY97jI1SjqR0ASBlJQ45vaD5CE367kaAuKFhpSCB1jXkAgHPgOQYO7besCsyWk0FxgytSYG5ZNspSYCHWgBopsNUboFhexue3rOnl+npJccNJC84ztB3upUoMzTvS4cWs6YF+DdnvDQe/nSLpd4d7pwUYG0BTjqbH91Z30zA/Cv0ayrPSN96rw/1UGaJmYZ1RtjIVPxvAtwzHPjNQ+mWH+6cFHRtAzcOao/Rpyrs29Y7hbGZSMavD/ZU4xDhVYhC5Q05d1g0AjHX+oUHe3CkgI2M3nY2XlC0Eha6vqLiOqgLF1EnUCrqvCREAaAha3HCCVfVdnud7wqy8f3MNTmvrPwCglUE32U9coK+d5hBgQFM8cTNVdOjoPctMK/JSdoEv6X24116dKpTS7CGNuR16SsivwZKvECP9kH3inmJHj8O67npzvABRAnmVp5fbAAB0PtWDuG16xwVVD//lrUdpNnNEVUF3OwZaawqzNCA4i8/fFULIbMoQKwhhO3AWsQgJrcJqAgBgWoPsKmQq5ssElS6OSUyy3pWZBGBWnFzDDgAwW4gViymtJViXy9wAWNMRbwysBZvMCOQbOA5KHPjw4W64R/QpUOf+USpkGqV+XtxXVexgOMGuO5jAu7kjyH3vzo1+pcfyLsPbhmN7PXj762iP3ZUNqwxeZpUhAHBjBImTFGpTLLTZSXTdOoZulpNTJpHomHy+cw4ff1dUlTZXoAQEqr1BAhUD6GlABAAAkHS5T3VGFEg0tVf/N+1NEy9Pr/4HAAbQHGT/bLmyarxlNreJt4zxNvHWP9FtyiWl1l0ALX2ihcELlreJ+eAizn/V3F4G+SS7f/7ZK/25bOVuEMRc/v+Ca1TySGaV2qjLml6MGpLemqDBMYTBiOTKE08daMVS/nvWcXOrMyw8VqYxzPPR9ppQOBZ3Wn94/Um32923F6Bf4SOLGP1X9qXaNoCeBDw7SNxYiNlXhjdf/5XuH6xlHvXoNj4IwsCxhuYSv3dhJ4QTu9yus2GyLIHdG4zBU9yETXEIT7N4CgBw2lRyFMfnlW7Csfx2XnNsrlthiiogf/RWvmwsygMAgvRqMkRWJQfn5o7cqFbGTCA3N8g2V5A7ChqsLijt3RQVVUi2C6dYPrgdbWMVXuW00ur9GLwNhxN8o/sL3tG++7X15Uk5w2lT03qJPRQ1pID50buO9tXdccGa6zondqdzapEhABBr8IuRZmcBDryZOGA19vxu17qhQJ9sYXDx7mYOAep8EvABnLIihD5XeK67cJqcaHtBLGv/eEGwpD/sxn8AYCRou9f+WThwarxtNpfEC2O8JF68tCyVTijFJvAtRGUGlTYn6dvZRSRMBV0SAgmzGwMlCkrttrvBNJSuCsaCFTLd2dYOAIRVUIBt+SIWMmA220U8pEQurcRVURVYpSkPAGA5vKoqqMDFTQ3IlptxCiTBsz0L0ssbUgJp1EGl4sL9+Ka0ROFhec1wThHfWO+O9tIlhkYN6XBV1LSwghv+hjOV8yRxO9o7L6zWABowND0OeppOWVklfYaDzwl+R6aj/XQZoj5djUoTvPRa6TscHdj9edHR/nmhtgZQ365etzRNB6zhzAuH03xs7U1H++yuZFQlEuucLK0CBwDS9seH2uHNDQERjF021y8rWYj69jwWxQaq5JMoC+jYikD3+P9z3YWuXSpK5PaiqVnv3/RGNtT+dDX+AwADQnNN+2fLRU3jObO5TbxljLeJt17aLpXuEGpewB0QjutXLboc2/SbFbJQw6H+sOIL/ft+wd+b6U6MyAS4feN9baAu4Dlgwn2z+Xha7iTv7cMHbjwaKt72DLf/q0hbAOaU5fFiZIaszQJXyDTjCGQCC0c7nwsZo2pMW02HRY/Uh59IF6r1/PP5c6oYLepaXB19DcgySoWXzJ958fRSIXaEx1VsH2Gam0Lmqqgs4XF1yz+58jSIUy+4xslcUiznMrCcmFdPb5qBjPCbYGbb4ndWZdlTk7zNkAUX2UCtmZG5p5kbZKcGSPmQbg5rhoZEzdTOws3HiZmqF1Axb/dJKl/RkYbSlYcu24C5fKTycg8Yq1RmXyYCY9nPUuZm5loq6/LT6blR9hcV4NTDRddN9hJaWKBWNuKW/SDsDBMWZ2BHkrnn9+eyKJspnzBwOsT3er6W8G++uxQCIDwG50QkUz/WLpM4qWoLPaqjBawwk+Ow1As0bVUDxvorqK03qysvqPznCsX8fErUFw8gjE8Jz3wwTcwDP+t5YcWDpuwIG1LXt68AxgdCnHTda4UB+ytdqS58bxZnZlokH+cbVAJTVT6CbTYAp88kOvvMbHJij0DiJ6snbHIXMmB8wpXO2pO50Ms2eQuVZomnAItnBZd6GhXHsGUKzUdTbVAIvJNjXFM61aYdALlRKsyTV4o2d+fNzV1FfNsncqqpKd4id6GS2+s6waXXhzZ357n2XJ1c+JGjzqvnbjX/6D/0+Ko8lXs50Zh/rlUL/i5Uz5f2FGGc8N8BGe31HTfaZ8Nah3+ex90b8PW5+oMd3CT5LkuOJaNwEDFa1LU5J6AMj1NW0cxSaBBGzpYIND3fQ1knqFqMrhUui6Q8HCuta4C2KBp/gMhEqStieEdxfboEO58SqR0vZ4QDTeVfNksfgt1Ol8qskv2PcXNMfWdI529uTVkfRS0QPoc5X4AVENjpiVvAq4DbYRjbHgB2Ms6WDYIX4Kz7dwTahAh5ZYCOByPEztstw1vY+SR6HlPSTKGuxYEHrnUgbwAyqFFFoJgYgL1lwIx6lw2tNhWUebR6Kzp/uhv9cNm/1DGO5v1FsNvGWX0z53c6rHXeRtVsoUobeuCIqgFLTTZ2N4VR2WRFg6dQDNYozsykBWBtCHUiLPsMW3okquub2UB90l96Wvk3OzA5ro+uf7EHAPSp2EqwdBRfWYgVsXjbRLWDY9Z9ivRRihAFj89ETROi2FURo8ZX84E3ptDzSPemECV2owC1TsUCQpRmmwEoF7dia9XoWnRob63fWmBRnnlisIWDrFIn9rspA+rcNcZSER1f6/B09ajDMWp0i+NuSJEZXq+K7vGq1r1dNZWermpuSQxm9g5x58jO1AqQfltl8M9ALbh/qpWnDnRiIQANKfEakCz5+YK1xvvfP3ooVtbIeu9fRfexipKJ31TQFOz5Ag6dFHVB0AfbiboHTRVTgeqMiXvbCRr/g50rHlRh8lDylC9VXII9dxSAc/fd1lYx3QZIPMcTseCLPd+LeR23q8TDbRjamalmsheIVWlGqWfHBc1k9pNjIj64tZ19A3wA5Vu+ULg3zjF7Zg9jjO0mKCC7aYWwGis7B8tsf79WrAlm8QChh+pjPAsNPRqEN+nGHsd6gDjgp+W38edgnoWenfFiVXx8Jw0aq+9h+u28+LAmmUKA+QwjzhQGTgd7lQuFf/wWvr7qynG7iEk+AgzdOvWT0qj10Q5+Jro7MfjjFn7pv+1tXbW6w9hT5Y98094vJpwCkL4GEwAgIDC07TGz4QQVUQKV+Z80CFay6YzdhWDNhQVsNoJ1HSKxZQAuK4I13FxbiAAACAfgRIsDjZjr0NpfcwPUd9QAEADkBuQV+zEOVNZgprfKyAy6VBUn119S0G1WmhAc2CrYyV4CFByVHbAnBSPwrq0C4/IQbi1ylXO7sZCrbTaWDB9Z3TRABABZgqkzfdtx1F5uejx3u2A0A4mrnAqZTpoJAQAugFm0cVMEGMrM7MZ9VdoYPHuvGG1mxSAOB2bgETuY8Tir6m6oh8Oa90SG+uvW3AYanf52EeoG0Cyj6XB01V1rb9JvyWTSD1ZzVtTNq/92UesGUFevXq9x3W0JN/J+OeFrlb9feT29+m97LhlV10BQ7J7Nw+oNYMK8AdRqMAEA1AuYZXt4YrhqESVAFf+DwAibdmWMqctnZdRIGiCojUhSoWTWVt3C7bC2VE9YFLfDLELHawZRi+EAke/vAQQAOkBr+QNB4axZocZdJFYSy+5Qlyz1QihWkOge5ih69s+qtXFOiSHrM9p9M0mun67N41m+9Ndl+IrsBhdHkEECiIx4JY+H5WRXAxzoIT8EoWI5BlUczr/kIPCN/Rc67JkCOHtnSAKssAIaAHtcOWNAdsMHAOASVQi11WChpyCR+pkZE4Bu2OCOP2g02RVYnMmylpPEGwHpTlk3LDZn00JQcylOopGJ4LqwwOttkuNMOWY8h1XMeeIq3RDbAhxx3KgTuejAsFAHNtwCherYPTr3QYken/a1/Ik6hcm3lqGHfzt2zXnCvdnxhX+nPRwvvnOkiXbNybRz289OHgS7O569JWvlBJ3eVEdZuIveP67vq3Wr+ypAsY7a22LC3gApNpgAAKkBpoenjwdQlwUot75LsAPvGVEC9jADAgB7WRIhImqVKACggigMI6KpBEXl4yjZxWKZYvMn/riB4mqrNgCAcvsWxnSWWpigQb2EXm4hp2xEFzUbbWbLhppaR9y60bvSMZo+BVLtGrSXXJigPWld0YOMG1ijcqaJr6sTpdHAs8tWvkvTF941dARqpUHJcQ3D/A0XvKArxPEeOjCI0RWXjx2AvLK2PwQAB5XoOmn5jkPk9ehXj32+nWjXZ61cpTEBxzPblH9vCz2pbeldtMK1b5s5ki1sP4/ZMkGyhTuVOLZdSrYIK+zBEyXb7FM8Yh7o4K08pS8hXDTlbq8UOSFfhmZX98a4X08+ffjhPL/mcOn/o1eFarW+60dBwRkz4dkC5qbBBADYauC6LfXz1nUEKfG/KAjS8Z9RpYixDQQirpUkElmrRAEAH8SgGREHcb01fw6f7JQvMbrGcfU92xAPAEw3KKzl4izO52mFrjjN6EALhjib/pwoaNOWmoob+WMQzpRxvbb2ll7hrI3/0YBbt4Vbw7suBrftI7whGI7hXWyHRngRH7sl/UsaIAKAW4M34/rulv7Neu7uDjpNcZXLpkWsNFvl4ZtFPiddft9hQAO3E1vyFdTYyAykoI5W9kgKuo9BzBTopkdsEsbkm64p29cYPDLJRcfZ4a81Q6f/Y7HcBtCGoSn5fse8lD4Yj95McnP0l9agIlv9vty6+G4DqNhW8/dwEqbw99rSY5LkabkM6Eptx+v4rNf33rjVvRcsW0ftKTFhjwEfGkwAAF+AqfD0UQDe2X9SADw8km15z9gHsMMMiAbYw5IIEpGrRAEAHkR1GBGN6O2aoEi/XyJKkpX5+xyu2gMAXKm5YSEpBGi5MHFu8dTuVxFXm02JmGOMV0Ra3qYLcVy5dqi00Kx4q/Jn9LPQ5SKs/6Cwv0zxrX1FkZnfpiGfta/6M3UU/p5cT1L2U4SIJF1AJhkIKbtBWZomXH81jiQWuic34LlndXzwJaUnqFEwkbV2xDGYFwVBFek0q+AGTUsEEJQ/500oXQW83vrTAYGcw0YvCKESztCxGN7HAB7hNiXLcMdiNDN60+mPgRb1qQ9MEORwVfgqESSRvLJshygAWmt+1WIwnlpxsKXSGtnh1rJtj5VW4XbxP/eefk0FduiduW5gV6zgWMBVO/LTIaZ4Wz4AgKldhGKEKxqBt2ZVdvx7+mlm+Mgnkb/R82sWG1kAgMX+Su1ioNTphdojl9m5shMzqU6XK66e7ZHHJ6uDtxvWl3Sn3lYF2zVYr1apF1eldFnVOzuZHvgpGDBOGn+VP7jmR7rR/OjlyqjmWhQmxwKBTBhIrhIBsFmY/byvvxI/l3z2dX1gXKSW09OWSLBrwj+2DsE9bzrj8RC8WlfJy4GXzp85h70IC2mhUO2wCLV2LPaLEAAASQsyIh0ryugEva33SUQfGMGX7DWa9gCAvq0gTopICVPgPljVFQLHwGzpMnHwGNiOjhiXtZvmGFiMXAo36pdYknllL7q4WiWWzxYg1lFc2qyDrl0R2hw3D+66x4hFwjL5XJc1vSQsy8/zWcOGe8QVZwabZsygzJafX7iyy64F5uWS9CWa+h+FZXdPdhde6+qU9PPcULbnLwPdGz6Oc2JtNC7NRcCFLNsIEV3pUqeSWdphjLO48HBk46aMYV2ZiC+AvM8YeRzpqtdHygMcwJlV9VnsrvGj075I8gCEOOEdLbgK77wcFUDnrvFU3vEt6P7rlJa/OHPh+/MlILYalycZUfVvmIqYhJRRjgqn6eIr5Estncih49A29XjhHwHGf45p4gcTaYHmhosPt9Lsvglcf66+JmkFRQAABZqm63vK1kzWxEhm4d7bHcI/ptd4rYMnO8XMdQB9YQTI0lbB3IrW2XLzv6O54PbqzXBjYafL/aT+k92+iDkKFkA+l1U0i/eEsp3g6hYq/jYM2FXZuDd9oNYQH0KOhA1BC6jfr4E00gHM8V3nDP/XjmlySqgUdLTTgk/wtg5kA3qU0D16kpGTIhE2aTl5wI6U+NgWlizE8p5RhhZnFgD2OEPUoAk2dP4YTdJM9f/DAgiBOyID47tb0tsioogZBwng0GboVWQIQyJblgMKa53DA9sLJYmRoF9nRAfnn/Bf2ofOAaQ8X0YktzbLdEWc3QHgCO4Ekziv0+wGzqRuEyARTe0R0gud47XNmPaTVOa1lxESop3mKPHA36asngmg3fta9ir2mpg4TDX8N/VeX4N8+TZ9ZCvXs4B5G3UIkfN4S3/UNpF+mfYm9by/rw5PaM2F6XDwRYzBuX/O2QdPDXJ2ugq1HFkctolKfJP+x7hFgsuVgtBiZYcbXWrhTKAStMY9Ls5Xa7P5HA+n7GquFjnrcwp+6pZnHr/OpflGj9vAgsud2aVu+MA9addyq5HbpuVoWeg7zze6uagc54q0xEw1aYqZStEWM40xjTFToXFQze8rkIOhe12yo1z3RLct2B25EQaAAx5CTx2drk7VzFSaupmpkrt8pprUzrgIyE/9zNQkKuglP+SD23y6aKbG0EczVaGTZippjYw33TTT+NNPM00QOmqmavTUTA2jq0qNwVgLtems8qOEQm2OP93VTBNesKDxETy7uetRdwkEy62oQ2o7GszqjcXe2omjjKRxhVrYw3CqJhiURHSByt3rRVo3Ra8ntrtzpS6CJ++6f5TEveM2LQVhw6fLu9DvoTajsl8RkwPdU2hGEzyHwAPSPLrGRKoqFywDZ4uka96q9QNrto/VURZck9OcohBf+i877nU5whU3bvP0rv8jMY1/5p94eOJGxBrc8z3WGSSs4eQDtdYubTJ1QrAy3bOMFos71VZCAGCrZ5p4S7bsqGbgFiYLdT+XWWR2nBojhCAbuYCQwwcMAFJ6k8sTx1ZaFUO4zRHahCHfnpd0Dkoe6pu09zTTZ5aGITzWW69XZrU3eeoJcgJhKB2UMGi2GQUA0AJIyTBEL9N4KUhgtf1HZZhpfhkrd654tFR+F+pCSKC2yDnsRdhIEwHbVgTZKbpbhAAASK4em8idR/UJULXvkwh0jxKlNO0BAOhZM6YKSWEv9g9rVTeIcWaTTcwyxmxiljXFZgwiuNUrO6g9ekWYFYqaoj2zi3S4WF6nbO6Kj3WEJ47ZLel2m6gqXI7Z7ej0m3KWkboHAU/TC3Wvtp4EAM0pZKOw1W4AaEFQU+X42kmcu4RNbT5Qn2w3JtM2VbVVZk22mlKaCQEAJsC4KrkuFL4VTNnM7NwJAXk29iBExyBwDTGiT4zXjKl5k5NKjA/qc38f7Z/jNXy6hvSNEPBF0CFA7KhT0mAUTvkX/F5hk879HqdTAgjSPzLzF1WHAAEF6c2HiV2T8t5sOTuUh1jvqmCC9D96mTOqme2x/V0BtzlVEp6MKAGYLFyOAgDM2awE3tkeYrmuV0QJdeF/zWXEXQ2vvdozLLg3toGOsaqHI828RGmpyZQoAEAtajCiXuxAHSouJjYo1VN7AMBUXnte0jrX3Ic1DIdDuZjZOlT2xH2ToQaoI9siiIyuu39calnSRv/aEi55Bm21b3FqR+KBfofzfr45t+Hz7liHt3KATEuGTPTsciJ2gZflZDcN3E5zCQBwVwh3wzS4E1Ss5CBMw/4bHSHvLmOP5nGcOmKlPsU46yonPTYyzps5f0UrU04Io131AQDM1U0cYhoJWQYdCbQ31UAKErzeygIAwAWIKDEXstft4fFIxMRlkjdl34oiS3HEFNv2Fp8ost9usC8JN6JrXDfDY+C8VTTwlqY6sbPTfTdn2YS/8wx8dKrs6XA3+qoSjl5rq9XuG34ci+UaCGPFWL5gU80oAMBG7JytziIaWIATQBnvmaYBZZmBhoCmWJImwJ6W266qXZ+nLYUeThRlVIoRrdQmMvMLuKTX2+EBAE4vKIX9KAXJotNUdoFeIXnsijW4o7ysTUNIc+NcdSq/YLRK2oY70aWmgplZRqVYwhrcV3OxdocBazhZ8ijt2QeHdbP26RtCy/ExD0aKxt/lR+whHcxyJXc+WCAENrzYlvNDQoTj9olllhlEYoSYIQaWx9sACIm3ngQAWDcSWW61GwBwZQiLOD6W+gwT94il9Nux7PGQuzIUBqv33IEEM42EAAAmRY7I8bItHRyFzW5Usq5uR7NGVkvELkvbIHbZECaUvto0FvlIDsd8FdwRCJ849r3D4Xy6Nq2VyE/0nrXaaB+Hl4YOrD+1JXoUzCq16bg7YhEyYRZzbRhYzsJiFABAwT6G6QQJHMoCvCxSOEKb3XSmayC022GBjkToqjmSznMxu3Dt2hHuvv/nIgQAQIzNiRITc2oTuUjOXKM2AMDrFYJwSkXF7EdzkIbTZmq3IE3OFet6lR9EzXIpHdAv6a7Nq7uzwqZVclUMirtdwjazmLAp8C62F7pfZNOrxDYXUSDBRHDbXQqECFfARjEQkQQ8lAERs1tPAgAqQhKXrXYDAN2LpHimL0mN4T4lzx0zkKo6WBFIcVirCQGAiyNSq4tLC0S5olEmSsSGpW0RGzaEzShc6YOLaZp9+zkY+AaSN0jpjvxUfzpK9EgaVbK9aHJXFmhOlYTLWDlgKQuXogAAdwf2Wh9ErYRZRBldLwNeRSv3R1pbf3ZFtGMbHIj2bKQTwjXH2tzcoIjO05ZigRMlOvnjzLrlsOM9XU5UgTWuDQAUtXJHK+mYy04LX3tLWJ+5h92+L5QnfjRA06yt05jXKhfedYck1Ko73c180u7yo54yKnLlpWuU+hKc7iBc3O3yjckhddSHp43kET0ilMugBAA25U7ubgCoAyr2OXskrJKbuIu3vIMMBdOgzXHczHDJ497vw3lvhXf2uKB/2k8hiZHgECAIoHYzPsJMr7cUPz5E78njoxwAUPuVH822sfNqo/50uML2roaxGC56oKkUAEDAcPWmqBBwYAs7hRfQckC4QUPZIKkUdbBgwrYNVdmwtkheJBDpRILJxgMAOUACyAsicgZ0PC4wzK3Bid+gnIv+oq20jzBjMYPUuLnqHCv69uZEDl/77U3RT8XEkcGJ5LoJyNxVCHcnC5eYAAAnQF01oLxELTkIy2OAOwYy552ZHiBXpnK4sOacQ2EqrnwsYKf+j3d9fyo0fyMx3QfoKsyPFXbwO81LyysJMMRa0gNelbfmTuAx21kAAJYLnIHlspdbWWMSV2MyL6tdvQI754hVVQaCUHH3P1SpOhaIDWT1i3Suj0xKNW5dS6jdXpRGc6aJr6oTTD7qF/Iz4aw/QyTShK/OLaFJw5/gJ+T1joyju/8J13VXqu5Z44/Ezbl+Y8K4AXCXhUUpAIA7tNR7wPUtAdbq56V0S/Vnq4i/om3bYEO0tJH2ABdecY31sE1J5nhh8+7qY3DKnG2iXD+9K4F67n0SIVzHFSaF3oZ4AEB0KqmSG2E/Rs4oHBrlNE2vsV5kqByxeU0I8BEM3xy9VV6khz1MYPlabzh9buCkNbIFQlDVvMsBqLpXPPVeYig2/hfmZcje9sGMMdrEYvZa5Tq6MfxvPqzDbzJEiaFMLD6dNZN1AIocu1HTzRF+k74Vfz67Nor3t5r1pCipvSjrZSiM9afu/mbB1QMlp15TirgJEWSqXl9ieRLQ3hu4IMWht9Af47L6pJvkajh36IAGtg6XJ+h1csuGJlFCBlgqsiLkMfoogDaq8BJtxulJn7Lif8LkQbAiAzFGRT1kn6DP0ifzYtlApouZl6YwblT7/HeoyQOKmwkpy5KSQAE0Ea9ovJgeBCpAMlVYZLNddNyOY09eXcPK9xDKujHmPTzzP1Fk9X7qOaomeNx3ku+mYvrsxJWTI2IYc+mWmhWOdvPIjYHCpGhejTnyJNj5cC/25FHYgQVZbrmzK66AJeMQ2PAgrmhzfj5KiRJIBhshkUIFfuzp1otzkeAoNQrmSgRReQdB4Qr6whPihUnrgYdTwelcU75c1pMG6ZPO7mpIk4ooBxW6ENtEyJ8/mSF//qghf2Z1c+rnJzPkzzrnL0EKsh6f35IFSAFREB0HvezjM33Rrpcb0KMS1sWfghoEClSEEGeWOBAWl5McCp+EkD9nlhbDSHsfmxRP0VMYOdiKT5tkbpCBD9fhl3Qkk7M+pbKQ9k+psIqAws1BKrXF0ufFoQ5tkgLRwEkXdljxOjFVJEXTNLCNc0o9B4m4or2NwsRbLoGn6IymGUnjbnpRL7qElbZYJyBngXSw9VTHwyw8FcuoaHny++4Ih16qn5itWCgJWtZuCQGAXHEz0V3VoFcrOMpSH87LBEWoT9PIDtBQ37D5EGig07WHD1eb6+H9+/jiTEjyKkDv/53A/mQONrVU+d9p6brWJg+Pqznm1MrmIsB/39zo71f6nrvdffwj/7tzpZImZ/+Z82qxTX7bqetdTluNTBf/Lbr9t+AiJxPcfcs9TOH2vpxhEipM92fVWs8fmq/yZXpRdKLI7U65RWZOsbqtViB2hgmzp14UBfZuRwEA2MdYRYFYls4sQmXyP9W9AMZK7269Zy7lnwK4mhm4ArjIklxLhG7eBQAwFG6PE03dyAcbiUPrErXPf+AnpIYr4gEASzJR9o+1FsyOrMLNaVoLiqqMLVlybJeexJjGe6ug9ho5We2AhcdEtWRd6Kkbco6JAtyYiF4Cxw4I1ABwohlWFyY5s6i/c37nYjHKwuU2bavT4O1uJxMA1GdITbenYoxUi4xAnF33fglcuLK14t48USoYbf3eruV3EYmJM6uTsVEa1MnwBplWs2y1kekMg5AaZEF5Mtk6pkbcb0qnIbY5ebXk3ftoQkzUn+gCPTFuVQzYXqUkfLqLgb3ZWIwCAIhk2+k0QiUpJcAVjluV3u3Vn7nW6q/IZRu4iFxWkgth1G3jBQCMKLDEbYcVEi1RuBZFi4kTyuLoHgCwg8zyk1I3+/FJNdbmWTGTJ/bGITgSjw4xUmoHJc3ec6fH2CJf9G8fSmXWlQ0brkPN5cQRBEiCJkRFYaRt60kqSaKRAWpx26Ccy5UJABsImVMdSooRZAMZEYBb74UzcRU2MGv8sMuo7zofo5UnpJD2Hc/+AEIMaXekzn+qez8V2jdNbhqj8EI6707iFe1bh+0Wmg0bmKkUAGCA5uqmoATchWaHz9ZlAaWxQgMt6CBJC2qKFwAwMLJoF3QycXhV3+geANApS/WTYvEfUfZGToLwxdcNVxxgrKd/YgXO4D7Q0b9pa1DP/0Ez/ng+I/9ftpOf6Bd4quD/qvLqP1NH8Xi+q1mZUKisCQAAUiQybI1CEzqoJAm4hVpHRzwJwKGfRSKtSsH4h5Xz3HGO73nVmElTPHqb9bt9rYE+XySTAwDAKF3YUloZXeHg/13D6rNMZ1oAgDHqRrhclwIGXUmDmHlH17HqK0ViatXXkkRq6q6K3igo42/VbZmCNPm94Chqn+T6e5xD8Dtajlcf6vMwTHiH0JLzwEwKAFBF1arY0IchCoNuFAeAm9Y7SzWSZ64v4y0FM4PRIpn3HL/WwageBhCmiPwuALCDXpwoOo6lJUIvJhKUcC4eAOBCHe7CfYPsvhI0b3IhzGwsQFgpJUK6+TuCXEIgQY5aPayrPXvAzmO2YDcmtjcAqYCAhgEqARvN5Xfody4Wo1bgYNM2HYG83k4mANC3EM1tTzlZJK0wAs60sUxK4AJruYqsxlS0gppaSQgATFX59QrWroNjGumTycQZNIN8f7y+UJ4Nf7y+PR9DAKFu6DKZqng45ucpFHIBBIo8LNfWEOKh6CXVWxXjQEX9/aOcDoSXn1GLjuMoAICWogL17ORUKgmo5ruuiskzV/71TnHMYHSKE03HsEUrIH93FwDANldT4JpommWg5XelGpcS3RPc/62kmIkHALyaIdOyXaxOHuZpbyjGaHpXu1Gyso7Y6WbykiqoOSYVFpid6nW7CqF6xSlU/9soCD2QUCzLCz19qRKK+xJ6bqJwmje1LRGscD4nrHbNCTeLmj8m4V9MiVG49YZt9QxSVdpOJgAI3ZDa3Z6K20i1b9OgeAUcmq24s0ROERM1FAIAvEpTTpYh7BxnU6c5z6ip05bZInV6JYQMsRfKfHQz/OfNhNN7KdbHhubqtWe0ib79QUEoXDlkOoVGUgAArQ0cfrSRH72UysUBb0WD+urdGB1V3qwG5qquWJnzmfLHqWLJplWMiaonwwsADFCtsKguaNPiOUOJk+q+VXIm4gGA0SKZ/ewCCmURJmpOoZJpkS8W10bWw4GSUmhoNrpiDwXfrs/nGAZsi+AdQvOunQY/rBI3nKg6WpwAWlB+uIRoO02F4oy+qxsruR3pzpooEwBKi4SIOjpYycFVXVsMxR7J1dhhQ/wFiLePBRK8KT26EN8/FuhHtT6AaENanrrnDUtSP9p9TLmESn2Rhnj9YUEPw4YzxLfeMdZUCgCwFgg/Gu+BXspCEnAXmkugESh2YADMaYCe4gUAAlRYVBn6fF19phOLezgZDwAEkADCgoicAR2PCwybanD8974T8evW6v9trcbzMdTf5IhuprbBB+rd83n1pysvPDfLBvchXtnVssweIvTgSRMAwEDYbVADCTigY87el7Kn5/Bt4JSHE5vMDOWyt4QqnoayZVLMrEVScbPAgGgtD3eXX9NGfVFE/uLsobOWM9ScBrPIHJw7LMcyixvewWxzQsOXHxNMSjBFDMi2c85yUb0qe3FzlZeMmHhrErOjfZBS/1qhgvmqsdPCUvH1ywmc907sG7M5nSaz2Cze+8aakWsAuzzprIUc9/QtJovd5AAAS8i6UGNZX5OxZUaHu9hlzU3B7NPh9T49CwCgIlTjmu+ine2XcaRabJWp8/LRH5Y2dUANiRda2jmgdgQ3fmBJUzfcL0mUCBMkKRsZ0DpsLBOsSCv11Se7OcA0aMhNq7BXXUELOJZ693dbup98Pf/tiWdUjJVGGGhAviTP+mI7O+fMYXEeNbFJRjbzQzj8kptlX2QoobZEBMQ2I4wWIkIXlUCWh/T+IkpPUKOxQu5IPoPPoWkKBiyfWE/OiMMlljbKxEkCsgkPM5KfQK4VmO5er6NNyjWjKHOCzmenHUZ9WgdHxMTkdobl+QpkJd3ByX7nqtXLiOp7k/5ysHKi1M0oAIDkDLwwDMFhXJsyUC7EGhtQjHEPfCPD/EubatwAxio7+XbRQ2oW2qy+V7TVJdiFiRyjSY40HKCvywwR00ebzG0Gog//pGSuJ+ph9hyX7ISEJw0tmZE621rrdy9H5E+Xz8oDM4U1huYqOObXhiINXUnsRjiGZo5Od8KVMwCfDdyhtEbbdwEAbfjQXH7E2bOKtqbfejIWvkTztjcq0kQ3xAMAlneWrxTA9k+4gU6ksPvNKDQ7zC0Uim9GUbxBIqDQfDOW23X0zQRxxn0js4dQpHhhCWRICKsCL2JqUEDFVm3iFFLy8YG4kNK0EU5K9p8ZVClt88UMkdKNbzt79N1pKBMABgQTOtQ90s+0RXC1oBmWv5WO1lrZHcf4pG02EwIALpe7EWSxXZynoMGumxkHGlZ49nihIcEgJgWtMpvMdkTJKAdxdgmy3EGexyEN0OLXcs9Wh8qHXxIkq/434uCqYsUG1YWoXluYWlItI2pFCgBAQfS2nR7sleQmfFZUAorcGkbIrKm5gJUYBMApXgBgQYVEJ9DTwR5K3E+8OFijewBAk77dU4oKfoaCvoPlNVfAS6eAN94jujeA4O8E47uTnr4BbH+i6AwjnDfsYvcBl2xMZGOAnWEEroyhfdQuY3MtqD3G6DpQ195tdxEfG8oEALdA1zpUs+m71jdoAkolDCWsmc70zo11EFOFAECD5eP2L7kOjpfpoRU1AGbZYwPY4YMNYNJkoKOLq/AGj3CvF/0uiF96zDvSyfavZ/VttmPrPh2gWGy4AU6lAAAExjd0dMGCIAnHAgkoNbfgJAYBZIoXAGiKXRfNHTjpxOWenowHAAQ2AzJYkVMg4/ECku860BG8wOECoDrduovdZezZFc5j+3Jib3yTlGUEHlV1DhRjGx0oxrhaqrK0XadVwhNlAgC1aBBRSwcrNdhayiNQcHsz8SPZ2/heK3X1Q35AYF/W51lkK60P4f4xPRAg0pV2cwfAJNcLNG86TNtfQD3MUa60/6aYyDrP40rJY8MFYCoFAAAQrl7AskAATM0NmMRgA57iBQAKnKBoata3MOnEASsbDwCIYPEfUeK8ZkOj10H4Yh0kf19A8TVt/eeWxfj/Tv1za/28G4NaGt7v3czzY4DN6rzwpuV68E3RXuSViQZubSdlBUSZDzXOmAAAs1RTHRumaZwdOFixwAC5YZewdLsXfvZQo4s+QFHRiPuOqpofhj+8rttXPNDAbp/P6AGJf6n4cqgu2Z+6P1/Ns8vO7M3MXlBp8ErbVGgMV4S5akW4jthpspbdKuz+SV3cVKO+Qap5TRYAgOCeeOOUSrppruRayKUzmu7Sl/K4XNuaYkMq1311exm9h1hKylg677KqfJOkjFuHUhYX8hgf0J+rAulO8Z5+6RmYaXzMfDQlTZemcLrFirUKmFTUiAlrDtClGQUAcBUQjp2e6abfCDG2AaUZj//IRMU155djBFLrFVQVYBekfF4OdrawEwAIaI62uZxooaKCmmy1N9HxgLuaVHpz8QDANKQNf677LFnkmTenoVQ0nh2GydeSVrxPoMX8fQOtpMAdanvlhRvU4nIiblHDNYEOqNGaTSfUeM2oM2rm4rYulHOZMgGgilqnGbWH53VaHOyl7h6G4pNSJn+gNMvNhACAJeBgB5e+hhWkArNyM1veoQzTbIFnbw00i2UQ2wXthZvJDjxvj7R/mEoYlyrnpwCcEeQFHtLVSv2N7jNTIo0vVmCs+us5/50qWJtpOkQNbWGq9i+LqFUpAAAFhLHTM11PBSFGDFCq9Ukc+tbsC5M1NUeKuSzIO0g3qQsACJyA6ILUTgNYQ4mbcCjrVXMj8QDA/vbdQQYu68je3pY5n7nT+GkA2hs3DSEdbP4O0N71egpW22L5k4skWEKzi0QwvIu8/csKEdKmRKosue1wwFQgd8YJm75wtDNzmo8u18ZezEnu44Ztc81HjEYzmQCgPqTpc6feg+e+z8wIAt8OJiUAV5tmK7OJb28ANU4IAMzp/g7KwzXN0BtA+plyjsfBDrN1cAIIHcTQnNf01dstewiKF5VeQnSTrbnFcW7FPe2fGDYcis2lAAA6AFw9FBaBPKBTcwa4MMijUFYXAPCB4EUEmU4UOFPxAMB02z4sHAbUYPxmp6Du6/EZjwUWfzfYETwgmcByRWDWXeQuq6Wa4MVE8rhyK/9NYHJimiy9XvgqtNhJapnljAWtFrcnvKo4WSYAFFgxtSi9jGDb9PwhuIQwlOTY6bFcpvv5xK9hXlaHsDO5coNFs9J2CgqM4oEA0a20m3sCZs3Ut4DrkDKIdroS2Ur7aSewWcbWfb5W0GzYwEylAAALdKDe7CS0QCHgihVgQaXmBCIxuAAndQGABTso6r3HWYh0IsFk4wGAHBgGVIBnzhy40ZiUPv4usCK4QUT/oa18E7jm8Lqo0Jujwntk2x6LUvBVvyoS+DBmJABscQJf9WBiJRVD58BOiWkbQmAwcdZ+YCFRXuvn0oF+IdMhTncd77s4mqTETYBDvyS3+7nOAWGqEdtDwFSx+ZArIQs/7oPVB3HSNCxv4ggtIyIhLo9XYHbxzfbxIxXjFSxKnRiMlbWEL33YQ0J/ZJjFE7StWGuabfjnLLCv83SJuH1Zozp350djXMSWdHAtVt+LylseHDn2LqPQ6E7pziOnqhsdgpGxXezCQAfLUgOIEHD++P55LwahioUgNtkbAKBBocjcr1Zk8afFQos1qAry53W1ymkWACA6hXhJb9tZH/zhneanARkxc4cDQgOgSAyfFBD3ofUvuwSd4q8INDVgxZ6TljZyN+AgKGKyaVzLLsdTLCKjYjhcATHPdnKJukwTaFxHb625bZZmJaLI00kzKFLfOO2jHmdfhXtwtxFbASABDt7FvHXfyfmVx+ZbhUAyfvw1Xjm1yxMdtO8XsmmB/3VaWf2Ci3VjFgq7yekCAB1IzYhydeyqAVAqMV3nFgc5tQcA8KI8kacUjpVoVaZqN48WCvvNi2BXDRTjjW0AZtFh7sjAzV0wBxO7zw8ja/znBFPgdBmDYDssjnvVEnLw1eWYUCz1aFnBoSfF2g49U6zx0LNJbx96y9kyAcDFV88wqrb6UouDBjqNtUo4PeV4V6gzUggA9OxZLMVEOWy5gi06R5m9aEfjUJNlnw7xJAQEjZbJ0jxM0wXqEXIYKBR5c5hYjJ94mj5u7pmInQB+R3MFgMc7mYfh/HL/AAoCn3nVz/U5NOfnNQ4M+jmdo7oAgKRiRHmliYHGQg4llozXDmJ0DwC4jCrsKYUNSzraWe2K8poNQnkH44cvrT7cFxP6TEAHnk+IB58+WCxo/+9r7ggN89LylrAj7HSi2LkTTkB27lnORnbuXc5IdkYpuS3eZ4CTZQKA0JyKqqHmbHowkMVRZgq4fXRDD+9ddpMN4QXHuN4ZAjigKDOXNuobQATZPlm4AURF2+YgB8rsqDwc+mTS3Wfoe6AT22/RXxSmI7cCQEJBvIt56679mXsaZcEssIBOzQVkYrAATeoCAAWSFxlkOtHcM5PxAADAYT0EEzdB6YvHBiv5EBDee/3rdlAexdPFHcFlXlp6F3aEkk4UO7eHE5CdO8fZyM49xxnJzn1ObpP3Ga3JMgFAaKajaqiZSw8GMjnKrMKzx6E5vTaP0auParrm4x11z8iuAJD4FOPkHEAUPi1fI4QyOLX1tfoI7g+PHEXgM6IrACRoxjuZB89/D/dfColAHlCpOQNYGORRMKsLAPhA8CKBSCeKezIZDwA0GNYD0H6zyTdk4UZjUfqSDwbbv15y9WlZpP+/iurTVhp5XCMezuGVH/SjH326m2Lmbw03OMAQLnYYdehRq7Xh35T/Sm2j3wmKlDHUwTj5MSd+tkdNBgjvvL6uF2aOuMe3YtNb1/xO1KRktD43AfTwSKP3fZyVhTXsXvDAbLPUaltFxZMYUhFvTtP25rHER1pHL8q+5H6zKmS2cNYga/UEhzCgAWHoUGBoK/y0E4jQz06ujfiWzuN4VKvM9nla40dUDMEnNPaBU2O5Z40R5jIaygVUJVlA4PQKlgjWm8uxfZ/5nTdx54ZyX+ESL7DPklXdtnfzp0dCt+uPKY5YZSxMgi87YlfyESLEyEiKFiGGWnmUTTF+pC21Htq35ZVE8BG5Mc624kTuUQu/LxxWJgqOCv/TdzosCpmj7g0oL9/DwBJpQ4FzoNeoMRplk45OY4eLq8KzHlKCDEdc3EskMXi1Vdt/Hp3jGIB4xp6yAMvsNsE9Y4ufm+Q9stgUHjeuCi/yJP2I0MmLctch16Fflim7LL76trDRktt1MvUrsxqBCZ5n2zo5m10GVgcVwgD2OTaJvRNT225IVvwoWSvsEm/tD69ZPtit5wJnE8PXBBNIMpcDprnkFPAbpeBTUm3jH/ECMKchtMpTLEAc0e3fuv6gtzmvlTY//wDQWdgG/YnBJKcnE46pyFtNOTmTBMxxtUA+q4caJdJTGC3KHCFKdQwrQGyVxwZH5gUk9URBJxbgSCJDaQEbmuhKRDKtw8T5JQFxVrm1dqC8K/57AWK/j/VZ+QKFxgltSz2zhabYB2QqIwaVjyXayOAy/ClJeadpGGojo3xp1DUFSKdtSQsCoEKO6/gw2eQucDpuDfBo1KneWSi04ehacGJWbJk+idJMPkMvTQakYTGtu0u17yGO83mAStx8NRi/ouccITsNgxHhiZVP6mnMUCfpFKJsCm+K0ZKVIG8oEYKsWtymHHeiyy/Ud2htNGgHQwIB2YhehhE+EdNDueUKdswmLdgEbbXtL6PJskFmjkdiTM1XoCrxnNXrdj/oFPSmfELuBcl3OzZ6KQTMrn27CJBHqD6C234+2l7SvTUJ089hqxZWLIKiuJQwgPhE1ZENHW1QJnQY55rVWXUGEOFGalDxah/GksocanyFDiFlqSDr1AjSugbWNsisApxM6i9nQK6o4YMTEaewRPvGp7sGiSXplXx9qMvNNFF7c/8eZenN+t3iH9LDTTwYkWj8BOcd2yr3tRobDn9YQlq8KHBIPpEvwgnYAgcVYkaF5kKX0s9aj2qDqGw2Cn1oLDdGKB16Rd8LTrIaP8fhPb+g6aUdKmQgF0zDL3LQxfh/7O2Qq/1OJLGvifQq6v+KfaqYmk4u2YSCqw7qX9nOho7eZI2aNQtnQnf4HNZ/VUK0H6fqCD8sjBRCYlu8Y0I68GFyRscJf0z1U9PA19mM381Pm5AWqpuNnq7NUUUZMkKie9+uSCegu8as73tAwPY6b4yY15FMEo+dh0lLlCEZlm3BEIKlA/FAs0dlF33O29A0TZVBHCFwI033XR+sEejhU9us8gMzwqo4RP0eg7NHVZP/mGcMIfdUHL/OaBhYHuRrhfYxQHTrFCouFoGtjpc5MKEMi6b1rIpMSynvZWMIW4FJRNelN53NTijBHrTm+Y1FenCJNIJoKyNAGcvt0LaZfRU7jNu7kuYgD7meOABh6JNQlzhl1Xtz7tyCaD9DQAdmivXHhkQbEZTBMeCtbOT9xg0vAakVDY/8Jy4l6IeKsQXxvRSYAU0AyfyHs63ORtLghBUgQgfwQQNA1k4/l9V/TrzR9vyr2usvYY//mQ028W0AT+Zu2nBgH0JRRenkE+5UFNQj7evzdj98lvf9n2MSHhCwq+OGSg5aY29k2dxSEcRK89GMl7hPGctiysQupqnF7QHwUNzcZ6l5XHOJNNdN71SGfVYmEAy083VIjIMKtKBghRyoXemrkjXnyvjE1D4ixYt9Y7G8XLG88YmYxrrCIidYwq1n9ZYbqAQaiR9r2bI91BH0pjo7ed3EVvQ7v2DHDWfcZbMUmezeuuzcbou/rxdfPHDgs1ne7UIy3ox5lycQNMu1fIIgl3JUT4pTSsY+zVpBxc5svbbfX9Q923e9PpyWGZgLSKsUKeNczJJVGgd+KkUD5ACysuxGuIAS8zWzJ9yTu/MSuKvocpRpOMEf2aY97kJKRZUl2mhRxwFFne50IpWiU0adLX6iHeuh2/kysepZHJx4pdTfFsdRV+Hd/sYdxJxPTPKI2YThw/AmtTrCTMPnWZKGNJ0cCyKvkCRBuIT1NrYogboJLYphqRHKuG3e4tTxcbAiWrpEZhL3ypY5hYbc7mYS0LSK/w90bv0fGhoY7WLWASeqG+aCdOB3gcpZschyjReRDbsMG4LV0yUTV2j5KwxHdkWR0dCtwjG1sLz9NxTFS9T7ctvLYbKaZTizBTjB0htZddM4fqpQGFTfDpuqvCKBUDiujDT096wedob1p837Vqv412rznr4QzeMXRc6/v/1lJ78stmys+fNHXZsFfI/H7tpBi26I//yVeXJeLjKvuqmcv8D3jUTLxzRssP1isQybxfLuweeDjxQkuV8l1q2KVFTG3KMYzh7jbfPwoKXV30JY25cdtJT5+wisZbLrLN8qNF/F6B56WihLKWlMdJxy2FsDfcnnPIcG+7Kux9DgrWLol0IGldq8pDSHNfO5YvUittLs+V/1+fzLL8rT7KAU/FDmrofQsokKEJnAbNaOLhXSOzJJmTs3Y6WgR55dMQ+ccdhVrP7Ah751SJUvLeoKzf3DuVjYnnEolPnXZwCAWFfWFdH8o6S4vQyOOaCyX3wxKbcOXFTBQOTvsqrPBinJnuV1nMRw/AI78HOzf6WxfUx3VpPVdxsZ3eLMrp/c5h21XduinnLRbelzXxnQ+XEUXxIaEXJpTJoNnHmDSb+W22vwrnYcVMPVK+2vn1fx+2286H7WePCRtG88WXPLg45R7bmugey0dfkQlPB3GNDlLASV+TsL6GF2H6hbQRjjSXkIprAUHLZ1FoJpLwWHpcj49vg0kP81z8fQT0zgdZuAwFsUo8ANRuGw6C3FKnCFlbC9EZyCMd7C5CwL/s3F7QAYtrG8uxDML4VY/uASqpO4NlA8ZX85k3j4aV2lU6f3CJA205QW2cVRVShzQdS7RSByYY2wZsRAF2qjR1eK6pdZ4tSfQ8E8wyOy/n7sZq2eDbaEZeUXnEWGZLUJHXIUNbS/mduiQID31tWYkKam+EFWz6IxHFu28C2iV/Jnaff+lx7bdmNBbcR4uhJu00iLC1GiHl+I0QmNWaXE/uNF5gf37LH8dJYSQ3x9thXVrLYXBtBi/wdUX3kDUeQFEopM4R8KhoQ8D5JBqB04VsofL90g4RoVB7Bd8KSuKZjCsgcKrS5ZtIeOHvQgtkqlH+34rDu4B9b6V68BMcbox/WGIxefFqSd+XgMu8QLvnIMnOWbEjN8xCM0NS+5gnrsWFxQRUyeOeVkNlR8pRmQ8JbbaRqUV6hnNKiMYr2lDrxF1FW0Z1ORQOAMrrrPUKpaKjj6Fn9sm3C2yGv4cejNHkw1MyxAQIfnIeyV4q2h8hTpabKH6GOH6nh/vh/RWurUbqvpG+FbOsI5hrVZt3CBSbn/1/PmaO3Xju/seeoz3WIsrxwYxDpVVf8+XAB5yrsXQiqK+Gt9VXkWdb8oAq+VHj4UXR2rysGtm51tnFXW2cZJaz1bOe31bJIWeza/NhsHt4LYzxbEcVaRWSjt0KDXoeufnU3nPzuu+5+NTwHM1vipgNncUwIEhkACnn9sBZpOARCmDpUgVYQprtoiW+SNKplEjsXBRNMrXMYUNaF0fjnlxWDe21VU2EklMaZWown7nUNw8PnW/hsX7/TuBg16gCA0CS1bgNx1FmDqLhfhr+H0WlHUYpHbiG6u7YdGOPdxRqTZDnQwnEB5WaOcrjDirdzUlthNXzp3ik45UFotysU0uzSX65W5fEoziynFCz70KAiUVkOZFI/sas7UjmXQWpDjOITt0Z5xoreRcmsXG/bGBhJXCP3AHhED3AdLx2BSyV01KHR00q7RHbSVsT2UpPg1QJqv6lMD+uSYCo7VHWYWeGA/9ph7FjqpsWRjTB2ol7zzGr15GNTwlfaSc5DIVmmUrOjZpBMYS6w56gW4uWK4lw53ysGOYZJwxNH6lJtLsOlBo3MevDPwpgfljI406zsqx6N27t690s2WsAepKGV26pTO0JfB7aOgqvKQ84ZD6Q0zHqBjhq6kopA5JS365Qz3pH0tURPLluhlvH3+MyoJYEsKJnot2Z2zZMFk4iI+GZGKgSNjbmzOqQBMR58LTQADw7nZ0SblmJIvGZPVJ2OyvF0aUZzEUYkwKWFIYE3WyixNM05R08CWULrXkqmYW4r0RTXpSVZLSA0qlky1xJk+tUQPARmdmSUjcPcfyt2XzBVqKgqGkopt83d9OdmmUFEhh4KKK9Hc3JdjSCbepu8HqsSOYEuMN0/IplCGb22ZL0ztm5NxJ3TRTTVQgvSzQgOXAF5ERIEznMZCZRfZFYuB0V2HzVciuviaqEB62fh7oNR2qTHF1zRvukiea//BvJKuKUr4ir3StOAvQWNzZxCXKBeoJTbxe8GY1+sSc/L3X6g+mMAPzJBgE+9ASOTVhanF5rTkAU1SzkwIAhLkhK5cEa964kFJsdgSnH+WwpdEphdPHYNbHiMyhtT5Q6me+6JSA84LnqX3z4VDsMTkCdX0SQoDm3K4rFGgEeblqV3GI37npfhAjX/oy+LznORPwndNznviB6/BOgVGCl5buVLxEQjFAV53vRxDQnD/92NBhSWu77rLd+veY2F9KLffoeXF2ZdgiGKCxm8yNooM3CGSZRrHE4gPITG3LvaKtkgd7DZTE0qLl0usKOT9OnJkh9TJJkPo2tCI45J++9tfhGZNMi3F04zzvnB6lxIuEDaCH7CMEkVamRI+zjMMRcAXy/24QX2kFqcXYMduXac/tH94mtQf293XiH/4cbs8Ivtp7srWTiv691kXPeZy3EnsZz8XnB3cWNz5Ixhzx/UliVgLoe9KRkO+mcuwaFQ6mkp9cUbcMX7701ctYoqjUyzDZxgSoOVNju+7CQDnFpVwyGYUYOIX4AJnSn6CplAokFw5KpqiX1kqBaqhSRxEqGmsGqe++hqoIoR0uH75oEhlVFSLhw7V1RQlPRFAuPUODa3FcKf0sWntcEfHfZi479vUW1+4Rpxh1EA4Vda9l6i4i3CpE+5P4GNqUiQ004igloOBFWF4iMzQUheolfph1Aa1+rFf8dmZBGJ95CGZOpDZNpy4Ey7jwwZqg1uogQaoo4Iy3HT8d7lNmphMZ51qOUi2eYhsYLu1CQuaH4RpoihOw42xBvHT+XFuRKdBqGGqa6L9ReFzUcOtbhSKt4T8mqs0p/HnVgqagFAj1DeR+M0V4wM1Ps8twdlDSKWoDV7WNFCWwzhz8EConAmKN8cmYcAlXQPV1SgT0RMbeOlqoDGq0flxnMBBwaj0r8hNwNBMOqOGOgv2UWu1r6sy+GFg+4GlYjBFbfCS0QAzadSkCcKCMe+xbc3ITE01MeAW6P10wWDjFL0Yay6VeBllWj6X8ebTAokSHbWZH2mO+GD4KGBSCR/MwykvZ0o7FGx55XZUTg/9q/x2Awr9MICg/4W6Y5EsnUO8oXFOKbTV/oH6wDCy3PwVjU+lQ2WVZKDza5jymqUQB1Sdn6acchquvtIIQSodmRvkDswM9VuTUr3Z9H+MVYCqcTXR6aoYQ+Nr4tMR1HxNNBmcNWiyiaQiXX3XOCOhHvY5o/WEkBo1Rhpha/0Hb6P+B589A9FLsYdSvEvqmqSzmQvparU0Vv234vnaxptf2mopJN4qU93C/c2yQ5nQ11rz50rrqOnvvwMz2afdUl/pdaxxP/sgm9IsxhgaL8VVNNerO9ABTBdPfzqpfsjBxQs1hV9BeGbMXT/fBOVex59San2JXwOU4ueEZ8LDXHxruPwppRIyriYgzsrlEPrqDgHlNZ2j3pRSfVApZbgU4oKK8isPz81LMKvnmWFWN7VUP86rYTxK0hEdV5sDXhgOAK27gacGZqjzxX9BCna0LfMNV21WOlqayp9ss8548xsgHIG92uA8BT7loclhPJxduB4ppbCEvhswGDjjPDewxS+AfNIGT4SWthNIvOYAevhtlLKgjadP0mdE8Bvb5cWO4vv/tuiBfWyYg/WWXBJqgAPJ8+eejw33RYHBwvmJbNY0jVNNebrq3FBJ46gmzsXPT8eNFT/iwum45nOqz6+uA6XygXKv4ya5aYHNmqe8+srTNYxu/DWVTodq4lBpuuarz68+N27ceCGX6orza7bmqwfVMf7GVn06P1JMfTo/P51f8/lVpPPj/IgX4WoinKI+VBVCxczV6j7nleSXl/jjpJWG6muu8pwqKQ+J6mu48hBSVXZI5ZkvA9X5yI2z45yR+bjRYaQtt1LfWJvX7tddyEm0t1xw/azSMURQ7PNDaxfeYH0MztsaEys6X8MtVPpACxWaSgwYds+mCAN9qbiyFqy9iQunM5rTIxn9gzXf/K3xlYtvpZ12pvVUe+uOlrQChDbwajpnT8j+PkL0mtsPyGX7b+J1h/mUZVRPpA/UUyPYF5Wir4ctn/BDDo6cn7KSojFpv4YG/lBTITukQFZIQBhSH9L5ZzR0oq48bXQokN6Hov9Ky1I4HdiSm6safp4Wi0sr6tJhM65O7DXffQn8J0tw/Dwn2suIRfioPnVRn6TlhbmXvSg8H1y3bka5PcIJqtPv+OVW/K38D71v6OnBcsWIp+c7Jtxk+FBo3jXUKtZkRMUETQIKUWbkpmJj0DRzKPUfVrA5uLGg3qhNWO6SIxABTWDUzMIj0s2hTn9oQXlQpvY4/s1HNLGgipCD3vNXltLmWOU/tIS7C4lvW1+A00uROFR7kfUjc3o7ki+iOna54K5JRppIhMpBtaCG0Cc3f3eyaH1SbVCWL1HyHmVkEBUTmQHCJz197jE7T7kyGB9bgYplrW8OTIYZZwv8kYfDSSjtxO32f9cy/uYADGlXX7XsCZBxrmrVKiw8xUp0xiMAYFHmiu8KSDlzjrovyqF5z54vnPXYX/DLd5XYq1Hv9ueyR7ojwAueuUvrRnyE+DPs68D9Lv2hSz6BMwUE4bJenY0jGaQYiPqX9jfnWfvJTNtkFvdzi/tUT9szKcw0zgvKTCyFFHz/+gwAoFitS01uJtQlNRWrsz1srTgC05/ws8vup3jHrd/9xPqRBrRuITm3H6F7R89dVzQ9IrGkNi8tGaCRk1ACtMM9tiwQXLAzvDq+Jxayn5bbx1dVFH9Hb5ozV4pMRg7q2s5PhCnaKeKGljBeHVkEAU3C3UCtKwSiSe6ehA/eytSaAdCqoWeUHZrhbtEAgLkscG291aeMoEi2v0M0PR7lyMLK0AXr9vP2U1gJysyGYm3RtAgahRZOowdNYRLMY5jrHbbpDZQ+g49guAaEmesu3wr0OKgyHYSmyZoKSI2BX6N9Kz6/GlZig6LuAEho/VrRLb9c0nicumvCvfzySWJzLHKGQAsTZSCQmiecyuiDqljInGvzqyQCrrMQEfS5sNXeBfbRbzo53Qn+sReYJBk47XruLDAuKWGhkzPSTmLX9z/dWHZ5sHkIoAv48tz0yjSgsSxVXsTgJGgv1gHjyiwyjF0onbJLabzkiXnasCGg8u7ztvwtGLyIlvo4zMeuaXjGQ4uXxWaeDduS4PboQvjEWX3gxvZT7rbzzExTXd8ZXWm0EjgnmKgzJOItJSInX7J/C17OchgYGbHLzLMOZDcbnxBPGNcilN3DlOi/9NDx7Msls1uiZFLtLArju8hDzUb2rprvRc4Byz8fDFObwbKBuQJFe8LVRxcI32kD/lAi726kc4xTu1BjYFswaJy83Pn3tlud1KakMPGKNjQ+RmmbOb5edijC/Uc8WejqGJaOeFfk0/IoKeqoDt6IHsfBnr/XwnlRUgBkFeGMKyywOrLf4gnaJOYG8OHQyxSTKBRDAOO6Yh5cy9G+k9aJDVGmisLKLbyeqf90ijn+nluXGWuWF78NnGmbGRcUuCSsa99VworlRYU59C7LlkTKI6epM/8GNetP/HAYos0133xWlRGIdavU8YGl6O2mnLjyXWsprhN9UGRuN/MUBViBUkDoBxc6S329OPU/mXuS+U6YMP0ONG0dMw4LB4Y+VpogfbKDM2oZ9jHjY/rcwj7e+ZY+W9inbp/X5wj70uPd+maEfSG8ad8c+8WnmE7wKcX5+R/uVqTow7xGANtZWT32qRaM7ooxwsDHsGdx6nuOYaQZF+obsEH8FUbPkxSPvsH+7cbPluTiMyTpl1NScemOH65pL8rFuvN5iS7QupttHHYJa7wAc6oUizDPeVyRinVnNtBZasHtLoAGALBWCOGrTZJb9UZ3EkRVg5uZtd6QWWJi3twMOjs1gX1Lh8xeTdrZmkaTu6ZLdqvoKVSo1EHErQ9qCCHjYyBZCOHOt0A6IcRunwe5hJB7vBs0JYRMeFNogGzIm8Td4s9fverNX6s8rGzcwm53OVv4xjk4BpYTKp9CA28ZVvdzhNkmN1hamTG9tK48uJf4CN3sEZ/dJ/8B2Yz7CR9N/iz/8+QXwIM62OfQVv7HWH4qPdYWna0L8+JXxb62/FfS2WIcGqhQda3jsDuVzmb79BAett7h4QzTrsGHmahb/fVdAbDt0tQ9V96Xg1QaBlKVFQLBzU0whwSF7QkBALyFoFN4iDEQAQb/1A7inNoO1TZpX7uLnSMd2iEfiGJNoJvloK6o/WvOoMakb/D17aPpofF1ztf+cAdj+Kb4jPiKnEUY1kErXhpvgdQ0BqK1fXbjnGDOXWqxGNcvtw2FTLC+yuBwJdiZ2sdpCnLe5/hccml6xHGa1+mtcYAJllvPPqIEO1yoDQCoG5dru1UZvKExMjKvIp8Q+PIuMGfRHHZT28dE3/XUo1khxgcjtPLnj+/qs2sagYal9KFCZs4Wd+DCZ0ks5jxHxYiGS7VXOWHAbVRRhc2pOAeJFZpi5vC5ySY1fAicps8QYycQsVYEYnxyCKxwHjIMsRj+uOu0Z/KUWhcUK0GIC+XR1+nO5e/ezFv9nWtZ9CNID5elmYsyWRbTl7Pgu1YdZi4lPh83S3NpWm4i/Ef4xzl3J+q68/rGLgqemiPwCoVsX4O4UGjHtyAbFLrzecitDqZc2V1JB4Oqag9GWc0Xm4A5pD2I10R8QSwGf/49YLX+az0pf7sVX9/9GMmobFNzCD5r9MXw6WJcE2JN/QCwYylmfnL4ZwDq/joqiRXGJyYn/mtdmZCcx/e/bbk3LQHYOY9/bA6dh+zxqN0fZAbxNoQpPxntNnqukAlyC273eeqhgbZ6n9qpo3ovtVtcuCMAcGe121vf67V2Z/aP+oSuT6/13an4DOGlZtE7G+B8Ddhfhvm/vmhYqTST8mOPvHeZQlZgKTiGNhiM1+jZ5x/KFo0Dqf36veSvduu1/fj1eKxyLrFzqNOtq6rkqq9ScIpHIrSCu/L5xEFwhUkVQoWgKSXvg5Jvf0UP88tHRxdvL6MEEcCY4rQRQndIe75kUZ/kUXnfVeFsRRCRdnLBzSxy5zsCgKnoTq33eodFuyLviZM0wOtK3zwTHPt6lWtUa2fM6XnH9XiH2Otr4fYAgwiX4XmEt9ljJxH1bkEDACKSQSS4IDiSTRoQ3L3FcJ6+Og+mP7drJrnTpS1kbVmA24tsMVtMl3y3tFRjBZFssbOUpZeWazs4wmk+GoS2o4Eq+TvYkue99lZWZLZDf/ho8n+aptmlN7kTf7D2TVySs8UcUgRml9LAqC3tyyYm/Mec0GU4k+hDyrlg4I7GCZj7cqZxToeWnLH9L47eF9Z7LL9p/a202ca6s1qRt30i8YMqm6k5EbdFTS/nbalZlwjz9sHvM3NEiyZucWdET3oVchV6gTuZG8Bct9bfXVBV67pNHghjPFSehKrBX7MegwIyLIuUxRX880FHtd4kk/4qabO3TUvrD85PwPAnW//TvzJ+fjHz/nPbMiXUlW1hk9OIVwkgbF2T4odaPejO8qxJpu1SMv5zxQ2Cki7N+3YvwtuoNv4nXllz37574Afa9sq2z9OfBvk5P/t/jv+T9G+4sva8+fXmj/zwp5WMF/1v2u3fxwVMltpDJ8Z/3JV1V+bNn+Rl7xVA+bWfeMmnt0fAon/+yuB94/mMU85prO4qJU1utUOZ31iXheZSsfWsMT3W6ocV2GqnsCXl1zVblAx/kl3dJme8vpaBXVBbYdd2eFCBmpGNlGmOIVFdRLZZsJ2BBAsdnrPrEMvZCgYAsI01M4FkeyU1HQtUFGZ66sMGQ9pwO+trEnOwP29r0FzoYd8WMbf07mwHTe8EL8PsdzjdLGSPcAZO5nxwS87lzmA7bZ6rxh+7sIKxUMdo6rsYxBq0w9Kv0fnP9tJdkePgNmyq+/oXKlZ7nIIVi5uYmGnzVnsXKvKGh1wRadEhoWtttupbKDIPz3xnzrsZ3dP04Vk/2vJgLoqFBswzcQwZ6zLzLrStsXZXlY0jZNz+4XYRdqetJ0rSMDh0vWFy3TZy9x6geKzpUTZ21B1k10nkOu2SL3aWwdNL62abycDs6yj+ugvGtetXnhw74Z/IXZ0fuJurfxxqA0gBCxd9c5S30pzHBPY9VP6sd1zrMKK9PQ/VOtT+uwCcUni7Q4GT1k6HypXjON/agN6+VxHRLmlcuaWloXJlOeOCwPWxyQm25yn/LidYexK1S82pZd2OJ8W4QtQF7pPQre1BtT9pwW43SFjTghO8DZsjuJF3YQ8Ft/F57LXr2EcQYPsI8rpom39sg358MGb06dNnwn2HEvV1UM1LuVv9+HB+mu3hhKDO8gm6tyhXe/fhPn1yMXc4wxbGophhN1Ivuvd1HkOC1f5dmHW8Q8WJWNDNoCvkqnJQyMMt53EfedpeU6eMoJuNThiAhDsblDCxOcH9GkZINtjDcRDGvAqxsJKtDv8L3BKvhnffh33/7LsxoVMBMMQx23ZPGMHSMxcr1e/u+2f7y4TxXHVYXu/GdE+y56qi9XlULq6FlOpnrq5ofKeLF1i03RcrvM3Ecqg3Dhhv5xVP6WQA/f0zAhwBDJtPs0LoGqnOlpSaDdlDovO52qd298ITo2RlOgKAObQQfG6UOXME3Zepz5xXrG9p6XGhfIjfU+OojrNR5h9FVUztKq54yLnSPD+j0LN6QTAA4BxOZ2s3bub8VdyyEn2FXuKE+YWi7+O0WcCC19fJp/xzU36TieCNPavy20e/z4zwzkiPfYX86g40VZpvp6udFp2rhWvpuJJ7IGW3Ey1Mry2Y1l3b52atcpW+UU8y2MxNCmwvY70a0BKHgwzIePQki0Y+dvfonjw75klQLKvEQORKgmJWcTDuzU2UqhyLLTdRav5IO5OVwxv2HR/PlO4jXEz2Ln7v47/Fe7rU+FO/SL1tY8f+31WkfKRLKll3Yau+y8zHXgAwco8uGqq66+DH6v2g2M6M9MPw5blIV7vVGTW5O1C+t9uaNgq+ROZqAADA0Q0dT2N0J0ywVZAom/koWiyfz+BBCnbPajAAAB0F1C6y+kW7mE73zOKO0N3x5jVBbsH+dZTQluzdAQIVcpdIyDBCEItCZtvF2LWRLdyAqXEtNt2AmQoXbPfqz6SdCXU8XtJeBrGeLQe1y3ulKx8wW8JUlf5ke5dJzR26xm1uOorktXY7QgBw3KBjVXh49pJOifVvFqXHz/wocKEtcHNtxSKDtsD2eNkNLgl0Dw6ia9s/Lhpxmm29iiVN9GXOB+0spKPqMBk9eXzZQWHXengwnAYcAGBU6Z3SwqQ6PuQNCVNYiIJdva13rkC7SxKvV5oBADuiRbbM7Ul3xcgW60OTjX8uLLyWD72rwFH+mAZEu/8sTcDKrX6KIqk+PpI6fWqNTUafbuMyTdKYH+ogYxvv+/B0eLq4T7PIaVrnQ7A/FDs6Un9cLPhspFI/YwQTHQkedFYb8NEFvrLcyuntTcjD6t7lQyas2lJpTWUptCp9dINTn1/680ucPRx+uaGHvJcdVCrpA/l7TUue3bCU/zfxniFSrkDaDHS+zj3XaAcSOSe4IIG0HtOupPMdPCW6fUwkbVK0R4/x1dzFP1eDt8sbCHu4ynRnwSkcmEB78s22IZJ1pWRYJC2uOyu5iBc05YwcQfPcvXMopDZVJFwrN92u8tKtw8HgXab8XfOA/TN6HgFc3wDSCKEUUp0tKfU1gp7aCzp0PlHTAPUtY0lKbt4kANhBV/LRh8bnoUv3dSG8pmfw89kDSI7PFfTYe52maN+zm3lzVDDPxYAs3XCmwgCAQ1ssNswK+LVt683gcz7heR4+/vX+jy12H+BmPOuMVRkvLWXu1O7Mc6D2pOBJNRl5vt3nNpbeQh4MANikecUugAoi08VdJUTCGXs7u+8gvVnOG8QOQhw/NuZMUSCTup3Fd8fonUkIggJQn6qNQV2hvkHbgkZQ3zpcQPNI9DHUATUkUBcugznpREXKn3cW3lO5B+Kzpg2N6a5Mz4roVrJwKQAAcAE6bkcowBwTFAnSZMzZAM4wdMVQjYYwAMC1YLrM1XK/8FtER2wXArgFDy1O/jzxIAkPu7sBDd+OSXTlCl0ObJTVcZAp7tmAj5FrxMlMXW8EYk7OZZoo5wkXprWR0zHbGbotnOX0No8djoMQEgVL2Cxib2wpsnMDk+nSqMQMkM7hLrXtJMdc9C9p/2P56MCSdmO6kvenn2ap9INjeZtzSfu4kZZMo1clfqhJaJLm/XPov0Ba0I1fszUg/XP5o9qDvJ9VYKd+m+SnZKLP/vRm9ERdvRWTwVuQOFTI5qTPoHSE/PhItrR0sJngKIir9WByVWuVXDGHSa4LqzBd9obsSfvn3UOe7bY+dWtXLqS3NJyF53xngL4jIo8tXcfQOSBVDTgAQKph0OYFCwNYhTiRxq62UQOws9nNGNhveKUZAECL7dqerN5lgzF3w5E7Fd8fG6T71oPOFTJ6vTGqAA6eRk6hEeD2Jx1yVRiJ+45hbuhKW2NE0F1ti1mF3K1wwWx+JU2AHdnoe4G+SR5sCzp4ynjliHVIEMRuIjb6qsIWSbaW9fQU7Mya2nuSKYIqMQRrM5YxNMtaB/m4G1MUvpYAADDl6ykWHMvbykv6x0adZEonlZjjhLMomEx5TlkP18phFQOjvjWmzxUbJN02BzZ8KI+bbUNmfKV0YmRvX2G9C1N0ZRhOXwTC2w+pPxpuvQad0WThiO5+hnA5K7pYsRmmdo7z0Twg9Nz5VTOWt39GzyOA6wxAHBbkOMQ6W1xqF1gPojur++oEDXEXo0Lk+XsfAUAqatfJx1l0Og9zuq+6oFm2ucw/fgj22V3RHiPodZjNOvrskVnvOwtO7uSgUk2Toc/tYwNLjzZpMBlMyvY268UUm7DsWGIGwBunzW9uWoIO3g9r31qwpRSJOlFNz4WlQdGHiTozV/aWPlXVDXGzyab7c+i+YK+7YHvrRs9zYLrqaUm7MrjK4KSslF+GoOLNtqrpC9IHDXxx+++c4+HGJt4t59xersN513xnTFvkfjQPqw8f3lY8mN+9/9cajWa7KE2FZGOroWyErdFI3LQS4WVJBugdIK8oprKLbCyHMjUYuPPdvUDZ+cJWCKqVCBHdTgYIRNu5gGWEDsIY2NHnlLVjpA8uY4YlnbzNch8aDj6+qtb3GvaJH9ziZ0/enJXoaiUAAHCEapidCRRsCe6tDic7uznGPAKQYZ9bW5xKJt65HAwA2GS6uwz+miu+mppeKBTbSw63xP5AlJYzNXpGYnUdu08k1u6k0cFlv5zqXiinUlYItMk/0DToZIaNpm3nMhSaznCGofMyx95xvMyzar1gJ3yJtXdEVYdSTCMorN8ogr40zQEBQNYwRX64abS1E/Yv3TBpx3JaqIyzGBu62x3PHZTFdEdCqWb7FyJk0OvqTUtbC3z4rc5i7L3BH+0hnfVnx0XdDkhUeVGX4gAA1s06GHJ1t34k6XoXp/slA7oHQ8w6RdHRzt6BxDaZAQBiwWB/COPT+P65uOhPc1IKdyhd8vLY7kFFRwYvtX/XEDP1WsoNcJNCPtFNbcwayP1UCg+m1+1vDUSTkagIMXE2moasdS6ugUQxBvfpG8uOBqNviQePDiz9jElpyG4WD6IIhawtUWBul3pu/y6K7EWiZ9DgVPmiDtafvqaPAOCyYMfWY3ebFeLUrZfTMCKZrDFpkOadFyUTMMurZWoJ7q6dCqvAlluj7RqwuvZ+2w3m4K24ut3HaFpf+itVOLkFoisIV39AXxZfSABXemAZkoWQF6nPlrR6mrKHQpezFYXai1EqJZX9CACW6Cp47PVCh8ZeIeZCyHPEz2GW0uv2xBoCsP1sNt7nduyeVSF9J4dINRx5Pi45k6VnkAcDAObyw0g1s1pPJcdSOEVzl7I+N/GG5PesXP1Glq8WuX822llHS60WdtZqnHvpi4tXJd/erT9//O/53N8T38pr/IZQHrPTVUNF2Bo+uN16Z/LzVPUgjwK32wwGAKQUBbDnL+As8NKKy96kdoEZ+fN2CbfhYT87sIR352agKRaSOegbEzP6TsEQxmV2Ht4JkRgD5kiswXZYRWKzPJYF+pMGfGfYa706Qjj70rTWEN3pRtVP2u4QCPngiTEla8YZ2FZaHTttYNsXCtqBI3t75m8C5t5VORWjlI2eE4erwgCAoe7Ru6AKwHkpTruVUlpt/HlhQ0M1YVM3zkWL84Al787Ad3HGfllDC1bIIDgpJzNzRhNVnMuyYQzGsCLcVLCz5YY7CWi3hiQ5tXZ45KH/gMMvJMY2y9+khTn5+Xv+C6j44tlTaljVfiO09QvVHBAAwAt7YiGKNzQtaW7DChc2a+Wa9435s5bg8Pcf0bwEB3/2AuvfQ1RgKsYHUkIFXTHGc8nvy8RrWNqFWFUB+pafpRLLhjigYxoP04s0pfnxhKPrgVa5Cvb6s8PKjqBXTScAQO840TjT2k8DonIWzMu4hImgHl6oHZAcrx4tkMKzrYLabjIDALyEs+1puwboFB9jCdDt/XMRcs+H7jFQnTfGN8Dh02jcaCvt9he+3ZQZOwGJdzc4aWdzDpyLc7kz2NpwIVVDpjqhUdAmU0QQHHBgiKdOTBjM03BVTj6kdsFw2zLm5Of3hTCHh3DgVQUtIqCa80C4xfV3j+Aq62pqIXI2gm4vT1a+Sx+7KwUAAHNHTjZ/odMQr2kJsl3De8oiifYao2vSOHpRPAXGi/98JOUl/qz4IrJlybF+ux/c+hsebJ4FAPKmMECoe8l2GbxVH5KHubRIW7crCPHFMvgC8aaG4QrNmePgrmH8CL9lYjv51XZraUCxGBXagGgjQ1gLdUoWm3kQt3XhedwiK3lI4lbK0uVgAEA0iNRaBa7ezHKmTovhUNPt9Iak9x6i/3O6fP3Q+tTXpENdn9nxER3qm85g95mdAGzCFhwjU+gyepptEadWhQEAaY7ClPwF0gGJrLjJhpcBa9foXfLwwWjPj80iUySIddesM7B8VepJuQdD4MJGCNiVz8VRFuJj2BMoK125EB2cjihrWGMg0Fc7dYjt1yJFi2JhM1Lisc75YvdYU+f99nOqDq+5K/OEp8TQDB3iphFLeUDY3jKQU7JRUAzDOfFvUOZ3jfuk7rjqmY1hTgHmzAInwyWcx6mpsRcqprbSmQJxFAx6WXCV6Q5+GE6+/8utpZns7HwmTGcuIMES+sT7UAVzc0kYADC6q6pabF2NKp2mcgvMAGZtOFe5WEdrn+rzpkTrGw/7znC06VGtzZyoahD41gVnIeq8KCAII0pXCtHcCfwagaHf+h1RJ3MNf6oW4mI0STAYEq3TOSdQvAsmTz9101Leg0/lj+Stp0JDEheWZ57ChSHItvzCaAtpYxZNtJVuWxYG2hqGC4uIXGwHQKvBKte+2waxq5Pbcx96UIaqHBhRFeb1VIo4LmUVNNfCGDdFRilpDk/79tT3zzVARnl7B9+G07QRb5odA11m/ZND1+Or2ymYr1O4HWfRmL7DwC465GaDm+G6QG70XFCcOMDs7GvbMDOueGohFzOVXtp63i6OkPfbPjy1Ee4DCzUun8Av8FF5Zvj3qMn5ST2Op8/aH/EVHnb4Mkk/QwSZJjgS4PP2puJzQE9W+A2+fAblxwcOWtoGzNseYkyrBJYsUooDPXbefG1BXHm9GwgMXgzr9inVvxCoWbp9T//hiVtqLakB2hbUPuHjWxLOiyZNZzInFibaxOlzgoQuPziEcRmBdZd5eXGa7Lj42wx9pNKvrlLZKVi7AXANOwAACHUz5sVMoC8gmrAw1gmGxau3jshlaaeIrZVmAEBEf6WatjEI0h6bAQXV/k1ABV70aOku3HmmKAsZfBXCPJUWAhX+kGLUdaMK+N7m9mVvw7+0d78QTLequhYH1K0g3gkzrVJH6T6bJOwCoOK0uQmhoMe5RJ1tGGKAgCHCTn1xfkhhDusTv4B1+BQUEnr4MrZo2k//XkZmGJx4LbaKozxlzguhnEAHyCFBY23xAAyL9awb2OZVlcUBtibM6CIoccWAN1xkywIA0DWmvB/v3eAWoWPDDXVlrpJNAeJYVxgVC/K2N6GkDlCwdbWKtyyxKuO6dXe7kEu0KwqIXMbOPhnksduPkTbfcNSe3ftswr3MXyhb3b9+TdsM5p8BED/js6nHIzXNz9fbFS19lTwYAHCQpVvL1s9wbcciU5LJn+O5GfmUL8kX3yjLXqP21yacc0Je3vZccNqO+6ZWXMUddR3WVsWb1aBUuwpneU5FQSNLk5UHAwB4sqrwFgwG7ptaaN2lXjusdIXxvj+Etnm4dPtSwzrkI5tTRM+B7Ap184TwTcwjs1DixldRKs7rvEP+QH2fbCcWhqHwBuNIULr36VRC9jQ4qMAUFQmGyFkrKtLa9JhtOT+H4l/GzJirY/90Nt70q6o5VPNDetobo/44oQUlE8ZvXwqp0AVBIsrJSEMsti1yHbHIGGR04dJSnguANKSZHqR85rEa51tZ+q2imjay3pjXKX+/TWjXWnCHZvWm2/RMd8hECiRuGgAAkgWuZHQuPeGOAtfDBW8bgc6Fz4BA7zL8XOXqlY5VFdQMBgCoTkrEXl7XSu6bSkHOPG6JMqrE3qlG77orxoivzNWBuYkSV4bVcOicMQp5UbMvHGhXWSiVDjMs5GSPsaejysmcAR3HzuUc6LjDGM6DPN8FQDdXkpd2QHvbgNwsTmTS61DJsQIpbwyxTy6FquSS7bHR/OXR/CXR/Dam+RdoLjbMlFq90SyJpjOinDGyPVaaP4dm/W+J5y3d/gLN5RRjpVbpNBOZCw4ZDMmVJkH/1cizUJPrVlRa20SKcNvOgkivgEEsqDUmGxAvF7gJPohgckvtaYjvmw3j3R08ABsP1eTbvnEa6bBaR+ojt8Dt7zB+ZKHDgZuwqCZ8TWcy7Wgd4FX6hnzaY7XOB43foZ7Olqm7EKq2f3UWZrx309tvVcT61UvLBaZFevSMDudrwpvgZc+s21q/ulOmbgpwc21whzn+v33HYdzuZdHAhJxwSQZWtbNgV58Ec8ez9wgu1WAGABwDoYUNbcAQsNag5LrPjJMs+seMZdTU+xcD5MKybCqspvbvLq9pQ++6kqlhLBWqF40mTh3P0aFwHigLadmETYrkgJndu7JDn7pMp+2Utk79InK+iJfxY0ban3w//v3h/sgpbzVBT6WB+ip9uuy1sLezJkalEZqRTDoFaKPRqq2ZzEHjPucy0yPnIRqzw4UZ1iRnxIBpTkDO+ILguQjactEiuDBAcrgOvRATX1W4a4gnsh51Nuh2UquvqGIMQSmmgWwEuylvTRKaa1oAADCIVjelfRFCs0dcRaYbxGCtxB3kqbrC+CbQzLQXZUvdSQYtmKvVmploFV9xdxKSK1Y9J7pKgeSK4vP6q8gk19hVif36oFq67beA0M4lhGm6dMEAqWCp6IcydCb3xZ+1Ra6jf+z6oAsf73xSIKCRCQYPLtMiSMtCTy8l6yjSoxVhAEBaCgiw1jWbGuXUKBUvphfZe3gw8BsEz6FBqzehsHcTpQZ2kqvgI1IxUYdbya1VqyoUlKN2A/QwxOsQOBIGAKgBQMKgUZaYswEO58UcXgc6WlFDiiqaMzgK8fp51SwGIUNvSEcls4zbJVO1VFZ0sbTUrEGpc9TrCjxJoDnqqFfMW40B89K38+ovpz/ll1Zwh+9TsfkBAGCaYmaeaQjFB4UahNAumWoVxc81REP6qbyzhgw0nCRVYutYt3tHKthArowqp5h0nuSgB+HlgIcoZNFIENhoEiLEvZ3zW3SOMit94p3LBeiTVgwXcnuxJIFW3mhvlVM8NnooWkuiPfTUSamDe6QWoGTV4XRrlIiCj8a3/E6UuWVpRnlUagFrrtTV7DtYVZF9DKil/6NsxUFgSbuw8cbUYt3IqQdQMwxxaDB1vH+HILbXNmeR7LazUBHslDOWFqmust14A+bKi1i4O+4PVcirnHvnholm4OshlcMoWHfni9Udt69NMQqWs6aaYfJYpVR/byvuIXek8rgTZFoHADhAMUZAuGGA5dZDgUA70xEueyfNAIDDInqxLaGAZNsAPfy37f6rHSuWREOS0nsX0Xdr/vf+Av4VaOwnMTllHX0Wr3+xXDmobDg87WBDv/++J+b8i+R0s83ufoIOO//jwpz9lyzbnicgeZalTLhKM4Ikg7bq7mZoaDy/jKAdxrAJopRV3kmmW0zhtsPgLRTYlacNe0ERXCcyOOj15dREdzYPMKCTyEQ366rQoDOvzGGpiJy8MQaH+zLNwE9i18CbP6pxAQAY7Nb+P6VGX9XXzIPDfQk6AxdNBiPxx2HFBADCsn5G2eUxm4H1cHr0iK00T6ffTKyw0FUmXQVepRalNz+UouX0FWszLUxh7b0iKAZsLhrGAgBLa3u2n+3dhy0ttPwdeKHqaSfT5oE/AOgvdPCM57ZywDcK4GVyR5vjkWJJdAmKc2EAwA6qewEhwBFp0J+dbM/h8NuWvCaHX0k+uH08GOkOdlE/KNR7Jx4LW4iL8frFfhsdriY+vro80fgssQw5Th+fFnuuituF4blzJlVxe7YG7xhYC4bn1g6JtV6VVoMBAAcN7M5sLrBhhNL+mdX0Pvp7yy+WmzKfhdC1/HkuJGinpDOcleuYmyihG5C775xy//+Z9vnfbR7dh72p4qM+9XroUIO4kBuXDxbyxl8lT1UI4tVAnrCN8bUhz6158eVMp+TtYgy+dHaMMgUEQOnZSaa4PDaoHIJSv9IKnx7q+0xifLeTX70YgOPQ+/3r0Muw34bfjzxp3XmyW9mp6No+JMIs9AtI3OrgFvdqx/0B3UIFsIsBK9yIbAPS56J4Yl0eIZQQsm7oXgeMG/oveHn3hhDBPgmYLQMU4Tf4OQdgDwrixcVLcg1fIMcqzzOY3Px2lHZY5g/PqR7CxFoGetXj/PXW3Qja44oM5IcFA54fOR8vd9Z63Xga37d+lN3Z2NVyGEji6jR6OVP9YpryS2kLQTGQfS0o1i5nFzGBZ06lH33JdEtLvJw12cpe1xM8wtb/3SPPBZKXpUcJPTPMk0j4nLyHVEbp/75+bW2Oz45w2QayT3n8wjxJJiKqvBgvCQTFuB26EJSODdKN4FSrYj1PJGyche6kxUvH2pFWhAEAjgZ6h++z4FSVRKQK8uK5QkdFhrcxL7uBMjOb4HNeROZm40ZuC8KigwFWyZq/CWvpEIRd7Uq0CWtv2xh2LQnrSPPCzvWYiHV6iV1e0A12ewIgNs0Ndg9DWjYH2qYDoqUa2hwDqb0KlGG/ntO83cTy12l32wLMRbuNf1/PuDp+PXd8u5HLmACAE4efGpRy3JuWco2fgenh7deDUppIXbD7xUBMcHzaGl3ZXDdQhtNWTGGhzObf3tQMWkeWGff9uifdXOzLun4PDn4x5PDnfn93D7s3t85g++CDuf8YOuOOQDOSm2FC49uCm9Nqy8nOUm+a+LEYzpDPLxSvbMnPBvXxjsdi7Mx7x6n9dMDZm4WaqvQSKcCMq53NfqsUmF1bcOldGApkYp8PpeB0rwYDAGakQHX8BV0DiOR5ZugOPHpaApM2V7phH+38RPVm22rQjQNpC/plTog8VsjVGrf8hLdPRmYaWMu5pHocH0reJGRIAYpHFhBYT1fm5avlWEu/0hz7eok7k+hvx992Y4EbpSJ1OdVy6PYsZxSptXg5GpO+A/r75tE7bP3qukygi7ShzvyxTugyvAxUH/7pV2+QdXIQotJqBQCgBCBndsgRhpIgFsEgqVVkWtApgIB9rh6DJStIT52BrLlJ6iXwLXjWIURE+sbSC4sVFdFujV4CxXA9fAYRy7UUGQjXFxKwC0uVEIPLIGUhmUy8rmJm1HmbiVFVSw8MlDMxYTPAvKwqA22Xw5mXnZKsDiTnNJyoTdAoLjUksH0bnaZo/xCRWa45mhrZ4S5GBQBEuQs/HDgPTzs+sS3WL2+fJH98LpzWN7OhXHdrMaheSgS8lHuGCzyvbQz7iYi272Q1T01sful90v6P3M+DPvn0uWMtt8c5MfViR+8dVWXpgJtNTjyZ6hYUQaSKhic1AEMQqQ4bTGUzQz+qPU3L6Of4j6M6nC4LAwBO0ODmgiYsiIfnTYreaf15Lm9u5KRbe+HdDIcXI1d5tSXUbhhQfLJDMt/3vUGJx81kK68lhBycS1a5Tj1lSsFCNgXzeCJhuC/7gjJED+H0UrwEfhvcSXU/8dDVdd5V4/O78a3VqWQ7/iu0Z3/+aoDXce23v2jV0wrvogH87KsL1+ELJw/XOQUxfDqtA8ePG7QyA1pSYQUGMOKn7XFbkJHf4fTGwyF6VK2V1HyPdPUIXMhXLC+y1+h7QR4yVPnDWhJYDfGOI9bJuboE5j+U63eebN8esp/rrPhXGD8Xrx5VYhD+vVXn/PVZcRpoo+GOdPZKFOMczj47/mdY+PVpcRDa75xUOka7FV8Ekxz3twnh15ampZ0EEUXM8WUwyWKb9LK7uOs3NU95AIwFtoJ8Fnu+a3X5jv0wCsSDufUuzO22a7+0ciJWjBl9NPlFym1zbcXZc6UPOhi+FQkG5bVXvBLNesAhEaR2yf9K2Izm5BZxY2DuDB/ymm62El9QkH/HCRXZdPnpKCu5xNfgFYHrbH4VwHMCr2/Xlpf4vlgJ9VcPkhpwSmdJxoJGGhUAgMYBdJsd9WBY4YiMZA2KKyN1xDRlQe8SnZbPd723KyjcajAAwJACQ9nwmy3JZXoEGPM8tQAn9XnTPZXlJ5Kingi/7jx+lIDybmylgE8iCT5At7OPJ2xzVLJBBmXHJuxUKSZmVgk7tGJaFkrY0Sj2wkoJe+3WjSiRsDfbAhAVDlvfTr1/XiZCy/LpKmBShxksoN+biVseqk3WVUB/MlskAoC5BjjLAHHrAJz7p9/oWRInpHMu9tK+lWnr85fsYZ14/yP2MqqNTSwLu/Q/Ra3djspbVt1ddrVnvzPeG1vsBHONWydcVc6HpbPRrT71hnlEf/Q1bF864GjEvqvu7dOpwfom5tmwnW7O9BjgCX3osFnFnviqFnWpakEUJ+rsmi93lIsNnr5Th1WI/t1FOs4mTBu0hpOkshzehsnqQtXoVnlrcOWKl/N6Vnn3d90FLcJDPjYU9JQbHxjsy73whm7vu4N9vAiaROPgTm2IvG129iHvAosJP2F2vTB5+ZiCVsOwSXNGZ2NYfm7CKrSHLTUhyK+zQTx1wHNM15Mt5dCOf+lnzlh0xxd8t36Emr/9bnYL47rfDVB3NFxgNjsSp/ub7M/Vwv4W9EPEmlP5ESPePcZfor2iPnz2exaMGGKrurtAdWPKZAntfQ7bhW82ab0Xur8b11npQgV5BQAgRu1EHW/Idi2tKjmYsNGtnweiEitE3yJROSoeCwMAdNQUh79zeHo8VszJPNc4s/xOsjaht1s3HQnKAOYqt84+z0+8/c7oIwaWMnwcTGLIgIDbCX8eluIgqE7xdgX2xsWgVgWOcC1oqMBJfAFN7xFt6NwoI9GxM2AErBESXXlA3gV8B9IdImfDFQUnFWg/SnB+MLmSzSvP9x6QGUF8ZRf/6c58msAuMObL9GqypO13SuuGjeuMcjjwSmzKNvdzRiiOn59FGM2zlzH4u1R9ktnaex+qWZaaUy+3a7dIBABLF3IxxQ/NQlop1j8ImN51Pxpoa9pZLGMafNyGe141dJ3jv6fo82v+/JrT4PwQO9833r8DW7z26NoSv3C1o/7zau52/Uuyi+uBnRNPqFqBBtWO7YOlgNbLg5Zoxv+Xa/X9tVQo2vTpB7r8njrLTyTtb921v+fSOGwD2f2WAL9zdeK+tuOwuziOmivCAADNSouGnmbrvRUcdMbbPnhhgDzPxOqJPrJ5qs+Lh3XEI3siYzVIX8jnJwp9YcojIsf2csgER2qadMzMTD5eOJq4J9eyNchJaDFsp3D2R7Pbat+2OMCeWogthy9S8xepOS3Gtw+RJnuLZPt5c5bwExh7/gm8Nb8OO/jq+nvDf8qfZMb42wPfXRmaFT3VuQx10Z2pBMf/+9O8Lk663/iMzmpvGm8r4Lu5f0nmAM81KgAAXgBbqnY2Tc9UYHuWBld3VSUK1tRqTlCA3O0j6QzQfw7+kdftxGVTpyrJkby3zWAAgO86RdS7Tt+IrQ+RGsRMZbvXYRGOdzGDVS2oUJuHXVGZyaqeU3sdPKNPrur7wMBSXpTviMKEA5K33esSWlohif/mjGBJJmbY7QneIzwn0zKje4SvZS/MSoGta99YBWCBloCFJlFBUskikoIMS+NQtd1/o6oLnPj5jNPe+nXjc44lzzEmnlT2Mr92bguj/ydUWzXbPnN6u/gX6wDAVkNol86F0GUCYj0Q9FadAyRbJanED1kSDsX7JwVua81fkSRVd4qp4BrInVItxTiLStIUlX/9oVUe/AY=","base64")).toString()),qH}var Bme=new Map([[G.makeIdent(null,"fsevents").identHash,Cme],[G.makeIdent(null,"resolve").identHash,wme],[G.makeIdent(null,"typescript").identHash,Ime]]),Igt={hooks:{registerPackageExtensions:async(t,e)=>{for(let[r,o]of UH)e(G.parseDescriptor(r,!0),o)},getBuiltinPatch:async(t,e)=>{let r="compat/";if(!e.startsWith(r))return;let o=G.parseIdent(e.slice(r.length)),a=Bme.get(o.identHash)?.();return typeof a<"u"?a:null},reduceDependency:async(t,e,r,o)=>typeof Bme.get(t.identHash)>"u"?t:G.makeDescriptor(t,G.makeRange({protocol:"patch:",source:G.stringifyDescriptor(t),selector:`optional!builtin`,params:null}))}},Bgt=Igt;var a6={};Kt(a6,{ConstraintsCheckCommand:()=>sC,ConstraintsQueryCommand:()=>nC,ConstraintsSourceCommand:()=>iC,default:()=>Jgt});Ke();Ke();j2();var $E=class{constructor(e){this.project=e}createEnvironment(){let e=new ZE(["cwd","ident"]),r=new ZE(["workspace","type","ident"]),o=new ZE(["ident"]),a={manifestUpdates:new Map,reportedErrors:new Map},n=new Map,u=new Map;for(let A of this.project.storedPackages.values()){let p=Array.from(A.peerDependencies.values(),h=>[G.stringifyIdent(h),h.range]);n.set(A.locatorHash,{workspace:null,ident:G.stringifyIdent(A),version:A.version,dependencies:new Map,peerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional!==!0)),optionalPeerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional===!0))})}for(let A of this.project.storedPackages.values()){let p=n.get(A.locatorHash);p.dependencies=new Map(Array.from(A.dependencies.values(),h=>{let E=this.project.storedResolutions.get(h.descriptorHash);if(typeof E>"u")throw new Error("Assertion failed: The resolution should have been registered");let I=n.get(E);if(typeof I>"u")throw new Error("Assertion failed: The package should have been registered");return[G.stringifyIdent(h),I]})),p.dependencies.delete(p.ident)}for(let A of this.project.workspaces){let p=G.stringifyIdent(A.anchoredLocator),h=A.manifest.exportTo({}),E=n.get(A.anchoredLocator.locatorHash);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");let I=(T,L,{caller:U=Xi.getCaller()}={})=>{let z=q2(T),te=qe.getMapWithDefault(a.manifestUpdates,A.cwd),le=qe.getMapWithDefault(te,z),ce=qe.getSetWithDefault(le,L);U!==null&&ce.add(U)},D=T=>I(T,void 0,{caller:Xi.getCaller()}),x=T=>{qe.getArrayWithDefault(a.reportedErrors,A.cwd).push(T)},C=e.insert({cwd:A.relativeCwd,ident:p,manifest:h,pkg:E,set:I,unset:D,error:x});u.set(A,C);for(let T of _t.allDependencies)for(let L of A.manifest[T].values()){let U=G.stringifyIdent(L),z=()=>{I([T,U],void 0,{caller:Xi.getCaller()})},te=ce=>{I([T,U],ce,{caller:Xi.getCaller()})},le=null;if(T!=="peerDependencies"&&(T!=="dependencies"||!A.manifest.devDependencies.has(L.identHash))){let ce=A.anchoredPackage.dependencies.get(L.identHash);if(ce){if(typeof ce>"u")throw new Error("Assertion failed: The dependency should have been registered");let ue=this.project.storedResolutions.get(ce.descriptorHash);if(typeof ue>"u")throw new Error("Assertion failed: The resolution should have been registered");let Ce=n.get(ue);if(typeof Ce>"u")throw new Error("Assertion failed: The package should have been registered");le=Ce}}r.insert({workspace:C,ident:U,range:L.range,type:T,resolution:le,update:te,delete:z,error:x})}}for(let A of this.project.storedPackages.values()){let p=this.project.tryWorkspaceByLocator(A);if(!p)continue;let h=u.get(p);if(typeof h>"u")throw new Error("Assertion failed: The workspace should have been registered");let E=n.get(A.locatorHash);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");E.workspace=h}return{workspaces:e,dependencies:r,packages:o,result:a}}async process(){let e=this.createEnvironment(),r={Yarn:{workspace:a=>e.workspaces.find(a)[0]??null,workspaces:a=>e.workspaces.find(a),dependency:a=>e.dependencies.find(a)[0]??null,dependencies:a=>e.dependencies.find(a),package:a=>e.packages.find(a)[0]??null,packages:a=>e.packages.find(a)}},o=await this.project.loadUserConfig();return o?.constraints?(await o.constraints(r),e.result):null}};Ke();Ke();Gt();var nC=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.query=de.String()}static{this.paths=[["constraints","query"]]}static{this.usage=st.Usage({category:"Constraints-related commands",description:"query the constraints fact database",details:` + This command will output all matches to the given prolog query. + `,examples:[["List all dependencies throughout the workspace","yarn constraints query 'workspace_has_dependency(_, DependencyName, _, _).'"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(K2(),W2)),o=await Je.find(this.context.cwd,this.context.plugins),{project:a}=await Qt.find(o,this.context.cwd),n=await r.find(a),u=this.query;return u.endsWith(".")||(u=`${u}.`),(await Nt.start({configuration:o,json:this.json,stdout:this.context.stdout},async p=>{for await(let h of n.query(u)){let E=Array.from(Object.entries(h)),I=E.length,D=E.reduce((x,[C])=>Math.max(x,C.length),0);for(let x=0;x(K2(),W2)),o=await Je.find(this.context.cwd,this.context.plugins),{project:a}=await Qt.find(o,this.context.cwd),n=await r.find(a);this.context.stdout.write(this.verbose?n.fullSource:n.source)}};Ke();Ke();Gt();j2();var sC=class extends ut{constructor(){super(...arguments);this.fix=de.Boolean("--fix",!1,{description:"Attempt to automatically fix unambiguous issues, following a multi-pass process"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["constraints"]]}static{this.usage=st.Usage({category:"Constraints-related commands",description:"check that the project constraints are met",details:` + This command will run constraints on your project and emit errors for each one that is found but isn't met. If any error is emitted the process will exit with a non-zero exit code. + + If the \`--fix\` flag is used, Yarn will attempt to automatically fix the issues the best it can, following a multi-pass process (with a maximum of 10 iterations). Some ambiguous patterns cannot be autofixed, in which case you'll have to manually specify the right resolution. + + For more information as to how to write constraints, please consult our dedicated page on our website: https://yarnpkg.com/features/constraints. + `,examples:[["Check that all constraints are satisfied","yarn constraints"],["Autofix all unmet constraints","yarn constraints --fix"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);await o.restoreInstallState();let a=await o.loadUserConfig(),n;if(a?.constraints)n=new $E(o);else{let{Constraints:h}=await Promise.resolve().then(()=>(K2(),W2));n=await h.find(o)}let u,A=!1,p=!1;for(let h=this.fix?10:1;h>0;--h){let E=await n.process();if(!E)break;let{changedWorkspaces:I,remainingErrors:D}=Vk(o,E,{fix:this.fix}),x=[];for(let[C,T]of I){let L=C.manifest.indent;C.manifest=new _t,C.manifest.indent=L,C.manifest.load(T),x.push(C.persistManifest())}if(await Promise.all(x),!(I.size>0&&h>1)){u=kme(D,{configuration:r}),A=!1,p=!0;for(let[,C]of D)for(let T of C)T.fixable?A=!0:p=!1}}if(u.children.length===0)return 0;if(A){let h=p?`Those errors can all be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`:`Errors prefixed by '\u2699' can be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`;await Nt.start({configuration:r,stdout:this.context.stdout,includeNames:!1,includeFooter:!1},async E=>{E.reportInfo(0,h),E.reportSeparator()})}return u.children=qe.sortMap(u.children,h=>h.value[1]),As.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1}),1}};j2();var zgt={configuration:{enableConstraintsChecks:{description:"If true, constraints will run during installs",type:"BOOLEAN",default:!1},constraintsPath:{description:"The path of the constraints file.",type:"ABSOLUTE_PATH",default:"./constraints.pro"}},commands:[nC,iC,sC],hooks:{async validateProjectAfterInstall(t,{reportError:e}){if(!t.configuration.get("enableConstraintsChecks"))return;let r=await t.loadUserConfig(),o;if(r?.constraints)o=new $E(t);else{let{Constraints:u}=await Promise.resolve().then(()=>(K2(),W2));o=await u.find(t)}let a=await o.process();if(!a)return;let{remainingErrors:n}=Vk(t,a);if(n.size!==0)if(t.configuration.isCI)for(let[u,A]of n)for(let p of A)e(84,`${pe.pretty(t.configuration,u.anchoredLocator,pe.Type.IDENT)}: ${p.text}`);else e(84,`Constraint check failed; run ${pe.pretty(t.configuration,"yarn constraints",pe.Type.CODE)} for more details`)}}},Jgt=zgt;var l6={};Kt(l6,{CreateCommand:()=>oC,DlxCommand:()=>aC,default:()=>Zgt});Ke();Gt();var oC=class extends ut{constructor(){super(...arguments);this.pkg=de.String("-p,--package",{description:"The package to run the provided command from"});this.quiet=de.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=de.String();this.args=de.Proxy()}static{this.paths=[["create"]]}async execute(){let r=[];this.pkg&&r.push("--package",this.pkg),this.quiet&&r.push("--quiet");let o=this.command.replace(/^(@[^@/]+)(@|$)/,"$1/create$2"),a=G.parseDescriptor(o),n=a.name.match(/^create(-|$)/)?a:a.scope?G.makeIdent(a.scope,`create-${a.name}`):G.makeIdent(null,`create-${a.name}`),u=G.stringifyIdent(n);return a.range!=="unknown"&&(u+=`@${a.range}`),this.cli.run(["dlx",...r,u,...this.args])}};Ke();Ke();Pt();Gt();var aC=class extends ut{constructor(){super(...arguments);this.packages=de.Array("-p,--package",{description:"The package(s) to install before running the command"});this.quiet=de.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=de.String();this.args=de.Proxy()}static{this.paths=[["dlx"]]}static{this.usage=st.Usage({description:"run a package in a temporary environment",details:"\n This command will install a package within a temporary environment, and run its binary script if it contains any. The binary will run within the current cwd.\n\n By default Yarn will download the package named `command`, but this can be changed through the use of the `-p,--package` flag which will instruct Yarn to still run the same command but from a different package.\n\n Using `yarn dlx` as a replacement of `yarn add` isn't recommended, as it makes your project non-deterministic (Yarn doesn't keep track of the packages installed through `dlx` - neither their name, nor their version).\n ",examples:[["Use create-react-app to create a new React app","yarn dlx create-react-app ./my-app"],["Install multiple packages for a single command",`yarn dlx -p typescript -p ts-node ts-node --transpile-only -e "console.log('hello!')"`]]})}async execute(){return Je.telemetry=null,await ae.mktempPromise(async r=>{let o=K.join(r,`dlx-${process.pid}`);await ae.mkdirPromise(o),await ae.writeFilePromise(K.join(o,"package.json"),`{} +`),await ae.writeFilePromise(K.join(o,"yarn.lock"),"");let a=K.join(o,".yarnrc.yml"),n=await Je.findProjectCwd(this.context.cwd),A={enableGlobalCache:!(await Je.find(this.context.cwd,null,{strict:!1})).get("enableGlobalCache"),enableTelemetry:!1,logFilters:[{code:zu(68),level:pe.LogLevel.Discard}]},p=n!==null?K.join(n,".yarnrc.yml"):null;p!==null&&ae.existsSync(p)?(await ae.copyFilePromise(p,a),await Je.updateConfiguration(o,L=>{let U=qe.toMerged(L,A);return Array.isArray(L.plugins)&&(U.plugins=L.plugins.map(z=>{let te=typeof z=="string"?z:z.path,le=Ae.isAbsolute(te)?te:Ae.resolve(Ae.fromPortablePath(n),te);return typeof z=="string"?le:{path:le,spec:z.spec}})),U})):await ae.writeJsonPromise(a,A);let h=this.packages??[this.command],E=G.parseDescriptor(this.command).name,I=await this.cli.run(["add","--fixed","--",...h],{cwd:o,quiet:this.quiet});if(I!==0)return I;this.quiet||this.context.stdout.write(` +`);let D=await Je.find(o,this.context.plugins),{project:x,workspace:C}=await Qt.find(D,o);if(C===null)throw new or(x.cwd,o);await x.restoreInstallState();let T=await hn.getWorkspaceAccessibleBinaries(C);return T.has(E)===!1&&T.size===1&&typeof this.packages>"u"&&(E=Array.from(T)[0][0]),await hn.executeWorkspaceAccessibleBinary(C,E,this.args,{packageAccessibleBinaries:T,cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})})}};var Xgt={commands:[oC,aC]},Zgt=Xgt;var A6={};Kt(A6,{ExecFetcher:()=>z2,ExecResolver:()=>J2,default:()=>tdt,execUtils:()=>Zk});Ke();Ke();Pt();var hA="exec:";var Zk={};Kt(Zk,{loadGeneratorFile:()=>V2,makeLocator:()=>u6,makeSpec:()=>rye,parseSpec:()=>c6});Ke();Pt();function c6(t){let{params:e,selector:r}=G.parseRange(t),o=Ae.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:o}}function rye({parentLocator:t,path:e,generatorHash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function u6(t,{parentLocator:e,path:r,generatorHash:o,protocol:a}){return G.makeLocator(t,rye({parentLocator:e,path:r,generatorHash:o,protocol:a}))}async function V2(t,e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(t,{protocol:e}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath)}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.join(u.prefixPath,a);return await A.readFilePromise(p,"utf8")}var z2=class{supports(e,r){return!!e.reference.startsWith(hA)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:hA});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){let o=await V2(e.reference,hA,r);return ae.mktempPromise(async a=>{let n=K.join(a,"generator.js");return await ae.writeFilePromise(n,o),ae.mktempPromise(async u=>{if(await this.generatePackage(u,e,n,r),!ae.existsSync(K.join(u,"build")))throw new Error("The script should have generated a build directory");return await $i.makeArchiveFromDirectory(K.join(u,"build"),{prefixPath:G.getIdentVendorPath(e),compressionLevel:r.project.configuration.get("compressionLevel")})})})}async generatePackage(e,r,o,a){return await ae.mktempPromise(async n=>{let u=await hn.makeScriptEnv({project:a.project,binFolder:n}),A=K.join(e,"runtime.js");return await ae.mktempPromise(async p=>{let h=K.join(p,"buildfile.log"),E=K.join(e,"generator"),I=K.join(e,"build");await ae.mkdirPromise(E),await ae.mkdirPromise(I);let D={tempDir:Ae.fromPortablePath(E),buildDir:Ae.fromPortablePath(I),locator:G.stringifyLocator(r)};await ae.writeFilePromise(A,` + // Expose 'Module' as a global variable + Object.defineProperty(global, 'Module', { + get: () => require('module'), + configurable: true, + enumerable: false, + }); + + // Expose non-hidden built-in modules as global variables + for (const name of Module.builtinModules.filter((name) => name !== 'module' && !name.startsWith('_'))) { + Object.defineProperty(global, name, { + get: () => require(name), + configurable: true, + enumerable: false, + }); + } + + // Expose the 'execEnv' global variable + Object.defineProperty(global, 'execEnv', { + value: { + ...${JSON.stringify(D)}, + }, + enumerable: true, + }); + `);let x=u.NODE_OPTIONS||"",C=/\s*--require\s+\S*\.pnp\.c?js\s*/g;x=x.replace(C," ").trim(),u.NODE_OPTIONS=x;let{stdout:T,stderr:L}=a.project.configuration.getSubprocessStreams(h,{header:`# This file contains the result of Yarn generating a package (${G.stringifyLocator(r)}) +`,prefix:G.prettyLocator(a.project.configuration,r),report:a.report}),{code:U}=await Hr.pipevp(process.execPath,["--require",Ae.fromPortablePath(A),Ae.fromPortablePath(o),G.stringifyIdent(r)],{cwd:e,env:u,stdin:null,stdout:T,stderr:L});if(U!==0)throw ae.detachTemp(p),new Error(`Package generation failed (exit code ${U}, logs can be found here: ${pe.pretty(a.project.configuration,h,pe.Type.PATH)})`)})})}};Ke();Ke();var $gt=2,J2=class{supportsDescriptor(e,r){return!!e.range.startsWith(hA)}supportsLocator(e,r){return!!e.reference.startsWith(hA)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=c6(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=await V2(G.makeRange({protocol:hA,source:a,selector:a,params:{locator:G.stringifyLocator(n)}}),hA,o.fetchOptions),A=xn.makeHash(`${$gt}`,u).slice(0,6);return[u6(e,{parentLocator:n,path:a,generatorHash:A,protocol:hA})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var edt={fetchers:[z2],resolvers:[J2]},tdt=edt;var p6={};Kt(p6,{FileFetcher:()=>eB,FileResolver:()=>tB,TarballFileFetcher:()=>rB,TarballFileResolver:()=>nB,default:()=>idt,fileUtils:()=>$g});Ke();Pt();var lC=/^(?:[a-zA-Z]:[\\/]|\.{0,2}\/)/,X2=/^[^?]*\.(?:tar\.gz|tgz)(?:::.*)?$/,_i="file:";var $g={};Kt($g,{fetchArchiveFromLocator:()=>$2,makeArchiveFromLocator:()=>$k,makeBufferFromLocator:()=>f6,makeLocator:()=>cC,makeSpec:()=>nye,parseSpec:()=>Z2});Ke();Pt();function Z2(t){let{params:e,selector:r}=G.parseRange(t),o=Ae.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:o}}function nye({parentLocator:t,path:e,hash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function cC(t,{parentLocator:e,path:r,hash:o,protocol:a}){return G.makeLocator(t,nye({parentLocator:e,path:r,hash:o,protocol:a}))}async function $2(t,e){let{parentLocator:r,path:o}=G.parseFileStyleRange(t.reference,{protocol:_i}),a=K.isAbsolute(o)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await e.fetcher.fetch(r,e),n=a.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,a.localPath)}:a;a!==n&&a.releaseFs&&a.releaseFs();let u=n.packageFs,A=K.join(n.prefixPath,o);return await qe.releaseAfterUseAsync(async()=>await u.readFilePromise(A),n.releaseFs)}async function $k(t,{protocol:e,fetchOptions:r,inMemory:o=!1}){let{parentLocator:a,path:n}=G.parseFileStyleRange(t.reference,{protocol:e}),u=K.isAbsolute(n)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(a,r),A=u.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,u.localPath)}:u;u!==A&&u.releaseFs&&u.releaseFs();let p=A.packageFs,h=K.join(A.prefixPath,n);return await qe.releaseAfterUseAsync(async()=>await $i.makeArchiveFromDirectory(h,{baseFs:p,prefixPath:G.getIdentVendorPath(t),compressionLevel:r.project.configuration.get("compressionLevel"),inMemory:o}),A.releaseFs)}async function f6(t,{protocol:e,fetchOptions:r}){return(await $k(t,{protocol:e,fetchOptions:r,inMemory:!0})).getBufferAndClose()}var eB=class{supports(e,r){return!!e.reference.startsWith(_i)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:_i});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){return $k(e,{protocol:_i,fetchOptions:r})}};Ke();Ke();var rdt=2,tB=class{supportsDescriptor(e,r){return e.range.match(lC)?!0:!!e.range.startsWith(_i)}supportsLocator(e,r){return!!e.reference.startsWith(_i)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return lC.test(e.range)&&(e=G.makeDescriptor(e,`${_i}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=Z2(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=await f6(G.makeLocator(e,G.makeRange({protocol:_i,source:a,selector:a,params:{locator:G.stringifyLocator(n)}})),{protocol:_i,fetchOptions:o.fetchOptions}),A=xn.makeHash(`${rdt}`,u).slice(0,6);return[cC(e,{parentLocator:n,path:a,hash:A,protocol:_i})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};Ke();var rB=class{supports(e,r){return X2.test(e.reference)?!!e.reference.startsWith(_i):!1}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromDisk(e,r){let o=await $2(e,r);return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();Ke();Ke();var nB=class{supportsDescriptor(e,r){return X2.test(e.range)?!!(e.range.startsWith(_i)||lC.test(e.range)):!1}supportsLocator(e,r){return X2.test(e.reference)?!!e.reference.startsWith(_i):!1}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return lC.test(e.range)&&(e=G.makeDescriptor(e,`${_i}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=Z2(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=cC(e,{parentLocator:n,path:a,hash:"",protocol:_i}),A=await $2(u,o.fetchOptions),p=xn.makeHash(A).slice(0,6);return[cC(e,{parentLocator:n,path:a,hash:p,protocol:_i})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var ndt={fetchers:[rB,eB],resolvers:[nB,tB]},idt=ndt;var d6={};Kt(d6,{GithubFetcher:()=>iB,default:()=>odt,githubUtils:()=>eQ});Ke();Pt();var eQ={};Kt(eQ,{invalidGithubUrlMessage:()=>oye,isGithubUrl:()=>h6,parseGithubUrl:()=>g6});var iye=et(ve("querystring")),sye=[/^https?:\/\/(?:([^/]+?)@)?github.com\/([^/#]+)\/([^/#]+)\/tarball\/([^/#]+)(?:#(.*))?$/,/^https?:\/\/(?:([^/]+?)@)?github.com\/([^/#]+)\/([^/#]+?)(?:\.git)?(?:#(.*))?$/];function h6(t){return t?sye.some(e=>!!t.match(e)):!1}function g6(t){let e;for(let A of sye)if(e=t.match(A),e)break;if(!e)throw new Error(oye(t));let[,r,o,a,n="master"]=e,{commit:u}=iye.default.parse(n);return n=u||n.replace(/[^:]*:/,""),{auth:r,username:o,reponame:a,treeish:n}}function oye(t){return`Input cannot be parsed as a valid GitHub URL ('${t}').`}var iB=class{supports(e,r){return!!h6(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from GitHub`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await on.get(this.getLocatorUrl(e,r),{configuration:r.project.configuration});return await ae.mktempPromise(async a=>{let n=new En(a);await $i.extractArchiveTo(o,n,{stripComponents:1});let u=ra.splitRepoUrl(e.reference),A=K.join(a,"package.tgz");await hn.prepareExternalProject(a,A,{configuration:r.project.configuration,report:r.report,workspace:u.extra.workspace,locator:e});let p=await ae.readFilePromise(A);return await $i.convertToZip(p,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})})}getLocatorUrl(e,r){let{auth:o,username:a,reponame:n,treeish:u}=g6(e.reference);return`https://${o?`${o}@`:""}github.com/${a}/${n}/archive/${u}.tar.gz`}};var sdt={hooks:{async fetchHostedRepository(t,e,r){if(t!==null)return t;let o=new iB;if(!o.supports(e,r))return null;try{return await o.fetch(e,r)}catch{return null}}}},odt=sdt;var m6={};Kt(m6,{TarballHttpFetcher:()=>oB,TarballHttpResolver:()=>aB,default:()=>ldt});Ke();function sB(t){let e;try{e=new URL(t)}catch{return!1}return!(e.protocol!=="http:"&&e.protocol!=="https:"||!e.pathname.match(/(\.tar\.gz|\.tgz|\/[^.]+)$/))}var oB=class{supports(e,r){return sB(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await on.get(e.reference,{configuration:r.project.configuration});return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();Ke();var aB=class{supportsDescriptor(e,r){return sB(e.range)}supportsLocator(e,r){return sB(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[G.convertDescriptorToLocator(e)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var adt={fetchers:[oB],resolvers:[aB]},ldt=adt;var y6={};Kt(y6,{InitCommand:()=>uC,default:()=>udt});Ke();Ke();Pt();Gt();var uC=class extends ut{constructor(){super(...arguments);this.private=de.Boolean("-p,--private",!1,{description:"Initialize a private package"});this.workspace=de.Boolean("-w,--workspace",!1,{description:"Initialize a workspace root with a `packages/` directory"});this.install=de.String("-i,--install",!1,{tolerateBoolean:!0,description:"Initialize a package with a specific bundle that will be locked in the project"});this.name=de.String("-n,--name",{description:"Initialize a package with the given name"});this.usev2=de.Boolean("-2",!1,{hidden:!0});this.yes=de.Boolean("-y,--yes",{hidden:!0})}static{this.paths=[["init"]]}static{this.usage=st.Usage({description:"create a new package",details:"\n This command will setup a new package in your local directory.\n\n If the `-p,--private` or `-w,--workspace` options are set, the package will be private by default.\n\n If the `-w,--workspace` option is set, the package will be configured to accept a set of workspaces in the `packages/` directory.\n\n If the `-i,--install` option is given a value, Yarn will first download it using `yarn set version` and only then forward the init call to the newly downloaded bundle. Without arguments, the downloaded bundle will be `latest`.\n\n The initial settings of the manifest can be changed by using the `initScope` and `initFields` configuration values. Additionally, Yarn will generate an EditorConfig file whose rules can be altered via `initEditorConfig`, and will initialize a Git repository in the current directory.\n ",examples:[["Create a new package in the local directory","yarn init"],["Create a new private package in the local directory","yarn init -p"],["Create a new package and store the Yarn release inside","yarn init -i=latest"],["Create a new private package and defines it as a workspace root","yarn init -w"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=typeof this.install=="string"?this.install:this.usev2||this.install===!0?"latest":null;return o!==null?await this.executeProxy(r,o):await this.executeRegular(r)}async executeProxy(r,o){if(r.projectCwd!==null&&r.projectCwd!==this.context.cwd)throw new ot("Cannot use the --install flag from within a project subdirectory");ae.existsSync(this.context.cwd)||await ae.mkdirPromise(this.context.cwd,{recursive:!0});let a=K.join(this.context.cwd,mr.lockfile);ae.existsSync(a)||await ae.writeFilePromise(a,"");let n=await this.cli.run(["set","version",o],{quiet:!0});if(n!==0)return n;let u=[];return this.private&&u.push("-p"),this.workspace&&u.push("-w"),this.name&&u.push(`-n=${this.name}`),this.yes&&u.push("-y"),await ae.mktempPromise(async A=>{let{code:p}=await Hr.pipevp("yarn",["init",...u],{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,env:await hn.makeScriptEnv({binFolder:A})});return p})}async executeRegular(r){let o=null;try{o=(await Qt.find(r,this.context.cwd)).project}catch{o=null}ae.existsSync(this.context.cwd)||await ae.mkdirPromise(this.context.cwd,{recursive:!0});let a=await _t.tryFind(this.context.cwd),n=a??new _t,u=Object.fromEntries(r.get("initFields").entries());n.load(u),n.name=n.name??G.makeIdent(r.get("initScope"),this.name??K.basename(this.context.cwd)),n.packageManager=nn&&qe.isTaggedYarnVersion(nn)?`yarn@${nn}`:null,(!a&&this.workspace||this.private)&&(n.private=!0),this.workspace&&n.workspaceDefinitions.length===0&&(await ae.mkdirPromise(K.join(this.context.cwd,"packages"),{recursive:!0}),n.workspaceDefinitions=[{pattern:"packages/*"}]);let A={};n.exportTo(A);let p=K.join(this.context.cwd,_t.fileName);await ae.changeFilePromise(p,`${JSON.stringify(A,null,2)} +`,{automaticNewlines:!0});let h=[p],E=K.join(this.context.cwd,"README.md");if(ae.existsSync(E)||(await ae.writeFilePromise(E,`# ${G.stringifyIdent(n.name)} +`),h.push(E)),!o||o.cwd===this.context.cwd){let I=K.join(this.context.cwd,mr.lockfile);ae.existsSync(I)||(await ae.writeFilePromise(I,""),h.push(I));let x=[".yarn/*","!.yarn/patches","!.yarn/plugins","!.yarn/releases","!.yarn/sdks","!.yarn/versions","","# Swap the comments on the following lines if you wish to use zero-installs","# In that case, don't forget to run `yarn config set enableGlobalCache false`!","# Documentation here: https://yarnpkg.com/features/caching#zero-installs","","#!.yarn/cache",".pnp.*"].map(ce=>`${ce} +`).join(""),C=K.join(this.context.cwd,".gitignore");ae.existsSync(C)||(await ae.writeFilePromise(C,x),h.push(C));let L=["/.yarn/** linguist-vendored","/.yarn/releases/* binary","/.yarn/plugins/**/* binary","/.pnp.* binary linguist-generated"].map(ce=>`${ce} +`).join(""),U=K.join(this.context.cwd,".gitattributes");ae.existsSync(U)||(await ae.writeFilePromise(U,L),h.push(U));let z={"*":{endOfLine:"lf",insertFinalNewline:!0},"*.{js,json,yml}":{charset:"utf-8",indentStyle:"space",indentSize:2}};qe.mergeIntoTarget(z,r.get("initEditorConfig"));let te=`root = true +`;for(let[ce,ue]of Object.entries(z)){te+=` +[${ce}] +`;for(let[Ce,he]of Object.entries(ue)){let De=Ce.replace(/[A-Z]/g,Ee=>`_${Ee.toLowerCase()}`);te+=`${De} = ${he} +`}}let le=K.join(this.context.cwd,".editorconfig");ae.existsSync(le)||(await ae.writeFilePromise(le,te),h.push(le)),await this.cli.run(["install"],{quiet:!0}),ae.existsSync(K.join(this.context.cwd,".git"))||(await Hr.execvp("git",["init"],{cwd:this.context.cwd}),await Hr.execvp("git",["add","--",...h],{cwd:this.context.cwd}),await Hr.execvp("git",["commit","--allow-empty","-m","First commit"],{cwd:this.context.cwd}))}}};var cdt={configuration:{initScope:{description:"Scope used when creating packages via the init command",type:"STRING",default:null},initFields:{description:"Additional fields to set when creating packages via the init command",type:"MAP",valueDefinition:{description:"",type:"ANY"}},initEditorConfig:{description:"Extra rules to define in the generator editorconfig",type:"MAP",valueDefinition:{description:"",type:"ANY"}}},commands:[uC]},udt=cdt;var mj={};Kt(mj,{SearchCommand:()=>bC,UpgradeInteractiveCommand:()=>xC,default:()=>Uwt});Ke();var lye=et(ve("os"));function AC({stdout:t}){if(lye.default.endianness()==="BE")throw new Error("Interactive commands cannot be used on big-endian systems because ink depends on yoga-layout-prebuilt which only supports little-endian architectures");if(!t.isTTY)throw new Error("Interactive commands can only be used inside a TTY environment")}Gt();var CEe=et(L6()),M6={appId:"OFCNCOG2CU",apiKey:"6fe4476ee5a1832882e326b506d14126",indexName:"npm-search"},ayt=(0,CEe.default)(M6.appId,M6.apiKey).initIndex(M6.indexName),O6=async(t,e=0)=>await ayt.search(t,{analyticsTags:["yarn-plugin-interactive-tools"],attributesToRetrieve:["name","version","owner","repository","humanDownloadsLast30Days"],page:e,hitsPerPage:10});var sv=["regular","dev","peer"],bC=class extends ut{static{this.paths=[["search"]]}static{this.usage=st.Usage({category:"Interactive commands",description:"open the search interface",details:` + This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry. + `,examples:[["Open the search window","yarn search"]]})}async execute(){AC(this.context);let{Gem:e}=await Promise.resolve().then(()=>(UQ(),oj)),{ScrollableItems:r}=await Promise.resolve().then(()=>(jQ(),qQ)),{useKeypress:o}=await Promise.resolve().then(()=>(rv(),xIe)),{useMinistore:a}=await Promise.resolve().then(()=>(fj(),Aj)),{renderForm:n}=await Promise.resolve().then(()=>(KQ(),WQ)),{default:u}=await Promise.resolve().then(()=>et(UIe())),{Box:A,Text:p}=await Promise.resolve().then(()=>et(ac())),{default:h,useEffect:E,useState:I}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),x=()=>h.createElement(A,{flexDirection:"row"},h.createElement(A,{flexDirection:"column",width:48},h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},""),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to move between packages.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to select a package.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," again to change the target."))),h.createElement(A,{flexDirection:"column"},h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to install the selected packages.")),h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to abort.")))),C=()=>h.createElement(h.Fragment,null,h.createElement(A,{width:15},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Owner")),h.createElement(A,{width:11},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Version")),h.createElement(A,{width:10},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Downloads"))),T=()=>h.createElement(A,{width:17},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Target")),L=({hit:he,active:De})=>{let[Ee,g]=a(he.name,null);o({active:De},(fe,ie)=>{if(ie.name!=="space")return;if(!Ee){g(sv[0]);return}let Z=sv.indexOf(Ee)+1;Z===sv.length?g(null):g(sv[Z])},[Ee,g]);let me=G.parseIdent(he.name),we=G.prettyIdent(D,me);return h.createElement(A,null,h.createElement(A,{width:45},h.createElement(p,{bold:!0,wrap:"wrap"},we)),h.createElement(A,{width:14,marginLeft:1},h.createElement(p,{bold:!0,wrap:"truncate"},he.owner.name)),h.createElement(A,{width:10,marginLeft:1},h.createElement(p,{italic:!0,wrap:"truncate"},he.version)),h.createElement(A,{width:16,marginLeft:1},h.createElement(p,null,he.humanDownloadsLast30Days)))},U=({name:he,active:De})=>{let[Ee]=a(he,null),g=G.parseIdent(he);return h.createElement(A,null,h.createElement(A,{width:47},h.createElement(p,{bold:!0}," - ",G.prettyIdent(D,g))),sv.map(me=>h.createElement(A,{key:me,width:14,marginLeft:1},h.createElement(p,null," ",h.createElement(e,{active:Ee===me})," ",h.createElement(p,{bold:!0},me)))))},z=()=>h.createElement(A,{marginTop:1},h.createElement(p,null,"Powered by Algolia.")),le=await n(({useSubmit:he})=>{let De=a();he(De);let Ee=Array.from(De.keys()).filter(q=>De.get(q)!==null),[g,me]=I(""),[we,fe]=I(0),[ie,Z]=I([]),xe=q=>{q.match(/\t| /)||me(q)},Re=async()=>{fe(0);let q=await O6(g);q.query===g&&Z(q.hits)},gt=async()=>{let q=await O6(g,we+1);q.query===g&&q.page-1===we&&(fe(q.page),Z([...ie,...q.hits]))};return E(()=>{g?Re():Z([])},[g]),h.createElement(A,{flexDirection:"column"},h.createElement(x,null),h.createElement(A,{flexDirection:"row",marginTop:1},h.createElement(p,{bold:!0},"Search: "),h.createElement(A,{width:41},h.createElement(u,{value:g,onChange:xe,placeholder:"i.e. babel, webpack, react...",showCursor:!1})),h.createElement(C,null)),ie.length?h.createElement(r,{radius:2,loop:!1,children:ie.map(q=>h.createElement(L,{key:q.name,hit:q,active:!1})),willReachEnd:gt}):h.createElement(p,{color:"gray"},"Start typing..."),h.createElement(A,{flexDirection:"row",marginTop:1},h.createElement(A,{width:49},h.createElement(p,{bold:!0},"Selected:")),h.createElement(T,null)),Ee.length?Ee.map(q=>h.createElement(U,{key:q,name:q,active:!1})):h.createElement(p,{color:"gray"},"No selected packages..."),h.createElement(z,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof le>"u")return 1;let ce=Array.from(le.keys()).filter(he=>le.get(he)==="regular"),ue=Array.from(le.keys()).filter(he=>le.get(he)==="dev"),Ce=Array.from(le.keys()).filter(he=>le.get(he)==="peer");return ce.length&&await this.cli.run(["add",...ce]),ue.length&&await this.cli.run(["add","--dev",...ue]),Ce&&await this.cli.run(["add","--peer",...Ce]),0}};Ke();Gt();n8();var WIe=et(ni()),YIe=/^((?:[\^~]|>=?)?)([0-9]+)(\.[0-9]+)(\.[0-9]+)((?:-\S+)?)$/,KIe=(t,e)=>t.length>0?[t.slice(0,e)].concat(KIe(t.slice(e),e)):[],xC=class extends ut{static{this.paths=[["upgrade-interactive"]]}static{this.usage=st.Usage({category:"Interactive commands",description:"open the upgrade interface",details:` + This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade. + `,examples:[["Open the upgrade window","yarn upgrade-interactive"]]})}async execute(){AC(this.context);let{ItemOptions:e}=await Promise.resolve().then(()=>(GIe(),jIe)),{Pad:r}=await Promise.resolve().then(()=>(dj(),qIe)),{ScrollableItems:o}=await Promise.resolve().then(()=>(jQ(),qQ)),{useMinistore:a}=await Promise.resolve().then(()=>(fj(),Aj)),{renderForm:n}=await Promise.resolve().then(()=>(KQ(),WQ)),{Box:u,Text:A}=await Promise.resolve().then(()=>et(ac())),{default:p,useEffect:h,useRef:E,useState:I}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),{project:x,workspace:C}=await Qt.find(D,this.context.cwd),T=await Yr.find(D);if(!C)throw new or(x.cwd,this.context.cwd);await x.restoreInstallState({restoreResolutions:!1});let L=this.context.stdout.rows-7,U=(me,we)=>{let fe=$pe(me,we),ie="";for(let Z of fe)Z.added?ie+=pe.pretty(D,Z.value,"green"):Z.removed||(ie+=Z.value);return ie},z=(me,we)=>{if(me===we)return we;let fe=G.parseRange(me),ie=G.parseRange(we),Z=fe.selector.match(YIe),xe=ie.selector.match(YIe);if(!Z||!xe)return U(me,we);let Re=["gray","red","yellow","green","magenta"],gt=null,q="";for(let nt=1;nt{let ie=await nu.fetchDescriptorFrom(me,fe,{project:x,cache:T,preserveModifier:we,workspace:C});return ie!==null?ie.range:me.range},le=async me=>{let we=WIe.default.valid(me.range)?`^${me.range}`:me.range,[fe,ie]=await Promise.all([te(me,me.range,we).catch(()=>null),te(me,me.range,"latest").catch(()=>null)]),Z=[{value:null,label:me.range}];return fe&&fe!==me.range?Z.push({value:fe,label:z(me.range,fe)}):Z.push({value:null,label:""}),ie&&ie!==fe&&ie!==me.range?Z.push({value:ie,label:z(me.range,ie)}):Z.push({value:null,label:""}),Z},ce=()=>p.createElement(u,{flexDirection:"row"},p.createElement(u,{flexDirection:"column",width:49},p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},""),"/",p.createElement(A,{bold:!0,color:"cyanBright"},"")," to select packages.")),p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},""),"/",p.createElement(A,{bold:!0,color:"cyanBright"},"")," to select versions."))),p.createElement(u,{flexDirection:"column"},p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"")," to install.")),p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"")," to abort.")))),ue=()=>p.createElement(u,{flexDirection:"row",paddingTop:1,paddingBottom:1},p.createElement(u,{width:50},p.createElement(A,{bold:!0},p.createElement(A,{color:"greenBright"},"?")," Pick the packages you want to upgrade.")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Current")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Range")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Latest"))),Ce=({active:me,descriptor:we,suggestions:fe})=>{let[ie,Z]=a(we.descriptorHash,null),xe=G.stringifyIdent(we),Re=Math.max(0,45-xe.length);return p.createElement(p.Fragment,null,p.createElement(u,null,p.createElement(u,{width:45},p.createElement(A,{bold:!0},G.prettyIdent(D,we)),p.createElement(r,{active:me,length:Re})),p.createElement(e,{active:me,options:fe,value:ie,skewer:!0,onChange:Z,sizes:[17,17,17]})))},he=({dependencies:me})=>{let[we,fe]=I(me.map(()=>null)),ie=E(!0),Z=async xe=>{let Re=await le(xe);return Re.filter(gt=>gt.label!=="").length<=1?null:{descriptor:xe,suggestions:Re}};return h(()=>()=>{ie.current=!1},[]),h(()=>{let xe=Math.trunc(L*1.75),Re=me.slice(0,xe),gt=me.slice(xe),q=KIe(gt,L),nt=Re.map(Z).reduce(async(Ne,Te)=>{await Ne;let ke=await Te;ke!==null&&ie.current&&fe(Ve=>{let Se=Ve.findIndex(He=>He===null),tt=[...Ve];return tt[Se]=ke,tt})},Promise.resolve());q.reduce((Ne,Te)=>Promise.all(Te.map(ke=>Promise.resolve().then(()=>Z(ke)))).then(async ke=>{ke=ke.filter(Ve=>Ve!==null),await Ne,ie.current&&fe(Ve=>{let Se=Ve.findIndex(tt=>tt===null);return Ve.slice(0,Se).concat(ke).concat(Ve.slice(Se+ke.length))})}),nt).then(()=>{ie.current&&fe(Ne=>Ne.filter(Te=>Te!==null))})},[]),we.length?p.createElement(o,{radius:L>>1,children:we.map((xe,Re)=>xe!==null?p.createElement(Ce,{key:Re,active:!1,descriptor:xe.descriptor,suggestions:xe.suggestions}):p.createElement(A,{key:Re},"Loading..."))}):p.createElement(A,null,"No upgrades found")},Ee=await n(({useSubmit:me})=>{me(a());let we=new Map;for(let ie of x.workspaces)for(let Z of["dependencies","devDependencies"])for(let xe of ie.manifest[Z].values())x.tryWorkspaceByDescriptor(xe)===null&&(xe.range.startsWith("link:")||we.set(xe.descriptorHash,xe));let fe=qe.sortMap(we.values(),ie=>G.stringifyDescriptor(ie));return p.createElement(u,{flexDirection:"column"},p.createElement(ce,null),p.createElement(ue,null),p.createElement(he,{dependencies:fe}))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof Ee>"u")return 1;let g=!1;for(let me of x.workspaces)for(let we of["dependencies","devDependencies"]){let fe=me.manifest[we];for(let ie of fe.values()){let Z=Ee.get(ie.descriptorHash);typeof Z<"u"&&Z!==null&&(fe.set(ie.identHash,G.makeDescriptor(ie,Z)),g=!0)}}return g?await x.installWithNewReport({quiet:this.context.quiet,stdout:this.context.stdout},{cache:T}):0}};var Owt={commands:[bC,xC]},Uwt=Owt;var yj={};Kt(yj,{LinkFetcher:()=>av,LinkResolver:()=>lv,PortalFetcher:()=>cv,PortalResolver:()=>uv,default:()=>Hwt});Ke();Pt();var Zf="portal:",$f="link:";var av=class{supports(e,r){return!!e.reference.startsWith($f)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:$f});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:$f}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath),localPath:Bt.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new En(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,discardFromLookup:!0,localPath:p}:{packageFs:new Gu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,discardFromLookup:!0}}};Ke();Pt();var lv=class{supportsDescriptor(e,r){return!!e.range.startsWith($f)}supportsLocator(e,r){return!!e.reference.startsWith($f)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice($f.length);return[G.makeLocator(e,`${$f}${Ae.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){return{...e,version:"0.0.0",languageName:r.project.configuration.get("defaultLanguageName"),linkType:"SOFT",conditions:null,dependencies:new Map,peerDependencies:new Map,dependenciesMeta:new Map,peerDependenciesMeta:new Map,bin:new Map}}};Ke();Pt();var cv=class{supports(e,r){return!!e.reference.startsWith(Zf)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath),localPath:Bt.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new En(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,localPath:p}:{packageFs:new Gu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot}}};Ke();Ke();Pt();var uv=class{supportsDescriptor(e,r){return!!e.range.startsWith(Zf)}supportsLocator(e,r){return!!e.reference.startsWith(Zf)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Zf.length);return[G.makeLocator(e,`${Zf}${Ae.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"SOFT",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var _wt={fetchers:[av,cv],resolvers:[lv,uv]},Hwt=_wt;var t5={};Kt(t5,{NodeModulesLinker:()=>Dv,NodeModulesMode:()=>Xj,PnpLooseLinker:()=>Pv,default:()=>n1t});Pt();Ke();Pt();Pt();var Cj=(t,e)=>`${t}@${e}`,VIe=(t,e)=>{let r=e.indexOf("#"),o=r>=0?e.substring(r+1):e;return Cj(t,o)};var JIe=(t,e={})=>{let r=e.debugLevel||Number(process.env.NM_DEBUG_LEVEL||-1),o=e.check||r>=9,a=e.hoistingLimits||new Map,n={check:o,debugLevel:r,hoistingLimits:a,fastLookupPossible:!0},u;n.debugLevel>=0&&(u=Date.now());let A=Vwt(t,n),p=!1,h=0;do{let E=wj(A,[A],new Set([A.locator]),new Map,n);p=E.anotherRoundNeeded||E.isGraphChanged,n.fastLookupPossible=!1,h++}while(p);if(n.debugLevel>=0&&console.log(`hoist time: ${Date.now()-u}ms, rounds: ${h}`),n.debugLevel>=1){let E=Av(A);if(wj(A,[A],new Set([A.locator]),new Map,n).isGraphChanged)throw new Error(`The hoisting result is not terminal, prev tree: +${E}, next tree: +${Av(A)}`);let D=XIe(A);if(D)throw new Error(`${D}, after hoisting finished: +${Av(A)}`)}return n.debugLevel>=2&&console.log(Av(A)),zwt(A)},qwt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=n=>{if(!o.has(n)){o.add(n);for(let u of n.hoistedDependencies.values())r.set(u.name,u);for(let u of n.dependencies.values())n.peerNames.has(u.name)||a(u)}};return a(e),r},jwt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=new Set,n=(u,A)=>{if(o.has(u))return;o.add(u);for(let h of u.hoistedDependencies.values())if(!A.has(h.name)){let E;for(let I of t)E=I.dependencies.get(h.name),E&&r.set(E.name,E)}let p=new Set;for(let h of u.dependencies.values())p.add(h.name);for(let h of u.dependencies.values())u.peerNames.has(h.name)||n(h,p)};return n(e,a),r},zIe=(t,e)=>{if(e.decoupled)return e;let{name:r,references:o,ident:a,locator:n,dependencies:u,originalDependencies:A,hoistedDependencies:p,peerNames:h,reasons:E,isHoistBorder:I,hoistPriority:D,dependencyKind:x,hoistedFrom:C,hoistedTo:T}=e,L={name:r,references:new Set(o),ident:a,locator:n,dependencies:new Map(u),originalDependencies:new Map(A),hoistedDependencies:new Map(p),peerNames:new Set(h),reasons:new Map(E),decoupled:!0,isHoistBorder:I,hoistPriority:D,dependencyKind:x,hoistedFrom:new Map(C),hoistedTo:new Map(T)},U=L.dependencies.get(r);return U&&U.ident==L.ident&&L.dependencies.set(r,L),t.dependencies.set(L.name,L),L},Gwt=(t,e)=>{let r=new Map([[t.name,[t.ident]]]);for(let a of t.dependencies.values())t.peerNames.has(a.name)||r.set(a.name,[a.ident]);let o=Array.from(e.keys());o.sort((a,n)=>{let u=e.get(a),A=e.get(n);if(A.hoistPriority!==u.hoistPriority)return A.hoistPriority-u.hoistPriority;{let p=u.dependents.size+u.peerDependents.size;return A.dependents.size+A.peerDependents.size-p}});for(let a of o){let n=a.substring(0,a.indexOf("@",1)),u=a.substring(n.length+1);if(!t.peerNames.has(n)){let A=r.get(n);A||(A=[],r.set(n,A)),A.indexOf(u)<0&&A.push(u)}}return r},Ej=t=>{let e=new Set,r=(o,a=new Set)=>{if(!a.has(o)){a.add(o);for(let n of o.peerNames)if(!t.peerNames.has(n)){let u=t.dependencies.get(n);u&&!e.has(u)&&r(u,a)}e.add(o)}};for(let o of t.dependencies.values())t.peerNames.has(o.name)||r(o);return e},wj=(t,e,r,o,a,n=new Set)=>{let u=e[e.length-1];if(n.has(u))return{anotherRoundNeeded:!1,isGraphChanged:!1};n.add(u);let A=Jwt(u),p=Gwt(u,A),h=t==u?new Map:a.fastLookupPossible?qwt(e):jwt(e),E,I=!1,D=!1,x=new Map(Array.from(p.entries()).map(([T,L])=>[T,L[0]])),C=new Map;do{let T=Kwt(t,e,r,h,x,p,o,C,a);T.isGraphChanged&&(D=!0),T.anotherRoundNeeded&&(I=!0),E=!1;for(let[L,U]of p)U.length>1&&!u.dependencies.has(L)&&(x.delete(L),U.shift(),x.set(L,U[0]),E=!0)}while(E);for(let T of u.dependencies.values())if(!u.peerNames.has(T.name)&&!r.has(T.locator)){r.add(T.locator);let L=wj(t,[...e,T],r,C,a);L.isGraphChanged&&(D=!0),L.anotherRoundNeeded&&(I=!0),r.delete(T.locator)}return{anotherRoundNeeded:I,isGraphChanged:D}},Ywt=t=>{for(let[e,r]of t.dependencies)if(!t.peerNames.has(e)&&r.ident!==t.ident)return!0;return!1},Wwt=(t,e,r,o,a,n,u,A,{outputReason:p,fastLookupPossible:h})=>{let E,I=null,D=new Set;p&&(E=`${Array.from(e).map(L=>Js(L)).join("\u2192")}`);let x=r[r.length-1],T=!(o.ident===x.ident);if(p&&!T&&(I="- self-reference"),T&&(T=o.dependencyKind!==1,p&&!T&&(I="- workspace")),T&&o.dependencyKind===2&&(T=!Ywt(o),p&&!T&&(I="- external soft link with unhoisted dependencies")),T&&(T=!t.peerNames.has(o.name),p&&!T&&(I=`- cannot shadow peer: ${Js(t.originalDependencies.get(o.name).locator)} at ${E}`)),T){let L=!1,U=a.get(o.name);if(L=!U||U.ident===o.ident,p&&!L&&(I=`- filled by: ${Js(U.locator)} at ${E}`),L)for(let z=r.length-1;z>=1;z--){let le=r[z].dependencies.get(o.name);if(le&&le.ident!==o.ident){L=!1;let ce=A.get(x);ce||(ce=new Set,A.set(x,ce)),ce.add(o.name),p&&(I=`- filled by ${Js(le.locator)} at ${r.slice(0,z).map(ue=>Js(ue.locator)).join("\u2192")}`);break}}T=L}if(T&&(T=n.get(o.name)===o.ident,p&&!T&&(I=`- filled by: ${Js(u.get(o.name)[0])} at ${E}`)),T){let L=!0,U=new Set(o.peerNames);for(let z=r.length-1;z>=1;z--){let te=r[z];for(let le of U){if(te.peerNames.has(le)&&te.originalDependencies.has(le))continue;let ce=te.dependencies.get(le);ce&&t.dependencies.get(le)!==ce&&(z===r.length-1?D.add(ce):(D=null,L=!1,p&&(I=`- peer dependency ${Js(ce.locator)} from parent ${Js(te.locator)} was not hoisted to ${E}`))),U.delete(le)}if(!L)break}T=L}if(T&&!h)for(let L of o.hoistedDependencies.values()){let U=a.get(L.name)||t.dependencies.get(L.name);if(!U||L.ident!==U.ident){T=!1,p&&(I=`- previously hoisted dependency mismatch, needed: ${Js(L.locator)}, available: ${Js(U?.locator)}`);break}}return D!==null&&D.size>0?{isHoistable:2,dependsOn:D,reason:I}:{isHoistable:T?0:1,reason:I}},VQ=t=>`${t.name}@${t.locator}`,Kwt=(t,e,r,o,a,n,u,A,p)=>{let h=e[e.length-1],E=new Set,I=!1,D=!1,x=(U,z,te,le,ce)=>{if(E.has(le))return;let ue=[...z,VQ(le)],Ce=[...te,VQ(le)],he=new Map,De=new Map;for(let fe of Ej(le)){let ie=Wwt(h,r,[h,...U,le],fe,o,a,n,A,{outputReason:p.debugLevel>=2,fastLookupPossible:p.fastLookupPossible});if(De.set(fe,ie),ie.isHoistable===2)for(let Z of ie.dependsOn){let xe=he.get(Z.name)||new Set;xe.add(fe.name),he.set(Z.name,xe)}}let Ee=new Set,g=(fe,ie,Z)=>{if(!Ee.has(fe)){Ee.add(fe),De.set(fe,{isHoistable:1,reason:Z});for(let xe of he.get(fe.name)||[])g(le.dependencies.get(xe),ie,p.debugLevel>=2?`- peer dependency ${Js(fe.locator)} from parent ${Js(le.locator)} was not hoisted`:"")}};for(let[fe,ie]of De)ie.isHoistable===1&&g(fe,ie,ie.reason);let me=!1;for(let fe of De.keys())if(!Ee.has(fe)){D=!0;let ie=u.get(le);ie&&ie.has(fe.name)&&(I=!0),me=!0,le.dependencies.delete(fe.name),le.hoistedDependencies.set(fe.name,fe),le.reasons.delete(fe.name);let Z=h.dependencies.get(fe.name);if(p.debugLevel>=2){let xe=Array.from(z).concat([le.locator]).map(gt=>Js(gt)).join("\u2192"),Re=h.hoistedFrom.get(fe.name);Re||(Re=[],h.hoistedFrom.set(fe.name,Re)),Re.push(xe),le.hoistedTo.set(fe.name,Array.from(e).map(gt=>Js(gt.locator)).join("\u2192"))}if(!Z)h.ident!==fe.ident&&(h.dependencies.set(fe.name,fe),ce.add(fe));else for(let xe of fe.references)Z.references.add(xe)}if(le.dependencyKind===2&&me&&(I=!0),p.check){let fe=XIe(t);if(fe)throw new Error(`${fe}, after hoisting dependencies of ${[h,...U,le].map(ie=>Js(ie.locator)).join("\u2192")}: +${Av(t)}`)}let we=Ej(le);for(let fe of we)if(Ee.has(fe)){let ie=De.get(fe);if((a.get(fe.name)===fe.ident||!le.reasons.has(fe.name))&&ie.isHoistable!==0&&le.reasons.set(fe.name,ie.reason),!fe.isHoistBorder&&Ce.indexOf(VQ(fe))<0){E.add(le);let xe=zIe(le,fe);x([...U,le],ue,Ce,xe,T),E.delete(le)}}},C,T=new Set(Ej(h)),L=Array.from(e).map(U=>VQ(U));do{C=T,T=new Set;for(let U of C){if(U.locator===h.locator||U.isHoistBorder)continue;let z=zIe(h,U);x([],Array.from(r),L,z,T)}}while(T.size>0);return{anotherRoundNeeded:I,isGraphChanged:D}},XIe=t=>{let e=[],r=new Set,o=new Set,a=(n,u,A)=>{if(r.has(n)||(r.add(n),o.has(n)))return;let p=new Map(u);for(let h of n.dependencies.values())n.peerNames.has(h.name)||p.set(h.name,h);for(let h of n.originalDependencies.values()){let E=p.get(h.name),I=()=>`${Array.from(o).concat([n]).map(D=>Js(D.locator)).join("\u2192")}`;if(n.peerNames.has(h.name)){let D=u.get(h.name);(D!==E||!D||D.ident!==h.ident)&&e.push(`${I()} - broken peer promise: expected ${h.ident} but found ${D&&D.ident}`)}else{let D=A.hoistedFrom.get(n.name),x=n.hoistedTo.get(h.name),C=`${D?` hoisted from ${D.join(", ")}`:""}`,T=`${x?` hoisted to ${x}`:""}`,L=`${I()}${C}`;E?E.ident!==h.ident&&e.push(`${L} - broken require promise for ${h.name}${T}: expected ${h.ident}, but found: ${E.ident}`):e.push(`${L} - broken require promise: no required dependency ${h.name}${T} found`)}}o.add(n);for(let h of n.dependencies.values())n.peerNames.has(h.name)||a(h,p,n);o.delete(n)};return a(t,t.dependencies,t),e.join(` +`)},Vwt=(t,e)=>{let{identName:r,name:o,reference:a,peerNames:n}=t,u={name:o,references:new Set([a]),locator:Cj(r,a),ident:VIe(r,a),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(n),reasons:new Map,decoupled:!0,isHoistBorder:!0,hoistPriority:0,dependencyKind:1,hoistedFrom:new Map,hoistedTo:new Map},A=new Map([[t,u]]),p=(h,E)=>{let I=A.get(h),D=!!I;if(!I){let{name:x,identName:C,reference:T,peerNames:L,hoistPriority:U,dependencyKind:z}=h,te=e.hoistingLimits.get(E.locator);I={name:x,references:new Set([T]),locator:Cj(C,T),ident:VIe(C,T),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(L),reasons:new Map,decoupled:!0,isHoistBorder:te?te.has(x):!1,hoistPriority:U||0,dependencyKind:z||0,hoistedFrom:new Map,hoistedTo:new Map},A.set(h,I)}if(E.dependencies.set(h.name,I),E.originalDependencies.set(h.name,I),D){let x=new Set,C=T=>{if(!x.has(T)){x.add(T),T.decoupled=!1;for(let L of T.dependencies.values())T.peerNames.has(L.name)||C(L)}};C(I)}else for(let x of h.dependencies)p(x,I)};for(let h of t.dependencies)p(h,u);return u},Ij=t=>t.substring(0,t.indexOf("@",1)),zwt=t=>{let e={name:t.name,identName:Ij(t.locator),references:new Set(t.references),dependencies:new Set},r=new Set([t]),o=(a,n,u)=>{let A=r.has(a),p;if(n===a)p=u;else{let{name:h,references:E,locator:I}=a;p={name:h,identName:Ij(I),references:E,dependencies:new Set}}if(u.dependencies.add(p),!A){r.add(a);for(let h of a.dependencies.values())a.peerNames.has(h.name)||o(h,a,p);r.delete(a)}};for(let a of t.dependencies.values())o(a,t,e);return e},Jwt=t=>{let e=new Map,r=new Set([t]),o=u=>`${u.name}@${u.ident}`,a=u=>{let A=o(u),p=e.get(A);return p||(p={dependents:new Set,peerDependents:new Set,hoistPriority:0},e.set(A,p)),p},n=(u,A)=>{let p=!!r.has(A);if(a(A).dependents.add(u.ident),!p){r.add(A);for(let E of A.dependencies.values()){let I=a(E);I.hoistPriority=Math.max(I.hoistPriority,E.hoistPriority),A.peerNames.has(E.name)?I.peerDependents.add(A.ident):n(A,E)}}};for(let u of t.dependencies.values())t.peerNames.has(u.name)||n(t,u);return e},Js=t=>{if(!t)return"none";let e=t.indexOf("@",1),r=t.substring(0,e);r.endsWith("$wsroot$")&&(r=`wh:${r.replace("$wsroot$","")}`);let o=t.substring(e+1);if(o==="workspace:.")return".";if(o){let a=(o.indexOf("#")>0?o.split("#")[1]:o).replace("npm:","");return o.startsWith("virtual")&&(r=`v:${r}`),a.startsWith("workspace")&&(r=`w:${r}`,a=""),`${r}${a?`@${a}`:""}`}else return`${r}`};var Av=t=>{let e=0,r=(a,n,u="")=>{if(e>5e4||n.has(a))return"";e++;let A=Array.from(a.dependencies.values()).sort((h,E)=>h.name===E.name?0:h.name>E.name?1:-1),p="";n.add(a);for(let h=0;h":"")+(D!==E.name?`a:${E.name}:`:"")+Js(E.locator)+(I?` ${I}`:"")} +`,p+=r(E,n,`${u}${h5e4?` +Tree is too large, part of the tree has been dunped +`:"")};var fv=(o=>(o.WORKSPACES="workspaces",o.DEPENDENCIES="dependencies",o.NONE="none",o))(fv||{}),ZIe="node_modules",jh="$wsroot$";var pv=(t,e)=>{let{packageTree:r,hoistingLimits:o,errors:a,preserveSymlinksRequired:n}=Zwt(t,e),u=null;if(a.length===0){let A=JIe(r,{hoistingLimits:o});u=eIt(t,A,e)}return{tree:u,errors:a,preserveSymlinksRequired:n}},yA=t=>`${t.name}@${t.reference}`,vj=t=>{let e=new Map;for(let[r,o]of t.entries())if(!o.dirList){let a=e.get(o.locator);a||(a={target:o.target,linkType:o.linkType,locations:[],aliases:o.aliases},e.set(o.locator,a)),a.locations.push(r)}for(let r of e.values())r.locations=r.locations.sort((o,a)=>{let n=o.split(K.delimiter).length,u=a.split(K.delimiter).length;return a===o?0:n!==u?u-n:a>o?1:-1});return e},$Ie=(t,e)=>{let r=G.isVirtualLocator(t)?G.devirtualizeLocator(t):t,o=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e;return G.areLocatorsEqual(r,o)},Bj=(t,e,r,o)=>{if(t.linkType!=="SOFT")return!1;let a=Ae.toPortablePath(r.resolveVirtual&&e.reference&&e.reference.startsWith("virtual:")?r.resolveVirtual(t.packageLocation):t.packageLocation);return K.contains(o,a)===null},Xwt=t=>{let e=t.getPackageInformation(t.topLevel);if(e===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");if(t.findPackageLocator(e.packageLocation)===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let o=Ae.toPortablePath(e.packageLocation.slice(0,-1)),a=new Map,n={children:new Map},u=t.getDependencyTreeRoots(),A=new Map,p=new Set,h=(D,x)=>{let C=yA(D);if(p.has(C))return;p.add(C);let T=t.getPackageInformation(D);if(T){let L=x?yA(x):"";if(yA(D)!==L&&T.linkType==="SOFT"&&!D.reference.startsWith("link:")&&!Bj(T,D,t,o)){let U=e1e(T,D,t);(!A.get(U)||D.reference.startsWith("workspace:"))&&A.set(U,D)}for(let[U,z]of T.packageDependencies)z!==null&&(T.packagePeers.has(U)||h(t.getLocator(U,z),D))}};for(let D of u)h(D,null);let E=o.split(K.sep);for(let D of A.values()){let x=t.getPackageInformation(D),T=Ae.toPortablePath(x.packageLocation.slice(0,-1)).split(K.sep).slice(E.length),L=n;for(let U of T){let z=L.children.get(U);z||(z={children:new Map},L.children.set(U,z)),L=z}L.workspaceLocator=D}let I=(D,x)=>{if(D.workspaceLocator){let C=yA(x),T=a.get(C);T||(T=new Set,a.set(C,T)),T.add(D.workspaceLocator)}for(let C of D.children.values())I(C,D.workspaceLocator||x)};for(let D of n.children.values())I(D,n.workspaceLocator);return a},Zwt=(t,e)=>{let r=[],o=!1,a=new Map,n=Xwt(t),u=t.getPackageInformation(t.topLevel);if(u===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");let A=t.findPackageLocator(u.packageLocation);if(A===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let p=Ae.toPortablePath(u.packageLocation.slice(0,-1)),h={name:A.name,identName:A.name,reference:A.reference,peerNames:u.packagePeers,dependencies:new Set,dependencyKind:1},E=new Map,I=(x,C)=>`${yA(C)}:${x}`,D=(x,C,T,L,U,z,te,le)=>{let ce=I(x,T),ue=E.get(ce),Ce=!!ue;!Ce&&T.name===A.name&&T.reference===A.reference&&(ue=h,E.set(ce,h));let he=Bj(C,T,t,p);if(!ue){let fe=0;he?fe=2:C.linkType==="SOFT"&&T.name.endsWith(jh)&&(fe=1),ue={name:x,identName:T.name,reference:T.reference,dependencies:new Set,peerNames:fe===1?new Set:C.packagePeers,dependencyKind:fe},E.set(ce,ue)}let De;if(he?De=2:U.linkType==="SOFT"?De=1:De=0,ue.hoistPriority=Math.max(ue.hoistPriority||0,De),le&&!he){let fe=yA({name:L.identName,reference:L.reference}),ie=a.get(fe)||new Set;a.set(fe,ie),ie.add(ue.name)}let Ee=new Map(C.packageDependencies);if(e.project){let fe=e.project.workspacesByCwd.get(Ae.toPortablePath(C.packageLocation.slice(0,-1)));if(fe){let ie=new Set([...Array.from(fe.manifest.peerDependencies.values(),Z=>G.stringifyIdent(Z)),...Array.from(fe.manifest.peerDependenciesMeta.keys())]);for(let Z of ie)Ee.has(Z)||(Ee.set(Z,z.get(Z)||null),ue.peerNames.add(Z))}}let g=yA({name:T.name.replace(jh,""),reference:T.reference}),me=n.get(g);if(me)for(let fe of me)Ee.set(`${fe.name}${jh}`,fe.reference);(C!==U||C.linkType!=="SOFT"||!he&&(!e.selfReferencesByCwd||e.selfReferencesByCwd.get(te)))&&L.dependencies.add(ue);let we=T!==A&&C.linkType==="SOFT"&&!T.name.endsWith(jh)&&!he;if(!Ce&&!we){let fe=new Map;for(let[ie,Z]of Ee)if(Z!==null){let xe=t.getLocator(ie,Z),Re=t.getLocator(ie.replace(jh,""),Z),gt=t.getPackageInformation(Re);if(gt===null)throw new Error("Assertion failed: Expected the package to have been registered");let q=Bj(gt,xe,t,p);if(e.validateExternalSoftLinks&&e.project&&q){gt.packageDependencies.size>0&&(o=!0);for(let[Ve,Se]of gt.packageDependencies)if(Se!==null){let tt=G.parseLocator(Array.isArray(Se)?`${Se[0]}@${Se[1]}`:`${Ve}@${Se}`);if(yA(tt)!==yA(xe)){let He=Ee.get(Ve);if(He){let b=G.parseLocator(Array.isArray(He)?`${He[0]}@${He[1]}`:`${Ve}@${He}`);$Ie(b,tt)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(xe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${T.name}@${T.reference}`))} dependency ${G.prettyLocator(e.project.configuration,tt)} conflicts with parent dependency ${G.prettyLocator(e.project.configuration,b)}`})}else{let b=fe.get(Ve);if(b){let w=b.target,S=G.parseLocator(Array.isArray(w)?`${w[0]}@${w[1]}`:`${Ve}@${w}`);$Ie(S,tt)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(xe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${T.name}@${T.reference}`))} dependency ${G.prettyLocator(e.project.configuration,tt)} conflicts with dependency ${G.prettyLocator(e.project.configuration,S)} from sibling portal ${G.prettyIdent(e.project.configuration,G.parseIdent(b.portal.name))}`})}else fe.set(Ve,{target:tt.reference,portal:xe})}}}}let nt=e.hoistingLimitsByCwd?.get(te),Ne=q?te:K.relative(p,Ae.toPortablePath(gt.packageLocation))||Bt.dot,Te=e.hoistingLimitsByCwd?.get(Ne);D(ie,gt,xe,ue,C,Ee,Ne,nt==="dependencies"||Te==="dependencies"||Te==="workspaces")}}};return D(A.name,u,A,h,u,u.packageDependencies,Bt.dot,!1),{packageTree:h,hoistingLimits:a,errors:r,preserveSymlinksRequired:o}};function e1e(t,e,r){let o=r.resolveVirtual&&e.reference&&e.reference.startsWith("virtual:")?r.resolveVirtual(t.packageLocation):t.packageLocation;return Ae.toPortablePath(o||t.packageLocation)}function $wt(t,e,r){let o=e.getLocator(t.name.replace(jh,""),t.reference),a=e.getPackageInformation(o);if(a===null)throw new Error("Assertion failed: Expected the package to be registered");return r.pnpifyFs?{linkType:"SOFT",target:Ae.toPortablePath(a.packageLocation)}:{linkType:a.linkType,target:e1e(a,t,e)}}var eIt=(t,e,r)=>{let o=new Map,a=(E,I,D)=>{let{linkType:x,target:C}=$wt(E,t,r);return{locator:yA(E),nodePath:I,target:C,linkType:x,aliases:D}},n=E=>{let[I,D]=E.split("/");return D?{scope:I,name:D}:{scope:null,name:I}},u=new Set,A=(E,I,D)=>{if(u.has(E))return;u.add(E);let x=Array.from(E.references).sort().join("#");for(let C of E.dependencies){let T=Array.from(C.references).sort().join("#");if(C.identName===E.identName.replace(jh,"")&&T===x)continue;let L=Array.from(C.references).sort(),U={name:C.identName,reference:L[0]},{name:z,scope:te}=n(C.name),le=te?[te,z]:[z],ce=K.join(I,ZIe),ue=K.join(ce,...le),Ce=`${D}/${U.name}`,he=a(U,D,L.slice(1)),De=!1;if(he.linkType==="SOFT"&&r.project){let Ee=r.project.workspacesByCwd.get(he.target.slice(0,-1));De=!!(Ee&&!Ee.manifest.name)}if(!C.name.endsWith(jh)&&!De){let Ee=o.get(ue);if(Ee){if(Ee.dirList)throw new Error(`Assertion failed: ${ue} cannot merge dir node with leaf node`);{let we=G.parseLocator(Ee.locator),fe=G.parseLocator(he.locator);if(Ee.linkType!==he.linkType)throw new Error(`Assertion failed: ${ue} cannot merge nodes with different link types ${Ee.nodePath}/${G.stringifyLocator(we)} and ${D}/${G.stringifyLocator(fe)}`);if(we.identHash!==fe.identHash)throw new Error(`Assertion failed: ${ue} cannot merge nodes with different idents ${Ee.nodePath}/${G.stringifyLocator(we)} and ${D}/s${G.stringifyLocator(fe)}`);he.aliases=[...he.aliases,...Ee.aliases,G.parseLocator(Ee.locator).reference]}}o.set(ue,he);let g=ue.split("/"),me=g.indexOf(ZIe);for(let we=g.length-1;me>=0&&we>me;we--){let fe=Ae.toPortablePath(g.slice(0,we).join(K.sep)),ie=g[we],Z=o.get(fe);if(!Z)o.set(fe,{dirList:new Set([ie])});else if(Z.dirList){if(Z.dirList.has(ie))break;Z.dirList.add(ie)}}}A(C,he.linkType==="SOFT"?he.target:ue,Ce)}},p=a({name:e.name,reference:Array.from(e.references)[0]},"",[]),h=p.target;return o.set(h,p),A(e,h,""),o};Ke();Ke();Pt();Pt();sA();Ml();var jj={};Kt(jj,{PnpInstaller:()=>pd,PnpLinker:()=>Wh,UnplugCommand:()=>QC,default:()=>kIt,getPnpPath:()=>Kh,jsInstallUtils:()=>CA,pnpUtils:()=>vv,quotePathIfNeeded:()=>O1e});Pt();var M1e=ve("url");Ke();Ke();Pt();Pt();var t1e={DEFAULT:{collapsed:!1,next:{"*":"DEFAULT"}},TOP_LEVEL:{collapsed:!1,next:{fallbackExclusionList:"FALLBACK_EXCLUSION_LIST",packageRegistryData:"PACKAGE_REGISTRY_DATA","*":"DEFAULT"}},FALLBACK_EXCLUSION_LIST:{collapsed:!1,next:{"*":"FALLBACK_EXCLUSION_ENTRIES"}},FALLBACK_EXCLUSION_ENTRIES:{collapsed:!0,next:{"*":"FALLBACK_EXCLUSION_DATA"}},FALLBACK_EXCLUSION_DATA:{collapsed:!0,next:{"*":"DEFAULT"}},PACKAGE_REGISTRY_DATA:{collapsed:!1,next:{"*":"PACKAGE_REGISTRY_ENTRIES"}},PACKAGE_REGISTRY_ENTRIES:{collapsed:!0,next:{"*":"PACKAGE_STORE_DATA"}},PACKAGE_STORE_DATA:{collapsed:!1,next:{"*":"PACKAGE_STORE_ENTRIES"}},PACKAGE_STORE_ENTRIES:{collapsed:!0,next:{"*":"PACKAGE_INFORMATION_DATA"}},PACKAGE_INFORMATION_DATA:{collapsed:!1,next:{packageDependencies:"PACKAGE_DEPENDENCIES","*":"DEFAULT"}},PACKAGE_DEPENDENCIES:{collapsed:!1,next:{"*":"PACKAGE_DEPENDENCY"}},PACKAGE_DEPENDENCY:{collapsed:!0,next:{"*":"DEFAULT"}}};function tIt(t,e,r){let o="";o+="[";for(let a=0,n=t.length;a"u"||(A!==0&&(a+=", "),a+=JSON.stringify(p),a+=": ",a+=zQ(p,h,e,r).replace(/^ +/g,""),A+=1)}return a+="}",a}function iIt(t,e,r){let o=Object.keys(t),a=`${r} `,n="";n+=r,n+=`{ +`;let u=0;for(let A=0,p=o.length;A"u"||(u!==0&&(n+=",",n+=` +`),n+=a,n+=JSON.stringify(h),n+=": ",n+=zQ(h,E,e,a).replace(/^ +/g,""),u+=1)}return u!==0&&(n+=` +`),n+=r,n+="}",n}function zQ(t,e,r,o){let{next:a}=t1e[r],n=a[t]||a["*"];return r1e(e,n,o)}function r1e(t,e,r){let{collapsed:o}=t1e[e];return Array.isArray(t)?o?tIt(t,e,r):rIt(t,e,r):typeof t=="object"&&t!==null?o?nIt(t,e,r):iIt(t,e,r):JSON.stringify(t)}function n1e(t){return r1e(t,"TOP_LEVEL","")}function hv(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function sIt(t){let e=new Map,r=hv(t.fallbackExclusionList||[],[({name:o,reference:a})=>o,({name:o,reference:a})=>a]);for(let{name:o,reference:a}of r){let n=e.get(o);typeof n>"u"&&e.set(o,n=new Set),n.add(a)}return Array.from(e).map(([o,a])=>[o,Array.from(a)])}function oIt(t){return hv(t.fallbackPool||[],([e])=>e)}function aIt(t){let e=[];for(let[r,o]of hv(t.packageRegistry,([a])=>a===null?"0":`1${a}`)){let a=[];e.push([r,a]);for(let[n,{packageLocation:u,packageDependencies:A,packagePeers:p,linkType:h,discardFromLookup:E}]of hv(o,([I])=>I===null?"0":`1${I}`)){let I=[];r!==null&&n!==null&&!A.has(r)&&I.push([r,n]);for(let[C,T]of hv(A.entries(),([L])=>L))I.push([C,T]);let D=p&&p.size>0?Array.from(p):void 0,x=E||void 0;a.push([n,{packageLocation:u,packageDependencies:I,packagePeers:D,linkType:h,discardFromLookup:x}])}}return e}function gv(t){return{__info:["This file is automatically generated. Do not touch it, or risk","your modifications being lost."],dependencyTreeRoots:t.dependencyTreeRoots,enableTopLevelFallback:t.enableTopLevelFallback||!1,ignorePatternData:t.ignorePattern||null,fallbackExclusionList:sIt(t),fallbackPool:oIt(t),packageRegistryData:aIt(t)}}var o1e=et(s1e());function a1e(t,e){return[t?`${t} +`:"",`/* eslint-disable */ +`,`// @ts-nocheck +`,`"use strict"; +`,` +`,e,` +`,(0,o1e.default)()].join("")}function lIt(t){return JSON.stringify(t,null,2)}function cIt(t){return`'${t.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,`\\ +`)}'`}function uIt(t){return[`const RAW_RUNTIME_STATE = +`,`${cIt(n1e(t))}; + +`,`function $$SETUP_STATE(hydrateRuntimeState, basePath) { +`,` return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname}); +`,`} +`].join("")}function AIt(){return[`function $$SETUP_STATE(hydrateRuntimeState, basePath) { +`,` const fs = require('fs'); +`,` const path = require('path'); +`,` const pnpDataFilepath = path.resolve(__dirname, ${JSON.stringify(mr.pnpData)}); +`,` return hydrateRuntimeState(JSON.parse(fs.readFileSync(pnpDataFilepath, 'utf8')), {basePath: basePath || __dirname}); +`,`} +`].join("")}function l1e(t){let e=gv(t),r=uIt(e);return a1e(t.shebang,r)}function c1e(t){let e=gv(t),r=AIt(),o=a1e(t.shebang,r);return{dataFile:lIt(e),loaderFile:o}}Pt();function Pj(t,{basePath:e}){let r=Ae.toPortablePath(e),o=K.resolve(r),a=t.ignorePatternData!==null?new RegExp(t.ignorePatternData):null,n=new Map,u=new Map(t.packageRegistryData.map(([I,D])=>[I,new Map(D.map(([x,C])=>{if(I===null!=(x===null))throw new Error("Assertion failed: The name and reference should be null, or neither should");let T=C.discardFromLookup??!1,L={name:I,reference:x},U=n.get(C.packageLocation);U?(U.discardFromLookup=U.discardFromLookup&&T,T||(U.locator=L)):n.set(C.packageLocation,{locator:L,discardFromLookup:T});let z=null;return[x,{packageDependencies:new Map(C.packageDependencies),packagePeers:new Set(C.packagePeers),linkType:C.linkType,discardFromLookup:T,get packageLocation(){return z||(z=K.join(o,C.packageLocation))}}]}))])),A=new Map(t.fallbackExclusionList.map(([I,D])=>[I,new Set(D)])),p=new Map(t.fallbackPool),h=t.dependencyTreeRoots,E=t.enableTopLevelFallback;return{basePath:r,dependencyTreeRoots:h,enableTopLevelFallback:E,fallbackExclusionList:A,fallbackPool:p,ignorePattern:a,packageLocatorsByLocations:n,packageRegistry:u}}Pt();Pt();var tp=ve("module"),fd=ve("url"),Lj=ve("util");var Qo=ve("url");var p1e=et(ve("assert"));var Sj=Array.isArray,dv=JSON.stringify,mv=Object.getOwnPropertyNames,Ad=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),bj=(t,e)=>RegExp.prototype.exec.call(t,e),xj=(t,...e)=>RegExp.prototype[Symbol.replace].apply(t,e),Gh=(t,...e)=>String.prototype.endsWith.apply(t,e),kj=(t,...e)=>String.prototype.includes.apply(t,e),Qj=(t,...e)=>String.prototype.lastIndexOf.apply(t,e),yv=(t,...e)=>String.prototype.indexOf.apply(t,e),u1e=(t,...e)=>String.prototype.replace.apply(t,e),Yh=(t,...e)=>String.prototype.slice.apply(t,e),EA=(t,...e)=>String.prototype.startsWith.apply(t,e),A1e=Map,f1e=JSON.parse;function Ev(t,e,r){return class extends r{constructor(...o){super(e(...o)),this.code=t,this.name=`${r.name} [${t}]`}}}var h1e=Ev("ERR_PACKAGE_IMPORT_NOT_DEFINED",(t,e,r)=>`Package import specifier "${t}" is not defined${e?` in package ${e}package.json`:""} imported from ${r}`,TypeError),Fj=Ev("ERR_INVALID_MODULE_SPECIFIER",(t,e,r=void 0)=>`Invalid module "${t}" ${e}${r?` imported from ${r}`:""}`,TypeError),g1e=Ev("ERR_INVALID_PACKAGE_TARGET",(t,e,r,o=!1,a=void 0)=>{let n=typeof r=="string"&&!o&&r.length&&!EA(r,"./");return e==="."?((0,p1e.default)(o===!1),`Invalid "exports" main target ${dv(r)} defined in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`):`Invalid "${o?"imports":"exports"}" target ${dv(r)} defined for '${e}' in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`},Error),Cv=Ev("ERR_INVALID_PACKAGE_CONFIG",(t,e,r)=>`Invalid package config ${t}${e?` while importing ${e}`:""}${r?`. ${r}`:""}`,Error),d1e=Ev("ERR_PACKAGE_PATH_NOT_EXPORTED",(t,e,r=void 0)=>e==="."?`No "exports" main defined in ${t}package.json${r?` imported from ${r}`:""}`:`Package subpath '${e}' is not defined by "exports" in ${t}package.json${r?` imported from ${r}`:""}`,Error);var XQ=ve("url");function m1e(t,e){let r=Object.create(null);for(let o=0;oe):t+e}wv(r,t,o,u,a)}bj(E1e,Yh(t,2))!==null&&wv(r,t,o,u,a);let p=new URL(t,o),h=p.pathname,E=new URL(".",o).pathname;if(EA(h,E)||wv(r,t,o,u,a),e==="")return p;if(bj(E1e,e)!==null){let I=n?u1e(r,"*",()=>e):r+e;hIt(I,o,u,a)}return n?new URL(xj(C1e,p.href,()=>e)):new URL(e,p)}function dIt(t){let e=+t;return`${e}`!==t?!1:e>=0&&e<4294967295}function kC(t,e,r,o,a,n,u,A){if(typeof e=="string")return gIt(e,r,o,t,a,n,u,A);if(Sj(e)){if(e.length===0)return null;let p;for(let h=0;hn?-1:n>a||r===-1?1:o===-1||t.length>e.length?-1:e.length>t.length?1:0}function mIt(t,e,r){if(typeof t=="string"||Sj(t))return!0;if(typeof t!="object"||t===null)return!1;let o=mv(t),a=!1,n=0;for(let u=0;u=h.length&&Gh(e,I)&&I1e(n,h)===1&&Qj(h,"*")===E&&(n=h,u=Yh(e,E,e.length-I.length))}}if(n){let p=r[n],h=kC(t,p,u,n,o,!0,!1,a);return h==null&&Rj(e,t,o),h}Rj(e,t,o)}function v1e({name:t,base:e,conditions:r,readFileSyncFn:o}){if(t==="#"||EA(t,"#/")||Gh(t,"/")){let u="is not a valid internal imports specifier name";throw new Fj(t,u,(0,Qo.fileURLToPath)(e))}let a,n=y1e(e,o);if(n.exists){a=(0,Qo.pathToFileURL)(n.pjsonPath);let u=n.imports;if(u)if(Ad(u,t)&&!kj(t,"*")){let A=kC(a,u[t],"",t,e,!1,!0,r);if(A!=null)return A}else{let A="",p,h=mv(u);for(let E=0;E=I.length&&Gh(t,x)&&I1e(A,I)===1&&Qj(I,"*")===D&&(A=I,p=Yh(t,D,t.length-x.length))}}if(A){let E=u[A],I=kC(a,E,p,A,e,!0,!0,r);if(I!=null)return I}}}pIt(t,a,e)}Pt();var EIt=new Set(["BUILTIN_NODE_RESOLUTION_FAILED","MISSING_DEPENDENCY","MISSING_PEER_DEPENDENCY","QUALIFIED_PATH_RESOLUTION_FAILED","UNDECLARED_DEPENDENCY"]);function ts(t,e,r={},o){o??=EIt.has(t)?"MODULE_NOT_FOUND":t;let a={configurable:!0,writable:!0,enumerable:!1};return Object.defineProperties(new Error(e),{code:{...a,value:o},pnpCode:{...a,value:t},data:{...a,value:r}})}function pu(t){return Ae.normalize(Ae.fromPortablePath(t))}var b1e=et(P1e());function x1e(t){return CIt(),Nj[t]}var Nj;function CIt(){Nj||(Nj={"--conditions":[],...S1e(wIt()),...S1e(process.execArgv)})}function S1e(t){return(0,b1e.default)({"--conditions":[String],"-C":"--conditions"},{argv:t,permissive:!0})}function wIt(){let t=[],e=IIt(process.env.NODE_OPTIONS||"",t);return t.length,e}function IIt(t,e){let r=[],o=!1,a=!0;for(let n=0;nparseInt(t,10)),k1e=Ha>19||Ha===19&&ep>=2||Ha===18&&ep>=13,tJt=Ha===20&&ep<6||Ha===19&&ep>=3,rJt=Ha>19||Ha===19&&ep>=6,nJt=Ha>=21||Ha===20&&ep>=10||Ha===18&&ep>=19,iJt=Ha>=21||Ha===20&&ep>=10||Ha===18&&ep>=20,sJt=Ha>=22;function Q1e(t){if(process.env.WATCH_REPORT_DEPENDENCIES&&process.send)if(t=t.map(e=>Ae.fromPortablePath(qs.resolveVirtual(Ae.toPortablePath(e)))),k1e)process.send({"watch:require":t});else for(let e of t)process.send({"watch:require":e})}function Mj(t,e){let r=Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK)>0,o=Number(process.env.PNP_DEBUG_LEVEL),a=/^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/,n=/^(\/|\.{1,2}(\/|$))/,u=/\/$/,A=/^\.{0,2}\//,p={name:null,reference:null},h=[],E=new Set;if(t.enableTopLevelFallback===!0&&h.push(p),e.compatibilityMode!==!1)for(let Ne of["react-scripts","gatsby"]){let Te=t.packageRegistry.get(Ne);if(Te)for(let ke of Te.keys()){if(ke===null)throw new Error("Assertion failed: This reference shouldn't be null");h.push({name:Ne,reference:ke})}}let{ignorePattern:I,packageRegistry:D,packageLocatorsByLocations:x}=t;function C(Ne,Te){return{fn:Ne,args:Te,error:null,result:null}}function T(Ne){let Te=process.stderr?.hasColors?.()??process.stdout.isTTY,ke=(tt,He)=>`\x1B[${tt}m${He}\x1B[0m`,Ve=Ne.error;console.error(Ve?ke("31;1",`\u2716 ${Ne.error?.message.replace(/\n.*/s,"")}`):ke("33;1","\u203C Resolution")),Ne.args.length>0&&console.error();for(let tt of Ne.args)console.error(` ${ke("37;1","In \u2190")} ${(0,Lj.inspect)(tt,{colors:Te,compact:!0})}`);Ne.result&&(console.error(),console.error(` ${ke("37;1","Out \u2192")} ${(0,Lj.inspect)(Ne.result,{colors:Te,compact:!0})}`));let Se=new Error().stack.match(/(?<=^ +)at.*/gm)?.slice(2)??[];if(Se.length>0){console.error();for(let tt of Se)console.error(` ${ke("38;5;244",tt)}`)}console.error()}function L(Ne,Te){if(e.allowDebug===!1)return Te;if(Number.isFinite(o)){if(o>=2)return(...ke)=>{let Ve=C(Ne,ke);try{return Ve.result=Te(...ke)}catch(Se){throw Ve.error=Se}finally{T(Ve)}};if(o>=1)return(...ke)=>{try{return Te(...ke)}catch(Ve){let Se=C(Ne,ke);throw Se.error=Ve,T(Se),Ve}}}return Te}function U(Ne){let Te=g(Ne);if(!Te)throw ts("INTERNAL","Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)");return Te}function z(Ne){if(Ne.name===null)return!0;for(let Te of t.dependencyTreeRoots)if(Te.name===Ne.name&&Te.reference===Ne.reference)return!0;return!1}let te=new Set(["node","require",...x1e("--conditions")]);function le(Ne,Te=te,ke){let Ve=fe(K.join(Ne,"internal.js"),{resolveIgnored:!0,includeDiscardFromLookup:!0});if(Ve===null)throw ts("INTERNAL",`The locator that owns the "${Ne}" path can't be found inside the dependency tree (this is probably an internal error)`);let{packageLocation:Se}=U(Ve),tt=K.join(Se,mr.manifest);if(!e.fakeFs.existsSync(tt))return null;let He=JSON.parse(e.fakeFs.readFileSync(tt,"utf8"));if(He.exports==null)return null;let b=K.contains(Se,Ne);if(b===null)throw ts("INTERNAL","unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)");b!=="."&&!A.test(b)&&(b=`./${b}`);try{let w=B1e({packageJSONUrl:(0,fd.pathToFileURL)(Ae.fromPortablePath(tt)),packageSubpath:b,exports:He.exports,base:ke?(0,fd.pathToFileURL)(Ae.fromPortablePath(ke)):null,conditions:Te});return Ae.toPortablePath((0,fd.fileURLToPath)(w))}catch(w){throw ts("EXPORTS_RESOLUTION_FAILED",w.message,{unqualifiedPath:pu(Ne),locator:Ve,pkgJson:He,subpath:pu(b),conditions:Te},w.code)}}function ce(Ne,Te,{extensions:ke}){let Ve;try{Te.push(Ne),Ve=e.fakeFs.statSync(Ne)}catch{}if(Ve&&!Ve.isDirectory())return e.fakeFs.realpathSync(Ne);if(Ve&&Ve.isDirectory()){let Se;try{Se=JSON.parse(e.fakeFs.readFileSync(K.join(Ne,mr.manifest),"utf8"))}catch{}let tt;if(Se&&Se.main&&(tt=K.resolve(Ne,Se.main)),tt&&tt!==Ne){let He=ce(tt,Te,{extensions:ke});if(He!==null)return He}}for(let Se=0,tt=ke.length;Se{let b=JSON.stringify(He.name);if(Ve.has(b))return;Ve.add(b);let w=me(He);for(let S of w)if(U(S).packagePeers.has(Ne))Se(S);else{let R=ke.get(S.name);typeof R>"u"&&ke.set(S.name,R=new Set),R.add(S.reference)}};Se(Te);let tt=[];for(let He of[...ke.keys()].sort())for(let b of[...ke.get(He)].sort())tt.push({name:He,reference:b});return tt}function fe(Ne,{resolveIgnored:Te=!1,includeDiscardFromLookup:ke=!1}={}){if(he(Ne)&&!Te)return null;let Ve=K.relative(t.basePath,Ne);Ve.match(n)||(Ve=`./${Ve}`),Ve.endsWith("/")||(Ve=`${Ve}/`);do{let Se=x.get(Ve);if(typeof Se>"u"||Se.discardFromLookup&&!ke){Ve=Ve.substring(0,Ve.lastIndexOf("/",Ve.length-2)+1);continue}return Se.locator}while(Ve!=="");return null}function ie(Ne){try{return e.fakeFs.readFileSync(Ae.toPortablePath(Ne),"utf8")}catch(Te){if(Te.code==="ENOENT")return;throw Te}}function Z(Ne,Te,{considerBuiltins:ke=!0}={}){if(Ne.startsWith("#"))throw new Error("resolveToUnqualified can not handle private import mappings");if(Ne==="pnpapi")return Ae.toPortablePath(e.pnpapiResolution);if(ke&&(0,tp.isBuiltin)(Ne))return null;let Ve=pu(Ne),Se=Te&&pu(Te);if(Te&&he(Te)&&(!K.isAbsolute(Ne)||fe(Ne)===null)){let b=Ce(Ne,Te);if(b===!1)throw ts("BUILTIN_NODE_RESOLUTION_FAILED",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) + +Require request: "${Ve}" +Required by: ${Se} +`,{request:Ve,issuer:Se});return Ae.toPortablePath(b)}let tt,He=Ne.match(a);if(He){if(!Te)throw ts("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:Ve,issuer:Se});let[,b,w]=He,S=fe(Te);if(!S){let Fe=Ce(Ne,Te);if(Fe===!1)throw ts("BUILTIN_NODE_RESOLUTION_FAILED",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). + +Require path: "${Ve}" +Required by: ${Se} +`,{request:Ve,issuer:Se});return Ae.toPortablePath(Fe)}let R=U(S).packageDependencies.get(b),J=null;if(R==null&&S.name!==null){let Fe=t.fallbackExclusionList.get(S.name);if(!Fe||!Fe.has(S.reference)){for(let Et=0,qt=h.length;Etz(lt))?X=ts("MISSING_PEER_DEPENDENCY",`${S.name} tried to access ${b} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +${Fe.map(lt=>`Ancestor breaking the chain: ${lt.name}@${lt.reference} +`).join("")} +`,{request:Ve,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b,brokenAncestors:Fe}):X=ts("MISSING_PEER_DEPENDENCY",`${S.name} tried to access ${b} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) + +${Fe.map(lt=>`Ancestor breaking the chain: ${lt.name}@${lt.reference} +`).join("")} +`,{request:Ve,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b,brokenAncestors:Fe})}else R===void 0&&(!ke&&(0,tp.isBuiltin)(Ne)?z(S)?X=ts("UNDECLARED_DEPENDENCY",`Your application tried to access ${b}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${b} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${Se} +`,{request:Ve,issuer:Se,dependencyName:b}):X=ts("UNDECLARED_DEPENDENCY",`${S.name} tried to access ${b}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${b} isn't otherwise declared in ${S.name}'s dependencies, this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${Se} +`,{request:Ve,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b}):z(S)?X=ts("UNDECLARED_DEPENDENCY",`Your application tried to access ${b}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${Se} +`,{request:Ve,issuer:Se,dependencyName:b}):X=ts("UNDECLARED_DEPENDENCY",`${S.name} tried to access ${b}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ve?` (via "${Ve}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +`,{request:Ve,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b}));if(R==null){if(J===null||X===null)throw X||new Error("Assertion failed: Expected an error to have been set");R=J;let Fe=X.message.replace(/\n.*/g,"");X.message=Fe,!E.has(Fe)&&o!==0&&(E.add(Fe),process.emitWarning(X))}let $=Array.isArray(R)?{name:R[0],reference:R[1]}:{name:b,reference:R},se=U($);if(!se.packageLocation)throw ts("MISSING_DEPENDENCY",`A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. + +Required package: ${$.name}@${$.reference}${$.name!==Ve?` (via "${Ve}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +`,{request:Ve,issuer:Se,dependencyLocator:Object.assign({},$)});let be=se.packageLocation;w?tt=K.join(be,w):tt=be}else if(K.isAbsolute(Ne))tt=K.normalize(Ne);else{if(!Te)throw ts("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:Ve,issuer:Se});let b=K.resolve(Te);Te.match(u)?tt=K.normalize(K.join(b,Ne)):tt=K.normalize(K.join(K.dirname(b),Ne))}return K.normalize(tt)}function xe(Ne,Te,ke=te,Ve){if(n.test(Ne))return Te;let Se=le(Te,ke,Ve);return Se?K.normalize(Se):Te}function Re(Ne,{extensions:Te=Object.keys(tp.Module._extensions)}={}){let ke=[],Ve=ce(Ne,ke,{extensions:Te});if(Ve)return K.normalize(Ve);{Q1e(ke.map(He=>Ae.fromPortablePath(He)));let Se=pu(Ne),tt=fe(Ne);if(tt){let{packageLocation:He}=U(tt),b=!0;try{e.fakeFs.accessSync(He)}catch(w){if(w?.code==="ENOENT")b=!1;else{let S=(w?.message??w??"empty exception thrown").replace(/^[A-Z]/,y=>y.toLowerCase());throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`Required package exists but could not be accessed (${S}). + +Missing package: ${tt.name}@${tt.reference} +Expected package location: ${pu(He)} +`,{unqualifiedPath:Se,extensions:Te})}}if(!b){let w=He.includes("/unplugged/")?"Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).":"Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.";throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`${w} + +Missing package: ${tt.name}@${tt.reference} +Expected package location: ${pu(He)} +`,{unqualifiedPath:Se,extensions:Te})}}throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`Qualified path resolution failed: we looked for the following paths, but none could be accessed. + +Source path: ${Se} +${ke.map(He=>`Not found: ${pu(He)} +`).join("")}`,{unqualifiedPath:Se,extensions:Te})}}function gt(Ne,Te,ke){if(!Te)throw new Error("Assertion failed: An issuer is required to resolve private import mappings");let Ve=v1e({name:Ne,base:(0,fd.pathToFileURL)(Ae.fromPortablePath(Te)),conditions:ke.conditions??te,readFileSyncFn:ie});if(Ve instanceof URL)return Re(Ae.toPortablePath((0,fd.fileURLToPath)(Ve)),{extensions:ke.extensions});if(Ve.startsWith("#"))throw new Error("Mapping from one private import to another isn't allowed");return q(Ve,Te,ke)}function q(Ne,Te,ke={}){try{if(Ne.startsWith("#"))return gt(Ne,Te,ke);let{considerBuiltins:Ve,extensions:Se,conditions:tt}=ke,He=Z(Ne,Te,{considerBuiltins:Ve});if(Ne==="pnpapi")return He;if(He===null)return null;let b=()=>Te!==null?he(Te):!1,w=(!Ve||!(0,tp.isBuiltin)(Ne))&&!b()?xe(Ne,He,tt,Te):He;return Re(w,{extensions:Se})}catch(Ve){throw Object.hasOwn(Ve,"pnpCode")&&Object.assign(Ve.data,{request:pu(Ne),issuer:Te&&pu(Te)}),Ve}}function nt(Ne){let Te=K.normalize(Ne),ke=qs.resolveVirtual(Te);return ke!==Te?ke:null}return{VERSIONS:De,topLevel:Ee,getLocator:(Ne,Te)=>Array.isArray(Te)?{name:Te[0],reference:Te[1]}:{name:Ne,reference:Te},getDependencyTreeRoots:()=>[...t.dependencyTreeRoots],getAllLocators(){let Ne=[];for(let[Te,ke]of D)for(let Ve of ke.keys())Te!==null&&Ve!==null&&Ne.push({name:Te,reference:Ve});return Ne},getPackageInformation:Ne=>{let Te=g(Ne);if(Te===null)return null;let ke=Ae.fromPortablePath(Te.packageLocation);return{...Te,packageLocation:ke}},findPackageLocator:Ne=>fe(Ae.toPortablePath(Ne)),resolveToUnqualified:L("resolveToUnqualified",(Ne,Te,ke)=>{let Ve=Te!==null?Ae.toPortablePath(Te):null,Se=Z(Ae.toPortablePath(Ne),Ve,ke);return Se===null?null:Ae.fromPortablePath(Se)}),resolveUnqualified:L("resolveUnqualified",(Ne,Te)=>Ae.fromPortablePath(Re(Ae.toPortablePath(Ne),Te))),resolveRequest:L("resolveRequest",(Ne,Te,ke)=>{let Ve=Te!==null?Ae.toPortablePath(Te):null,Se=q(Ae.toPortablePath(Ne),Ve,ke);return Se===null?null:Ae.fromPortablePath(Se)}),resolveVirtual:L("resolveVirtual",Ne=>{let Te=nt(Ae.toPortablePath(Ne));return Te!==null?Ae.fromPortablePath(Te):null})}}Pt();var F1e=(t,e,r)=>{let o=gv(t),a=Pj(o,{basePath:e}),n=Ae.join(e,mr.pnpCjs);return Mj(a,{fakeFs:r,pnpapiResolution:n})};var Uj=et(T1e());Gt();var CA={};Kt(CA,{checkManifestCompatibility:()=>N1e,extractBuildRequest:()=>ZQ,getExtractHint:()=>_j,hasBindingGyp:()=>Hj});Ke();Pt();function N1e(t){return G.isPackageCompatible(t,Xi.getArchitectureSet())}function ZQ(t,e,r,{configuration:o}){let a=[];for(let n of["preinstall","install","postinstall"])e.manifest.scripts.has(n)&&a.push({type:0,script:n});return!e.manifest.scripts.has("install")&&e.misc.hasBindingGyp&&a.push({type:1,script:"node-gyp rebuild"}),a.length===0?null:t.linkType!=="HARD"?{skipped:!0,explain:n=>n.reportWarningOnce(6,`${G.prettyLocator(o,t)} lists build scripts, but is referenced through a soft link. Soft links don't support build scripts, so they'll be ignored.`)}:r&&r.built===!1?{skipped:!0,explain:n=>n.reportInfoOnce(5,`${G.prettyLocator(o,t)} lists build scripts, but its build has been explicitly disabled through configuration.`)}:!o.get("enableScripts")&&!r.built?{skipped:!0,explain:n=>n.reportWarningOnce(4,`${G.prettyLocator(o,t)} lists build scripts, but all build scripts have been disabled.`)}:N1e(t)?{skipped:!1,directives:a}:{skipped:!0,explain:n=>n.reportWarningOnce(76,`${G.prettyLocator(o,t)} The ${Xi.getArchitectureName()} architecture is incompatible with this package, build skipped.`)}}var vIt=new Set([".exe",".bin",".h",".hh",".hpp",".c",".cc",".cpp",".java",".jar",".node"]);function _j(t){return t.packageFs.getExtractHint({relevantExtensions:vIt})}function Hj(t){let e=K.join(t.prefixPath,"binding.gyp");return t.packageFs.existsSync(e)}var vv={};Kt(vv,{getUnpluggedPath:()=>Bv});Ke();Pt();function Bv(t,{configuration:e}){return K.resolve(e.get("pnpUnpluggedFolder"),G.slugifyLocator(t))}var DIt=new Set([G.makeIdent(null,"open").identHash,G.makeIdent(null,"opn").identHash]),Wh=class{constructor(){this.mode="strict";this.pnpCache=new Map}getCustomDataKey(){return JSON.stringify({name:"PnpLinker",version:2})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the PnP linker to be enabled");let o=Kh(r.project).cjs;if(!ae.existsSync(o))throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let a=qe.getFactoryWithDefault(this.pnpCache,o,()=>qe.dynamicRequire(o,{cachingStrategy:qe.CachingStrategy.FsTime})),n={name:G.stringifyIdent(e),reference:e.reference},u=a.getPackageInformation(n);if(!u)throw new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed PnP map - running an install might help`);return Ae.toPortablePath(u.packageLocation)}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=Kh(r.project).cjs;if(!ae.existsSync(o))return null;let n=qe.getFactoryWithDefault(this.pnpCache,o,()=>qe.dynamicRequire(o,{cachingStrategy:qe.CachingStrategy.FsTime})).findPackageLocator(Ae.fromPortablePath(e));return n?G.makeLocator(G.parseIdent(n.name),n.reference):null}makeInstaller(e){return new pd(e)}isEnabled(e){return!(e.project.configuration.get("nodeLinker")!=="pnp"||e.project.configuration.get("pnpMode")!==this.mode)}},pd=class{constructor(e){this.opts=e;this.mode="strict";this.asyncActions=new qe.AsyncActions(10);this.packageRegistry=new Map;this.virtualTemplates=new Map;this.isESMLoaderRequired=!1;this.customData={store:new Map};this.unpluggedPaths=new Set;this.opts=e}attachCustomData(e){this.customData=e}async installPackage(e,r,o){let a=G.stringifyIdent(e),n=e.reference,u=!!this.opts.project.tryWorkspaceByLocator(e),A=G.isVirtualLocator(e),p=e.peerDependencies.size>0&&!A,h=!p&&!u,E=!p&&e.linkType!=="SOFT",I,D;if(h||E){let te=A?G.devirtualizeLocator(e):e;I=this.customData.store.get(te.locatorHash),typeof I>"u"&&(I=await PIt(r),e.linkType==="HARD"&&this.customData.store.set(te.locatorHash,I)),I.manifest.type==="module"&&(this.isESMLoaderRequired=!0),D=this.opts.project.getDependencyMeta(te,e.version)}let x=h?ZQ(e,I,D,{configuration:this.opts.project.configuration}):null,C=E?await this.unplugPackageIfNeeded(e,I,r,D,o):r.packageFs;if(K.isAbsolute(r.prefixPath))throw new Error(`Assertion failed: Expected the prefix path (${r.prefixPath}) to be relative to the parent`);let T=K.resolve(C.getRealPath(),r.prefixPath),L=qj(this.opts.project.cwd,T),U=new Map,z=new Set;if(A){for(let te of e.peerDependencies.values())U.set(G.stringifyIdent(te),null),z.add(G.stringifyIdent(te));if(!u){let te=G.devirtualizeLocator(e);this.virtualTemplates.set(te.locatorHash,{location:qj(this.opts.project.cwd,qs.resolveVirtual(T)),locator:te})}}return qe.getMapWithDefault(this.packageRegistry,a).set(n,{packageLocation:L,packageDependencies:U,packagePeers:z,linkType:e.linkType,discardFromLookup:r.discardFromLookup||!1}),{packageLocation:T,buildRequest:x}}async attachInternalDependencies(e,r){let o=this.getPackageInformation(e);for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){for(let o of r)this.getDiskInformation(o).packageDependencies.set(G.stringifyIdent(e),e.reference)}async finalizeInstall(){if(this.opts.project.configuration.get("pnpMode")!==this.mode)return;let e=Kh(this.opts.project);if(this.isEsmEnabled()||await ae.removePromise(e.esmLoader),this.opts.project.configuration.get("nodeLinker")!=="pnp"){await ae.removePromise(e.cjs),await ae.removePromise(e.data),await ae.removePromise(e.esmLoader),await ae.removePromise(this.opts.project.configuration.get("pnpUnpluggedFolder"));return}for(let{locator:E,location:I}of this.virtualTemplates.values())qe.getMapWithDefault(this.packageRegistry,G.stringifyIdent(E)).set(E.reference,{packageLocation:I,packageDependencies:new Map,packagePeers:new Set,linkType:"SOFT",discardFromLookup:!1});this.packageRegistry.set(null,new Map([[null,this.getPackageInformation(this.opts.project.topLevelWorkspace.anchoredLocator)]]));let r=this.opts.project.configuration.get("pnpFallbackMode"),o=this.opts.project.workspaces.map(({anchoredLocator:E})=>({name:G.stringifyIdent(E),reference:E.reference})),a=r!=="none",n=[],u=new Map,A=qe.buildIgnorePattern([".yarn/sdks/**",...this.opts.project.configuration.get("pnpIgnorePatterns")]),p=this.packageRegistry,h=this.opts.project.configuration.get("pnpShebang");if(r==="dependencies-only")for(let E of this.opts.project.storedPackages.values())this.opts.project.tryWorkspaceByLocator(E)&&n.push({name:G.stringifyIdent(E),reference:E.reference});return await this.asyncActions.wait(),await this.finalizeInstallWithPnp({dependencyTreeRoots:o,enableTopLevelFallback:a,fallbackExclusionList:n,fallbackPool:u,ignorePattern:A,packageRegistry:p,shebang:h}),{customData:this.customData}}async transformPnpSettings(e){}isEsmEnabled(){if(this.opts.project.configuration.sources.has("pnpEnableEsmLoader"))return this.opts.project.configuration.get("pnpEnableEsmLoader");if(this.isESMLoaderRequired)return!0;for(let e of this.opts.project.workspaces)if(e.manifest.type==="module")return!0;return!1}async finalizeInstallWithPnp(e){let r=Kh(this.opts.project),o=await this.locateNodeModules(e.ignorePattern);if(o.length>0){this.opts.report.reportWarning(31,"One or more node_modules have been detected and will be removed. This operation may take some time.");for(let n of o)await ae.removePromise(n)}if(await this.transformPnpSettings(e),this.opts.project.configuration.get("pnpEnableInlining")){let n=l1e(e);await ae.changeFilePromise(r.cjs,n,{automaticNewlines:!0,mode:493}),await ae.removePromise(r.data)}else{let{dataFile:n,loaderFile:u}=c1e(e);await ae.changeFilePromise(r.cjs,u,{automaticNewlines:!0,mode:493}),await ae.changeFilePromise(r.data,n,{automaticNewlines:!0,mode:420})}this.isEsmEnabled()&&(this.opts.report.reportWarning(0,"ESM support for PnP uses the experimental loader API and is therefore experimental"),await ae.changeFilePromise(r.esmLoader,(0,Uj.default)(),{automaticNewlines:!0,mode:420}));let a=this.opts.project.configuration.get("pnpUnpluggedFolder");if(this.unpluggedPaths.size===0)await ae.removePromise(a);else for(let n of await ae.readdirPromise(a)){let u=K.resolve(a,n);this.unpluggedPaths.has(u)||await ae.removePromise(u)}}async locateNodeModules(e){let r=[],o=e?new RegExp(e):null;for(let a of this.opts.project.workspaces){let n=K.join(a.cwd,"node_modules");if(o&&o.test(K.relative(this.opts.project.cwd,a.cwd))||!ae.existsSync(n))continue;let u=await ae.readdirPromise(n,{withFileTypes:!0}),A=u.filter(p=>!p.isDirectory()||p.name===".bin"||!p.name.startsWith("."));if(A.length===u.length)r.push(n);else for(let p of A)r.push(K.join(n,p.name))}return r}async unplugPackageIfNeeded(e,r,o,a,n){return this.shouldBeUnplugged(e,r,a)?this.unplugPackage(e,o,n):o.packageFs}shouldBeUnplugged(e,r,o){return typeof o.unplugged<"u"?o.unplugged:DIt.has(e.identHash)||e.conditions!=null?!0:r.manifest.preferUnplugged!==null?r.manifest.preferUnplugged:!!(ZQ(e,r,o,{configuration:this.opts.project.configuration})?.skipped===!1||r.misc.extractHint)}async unplugPackage(e,r,o){let a=Bv(e,{configuration:this.opts.project.configuration});return this.opts.project.disabledLocators.has(e.locatorHash)?new ju(a,{baseFs:r.packageFs,pathUtils:K}):(this.unpluggedPaths.add(a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{let n=K.join(a,r.prefixPath,".ready");await ae.existsPromise(n)||(this.opts.project.storedBuildState.delete(e.locatorHash),await ae.mkdirPromise(a,{recursive:!0}),await ae.copyPromise(a,Bt.dot,{baseFs:r.packageFs,overwrite:!1}),await ae.writeFilePromise(n,""))})),new En(a))}getPackageInformation(e){let r=G.stringifyIdent(e),o=e.reference,a=this.packageRegistry.get(r);if(!a)throw new Error(`Assertion failed: The package information store should have been available (for ${G.prettyIdent(this.opts.project.configuration,e)})`);let n=a.get(o);if(!n)throw new Error(`Assertion failed: The package information should have been available (for ${G.prettyLocator(this.opts.project.configuration,e)})`);return n}getDiskInformation(e){let r=qe.getMapWithDefault(this.packageRegistry,"@@disk"),o=qj(this.opts.project.cwd,e);return qe.getFactoryWithDefault(r,o,()=>({packageLocation:o,packageDependencies:new Map,packagePeers:new Set,linkType:"SOFT",discardFromLookup:!1}))}};function qj(t,e){let r=K.relative(t,e);return r.match(/^\.{0,2}\//)||(r=`./${r}`),r.replace(/\/?$/,"/")}async function PIt(t){let e=await _t.tryFind(t.prefixPath,{baseFs:t.packageFs})??new _t,r=new Set(["preinstall","install","postinstall"]);for(let o of e.scripts.keys())r.has(o)||e.scripts.delete(o);return{manifest:{scripts:e.scripts,preferUnplugged:e.preferUnplugged,type:e.type},misc:{extractHint:_j(t),hasBindingGyp:Hj(t)}}}Ke();Ke();Gt();var L1e=et(Xo());var QC=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Unplug direct dependencies from the entire project"});this.recursive=de.Boolean("-R,--recursive",!1,{description:"Unplug both direct and transitive dependencies"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.patterns=de.Rest()}static{this.paths=[["unplug"]]}static{this.usage=st.Usage({description:"force the unpacking of a list of packages",details:"\n This command will add the selectors matching the specified patterns to the list of packages that must be unplugged when installed.\n\n A package being unplugged means that instead of being referenced directly through its archive, it will be unpacked at install time in the directory configured via `pnpUnpluggedFolder`. Note that unpacking packages this way is generally not recommended because it'll make it harder to store your packages within the repository. However, it's a good approach to quickly and safely debug some packages, and can even sometimes be required depending on the context (for example when the package contains shellscripts).\n\n Running the command will set a persistent flag inside your top-level `package.json`, in the `dependenciesMeta` field. As such, to undo its effects, you'll need to revert the changes made to the manifest and run `yarn install` to apply the modification.\n\n By default, only direct dependencies from the current workspace are affected. If `-A,--all` is set, direct dependencies from the entire project are affected. Using the `-R,--recursive` flag will affect transitive dependencies as well as direct ones.\n\n This command accepts glob patterns inside the scope and name components (not the range). Make sure to escape the patterns to prevent your own shell from trying to expand them.\n ",examples:[["Unplug the lodash dependency from the active workspace","yarn unplug lodash"],["Unplug all instances of lodash referenced by any workspace","yarn unplug lodash -A"],["Unplug all instances of lodash referenced by the active workspace and its dependencies","yarn unplug lodash -R"],["Unplug all instances of lodash, anywhere","yarn unplug lodash -AR"],["Unplug one specific version of lodash","yarn unplug lodash@1.2.3"],["Unplug all packages with the `@babel` scope","yarn unplug '@babel/*'"],["Unplug all packages (only for testing, not recommended)","yarn unplug -R '*'"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);if(r.get("nodeLinker")!=="pnp")throw new ot("This command can only be used if the `nodeLinker` option is set to `pnp`");await o.restoreInstallState();let u=new Set(this.patterns),A=this.patterns.map(x=>{let C=G.parseDescriptor(x),T=C.range!=="unknown"?C:G.makeDescriptor(C,"*");if(!Ur.validRange(T.range))throw new ot(`The range of the descriptor patterns must be a valid semver range (${G.prettyDescriptor(r,T)})`);return L=>{let U=G.stringifyIdent(L);return!L1e.default.isMatch(U,G.stringifyIdent(T))||L.version&&!Ur.satisfiesWithPrereleases(L.version,T.range)?!1:(u.delete(x),!0)}}),p=()=>{let x=[];for(let C of o.storedPackages.values())!o.tryWorkspaceByLocator(C)&&!G.isVirtualLocator(C)&&A.some(T=>T(C))&&x.push(C);return x},h=x=>{let C=new Set,T=[],L=(U,z)=>{if(C.has(U.locatorHash))return;let te=!!o.tryWorkspaceByLocator(U);if(!(z>0&&!this.recursive&&te)&&(C.add(U.locatorHash),!o.tryWorkspaceByLocator(U)&&A.some(le=>le(U))&&T.push(U),!(z>0&&!this.recursive)))for(let le of U.dependencies.values()){let ce=o.storedResolutions.get(le.descriptorHash);if(!ce)throw new Error("Assertion failed: The resolution should have been registered");let ue=o.storedPackages.get(ce);if(!ue)throw new Error("Assertion failed: The package should have been registered");L(ue,z+1)}};for(let U of x)L(U.anchoredPackage,0);return T},E,I;if(this.all&&this.recursive?(E=p(),I="the project"):this.all?(E=h(o.workspaces),I="any workspace"):(E=h([a]),I="this workspace"),u.size>1)throw new ot(`Patterns ${pe.prettyList(r,u,pe.Type.CODE)} don't match any packages referenced by ${I}`);if(u.size>0)throw new ot(`Pattern ${pe.prettyList(r,u,pe.Type.CODE)} doesn't match any packages referenced by ${I}`);E=qe.sortMap(E,x=>G.stringifyLocator(x));let D=await Nt.start({configuration:r,stdout:this.context.stdout,json:this.json},async x=>{for(let C of E){let T=C.version??"unknown",L=o.topLevelWorkspace.manifest.ensureDependencyMeta(G.makeDescriptor(C,T));L.unplugged=!0,x.reportInfo(0,`Will unpack ${G.prettyLocator(r,C)} to ${pe.pretty(r,Bv(C,{configuration:r}),pe.Type.PATH)}`),x.reportJson({locator:G.stringifyLocator(C),version:T})}await o.topLevelWorkspace.persistManifest(),this.json||x.reportSeparator()});return D.hasErrors()?D.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};var Kh=t=>({cjs:K.join(t.cwd,mr.pnpCjs),data:K.join(t.cwd,mr.pnpData),esmLoader:K.join(t.cwd,mr.pnpEsmLoader)}),O1e=t=>/\s/.test(t)?JSON.stringify(t):t;async function SIt(t,e,r){let o=/\s*--require\s+\S*\.pnp\.c?js\s*/g,a=/\s*--experimental-loader\s+\S*\.pnp\.loader\.mjs\s*/,n=(e.NODE_OPTIONS??"").replace(o," ").replace(a," ").trim();if(t.configuration.get("nodeLinker")!=="pnp"){e.NODE_OPTIONS=n||void 0;return}let u=Kh(t),A=`--require ${O1e(Ae.fromPortablePath(u.cjs))}`;ae.existsSync(u.esmLoader)&&(A=`${A} --experimental-loader ${(0,M1e.pathToFileURL)(Ae.fromPortablePath(u.esmLoader)).href}`),ae.existsSync(u.cjs)&&(e.NODE_OPTIONS=n?`${A} ${n}`:A)}async function bIt(t,e){let r=Kh(t);e(r.cjs),e(r.data),e(r.esmLoader),e(t.configuration.get("pnpUnpluggedFolder"))}var xIt={hooks:{populateYarnPaths:bIt,setupScriptEnvironment:SIt},configuration:{nodeLinker:{description:'The linker used for installing Node packages, one of: "pnp", "pnpm", or "node-modules"',type:"STRING",default:"pnp"},winLinkType:{description:"Whether Yarn should use Windows Junctions or symlinks when creating links on Windows.",type:"STRING",values:["junctions","symlinks"],default:"junctions"},pnpMode:{description:"If 'strict', generates standard PnP maps. If 'loose', merges them with the n_m resolution.",type:"STRING",default:"strict"},pnpShebang:{description:"String to prepend to the generated PnP script",type:"STRING",default:"#!/usr/bin/env node"},pnpIgnorePatterns:{description:"Array of glob patterns; files matching them will use the classic resolution",type:"STRING",default:[],isArray:!0},pnpEnableEsmLoader:{description:"If true, Yarn will generate an ESM loader (`.pnp.loader.mjs`). If this is not explicitly set Yarn tries to automatically detect whether ESM support is required.",type:"BOOLEAN",default:!1},pnpEnableInlining:{description:"If true, the PnP data will be inlined along with the generated loader",type:"BOOLEAN",default:!0},pnpFallbackMode:{description:"If true, the generated PnP loader will follow the top-level fallback rule",type:"STRING",default:"dependencies-only"},pnpUnpluggedFolder:{description:"Folder where the unplugged packages must be stored",type:"ABSOLUTE_PATH",default:"./.yarn/unplugged"}},linkers:[Wh],commands:[QC]},kIt=xIt;var W1e=et(j1e());Gt();var Jj=et(ve("crypto")),K1e=et(ve("fs")),V1e=1,bi="node_modules",$Q=".bin",z1e=".yarn-state.yml",KIt=1e3,Xj=(o=>(o.CLASSIC="classic",o.HARDLINKS_LOCAL="hardlinks-local",o.HARDLINKS_GLOBAL="hardlinks-global",o))(Xj||{}),Dv=class{constructor(){this.installStateCache=new Map}getCustomDataKey(){return JSON.stringify({name:"NodeModulesLinker",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the node-modules linker to be enabled");let o=r.project.tryWorkspaceByLocator(e);if(o)return o.cwd;let a=await qe.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await zj(r.project,{unrollAliases:!0}));if(a===null)throw new ot("Couldn't find the node_modules state file - running an install might help (findPackageLocation)");let n=a.locatorMap.get(G.stringifyLocator(e));if(!n){let p=new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed node_modules map - running an install might help`);throw p.code="LOCATOR_NOT_INSTALLED",p}let u=n.locations.sort((p,h)=>p.split(K.sep).length-h.split(K.sep).length),A=K.join(r.project.configuration.startingCwd,bi);return u.find(p=>K.contains(A,p))||n.locations[0]}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=await qe.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await zj(r.project,{unrollAliases:!0}));if(o===null)return null;let{locationRoot:a,segments:n}=eF(K.resolve(e),{skipPrefix:r.project.cwd}),u=o.locationTree.get(a);if(!u)return null;let A=u.locator;for(let p of n){if(u=u.children.get(p),!u)break;A=u.locator||A}return G.parseLocator(A)}makeInstaller(e){return new Vj(e)}isEnabled(e){return e.project.configuration.get("nodeLinker")==="node-modules"}},Vj=class{constructor(e){this.opts=e;this.localStore=new Map;this.realLocatorChecksums=new Map;this.customData={store:new Map}}attachCustomData(e){this.customData=e}async installPackage(e,r){let o=K.resolve(r.packageFs.getRealPath(),r.prefixPath),a=this.customData.store.get(e.locatorHash);if(typeof a>"u"&&(a=await VIt(e,r),e.linkType==="HARD"&&this.customData.store.set(e.locatorHash,a)),!G.isPackageCompatible(e,this.opts.project.configuration.getSupportedArchitectures()))return{packageLocation:null,buildRequest:null};let n=new Map,u=new Set;n.has(G.stringifyIdent(e))||n.set(G.stringifyIdent(e),e.reference);let A=e;if(G.isVirtualLocator(e)){A=G.devirtualizeLocator(e);for(let E of e.peerDependencies.values())n.set(G.stringifyIdent(E),null),u.add(G.stringifyIdent(E))}let p={packageLocation:`${Ae.fromPortablePath(o)}/`,packageDependencies:n,packagePeers:u,linkType:e.linkType,discardFromLookup:r.discardFromLookup??!1};this.localStore.set(e.locatorHash,{pkg:e,customPackageData:a,dependencyMeta:this.opts.project.getDependencyMeta(e,e.version),pnpNode:p});let h=r.checksum?r.checksum.substring(r.checksum.indexOf("/")+1):null;return this.realLocatorChecksums.set(A.locatorHash,h),{packageLocation:o,buildRequest:null}}async attachInternalDependencies(e,r){let o=this.localStore.get(e.locatorHash);if(typeof o>"u")throw new Error("Assertion failed: Expected information object to have been registered");for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.pnpNode.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){throw new Error("External dependencies haven't been implemented for the node-modules linker")}async finalizeInstall(){if(this.opts.project.configuration.get("nodeLinker")!=="node-modules")return;let e=new qs({baseFs:new iA({maxOpenFiles:80,readOnlyArchives:!0})}),r=await zj(this.opts.project),o=this.opts.project.configuration.get("nmMode");(r===null||o!==r.nmMode)&&(this.opts.project.storedBuildState.clear(),r={locatorMap:new Map,binSymlinks:new Map,locationTree:new Map,nmMode:o,mtimeMs:0});let a=new Map(this.opts.project.workspaces.map(D=>{let x=this.opts.project.configuration.get("nmHoistingLimits");try{x=qe.validateEnum(fv,D.manifest.installConfig?.hoistingLimits??x)}catch{let T=G.prettyWorkspace(this.opts.project.configuration,D);this.opts.report.reportWarning(57,`${T}: Invalid 'installConfig.hoistingLimits' value. Expected one of ${Object.values(fv).join(", ")}, using default: "${x}"`)}return[D.relativeCwd,x]})),n=new Map(this.opts.project.workspaces.map(D=>{let x=this.opts.project.configuration.get("nmSelfReferences");return x=D.manifest.installConfig?.selfReferences??x,[D.relativeCwd,x]})),u={VERSIONS:{std:1},topLevel:{name:null,reference:null},getLocator:(D,x)=>Array.isArray(x)?{name:x[0],reference:x[1]}:{name:D,reference:x},getDependencyTreeRoots:()=>this.opts.project.workspaces.map(D=>{let x=D.anchoredLocator;return{name:G.stringifyIdent(x),reference:x.reference}}),getPackageInformation:D=>{let x=D.reference===null?this.opts.project.topLevelWorkspace.anchoredLocator:G.makeLocator(G.parseIdent(D.name),D.reference),C=this.localStore.get(x.locatorHash);if(typeof C>"u")throw new Error("Assertion failed: Expected the package reference to have been registered");return C.pnpNode},findPackageLocator:D=>{let x=this.opts.project.tryWorkspaceByCwd(Ae.toPortablePath(D));if(x!==null){let C=x.anchoredLocator;return{name:G.stringifyIdent(C),reference:C.reference}}throw new Error("Assertion failed: Unimplemented")},resolveToUnqualified:()=>{throw new Error("Assertion failed: Unimplemented")},resolveUnqualified:()=>{throw new Error("Assertion failed: Unimplemented")},resolveRequest:()=>{throw new Error("Assertion failed: Unimplemented")},resolveVirtual:D=>Ae.fromPortablePath(qs.resolveVirtual(Ae.toPortablePath(D)))},{tree:A,errors:p,preserveSymlinksRequired:h}=pv(u,{pnpifyFs:!1,validateExternalSoftLinks:!0,hoistingLimitsByCwd:a,project:this.opts.project,selfReferencesByCwd:n});if(!A){for(let{messageName:D,text:x}of p)this.opts.report.reportError(D,x);return}let E=vj(A);await e1t(r,E,{baseFs:e,project:this.opts.project,report:this.opts.report,realLocatorChecksums:this.realLocatorChecksums,loadManifest:async D=>{let x=G.parseLocator(D),C=this.localStore.get(x.locatorHash);if(typeof C>"u")throw new Error("Assertion failed: Expected the slot to exist");return C.customPackageData.manifest}});let I=[];for(let[D,x]of E.entries()){if(Z1e(D))continue;let C=G.parseLocator(D),T=this.localStore.get(C.locatorHash);if(typeof T>"u")throw new Error("Assertion failed: Expected the slot to exist");if(this.opts.project.tryWorkspaceByLocator(T.pkg))continue;let L=CA.extractBuildRequest(T.pkg,T.customPackageData,T.dependencyMeta,{configuration:this.opts.project.configuration});L&&I.push({buildLocations:x.locations,locator:C,buildRequest:L})}return h&&this.opts.report.reportWarning(72,`The application uses portals and that's why ${pe.pretty(this.opts.project.configuration,"--preserve-symlinks",pe.Type.CODE)} Node option is required for launching it`),{customData:this.customData,records:I}}};async function VIt(t,e){let r=await _t.tryFind(e.prefixPath,{baseFs:e.packageFs})??new _t,o=new Set(["preinstall","install","postinstall"]);for(let a of r.scripts.keys())o.has(a)||r.scripts.delete(a);return{manifest:{bin:r.bin,scripts:r.scripts},misc:{hasBindingGyp:CA.hasBindingGyp(e)}}}async function zIt(t,e,r,o,{installChangedByUser:a}){let n="";n+=`# Warning: This file is automatically generated. Removing it is fine, but will +`,n+=`# cause your node_modules installation to become invalidated. +`,n+=` +`,n+=`__metadata: +`,n+=` version: ${V1e} +`,n+=` nmMode: ${o.value} +`;let u=Array.from(e.keys()).sort(),A=G.stringifyLocator(t.topLevelWorkspace.anchoredLocator);for(let E of u){let I=e.get(E);n+=` +`,n+=`${JSON.stringify(E)}: +`,n+=` locations: +`;for(let D of I.locations){let x=K.contains(t.cwd,D);if(x===null)throw new Error(`Assertion failed: Expected the path to be within the project (${D})`);n+=` - ${JSON.stringify(x)} +`}if(I.aliases.length>0){n+=` aliases: +`;for(let D of I.aliases)n+=` - ${JSON.stringify(D)} +`}if(E===A&&r.size>0){n+=` bin: +`;for(let[D,x]of r){let C=K.contains(t.cwd,D);if(C===null)throw new Error(`Assertion failed: Expected the path to be within the project (${D})`);n+=` ${JSON.stringify(C)}: +`;for(let[T,L]of x){let U=K.relative(K.join(D,bi),L);n+=` ${JSON.stringify(T)}: ${JSON.stringify(U)} +`}}}}let p=t.cwd,h=K.join(p,bi,z1e);a&&await ae.removePromise(h),await ae.changeFilePromise(h,n,{automaticNewlines:!0})}async function zj(t,{unrollAliases:e=!1}={}){let r=t.cwd,o=K.join(r,bi,z1e),a;try{a=await ae.statPromise(o)}catch{}if(!a)return null;let n=Ki(await ae.readFilePromise(o,"utf8"));if(n.__metadata.version>V1e)return null;let u=n.__metadata.nmMode||"classic",A=new Map,p=new Map;delete n.__metadata;for(let[h,E]of Object.entries(n)){let I=E.locations.map(x=>K.join(r,x)),D=E.bin;if(D)for(let[x,C]of Object.entries(D)){let T=K.join(r,Ae.toPortablePath(x)),L=qe.getMapWithDefault(p,T);for(let[U,z]of Object.entries(C))L.set(U,Ae.toPortablePath([T,bi,z].join(K.sep)))}if(A.set(h,{target:Bt.dot,linkType:"HARD",locations:I,aliases:E.aliases||[]}),e&&E.aliases)for(let x of E.aliases){let{scope:C,name:T}=G.parseLocator(h),L=G.makeLocator(G.makeIdent(C,T),x),U=G.stringifyLocator(L);A.set(U,{target:Bt.dot,linkType:"HARD",locations:I,aliases:[]})}}return{locatorMap:A,binSymlinks:p,locationTree:J1e(A,{skipPrefix:t.cwd}),nmMode:u,mtimeMs:a.mtimeMs}}var RC=async(t,e)=>{if(t.split(K.sep).indexOf(bi)<0)throw new Error(`Assertion failed: trying to remove dir that doesn't contain node_modules: ${t}`);try{let r;if(!e.innerLoop&&(r=await ae.lstatPromise(t),!r.isDirectory()&&!r.isSymbolicLink()||r.isSymbolicLink()&&!e.isWorkspaceDir)){await ae.unlinkPromise(t);return}let o=await ae.readdirPromise(t,{withFileTypes:!0});for(let n of o){let u=K.join(t,n.name);n.isDirectory()?(n.name!==bi||e&&e.innerLoop)&&await RC(u,{innerLoop:!0,contentsOnly:!1}):await ae.unlinkPromise(u)}let a=!e.innerLoop&&e.isWorkspaceDir&&r?.isSymbolicLink();!e.contentsOnly&&!a&&await ae.rmdirPromise(t)}catch(r){if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw r}},G1e=4,eF=(t,{skipPrefix:e})=>{let r=K.contains(e,t);if(r===null)throw new Error(`Assertion failed: Writing attempt prevented to ${t} which is outside project root: ${e}`);let o=r.split(K.sep).filter(p=>p!==""),a=o.indexOf(bi),n=o.slice(0,a).join(K.sep),u=K.join(e,n),A=o.slice(a);return{locationRoot:u,segments:A}},J1e=(t,{skipPrefix:e})=>{let r=new Map;if(t===null)return r;let o=()=>({children:new Map,linkType:"HARD"});for(let[a,n]of t.entries()){if(n.linkType==="SOFT"&&K.contains(e,n.target)!==null){let A=qe.getFactoryWithDefault(r,n.target,o);A.locator=a,A.linkType=n.linkType}for(let u of n.locations){let{locationRoot:A,segments:p}=eF(u,{skipPrefix:e}),h=qe.getFactoryWithDefault(r,A,o);for(let E=0;E{if(process.platform==="win32"&&r==="junctions"){let o;try{o=await ae.lstatPromise(t)}catch{}if(!o||o.isDirectory()){await ae.symlinkPromise(t,e,"junction");return}}await ae.symlinkPromise(K.relative(K.dirname(e),t),e)};async function X1e(t,e,r){let o=K.join(t,`${Jj.default.randomBytes(16).toString("hex")}.tmp`);try{await ae.writeFilePromise(o,r);try{await ae.linkPromise(o,e)}catch{}}finally{await ae.unlinkPromise(o)}}async function JIt({srcPath:t,dstPath:e,entry:r,globalHardlinksStore:o,baseFs:a,nmMode:n}){if(r.kind==="file"){if(n.value==="hardlinks-global"&&o&&r.digest){let A=K.join(o,r.digest.substring(0,2),`${r.digest.substring(2)}.dat`),p;try{let h=await ae.statPromise(A);if(h&&(!r.mtimeMs||h.mtimeMs>r.mtimeMs||h.mtimeMs{await ae.mkdirPromise(t,{recursive:!0});let A=async(E=Bt.dot)=>{let I=K.join(e,E),D=await r.readdirPromise(I,{withFileTypes:!0}),x=new Map;for(let C of D){let T=K.join(E,C.name),L,U=K.join(I,C.name);if(C.isFile()){if(L={kind:"file",mode:(await r.lstatPromise(U)).mode},a.value==="hardlinks-global"){let z=await xn.checksumFile(U,{baseFs:r,algorithm:"sha1"});L.digest=z}}else if(C.isDirectory())L={kind:"directory"};else if(C.isSymbolicLink())L={kind:"symlink",symlinkTo:await r.readlinkPromise(U)};else throw new Error(`Unsupported file type (file: ${U}, mode: 0o${await r.statSync(U).mode.toString(8).padStart(6,"0")})`);if(x.set(T,L),C.isDirectory()&&T!==bi){let z=await A(T);for(let[te,le]of z)x.set(te,le)}}return x},p;if(a.value==="hardlinks-global"&&o&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);try{p=new Map(Object.entries(JSON.parse(await ae.readFilePromise(E,"utf8"))))}catch{p=await A()}}else p=await A();let h=!1;for(let[E,I]of p){let D=K.join(e,E),x=K.join(t,E);if(I.kind==="directory")await ae.mkdirPromise(x,{recursive:!0});else if(I.kind==="file"){let C=I.mtimeMs;await JIt({srcPath:D,dstPath:x,entry:I,nmMode:a,baseFs:r,globalHardlinksStore:o}),I.mtimeMs!==C&&(h=!0)}else I.kind==="symlink"&&await Zj(K.resolve(K.dirname(x),I.symlinkTo),x,n)}if(a.value==="hardlinks-global"&&o&&h&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);await ae.removePromise(E),await X1e(o,E,Buffer.from(JSON.stringify(Object.fromEntries(p))))}};function ZIt(t,e,r,o){let a=new Map,n=new Map,u=new Map,A=!1,p=(h,E,I,D,x)=>{let C=!0,T=K.join(h,E),L=new Set;if(E===bi||E.startsWith("@")){let z;try{z=ae.statSync(T)}catch{}C=!!z,z?z.mtimeMs>r?(A=!0,L=new Set(ae.readdirSync(T))):L=new Set(I.children.get(E).children.keys()):A=!0;let te=e.get(h);if(te){let le=K.join(h,bi,$Q),ce;try{ce=ae.statSync(le)}catch{}if(!ce)A=!0;else if(ce.mtimeMs>r){A=!0;let ue=new Set(ae.readdirSync(le)),Ce=new Map;n.set(h,Ce);for(let[he,De]of te)ue.has(he)&&Ce.set(he,De)}else n.set(h,te)}}else C=x.has(E);let U=I.children.get(E);if(C){let{linkType:z,locator:te}=U,le={children:new Map,linkType:z,locator:te};if(D.children.set(E,le),te){let ce=qe.getSetWithDefault(u,te);ce.add(T),u.set(te,ce)}for(let ce of U.children.keys())p(T,ce,U,le,L)}else U.locator&&o.storedBuildState.delete(G.parseLocator(U.locator).locatorHash)};for(let[h,E]of t){let{linkType:I,locator:D}=E,x={children:new Map,linkType:I,locator:D};if(a.set(h,x),D){let C=qe.getSetWithDefault(u,E.locator);C.add(h),u.set(E.locator,C)}E.children.has(bi)&&p(h,bi,E,x,new Set)}return{locationTree:a,binSymlinks:n,locatorLocations:u,installChangedByUser:A}}function Z1e(t){let e=G.parseDescriptor(t);return G.isVirtualDescriptor(e)&&(e=G.devirtualizeDescriptor(e)),e.range.startsWith("link:")}async function $It(t,e,r,{loadManifest:o}){let a=new Map;for(let[A,{locations:p}]of t){let h=Z1e(A)?null:await o(A,p[0]),E=new Map;if(h)for(let[I,D]of h.bin){let x=K.join(p[0],D);D!==""&&ae.existsSync(x)&&E.set(I,D)}a.set(A,E)}let n=new Map,u=(A,p,h)=>{let E=new Map,I=K.contains(r,A);if(h.locator&&I!==null){let D=a.get(h.locator);for(let[x,C]of D){let T=K.join(A,Ae.toPortablePath(C));E.set(x,T)}for(let[x,C]of h.children){let T=K.join(A,x),L=u(T,T,C);L.size>0&&n.set(A,new Map([...n.get(A)||new Map,...L]))}}else for(let[D,x]of h.children){let C=u(K.join(A,D),p,x);for(let[T,L]of C)E.set(T,L)}return E};for(let[A,p]of e){let h=u(A,A,p);h.size>0&&n.set(A,new Map([...n.get(A)||new Map,...h]))}return n}var Y1e=(t,e)=>{if(!t||!e)return t===e;let r=G.parseLocator(t);G.isVirtualLocator(r)&&(r=G.devirtualizeLocator(r));let o=G.parseLocator(e);return G.isVirtualLocator(o)&&(o=G.devirtualizeLocator(o)),G.areLocatorsEqual(r,o)};function $j(t){return K.join(t.get("globalFolder"),"store")}async function e1t(t,e,{baseFs:r,project:o,report:a,loadManifest:n,realLocatorChecksums:u}){let A=K.join(o.cwd,bi),{locationTree:p,binSymlinks:h,locatorLocations:E,installChangedByUser:I}=ZIt(t.locationTree,t.binSymlinks,t.mtimeMs,o),D=J1e(e,{skipPrefix:o.cwd}),x=[],C=async({srcDir:De,dstDir:Ee,linkType:g,globalHardlinksStore:me,nmMode:we,windowsLinkType:fe,packageChecksum:ie})=>{let Z=(async()=>{try{g==="SOFT"?(await ae.mkdirPromise(K.dirname(Ee),{recursive:!0}),await Zj(K.resolve(De),Ee,fe)):await XIt(Ee,De,{baseFs:r,globalHardlinksStore:me,nmMode:we,windowsLinkType:fe,packageChecksum:ie})}catch(xe){throw xe.message=`While persisting ${De} -> ${Ee} ${xe.message}`,xe}finally{le.tick()}})().then(()=>x.splice(x.indexOf(Z),1));x.push(Z),x.length>G1e&&await Promise.race(x)},T=async(De,Ee,g)=>{let me=(async()=>{let we=async(fe,ie,Z)=>{try{Z.innerLoop||await ae.mkdirPromise(ie,{recursive:!0});let xe=await ae.readdirPromise(fe,{withFileTypes:!0});for(let Re of xe){if(!Z.innerLoop&&Re.name===$Q)continue;let gt=K.join(fe,Re.name),q=K.join(ie,Re.name);Re.isDirectory()?(Re.name!==bi||Z&&Z.innerLoop)&&(await ae.mkdirPromise(q,{recursive:!0}),await we(gt,q,{...Z,innerLoop:!0})):Ce.value==="hardlinks-local"||Ce.value==="hardlinks-global"?await ae.linkPromise(gt,q):await ae.copyFilePromise(gt,q,K1e.default.constants.COPYFILE_FICLONE)}}catch(xe){throw Z.innerLoop||(xe.message=`While cloning ${fe} -> ${ie} ${xe.message}`),xe}finally{Z.innerLoop||le.tick()}};await we(De,Ee,g)})().then(()=>x.splice(x.indexOf(me),1));x.push(me),x.length>G1e&&await Promise.race(x)},L=async(De,Ee,g)=>{if(g)for(let[me,we]of Ee.children){let fe=g.children.get(me);await L(K.join(De,me),we,fe)}else{Ee.children.has(bi)&&await RC(K.join(De,bi),{contentsOnly:!1});let me=K.basename(De)===bi&&p.has(K.join(K.dirname(De)));await RC(De,{contentsOnly:De===A,isWorkspaceDir:me})}};for(let[De,Ee]of p){let g=D.get(De);for(let[me,we]of Ee.children){if(me===".")continue;let fe=g&&g.children.get(me),ie=K.join(De,me);await L(ie,we,fe)}}let U=async(De,Ee,g)=>{if(g){Y1e(Ee.locator,g.locator)||await RC(De,{contentsOnly:Ee.linkType==="HARD"});for(let[me,we]of Ee.children){let fe=g.children.get(me);await U(K.join(De,me),we,fe)}}else{Ee.children.has(bi)&&await RC(K.join(De,bi),{contentsOnly:!0});let me=K.basename(De)===bi&&D.has(K.join(K.dirname(De)));await RC(De,{contentsOnly:Ee.linkType==="HARD",isWorkspaceDir:me})}};for(let[De,Ee]of D){let g=p.get(De);for(let[me,we]of Ee.children){if(me===".")continue;let fe=g&&g.children.get(me);await U(K.join(De,me),we,fe)}}let z=new Map,te=[];for(let[De,Ee]of E)for(let g of Ee){let{locationRoot:me,segments:we}=eF(g,{skipPrefix:o.cwd}),fe=D.get(me),ie=me;if(fe){for(let Z of we)if(ie=K.join(ie,Z),fe=fe.children.get(Z),!fe)break;if(fe){let Z=Y1e(fe.locator,De),xe=e.get(fe.locator),Re=xe.target,gt=ie,q=xe.linkType;if(Z)z.has(Re)||z.set(Re,gt);else if(Re!==gt){let nt=G.parseLocator(fe.locator);G.isVirtualLocator(nt)&&(nt=G.devirtualizeLocator(nt)),te.push({srcDir:Re,dstDir:gt,linkType:q,realLocatorHash:nt.locatorHash})}}}}for(let[De,{locations:Ee}]of e.entries())for(let g of Ee){let{locationRoot:me,segments:we}=eF(g,{skipPrefix:o.cwd}),fe=p.get(me),ie=D.get(me),Z=me,xe=e.get(De),Re=G.parseLocator(De);G.isVirtualLocator(Re)&&(Re=G.devirtualizeLocator(Re));let gt=Re.locatorHash,q=xe.target,nt=g;if(q===nt)continue;let Ne=xe.linkType;for(let Te of we)ie=ie.children.get(Te);if(!fe)te.push({srcDir:q,dstDir:nt,linkType:Ne,realLocatorHash:gt});else for(let Te of we)if(Z=K.join(Z,Te),fe=fe.children.get(Te),!fe){te.push({srcDir:q,dstDir:nt,linkType:Ne,realLocatorHash:gt});break}}let le=Ys.progressViaCounter(te.length),ce=a.reportProgress(le),ue=o.configuration.get("nmMode"),Ce={value:ue},he=o.configuration.get("winLinkType");try{let De=Ce.value==="hardlinks-global"?`${$j(o.configuration)}/v1`:null;if(De&&!await ae.existsPromise(De)){await ae.mkdirpPromise(De);for(let g=0;g<256;g++)await ae.mkdirPromise(K.join(De,g.toString(16).padStart(2,"0")))}for(let g of te)(g.linkType==="SOFT"||!z.has(g.srcDir))&&(z.set(g.srcDir,g.dstDir),await C({...g,globalHardlinksStore:De,nmMode:Ce,windowsLinkType:he,packageChecksum:u.get(g.realLocatorHash)||null}));await Promise.all(x),x.length=0;for(let g of te){let me=z.get(g.srcDir);g.linkType!=="SOFT"&&g.dstDir!==me&&await T(me,g.dstDir,{nmMode:Ce})}await Promise.all(x),await ae.mkdirPromise(A,{recursive:!0});let Ee=await $It(e,D,o.cwd,{loadManifest:n});await t1t(h,Ee,o.cwd,he),await zIt(o,e,Ee,Ce,{installChangedByUser:I}),ue=="hardlinks-global"&&Ce.value=="hardlinks-local"&&a.reportWarningOnce(74,"'nmMode' has been downgraded to 'hardlinks-local' due to global cache and install folder being on different devices")}finally{ce.stop()}}async function t1t(t,e,r,o){for(let a of t.keys()){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);if(!e.has(a)){let n=K.join(a,bi,$Q);await ae.removePromise(n)}}for(let[a,n]of e){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);let u=K.join(a,bi,$Q),A=t.get(a)||new Map;await ae.mkdirPromise(u,{recursive:!0});for(let p of A.keys())n.has(p)||(await ae.removePromise(K.join(u,p)),process.platform==="win32"&&await ae.removePromise(K.join(u,`${p}.cmd`)));for(let[p,h]of n){let E=A.get(p),I=K.join(u,p);E!==h&&(process.platform==="win32"?await(0,W1e.default)(Ae.fromPortablePath(h),Ae.fromPortablePath(I),{createPwshFile:!1}):(await ae.removePromise(I),await Zj(h,I,o),K.contains(r,await ae.realpathPromise(h))!==null&&await ae.chmodPromise(h,493)))}}}Ke();Pt();sA();var Pv=class extends Wh{constructor(){super(...arguments);this.mode="loose"}makeInstaller(r){return new e5(r)}},e5=class extends pd{constructor(){super(...arguments);this.mode="loose"}async transformPnpSettings(r){let o=new qs({baseFs:new iA({maxOpenFiles:80,readOnlyArchives:!0})}),a=F1e(r,this.opts.project.cwd,o),{tree:n,errors:u}=pv(a,{pnpifyFs:!1,project:this.opts.project});if(!n){for(let{messageName:I,text:D}of u)this.opts.report.reportError(I,D);return}let A=new Map;r.fallbackPool=A;let p=(I,D)=>{let x=G.parseLocator(D.locator),C=G.stringifyIdent(x);C===I?A.set(I,x.reference):A.set(I,[C,x.reference])},h=K.join(this.opts.project.cwd,mr.nodeModules),E=n.get(h);if(!(typeof E>"u")){if("target"in E)throw new Error("Assertion failed: Expected the root junction point to be a directory");for(let I of E.dirList){let D=K.join(h,I),x=n.get(D);if(typeof x>"u")throw new Error("Assertion failed: Expected the child to have been registered");if("target"in x)p(I,x);else for(let C of x.dirList){let T=K.join(D,C),L=n.get(T);if(typeof L>"u")throw new Error("Assertion failed: Expected the subchild to have been registered");if("target"in L)p(`${I}/${C}`,L);else throw new Error("Assertion failed: Expected the leaf junction to be a package")}}}}};var r1t={hooks:{cleanGlobalArtifacts:async t=>{let e=$j(t);await ae.removePromise(e)}},configuration:{nmHoistingLimits:{description:"Prevents packages to be hoisted past specific levels",type:"STRING",values:["workspaces","dependencies","none"],default:"none"},nmMode:{description:"Defines in which measure Yarn must use hardlinks and symlinks when generated `node_modules` directories.",type:"STRING",values:["classic","hardlinks-local","hardlinks-global"],default:"classic"},nmSelfReferences:{description:"Defines whether the linker should generate self-referencing symlinks for workspaces.",type:"BOOLEAN",default:!0}},linkers:[Dv,Pv]},n1t=r1t;var $5={};Kt($5,{NpmHttpFetcher:()=>xv,NpmRemapResolver:()=>kv,NpmSemverFetcher:()=>rp,NpmSemverResolver:()=>Qv,NpmTagResolver:()=>Fv,default:()=>yvt,npmConfigUtils:()=>si,npmHttpUtils:()=>en,npmPublishUtils:()=>VC});Ke();var o2e=et(ni());var Zn="npm:";var en={};Kt(en,{AuthType:()=>n2e,customPackageError:()=>hd,del:()=>g1t,get:()=>gd,getIdentUrl:()=>tF,getPackageMetadata:()=>LC,handleInvalidAuthenticationError:()=>Vh,post:()=>p1t,put:()=>h1t});Ke();Ke();Pt();var i5=et(Q2()),t2e=et(c8()),r2e=et(ni());var si={};Kt(si,{RegistryType:()=>$1e,getAuditRegistry:()=>i1t,getAuthConfiguration:()=>n5,getDefaultRegistry:()=>Sv,getPublishRegistry:()=>s1t,getRegistryConfiguration:()=>e2e,getScopeConfiguration:()=>r5,getScopeRegistry:()=>TC,normalizeRegistry:()=>uc});var $1e=(o=>(o.AUDIT_REGISTRY="npmAuditRegistry",o.FETCH_REGISTRY="npmRegistryServer",o.PUBLISH_REGISTRY="npmPublishRegistry",o))($1e||{});function uc(t){return t.replace(/\/$/,"")}function i1t({configuration:t}){return Sv({configuration:t,type:"npmAuditRegistry"})}function s1t(t,{configuration:e}){return t.publishConfig?.registry?uc(t.publishConfig.registry):t.name?TC(t.name.scope,{configuration:e,type:"npmPublishRegistry"}):Sv({configuration:e,type:"npmPublishRegistry"})}function TC(t,{configuration:e,type:r="npmRegistryServer"}){let o=r5(t,{configuration:e});if(o===null)return Sv({configuration:e,type:r});let a=o.get(r);return a===null?Sv({configuration:e,type:r}):uc(a)}function Sv({configuration:t,type:e="npmRegistryServer"}){let r=t.get(e);return uc(r!==null?r:t.get("npmRegistryServer"))}function e2e(t,{configuration:e}){let r=e.get("npmRegistries"),o=uc(t),a=r.get(o);if(typeof a<"u")return a;let n=r.get(o.replace(/^[a-z]+:/,""));return typeof n<"u"?n:null}function r5(t,{configuration:e}){if(t===null)return null;let o=e.get("npmScopes").get(t);return o||null}function n5(t,{configuration:e,ident:r}){let o=r&&r5(r.scope,{configuration:e});return o?.get("npmAuthIdent")||o?.get("npmAuthToken")?o:e2e(t,{configuration:e})||e}var n2e=(a=>(a[a.NO_AUTH=0]="NO_AUTH",a[a.BEST_EFFORT=1]="BEST_EFFORT",a[a.CONFIGURATION=2]="CONFIGURATION",a[a.ALWAYS_AUTH=3]="ALWAYS_AUTH",a))(n2e||{});async function Vh(t,{attemptedAs:e,registry:r,headers:o,configuration:a}){if(nF(t))throw new zt(41,"Invalid OTP token");if(t.originalError?.name==="HTTPError"&&t.originalError?.response.statusCode===401)throw new zt(41,`Invalid authentication (${typeof e!="string"?`as ${await m1t(r,o,{configuration:a})}`:`attempted as ${e}`})`)}function hd(t,e){let r=t.response?.statusCode;return r?r===404?"Package not found":r>=500&&r<600?`The registry appears to be down (using a ${pe.applyHyperlink(e,"local cache","https://yarnpkg.com/advanced/lexicon#local-cache")} might have protected you against such outages)`:null:null}function tF(t){return t.scope?`/@${t.scope}%2f${t.name}`:`/${t.name}`}var i2e=new Map,o1t=new Map;async function a1t(t){return await qe.getFactoryWithDefault(i2e,t,async()=>{let e=null;try{e=await ae.readJsonPromise(t)}catch{}return e})}async function l1t(t,e,{configuration:r,cached:o,registry:a,headers:n,version:u,...A}){return await qe.getFactoryWithDefault(o1t,t,async()=>await gd(tF(e),{...A,customErrorMessage:hd,configuration:r,registry:a,ident:e,headers:{...n,"If-None-Match":o?.etag,"If-Modified-Since":o?.lastModified},wrapNetworkRequest:async p=>async()=>{let h=await p();if(h.statusCode===304){if(o===null)throw new Error("Assertion failed: cachedMetadata should not be null");return{...h,body:o.metadata}}let E=c1t(JSON.parse(h.body.toString())),I={metadata:E,etag:h.headers.etag,lastModified:h.headers["last-modified"]};return i2e.set(t,Promise.resolve(I)),Promise.resolve().then(async()=>{let D=`${t}-${process.pid}.tmp`;await ae.mkdirPromise(K.dirname(D),{recursive:!0}),await ae.writeJsonPromise(D,I,{compact:!0}),await ae.renamePromise(D,t)}).catch(()=>{}),{...h,body:E}}}))}async function LC(t,{cache:e,project:r,registry:o,headers:a,version:n,...u}){let{configuration:A}=r;o=bv(A,{ident:t,registry:o});let p=A1t(A,o),h=K.join(p,`${G.slugifyIdent(t)}.json`),E=null;if(!r.lockfileNeedsRefresh&&(E=await a1t(h),E)){if(typeof n<"u"&&typeof E.metadata.versions[n]<"u")return E.metadata;if(A.get("enableOfflineMode")){let I=structuredClone(E.metadata),D=new Set;if(e){for(let C of Object.keys(I.versions)){let T=G.makeLocator(t,`npm:${C}`),L=e.getLocatorMirrorPath(T);(!L||!ae.existsSync(L))&&(delete I.versions[C],D.add(C))}let x=I["dist-tags"].latest;if(D.has(x)){let C=Object.keys(E.metadata.versions).sort(r2e.default.compare),T=C.indexOf(x);for(;D.has(C[T])&&T>=0;)T-=1;T>=0?I["dist-tags"].latest=C[T]:delete I["dist-tags"].latest}}return I}}return await l1t(h,t,{...u,configuration:A,cached:E,registry:o,headers:a,version:n})}var s2e=["name","dist.tarball","bin","scripts","os","cpu","libc","dependencies","dependenciesMeta","optionalDependencies","peerDependencies","peerDependenciesMeta","deprecated"];function c1t(t){return{"dist-tags":t["dist-tags"],versions:Object.fromEntries(Object.entries(t.versions).map(([e,r])=>[e,(0,t2e.default)(r,s2e)]))}}var u1t=xn.makeHash(...s2e).slice(0,6);function A1t(t,e){let r=f1t(t),o=new URL(e);return K.join(r,u1t,o.hostname)}function f1t(t){return K.join(t.get("globalFolder"),"metadata/npm")}async function gd(t,{configuration:e,headers:r,ident:o,authType:a,registry:n,...u}){n=bv(e,{ident:o,registry:n}),o&&o.scope&&typeof a>"u"&&(a=1);let A=await rF(n,{authType:a,configuration:e,ident:o});A&&(r={...r,authorization:A});try{return await on.get(t.charAt(0)==="/"?`${n}${t}`:t,{configuration:e,headers:r,...u})}catch(p){throw await Vh(p,{registry:n,configuration:e,headers:r}),p}}async function p1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=bv(o,{ident:n,registry:A});let E=await rF(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...NC(p)});try{return await on.post(A+t,e,{configuration:o,headers:a,...h})}catch(I){if(!nF(I)||p)throw await Vh(I,{attemptedAs:r,registry:A,configuration:o,headers:a}),I;p=await s5(I,{configuration:o});let D={...a,...NC(p)};try{return await on.post(`${A}${t}`,e,{configuration:o,headers:D,...h})}catch(x){throw await Vh(x,{attemptedAs:r,registry:A,configuration:o,headers:a}),x}}}async function h1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=bv(o,{ident:n,registry:A});let E=await rF(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...NC(p)});try{return await on.put(A+t,e,{configuration:o,headers:a,...h})}catch(I){if(!nF(I))throw await Vh(I,{attemptedAs:r,registry:A,configuration:o,headers:a}),I;p=await s5(I,{configuration:o});let D={...a,...NC(p)};try{return await on.put(`${A}${t}`,e,{configuration:o,headers:D,...h})}catch(x){throw await Vh(x,{attemptedAs:r,registry:A,configuration:o,headers:a}),x}}}async function g1t(t,{attemptedAs:e,configuration:r,headers:o,ident:a,authType:n=3,registry:u,otp:A,...p}){u=bv(r,{ident:a,registry:u});let h=await rF(u,{authType:n,configuration:r,ident:a});h&&(o={...o,authorization:h}),A&&(o={...o,...NC(A)});try{return await on.del(u+t,{configuration:r,headers:o,...p})}catch(E){if(!nF(E)||A)throw await Vh(E,{attemptedAs:e,registry:u,configuration:r,headers:o}),E;A=await s5(E,{configuration:r});let I={...o,...NC(A)};try{return await on.del(`${u}${t}`,{configuration:r,headers:I,...p})}catch(D){throw await Vh(D,{attemptedAs:e,registry:u,configuration:r,headers:o}),D}}}function bv(t,{ident:e,registry:r}){if(typeof r>"u"&&e)return TC(e.scope,{configuration:t});if(typeof r!="string")throw new Error("Assertion failed: The registry should be a string");return uc(r)}async function rF(t,{authType:e=2,configuration:r,ident:o}){let a=n5(t,{configuration:r,ident:o}),n=d1t(a,e);if(!n)return null;let u=await r.reduceHook(A=>A.getNpmAuthenticationHeader,void 0,t,{configuration:r,ident:o});if(u)return u;if(a.get("npmAuthToken"))return`Bearer ${a.get("npmAuthToken")}`;if(a.get("npmAuthIdent")){let A=a.get("npmAuthIdent");return A.includes(":")?`Basic ${Buffer.from(A).toString("base64")}`:`Basic ${A}`}if(n&&e!==1)throw new zt(33,"No authentication configured for request");return null}function d1t(t,e){switch(e){case 2:return t.get("npmAlwaysAuth");case 1:case 3:return!0;case 0:return!1;default:throw new Error("Unreachable")}}async function m1t(t,e,{configuration:r}){if(typeof e>"u"||typeof e.authorization>"u")return"an anonymous user";try{return(await on.get(new URL(`${t}/-/whoami`).href,{configuration:r,headers:e,jsonResponse:!0})).username??"an unknown user"}catch{return"an unknown user"}}async function s5(t,{configuration:e}){let r=t.originalError?.response.headers["npm-notice"];if(r&&(await Nt.start({configuration:e,stdout:process.stdout,includeFooter:!1},async a=>{if(a.reportInfo(0,r.replace(/(https?:\/\/\S+)/g,pe.pretty(e,"$1",pe.Type.URL))),!process.env.YARN_IS_TEST_ENV){let n=r.match(/open (https?:\/\/\S+)/i);if(n&&Xi.openUrl){let{openNow:u}=await(0,i5.prompt)({type:"confirm",name:"openNow",message:"Do you want to try to open this url now?",required:!0,initial:!0,onCancel:()=>process.exit(130)});u&&(await Xi.openUrl(n[1])||(a.reportSeparator(),a.reportWarning(0,"We failed to automatically open the url; you'll have to open it yourself in your browser of choice.")))}}}),process.stdout.write(` +`)),process.env.YARN_IS_TEST_ENV)return process.env.YARN_INJECT_NPM_2FA_TOKEN||"";let{otp:o}=await(0,i5.prompt)({type:"password",name:"otp",message:"One-time password:",required:!0,onCancel:()=>process.exit(130)});return process.stdout.write(` +`),o}function nF(t){if(t.originalError?.name!=="HTTPError")return!1;try{return(t.originalError?.response.headers["www-authenticate"].split(/,\s*/).map(r=>r.toLowerCase())).includes("otp")}catch{return!1}}function NC(t){return{"npm-otp":t}}var xv=class{supports(e,r){if(!e.reference.startsWith(Zn))return!1;let{selector:o,params:a}=G.parseRange(e.reference);return!(!o2e.default.valid(o)||a===null||typeof a.__archiveUrl!="string")}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let{params:o}=G.parseRange(e.reference);if(o===null||typeof o.__archiveUrl!="string")throw new Error("Assertion failed: The archiveUrl querystring parameter should have been available");let a=await gd(o.__archiveUrl,{customErrorMessage:hd,configuration:r.project.configuration,ident:e});return await $i.convertToZip(a,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();var kv=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Zn)||!G.tryParseDescriptor(e.range.slice(Zn.length),!0))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Unreachable")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){let o=r.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return r.resolver.getResolutionDependencies(o,r)}async getCandidates(e,r,o){let a=o.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return await o.resolver.getCandidates(a,r,o)}async getSatisfying(e,r,o,a){let n=a.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return a.resolver.getSatisfying(n,r,o,a)}resolve(e,r){throw new Error("Unreachable")}};Ke();Ke();var a2e=et(ni());var rp=class t{supports(e,r){if(!e.reference.startsWith(Zn))return!1;let o=new URL(e.reference);return!(!a2e.default.valid(o.pathname)||o.searchParams.has("__archiveUrl"))}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote registry`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o;try{o=await gd(t.getLocatorUrl(e),{customErrorMessage:hd,configuration:r.project.configuration,ident:e})}catch{o=await gd(t.getLocatorUrl(e).replace(/%2f/g,"/"),{customErrorMessage:hd,configuration:r.project.configuration,ident:e})}return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}static isConventionalTarballUrl(e,r,{configuration:o}){let a=TC(e.scope,{configuration:o}),n=t.getLocatorUrl(e);return r=r.replace(/^https?:(\/\/(?:[^/]+\.)?npmjs.org(?:$|\/))/,"https:$1"),a=a.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r=r.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r===a+n||r===a+n.replace(/%2f/g,"/")}static getLocatorUrl(e){let r=Ur.clean(e.reference.slice(Zn.length));if(r===null)throw new zt(10,"The npm semver resolver got selected, but the version isn't semver");return`${tF(e)}/-/${e.name}-${r}.tgz`}};Ke();Ke();Ke();var o5=et(ni());var iF=G.makeIdent(null,"node-gyp"),y1t=/\b(node-gyp|prebuild-install)\b/,Qv=class{supportsDescriptor(e,r){return e.range.startsWith(Zn)?!!Ur.validRange(e.range.slice(Zn.length)):!1}supportsLocator(e,r){if(!e.reference.startsWith(Zn))return!1;let{selector:o}=G.parseRange(e.reference);return!!o5.default.valid(o)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=Ur.validRange(e.range.slice(Zn.length));if(a===null)throw new Error(`Expected a valid range, got ${e.range.slice(Zn.length)}`);let n=await LC(e,{cache:o.fetchOptions?.cache,project:o.project,version:o5.default.valid(a.raw)?a.raw:void 0}),u=qe.mapAndFilter(Object.keys(n.versions),h=>{try{let E=new Ur.SemVer(h);if(a.test(E))return E}catch{}return qe.mapAndFilter.skip}),A=u.filter(h=>!n.versions[h.raw].deprecated),p=A.length>0?A:u;return p.sort((h,E)=>-h.compare(E)),p.map(h=>{let E=G.makeLocator(e,`${Zn}${h.raw}`),I=n.versions[h.raw].dist.tarball;return rp.isConventionalTarballUrl(E,I,{configuration:o.project.configuration})?E:G.bindLocator(E,{__archiveUrl:I})})}async getSatisfying(e,r,o,a){let n=Ur.validRange(e.range.slice(Zn.length));if(n===null)throw new Error(`Expected a valid range, got ${e.range.slice(Zn.length)}`);return{locators:qe.mapAndFilter(o,p=>{if(p.identHash!==e.identHash)return qe.mapAndFilter.skip;let h=G.tryParseRange(p.reference,{requireProtocol:Zn});if(!h)return qe.mapAndFilter.skip;let E=new Ur.SemVer(h.selector);return n.test(E)?{locator:p,version:E}:qe.mapAndFilter.skip}).sort((p,h)=>-p.version.compare(h.version)).map(({locator:p})=>p),sorted:!0}}async resolve(e,r){let{selector:o}=G.parseRange(e.reference),a=Ur.clean(o);if(a===null)throw new zt(10,"The npm semver resolver got selected, but the version isn't semver");let n=await LC(e,{cache:r.fetchOptions?.cache,project:r.project,version:a});if(!Object.hasOwn(n,"versions"))throw new zt(15,'Registry returned invalid data for - missing "versions" field');if(!Object.hasOwn(n.versions,a))throw new zt(16,`Registry failed to return reference "${a}"`);let u=new _t;if(u.load(n.versions[a]),!u.dependencies.has(iF.identHash)&&!u.peerDependencies.has(iF.identHash)){for(let A of u.scripts.values())if(A.match(y1t)){u.dependencies.set(iF.identHash,G.makeDescriptor(iF,"latest"));break}}return{...e,version:a,languageName:"node",linkType:"HARD",conditions:u.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(u.dependencies),peerDependencies:u.peerDependencies,dependenciesMeta:u.dependenciesMeta,peerDependenciesMeta:u.peerDependenciesMeta,bin:u.bin}}};Ke();Ke();var l2e=et(ni());var Fv=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Zn)||!xy.test(e.range.slice(Zn.length)))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Unreachable")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Zn.length),n=await LC(e,{cache:o.fetchOptions?.cache,project:o.project});if(!Object.hasOwn(n,"dist-tags"))throw new zt(15,'Registry returned invalid data - missing "dist-tags" field');let u=n["dist-tags"];if(!Object.hasOwn(u,a))throw new zt(16,`Registry failed to return tag "${a}"`);let A=u[a],p=G.makeLocator(e,`${Zn}${A}`),h=n.versions[A].dist.tarball;return rp.isConventionalTarballUrl(p,h,{configuration:o.project.configuration})?[p]:[G.bindLocator(p,{__archiveUrl:h})]}async getSatisfying(e,r,o,a){let n=[];for(let u of o){if(u.identHash!==e.identHash)continue;let A=G.tryParseRange(u.reference,{requireProtocol:Zn});if(!(!A||!l2e.default.valid(A.selector))){if(A.params?.__archiveUrl){let p=G.makeRange({protocol:Zn,selector:A.selector,source:null,params:null}),[h]=await a.resolver.getCandidates(G.makeDescriptor(e,p),r,a);if(u.reference!==h.reference)continue}n.push(u)}}return{locators:n,sorted:!1}}async resolve(e,r){throw new Error("Unreachable")}};var VC={};Kt(VC,{getGitHead:()=>dvt,getPublishAccess:()=>XBe,getReadmeContent:()=>ZBe,makePublishBody:()=>gvt});Ke();Ke();Pt();var V5={};Kt(V5,{PackCommand:()=>KC,default:()=>XBt,packUtils:()=>BA});Ke();Ke();Ke();Pt();Gt();var BA={};Kt(BA,{genPackList:()=>SF,genPackStream:()=>K5,genPackageManifest:()=>UBe,hasPackScripts:()=>Y5,prepareForPack:()=>W5});Ke();Pt();var G5=et(Xo()),MBe=et(RBe()),OBe=ve("zlib"),_Bt=["/package.json","/readme","/readme.*","/license","/license.*","/licence","/licence.*","/changelog","/changelog.*"],HBt=["/package.tgz",".github",".git",".hg","node_modules",".npmignore",".gitignore",".#*",".DS_Store"];async function Y5(t){return!!(hn.hasWorkspaceScript(t,"prepack")||hn.hasWorkspaceScript(t,"postpack"))}async function W5(t,{report:e},r){await hn.maybeExecuteWorkspaceLifecycleScript(t,"prepack",{report:e});try{let o=K.join(t.cwd,_t.fileName);await ae.existsPromise(o)&&await t.manifest.loadFile(o,{baseFs:ae}),await r()}finally{await hn.maybeExecuteWorkspaceLifecycleScript(t,"postpack",{report:e})}}async function K5(t,e){typeof e>"u"&&(e=await SF(t));let r=new Set;for(let n of t.manifest.publishConfig?.executableFiles??new Set)r.add(K.normalize(n));for(let n of t.manifest.bin.values())r.add(K.normalize(n));let o=MBe.default.pack();process.nextTick(async()=>{for(let n of e){let u=K.normalize(n),A=K.resolve(t.cwd,u),p=K.join("package",u),h=await ae.lstatPromise(A),E={name:p,mtime:new Date(Pi.SAFE_TIME*1e3)},I=r.has(u)?493:420,D,x,C=new Promise((L,U)=>{D=L,x=U}),T=L=>{L?x(L):D()};if(h.isFile()){let L;u==="package.json"?L=Buffer.from(JSON.stringify(await UBe(t),null,2)):L=await ae.readFilePromise(A),o.entry({...E,mode:I,type:"file"},L,T)}else h.isSymbolicLink()?o.entry({...E,mode:I,type:"symlink",linkname:await ae.readlinkPromise(A)},T):T(new Error(`Unsupported file type ${h.mode} for ${Ae.fromPortablePath(u)}`));await C}o.finalize()});let a=(0,OBe.createGzip)();return o.pipe(a),a}async function UBe(t){let e=JSON.parse(JSON.stringify(t.manifest.raw));return await t.project.configuration.triggerHook(r=>r.beforeWorkspacePacking,t,e),e}async function SF(t){let e=t.project,r=e.configuration,o={accept:[],reject:[]};for(let I of HBt)o.reject.push(I);for(let I of _Bt)o.accept.push(I);o.reject.push(r.get("rcFilename"));let a=I=>{if(I===null||!I.startsWith(`${t.cwd}/`))return;let D=K.relative(t.cwd,I),x=K.resolve(Bt.root,D);o.reject.push(x)};a(K.resolve(e.cwd,mr.lockfile)),a(r.get("cacheFolder")),a(r.get("globalFolder")),a(r.get("installStatePath")),a(r.get("virtualFolder")),a(r.get("yarnPath")),await r.triggerHook(I=>I.populateYarnPaths,e,I=>{a(I)});for(let I of e.workspaces){let D=K.relative(t.cwd,I.cwd);D!==""&&!D.match(/^(\.\.)?\//)&&o.reject.push(`/${D}`)}let n={accept:[],reject:[]},u=t.manifest.publishConfig?.main??t.manifest.main,A=t.manifest.publishConfig?.module??t.manifest.module,p=t.manifest.publishConfig?.browser??t.manifest.browser,h=t.manifest.publishConfig?.bin??t.manifest.bin;u!=null&&n.accept.push(K.resolve(Bt.root,u)),A!=null&&n.accept.push(K.resolve(Bt.root,A)),typeof p=="string"&&n.accept.push(K.resolve(Bt.root,p));for(let I of h.values())n.accept.push(K.resolve(Bt.root,I));if(p instanceof Map)for(let[I,D]of p.entries())n.accept.push(K.resolve(Bt.root,I)),typeof D=="string"&&n.accept.push(K.resolve(Bt.root,D));let E=t.manifest.files!==null;if(E){n.reject.push("/*");for(let I of t.manifest.files)_Be(n.accept,I,{cwd:Bt.root})}return await qBt(t.cwd,{hasExplicitFileList:E,globalList:o,ignoreList:n})}async function qBt(t,{hasExplicitFileList:e,globalList:r,ignoreList:o}){let a=[],n=new Gu(t),u=[[Bt.root,[o]]];for(;u.length>0;){let[A,p]=u.pop(),h=await n.lstatPromise(A);if(!NBe(A,{globalList:r,ignoreLists:h.isDirectory()?null:p}))if(h.isDirectory()){let E=await n.readdirPromise(A),I=!1,D=!1;if(!e||A!==Bt.root)for(let T of E)I=I||T===".gitignore",D=D||T===".npmignore";let x=D?await TBe(n,A,".npmignore"):I?await TBe(n,A,".gitignore"):null,C=x!==null?[x].concat(p):p;NBe(A,{globalList:r,ignoreLists:p})&&(C=[...p,{accept:[],reject:["**/*"]}]);for(let T of E)u.push([K.resolve(A,T),C])}else(h.isFile()||h.isSymbolicLink())&&a.push(K.relative(Bt.root,A))}return a.sort()}async function TBe(t,e,r){let o={accept:[],reject:[]},a=await t.readFilePromise(K.join(e,r),"utf8");for(let n of a.split(/\n/g))_Be(o.reject,n,{cwd:e});return o}function jBt(t,{cwd:e}){let r=t[0]==="!";return r&&(t=t.slice(1)),t.match(/\.{0,1}\//)&&(t=K.resolve(e,t)),r&&(t=`!${t}`),t}function _Be(t,e,{cwd:r}){let o=e.trim();o===""||o[0]==="#"||t.push(jBt(o,{cwd:r}))}function NBe(t,{globalList:e,ignoreLists:r}){let o=PF(t,e.accept);if(o!==0)return o===2;let a=PF(t,e.reject);if(a!==0)return a===1;if(r!==null)for(let n of r){let u=PF(t,n.accept);if(u!==0)return u===2;let A=PF(t,n.reject);if(A!==0)return A===1}return!1}function PF(t,e){let r=e,o=[];for(let a=0;a{await W5(a,{report:p},async()=>{p.reportJson({base:Ae.fromPortablePath(a.cwd)});let h=await SF(a);for(let E of h)p.reportInfo(null,Ae.fromPortablePath(E)),p.reportJson({location:Ae.fromPortablePath(E)});if(!this.dryRun){let E=await K5(a,h),I=ae.createWriteStream(u);E.pipe(I),await new Promise(D=>{I.on("finish",D)})}}),this.dryRun||(p.reportInfo(0,`Package archive generated in ${pe.pretty(r,u,pe.Type.PATH)}`),p.reportJson({output:Ae.fromPortablePath(u)}))})).exitCode()}};function GBt(t,{workspace:e}){let r=t.replace("%s",YBt(e)).replace("%v",WBt(e));return Ae.toPortablePath(r)}function YBt(t){return t.manifest.name!==null?G.slugifyIdent(t.manifest.name):"package"}function WBt(t){return t.manifest.version!==null?t.manifest.version:"unknown"}var KBt=["dependencies","devDependencies","peerDependencies"],VBt="workspace:",zBt=(t,e)=>{e.publishConfig&&(e.publishConfig.type&&(e.type=e.publishConfig.type),e.publishConfig.main&&(e.main=e.publishConfig.main),e.publishConfig.browser&&(e.browser=e.publishConfig.browser),e.publishConfig.module&&(e.module=e.publishConfig.module),e.publishConfig.exports&&(e.exports=e.publishConfig.exports),e.publishConfig.imports&&(e.imports=e.publishConfig.imports),e.publishConfig.bin&&(e.bin=e.publishConfig.bin));let r=t.project;for(let o of KBt)for(let a of t.manifest.getForScope(o).values()){let n=r.tryWorkspaceByDescriptor(a),u=G.parseRange(a.range);if(u.protocol===VBt)if(n===null){if(r.tryWorkspaceByIdent(a)===null)throw new zt(21,`${G.prettyDescriptor(r.configuration,a)}: No local workspace found for this range`)}else{let A;G.areDescriptorsEqual(a,n.anchoredDescriptor)||u.selector==="*"?A=n.manifest.version??"0.0.0":u.selector==="~"||u.selector==="^"?A=`${u.selector}${n.manifest.version??"0.0.0"}`:A=u.selector;let p=o==="dependencies"?G.makeDescriptor(a,"unknown"):null,h=p!==null&&t.manifest.ensureDependencyMeta(p).optional?"optionalDependencies":o;e[h][G.stringifyIdent(a)]=A}}},JBt={hooks:{beforeWorkspacePacking:zBt},commands:[KC]},XBt=JBt;var zBe=ve("crypto"),JBe=et(VBe());async function gvt(t,e,{access:r,tag:o,registry:a,gitHead:n}){let u=t.manifest.name,A=t.manifest.version,p=G.stringifyIdent(u),h=(0,zBe.createHash)("sha1").update(e).digest("hex"),E=JBe.default.fromData(e).toString(),I=r??XBe(t,u),D=await ZBe(t),x=await BA.genPackageManifest(t),C=`${p}-${A}.tgz`,T=new URL(`${uc(a)}/${p}/-/${C}`);return{_id:p,_attachments:{[C]:{content_type:"application/octet-stream",data:e.toString("base64"),length:e.length}},name:p,access:I,"dist-tags":{[o]:A},versions:{[A]:{...x,_id:`${p}@${A}`,name:p,version:A,gitHead:n,dist:{shasum:h,integrity:E,tarball:T.toString()}}},readme:D}}async function dvt(t){try{let{stdout:e}=await Hr.execvp("git",["rev-parse","--revs-only","HEAD"],{cwd:t});return e.trim()===""?void 0:e.trim()}catch{return}}function XBe(t,e){let r=t.project.configuration;return t.manifest.publishConfig&&typeof t.manifest.publishConfig.access=="string"?t.manifest.publishConfig.access:r.get("npmPublishAccess")!==null?r.get("npmPublishAccess"):e.scope?"restricted":"public"}async function ZBe(t){let e=Ae.toPortablePath(`${t.cwd}/README.md`),r=t.manifest.name,a=`# ${G.stringifyIdent(r)} +`;try{a=await ae.readFilePromise(e,"utf8")}catch(n){if(n.code==="ENOENT")return a;throw n}return a}var Z5={npmAlwaysAuth:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"BOOLEAN",default:!1},npmAuthIdent:{description:"Authentication identity for the npm registry (_auth in npm and yarn v1)",type:"SECRET",default:null},npmAuthToken:{description:"Authentication token for the npm registry (_authToken in npm and yarn v1)",type:"SECRET",default:null}},$Be={npmAuditRegistry:{description:"Registry to query for audit reports",type:"STRING",default:null},npmPublishRegistry:{description:"Registry to push packages to",type:"STRING",default:null},npmRegistryServer:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"STRING",default:"https://registry.yarnpkg.com"}},mvt={configuration:{...Z5,...$Be,npmScopes:{description:"Settings per package scope",type:"MAP",valueDefinition:{description:"",type:"SHAPE",properties:{...Z5,...$Be}}},npmRegistries:{description:"Settings per registry",type:"MAP",normalizeKeys:uc,valueDefinition:{description:"",type:"SHAPE",properties:{...Z5}}}},fetchers:[xv,rp],resolvers:[kv,Qv,Fv]},yvt=mvt;var lG={};Kt(lG,{NpmAuditCommand:()=>JC,NpmInfoCommand:()=>XC,NpmLoginCommand:()=>ZC,NpmLogoutCommand:()=>ew,NpmPublishCommand:()=>tw,NpmTagAddCommand:()=>nw,NpmTagListCommand:()=>rw,NpmTagRemoveCommand:()=>iw,NpmWhoamiCommand:()=>sw,default:()=>Dvt,npmAuditTypes:()=>Xv,npmAuditUtils:()=>bF});Ke();Ke();Gt();var iG=et(Xo());il();var Xv={};Kt(Xv,{Environment:()=>zv,Severity:()=>Jv});var zv=(o=>(o.All="all",o.Production="production",o.Development="development",o))(zv||{}),Jv=(n=>(n.Info="info",n.Low="low",n.Moderate="moderate",n.High="high",n.Critical="critical",n))(Jv||{});var bF={};Kt(bF,{allSeverities:()=>zC,getPackages:()=>nG,getReportTree:()=>tG,getSeverityInclusions:()=>eG,getTopLevelDependencies:()=>rG});Ke();var eve=et(ni());var zC=["info","low","moderate","high","critical"];function eG(t){if(typeof t>"u")return new Set(zC);let e=zC.indexOf(t),r=zC.slice(e);return new Set(r)}function tG(t){let e={},r={children:e};for(let[o,a]of qe.sortMap(Object.entries(t),n=>n[0]))for(let n of qe.sortMap(a,u=>`${u.id}`))e[`${o}/${n.id}`]={value:pe.tuple(pe.Type.IDENT,G.parseIdent(o)),children:{ID:typeof n.id<"u"&&{label:"ID",value:pe.tuple(pe.Type.ID,n.id)},Issue:{label:"Issue",value:pe.tuple(pe.Type.NO_HINT,n.title)},URL:typeof n.url<"u"&&{label:"URL",value:pe.tuple(pe.Type.URL,n.url)},Severity:{label:"Severity",value:pe.tuple(pe.Type.NO_HINT,n.severity)},"Vulnerable Versions":{label:"Vulnerable Versions",value:pe.tuple(pe.Type.RANGE,n.vulnerable_versions)},"Tree Versions":{label:"Tree Versions",children:[...n.versions].sort(eve.default.compare).map(u=>({value:pe.tuple(pe.Type.REFERENCE,u)}))},Dependents:{label:"Dependents",children:qe.sortMap(n.dependents,u=>G.stringifyLocator(u)).map(u=>({value:pe.tuple(pe.Type.LOCATOR,u)}))}}};return r}function rG(t,e,{all:r,environment:o}){let a=[],n=r?t.workspaces:[e],u=["all","production"].includes(o),A=["all","development"].includes(o);for(let p of n)for(let h of p.anchoredPackage.dependencies.values())(p.manifest.devDependencies.has(h.identHash)?!A:!u)||a.push({workspace:p,dependency:h});return a}function nG(t,e,{recursive:r}){let o=new Map,a=new Set,n=[],u=(A,p)=>{let h=t.storedResolutions.get(p.descriptorHash);if(typeof h>"u")throw new Error("Assertion failed: The resolution should have been registered");if(!a.has(h))a.add(h);else return;let E=t.storedPackages.get(h);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");if(G.ensureDevirtualizedLocator(E).reference.startsWith("npm:")&&E.version!==null){let D=G.stringifyIdent(E),x=qe.getMapWithDefault(o,D);qe.getArrayWithDefault(x,E.version).push(A)}if(r)for(let D of E.dependencies.values())n.push([E,D])};for(let{workspace:A,dependency:p}of e)n.push([A.anchoredLocator,p]);for(;n.length>0;){let[A,p]=n.shift();u(A,p)}return o}var JC=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("-A,--all",!1,{description:"Audit dependencies from all workspaces"});this.recursive=de.Boolean("-R,--recursive",!1,{description:"Audit transitive dependencies as well"});this.environment=de.String("--environment","all",{description:"Which environments to cover",validator:js(zv)});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.noDeprecations=de.Boolean("--no-deprecations",!1,{description:"Don't warn about deprecated packages"});this.severity=de.String("--severity","info",{description:"Minimal severity requested for packages to be displayed",validator:js(Jv)});this.excludes=de.Array("--exclude",[],{description:"Array of glob patterns of packages to exclude from audit"});this.ignores=de.Array("--ignore",[],{description:"Array of glob patterns of advisory ID's to ignore in the audit report"})}static{this.paths=[["npm","audit"]]}static{this.usage=st.Usage({description:"perform a vulnerability audit against the installed packages",details:` + This command checks for known security reports on the packages you use. The reports are by default extracted from the npm registry, and may or may not be relevant to your actual program (not all vulnerabilities affect all code paths). + + For consistency with our other commands the default is to only check the direct dependencies for the active workspace. To extend this search to all workspaces, use \`-A,--all\`. To extend this search to both direct and transitive dependencies, use \`-R,--recursive\`. + + Applying the \`--severity\` flag will limit the audit table to vulnerabilities of the corresponding severity and above. Valid values are ${zC.map(r=>`\`${r}\``).join(", ")}. + + If the \`--json\` flag is set, Yarn will print the output exactly as received from the registry. Regardless of this flag, the process will exit with a non-zero exit code if a report is found for the selected packages. + + If certain packages produce false positives for a particular environment, the \`--exclude\` flag can be used to exclude any number of packages from the audit. This can also be set in the configuration file with the \`npmAuditExcludePackages\` option. + + If particular advisories are needed to be ignored, the \`--ignore\` flag can be used with Advisory ID's to ignore any number of advisories in the audit report. This can also be set in the configuration file with the \`npmAuditIgnoreAdvisories\` option. + + To understand the dependency tree requiring vulnerable packages, check the raw report with the \`--json\` flag or use \`yarn why package\` to get more information as to who depends on them. + `,examples:[["Checks for known security issues with the installed packages. The output is a list of known issues.","yarn npm audit"],["Audit dependencies in all workspaces","yarn npm audit --all"],["Limit auditing to `dependencies` (excludes `devDependencies`)","yarn npm audit --environment production"],["Show audit report as valid JSON","yarn npm audit --json"],["Audit all direct and transitive dependencies","yarn npm audit --recursive"],["Output moderate (or more severe) vulnerabilities","yarn npm audit --severity moderate"],["Exclude certain packages","yarn npm audit --exclude package1 --exclude package2"],["Ignore specific advisories","yarn npm audit --ignore 1234567 --ignore 7654321"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=rG(o,a,{all:this.all,environment:this.environment}),u=nG(o,n,{recursive:this.recursive}),A=Array.from(new Set([...r.get("npmAuditExcludePackages"),...this.excludes])),p=Object.create(null);for(let[L,U]of u)A.some(z=>iG.default.isMatch(L,z))||(p[L]=[...U.keys()]);let h=si.getAuditRegistry({configuration:r}),E,I=await pA.start({configuration:r,stdout:this.context.stdout},async()=>{let L=en.post("/-/npm/v1/security/advisories/bulk",p,{authType:en.AuthType.BEST_EFFORT,configuration:r,jsonResponse:!0,registry:h}),U=this.noDeprecations?[]:await Promise.all(Array.from(Object.entries(p),async([te,le])=>{let ce=await en.getPackageMetadata(G.parseIdent(te),{project:o});return qe.mapAndFilter(le,ue=>{let{deprecated:Ce}=ce.versions[ue];return Ce?[te,ue,Ce]:qe.mapAndFilter.skip})})),z=await L;for(let[te,le,ce]of U.flat(1))Object.hasOwn(z,te)&&z[te].some(ue=>Ur.satisfiesWithPrereleases(le,ue.vulnerable_versions))||(z[te]??=[],z[te].push({id:`${te} (deprecation)`,title:ce.trim()||"This package has been deprecated.",severity:"moderate",vulnerable_versions:le}));E=z});if(I.hasErrors())return I.exitCode();let D=eG(this.severity),x=Array.from(new Set([...r.get("npmAuditIgnoreAdvisories"),...this.ignores])),C=Object.create(null);for(let[L,U]of Object.entries(E)){let z=U.filter(te=>!iG.default.isMatch(`${te.id}`,x)&&D.has(te.severity));z.length>0&&(C[L]=z.map(te=>{let le=u.get(L);if(typeof le>"u")throw new Error("Assertion failed: Expected the registry to only return packages that were requested");let ce=[...le.keys()].filter(Ce=>Ur.satisfiesWithPrereleases(Ce,te.vulnerable_versions)),ue=new Map;for(let Ce of ce)for(let he of le.get(Ce))ue.set(he.locatorHash,he);return{...te,versions:ce,dependents:[...ue.values()]}}))}let T=Object.keys(C).length>0;return T?(As.emitTree(tG(C),{configuration:r,json:this.json,stdout:this.context.stdout,separators:2}),1):(await Nt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async L=>{L.reportInfo(1,"No audit suggestions")}),T?1:0)}};Ke();Ke();Pt();Gt();var sG=et(ni()),oG=ve("util"),XC=class extends ut{constructor(){super(...arguments);this.fields=de.String("-f,--fields",{description:"A comma-separated list of manifest fields that should be displayed"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.packages=de.Rest()}static{this.paths=[["npm","info"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"show information about a package",details:"\n This command fetches information about a package from the npm registry and prints it in a tree format.\n\n The package does not have to be installed locally, but needs to have been published (in particular, local changes will be ignored even for workspaces).\n\n Append `@` to the package argument to provide information specific to the latest version that satisfies the range or to the corresponding tagged version. If the range is invalid or if there is no version satisfying the range, the command will print a warning and fall back to the latest version.\n\n If the `-f,--fields` option is set, it's a comma-separated list of fields which will be used to only display part of the package information.\n\n By default, this command won't return the `dist`, `readme`, and `users` fields, since they are often very long. To explicitly request those fields, explicitly list them with the `--fields` flag or request the output in JSON mode.\n ",examples:[["Show all available information about react (except the `dist`, `readme`, and `users` fields)","yarn npm info react"],["Show all available information about react as valid JSON (including the `dist`, `readme`, and `users` fields)","yarn npm info react --json"],["Show all available information about react@16.12.0","yarn npm info react@16.12.0"],["Show all available information about react@next","yarn npm info react@next"],["Show the description of react","yarn npm info react --fields description"],["Show all available versions of react","yarn npm info react --fields versions"],["Show the readme of react","yarn npm info react --fields readme"],["Show a few fields of react","yarn npm info react --fields homepage,repository"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=typeof this.fields<"u"?new Set(["name",...this.fields.split(/\s*,\s*/)]):null,n=[],u=!1,A=await Nt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async p=>{for(let h of this.packages){let E;if(h==="."){let le=o.topLevelWorkspace;if(!le.manifest.name)throw new ot(`Missing ${pe.pretty(r,"name",pe.Type.CODE)} field in ${Ae.fromPortablePath(K.join(le.cwd,mr.manifest))}`);E=G.makeDescriptor(le.manifest.name,"unknown")}else E=G.parseDescriptor(h);let I=en.getIdentUrl(E),D=aG(await en.get(I,{configuration:r,ident:E,jsonResponse:!0,customErrorMessage:en.customPackageError})),x=Object.keys(D.versions).sort(sG.default.compareLoose),T=D["dist-tags"].latest||x[x.length-1],L=Ur.validRange(E.range);if(L){let le=sG.default.maxSatisfying(x,L);le!==null?T=le:(p.reportWarning(0,`Unmet range ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0)}else Object.hasOwn(D["dist-tags"],E.range)?T=D["dist-tags"][E.range]:E.range!=="unknown"&&(p.reportWarning(0,`Unknown tag ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0);let U=D.versions[T],z={...D,...U,version:T,versions:x},te;if(a!==null){te={};for(let le of a){let ce=z[le];if(typeof ce<"u")te[le]=ce;else{p.reportWarning(1,`The ${pe.pretty(r,le,pe.Type.CODE)} field doesn't exist inside ${G.prettyIdent(r,E)}'s information`),u=!0;continue}}}else this.json||(delete z.dist,delete z.readme,delete z.users),te=z;p.reportJson(te),this.json||n.push(te)}});oG.inspect.styles.name="cyan";for(let p of n)(p!==n[0]||u)&&this.context.stdout.write(` +`),this.context.stdout.write(`${(0,oG.inspect)(p,{depth:1/0,colors:!0,compact:!1})} +`);return A.exitCode()}};function aG(t){if(Array.isArray(t)){let e=[];for(let r of t)r=aG(r),r&&e.push(r);return e}else if(typeof t=="object"&&t!==null){let e={};for(let r of Object.keys(t)){if(r.startsWith("_"))continue;let o=aG(t[r]);o&&(e[r]=o)}return e}else return t||null}Ke();Ke();Gt();var tve=et(Q2()),ZC=class extends ut{constructor(){super(...arguments);this.scope=de.String("-s,--scope",{description:"Login to the registry configured for a given scope"});this.publish=de.Boolean("--publish",!1,{description:"Login to the publish registry"});this.alwaysAuth=de.Boolean("--always-auth",{description:"Set the npmAlwaysAuth configuration"})}static{this.paths=[["npm","login"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"store new login info to access the npm registry",details:"\n This command will ask you for your username, password, and 2FA One-Time-Password (when it applies). It will then modify your local configuration (in your home folder, never in the project itself) to reference the new tokens thus generated.\n\n Adding the `-s,--scope` flag will cause the authentication to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\n\n Adding the `--publish` flag will cause the authentication to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\n ",examples:[["Login to the default registry","yarn npm login"],["Login to the registry linked to the @my-scope registry","yarn npm login --scope my-scope"],["Login to the publish registry for the current package","yarn npm login --publish"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await xF({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope});return(await Nt.start({configuration:r,stdout:this.context.stdout,includeFooter:!1},async n=>{let u=await wvt({configuration:r,registry:o,report:n,stdin:this.context.stdin,stdout:this.context.stdout}),A=await Evt(o,u,r);return await Cvt(o,A,{alwaysAuth:this.alwaysAuth,scope:this.scope}),n.reportInfo(0,"Successfully logged in")})).exitCode()}};async function xF({scope:t,publish:e,configuration:r,cwd:o}){return t&&e?si.getScopeRegistry(t,{configuration:r,type:si.RegistryType.PUBLISH_REGISTRY}):t?si.getScopeRegistry(t,{configuration:r}):e?si.getPublishRegistry((await aE(r,o)).manifest,{configuration:r}):si.getDefaultRegistry({configuration:r})}async function Evt(t,e,r){let o=`/-/user/org.couchdb.user:${encodeURIComponent(e.name)}`,a={_id:`org.couchdb.user:${e.name}`,name:e.name,password:e.password,type:"user",roles:[],date:new Date().toISOString()},n={attemptedAs:e.name,configuration:r,registry:t,jsonResponse:!0,authType:en.AuthType.NO_AUTH};try{return(await en.put(o,a,n)).token}catch(E){if(!(E.originalError?.name==="HTTPError"&&E.originalError?.response.statusCode===409))throw E}let u={...n,authType:en.AuthType.NO_AUTH,headers:{authorization:`Basic ${Buffer.from(`${e.name}:${e.password}`).toString("base64")}`}},A=await en.get(o,u);for(let[E,I]of Object.entries(A))(!a[E]||E==="roles")&&(a[E]=I);let p=`${o}/-rev/${a._rev}`;return(await en.put(p,a,u)).token}async function Cvt(t,e,{alwaysAuth:r,scope:o}){let a=u=>A=>{let p=qe.isIndexableObject(A)?A:{},h=p[u],E=qe.isIndexableObject(h)?h:{};return{...p,[u]:{...E,...r!==void 0?{npmAlwaysAuth:r}:{},npmAuthToken:e}}},n=o?{npmScopes:a(o)}:{npmRegistries:a(t)};return await Je.updateHomeConfiguration(n)}async function wvt({configuration:t,registry:e,report:r,stdin:o,stdout:a}){r.reportInfo(0,`Logging in to ${pe.pretty(t,e,pe.Type.URL)}`);let n=!1;if(e.match(/^https:\/\/npm\.pkg\.github\.com(\/|$)/)&&(r.reportInfo(0,"You seem to be using the GitHub Package Registry. Tokens must be generated with the 'repo', 'write:packages', and 'read:packages' permissions."),n=!0),r.reportSeparator(),t.env.YARN_IS_TEST_ENV)return{name:t.env.YARN_INJECT_NPM_USER||"",password:t.env.YARN_INJECT_NPM_PASSWORD||""};let u=await(0,tve.prompt)([{type:"input",name:"name",message:"Username:",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a},{type:"password",name:"password",message:n?"Token:":"Password:",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a}]);return r.reportSeparator(),u}Ke();Ke();Gt();var $C=new Set(["npmAuthIdent","npmAuthToken"]),ew=class extends ut{constructor(){super(...arguments);this.scope=de.String("-s,--scope",{description:"Logout of the registry configured for a given scope"});this.publish=de.Boolean("--publish",!1,{description:"Logout of the publish registry"});this.all=de.Boolean("-A,--all",!1,{description:"Logout of all registries"})}static{this.paths=[["npm","logout"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"logout of the npm registry",details:"\n This command will log you out by modifying your local configuration (in your home folder, never in the project itself) to delete all credentials linked to a registry.\n\n Adding the `-s,--scope` flag will cause the deletion to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\n\n Adding the `--publish` flag will cause the deletion to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\n\n Adding the `-A,--all` flag will cause the deletion to be done against all registries and scopes.\n ",examples:[["Logout of the default registry","yarn npm logout"],["Logout of the @my-scope scope","yarn npm logout --scope my-scope"],["Logout of the publish registry for the current package","yarn npm logout --publish"],["Logout of all registries","yarn npm logout --all"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=async()=>{let n=await xF({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope}),u=await Je.find(this.context.cwd,this.context.plugins),A=G.makeIdent(this.scope??null,"pkg");return!si.getAuthConfiguration(n,{configuration:u,ident:A}).get("npmAuthToken")};return(await Nt.start({configuration:r,stdout:this.context.stdout},async n=>{if(this.all&&(await Bvt(),n.reportInfo(0,"Successfully logged out from everything")),this.scope){await rve("npmScopes",this.scope),await o()?n.reportInfo(0,`Successfully logged out from ${this.scope}`):n.reportWarning(0,"Scope authentication settings removed, but some other ones settings still apply to it");return}let u=await xF({configuration:r,cwd:this.context.cwd,publish:this.publish});await rve("npmRegistries",u),await o()?n.reportInfo(0,`Successfully logged out from ${u}`):n.reportWarning(0,"Registry authentication settings removed, but some other ones settings still apply to it")})).exitCode()}};function Ivt(t,e){let r=t[e];if(!qe.isIndexableObject(r))return!1;let o=new Set(Object.keys(r));if([...$C].every(n=>!o.has(n)))return!1;for(let n of $C)o.delete(n);if(o.size===0)return t[e]=void 0,!0;let a={...r};for(let n of $C)delete a[n];return t[e]=a,!0}async function Bvt(){let t=e=>{let r=!1,o=qe.isIndexableObject(e)?{...e}:{};o.npmAuthToken&&(delete o.npmAuthToken,r=!0);for(let a of Object.keys(o))Ivt(o,a)&&(r=!0);if(Object.keys(o).length!==0)return r?o:e};return await Je.updateHomeConfiguration({npmRegistries:t,npmScopes:t})}async function rve(t,e){return await Je.updateHomeConfiguration({[t]:r=>{let o=qe.isIndexableObject(r)?r:{};if(!Object.hasOwn(o,e))return r;let a=o[e],n=qe.isIndexableObject(a)?a:{},u=new Set(Object.keys(n));if([...$C].every(p=>!u.has(p)))return r;for(let p of $C)u.delete(p);if(u.size===0)return Object.keys(o).length===1?void 0:{...o,[e]:void 0};let A={};for(let p of $C)A[p]=void 0;return{...o,[e]:{...n,...A}}}})}Ke();Gt();var tw=class extends ut{constructor(){super(...arguments);this.access=de.String("--access",{description:"The access for the published package (public or restricted)"});this.tag=de.String("--tag","latest",{description:"The tag on the registry that the package should be attached to"});this.tolerateRepublish=de.Boolean("--tolerate-republish",!1,{description:"Warn and exit when republishing an already existing version of a package"});this.otp=de.String("--otp",{description:"The OTP token to use with the command"})}static{this.paths=[["npm","publish"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"publish the active workspace to the npm registry",details:'\n This command will pack the active workspace into a fresh archive and upload it to the npm registry.\n\n The package will by default be attached to the `latest` tag on the registry, but this behavior can be overridden by using the `--tag` option.\n\n Note that for legacy reasons scoped packages are by default published with an access set to `restricted` (aka "private packages"). This requires you to register for a paid npm plan. In case you simply wish to publish a public scoped package to the registry (for free), just add the `--access public` flag. This behavior can be enabled by default through the `npmPublishAccess` settings.\n ',examples:[["Publish the active workspace","yarn npm publish"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);if(a.manifest.private)throw new ot("Private workspaces cannot be published");if(a.manifest.name===null||a.manifest.version===null)throw new ot("Workspaces must have valid names and versions to be published on an external registry");await o.restoreInstallState();let n=a.manifest.name,u=a.manifest.version,A=si.getPublishRegistry(a.manifest,{configuration:r});return(await Nt.start({configuration:r,stdout:this.context.stdout},async h=>{if(this.tolerateRepublish)try{let E=await en.get(en.getIdentUrl(n),{configuration:r,registry:A,ident:n,jsonResponse:!0});if(!Object.hasOwn(E,"versions"))throw new zt(15,'Registry returned invalid data for - missing "versions" field');if(Object.hasOwn(E.versions,u)){h.reportWarning(0,`Registry already knows about version ${u}; skipping.`);return}}catch(E){if(E.originalError?.response?.statusCode!==404)throw E}await hn.maybeExecuteWorkspaceLifecycleScript(a,"prepublish",{report:h}),await BA.prepareForPack(a,{report:h},async()=>{let E=await BA.genPackList(a);for(let T of E)h.reportInfo(null,T);let I=await BA.genPackStream(a,E),D=await qe.bufferStream(I),x=await VC.getGitHead(a.cwd),C=await VC.makePublishBody(a,D,{access:this.access,tag:this.tag,registry:A,gitHead:x});await en.put(en.getIdentUrl(n),C,{configuration:r,registry:A,ident:n,otp:this.otp,jsonResponse:!0})}),h.reportInfo(0,"Package archive published")})).exitCode()}};Ke();Gt();var nve=et(ni());Ke();Pt();Gt();var rw=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.package=de.String({required:!1})}static{this.paths=[["npm","tag","list"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"list all dist-tags of a package",details:` + This command will list all tags of a package from the npm registry. + + If the package is not specified, Yarn will default to the current workspace. + `,examples:[["List all tags of package `my-pkg`","yarn npm tag list my-pkg"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n;if(typeof this.package<"u")n=G.parseIdent(this.package);else{if(!a)throw new or(o.cwd,this.context.cwd);if(!a.manifest.name)throw new ot(`Missing 'name' field in ${Ae.fromPortablePath(K.join(a.cwd,mr.manifest))}`);n=a.manifest.name}let u=await Zv(n,r),p={children:qe.sortMap(Object.entries(u),([h])=>h).map(([h,E])=>({value:pe.tuple(pe.Type.RESOLUTION,{descriptor:G.makeDescriptor(n,h),locator:G.makeLocator(n,E)})}))};return As.emitTree(p,{configuration:r,json:this.json,stdout:this.context.stdout})}};async function Zv(t,e){let r=`/-/package${en.getIdentUrl(t)}/dist-tags`;return en.get(r,{configuration:e,ident:t,jsonResponse:!0,customErrorMessage:en.customPackageError})}var nw=class extends ut{constructor(){super(...arguments);this.package=de.String();this.tag=de.String()}static{this.paths=[["npm","tag","add"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"add a tag for a specific version of a package",details:` + This command will add a tag to the npm registry for a specific version of a package. If the tag already exists, it will be overwritten. + `,examples:[["Add a `beta` tag for version `2.3.4-beta.4` of package `my-pkg`","yarn npm tag add my-pkg@2.3.4-beta.4 beta"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=G.parseDescriptor(this.package,!0),u=n.range;if(!nve.default.valid(u))throw new ot(`The range ${pe.pretty(r,n.range,pe.Type.RANGE)} must be a valid semver version`);let A=si.getPublishRegistry(a.manifest,{configuration:r}),p=pe.pretty(r,n,pe.Type.IDENT),h=pe.pretty(r,u,pe.Type.RANGE),E=pe.pretty(r,this.tag,pe.Type.CODE);return(await Nt.start({configuration:r,stdout:this.context.stdout},async D=>{let x=await Zv(n,r);Object.hasOwn(x,this.tag)&&x[this.tag]===u&&D.reportWarning(0,`Tag ${E} is already set to version ${h}`);let C=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.put(C,u,{configuration:r,registry:A,ident:n,jsonRequest:!0,jsonResponse:!0}),D.reportInfo(0,`Tag ${E} added to version ${h} of package ${p}`)})).exitCode()}};Ke();Gt();var iw=class extends ut{constructor(){super(...arguments);this.package=de.String();this.tag=de.String()}static{this.paths=[["npm","tag","remove"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"remove a tag from a package",details:` + This command will remove a tag from a package from the npm registry. + `,examples:[["Remove the `beta` tag from package `my-pkg`","yarn npm tag remove my-pkg beta"]]})}async execute(){if(this.tag==="latest")throw new ot("The 'latest' tag cannot be removed.");let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=G.parseIdent(this.package),u=si.getPublishRegistry(a.manifest,{configuration:r}),A=pe.pretty(r,this.tag,pe.Type.CODE),p=pe.pretty(r,n,pe.Type.IDENT),h=await Zv(n,r);if(!Object.hasOwn(h,this.tag))throw new ot(`${A} is not a tag of package ${p}`);return(await Nt.start({configuration:r,stdout:this.context.stdout},async I=>{let D=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.del(D,{configuration:r,registry:u,ident:n,jsonResponse:!0}),I.reportInfo(0,`Tag ${A} removed from package ${p}`)})).exitCode()}};Ke();Ke();Gt();var sw=class extends ut{constructor(){super(...arguments);this.scope=de.String("-s,--scope",{description:"Print username for the registry configured for a given scope"});this.publish=de.Boolean("--publish",!1,{description:"Print username for the publish registry"})}static{this.paths=[["npm","whoami"]]}static{this.usage=st.Usage({category:"Npm-related commands",description:"display the name of the authenticated user",details:"\n Print the username associated with the current authentication settings to the standard output.\n\n When using `-s,--scope`, the username printed will be the one that matches the authentication settings of the registry associated with the given scope (those settings can be overriden using the `npmRegistries` map, and the registry associated with the scope is configured via the `npmScopes` map).\n\n When using `--publish`, the registry we'll select will by default be the one used when publishing packages (`publishConfig.registry` or `npmPublishRegistry` if available, otherwise we'll fallback to the regular `npmRegistryServer`).\n ",examples:[["Print username for the default registry","yarn npm whoami"],["Print username for the registry on a given scope","yarn npm whoami --scope company"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o;return this.scope&&this.publish?o=si.getScopeRegistry(this.scope,{configuration:r,type:si.RegistryType.PUBLISH_REGISTRY}):this.scope?o=si.getScopeRegistry(this.scope,{configuration:r}):this.publish?o=si.getPublishRegistry((await aE(r,this.context.cwd)).manifest,{configuration:r}):o=si.getDefaultRegistry({configuration:r}),(await Nt.start({configuration:r,stdout:this.context.stdout},async n=>{let u;try{u=await en.get("/-/whoami",{configuration:r,registry:o,authType:en.AuthType.ALWAYS_AUTH,jsonResponse:!0,ident:this.scope?G.makeIdent(this.scope,""):void 0})}catch(A){if(A.response?.statusCode===401||A.response?.statusCode===403){n.reportError(41,"Authentication failed - your credentials may have expired");return}else throw A}n.reportInfo(0,u.username)})).exitCode()}};var vvt={configuration:{npmPublishAccess:{description:"Default access of the published packages",type:"STRING",default:null},npmAuditExcludePackages:{description:"Array of glob patterns of packages to exclude from npm audit",type:"STRING",default:[],isArray:!0},npmAuditIgnoreAdvisories:{description:"Array of glob patterns of advisory IDs to exclude from npm audit",type:"STRING",default:[],isArray:!0}},commands:[JC,XC,ZC,ew,tw,nw,rw,iw,sw]},Dvt=vvt;var gG={};Kt(gG,{PatchCommand:()=>Aw,PatchCommitCommand:()=>uw,PatchFetcher:()=>nD,PatchResolver:()=>iD,default:()=>jvt,patchUtils:()=>wd});Ke();Ke();Pt();sA();var wd={};Kt(wd,{applyPatchFile:()=>QF,diffFolders:()=>pG,ensureUnpatchedDescriptor:()=>cG,ensureUnpatchedLocator:()=>RF,extractPackageToDisk:()=>fG,extractPatchFlags:()=>uve,isParentRequired:()=>AG,isPatchDescriptor:()=>FF,isPatchLocator:()=>i0,loadPatchFiles:()=>rD,makeDescriptor:()=>TF,makeLocator:()=>uG,makePatchHash:()=>hG,parseDescriptor:()=>eD,parseLocator:()=>tD,parsePatchFile:()=>$v,unpatchDescriptor:()=>_vt,unpatchLocator:()=>Hvt});Ke();Pt();Ke();Pt();var Pvt=/^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@.*/;function ow(t){return K.relative(Bt.root,K.resolve(Bt.root,Ae.toPortablePath(t)))}function Svt(t){let e=t.trim().match(Pvt);if(!e)throw new Error(`Bad header line: '${t}'`);return{original:{start:Math.max(Number(e[1]),1),length:Number(e[3]||1)},patched:{start:Math.max(Number(e[4]),1),length:Number(e[6]||1)}}}var bvt=420,xvt=493;var ive=()=>({semverExclusivity:null,diffLineFromPath:null,diffLineToPath:null,oldMode:null,newMode:null,deletedFileMode:null,newFileMode:null,renameFrom:null,renameTo:null,beforeHash:null,afterHash:null,fromPath:null,toPath:null,hunks:null}),kvt=t=>({header:Svt(t),parts:[]}),Qvt={"@":"header","-":"deletion","+":"insertion"," ":"context","\\":"pragma",undefined:"context"};function Fvt(t){let e=[],r=ive(),o="parsing header",a=null,n=null;function u(){a&&(n&&(a.parts.push(n),n=null),r.hunks.push(a),a=null)}function A(){u(),e.push(r),r=ive()}for(let p=0;p0?"patch":"mode change",z=null;switch(U){case"rename":{if(!E||!I)throw new Error("Bad parser state: rename from & to not given");e.push({type:"rename",semverExclusivity:o,fromPath:ow(E),toPath:ow(I)}),z=I}break;case"file deletion":{let te=a||C;if(!te)throw new Error("Bad parse state: no path given for file deletion");e.push({type:"file deletion",semverExclusivity:o,hunk:L&&L[0]||null,path:ow(te),mode:kF(p),hash:D})}break;case"file creation":{let te=n||T;if(!te)throw new Error("Bad parse state: no path given for file creation");e.push({type:"file creation",semverExclusivity:o,hunk:L&&L[0]||null,path:ow(te),mode:kF(h),hash:x})}break;case"patch":case"mode change":z=T||n;break;default:qe.assertNever(U);break}z&&u&&A&&u!==A&&e.push({type:"mode change",semverExclusivity:o,path:ow(z),oldMode:kF(u),newMode:kF(A)}),z&&L&&L.length&&e.push({type:"patch",semverExclusivity:o,path:ow(z),hunks:L,beforeHash:D,afterHash:x})}if(e.length===0)throw new Error("Unable to parse patch file: No changes found. Make sure the patch is a valid UTF8 encoded string");return e}function kF(t){let e=parseInt(t,8)&511;if(e!==bvt&&e!==xvt)throw new Error(`Unexpected file mode string: ${t}`);return e}function $v(t){let e=t.split(/\n/g);return e[e.length-1]===""&&e.pop(),Rvt(Fvt(e))}function Tvt(t){let e=0,r=0;for(let{type:o,lines:a}of t.parts)switch(o){case"context":r+=a.length,e+=a.length;break;case"deletion":e+=a.length;break;case"insertion":r+=a.length;break;default:qe.assertNever(o);break}if(e!==t.header.original.length||r!==t.header.patched.length){let o=a=>a<0?a:`+${a}`;throw new Error(`hunk header integrity check failed (expected @@ ${o(t.header.original.length)} ${o(t.header.patched.length)} @@, got @@ ${o(e)} ${o(r)} @@)`)}}Ke();Pt();var aw=class extends Error{constructor(r,o){super(`Cannot apply hunk #${r+1}`);this.hunk=o}};async function lw(t,e,r){let o=await t.lstatPromise(e),a=await r();typeof a<"u"&&(e=a),await t.lutimesPromise(e,o.atime,o.mtime)}async function QF(t,{baseFs:e=new _n,dryRun:r=!1,version:o=null}={}){for(let a of t)if(!(a.semverExclusivity!==null&&o!==null&&!Ur.satisfiesWithPrereleases(o,a.semverExclusivity)))switch(a.type){case"file deletion":if(r){if(!e.existsSync(a.path))throw new Error(`Trying to delete a file that doesn't exist: ${a.path}`)}else await lw(e,K.dirname(a.path),async()=>{await e.unlinkPromise(a.path)});break;case"rename":if(r){if(!e.existsSync(a.fromPath))throw new Error(`Trying to move a file that doesn't exist: ${a.fromPath}`)}else await lw(e,K.dirname(a.fromPath),async()=>{await lw(e,K.dirname(a.toPath),async()=>{await lw(e,a.fromPath,async()=>(await e.movePromise(a.fromPath,a.toPath),a.toPath))})});break;case"file creation":if(r){if(e.existsSync(a.path))throw new Error(`Trying to create a file that already exists: ${a.path}`)}else{let n=a.hunk?a.hunk.parts[0].lines.join(` +`)+(a.hunk.parts[0].noNewlineAtEndOfFile?"":` +`):"";await e.mkdirpPromise(K.dirname(a.path),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),await e.writeFilePromise(a.path,n,{mode:a.mode}),await e.utimesPromise(a.path,Pi.SAFE_TIME,Pi.SAFE_TIME)}break;case"patch":await lw(e,a.path,async()=>{await Mvt(a,{baseFs:e,dryRun:r})});break;case"mode change":{let u=(await e.statPromise(a.path)).mode;if(sve(a.newMode)!==sve(u))continue;await lw(e,a.path,async()=>{await e.chmodPromise(a.path,a.newMode)})}break;default:qe.assertNever(a);break}}function sve(t){return(t&64)>0}function ove(t){return t.replace(/\s+$/,"")}function Lvt(t,e){return ove(t)===ove(e)}async function Mvt({hunks:t,path:e},{baseFs:r,dryRun:o=!1}){let a=await r.statSync(e).mode,u=(await r.readFileSync(e,"utf8")).split(/\n/),A=[],p=0,h=0;for(let I of t){let D=Math.max(h,I.header.patched.start+p),x=Math.max(0,D-h),C=Math.max(0,u.length-D-I.header.original.length),T=Math.max(x,C),L=0,U=0,z=null;for(;L<=T;){if(L<=x&&(U=D-L,z=ave(I,u,U),z!==null)){L=-L;break}if(L<=C&&(U=D+L,z=ave(I,u,U),z!==null))break;L+=1}if(z===null)throw new aw(t.indexOf(I),I);A.push(z),p+=L,h=U+I.header.original.length}if(o)return;let E=0;for(let I of A)for(let D of I)switch(D.type){case"splice":{let x=D.index+E;u.splice(x,D.numToDelete,...D.linesToInsert),E+=D.linesToInsert.length-D.numToDelete}break;case"pop":u.pop();break;case"push":u.push(D.line);break;default:qe.assertNever(D);break}await r.writeFilePromise(e,u.join(` +`),{mode:a})}function ave(t,e,r){let o=[];for(let a of t.parts)switch(a.type){case"context":case"deletion":{for(let n of a.lines){let u=e[r];if(u==null||!Lvt(u,n))return null;r+=1}a.type==="deletion"&&(o.push({type:"splice",index:r-a.lines.length,numToDelete:a.lines.length,linesToInsert:[]}),a.noNewlineAtEndOfFile&&o.push({type:"push",line:""}))}break;case"insertion":o.push({type:"splice",index:r,numToDelete:0,linesToInsert:a.lines}),a.noNewlineAtEndOfFile&&o.push({type:"pop"});break;default:qe.assertNever(a.type);break}return o}var Uvt=/^builtin<([^>]+)>$/;function cw(t,e){let{protocol:r,source:o,selector:a,params:n}=G.parseRange(t);if(r!=="patch:")throw new Error("Invalid patch range");if(o===null)throw new Error("Patch locators must explicitly define their source");let u=a?a.split(/&/).map(E=>Ae.toPortablePath(E)):[],A=n&&typeof n.locator=="string"?G.parseLocator(n.locator):null,p=n&&typeof n.version=="string"?n.version:null,h=e(o);return{parentLocator:A,sourceItem:h,patchPaths:u,sourceVersion:p}}function FF(t){return t.range.startsWith("patch:")}function i0(t){return t.reference.startsWith("patch:")}function eD(t){let{sourceItem:e,...r}=cw(t.range,G.parseDescriptor);return{...r,sourceDescriptor:e}}function tD(t){let{sourceItem:e,...r}=cw(t.reference,G.parseLocator);return{...r,sourceLocator:e}}function _vt(t){let{sourceItem:e}=cw(t.range,G.parseDescriptor);return e}function Hvt(t){let{sourceItem:e}=cw(t.reference,G.parseLocator);return e}function cG(t){if(!FF(t))return t;let{sourceItem:e}=cw(t.range,G.parseDescriptor);return e}function RF(t){if(!i0(t))return t;let{sourceItem:e}=cw(t.reference,G.parseLocator);return e}function lve({parentLocator:t,sourceItem:e,patchPaths:r,sourceVersion:o,patchHash:a},n){let u=t!==null?{locator:G.stringifyLocator(t)}:{},A=typeof o<"u"?{version:o}:{},p=typeof a<"u"?{hash:a}:{};return G.makeRange({protocol:"patch:",source:n(e),selector:r.join("&"),params:{...A,...p,...u}})}function TF(t,{parentLocator:e,sourceDescriptor:r,patchPaths:o}){return G.makeDescriptor(t,lve({parentLocator:e,sourceItem:r,patchPaths:o},G.stringifyDescriptor))}function uG(t,{parentLocator:e,sourcePackage:r,patchPaths:o,patchHash:a}){return G.makeLocator(t,lve({parentLocator:e,sourceItem:r,sourceVersion:r.version,patchPaths:o,patchHash:a},G.stringifyLocator))}function cve({onAbsolute:t,onRelative:e,onProject:r,onBuiltin:o},a){let n=a.lastIndexOf("!");n!==-1&&(a=a.slice(n+1));let u=a.match(Uvt);return u!==null?o(u[1]):a.startsWith("~/")?r(a.slice(2)):K.isAbsolute(a)?t(a):e(a)}function uve(t){let e=t.lastIndexOf("!");return{optional:(e!==-1?new Set(t.slice(0,e).split(/!/)):new Set).has("optional")}}function AG(t){return cve({onAbsolute:()=>!1,onRelative:()=>!0,onProject:()=>!1,onBuiltin:()=>!1},t)}async function rD(t,e,r){let o=t!==null?await r.fetcher.fetch(t,r):null,a=o&&o.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,o.localPath)}:o;o&&o!==a&&o.releaseFs&&o.releaseFs();let n=await qe.releaseAfterUseAsync(async()=>await Promise.all(e.map(async u=>{let A=uve(u),p=await cve({onAbsolute:async h=>await ae.readFilePromise(h,"utf8"),onRelative:async h=>{if(a===null)throw new Error("Assertion failed: The parent locator should have been fetched");return await a.packageFs.readFilePromise(K.join(a.prefixPath,h),"utf8")},onProject:async h=>await ae.readFilePromise(K.join(r.project.cwd,h),"utf8"),onBuiltin:async h=>await r.project.configuration.firstHook(E=>E.getBuiltinPatch,r.project,h)},u);return{...A,source:p}})));for(let u of n)typeof u.source=="string"&&(u.source=u.source.replace(/\r\n?/g,` +`));return n}async function fG(t,{cache:e,project:r}){let o=r.storedPackages.get(t.locatorHash);if(typeof o>"u")throw new Error("Assertion failed: Expected the package to be registered");let a=RF(t),n=r.storedChecksums,u=new Ri,A=await ae.mktempPromise(),p=K.join(A,"source"),h=K.join(A,"user"),E=K.join(A,".yarn-patch.json"),I=r.configuration.makeFetcher(),D=[];try{let x,C;if(t.locatorHash===a.locatorHash){let T=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u});D.push(()=>T.releaseFs?.()),x=T,C=T}else x=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u}),D.push(()=>x.releaseFs?.()),C=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u}),D.push(()=>C.releaseFs?.());await Promise.all([ae.copyPromise(p,x.prefixPath,{baseFs:x.packageFs}),ae.copyPromise(h,C.prefixPath,{baseFs:C.packageFs}),ae.writeJsonPromise(E,{locator:G.stringifyLocator(t),version:o.version})])}finally{for(let x of D)x()}return ae.detachTemp(A),h}async function pG(t,e){let r=Ae.fromPortablePath(t).replace(/\\/g,"/"),o=Ae.fromPortablePath(e).replace(/\\/g,"/"),{stdout:a,stderr:n}=await Hr.execvp("git",["-c","core.safecrlf=false","diff","--src-prefix=a/","--dst-prefix=b/","--ignore-cr-at-eol","--full-index","--no-index","--no-renames","--text",r,o],{cwd:Ae.toPortablePath(process.cwd()),env:{...process.env,GIT_CONFIG_NOSYSTEM:"1",HOME:"",XDG_CONFIG_HOME:"",USERPROFILE:""}});if(n.length>0)throw new Error(`Unable to diff directories. Make sure you have a recent version of 'git' available in PATH. +The following error was reported by 'git': +${n}`);let u=r.startsWith("/")?A=>A.slice(1):A=>A;return a.replace(new RegExp(`(a|b)(${qe.escapeRegExp(`/${u(r)}/`)})`,"g"),"$1/").replace(new RegExp(`(a|b)${qe.escapeRegExp(`/${u(o)}/`)}`,"g"),"$1/").replace(new RegExp(qe.escapeRegExp(`${r}/`),"g"),"").replace(new RegExp(qe.escapeRegExp(`${o}/`),"g"),"")}function hG(t,e){let r=[];for(let{source:o}of t){if(o===null)continue;let a=$v(o);for(let n of a){let{semverExclusivity:u,...A}=n;u!==null&&e!==null&&!Ur.satisfiesWithPrereleases(e,u)||r.push(JSON.stringify(A))}}return xn.makeHash(`${3}`,...r).slice(0,6)}Ke();function Ave(t,{configuration:e,report:r}){for(let o of t.parts)for(let a of o.lines)switch(o.type){case"context":r.reportInfo(null,` ${pe.pretty(e,a,"grey")}`);break;case"deletion":r.reportError(28,`- ${pe.pretty(e,a,pe.Type.REMOVED)}`);break;case"insertion":r.reportError(28,`+ ${pe.pretty(e,a,pe.Type.ADDED)}`);break;default:qe.assertNever(o.type)}}var nD=class{supports(e,r){return!!i0(e)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.patchPackage(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async patchPackage(e,r){let{parentLocator:o,sourceLocator:a,sourceVersion:n,patchPaths:u}=tD(e),A=await rD(o,u,r),p=await ae.mktempPromise(),h=K.join(p,"current.zip"),E=await r.fetcher.fetch(a,r),I=G.getIdentVendorPath(e),D=new Zi(h,{create:!0,level:r.project.configuration.get("compressionLevel")});await qe.releaseAfterUseAsync(async()=>{await D.copyPromise(I,E.prefixPath,{baseFs:E.packageFs,stableSort:!0})},E.releaseFs),D.saveAndClose();for(let{source:x,optional:C}of A){if(x===null)continue;let T=new Zi(h,{level:r.project.configuration.get("compressionLevel")}),L=new En(K.resolve(Bt.root,I),{baseFs:T});try{await QF($v(x),{baseFs:L,version:n})}catch(U){if(!(U instanceof aw))throw U;let z=r.project.configuration.get("enableInlineHunks"),te=!z&&!C?" (set enableInlineHunks for details)":"",le=`${G.prettyLocator(r.project.configuration,e)}: ${U.message}${te}`,ce=ue=>{z&&Ave(U.hunk,{configuration:r.project.configuration,report:ue})};if(T.discardAndClose(),C){r.report.reportWarningOnce(66,le,{reportExtra:ce});continue}else throw new zt(66,le,ce)}T.saveAndClose()}return new Zi(h,{level:r.project.configuration.get("compressionLevel")})}};Ke();var iD=class{supportsDescriptor(e,r){return!!FF(e)}supportsLocator(e,r){return!!i0(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){let{patchPaths:a}=eD(e);return a.every(n=>!AG(n))?e:G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){let{sourceDescriptor:o}=eD(e);return{sourceDescriptor:r.project.configuration.normalizeDependency(o)}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{parentLocator:a,patchPaths:n}=eD(e),u=await rD(a,n,o.fetchOptions),A=r.sourceDescriptor;if(typeof A>"u")throw new Error("Assertion failed: The dependency should have been resolved");let p=hG(u,A.version);return[uG(e,{parentLocator:a,sourcePackage:A,patchPaths:n,patchHash:p})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let{sourceLocator:o}=tD(e);return{...await r.resolver.resolve(o,r),...e}}};Ke();Pt();Gt();var uw=class extends ut{constructor(){super(...arguments);this.save=de.Boolean("-s,--save",!1,{description:"Add the patch to your resolution entries"});this.patchFolder=de.String()}static{this.paths=[["patch-commit"]]}static{this.usage=st.Usage({description:"generate a patch out of a directory",details:"\n By default, this will print a patchfile on stdout based on the diff between the folder passed in and the original version of the package. Such file is suitable for consumption with the `patch:` protocol.\n\n With the `-s,--save` option set, the patchfile won't be printed on stdout anymore and will instead be stored within a local file (by default kept within `.yarn/patches`, but configurable via the `patchFolder` setting). A `resolutions` entry will also be added to your top-level manifest, referencing the patched package via the `patch:` protocol.\n\n Note that only folders generated by `yarn patch` are accepted as valid input for `yarn patch-commit`.\n "})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=K.resolve(this.context.cwd,Ae.toPortablePath(this.patchFolder)),u=K.join(n,"../source"),A=K.join(n,"../.yarn-patch.json");if(!ae.existsSync(u))throw new ot("The argument folder didn't get created by 'yarn patch'");let p=await pG(u,n),h=await ae.readJsonPromise(A),E=G.parseLocator(h.locator,!0);if(!o.storedPackages.has(E.locatorHash))throw new ot("No package found in the project for the given locator");if(!this.save){this.context.stdout.write(p);return}let I=r.get("patchFolder"),D=K.join(I,`${G.slugifyLocator(E)}.patch`);await ae.mkdirPromise(I,{recursive:!0}),await ae.writeFilePromise(D,p);let x=[],C=new Map;for(let T of o.storedPackages.values()){if(G.isVirtualLocator(T))continue;let L=T.dependencies.get(E.identHash);if(!L)continue;let U=G.ensureDevirtualizedDescriptor(L),z=cG(U),te=o.storedResolutions.get(z.descriptorHash);if(!te)throw new Error("Assertion failed: Expected the resolution to have been registered");if(!o.storedPackages.get(te))throw new Error("Assertion failed: Expected the package to have been registered");let ce=o.tryWorkspaceByLocator(T);if(ce)x.push(ce);else{let ue=o.originalPackages.get(T.locatorHash);if(!ue)throw new Error("Assertion failed: Expected the original package to have been registered");let Ce=ue.dependencies.get(L.identHash);if(!Ce)throw new Error("Assertion failed: Expected the original dependency to have been registered");C.set(Ce.descriptorHash,Ce)}}for(let T of x)for(let L of _t.hardDependencies){let U=T.manifest[L].get(E.identHash);if(!U)continue;let z=TF(U,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(mr.home,K.relative(o.cwd,D))]});T.manifest[L].set(U.identHash,z)}for(let T of C.values()){let L=TF(T,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(mr.home,K.relative(o.cwd,D))]});o.topLevelWorkspace.manifest.resolutions.push({pattern:{descriptor:{fullName:G.stringifyIdent(L),description:T.range}},reference:L.range})}await o.persist()}};Ke();Pt();Gt();var Aw=class extends ut{constructor(){super(...arguments);this.update=de.Boolean("-u,--update",!1,{description:"Reapply local patches that already apply to this packages"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.package=de.String()}static{this.paths=[["patch"]]}static{this.usage=st.Usage({description:"prepare a package for patching",details:"\n This command will cause a package to be extracted in a temporary directory intended to be editable at will.\n\n Once you're done with your changes, run `yarn patch-commit -s path` (with `path` being the temporary directory you received) to generate a patchfile and register it into your top-level manifest via the `patch:` protocol. Run `yarn patch-commit -h` for more details.\n\n Calling the command when you already have a patch won't import it by default (in other words, the default behavior is to reset existing patches). However, adding the `-u,--update` flag will import any current patch.\n "})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let u=G.parseLocator(this.package);if(u.reference==="unknown"){let A=qe.mapAndFilter([...o.storedPackages.values()],p=>p.identHash!==u.identHash?qe.mapAndFilter.skip:G.isVirtualLocator(p)?qe.mapAndFilter.skip:i0(p)!==this.update?qe.mapAndFilter.skip:p);if(A.length===0)throw new ot("No package found in the project for the given locator");if(A.length>1)throw new ot(`Multiple candidate packages found; explicitly choose one of them (use \`yarn why \` to get more information as to who depends on them): +${A.map(p=>` +- ${G.prettyLocator(r,p)}`).join("")}`);u=A[0]}if(!o.storedPackages.has(u.locatorHash))throw new ot("No package found in the project for the given locator");await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=RF(u),h=await fG(u,{cache:n,project:o});A.reportJson({locator:G.stringifyLocator(p),path:Ae.fromPortablePath(h)});let E=this.update?" along with its current modifications":"";A.reportInfo(0,`Package ${G.prettyLocator(r,p)} got extracted with success${E}!`),A.reportInfo(0,`You can now edit the following folder: ${pe.pretty(r,Ae.fromPortablePath(h),"magenta")}`),A.reportInfo(0,`Once you are done run ${pe.pretty(r,`yarn patch-commit -s ${process.platform==="win32"?'"':""}${Ae.fromPortablePath(h)}${process.platform==="win32"?'"':""}`,"cyan")} and Yarn will store a patchfile based on your changes.`)})}};var qvt={configuration:{enableInlineHunks:{description:"If true, the installs will print unmatched patch hunks",type:"BOOLEAN",default:!1},patchFolder:{description:"Folder where the patch files must be written",type:"ABSOLUTE_PATH",default:"./.yarn/patches"}},commands:[uw,Aw],fetchers:[nD],resolvers:[iD]},jvt=qvt;var yG={};Kt(yG,{PnpmLinker:()=>sD,default:()=>Vvt});Ke();Pt();Gt();var sD=class{getCustomDataKey(){return JSON.stringify({name:"PnpmLinker",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the pnpm linker to be enabled");let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=a.pathsByLocator.get(e.locatorHash);if(typeof n>"u")throw new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed pnpm map - running an install might help`);return n.packageLocation}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=e.match(/(^.*\/node_modules\/(@[^/]*\/)?[^/]+)(\/.*$)/);if(n){let p=a.locatorByPath.get(n[1]);if(p)return p}let u=e,A=e;do{A=u,u=K.dirname(A);let p=a.locatorByPath.get(A);if(p)return p}while(u!==A);return null}makeInstaller(e){return new dG(e)}isEnabled(e){return e.project.configuration.get("nodeLinker")==="pnpm"}},dG=class{constructor(e){this.opts=e;this.asyncActions=new qe.AsyncActions(10);this.customData={pathsByLocator:new Map,locatorByPath:new Map};this.indexFolderPromise=$D(ae,{indexPath:K.join(e.project.configuration.get("globalFolder"),"index")})}attachCustomData(e){}async installPackage(e,r,o){switch(e.linkType){case"SOFT":return this.installPackageSoft(e,r,o);case"HARD":return this.installPackageHard(e,r,o)}throw new Error("Assertion failed: Unsupported package link type")}async installPackageSoft(e,r,o){let a=K.resolve(r.packageFs.getRealPath(),r.prefixPath),n=this.opts.project.tryWorkspaceByLocator(e)?K.join(a,mr.nodeModules):null;return this.customData.pathsByLocator.set(e.locatorHash,{packageLocation:a,dependenciesLocation:n}),{packageLocation:a,buildRequest:null}}async installPackageHard(e,r,o){let a=Gvt(e,{project:this.opts.project}),n=a.packageLocation;this.customData.locatorByPath.set(n,G.stringifyLocator(e)),this.customData.pathsByLocator.set(e.locatorHash,a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{await ae.mkdirPromise(n,{recursive:!0}),await ae.copyPromise(n,r.prefixPath,{baseFs:r.packageFs,overwrite:!1,linkStrategy:{type:"HardlinkFromIndex",indexPath:await this.indexFolderPromise,autoRepair:!0}})}));let A=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e,p={manifest:await _t.tryFind(r.prefixPath,{baseFs:r.packageFs})??new _t,misc:{hasBindingGyp:CA.hasBindingGyp(r)}},h=this.opts.project.getDependencyMeta(A,e.version),E=CA.extractBuildRequest(e,p,h,{configuration:this.opts.project.configuration});return{packageLocation:n,buildRequest:E}}async attachInternalDependencies(e,r){if(this.opts.project.configuration.get("nodeLinker")!=="pnpm"||!fve(e,{project:this.opts.project}))return;let o=this.customData.pathsByLocator.get(e.locatorHash);if(typeof o>"u")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(e)})`);let{dependenciesLocation:a}=o;a&&this.asyncActions.reduce(e.locatorHash,async n=>{await ae.mkdirPromise(a,{recursive:!0});let u=await Yvt(a),A=new Map(u),p=[n],h=(I,D)=>{let x=D;fve(D,{project:this.opts.project})||(this.opts.report.reportWarningOnce(0,"The pnpm linker doesn't support providing different versions to workspaces' peer dependencies"),x=G.devirtualizeLocator(D));let C=this.customData.pathsByLocator.get(x.locatorHash);if(typeof C>"u")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(D)})`);let T=G.stringifyIdent(I),L=K.join(a,T),U=K.relative(K.dirname(L),C.packageLocation),z=A.get(T);A.delete(T),p.push(Promise.resolve().then(async()=>{if(z){if(z.isSymbolicLink()&&await ae.readlinkPromise(L)===U)return;await ae.removePromise(L)}await ae.mkdirpPromise(K.dirname(L)),process.platform=="win32"&&this.opts.project.configuration.get("winLinkType")==="junctions"?await ae.symlinkPromise(C.packageLocation,L,"junction"):await ae.symlinkPromise(U,L)}))},E=!1;for(let[I,D]of r)I.identHash===e.identHash&&(E=!0),h(I,D);!E&&!this.opts.project.tryWorkspaceByLocator(e)&&h(G.convertLocatorToDescriptor(e),e),p.push(Wvt(a,A)),await Promise.all(p)})}async attachExternalDependents(e,r){throw new Error("External dependencies haven't been implemented for the pnpm linker")}async finalizeInstall(){let e=hve(this.opts.project);if(this.opts.project.configuration.get("nodeLinker")!=="pnpm")await ae.removePromise(e);else{let r;try{r=new Set(await ae.readdirPromise(e))}catch{r=new Set}for(let{dependenciesLocation:o}of this.customData.pathsByLocator.values()){if(!o)continue;let a=K.contains(e,o);if(a===null)continue;let[n]=a.split(K.sep);r.delete(n)}await Promise.all([...r].map(async o=>{await ae.removePromise(K.join(e,o))}))}return await this.asyncActions.wait(),await mG(e),this.opts.project.configuration.get("nodeLinker")!=="node-modules"&&await mG(pve(this.opts.project)),{customData:this.customData}}};function pve(t){return K.join(t.cwd,mr.nodeModules)}function hve(t){return K.join(pve(t),".store")}function Gvt(t,{project:e}){let r=G.slugifyLocator(t),o=hve(e),a=K.join(o,r,"package"),n=K.join(o,r,mr.nodeModules);return{packageLocation:a,dependenciesLocation:n}}function fve(t,{project:e}){return!G.isVirtualLocator(t)||!e.tryWorkspaceByLocator(t)}async function Yvt(t){let e=new Map,r=[];try{r=await ae.readdirPromise(t,{withFileTypes:!0})}catch(o){if(o.code!=="ENOENT")throw o}try{for(let o of r)if(!o.name.startsWith("."))if(o.name.startsWith("@")){let a=await ae.readdirPromise(K.join(t,o.name),{withFileTypes:!0});if(a.length===0)e.set(o.name,o);else for(let n of a)e.set(`${o.name}/${n.name}`,n)}else e.set(o.name,o)}catch(o){if(o.code!=="ENOENT")throw o}return e}async function Wvt(t,e){let r=[],o=new Set;for(let a of e.keys()){r.push(ae.removePromise(K.join(t,a)));let n=G.tryParseIdent(a)?.scope;n&&o.add(`@${n}`)}return Promise.all(r).then(()=>Promise.all([...o].map(a=>mG(K.join(t,a)))))}async function mG(t){try{await ae.rmdirPromise(t)}catch(e){if(e.code!=="ENOENT"&&e.code!=="ENOTEMPTY")throw e}}var Kvt={linkers:[sD]},Vvt=Kvt;var DG={};Kt(DG,{StageCommand:()=>fw,default:()=>sDt,stageUtils:()=>LF});Ke();Pt();Gt();Ke();Pt();var LF={};Kt(LF,{ActionType:()=>EG,checkConsensus:()=>NF,expandDirectory:()=>IG,findConsensus:()=>BG,findVcsRoot:()=>CG,genCommitMessage:()=>vG,getCommitPrefix:()=>gve,isYarnFile:()=>wG});Pt();var EG=(n=>(n[n.CREATE=0]="CREATE",n[n.DELETE=1]="DELETE",n[n.ADD=2]="ADD",n[n.REMOVE=3]="REMOVE",n[n.MODIFY=4]="MODIFY",n))(EG||{});async function CG(t,{marker:e}){do if(!ae.existsSync(K.join(t,e)))t=K.dirname(t);else return t;while(t!=="/");return null}function wG(t,{roots:e,names:r}){if(r.has(K.basename(t)))return!0;do if(!e.has(t))t=K.dirname(t);else return!0;while(t!=="/");return!1}function IG(t){let e=[],r=[t];for(;r.length>0;){let o=r.pop(),a=ae.readdirSync(o);for(let n of a){let u=K.resolve(o,n);ae.lstatSync(u).isDirectory()?r.push(u):e.push(u)}}return e}function NF(t,e){let r=0,o=0;for(let a of t)a!=="wip"&&(e.test(a)?r+=1:o+=1);return r>=o}function BG(t){let e=NF(t,/^(\w\(\w+\):\s*)?\w+s/),r=NF(t,/^(\w\(\w+\):\s*)?[A-Z]/),o=NF(t,/^\w\(\w+\):/);return{useThirdPerson:e,useUpperCase:r,useComponent:o}}function gve(t){return t.useComponent?"chore(yarn): ":""}var zvt=new Map([[0,"create"],[1,"delete"],[2,"add"],[3,"remove"],[4,"update"]]);function vG(t,e){let r=gve(t),o=[],a=e.slice().sort((n,u)=>n[0]-u[0]);for(;a.length>0;){let[n,u]=a.shift(),A=zvt.get(n);t.useUpperCase&&o.length===0&&(A=`${A[0].toUpperCase()}${A.slice(1)}`),t.useThirdPerson&&(A+="s");let p=[u];for(;a.length>0&&a[0][0]===n;){let[,E]=a.shift();p.push(E)}p.sort();let h=p.shift();p.length===1?h+=" (and one other)":p.length>1&&(h+=` (and ${p.length} others)`),o.push(`${A} ${h}`)}return`${r}${o.join(", ")}`}var Jvt="Commit generated via `yarn stage`",Xvt=11;async function dve(t){let{code:e,stdout:r}=await Hr.execvp("git",["log","-1","--pretty=format:%H"],{cwd:t});return e===0?r.trim():null}async function Zvt(t,e){let r=[],o=e.filter(h=>K.basename(h.path)==="package.json");for(let{action:h,path:E}of o){let I=K.relative(t,E);if(h===4){let D=await dve(t),{stdout:x}=await Hr.execvp("git",["show",`${D}:${I}`],{cwd:t,strict:!0}),C=await _t.fromText(x),T=await _t.fromFile(E),L=new Map([...T.dependencies,...T.devDependencies]),U=new Map([...C.dependencies,...C.devDependencies]);for(let[z,te]of U){let le=G.stringifyIdent(te),ce=L.get(z);ce?ce.range!==te.range&&r.push([4,`${le} to ${ce.range}`]):r.push([3,le])}for(let[z,te]of L)U.has(z)||r.push([2,G.stringifyIdent(te)])}else if(h===0){let D=await _t.fromFile(E);D.name?r.push([0,G.stringifyIdent(D.name)]):r.push([0,"a package"])}else if(h===1){let D=await dve(t),{stdout:x}=await Hr.execvp("git",["show",`${D}:${I}`],{cwd:t,strict:!0}),C=await _t.fromText(x);C.name?r.push([1,G.stringifyIdent(C.name)]):r.push([1,"a package"])}else throw new Error("Assertion failed: Unsupported action type")}let{code:a,stdout:n}=await Hr.execvp("git",["log",`-${Xvt}`,"--pretty=format:%s"],{cwd:t}),u=a===0?n.split(/\n/g).filter(h=>h!==""):[],A=BG(u);return vG(A,r)}var $vt={0:[" A ","?? "],4:[" M "],1:[" D "]},eDt={0:["A "],4:["M "],1:["D "]},mve={async findRoot(t){return await CG(t,{marker:".git"})},async filterChanges(t,e,r,o){let{stdout:a}=await Hr.execvp("git",["status","-s"],{cwd:t,strict:!0}),n=a.toString().split(/\n/g),u=o?.staged?eDt:$vt;return[].concat(...n.map(p=>{if(p==="")return[];let h=p.slice(0,3),E=K.resolve(t,p.slice(3));if(!o?.staged&&h==="?? "&&p.endsWith("/"))return IG(E).map(I=>({action:0,path:I}));{let D=[0,4,1].find(x=>u[x].includes(h));return D!==void 0?[{action:D,path:E}]:[]}})).filter(p=>wG(p.path,{roots:e,names:r}))},async genCommitMessage(t,e){return await Zvt(t,e)},async makeStage(t,e){let r=e.map(o=>Ae.fromPortablePath(o.path));await Hr.execvp("git",["add","--",...r],{cwd:t,strict:!0})},async makeCommit(t,e,r){let o=e.map(a=>Ae.fromPortablePath(a.path));await Hr.execvp("git",["add","-N","--",...o],{cwd:t,strict:!0}),await Hr.execvp("git",["commit","-m",`${r} + +${Jvt} +`,"--",...o],{cwd:t,strict:!0})},async makeReset(t,e){let r=e.map(o=>Ae.fromPortablePath(o.path));await Hr.execvp("git",["reset","HEAD","--",...r],{cwd:t,strict:!0})}};var tDt=[mve],fw=class extends ut{constructor(){super(...arguments);this.commit=de.Boolean("-c,--commit",!1,{description:"Commit the staged files"});this.reset=de.Boolean("-r,--reset",!1,{description:"Remove all files from the staging area"});this.dryRun=de.Boolean("-n,--dry-run",!1,{description:"Print the commit message and the list of modified files without staging / committing"});this.update=de.Boolean("-u,--update",!1,{hidden:!0})}static{this.paths=[["stage"]]}static{this.usage=st.Usage({description:"add all yarn files to your vcs",details:"\n This command will add to your staging area the files belonging to Yarn (typically any modified `package.json` and `.yarnrc.yml` files, but also linker-generated files, cache data, etc). It will take your ignore list into account, so the cache files won't be added if the cache is ignored in a `.gitignore` file (assuming you use Git).\n\n Running `--reset` will instead remove them from the staging area (the changes will still be there, but won't be committed until you stage them back).\n\n Since the staging area is a non-existent concept in Mercurial, Yarn will always create a new commit when running this command on Mercurial repositories. You can get this behavior when using Git by using the `--commit` flag which will directly create a commit.\n ",examples:[["Adds all modified project files to the staging area","yarn stage"],["Creates a new commit containing all modified project files","yarn stage --commit"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),{driver:a,root:n}=await rDt(o.cwd),u=[r.get("cacheFolder"),r.get("globalFolder"),r.get("virtualFolder"),r.get("yarnPath")];await r.triggerHook(I=>I.populateYarnPaths,o,I=>{u.push(I)});let A=new Set;for(let I of u)for(let D of nDt(n,I))A.add(D);let p=new Set([r.get("rcFilename"),mr.lockfile,mr.manifest]),h=await a.filterChanges(n,A,p),E=await a.genCommitMessage(n,h);if(this.dryRun)if(this.commit)this.context.stdout.write(`${E} +`);else for(let I of h)this.context.stdout.write(`${Ae.fromPortablePath(I.path)} +`);else if(this.reset){let I=await a.filterChanges(n,A,p,{staged:!0});I.length===0?this.context.stdout.write("No staged changes found!"):await a.makeReset(n,I)}else h.length===0?this.context.stdout.write("No changes found!"):this.commit?await a.makeCommit(n,h,E):(await a.makeStage(n,h),this.context.stdout.write(E))}};async function rDt(t){let e=null,r=null;for(let o of tDt)if((r=await o.findRoot(t))!==null){e=o;break}if(e===null||r===null)throw new ot("No stage driver has been found for your current project");return{driver:e,root:r}}function nDt(t,e){let r=[];if(e===null)return r;for(;;){(e===t||e.startsWith(`${t}/`))&&r.push(e);let o;try{o=ae.statSync(e)}catch{break}if(o.isSymbolicLink())e=K.resolve(K.dirname(e),ae.readlinkSync(e));else break}return r}var iDt={commands:[fw]},sDt=iDt;var PG={};Kt(PG,{default:()=>pDt});Ke();Ke();Pt();var Cve=et(ni());Ke();var yve=et(L6()),oDt="e8e1bd300d860104bb8c58453ffa1eb4",aDt="OFCNCOG2CU",Eve=async(t,e)=>{let r=G.stringifyIdent(t),a=lDt(e).initIndex("npm-search");try{return(await a.getObject(r,{attributesToRetrieve:["types"]})).types?.ts==="definitely-typed"}catch{return!1}},lDt=t=>(0,yve.default)(aDt,oDt,{requester:{async send(r){try{let o=await on.request(r.url,r.data||null,{configuration:t,headers:r.headers});return{content:o.body,isTimedOut:!1,status:o.statusCode}}catch(o){return{content:o.response.body,isTimedOut:!1,status:o.response.statusCode}}}}});var wve=t=>t.scope?`${t.scope}__${t.name}`:`${t.name}`,cDt=async(t,e,r,o)=>{if(r.scope==="types")return;let{project:a}=t,{configuration:n}=a;if(!(n.get("tsEnableAutoTypes")??(ae.existsSync(K.join(t.cwd,"tsconfig.json"))||ae.existsSync(K.join(a.cwd,"tsconfig.json")))))return;let A=n.makeResolver(),p={project:a,resolver:A,report:new Ri};if(!await Eve(r,n))return;let E=wve(r),I=G.parseRange(r.range).selector;if(!Ur.validRange(I)){let L=n.normalizeDependency(r),U=await A.getCandidates(L,{},p);I=G.parseRange(U[0].reference).selector}let D=Cve.default.coerce(I);if(D===null)return;let x=`${nu.Modifier.CARET}${D.major}`,C=G.makeDescriptor(G.makeIdent("types",E),x),T=qe.mapAndFind(a.workspaces,L=>{let U=L.manifest.dependencies.get(r.identHash)?.descriptorHash,z=L.manifest.devDependencies.get(r.identHash)?.descriptorHash;if(U!==r.descriptorHash&&z!==r.descriptorHash)return qe.mapAndFind.skip;let te=[];for(let le of _t.allDependencies){let ce=L.manifest[le].get(C.identHash);typeof ce>"u"||te.push([le,ce])}return te.length===0?qe.mapAndFind.skip:te});if(typeof T<"u")for(let[L,U]of T)t.manifest[L].set(U.identHash,U);else{try{let L=n.normalizeDependency(C);if((await A.getCandidates(L,{},p)).length===0)return}catch{return}t.manifest[nu.Target.DEVELOPMENT].set(C.identHash,C)}},uDt=async(t,e,r)=>{if(r.scope==="types")return;let{project:o}=t,{configuration:a}=o;if(!(a.get("tsEnableAutoTypes")??(ae.existsSync(K.join(t.cwd,"tsconfig.json"))||ae.existsSync(K.join(o.cwd,"tsconfig.json")))))return;let u=wve(r),A=G.makeIdent("types",u);for(let p of _t.allDependencies)typeof t.manifest[p].get(A.identHash)>"u"||t.manifest[p].delete(A.identHash)},ADt=(t,e)=>{e.publishConfig&&e.publishConfig.typings&&(e.typings=e.publishConfig.typings),e.publishConfig&&e.publishConfig.types&&(e.types=e.publishConfig.types)},fDt={configuration:{tsEnableAutoTypes:{description:"Whether Yarn should auto-install @types/ dependencies on 'yarn add'",type:"BOOLEAN",isNullable:!0,default:null}},hooks:{afterWorkspaceDependencyAddition:cDt,afterWorkspaceDependencyRemoval:uDt,beforeWorkspacePacking:ADt}},pDt=fDt;var QG={};Kt(QG,{VersionApplyCommand:()=>mw,VersionCheckCommand:()=>yw,VersionCommand:()=>Ew,default:()=>FDt,versionUtils:()=>dw});Ke();Ke();Gt();var dw={};Kt(dw,{Decision:()=>hw,applyPrerelease:()=>Sve,applyReleases:()=>kG,applyStrategy:()=>OF,clearVersionFiles:()=>SG,getUndecidedDependentWorkspaces:()=>aD,getUndecidedWorkspaces:()=>MF,openVersionFile:()=>gw,requireMoreDecisions:()=>xDt,resolveVersionFiles:()=>oD,suggestStrategy:()=>xG,updateVersionFiles:()=>bG,validateReleaseDecision:()=>pw});Ke();Pt();Ml();Gt();var Pve=et(Dve()),PA=et(ni()),bDt=/^(>=|[~^]|)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/,hw=(u=>(u.UNDECIDED="undecided",u.DECLINE="decline",u.MAJOR="major",u.MINOR="minor",u.PATCH="patch",u.PRERELEASE="prerelease",u))(hw||{});function pw(t){let e=PA.default.valid(t);return e||qe.validateEnum((0,Pve.default)(hw,"UNDECIDED"),t)}async function oD(t,{prerelease:e=null}={}){let r=new Map,o=t.configuration.get("deferredVersionFolder");if(!ae.existsSync(o))return r;let a=await ae.readdirPromise(o);for(let n of a){if(!n.endsWith(".yml"))continue;let u=K.join(o,n),A=await ae.readFilePromise(u,"utf8"),p=Ki(A);for(let[h,E]of Object.entries(p.releases||{})){if(E==="decline")continue;let I=G.parseIdent(h),D=t.tryWorkspaceByIdent(I);if(D===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${K.basename(u)} references ${h})`);if(D.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${G.prettyLocator(t.configuration,D.anchoredLocator)})`);let x=D.manifest.raw.stableVersion??D.manifest.version,C=r.get(D),T=OF(x,pw(E));if(T===null)throw new Error(`Assertion failed: Expected ${x} to support being bumped via strategy ${E}`);let L=typeof C<"u"?PA.default.gt(T,C)?T:C:T;r.set(D,L)}}return e&&(r=new Map([...r].map(([n,u])=>[n,Sve(u,{current:n.manifest.version,prerelease:e})]))),r}async function SG(t){let e=t.configuration.get("deferredVersionFolder");ae.existsSync(e)&&await ae.removePromise(e)}async function bG(t,e){let r=new Set(e),o=t.configuration.get("deferredVersionFolder");if(!ae.existsSync(o))return;let a=await ae.readdirPromise(o);for(let n of a){if(!n.endsWith(".yml"))continue;let u=K.join(o,n),A=await ae.readFilePromise(u,"utf8"),p=Ki(A),h=p?.releases;if(h){for(let E of Object.keys(h)){let I=G.parseIdent(E),D=t.tryWorkspaceByIdent(I);(D===null||r.has(D))&&delete p.releases[E]}Object.keys(p.releases).length>0?await ae.changeFilePromise(u,Pa(new Pa.PreserveOrdering(p))):await ae.unlinkPromise(u)}}}async function gw(t,{allowEmpty:e=!1}={}){let r=t.configuration;if(r.projectCwd===null)throw new ot("This command can only be run from within a Yarn project");let o=await ra.fetchRoot(r.projectCwd),a=o!==null?await ra.fetchBase(o,{baseRefs:r.get("changesetBaseRefs")}):null,n=o!==null?await ra.fetchChangedFiles(o,{base:a.hash,project:t}):[],u=r.get("deferredVersionFolder"),A=n.filter(x=>K.contains(u,x)!==null);if(A.length>1)throw new ot(`Your current branch contains multiple versioning files; this isn't supported: +- ${A.map(x=>Ae.fromPortablePath(x)).join(` +- `)}`);let p=new Set(qe.mapAndFilter(n,x=>{let C=t.tryWorkspaceByFilePath(x);return C===null?qe.mapAndFilter.skip:C}));if(A.length===0&&p.size===0&&!e)return null;let h=A.length===1?A[0]:K.join(u,`${xn.makeHash(Math.random().toString()).slice(0,8)}.yml`),E=ae.existsSync(h)?await ae.readFilePromise(h,"utf8"):"{}",I=Ki(E),D=new Map;for(let x of I.declined||[]){let C=G.parseIdent(x),T=t.getWorkspaceByIdent(C);D.set(T,"decline")}for(let[x,C]of Object.entries(I.releases||{})){let T=G.parseIdent(x),L=t.getWorkspaceByIdent(T);D.set(L,pw(C))}return{project:t,root:o,baseHash:a!==null?a.hash:null,baseTitle:a!==null?a.title:null,changedFiles:new Set(n),changedWorkspaces:p,releaseRoots:new Set([...p].filter(x=>x.manifest.version!==null)),releases:D,async saveAll(){let x={},C=[],T=[];for(let L of t.workspaces){if(L.manifest.version===null)continue;let U=G.stringifyIdent(L.anchoredLocator),z=D.get(L);z==="decline"?C.push(U):typeof z<"u"?x[U]=pw(z):p.has(L)&&T.push(U)}await ae.mkdirPromise(K.dirname(h),{recursive:!0}),await ae.changeFilePromise(h,Pa(new Pa.PreserveOrdering({releases:Object.keys(x).length>0?x:void 0,declined:C.length>0?C:void 0,undecided:T.length>0?T:void 0})))}}}function xDt(t){return MF(t).size>0||aD(t).length>0}function MF(t){let e=new Set;for(let r of t.changedWorkspaces)r.manifest.version!==null&&(t.releases.has(r)||e.add(r));return e}function aD(t,{include:e=new Set}={}){let r=[],o=new Map(qe.mapAndFilter([...t.releases],([n,u])=>u==="decline"?qe.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n])),a=new Map(qe.mapAndFilter([...t.releases],([n,u])=>u!=="decline"?qe.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n]));for(let n of t.project.workspaces)if(!(!e.has(n)&&(a.has(n.anchoredLocator.locatorHash)||o.has(n.anchoredLocator.locatorHash)))&&n.manifest.version!==null)for(let u of _t.hardDependencies)for(let A of n.manifest.getForScope(u).values()){let p=t.project.tryWorkspaceByDescriptor(A);p!==null&&o.has(p.anchoredLocator.locatorHash)&&r.push([n,p])}return r}function xG(t,e){let r=PA.default.clean(e);for(let o of Object.values(hw))if(o!=="undecided"&&o!=="decline"&&PA.default.inc(t,o)===r)return o;return null}function OF(t,e){if(PA.default.valid(e))return e;if(t===null)throw new ot(`Cannot apply the release strategy "${e}" unless the workspace already has a valid version`);if(!PA.default.valid(t))throw new ot(`Cannot apply the release strategy "${e}" on a non-semver version (${t})`);let r=PA.default.inc(t,e);if(r===null)throw new ot(`Cannot apply the release strategy "${e}" on the specified version (${t})`);return r}function kG(t,e,{report:r}){let o=new Map;for(let a of t.workspaces)for(let n of _t.allDependencies)for(let u of a.manifest[n].values()){let A=t.tryWorkspaceByDescriptor(u);if(A===null||!e.has(A))continue;qe.getArrayWithDefault(o,A).push([a,n,u.identHash])}for(let[a,n]of e){let u=a.manifest.version;a.manifest.version=n,PA.default.prerelease(n)===null?delete a.manifest.raw.stableVersion:a.manifest.raw.stableVersion||(a.manifest.raw.stableVersion=u);let A=a.manifest.name!==null?G.stringifyIdent(a.manifest.name):null;r.reportInfo(0,`${G.prettyLocator(t.configuration,a.anchoredLocator)}: Bumped to ${n}`),r.reportJson({cwd:Ae.fromPortablePath(a.cwd),ident:A,oldVersion:u,newVersion:n});let p=o.get(a);if(!(typeof p>"u"))for(let[h,E,I]of p){let D=h.manifest[E].get(I);if(typeof D>"u")throw new Error("Assertion failed: The dependency should have existed");let x=D.range,C=!1;if(x.startsWith(ci.protocol)&&(x=x.slice(ci.protocol.length),C=!0,x===a.relativeCwd))continue;let T=x.match(bDt);if(!T){r.reportWarning(0,`Couldn't auto-upgrade range ${x} (in ${G.prettyLocator(t.configuration,h.anchoredLocator)})`);continue}let L=`${T[1]}${n}`;C&&(L=`${ci.protocol}${L}`);let U=G.makeDescriptor(D,L);h.manifest[E].set(I,U)}}}var kDt=new Map([["%n",{extract:t=>t.length>=1?[t[0],t.slice(1)]:null,generate:(t=0)=>`${t+1}`}]]);function Sve(t,{current:e,prerelease:r}){let o=new PA.default.SemVer(e),a=o.prerelease.slice(),n=[];o.prerelease=[],o.format()!==t&&(a.length=0);let u=!0,A=r.split(/\./g);for(let p of A){let h=kDt.get(p);if(typeof h>"u")n.push(p),a[0]===p?a.shift():u=!1;else{let E=u?h.extract(a):null;E!==null&&typeof E[0]=="number"?(n.push(h.generate(E[0])),a=E[1]):(n.push(h.generate()),u=!1)}}return o.prerelease&&(o.prerelease=[]),`${t}-${n.join(".")}`}var mw=class extends ut{constructor(){super(...arguments);this.all=de.Boolean("--all",!1,{description:"Apply the deferred version changes on all workspaces"});this.dryRun=de.Boolean("--dry-run",!1,{description:"Print the versions without actually generating the package archive"});this.prerelease=de.String("--prerelease",{description:"Add a prerelease identifier to new versions",tolerateBoolean:!0});this.recursive=de.Boolean("-R,--recursive",{description:"Release the transitive workspaces as well"});this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["version","apply"]]}static{this.usage=st.Usage({category:"Release-related commands",description:"apply all the deferred version bumps at once",details:` + This command will apply the deferred version changes and remove their definitions from the repository. + + Note that if \`--prerelease\` is set, the given prerelease identifier (by default \`rc.%n\`) will be used on all new versions and the version definitions will be kept as-is. + + By default only the current workspace will be bumped, but you can configure this behavior by using one of: + + - \`--recursive\` to also apply the version bump on its dependencies + - \`--all\` to apply the version bump on all packages in the repository + + Note that this command will also update the \`workspace:\` references across all your local workspaces, thus ensuring that they keep referring to the same workspaces even after the version bump. + `,examples:[["Apply the version change to the local workspace","yarn version apply"],["Apply the version change to all the workspaces in the local workspace","yarn version apply --all"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=await Nt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=this.prerelease?typeof this.prerelease!="boolean"?this.prerelease:"rc.%n":null,h=await oD(o,{prerelease:p}),E=new Map;if(this.all)E=h;else{let I=this.recursive?a.getRecursiveWorkspaceDependencies():[a];for(let D of I){let x=h.get(D);typeof x<"u"&&E.set(D,x)}}if(E.size===0){let I=h.size>0?" Did you want to add --all?":"";A.reportWarning(0,`The current workspace doesn't seem to require a version bump.${I}`);return}kG(o,E,{report:A}),this.dryRun||(p||(this.all?await SG(o):await bG(o,[...E.keys()])),A.reportSeparator())});return this.dryRun||u.hasErrors()?u.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};Ke();Pt();Gt();var UF=et(ni());var yw=class extends ut{constructor(){super(...arguments);this.interactive=de.Boolean("-i,--interactive",{description:"Open an interactive interface used to set version bumps"})}static{this.paths=[["version","check"]]}static{this.usage=st.Usage({category:"Release-related commands",description:"check that all the relevant packages have been bumped",details:"\n **Warning:** This command currently requires Git.\n\n This command will check that all the packages covered by the files listed in argument have been properly bumped or declined to bump.\n\n In the case of a bump, the check will also cover transitive packages - meaning that should `Foo` be bumped, a package `Bar` depending on `Foo` will require a decision as to whether `Bar` will need to be bumped. This check doesn't cross packages that have declined to bump.\n\n In case no arguments are passed to the function, the list of modified files will be generated by comparing the HEAD against `master`.\n ",examples:[["Check whether the modified packages need a bump","yarn version check"]]})}async execute(){return this.interactive?await this.executeInteractive():await this.executeStandard()}async executeInteractive(){AC(this.context);let{Gem:r}=await Promise.resolve().then(()=>(UQ(),oj)),{ScrollableItems:o}=await Promise.resolve().then(()=>(jQ(),qQ)),{FocusRequest:a}=await Promise.resolve().then(()=>(lj(),QIe)),{useListInput:n}=await Promise.resolve().then(()=>(HQ(),FIe)),{renderForm:u}=await Promise.resolve().then(()=>(KQ(),WQ)),{Box:A,Text:p}=await Promise.resolve().then(()=>et(ac())),{default:h,useCallback:E,useState:I}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),{project:x,workspace:C}=await Qt.find(D,this.context.cwd);if(!C)throw new or(x.cwd,this.context.cwd);await x.restoreInstallState();let T=await gw(x);if(T===null||T.releaseRoots.size===0)return 0;if(T.root===null)throw new ot("This command can only be run on Git repositories");let L=()=>h.createElement(A,{flexDirection:"row",paddingBottom:1},h.createElement(A,{flexDirection:"column",width:60},h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},""),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to select workspaces.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},""),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to select release strategies."))),h.createElement(A,{flexDirection:"column"},h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to save.")),h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to abort.")))),U=({workspace:Ce,active:he,decision:De,setDecision:Ee})=>{let g=Ce.manifest.raw.stableVersion??Ce.manifest.version;if(g===null)throw new Error(`Assertion failed: The version should have been set (${G.prettyLocator(D,Ce.anchoredLocator)})`);if(UF.default.prerelease(g)!==null)throw new Error(`Assertion failed: Prerelease identifiers shouldn't be found (${g})`);let me=["undecided","decline","patch","minor","major"];n(De,me,{active:he,minus:"left",plus:"right",set:Ee});let we=De==="undecided"?h.createElement(p,{color:"yellow"},g):De==="decline"?h.createElement(p,{color:"green"},g):h.createElement(p,null,h.createElement(p,{color:"magenta"},g)," \u2192 ",h.createElement(p,{color:"green"},UF.default.valid(De)?De:UF.default.inc(g,De)));return h.createElement(A,{flexDirection:"column"},h.createElement(A,null,h.createElement(p,null,G.prettyLocator(D,Ce.anchoredLocator)," - ",we)),h.createElement(A,null,me.map(fe=>h.createElement(A,{key:fe,paddingLeft:2},h.createElement(p,null,h.createElement(r,{active:fe===De})," ",fe)))))},z=Ce=>{let he=new Set(T.releaseRoots),De=new Map([...Ce].filter(([Ee])=>he.has(Ee)));for(;;){let Ee=aD({project:T.project,releases:De}),g=!1;if(Ee.length>0){for(let[me]of Ee)if(!he.has(me)){he.add(me),g=!0;let we=Ce.get(me);typeof we<"u"&&De.set(me,we)}}if(!g)break}return{relevantWorkspaces:he,relevantReleases:De}},te=()=>{let[Ce,he]=I(()=>new Map(T.releases)),De=E((Ee,g)=>{let me=new Map(Ce);g!=="undecided"?me.set(Ee,g):me.delete(Ee);let{relevantReleases:we}=z(me);he(we)},[Ce,he]);return[Ce,De]},le=({workspaces:Ce,releases:he})=>{let De=[];De.push(`${Ce.size} total`);let Ee=0,g=0;for(let me of Ce){let we=he.get(me);typeof we>"u"?g+=1:we!=="decline"&&(Ee+=1)}return De.push(`${Ee} release${Ee===1?"":"s"}`),De.push(`${g} remaining`),h.createElement(p,{color:"yellow"},De.join(", "))},ue=await u(({useSubmit:Ce})=>{let[he,De]=te();Ce(he);let{relevantWorkspaces:Ee}=z(he),g=new Set([...Ee].filter(ie=>!T.releaseRoots.has(ie))),[me,we]=I(0),fe=E(ie=>{switch(ie){case a.BEFORE:we(me-1);break;case a.AFTER:we(me+1);break}},[me,we]);return h.createElement(A,{flexDirection:"column"},h.createElement(L,null),h.createElement(A,null,h.createElement(p,{wrap:"wrap"},"The following files have been modified in your local checkout.")),h.createElement(A,{flexDirection:"column",marginTop:1,paddingLeft:2},[...T.changedFiles].map(ie=>h.createElement(A,{key:ie},h.createElement(p,null,h.createElement(p,{color:"grey"},Ae.fromPortablePath(T.root)),Ae.sep,Ae.relative(Ae.fromPortablePath(T.root),Ae.fromPortablePath(ie)))))),T.releaseRoots.size>0&&h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:"wrap"},"Because of those files having been modified, the following workspaces may need to be released again (note that private workspaces are also shown here, because even though they won't be published, releasing them will allow us to flag their dependents for potential re-release):")),g.size>3?h.createElement(A,{marginTop:1},h.createElement(le,{workspaces:T.releaseRoots,releases:he})):null,h.createElement(A,{marginTop:1,flexDirection:"column"},h.createElement(o,{active:me%2===0,radius:1,size:2,onFocusRequest:fe},[...T.releaseRoots].map(ie=>h.createElement(U,{key:ie.cwd,workspace:ie,decision:he.get(ie)||"undecided",setDecision:Z=>De(ie,Z)}))))),g.size>0?h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:"wrap"},"The following workspaces depend on other workspaces that have been marked for release, and thus may need to be released as well:")),h.createElement(A,null,h.createElement(p,null,"(Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"")," to move the focus between the workspace groups.)")),g.size>5?h.createElement(A,{marginTop:1},h.createElement(le,{workspaces:g,releases:he})):null,h.createElement(A,{marginTop:1,flexDirection:"column"},h.createElement(o,{active:me%2===1,radius:2,size:2,onFocusRequest:fe},[...g].map(ie=>h.createElement(U,{key:ie.cwd,workspace:ie,decision:he.get(ie)||"undecided",setDecision:Z=>De(ie,Z)}))))):null)},{versionFile:T},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ue>"u")return 1;T.releases.clear();for(let[Ce,he]of ue)T.releases.set(Ce,he);await T.saveAll()}async executeStandard(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);return await o.restoreInstallState(),(await Nt.start({configuration:r,stdout:this.context.stdout},async u=>{let A=await gw(o);if(A===null||A.releaseRoots.size===0)return;if(A.root===null)throw new ot("This command can only be run on Git repositories");if(u.reportInfo(0,`Your PR was started right after ${pe.pretty(r,A.baseHash.slice(0,7),"yellow")} ${pe.pretty(r,A.baseTitle,"magenta")}`),A.changedFiles.size>0){u.reportInfo(0,"You have changed the following files since then:"),u.reportSeparator();for(let D of A.changedFiles)u.reportInfo(null,`${pe.pretty(r,Ae.fromPortablePath(A.root),"gray")}${Ae.sep}${Ae.relative(Ae.fromPortablePath(A.root),Ae.fromPortablePath(D))}`)}let p=!1,h=!1,E=MF(A);if(E.size>0){p||u.reportSeparator();for(let D of E)u.reportError(0,`${G.prettyLocator(r,D.anchoredLocator)} has been modified but doesn't have a release strategy attached`);p=!0}let I=aD(A);for(let[D,x]of I)h||u.reportSeparator(),u.reportError(0,`${G.prettyLocator(r,D.anchoredLocator)} doesn't have a release strategy attached, but depends on ${G.prettyWorkspace(r,x)} which is planned for release.`),h=!0;(p||h)&&(u.reportSeparator(),u.reportInfo(0,"This command detected that at least some workspaces have received modifications without explicit instructions as to how they had to be released (if needed)."),u.reportInfo(0,"To correct these errors, run `yarn version check --interactive` then follow the instructions."))})).exitCode()}};Ke();Gt();var _F=et(ni());var Ew=class extends ut{constructor(){super(...arguments);this.deferred=de.Boolean("-d,--deferred",{description:"Prepare the version to be bumped during the next release cycle"});this.immediate=de.Boolean("-i,--immediate",{description:"Bump the version immediately"});this.strategy=de.String()}static{this.paths=[["version"]]}static{this.usage=st.Usage({category:"Release-related commands",description:"apply a new version to the current package",details:"\n This command will bump the version number for the given package, following the specified strategy:\n\n - If `major`, the first number from the semver range will be increased (`X.0.0`).\n - If `minor`, the second number from the semver range will be increased (`0.X.0`).\n - If `patch`, the third number from the semver range will be increased (`0.0.X`).\n - If prefixed by `pre` (`premajor`, ...), a `-0` suffix will be set (`0.0.0-0`).\n - If `prerelease`, the suffix will be increased (`0.0.0-X`); the third number from the semver range will also be increased if there was no suffix in the previous version.\n - If `decline`, the nonce will be increased for `yarn version check` to pass without version bump.\n - If a valid semver range, it will be used as new version.\n - If unspecified, Yarn will ask you for guidance.\n\n For more information about the `--deferred` flag, consult our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).\n ",examples:[["Immediately bump the version to the next major","yarn version major"],["Prepare the version to be bumped to the next major","yarn version major --deferred"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=r.get("preferDeferredVersions");this.deferred&&(n=!0),this.immediate&&(n=!1);let u=_F.default.valid(this.strategy),A=this.strategy==="decline",p;if(u)if(a.manifest.version!==null){let E=xG(a.manifest.version,this.strategy);E!==null?p=E:p=this.strategy}else p=this.strategy;else{let E=a.manifest.version;if(!A){if(E===null)throw new ot("Can't bump the version if there wasn't a version to begin with - use 0.0.0 as initial version then run the command again.");if(typeof E!="string"||!_F.default.valid(E))throw new ot(`Can't bump the version (${E}) if it's not valid semver`)}p=pw(this.strategy)}if(!n){let I=(await oD(o)).get(a);if(typeof I<"u"&&p!=="decline"){let D=OF(a.manifest.version,p);if(_F.default.lt(D,I))throw new ot(`Can't bump the version to one that would be lower than the current deferred one (${I})`)}}let h=await gw(o,{allowEmpty:!0});return h.releases.set(a,p),await h.saveAll(),n?0:await this.cli.run(["version","apply"])}};var QDt={configuration:{deferredVersionFolder:{description:"Folder where are stored the versioning files",type:"ABSOLUTE_PATH",default:"./.yarn/versions"},preferDeferredVersions:{description:"If true, running `yarn version` will assume the `--deferred` flag unless `--immediate` is set",type:"BOOLEAN",default:!1}},commands:[mw,yw,Ew]},FDt=QDt;var FG={};Kt(FG,{WorkspacesFocusCommand:()=>Cw,WorkspacesForeachCommand:()=>Iw,default:()=>NDt});Ke();Ke();Gt();var Cw=class extends ut{constructor(){super(...arguments);this.json=de.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.production=de.Boolean("--production",!1,{description:"Only install regular dependencies by omitting dev dependencies"});this.all=de.Boolean("-A,--all",!1,{description:"Install the entire project"});this.workspaces=de.Rest()}static{this.paths=[["workspaces","focus"]]}static{this.usage=st.Usage({category:"Workspace-related commands",description:"install a single workspace and its dependencies",details:"\n This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\n\n Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\n\n If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\n "})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Yr.find(r);await o.restoreInstallState({restoreResolutions:!1});let u;if(this.all)u=new Set(o.workspaces);else if(this.workspaces.length===0){if(!a)throw new or(o.cwd,this.context.cwd);u=new Set([a])}else u=new Set(this.workspaces.map(A=>o.getWorkspaceByIdent(G.parseIdent(A))));for(let A of u)for(let p of this.production?["dependencies"]:_t.hardDependencies)for(let h of A.manifest.getForScope(p).values()){let E=o.tryWorkspaceByDescriptor(h);E!==null&&u.add(E)}for(let A of o.workspaces)u.has(A)?this.production&&A.manifest.devDependencies.clear():(A.manifest.installConfig=A.manifest.installConfig||{},A.manifest.installConfig.selfReferences=!1,A.manifest.dependencies.clear(),A.manifest.devDependencies.clear(),A.manifest.peerDependencies.clear(),A.manifest.scripts.clear());return await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n,persistProject:!1})}};Ke();Ke();Ke();Gt();var ww=et(Xo()),xve=et(lg());il();var Iw=class extends ut{constructor(){super(...arguments);this.from=de.Array("--from",{description:"An array of glob pattern idents or paths from which to base any recursion"});this.all=de.Boolean("-A,--all",{description:"Run the command on all workspaces of a project"});this.recursive=de.Boolean("-R,--recursive",{description:"Run the command on the current workspace and all of its recursive dependencies"});this.worktree=de.Boolean("-W,--worktree",{description:"Run the command on all workspaces of the current worktree"});this.verbose=de.Counter("-v,--verbose",{description:"Increase level of logging verbosity up to 2 times"});this.parallel=de.Boolean("-p,--parallel",!1,{description:"Run the commands in parallel"});this.interlaced=de.Boolean("-i,--interlaced",!1,{description:"Print the output of commands in real-time instead of buffering it"});this.jobs=de.String("-j,--jobs",{description:"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`",validator:pN([js(["unlimited"]),vI(fN(),[gN(),hN(1)])])});this.topological=de.Boolean("-t,--topological",!1,{description:"Run the command after all workspaces it depends on (regular) have finished"});this.topologicalDev=de.Boolean("--topological-dev",!1,{description:"Run the command after all workspaces it depends on (regular + dev) have finished"});this.include=de.Array("--include",[],{description:"An array of glob pattern idents or paths; only matching workspaces will be traversed"});this.exclude=de.Array("--exclude",[],{description:"An array of glob pattern idents or paths; matching workspaces won't be traversed"});this.publicOnly=de.Boolean("--no-private",{description:"Avoid running the command on private workspaces"});this.since=de.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.dryRun=de.Boolean("-n,--dry-run",{description:"Print the commands that would be run, without actually running them"});this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[["workspaces","foreach"]]}static{this.usage=st.Usage({category:"Workspace-related commands",description:"run a command on all workspaces",details:"\n This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\n\n - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\n\n - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\n\n - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\n\n - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `-W,--worktree` is set, Yarn will find workspaces to run the command on by looking at the current worktree.\n\n - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\n\n - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - If `--dry-run` is set, Yarn will explain what it would do without actually doing anything.\n\n - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n The `-v,--verbose` flag can be passed up to twice: once to prefix output lines with the originating workspace's name, and again to include start/finish/timing log lines. Maximum verbosity is enabled by default in terminal environments.\n\n If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\n ",examples:[["Publish all packages","yarn workspaces foreach -A npm publish --tolerate-republish"],["Run the build script on all descendant packages","yarn workspaces foreach -A run build"],["Run the build script on current and all descendant packages in parallel, building package dependencies first","yarn workspaces foreach -Apt run build"],["Run the build script on several packages and all their dependencies, building dependencies first","yarn workspaces foreach -Rpt --from '{workspace-a,workspace-b}' run build"]]})}static{this.schema=[PI("all",Ku.Forbids,["from","recursive","since","worktree"],{missingIf:"undefined"}),dN(["all","recursive","since","worktree"],{missingIf:"undefined"})]}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!this.all&&!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=this.cli.process([this.commandName,...this.args]),u=n.path.length===1&&n.path[0]==="run"&&typeof n.scriptName<"u"?n.scriptName:null;if(n.path.length===0)throw new ot("Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script");let A=Ee=>{this.dryRun&&this.context.stdout.write(`${Ee} +`)},p=()=>{let Ee=this.from.map(g=>ww.default.matcher(g));return o.workspaces.filter(g=>{let me=G.stringifyIdent(g.anchoredLocator),we=g.relativeCwd;return Ee.some(fe=>fe(me)||fe(we))})},h=[];if(this.since?(A("Option --since is set; selecting the changed workspaces as root for workspace selection"),h=Array.from(await ra.fetchChangedWorkspaces({ref:this.since,project:o}))):this.from?(A("Option --from is set; selecting the specified workspaces"),h=[...p()]):this.worktree?(A("Option --worktree is set; selecting the current workspace"),h=[a]):this.recursive?(A("Option --recursive is set; selecting the current workspace"),h=[a]):this.all&&(A("Option --all is set; selecting all workspaces"),h=[...o.workspaces]),this.dryRun&&!this.all){for(let Ee of h)A(` +- ${Ee.relativeCwd} + ${G.prettyLocator(r,Ee.anchoredLocator)}`);h.length>0&&A("")}let E;if(this.recursive?this.since?(A("Option --recursive --since is set; recursively selecting all dependent workspaces"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependents()]).flat())):(A("Option --recursive is set; recursively selecting all transitive dependencies"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependencies()]).flat())):this.worktree?(A("Option --worktree is set; recursively selecting all nested workspaces"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceChildren()]).flat())):E=null,E!==null&&(h=[...new Set([...h,...E])],this.dryRun))for(let Ee of E)A(` +- ${Ee.relativeCwd} + ${G.prettyLocator(r,Ee.anchoredLocator)}`);let I=[],D=!1;if(u?.includes(":")){for(let Ee of o.workspaces)if(Ee.manifest.scripts.has(u)&&(D=!D,D===!1))break}for(let Ee of h){if(u&&!Ee.manifest.scripts.has(u)&&!D&&!(await hn.getWorkspaceAccessibleBinaries(Ee)).has(u)){A(`Excluding ${Ee.relativeCwd} because it doesn't have a "${u}" script`);continue}if(!(u===r.env.npm_lifecycle_event&&Ee.cwd===a.cwd)){if(this.include.length>0&&!ww.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.include)&&!ww.default.isMatch(Ee.relativeCwd,this.include)){A(`Excluding ${Ee.relativeCwd} because it doesn't match the --include filter`);continue}if(this.exclude.length>0&&(ww.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.exclude)||ww.default.isMatch(Ee.relativeCwd,this.exclude))){A(`Excluding ${Ee.relativeCwd} because it matches the --include filter`);continue}if(this.publicOnly&&Ee.manifest.private===!0){A(`Excluding ${Ee.relativeCwd} because it's a private workspace and --no-private was set`);continue}I.push(Ee)}}if(this.dryRun)return 0;let x=this.verbose??(this.context.stdout.isTTY?1/0:0),C=x>0,T=x>1,L=this.parallel?this.jobs==="unlimited"?1/0:Number(this.jobs)||Math.ceil(Xi.availableParallelism()/2):1,U=L===1?!1:this.parallel,z=U?this.interlaced:!0,te=(0,xve.default)(L),le=new Map,ce=new Set,ue=0,Ce=null,he=!1,De=await Nt.start({configuration:r,stdout:this.context.stdout,includePrefix:!1},async Ee=>{let g=async(me,{commandIndex:we})=>{if(he)return-1;!U&&T&&we>1&&Ee.reportSeparator();let fe=RDt(me,{configuration:r,label:C,commandIndex:we}),[ie,Z]=bve(Ee,{prefix:fe,interlaced:z}),[xe,Re]=bve(Ee,{prefix:fe,interlaced:z});try{T&&Ee.reportInfo(null,`${fe?`${fe} `:""}Process started`);let gt=Date.now(),q=await this.cli.run([this.commandName,...this.args],{cwd:me.cwd,stdout:ie,stderr:xe})||0;ie.end(),xe.end(),await Z,await Re;let nt=Date.now();if(T){let Ne=r.get("enableTimers")?`, completed in ${pe.pretty(r,nt-gt,pe.Type.DURATION)}`:"";Ee.reportInfo(null,`${fe?`${fe} `:""}Process exited (exit code ${q})${Ne}`)}return q===130&&(he=!0,Ce=q),q}catch(gt){throw ie.end(),xe.end(),await Z,await Re,gt}};for(let me of I)le.set(me.anchoredLocator.locatorHash,me);for(;le.size>0&&!Ee.hasErrors();){let me=[];for(let[ie,Z]of le){if(ce.has(Z.anchoredDescriptor.descriptorHash))continue;let xe=!0;if(this.topological||this.topologicalDev){let Re=this.topologicalDev?new Map([...Z.manifest.dependencies,...Z.manifest.devDependencies]):Z.manifest.dependencies;for(let gt of Re.values()){let q=o.tryWorkspaceByDescriptor(gt);if(xe=q===null||!le.has(q.anchoredLocator.locatorHash),!xe)break}}if(xe&&(ce.add(Z.anchoredDescriptor.descriptorHash),me.push(te(async()=>{let Re=await g(Z,{commandIndex:++ue});return le.delete(ie),ce.delete(Z.anchoredDescriptor.descriptorHash),Re})),!U))break}if(me.length===0){let ie=Array.from(le.values()).map(Z=>G.prettyLocator(r,Z.anchoredLocator)).join(", ");Ee.reportError(3,`Dependency cycle detected (${ie})`);return}let fe=(await Promise.all(me)).find(ie=>ie!==0);Ce===null&&(Ce=typeof fe<"u"?1:Ce),(this.topological||this.topologicalDev)&&typeof fe<"u"&&Ee.reportError(0,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return Ce!==null?Ce:De.exitCode()}};function bve(t,{prefix:e,interlaced:r}){let o=t.createStreamReporter(e),a=new qe.DefaultStream;a.pipe(o,{end:!1}),a.on("finish",()=>{o.end()});let n=new Promise(A=>{o.on("finish",()=>{A(a.active)})});if(r)return[a,n];let u=new qe.BufferStream;return u.pipe(a,{end:!1}),u.on("finish",()=>{a.end()}),[u,n]}function RDt(t,{configuration:e,commandIndex:r,label:o}){if(!o)return null;let n=`[${G.stringifyIdent(t.anchoredLocator)}]:`,u=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],A=u[r%u.length];return pe.pretty(e,n,A)}var TDt={commands:[Cw,Iw]},NDt=TDt;var lE=()=>({modules:new Map([["@yarnpkg/cli",S2],["@yarnpkg/core",P2],["@yarnpkg/fslib",AI],["@yarnpkg/libzip",V1],["@yarnpkg/parsers",EI],["@yarnpkg/shell",e2],["clipanion",QI],["semver",LDt],["typanion",Wo],["@yarnpkg/plugin-essentials",OH],["@yarnpkg/plugin-compat",jH],["@yarnpkg/plugin-constraints",a6],["@yarnpkg/plugin-dlx",l6],["@yarnpkg/plugin-exec",A6],["@yarnpkg/plugin-file",p6],["@yarnpkg/plugin-git",MH],["@yarnpkg/plugin-github",d6],["@yarnpkg/plugin-http",m6],["@yarnpkg/plugin-init",y6],["@yarnpkg/plugin-interactive-tools",mj],["@yarnpkg/plugin-link",yj],["@yarnpkg/plugin-nm",t5],["@yarnpkg/plugin-npm",$5],["@yarnpkg/plugin-npm-cli",lG],["@yarnpkg/plugin-pack",V5],["@yarnpkg/plugin-patch",gG],["@yarnpkg/plugin-pnp",jj],["@yarnpkg/plugin-pnpm",yG],["@yarnpkg/plugin-stage",DG],["@yarnpkg/plugin-typescript",PG],["@yarnpkg/plugin-version",QG],["@yarnpkg/plugin-workspace-tools",FG]]),plugins:new Set(["@yarnpkg/plugin-essentials","@yarnpkg/plugin-compat","@yarnpkg/plugin-constraints","@yarnpkg/plugin-dlx","@yarnpkg/plugin-exec","@yarnpkg/plugin-file","@yarnpkg/plugin-git","@yarnpkg/plugin-github","@yarnpkg/plugin-http","@yarnpkg/plugin-init","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-link","@yarnpkg/plugin-nm","@yarnpkg/plugin-npm","@yarnpkg/plugin-npm-cli","@yarnpkg/plugin-pack","@yarnpkg/plugin-patch","@yarnpkg/plugin-pnp","@yarnpkg/plugin-pnpm","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"])});function Fve({cwd:t,pluginConfiguration:e}){let r=new Vo({binaryLabel:"Yarn Package Manager",binaryName:"yarn",binaryVersion:nn??""});return Object.assign(r,{defaultContext:{...Vo.defaultContext,cwd:t,plugins:e,quiet:!1,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr}})}function MDt(t){if(qe.parseOptionalBoolean(process.env.YARN_IGNORE_NODE))return!0;let r=process.versions.node,o=">=18.12.0";if(Ur.satisfiesWithPrereleases(r,o))return!0;let a=new ot(`This tool requires a Node version compatible with ${o} (got ${r}). Upgrade Node, or set \`YARN_IGNORE_NODE=1\` in your environment.`);return Vo.defaultContext.stdout.write(t.error(a)),!1}async function Rve({selfPath:t,pluginConfiguration:e}){return await Je.find(Ae.toPortablePath(process.cwd()),e,{strict:!1,usePathCheck:t})}function ODt(t,e,{yarnPath:r}){if(!ae.existsSync(r))return t.error(new Error(`The "yarn-path" option has been set, but the specified location doesn't exist (${r}).`)),1;process.on("SIGINT",()=>{});let o={stdio:"inherit",env:{...process.env,YARN_IGNORE_PATH:"1"}};try{(0,kve.execFileSync)(process.execPath,[Ae.fromPortablePath(r),...e],o)}catch(a){return a.status??1}return 0}function UDt(t,e){let r=null,o=e;return e.length>=2&&e[0]==="--cwd"?(r=Ae.toPortablePath(e[1]),o=e.slice(2)):e.length>=1&&e[0].startsWith("--cwd=")?(r=Ae.toPortablePath(e[0].slice(6)),o=e.slice(1)):e[0]==="add"&&e[e.length-2]==="--cwd"&&(r=Ae.toPortablePath(e[e.length-1]),o=e.slice(0,e.length-2)),t.defaultContext.cwd=r!==null?K.resolve(r):K.cwd(),o}function _Dt(t,{configuration:e}){if(!e.get("enableTelemetry")||Qve.isCI||!process.stdout.isTTY)return;Je.telemetry=new sE(e,"puba9cdc10ec5790a2cf4969dd413a47270");let o=/^@yarnpkg\/plugin-(.*)$/;for(let a of e.plugins.keys())oE.has(a.match(o)?.[1]??"")&&Je.telemetry?.reportPluginName(a);t.binaryVersion&&Je.telemetry.reportVersion(t.binaryVersion)}function Tve(t,{configuration:e}){for(let r of e.plugins.values())for(let o of r.commands||[])t.register(o)}async function HDt(t,e,{selfPath:r,pluginConfiguration:o}){if(!MDt(t))return 1;let a=await Rve({selfPath:r,pluginConfiguration:o}),n=a.get("yarnPath"),u=a.get("ignorePath");if(n&&!u)return ODt(t,e,{yarnPath:n});delete process.env.YARN_IGNORE_PATH;let A=UDt(t,e);_Dt(t,{configuration:a}),Tve(t,{configuration:a});let p=t.process(A,t.defaultContext);return p.help||Je.telemetry?.reportCommandName(p.path.join(" ")),await t.run(p,t.defaultContext)}async function qhe({cwd:t=K.cwd(),pluginConfiguration:e=lE()}={}){let r=Fve({cwd:t,pluginConfiguration:e}),o=await Rve({pluginConfiguration:e,selfPath:null});return Tve(r,{configuration:o}),r}async function Lk(t,{cwd:e=K.cwd(),selfPath:r,pluginConfiguration:o}){let a=Fve({cwd:e,pluginConfiguration:o});function n(){Vo.defaultContext.stdout.write(`ERROR: Yarn is terminating due to an unexpected empty event loop. +Please report this issue at https://github.com/yarnpkg/berry/issues.`)}process.once("beforeExit",n);try{process.exitCode=42,process.exitCode=await HDt(a,t,{selfPath:r,pluginConfiguration:o})}catch(u){Vo.defaultContext.stdout.write(a.error(u)),process.exitCode=1}finally{process.off("beforeExit",n),await ae.rmtempPromise()}}Lk(process.argv.slice(2),{cwd:K.cwd(),selfPath:Ae.toPortablePath(Ae.resolve(process.argv[1])),pluginConfiguration:lE()});})(); +/** + @license + Copyright (c) 2015, Rebecca Turner + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + */ +/** + @license + Copyright Node.js contributors. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ +/** + @license + The MIT License (MIT) + + Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +/** + @license + Copyright Joyent, Inc. and other Node contributors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +/*! Bundled license information: + +is-number/index.js: + (*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + *) + +to-regex-range/index.js: + (*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + *) + +fill-range/index.js: + (*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + *) + +is-extglob/index.js: + (*! + * is-extglob + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + *) + +is-glob/index.js: + (*! + * is-glob + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + *) + +queue-microtask/index.js: + (*! queue-microtask. MIT License. Feross Aboukhadijeh *) + +run-parallel/index.js: + (*! run-parallel. MIT License. Feross Aboukhadijeh *) + +git-url-parse/lib/index.js: + (*! + * buildToken + * Builds OAuth token prefix (helper function) + * + * @name buildToken + * @function + * @param {GitUrl} obj The parsed Git url object. + * @return {String} token prefix + *) + +object-assign/index.js: + (* + object-assign + (c) Sindre Sorhus + @license MIT + *) + +react/cjs/react.production.min.js: + (** @license React v17.0.2 + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +scheduler/cjs/scheduler.production.min.js: + (** @license React v0.20.2 + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +react-reconciler/cjs/react-reconciler.production.min.js: + (** @license React v0.26.2 + * react-reconciler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +is-windows/index.js: + (*! + * is-windows + * + * Copyright © 2015-2018, Jon Schlinkert. + * Released under the MIT License. + *) +*/ diff --git a/src/apps/Altinn.AccessManagement/test/K6/.yarnrc.yml b/src/apps/Altinn.AccessManagement/test/K6/.yarnrc.yml new file mode 100644 index 00000000..60ff8363 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/.yarnrc.yml @@ -0,0 +1,11 @@ +enableMessageNames: false + +enableTelemetry: false + +nodeLinker: node-modules + +plugins: + - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs + spec: "@yarnpkg/plugin-interactive-tools" + +yarnPath: .yarn/releases/yarn-4.5.1.cjs diff --git a/src/apps/Altinn.AccessManagement/test/K6/README.md b/src/apps/Altinn.AccessManagement/test/K6/README.md new file mode 100644 index 00000000..ac7983bf --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/README.md @@ -0,0 +1,33 @@ +# K6 API Tests + +This project has the api tests using [k6](https://k6.io/) for platform and app apis. + +## Develop Test Scripts + +### Install dependencies + +The dependencies are for linting and formatting of the test scripts. + +```cmd + yarn --immutable # only needed first time, or when dependencies are updated +``` + +### Lint files + +```cmd + yarn run eslint:check # Check the files devialting the rules + yarn run eslint:fix # Fix the linting errors +``` + +### Format files with prettier + +```cmd + yarn run prettier:check # Check the files deviating the configuration + yarn run prettier:format # Fix and save the files based on configuration +``` + +Refer this page for more [documentation](https://docs.altinn.studio/technology/altinnstudio/development/handbook/test/k6/) on how to write new test scripts. + +## Run Tests + +Each `.js` is an independent test script and has an example command with the parameters to be sent for the test script. diff --git a/src/apps/Altinn.AccessManagement/test/K6/docker-compose.yml b/src/apps/Altinn.AccessManagement/test/K6/docker-compose.yml new file mode 100644 index 00000000..da7a7a65 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3.4' + +networks: + k6: + grafana: + +services: + grafana: + image: grafana/grafana:latest + networks: + - grafana + ports: + - "3000:3000" + environment: + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_BASIC_ENABLED=false + volumes: + - ./grafana-datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml + - ./performance-test-dashboard.json:/etc/grafana/provisioning/dashboards/performance-test-dashboard.json + - ./grafana-dashboard.yaml/:/etc/grafana/provisioning/dashboards/dashboard.yaml + + k6: + image: loadimpact/k6:0.48.0 + networks: + - k6 + ports: + - "6565:6565" + volumes: + - ./src:/src diff --git a/src/apps/Altinn.AccessManagement/test/K6/grafana-dashboard.yaml b/src/apps/Altinn.AccessManagement/test/K6/grafana-dashboard.yaml new file mode 100644 index 00000000..00e0dd80 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/grafana-dashboard.yaml @@ -0,0 +1,12 @@ + +apiVersion: 1 + +providers: +- name: 'Performance test' + orgId: 1 + folder: '' + type: file + disableDeletion: false + editable: true + options: + path: /etc/grafana/provisioning/dashboards \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/grafana-datasource.yaml b/src/apps/Altinn.AccessManagement/test/K6/grafana-datasource.yaml new file mode 100644 index 00000000..69d09503 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/grafana-datasource.yaml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: + - name: myinfluxdb + type: influxdb + access: proxy + database: k6 + url: http://influxdb:8086 + isDefault: true \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/package.json b/src/apps/Altinn.AccessManagement/test/K6/package.json new file mode 100644 index 00000000..1a1d9749 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/package.json @@ -0,0 +1,18 @@ +{ + "name": "k6-api-tests", + "version": "1.0.0", + "description": "K6 test scripts for Altinn3 APIs", + "scripts": { + "eslint:check": "eslint \"src/**\"", + "eslint:fix": "eslint \"src/**\" --fix", + "prettier:check": "prettier -c src/**/*.js", + "prettier:format": "prettier -w src/**/*.js" + }, + "devDependencies": { + "@babel/core": "7.26.0", + "@babel/eslint-parser": "7.25.9", + "eslint": "9.14.0", + "prettier": "3.3.3" + }, + "packageManager": "yarn@4.5.1" +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/performance-test-dashboard.json b/src/apps/Altinn.AccessManagement/test/K6/performance-test-dashboard.json new file mode 100644 index 00000000..6e585ea7 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/performance-test-dashboard.json @@ -0,0 +1,1617 @@ +{ + "__inputs": [ + { + "name": "DS_K6", + "label": "k6", + "description": "", + "type": "datasource", + "pluginId": "influxdb", + "pluginName": "InfluxDB" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "4.4.1" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "panel", + "id": "heatmap", + "name": "Heatmap", + "version": "" + }, + { + "type": "datasource", + "id": "influxdb", + "name": "InfluxDB", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "" + } + ], + "annotations": { + "list": [] + }, + "description": "A dashboard for visualizing results from the k6.io load testing tool, using the InfluxDB exporter", + "editable": true, + "gnetId": 2587, + "graphTooltip": 2, + "hideControls": false, + "id": null, + "links": [], + "refresh": "5s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "myinfluxdb", + "fill": 1, + "id": 1, + "interval": ">1s", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Active VUs", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "vus", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Virtual Users", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "myinfluxdb", + "fill": 1, + "id": 17, + "interval": "1s", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Requests per Second", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "http_reqs", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "sum" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Requests per Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "myinfluxdb", + "fill": 1, + "id": 7, + "interval": "1s", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "show": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Num Errors", + "color": "#BF1B00" + } + ], + "spaceLength": 10, + "span": 3, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Num Errors", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "errors", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "count" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Errors Per Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "myinfluxdb", + "fill": 1, + "id": 10, + "interval": ">1s", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "show": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Num Errors", + "color": "#BF1B00" + } + ], + "spaceLength": 10, + "span": 3, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_check", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "check" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "checks", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "sum" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Checks Per Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "", + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 11, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM $Measurement WHERE $timeFilter ", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (mean)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 14, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT max(\"value\") FROM $Measurement WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (max)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 15, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT median(\"value\") FROM $Measurement WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (med)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 16, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT min(\"value\") FROM $Measurement WHERE $timeFilter and value > 0", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (min)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 12, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT percentile(\"value\", 90) FROM $Measurement WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (p90)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "myinfluxdb", + "decimals": 2, + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "50px", + "id": 13, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 2, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT percentile(\"value\", 95) FROM $Measurement WHERE $timeFilter ", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "$Measurement (p95)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "myinfluxdb", + "description": "Grouped by 1 sec intervals", + "fill": 1, + "height": "250px", + "id": 5, + "interval": ">1s", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "max", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "/^$Measurement$/", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT max(\"value\") FROM /^$Measurement$/ WHERE $timeFilter and value > 0 GROUP BY time($__interval) fill(none)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "max" + } + ] + ], + "tags": [] + }, + { + "alias": "p95", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "/^$Measurement$/", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT percentile(\"value\", 95) FROM /^$Measurement$/ WHERE $timeFilter and value > 0 GROUP BY time($__interval) fill(none)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [ + 95 + ], + "type": "percentile" + } + ] + ], + "tags": [] + }, + { + "alias": "p90", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "/^$Measurement$/", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT percentile(\"value\", 90) FROM /^$Measurement$/ WHERE $timeFilter and value > 0 GROUP BY time($__interval) fill(none)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [ + "90" + ], + "type": "percentile" + } + ] + ], + "tags": [] + }, + { + "alias": "min", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "/^$Measurement$/", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT min(\"value\") FROM /^$Measurement$/ WHERE $timeFilter and value > 0 GROUP BY time($__interval) fill(none)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "min" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$Measurement (over time)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 2, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "rgb(0, 234, 255)", + "colorScale": "sqrt", + "colorScheme": "interpolateRdYlGn", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "datasource": "myinfluxdb", + "heatmap": {}, + "height": "250px", + "highlightCards": true, + "id": 8, + "interval": ">1s", + "links": [], + "span": 6, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "http_req_duration", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"value\" FROM $Measurement WHERE $timeFilter and value > 0", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "title": "$Measurement (over time)", + "tooltip": { + "show": true, + "showHistogram": true + }, + "tooltipDecimals": null, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "ms", + "logBase": 2, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketNumber": null, + "yBucketSize": null + } + ], + "repeat": "Measurement", + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "$Measurement", + "titleSize": "h6" + }, + { + "collapse": false, + "height": 250, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": { + "selected": true, + "tags": [], + "text": "http_req_duration + http_req_blocked", + "value": [ + "http_req_duration", + "http_req_blocked" + ] + }, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "Measurement", + "options": [ + { + "selected": false, + "text": "All", + "value": "$__all" + }, + { + "selected": true, + "text": "http_req_duration", + "value": "http_req_duration" + }, + { + "selected": true, + "text": "http_req_blocked", + "value": "http_req_blocked" + }, + { + "selected": false, + "text": "http_req_connecting", + "value": "http_req_connecting" + }, + { + "selected": false, + "text": "http_req_looking_up", + "value": "http_req_looking_up" + }, + { + "selected": false, + "text": "http_req_receiving", + "value": "http_req_receiving" + }, + { + "selected": false, + "text": "http_req_sending", + "value": "http_req_sending" + }, + { + "selected": false, + "text": "http_req_waiting", + "value": "http_req_waiting" + } + ], + "query": "http_req_duration,http_req_blocked,http_req_connecting,http_req_looking_up,http_req_receiving,http_req_sending,http_req_waiting", + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "k6 Load Testing Results", + "version": 22 +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/Helpers/TestdataHelper.js b/src/apps/Altinn.AccessManagement/test/K6/src/Helpers/TestdataHelper.js new file mode 100644 index 00000000..01bb0967 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/Helpers/TestdataHelper.js @@ -0,0 +1,132 @@ +import { check, sleep } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../errorcounter.js'; +import * as delegation from '../api/platform/authorization/delegations.js'; +import * as authorization from '../api/platform/authorization/authorization.js'; +import * as setUpData from '../setup.js'; + +let pdpInputJson = open('../data/pdpinput.json'); + +/** + * Helper function to quickly add rules for testing purposes + * @param {*} performedByUserId The userId of the person who performed the delegation + * @param {*} offeredByPartyId The partyId of the user/org giving the rule + * @param {*} coveredBy the userid/partyid of the user/org receiving the rule + * @param {*} coveredByType 'userid' for users, 'partyid' for organizations + * @param {*} taskName 'Task_1', 'EndEvent_1' + * @param {*} actionName 'read', 'write', 'sign' + * @returns the ruleid for the newly added rule + */ + export function addRulesForTest(altinnToken, performedByUserId, offeredByPartyId, coveredBy, coveredByType, taskName, actionName, appOwner, appName) { + var policyMatchKeys = { + coveredBy: 'urn:altinn:' + coveredByType, + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + + var res = delegation.addRules(altinnToken, policyMatchKeys, performedByUserId, offeredByPartyId, coveredBy, appOwner, appName, taskName, actionName); + + // Assert + var success = check(res, { + 'Add delegation rule - status is 201': (r) => r.status === 201, + }); + addErrorCount(success); + stopIterationOnFail('Add delegation rule Failed', success, res); + sleep(3); + + return res.json('0.ruleId'); +} + +/** + * Helper function to quickly add rules for testing purposes + * @param {*} delegatedByUserId The userId of the person who performed the delegation + * @param {*} offeredByPartyId The partyId of the user/org giving the rule + * @param {*} coveredBy the userid/partyid of the user/org receiving the rule + * @param {*} coveredByType 'userid' for users, 'partyid' for organizations + * @param {*} taskName 'Task_1', 'EndEvent_1' + * @param {*} actionName 'read', 'write', 'sign' + * @returns the object used to generate policy match in addMultipleRules + */ + export function generateDataForAddMultipleRules(delegatedByUserId, offeredByPartyId, coveredBy, coveredByType, taskName, actionName, appOwnerIn=appOwner, appNameIn=appName) { + var policyMatchKeys = { + coveredBy: 'urn:altinn:' + coveredByType, + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + + return { + policyMatchKeys: policyMatchKeys, + delegatedByUserId: delegatedByUserId, + offeredByPartyId: offeredByPartyId, + coveredBy: coveredBy, + appOwner: appOwnerIn, + appName: appNameIn, + altinnTask: taskName, + altinnAction: actionName + }; +} + +/** + * Helper function for quickly checking whether the PDP's decision is 'permit' or something else + * @param {*} offeredByPartyId The partyid in the Resource + * @param {*} coveredBy The AccessSubject's userid/partyid + * @param {*} taskName 'Task_1', 'EndEvent_1' + * @param {*} actionName 'read', 'write', 'sign' + * @param {*} expectedDecision 'Permit', 'NotApplicable' + */ +export function checkPDPDecision(offeredByPartyId, coveredBy, taskName, actionName, expectedDecision, showResults, appOwner, appName) { + var jsonPermitData = { + AccessSubject: ['urn:altinn:userid'], + Action: [actionName], + Resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:partyid', 'urn:altinn:task'], + }; + var res = authorization.postGetDecision(pdpInputJson, jsonPermitData, appOwner, appName, coveredBy, offeredByPartyId, taskName); + + // Assert + var success = check(res, { + 'Get PDP Decision for delegated rule Status is 200': (r) => r.status === 200, + 'Get PDP Decision for delegated rule - decision is permit': (r) => r.json('response.0.decision') === expectedDecision, + }); + + if(!success && showResults) { + console.log('Expected decision to be ' + expectedDecision + ', but it was not.'); + } + + // console.log('Decision was ' + expectedDecision + ', as expected.'); + addErrorCount(success); + return success; +} + +/** + * Helper function that deletes all rules as a cleanup step before/after a test + * @param {*} performedByUserId The userId of the user who does the deleting + * @param {*} offeredByPartyId The partyid of the organization the rule is delegated from + * @param {*} coveredBy The userid/partyid of the user/org the rule is delegated to + * @param {*} coveredByType 'userid' for user, 'partyid' for organization + * @param {*} ignoreErrors If true, the entire check/assert part is skipped + */ +export function deleteAllRules(altinnToken, performedByUserId, offeredByPartyId, coveredBy, coveredByType, appOwner, appName) { + var policyMatchKeys = { + coveredBy: 'urn:altinn:' + coveredByType, + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var resources = [{ appOwner: appOwner, appName: appName }]; + + var res = delegation.getRules(altinnToken, policyMatchKeys, offeredByPartyId, coveredBy, resources, null, null); + if (res.body == '[]') { + return; + } + + res = delegation.deletePolicy(altinnToken, policyMatchKeys, performedByUserId, offeredByPartyId, coveredBy, appOwner, appName, null); + var success = check(res, { + 'Delete delegated policy with all rules - status is 200': (r) => r.status === 200, + }); + addErrorCount(success); + sleep(3); + +} + +export function minimumSBLVersion(major, minor) { + var altinnBuildVersion = setUpData.getSBLBuildVersion(); + if (altinnBuildVersion.split('.')[0] > major || altinnBuildVersion.split('.')[0] == major && altinnBuildVersion.split('.')[1] >= minor) { + return true; + } + return false; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/maskinporten/maskinporten.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/maskinporten/maskinporten.js new file mode 100644 index 00000000..9e31c3fc --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/maskinporten/maskinporten.js @@ -0,0 +1,157 @@ +import http from 'k6/http'; +import * as config from '../../../config.js'; +import * as header from '../../../buildrequestheaders.js'; + +/** + * GET call to get maskinportenschemas that have been offered by the current party + * @param {*} altinnToken personal token for offering party's DAGL + * @param {*} partyid the offering party's partyid or organization number + */ +export function getMaskinportenSchemaOffered(altinnToken, partyid) { + var endpoint = config.buildMaskinPorteSchemaUrls(partyid, 'offered'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + return http.get(endpoint, params); +} + +/** + * GET call to get maskinportenschemas that have been received by the current party + * @param {*} altinnToken personal token for the receiving party's DAGL + * @param {*} partyid the receiving party's partyid or organization number + */ +export function getMaskinportenSchemaReceived(altinnToken, partyid) { + var endpoint = config.buildMaskinPorteSchemaUrls(partyid, 'received'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + return http.get(endpoint, params); +} + +/** + * POST call to revoke maskinportenschemas that have been offered by the current party + * @param {*} altinnToken personal token for DAGL of offeredby + * @param {*} offeredByPartyId the offering party's partyid + * @param {*} to the receiving organization's party id or organization number + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function revokeOfferedMaskinportenSchema(altinnToken, offeredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(offeredByPartyId, 'revokeoffered'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to revoke maskinportenschemas that have been received by the current party + * @param {*} altinnToken personal token for DAGL of receiver + * @param {*} coveredByPartyId the receiving party's partyid + * @param {*} resourceid the id of the resource to delegate + * @param {*} fromAttributeId the attribute id for the offerer of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} fromAttributeValue the offerer's partyid or organization number + */ +export function revokeReceivedMaskinportenSchema(altinnToken, coveredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(coveredByPartyId, 'revokereceived'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, null, null, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1); + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to delegate a maskinportenschema where the offeredby's partyid is in the path + * @param {*} altinnToken personal token for DAGL + * @param {*} offeredByPartyId the offeredby's party id + * @param {*} resourceid the id of the resource to delegate + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function postMaskinportenSchema(altinnToken, offeredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(offeredByPartyId, 'maskinportenschema'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to delegate a maskinportenschema where the offeredby's organization number is in the header + * @param {*} altinnToken personal token for DAGL + * @param {*} offeredByOrganizationNumber the organization number for the offeredby party + * @param {*} resourceid the id of the resource to delegate + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function postMaskinportenSchemaOrgNoInHeader(altinnToken, offeredByOrganizationNumber, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls('organization', 'maskinportenschema'); + var params = header.buildHeaderWithRuntimeOrgNumberAndJson(altinnToken, offeredByOrganizationNumber); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to delegation check on a maskinportenschema where the offeredby's partyid is in the path + * @param {*} altinnToken personal token for DAGL + * @param {*} offeredByPartyId the offeredby's party id + * @param {*} resourceid the id of the resource to delegate + */ +export function postDelegationCheck(altinnToken, offeredByPartyId, resourceid) { + var endpoint = config.buildMaskinPorteSchemaUrls(offeredByPartyId, 'delegationCheck'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1); + return http.post(endpoint, bodystring, params); +} + +/** + * function to build the request body for maskinportenschema + * @param {*} resourceid the resourceid for the schema + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + * @param {*} fromAttributeId the attribute id for the sender of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} fromAttributeValue the sender's partyid or organization number + * @returns request body json object + */ +function makeRequestBody(resourceid, toAttributeId = null, toAttributeValue = null, fromAttributeId = null, fromAttributeValue = null) { + var rights = { + resource: [{ + id: 'urn:altinn:resource', + value: resourceid + }], + } + var requestBody = {}; + + if (toAttributeId !== null && toAttributeValue !== null) { + requestBody = { + to: [], + rights: [] + }; + + requestBody.to.push({id: toAttributeId, value: toAttributeValue}); + requestBody.rights.push(rights); + } + + else if (fromAttributeId !== null && fromAttributeValue !== null ) { + requestBody = { + from: [], + rights: [] + }; + requestBody.from.push({id: fromAttributeId, value: fromAttributeValue}); + requestBody.rights.push(rights); + } + + else { + requestBody = rights; + } + + return requestBody; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/rights-delegations/userdelegationcheck.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/rights-delegations/userdelegationcheck.js new file mode 100644 index 00000000..b066255b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/access-management/rights-delegations/userdelegationcheck.js @@ -0,0 +1,78 @@ +import http from 'k6/http'; +import * as config from '../../../config.js'; +import * as header from '../../../buildrequestheaders.js'; + +export function resourceUserDelegationCheck(altinnToken, offeredByPartyId, resourceid) { + var endpoint = config.buildRightsEndpointUrls(offeredByPartyId, 'delegationcheck'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeResourceRequestBody(resourceid)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +function makeResourceRequestBody(resourceid) { + var requestBody = { + resource: [{ + id: 'urn:altinn:resource', + value: resourceid + }], + }; + + return requestBody; +} + +export function appUserDelegationCheck(altinnToken, offeredByPartyId, org, app) { + var endpoint = config.buildRightsEndpointUrls(offeredByPartyId, 'delegationcheck'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeAppRequestBody(org, app)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +function makeAppRequestBody(org, app) { + var requestBody = { + resource: [{ + id: 'urn:altinn:org', + value: org + }, + { + id: 'urn:altinn:app', + value: app + } + ], + }; + + return requestBody; +} + +export function altinn2ServiceUserDelegationCheck(altinnToken, offeredByPartyId, serviceCode, serviceEditionCode) { + var endpoint = config.buildRightsEndpointUrls(offeredByPartyId, 'delegationcheck'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeAltinn2ServiceRequestBody(serviceCode, serviceEditionCode)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); + console.log('Altinn2service body') + console.log(bodystring) +} + +function makeAltinn2ServiceRequestBody(serviceCode, serviceEditionCode) { + var requestBody = { + resource: [{ + id: 'urn:altinn:servicecode', + value: serviceCode + }, + { + id: 'urn:altinn:serviceeditioncode', + value: serviceEditionCode + } + ], + }; + + return requestBody; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/altinn-testtools/token-generator.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/altinn-testtools/token-generator.js new file mode 100644 index 00000000..dc672d2b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/altinn-testtools/token-generator.js @@ -0,0 +1,40 @@ +import http from 'k6/http'; +import { check } from 'k6'; +import encoding from 'k6/encoding'; +import * as config from '../../config.js'; +import * as support from '../../support.js'; +import { stopIterationOnFail } from '../../errorcounter.js'; + +/** + * only for test environments - api call to get enterprise or personal token with requested scopes and other params + * @param {string} tokenFor enterprise or personal + * @param {string} userName user name for basic authentication + * @param {string} userPwd password for basic authentication + * @param {JSON} queryParams for enterprise: { env: 'at22', scopes: 'altinn:serviceowner/instances.read', org: 'ttd', orgNo: '991825827', } + * for personal: { env: 'at22', scopes: 'altinn:instances.read', userId: 123, partyId: 123, authLvl: 3, pid: '11 digit ssn', } + * @returns jwt token for enterprise or person with supplied params + */ +export function generateToken(tokenFor, userName, userPwd, queryParams) { + const credentials = `${userName}:${userPwd}`; + const encodedCredentials = encoding.b64encode(credentials); + var endpoint; + + if (tokenFor === 'enterprise') endpoint = config.tokenGenerator.getEnterpriseToken; + if (tokenFor === 'personal') endpoint = config.tokenGenerator.getPersonalToken; + if (tokenFor === 'platform') endpoint = config.tokenGenerator.getPlatformToken; + endpoint += support.buildQueryParametersForEndpoint(queryParams); + + var params = { + headers: { + Authorization: `Basic ${encodedCredentials}`, + }, + }; + + var token = http.get(endpoint, params); + check(token, { + 'Token generation is success': (r) => r.status === 200, + }); + if (token.status != 200) stopIterationOnFail('token gen failed', false, token); + token = token.body; + return token; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authentication.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authentication.js new file mode 100644 index 00000000..b950f3a1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authentication.js @@ -0,0 +1,14 @@ +import http from 'k6/http'; +import * as config from '../../config.js'; +import * as header from '../../buildrequestheaders.js'; +import { stopIterationOnFail } from '../../errorcounter.js'; + +//Request to convert a maskinporten token and returns altinnstudioruntime token for en appOwner +export function convertMaskinPortenToken(maskinportentoken, isTest) { + if (!maskinportentoken) stopIterationOnFail('maskinporten token is undefined', false, null); + var endpoint = config.platformAuthentication['maskinporten'] + '?test=' + isTest; + var params = header.buildHeaderWithRuntime(maskinportentoken); + var token = http.get(endpoint, params); + token = token.body; + return token; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/authorization.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/authorization.js new file mode 100644 index 00000000..b331076c --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/authorization.js @@ -0,0 +1,104 @@ +import http from 'k6/http'; +import * as config from '../../../config.js'; +import * as header from '../../../buildrequestheaders.js'; + +/**Request to get parties that an user can represent and return response */ +export function getParties(altinnToken, userId) { + var endpoint = config.platformAuthorization['parties'] + '?userId=' + userId; + var params = header.buildHeaderWithRuntime(altinnToken, 'platform'); + return http.get(endpoint, params); +} + +/**Request to get roles of an user */ +export function getRoles(altinnToken, userId, partyId) { + var endpoint = config.platformAuthorization['roles'] + '?coveredbyuserid=' + userId + '&offeredbypartyid=' + partyId; + var params = header.buildHeaderWithRuntime(altinnToken, 'platform'); + return http.get(endpoint, params); +} + +/**Request to upload app policy to storage */ +export function postPolicy(data, appOwner, appName, altinnStudioRuntimeCookie) { + var endpoint = config.platformAuthorization['policy'] + '?org=' + appOwner + '&app=' + appName; + var params = header.buildHeaderWithRuntime(altinnStudioRuntimeCookie, 'platform'); + return http.post(endpoint, data, params); +} + +/** + * function to get decision from PDP and return response + * @param {*} pdpInputJson Template + * @param {*} jsonPermitData keys to be populated in decision + * @param {*} appOwner + * @param {*} testappName + * @param {*} coveredBy the userId for the accessSubject (coveredby) + * @param {*} offeredByPartyId partyid in the Resource (offeredby) + * @param {*} altinnTask Task_1, EndEvent_1 + * @returns json object of a PDP decision + */ +export function postGetDecision(pdpInputJson, jsonPermitData, appOwner, testappName, userId, partyId, altinnTask) { + var endpoint = config.platformAuthorization['decision']; + var pdpJson = buildPdpJson(pdpInputJson, jsonPermitData, appOwner, testappName, userId, partyId, altinnTask); + var requestBody = JSON.stringify(pdpJson); + var params = header.buildHeaderWithJson('platform'); + return http.post(endpoint, requestBody, params); +} + +//Function to build a json for authz: decision request and returns a json object +function buildPdpJson(pdpInputJson, jsonPermitData, appOwner, testappName, userId, partyId, altinnTask) { + var action = jsonPermitData['Action']; + var accessSubject = jsonPermitData['AccessSubject']; + var resource = jsonPermitData['Resource']; + pdpInputJson = JSON.parse(pdpInputJson); + + //Loop through action and add to the json input template under Action + for (var i = 0; i < action.length; i++) { + var emptyObject = {}; + pdpInputJson.Request.Action[0].Attribute.push(emptyObject); + pdpInputJson.Request.Action[0].Attribute[i].AttributeId = 'urn:oasis:names:tc:xacml:1.0:action:action-id'; + pdpInputJson.Request.Action[0].Attribute[i].Value = action[i]; + pdpInputJson.Request.Action[0].Attribute[i].DataType = 'http://www.w3.org/2001/XMLSchema#string'; + } + + //Loop through access Subject and add to the json input template under AccessSubject + for (var i = 0; i < accessSubject.length; i++) { + var value = ''; + var emptyObject = {}; + pdpInputJson.Request.AccessSubject[0].Attribute.push(emptyObject); + switch (accessSubject[i]) { + case 'urn:altinn:org': + value = appOwner; + break; + case 'urn:altinn:userid': + value = userId; + break; + } + pdpInputJson.Request.AccessSubject[0].Attribute[i].AttributeId = accessSubject[i]; + pdpInputJson.Request.AccessSubject[0].Attribute[i].Value = value; + } + + //Loop through Resource array and add to the json input template under resources + for (var i = 0; i < resource.length; i++) { + var value = ''; + var emptyObject = {}; + pdpInputJson.Request.Resource[0].Attribute.push(emptyObject); + switch (resource[i]) { + case 'urn:altinn:org': + value = appOwner; + break; + case 'urn:altinn:app': + value = testappName; + break; + case 'urn:altinn:partyid': + value = partyId; + break; + case 'urn:altinn:task': + value = altinnTask; + break; + case 'urn:altinn:appresource': + value = 'events'; + break; + } + pdpInputJson.Request.Resource[0].Attribute[i].AttributeId = resource[i]; + pdpInputJson.Request.Resource[0].Attribute[i].Value = value; + } + return pdpInputJson; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/delegations.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/delegations.js new file mode 100644 index 00000000..8e80ee07 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/delegations.js @@ -0,0 +1,231 @@ +import http from 'k6/http'; +import * as config from '../../../config.js'; +import * as header from '../../../buildrequestheaders.js'; + +/** + * Retrieve policy of an app in json format + * @param {*} altinnToken authorization token + * @param {Array} resources [{ appOwner: ttd, appName: apps-test }] + * @returns return response of GET request + */ +export function getPolicies(resources) { + var endpoint = config.platformAuthorization.getPolicies; + var params = header.buildHeaderWithJson('platform'); + var body = []; + resources.forEach((resource) => { + var appOwner = resource.appOwner ? resource.appOwner : null; + var appName = resource.appName ? resource.appName : null; + body.push(buildResourcesArray(['urn:altinn:app', 'urn:altinn:org'], appOwner, appName, null)); + }); + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * POST api call to add a rule that delagates access to an user + * @param {*} altinnToken token for authorizing the request + * @param {*} policyMatchKeys keys to be populated in the request + * @param {*} delegatedByUserId user id of the user who delegates the rule + * @param {*} offeredByPartyId party id of the user who offers the rule + * @param {*} coveredById user id or party id of whom that receives the rule + * @param {*} appOwner + * @param {*} appName + * @param {*} altinnTask Task_1, EndEvent_1 + * @param {*} altinnAction read,write,sign + * @returns response of the POST request + */ +export function addRules(altinnToken, policyMatchKeys, delegatedByUserId, offeredByPartyId, coveredById, appOwner, appName, altinnTask, altinnAction) { + var endpoint = config.platformAuthorization.addRules; + var params = header.buildHeaderWithRuntimeAndJson(altinnToken, 'platform'); + var body = []; + body.push(generatePolicyMatch(policyMatchKeys, delegatedByUserId, offeredByPartyId, coveredById, appOwner, appName, altinnTask, altinnAction)); + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * POST api call to add a rule that delagates access to an user + * @param {*} altinnToken token for authorizing the request + * @param {*} rulesList list of rules to add to the request + * @returns response of the POST request + */ + export function addMultipleRules(altinnToken, rulesList) { + var endpoint = config.platformAuthorization.addRules; + var params = header.buildHeaderWithRuntimeAndJson(altinnToken, 'platform'); + var body = []; + rulesList.forEach(r => { + body.push(generatePolicyMatch(r.policyMatchKeys, r.delegatedByUserId, r.offeredByPartyId, r.coveredBy, r.appOwner, r.appName, r.altinnTask, r.altinnAction)); + }); + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * POST call to get rules matching a criteria + * @param {*} altinnToken token for authorizing the request + * @param {*} policyMatchKeys keys to be populated in the request + * @param {*} offeredByPartyId party id of the user who offers the rule + * @param {*} coveredById user id or party id of whom that receives the rule + * @param {Array} resources [{ appOwner: ttd, appName: apps-test }] + * @param {*} parentPartyId parent party id from whom rules should be inherited + * @param {Array} keyRolePartyIds [123,124] + * @returns response of the POST request + */ +export function getRules(altinnToken, policyMatchKeys, offeredByPartyId, coveredById, resources, parentPartyId, keyRolePartyIds) { + var endpoint = config.platformAuthorization.getRules; + var params = header.buildHeaderWithRuntimeAndJson(altinnToken, 'platform'); + + var body = { coveredBy: [], resources: [] }; + + if (offeredByPartyId) body.offeredByPartyId = offeredByPartyId; + + if (parentPartyId) body.parentPartyId = parentPartyId; + + var coveredBy = policyMatchKeys['coveredBy']; + if (coveredById && coveredBy) { + body.coveredBy.push({}); + body.coveredBy[0].id = coveredBy; + body.coveredBy[0].value = coveredById.toString(); + } + + resources.forEach((resource) => { + var appOwner = resource.appOwner ? resource.appOwner : null; + var appName = resource.appName ? resource.appName : null; + var altinnTask = resource.altinnTask ? resource.altinnTask : null; + body.resources.push(buildResourcesArray(policyMatchKeys['resource'], appOwner, appName, altinnTask)); + }); + + if (keyRolePartyIds) { + body.keyRolePartyIds = keyRolePartyIds; + } else { + body.keyRolePartyIds = []; + } + + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * Post call to delete a delegated rule based on rule id + * @param {*} altinnToken token for authorizing the request + * @param {*} policyMatchKeys keys to be populated in the request + * @param {Array} ruleIds an array of guids + * @param {*} deletedByUserId user who deletes the rule + * @param {*} offeredByPartyId party id of the user who offers the rule + * @param {*} coveredById user id or party id of whom that receives the rule + * @param {*} appOwner + * @param {*} appName + * @param {*} altinnTask Task_1, EndEvent_1 + * @param {*} altinnAction read,write,sign + * @returns response of the POST request + */ +export function deleteRules( + altinnToken, + policyMatchKeys, + ruleIds, + deletedByUserId, + offeredByPartyId, + coveredById, + appOwner, + appName, + altinnTask, + altinnAction, +) { + var endpoint = config.platformAuthorization.deleteRules; + var params = header.buildHeaderWithRuntimeAndJson(altinnToken, 'platform'); + var body = [{}]; + body[0].policyMatch = generatePolicyMatch(policyMatchKeys, null, offeredByPartyId, coveredById, appOwner, appName, altinnTask, altinnAction); + body[0].ruleIds = ruleIds; + body[0].deletedByUserId = deletedByUserId; + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * Post call to delete the complete policy wit all rules + * @param {*} altinnToken token for authorizing the request + * @param {*} policyMatchKeys keys to be populated in the request + * @param {*} deletedByUserId user who deletes the policy + * @param {*} offeredByPartyId party id of the user who offers the rule + * @param {*} coveredById user id or party id of whom that receives the rule + * @param {*} appOwner + * @param {*} appName + * @param {*} altinnTask Task_1, EndEvent_1 + * @returns response of the POST request + */ +export function deletePolicy(altinnToken, policyMatchKeys, deletedByUserId, offeredByPartyId, coveredById, appOwner, appName, altinnTask) { + var endpoint = config.platformAuthorization.deletePolicy; + var params = header.buildHeaderWithRuntimeAndJson(altinnToken, 'platform'); + var body = [{}]; + body[0].policyMatch = generatePolicyMatch(policyMatchKeys, null, offeredByPartyId, coveredById, appOwner, appName, altinnTask, null); + body[0].deletedByUserId = deletedByUserId; + return http.post(endpoint, JSON.stringify(body), params); +} + +/** + * function to build a policy match with action, user and resource details + * @param {*} policyMatch Template + * @param {*} policyMatchKeys keys to be populated in policy match + * @param {*} delegatedByUserId user id of the user who delegates the rule + * @param {*} offeredByPartyId party id of the user who offers the rule + * @param {*} coveredById user id or party id of whom that receives the rule + * @param {*} appOwner + * @param {*} appName + * @param {*} altinnTask Task_1, EndEvent_1 + * @param {*} altinnAction read,write,sign + * @returns json object of a completed policy match + */ +function generatePolicyMatch(policyMatchKeys, delegatedByUserId, offeredByPartyId, coveredById, appOwner, appName, altinnTask, altinnAction) { + var policyMatch = { + coveredBy: [], + }; + var coveredBy = policyMatchKeys['coveredBy']; + var resourceKeys = policyMatchKeys['resource']; + + if (coveredById && coveredBy) { + policyMatch.coveredBy.push({}); + policyMatch.coveredBy[0].id = coveredBy; + policyMatch.coveredBy[0].value = coveredById.toString(); + } + + if (altinnAction) { + policyMatch.action = {}; + policyMatch.action.id = 'urn:oasis:names:tc:xacml:1.0:action:action-id'; + policyMatch.action.value = altinnAction; + } + + if (delegatedByUserId) policyMatch.delegatedByUserId = delegatedByUserId; + if (offeredByPartyId) policyMatch.offeredByPartyId = offeredByPartyId; + + policyMatch.resource = buildResourcesArray(resourceKeys, appOwner, appName, altinnTask); + + return policyMatch; +} + +/** + * build an array with resource key and value + * @param {*} resourceKeys ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:partyid', 'urn:altinn:task'], + * @param {*} appOwner + * @param {*} appName + * @param {*} altinnTask + * @returns an array of resource + */ +function buildResourcesArray(resourceKeys, appOwner, appName, altinnTask) { + var resource = []; + for (var i = 0; i < resourceKeys.length; i++) { + var value = ''; + resource.push({}); + switch (resourceKeys[i]) { + case 'urn:altinn:org': + value = appOwner; + break; + case 'urn:altinn:app': + value = appName; + break; + case 'urn:altinn:task': + value = altinnTask; + break; + case 'urn:altinn:appresource': + value = 'events'; + break; + } + resource[i].id = resourceKeys[i]; + resource[i].value = value; + } + return resource; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/maskinporten.js b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/maskinporten.js new file mode 100644 index 00000000..22b1a188 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/api/platform/authorization/maskinporten.js @@ -0,0 +1,135 @@ +import http from 'k6/http'; +import * as config from '../../../config.js'; +import * as header from '../../../buildrequestheaders.js'; + +/** + * GET call to get maskinportenschemas that have been offered by the current party + * @param {*} altinnToken personal token for offering party's DAGL + * @param {*} partyid the offering party's partyid or organization number + */ +export function getMaskinportenSchemaOffered(altinnToken, partyid) { + var endpoint = config.buildMaskinPorteSchemaUrls(partyid, 'offered'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + return http.get(endpoint, params); +} + +/** + * GET call to get maskinportenschemas that have been received by the current party + * @param {*} altinnToken personal token for the receiving party's DAGL + * @param {*} partyid the receiving party's partyid or organization number + */ +export function getMaskinportenSchemaReceived(altinnToken, partyid) { + var endpoint = config.buildMaskinPorteSchemaUrls(partyid, 'received'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + return http.get(endpoint, params); +} + +/** + * POST call to revoke maskinportenschemas that have been offered by the current party + * @param {*} altinnToken personal token for DAGL of offeredby + * @param {*} offeredByPartyId the offering party's partyid + * @param {*} to the receiving organization's party id or organization number + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function revokeOfferedMaskinportenSchema(altinnToken, offeredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(offeredByPartyId, 'revokeoffered'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to revoke maskinportenschemas that have been received by the current party + * @param {*} altinnToken personal token for DAGL of receiver + * @param {*} coveredByPartyId the receiving party's partyid + * @param {*} resourceid the id of the resource to delegate + * @param {*} fromAttributeId the attribute id for the offerer of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} fromAttributeValue the offerer's partyid or organization number + */ +export function revokeReceivedMaskinportenSchema(altinnToken, coveredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(coveredByPartyId, 'revokereceived'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, null, null, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1); + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to delegate a maskinportenschema where the offeredby's partyid is in the path + * @param {*} altinnToken personal token for DAGL + * @param {*} offeredByPartyId the offeredby's party id + * @param {*} resourceid the id of the resource to delegate + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function postMaskinportenSchema(altinnToken, offeredByPartyId, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls(offeredByPartyId, 'maskinportenschema'); + var params = header.buildHeaderWithRuntimeAndJson(altinnToken); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * POST call to delegate a maskinportenschema where the offeredby's organization number is in the header + * @param {*} altinnToken personal token for DAGL + * @param {*} offeredByOrganizationNumber the organization number for the offeredby party + * @param {*} resourceid the id of the resource to delegate + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + */ +export function postMaskinportenSchemaOrgNoInHeader(altinnToken, offeredByOrganizationNumber, resourceid, attributeId, attributeValue) { + var endpoint = config.buildMaskinPorteSchemaUrls('organization', 'maskinportenschema'); + var params = header.buildHeaderWithRuntimeOrgNumberAndJson(altinnToken, offeredByOrganizationNumber); + var body = []; + body.push(makeRequestBody(resourceid, attributeId, attributeValue)); + var bodystring = JSON.stringify(body); + bodystring = bodystring.substring(1, bodystring.length-1) + return http.post(endpoint, bodystring, params); +} + +/** + * function to build the request body for maskinportenschema + * @param {*} resourceid the resourceid for the schema + * @param {*} toAttributeId the attribute id for the receiver of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} toAttributeValue the receiver's partyid or organization number + * @param {*} fromAttributeId the attribute id for the sender of the schema. 'urn:altinn:partyid' or 'urn:altinn:organizationnumber' + * @param {*} fromAttributeValue the sender's partyid or organization number + * @returns request body json object + */ +function makeRequestBody(resourceid, toAttributeId, toAttributeValue, fromAttributeId, fromAttributeValue) { + var rights = { + resource: [{ + id: 'urn:altinn:resource', + value: resourceid + }], + } + var requestBody = {}; + + if (toAttributeId != null && toAttributeValue != null) { + requestBody = { + to: [], + rights: [] + }; + requestBody.to.push({id: toAttributeId, value: toAttributeValue}); + } + + else { + requestBody = { + from: [], + rights: [] + }; + requestBody.from.push({id: fromAttributeId, value: fromAttributeValue}); + } + + requestBody.rights.push(rights); + return requestBody; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/availability.js b/src/apps/Altinn.AccessManagement/test/K6/src/availability.js new file mode 100644 index 00000000..ab91f160 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/availability.js @@ -0,0 +1,15 @@ +/** + * This script is to check if the infoportal of altinn has the downtime information + * and print up or down to the console. + */ +import { parseHTML } from 'k6/html'; +import http from 'k6/http'; +import { baseUrl } from './config.js'; + +export default function () { + const res = http.get('https://' + baseUrl); + const doc = parseHTML(res.body); + const availability = doc.find('body').find('h1').text(); + if (availability.includes('Altinn is unavailable at the moment')) console.log('down'); + else console.log('up'); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/buildrequestheaders.js b/src/apps/Altinn.AccessManagement/test/K6/src/buildrequestheaders.js new file mode 100644 index 00000000..45090bb0 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/buildrequestheaders.js @@ -0,0 +1,171 @@ +const appsAccessSubscriptionKey = __ENV.appsaccesskey; +const sblAccessSubscriptionKey = __ENV.sblaccesskey; + +//Function to determine the headers for a POST/PUT data based on dataType +export function buildHeadersForData(isBinaryAttachment, binaryAttachmentType, altinnStudioRuntimeCookie, api) { + var params = {}; + if (isBinaryAttachment) { + params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': `${findContentType(binaryAttachmentType)}`, + 'Content-Disposition': `attachment; filename=test.${binaryAttachmentType}`, + }, + }; + } else { + params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': 'application/xml', + }, + }; + } + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnStudioRuntimeCookie and returns a json object +export function buildHeaderWithRuntime(altinnStudioRuntimeCookie, api) { + var params = { + headers: { Authorization: 'Bearer ' + altinnStudioRuntimeCookie }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnStudioRuntimeCookie for storage/sbl api endpoints and returns a json object +export function buildHeaderWithRuntimeForSbl(altinnStudioRuntimeCookie, api) { + var params = { + headers: { Authorization: 'Bearer ' + altinnStudioRuntimeCookie }, + }; + params = addSubscriptionKey(params, sblAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnStudioRuntimeCookie for storage/sbl api endpoints and returns a json object +export function buildHeaderWithRuntimeAndJsonForSbl(altinnStudioRuntimeCookie, api) { + var params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': 'application/json', + }, + }; + params = addSubscriptionKey(params, sblAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnStudioRuntimeCookie and JSON content-type and returns a json object +export function buildHeaderWithRuntimeAndJson(altinnStudioRuntimeCookie, api) { + var params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': 'application/json', + }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnStudioRuntimeCookie, JSON content-type, and offeredby's org number and returns a json object +export function buildHeaderWithRuntimeOrgNumberAndJson(altinnStudioRuntimeCookie, organizationNumber) { + var params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': 'application/json', + 'Altinn-Party-OrganizationNumber': organizationNumber, + }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey); + return params; +} + +//Function to build headers with .aspxauth cookie +export function buildHeaderWithAspxAuth(aspxauthCookie, api) { + var params = { + cookies: { '.ASPXAUTH': aspxauthCookie }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with .aspxauth cookie +export function buildHeaderWithJson(api) { + var params = { + headers: { + 'Content-Type': 'application/json', + }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build headers with altinnstudioruntime as cookie and returns the response +export function buildHeaderWithRuntimeAsCookie(altinnStudioRuntimeCookie, api) { + var params = { + cookies: { + AltinnStudioRuntime: altinnStudioRuntimeCookie, + }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to build a request header only with subscription key +export function buildHeaderWithSubsKey(api) { + var params = {}; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +/** + * + * @param {*} altinnStudioRuntimeCookie Token to send in header as bearer token + * @param {String} api platform or app + * @returns {JSON} a JSON object with the header values for Authorization and content-type: multipart/formdata + */ +export function buildHeaderWithRuntimeForMultipart(altinnStudioRuntimeCookie, api) { + var params = { + headers: { + Authorization: 'Bearer ' + altinnStudioRuntimeCookie, + 'Content-Type': 'multipart/form-data; boundary="abcdefg"', + }, + }; + params = addSubscriptionKey(params, appsAccessSubscriptionKey, api); + return params; +} + +//Function to add subscription key to the header when sent as env variable from command line +//and endpoint is a platform endpoint +export function addSubscriptionKey(params, subscriptionKey, api) { + if (subscriptionKey != null && api == 'platform') { + if (params['headers'] == null) { + params['headers'] = {}; + } + params.headers['Ocp-Apim-Subscription-Key'] = subscriptionKey; + } + return params; +} + +/** + * Find the content type for a given type + * @param {string} type xml, pdf, txt + * @returns content type + */ +function findContentType(type) { + var contentType; + switch (type) { + case 'xml': + contentType = 'text/xml'; + break; + case 'pdf': + contentType = 'application/pdf'; + break; + case 'txt': + contentType = 'text/plain'; + break; + default: + contentType = 'application/octet-stream'; + break; + } + return contentType; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/config.js b/src/apps/Altinn.AccessManagement/test/K6/src/config.js new file mode 100644 index 00000000..23319f41 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/config.js @@ -0,0 +1,301 @@ +// This file inhols baseURLs and endpoints for the APIs +export var baseUrls = { + at21: 'at21.altinn.cloud', + at22: 'at22.altinn.cloud', + at23: 'at23.altinn.cloud', + at24: 'at24.altinn.cloud', + tt02: 'tt02.altinn.no', + yt01: 'yt01.altinn.cloud', + prod: 'altinn.no', +}; + +//Get values from environment +const environment = __ENV.env.toLowerCase(); +export let baseUrl = baseUrls[environment]; + +//Altinn API +export var authentication = { + authenticationWithPassword: 'https://' + baseUrl + '/api/authentication/authenticatewithpassword', + authenticationYt01: 'https://yt01.ai.basefarm.net/api/authentication/authenticatewithpassword', +}; + +//Platform APIs +//Authentication +export var platformAuthentication = { + authentication: 'https://platform.' + baseUrl + '/authentication/api/v1/authentication', + refresh: 'https://platform.' + baseUrl + '/authentication/api/v1/refresh', + maskinporten: 'https://platform.' + baseUrl + '/authentication/api/v1/exchange/maskinporten', + idporten: 'https://platform.' + baseUrl + '/authentication/api/v1/exchange/id-porten', +}; + +//Profile +export var platformProfile = { + users: 'https://platform.' + baseUrl + '/profile/api/v1/users/', +}; + +//Register +export var platformRegister = { + organizations: 'https://platform.' + baseUrl + '/register/api/v1/organizations/', + parties: 'https://platform.' + baseUrl + '/register/api/v1/parties/', + persons: 'https://platform.' + baseUrl + '/register/api/v1/persons', + lookup: 'https://platform.' + baseUrl + '/register/api/v1/parties/lookup', + persons: 'https://platform.' + baseUrl + '/register/api/v1/parties/lookupobject', +}; + +//Authorization +export var platformAuthorization = { + decision: `https://platform.${baseUrl}/authorization/api/v1/decision`, + parties: `https://platform.${baseUrl}/authorization/api/v1/parties`, + policy: `https://platform.${baseUrl}/authorization/api/v1/policies`, + roles: `https://platform.${baseUrl}/authorization/api/v1/roles`, + getPolicies: `https://platform.${baseUrl}/authorization/api/v1/policies/GetPolicies`, + addRules: `https://platform.${baseUrl}/authorization/api/v1/delegations/AddRules`, + getRules: `https://platform.${baseUrl}/authorization/api/v1/delegations/GetRules`, + deleteRules: `https://platform.${baseUrl}/authorization/api/v1/delegations/DeleteRules`, + deletePolicy: `https://platform.${baseUrl}/authorization/api/v1/delegations/DeletePolicy`, + maskinPortenSchemaOffered: `https://platform.${baseUrl}/authorization/api/v1/delegations/AddRules`, + maskinPortenSchemaReceived: `https://platform.${baseUrl}/authorization/api/v1/delegations/AddRules`, +}; + +//PDF +export var platformPdf = { + generate: 'https://platform.' + baseUrl + '/pdf/api/v1/generate', +}; + +//Receipt +export var platformReceipt = { + receipt: 'https://platform.' + baseUrl + '/receipt/api/v1/instances', +}; + +//Platform Storage +export var platformStorage = { + applications: 'https://platform.' + baseUrl + '/storage/api/v1/applications', + instances: 'https://platform.' + baseUrl + '/storage/api/v1/instances', + messageBoxInstances: 'https://platform.' + baseUrl + '/storage/api/v1/sbl/instances', +}; + +//Platform events +export var platformEvents = { + events: 'https://platform.' + baseUrl + '/events/api/v1/app/', + eventsByParty: 'https://platform.' + baseUrl + '/events/api/v1/app/party/', + subscriptions: 'https://platform.' + baseUrl + '/events/api/v1/subscriptions', +}; + +//eFormidling +export var eFormidling = { + conversations: 'https://platform.' + baseUrl + '/eformidling/api/conversations', + statuses: 'https://platform.' + baseUrl + '/eformidling/api/statuses', + health: 'https://platform.' + baseUrl + '/eformidling/api/manage/health', + capabilities: 'https://platform.' + baseUrl + '/eformidling/api/capabilities', +}; + +//sblBridge +export var sblBridge = { + enterpriseUser: 'https://' + baseUrl + '/sblbridge/authentication/api/enterpriseuser' +}; + +export var sbl = { + altinnBuildVersion: `https://${baseUrl}/pages/logout/AltinnBuildVersion.txt` +} + +export function buildMaskinPorteSchemaUrls(party, type) { + var value = ''; + switch (type) { + case 'offered': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/offered`; + break; + case 'received': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/received`; + break; + case 'revokeoffered': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/offered/revoke`; + break; + case 'revokereceived': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/received/revoke`; + break; + case 'maskinportenschema': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/offered`; + break; + case 'delegationCheck': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/maskinportenschema/delegationcheck`; + break; + } + return value; +} +export function buildRightsEndpointUrls(party, type) { + var value = ''; + switch (type) { + case 'offered': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/offered`; + break; + case 'received': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/received`; + break; + case 'revokeoffered': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/offered/revoke`; + break; + case 'revokereceived': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/received/revoke`; + break; + case 'rights/delegation': + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/offered`; + break; + case 'delegationcheck': + if (baseUrl == null) { + value = `http://localhost:5117/accessmanagement/api/v1/${party}/rights/delegation/delegationcheck`; + break; + } + else { + value = `https://platform.${baseUrl}/accessmanagement/api/v1/${party}/rights/delegation/delegationcheck`; + break; + } + + } + console.log(value) + return value; +} + +//Function to build endpoints in storage with instanceOwnerId, instanceId, dataId, type +//and returns the endpoint +export function buildStorageUrls(instanceOwnerId, instanceId, dataId, type) { + var value = ''; + switch (type) { + case 'instanceid': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId; + break; + case 'dataid': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/data/' + dataId; + break; + case 'dataelements': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/dataelements'; + break; + case 'events': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/events'; + break; + case 'sblinstanceid': + value = platformStorage['messageBoxInstances'] + '/' + instanceOwnerId + '/' + instanceId; + break; + case 'process': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/process'; + break; + case 'completeconfirmation': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/complete'; + break; + case 'readstatus': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/readstatus'; + break; + case 'substatus': + value = platformStorage['instances'] + '/' + instanceOwnerId + '/' + instanceId + '/substatus'; + break; + case 'presentationtexts': + value = `${platformStorage['instances']}/${instanceOwnerId}/${instanceId}/presentationtexts`; + break; + case 'datavalues': + value = `${platformStorage['instances']}/${instanceOwnerId}/${instanceId}/datavalues`; + break; + } + return value; +} + +//App APIs +export function appApiBaseUrl(appOwner, appName) { + var url = 'https://' + appOwner + '.apps.' + baseUrl + '/' + appOwner + '/' + appName; + return url; +} + +//Validate Instantiation +export var appValidateInstantiation = '/api/v1/parties/validateInstantiation'; + +//Stateless +export var statelessdata = '/v1/data'; + +//App Profile +export var appProfile = { + user: '/api/v1/profile/user', +}; + +//Function to build endpoints in App Api with instanceOwnerId, instanceId, dataId, type +//and returns the endpoint +export function buildAppApiUrls(instanceOwnerId, instanceId, dataId, type) { + var value = ''; + switch (type) { + case 'instanceid': + value = '/instances/' + instanceOwnerId + '/' + instanceId; + break; + case 'dataid': + value = '/instances/' + instanceOwnerId + '/' + instanceId + '/data/' + dataId; + break; + case 'process': + value = '/instances/' + instanceOwnerId + '/' + instanceId + '/process'; + break; + case 'complete': + value = '/instances/' + instanceOwnerId + '/' + instanceId + '/complete'; + break; + case 'substatus': + value = '/instances/' + instanceOwnerId + '/' + instanceId + '/substatus'; + break; + case 'completeprocess': + value = '/instances/' + instanceOwnerId + '/' + instanceId + '/process/completeprocess'; + break; + case 'active': + value = `/instances/${instanceOwnerId}/active`; + break; + case 'datatags': + value = `/instances/${instanceOwnerId}/${instanceId}/data/${dataId}/tags`; + break; + } + return value; +} + +//App Resources +export var appResources = { + textresources: '/api/textresources', + applicationmetadata: '/api/v1/applicationmetadata', + servicemetadata: '/api/metadata/ServiceMetadata', + formlayout: '/api/resource/FormLayout.json', + rulehandler: '/api/resource/RuleHandler.js', + ruleconfiguration: '/api/resource/RuleConfiguration.json', + texts: '/api/v1/texts/', + jsonschema: '/api/jsonschema/', + layoutsettings: '/api/layoutsettings', +}; + +//App Authorization +export var appAuthorization = { + currentparties: '/api/authorization/parties/current?returnPartyObject=true', +}; + +//AltinnTestTools +export var tokenGenerator = { + getEnterpriseToken: 'https://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken', + getPersonalToken: 'https://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken', + getPlatformToken: 'https://altinn-testtools-token-generator.azurewebsites.net/api/GetPlatformToken', +}; + +//AltinnCDN +export var altinnCdn = { + toolkits: { + 'altinn-no-bold.css': 'https://altinncdn.no/toolkits/fortawesome/altinn-no-bold/0.1/css/embedded-woff.css', + 'altinn-no-regular.css': 'https://altinncdn.no/toolkits/fortawesome/altinn-no-regular/0.1/css/embedded-woff.css', + 'altinn-studio.css': 'https://altinncdn.no/toolkits/fortawesome/altinn-studio/0.1/css/embedded-woff.css', + 'altinn-app-frontend.css': 'https://altinncdn.no/toolkits/altinn-app-frontend/3/altinn-app-frontend.css', + 'altinn-app-frontend.js': 'https://altinncdn.no/toolkits/altinn-app-frontend/3/altinn-app-frontend.js', + }, + fonts: { + 'altinn-din.css': 'https://altinncdn.no/fonts/altinn-din/altinn-din.css', + 'altinn-DIN-Bold.woff2': 'https://altinncdn.no/fonts/altinn-din/woff2/Altinn-DIN-Bold.woff2', + 'altinn-DIN.woff2': 'https://altinncdn.no/fonts/altinn-din/woff2/Altinn-DIN.woff2', + }, + images: { + 'favicon.ico': 'https://altinncdn.no/favicon.ico', + 'altinn-logo-black': 'https://altinncdn.no/img/Altinn-logo-black.svg', + }, + orgs: 'https://altinncdn.no/orgs/altinn-orgs.json', +}; + +export var altinnUi = { + inbox: `https://${baseUrl}/ui/messagebox`, + archive: `https://${baseUrl}/ui/messagebox/archive`, + deleted: `https://${baseUrl}/ui/messagebox/trash`, + search: `https://${baseUrl}/ui/messagebox/search`, +}; diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/pdpinput.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/pdpinput.json new file mode 100644 index 00000000..956f4f27 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/pdpinput.json @@ -0,0 +1,23 @@ +{ + "Request": { + "ReturnPolicyIdList": false, + "AccessSubject": [ + { + "Attribute": [ + ] + } + ], + "Action": [ + { + "Attribute": [ + ] + } + ], + "Resource": [ + { + "Attribute": [ + ] + } + ] + } + } \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/policy.xml b/src/apps/Altinn.AccessManagement/test/K6/src/data/policy.xml new file mode 100644 index 00000000..8d9c6a35 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/policy.xml @@ -0,0 +1,158 @@ + + + + + A rule giving user with role REGNA or DAGL and the app owner ttd the right to instantiate a instance of a given app of ttd/postmanapp + + + + + REGNA + + + + + + DAGL + + + + + + ttd + + + + + + + + ttd + + + + postmanapp + + + + + + + + instantiate + + + + + + read + + + + + + + + Rule that defines that user with role REGNA or DAGL can read and write for ttd/postmanapp when it is in Task_1 + + + + + REGNA + + + + + + DAGL + + + + + + + + ttd + + + + postmanapp + + + + Task_1 + + + + + + ttd + + + + postmanapp + + + + EndEvent_1 + + + + + + + + read + + + + + + write + + + + + + + + Rule that defines that org can write to instances of ttd/postmanapp for any states + + + + + ttd + + + + + + + + ttd + + + + postmanapp + + + + + + + + write + + + + + + + + + + 2 + + + + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/access-management/rights-delegations/localtestdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/access-management/rights-delegations/localtestdata.json new file mode 100644 index 00000000..83109c9a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/access-management/rights-delegations/localtestdata.json @@ -0,0 +1,29 @@ +{ + "env": "at22", + "org": "ttd", + "app": "apps-test", + "resource": "", + "org1": { + "orgno": "810414782", + "partyid": "50067258", + "dagl": { + "pid":"21025400167", + "userid": "20004896", + "partyid": "50020295" + }, + "hadm": { + "pid": "17048001742", + "userid": "20003595", + "partyid": "50020440" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50066506", + "dagl": { + "pid": "26013000394", + "userid": "20004270", + "partyid": "50019590" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at21testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at21testdata.json new file mode 100644 index 00000000..555332cb --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at21testdata.json @@ -0,0 +1,38 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "910033166", + "partyid": "50078191", + "dagl": { + "userid": "20003434", + "partyid": "50012985" + } + }, + "org2": { + "orgno": "910029983", + "partyid": "50079385", + "dagl": { + "userid": "20004235", + "partyid": "50011204" + }, + "ecuser": { + "userid": "50079385", + "partyid": "20007680" + } + }, + "org3": { + "orgno": "910073478", + "partyid": "50078072", + "dagl": { + "userid": "20004105", + "partyid": "50013068" + }, + "subunit": { + "orgno": "910057901", + "partyid": "50079554" + } + } +} + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at22testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at22testdata.json new file mode 100644 index 00000000..415863e1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at22testdata.json @@ -0,0 +1,38 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "910033166", + "partyid": "50066583", + "dagl": { + "userid": "20003934", + "partyid": "50020484" + } + }, + "org2": { + "orgno": "910029983", + "partyid": "50066621", + "dagl": { + "userid": "20004677", + "partyid": "50018703" + }, + "ecuser": { + "userid": "50024601", + "partyid": "20018090" + } + }, + "org3": { + "orgno": "910073478", + "partyid": "50066757", + "dagl": { + "userid": "20002630", + "partyid": "50020567" + }, + "subunit": { + "orgno": "910057901", + "partyid": "50066669" + } + } +} + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at23testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at23testdata.json new file mode 100644 index 00000000..8513b3b1 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at23testdata.json @@ -0,0 +1,38 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "910033166", + "partyid": "50023723", + "dagl": { + "userid": "20002249", + "partyid": "50012985" + } + }, + "org2": { + "orgno": "910029983", + "partyid": "50024601", + "dagl": { + "userid": "20003203", + "partyid": "50011204" + }, + "ecuser": { + "userid": "50066621", + "partyid": "20008005" + } + }, + "org3": { + "orgno": "910073478", + "partyid": "50025117", + "dagl": { + "userid": "50011204", + "partyid": "50013068" + }, + "subunit": { + "orgno": "910057901", + "partyid": "50024534" + } + } +} + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at24testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at24testdata.json new file mode 100644 index 00000000..b52a139b --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/at24testdata.json @@ -0,0 +1,38 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "910033166", + "partyid": "50023721", + "dagl": { + "userid": "20013576", + "partyid": "50012985" + } + }, + "org2": { + "orgno": "910029983", + "partyid": "50024603", + "dagl": { + "userid": "20014275", + "partyid": "50011204" + }, + "ecuser": { + "userid": "50024603", + "partyid": "20017811" + } + }, + "org3": { + "orgno": "910073478", + "partyid": "50025123", + "dagl": { + "userid": "20014187", + "partyid": "50013068" + }, + "subunit": { + "orgno": "910057901", + "partyid": "50024537" + } + } +} + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/tt02testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/tt02testdata.json new file mode 100644 index 00000000..114340a3 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/delegations/tt02testdata.json @@ -0,0 +1,38 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "910033166", + "partyid": "50140163", + "dagl": { + "userid": "91449", + "partyid": "50037884" + } + }, + "org2": { + "orgno": "910029983", + "partyid": "50190412", + "dagl": { + "userid": "90955", + "partyid": "50021960" + }, + "ecuser": { + "userid": "159104", + "partyid": "50190412" + } + }, + "org3": { + "orgno": "910073478", + "partyid": "50128837", + "dagl": { + "userid": "92140", + "partyid": "50066551" + }, + "subunit": { + "orgno": "910057901", + "partyid": "50207257" + } + } +} + diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at21testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at21testdata.json new file mode 100644 index 00000000..3532391e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at21testdata.json @@ -0,0 +1,33 @@ +{ + "env": "at21", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": "50079380", + "dagl": { + "pid":"21025400167", + "userid": "20004475", + "partyid": "50012796" + }, + "hadm": { + "pid": "17048001742", + "userid": "20003092", + "partyid": "50012941" + }, + "apiadm": { + "pid": "18036000194", + "userid": "20003823", + "partyid": "50009383" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50079370", + "dagl": { + "pid": "26013000394", + "userid": "20003812", + "partyid": "50012091" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at22testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at22testdata.json new file mode 100644 index 00000000..b25c8189 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at22testdata.json @@ -0,0 +1,33 @@ +{ + "env": "at22", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": "50067258", + "dagl": { + "pid":"21025400167", + "userid": "20004896", + "partyid": "50020295" + }, + "hadm": { + "pid": "17048001742", + "userid": "20003595", + "partyid": "50020440" + }, + "apiadm": { + "pid": "18036000194", + "userid": "20004282", + "partyid": "50009383" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50066506", + "dagl": { + "pid": "26013000394", + "userid": "20004270", + "partyid": "50019590" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at23testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at23testdata.json new file mode 100644 index 00000000..69027e7d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at23testdata.json @@ -0,0 +1,33 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": "50024759", + "dagl": { + "pid":"21025400167", + "userid": "20002359", + "partyid": "50012796" + }, + "hadm": { + "pid": "17048001742", + "userid": "20003618", + "partyid": "50012941" + }, + "apiadm": { + "pid": "18036000194", + "userid": "20003412", + "partyid": "50009383" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50024778", + "dagl": { + "pid": "26013000394", + "userid": "20002644", + "partyid": "50012091" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at24testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at24testdata.json new file mode 100644 index 00000000..2c7a074d --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/at24testdata.json @@ -0,0 +1,33 @@ +{ + "env": "at23", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": "50024756", + "dagl": { + "pid":"21025400167", + "userid": "20014526", + "partyid": "50012796" + }, + "hadm": { + "pid": "17048001742", + "userid": "20013232", + "partyid": "50012941" + }, + "apiadm": { + "pid": "18036000194", + "userid": "20013942", + "partyid": "50009383" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50024778", + "dagl": { + "pid": "26013000394", + "userid": "20013938", + "partyid": "50012091" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/tt02testdata.json b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/tt02testdata.json new file mode 100644 index 00000000..e975dd29 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/data/testdata/maskinportenschema/tt02testdata.json @@ -0,0 +1,33 @@ +{ + "env": "tt02", + "org": "ttd", + "app": "apps-test", + "org1": { + "orgno": "810414782", + "partyid": "50189353", + "dagl": { + "pid":"21025400167", + "userid": "92356", + "partyid": "50077669" + }, + "hadm": { + "pid": "17048001742", + "userid": "92095", + "partyid": "50063278" + }, + "apiadm": { + "pid": "18036000275", + "userid": "92147", + "partyid": "50066592" + } + }, + "org2": { + "orgno": "910049356", + "partyid": "50189988", + "dagl": { + "pid": "26013000394", + "userid": "92630", + "partyid": "50096367" + } + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/errorcounter.js b/src/apps/Altinn.AccessManagement/test/K6/src/errorcounter.js new file mode 100644 index 00000000..46aec53e --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/errorcounter.js @@ -0,0 +1,25 @@ +import { Counter } from 'k6/metrics'; +import { fail } from 'k6'; + +let ErrorCount = new Counter('errors'); + +//Adds a count to the error counter when value of success is false +export function addErrorCount(success) { + if (!success) { + ErrorCount.add(1); + } +} + +/** + * Stops k6 iteration when success is false and prints test name with response code + * @param {String} testName + * @param {boolean} success + * @param {JSON} res + */ +export function stopIterationOnFail(testName, success, res) { + if (!success && res != null) { + fail(testName + ': Response code: ' + res.status); + } else if (!success) { + fail(testName); + } +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/report.js b/src/apps/Altinn.AccessManagement/test/K6/src/report.js new file mode 100644 index 00000000..caa1fb1a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/report.js @@ -0,0 +1,72 @@ +var replacements = { + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"', +}; + +function escapeHTML(str) { + return str.replace(/[&<>'"]/g, function (char) { + return replacements[char]; + }); +} + +function checksToTestcase(checks, failures) { + var testCases = []; + if (checks.length > 0) { + checks.forEach((check) => { + if (check.passes >= 1 && check.fails === 0) { + testCases.push(``); + } else { + failures++; + testCases.push(``); + } + }); + } + return [testCases, failures]; +} + +/** + * Generate a junit xml string from the summary of a k6 run considering each checks as a test case + * @param {*} data + * @param {String} suiteName Name of the test ex., filename + * @returns junit xml string + */ +export function generateJUnitXML(data, suiteName) { + var failures = 0; + var allTests = [], + testSubset = []; + var time = data.state.testRunDurationMs ? data.state.testRunDurationMs : 0; + + if (data.root_group.hasOwnProperty('groups') && data.root_group.groups.length > 0) { + var groups = data.root_group.groups; + groups.forEach((group) => { + var testSubset = []; + if (group.hasOwnProperty('checks')) [testSubset, failures] = checksToTestcase(group.checks, failures); + allTests.push(...testSubset); + }); + } + + if (data.root_group.hasOwnProperty('checks')) [testSubset, failures] = checksToTestcase(data.root_group.checks, failures); + allTests.push(...testSubset); + + return ( + `\n\n` + + `\n` + + `${allTests.join('\n')}\n\n` + ); +} + +/** + * Returns string that is path to the reports based on the OS where the test in run + * @param {String} reportName name of the file with extension + * @returns path + */ +export function reportPath(reportName) { + var path = `src/reports/${reportName}`; + if (!(__ENV.OS || __ENV.AGENT_OS)) path = `/${path}`; + return path; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/scenarios.js b/src/apps/Altinn.AccessManagement/test/K6/src/scenarios.js new file mode 100644 index 00000000..8623579a --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/scenarios.js @@ -0,0 +1,68 @@ +/** + * Function builds a JSOn object for the k6 scenario to be used in load test + * @param {*} type type of the executor: constantvus, sharediter, ramp + * @param {*} vus number of virtual users + * @param {*} iterations number of iterations + * @param {*} maxDuration duration of load + * @param {*} stages only for type: ramp in format "10s:5,40s:20,10s:5" + */ +export function k6scenarios(type, vus, iterations, maxDuration, stages) { + var scenario = {}; + switch (type) { + case 'constantvus': + constantVus.vus = vus; + constantVus.duration = maxDuration; + scenario.constantvus = constantVus; + break; + case 'sharediter': + sharedIterations.vus = vus; + sharedIterations.iterations = iterations; + sharedIterations.maxDuration = maxDuration; + scenario.sharedIter = sharedIterations; + break; + case 'ramp': + rampingVus.stages = buildRamp(stages); + scenario.ramp = rampingVus; + break; + } + return scenario; +} + +var constantVus = { + executor: 'constant-vus', + vus: 1, + duration: '1m', +}; + +var sharedIterations = { + executor: 'shared-iterations', + vus: 1, + iterations: 2, + maxDuration: '10m', +}; + +var rampingVus = { + executor: 'ramping-vus', + startVUs: 0, + stages: [], + gracefulRampDown: '30s', +}; + +/** + * function returns an array of JSON object for ramping-vus scenario in format + * [{duration : 10s, targer: 5}] + * @param {*} stages a string in format: 10s:5,40s:20,10s:5 + */ +function buildRamp(stages) { + var stagesArray = []; + var stages = stages.split(','); + stages.forEach((element) => { + element = element.split(':'); + var ramp = { + duration: element[0], + target: element[1], + }; + stagesArray.push(ramp); + }); + return stagesArray; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/setup.js b/src/apps/Altinn.AccessManagement/test/K6/src/setup.js new file mode 100644 index 00000000..817ec144 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/setup.js @@ -0,0 +1,160 @@ +import http from 'k6/http'; +import { check } from 'k6'; +import * as config from './config.js'; +import * as headers from './buildrequestheaders.js'; +import { getParties } from './api/platform/authorization/authorization.js'; +import { addErrorCount, stopIterationOnFail } from './errorcounter.js'; +import { convertMaskinPortenToken } from './api/platform/authentication.js'; +import { generateToken } from './api/altinn-testtools/token-generator.js'; + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; +const scopes = __ENV.scopes; +const maskinPortenToken = __ENV.maskinporten; + +//Request to Authenticate an user with Altinn userName and password and returns ASPXAUTH Cookie +export function authenticateUser(userName, userPassword) { + var endpoint = environment != 'yt01' ? config.authentication['authenticationWithPassword'] : config.authentication['authenticationYt01']; + var requestBody = { + UserName: userName, + UserPassword: userPassword, + }; + var params = { + headers: { + Accept: 'application/hal+json', + }, + }; + var res = http.post(endpoint, requestBody, params); + var success = check(res, { + 'Authentication towards Altinn 2 Success': (r) => r.status === 200, + }); + addErrorCount(success); + stopIterationOnFail('Authentication towards Altinn 2 Failed', success, res); + + const cookieName = '.ASPXAUTH'; + var cookieValue = res.cookies[cookieName][0].value; + return cookieValue; +} + +/**Request to authenticate an enterprise user and returns username, userid and partyid */ +export function authenticateECUser(username, password, orgNumber) { + var endpoint = environment != 'yt01' ? config.sblBridge['enterpriseUser'] : config.authentication['authenticationYt01']; + var requestBody = { + UserName: username, + Password: password, + OrganizationNumber: orgNumber + }; + var params = { + headers: { + ContentType: 'application/json', + }, + }; + var res = http.post(endpoint, requestBody, params); + + var success = check(res, { + 'Authentication of enterprise user via SBL Bridge Success': (r) => r.status === 200, + }); + addErrorCount(success); + stopIterationOnFail('Authentication of enterprise user via SBL Bridge Failed', success, res); + res = JSON.parse(res.body); + var ecUserData = { + userName: res.Username, + userId: res.UserID, + partyId: res.PartyID + } + + return ecUserData; + +} + +//Request to Authenticate an user and returns AltinnStudioRuntime Token +export function getAltinnStudioRuntimeToken(aspxauthCookie) { + clearCookies(); + var endpoint = config.platformAuthentication['authentication'] + '?goto=' + config.platformAuthentication['refresh']; + var params = headers.buildHeaderWithAspxAuth(aspxauthCookie, 'platform'); + var res = http.get(endpoint, params); + var success = check(res, { + 'T3.0 Authentication Success': (r) => r.status === 200, + }); + addErrorCount(success); + stopIterationOnFail('T3.0 Authentication Failed', success, res); + return res.body; +} + +//Request to get user data and returns partyId, ssn, userId, orgNr +export function getUserData(altinnStudioRuntimeCookie, appOwner, appName, orgNo) { + clearCookies(); + var endpoint = config.appApiBaseUrl(appOwner, appName) + config.appProfile['user']; + var params = headers.buildHeaderWithRuntime(altinnStudioRuntimeCookie, 'app'); + var res = http.get(endpoint, params); + var success = check(res, { + 'Get User data': (r) => r.status === 200, + }); + addErrorCount(success); + stopIterationOnFail('Get User data failed', success, res); + res = JSON.parse(res.body); + + var userData = { + userId: res.userId, + ssn: res.party.ssn, + partyId: res.partyId, + orgNumber: orgNo, + orgNumberPartyId: null, + personalToken: null, + }; + + //get parties and find an Org that an user can represent + res = getParties(altinnStudioRuntimeCookie, userData['userId']); + success = check(res, { + 'Get User data': (r) => r.status === 200, + }); + addErrorCount(success); + stopIterationOnFail('Get User data failed', success, res); + + res = JSON.parse(res.body); + for (var i = 0; i < res.length; i++) { + if ( orgNo == null && res[i].orgNumber != null) { + userData.orgNumberPartyId = res[i].partyId; + userData.orgNumber = res[i].orgNumber; + break; + } + else if( orgNo != null && orgNo == res[i].orgNumber){ + userData.orgNumberPartyId = res[i].partyId; + break; + } + } + return userData; +} + +//Function to clear the cookies under baseurl by setting the expires field to a past date +export function clearCookies() { + var jar = http.cookieJar(); + jar.set('https://' + config.baseUrl, 'AltinnStudioRuntime', 'test', { expires: 'Mon, 02 Jan 2010 15:04:05 MST' }); + jar.set('https://' + config.baseUrl, '.ASPXAUTH', 'test', { expires: 'Mon, 02 Jan 2010 15:04:05 MST' }); +} + +/** + * generate an altinn token for TTD based on the environment + * use exchange token if prod, and altinnTestTools for test environments + * @returns altinn token with the scopes for an org/appowner + */ +export function getAltinnTokenForTTD() { + if (environment === 'prod') { + return convertMaskinPortenToken(maskinPortenToken, 'true'); + } else { + var queryParams = { + env: environment, + scopes: scopes, + org: 'ttd', + orgNo: '991825827', + }; + return generateToken('enterprise', tokenGeneratorUserName, tokenGeneratorUserPwd, queryParams); + } +} + +export function getSBLBuildVersion() { + var endpoint = config.sbl['altinnBuildVersion']; + var res = http.get(endpoint); + return res.body.replace(/[^0-9a-zA-Z.]/g, ""); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/support.js b/src/apps/Altinn.AccessManagement/test/K6/src/support.js new file mode 100644 index 00000000..a4b7394f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/support.js @@ -0,0 +1,68 @@ +//Fisher–Yates shuffle of an array +export function shuffle(array) { + for (let i = array.length - 1; i > 0; i--) { + let j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} + +/** + * Build a string in a format of query param to the endpoint + * @param {*} filterParameters a json object with key as query name and value as query value + * @example {"key1": "value1", "key2": "value2"} + * @returns string a string like key1=value&key2=value2 + */ +export function buildQueryParametersForEndpoint(filterParameters) { + var query = '?'; + Object.keys(filterParameters).forEach(function (key) { + if (Array.isArray(filterParameters[key])) { + filterParameters[key].forEach((value) => { + query += key + '=' + value + '&'; + }); + } else { + query += key + '=' + filterParameters[key] + '&'; + } + }); + query = query.slice(0, -1); + return query; +} + +/** + * @returns today's date with time 00:00:00 in ISO format + */ +export function todayDateInISO() { + var todayDateTime = new Date(); + todayDateTime.setUTCHours(0, 0, 0, 0); + return todayDateTime.toISOString(); +} + +/** + * Check if a string is a guid + * @param {String} stringToTest + * @returns true or false + */ +export function isGuid(stringToTest) { + var regexGuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + return regexGuid.test(stringToTest); +} + +//Generate array with type of attachment for all the iterations +//based on the distribution across small, medium and large attachment +export function buildAttachmentTypeArray(distribution, totalIterations) { + distribution = distribution.split(';'); + var small = distribution[0] != null ? buildArray(totalIterations * (distribution[0] / 100), 's') : []; + var medium = distribution[1] != null ? buildArray(totalIterations * (distribution[1] / 100), 'm') : []; + var large = distribution[2] != null ? buildArray(totalIterations * (distribution[2] / 100), 'l') : []; + var attachmentTypes = small.concat(medium, large); + return shuffle(attachmentTypes); +} + +//Function to build an array with the specified value and count +function buildArray(count, value) { + var array = []; + for (var i = 0; i < count; i++) { + array.push(value); + } + return array; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/maskinporten/maskinporten.js b/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/maskinporten/maskinporten.js new file mode 100644 index 00000000..6c193c36 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/maskinporten/maskinporten.js @@ -0,0 +1,685 @@ +/* + Test data required: deployed app (reference app: ttd/apps-test) + userid, partyid for two users that are DAGL for two orgs, and partyid and orgno for those orgs (user1 and user2) + Org number for user2's org +docker-compose run k6 run /src/tests/maskinporten/maskinporten.js -e env=*** -e tokengenuser=*** -e tokengenuserpwd=*** -e appsaccesskey=*** + + +*/ +import { check, sleep, fail } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../../../errorcounter.js'; +import { generateToken } from '../../../api/altinn-testtools/token-generator.js'; +import { generateJUnitXML, reportPath } from '../../../report.js'; +import * as maskinporten from '../../../api/access-management/maskinporten/maskinporten.js'; + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; +let testdataFile = open(`../../../data/testdata/maskinportenschema/${__ENV.env}testdata.json`); +var testdata = JSON.parse(testdataFile); +var org1; +var org2; + +export const options = { + thresholds: { + errors: ['count<1'], + }, + setupTimeout: '1m', +}; + +export function setup() { + + //generate personal token for user 1 (DAGL for org1) + var tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.dagl.pid, + userid: testdata.org1.dagl.userid, + partyid: testdata.org1.dagl.partyid, + authLvl: 3, + }; + testdata.org1.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org2.dagl.pid, + userid: testdata.org2.dagl.userid, + partyid: testdata.org2.dagl.partyid, + authLvl: 3, + }; + testdata.org2.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.hadm.pid, + userid: testdata.org1.hadm.userid, + partyid: testdata.org1.hadm.partyid, + authLvl: 3, + }; + testdata.org1.hadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.apiadm.pid, + userid: testdata.org1.apiadm.userid, + partyid: testdata.org1.apiadm.partyid, + authLvl: 3, + }; + testdata.org1.apiadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + return testdata; +} + +export default function (data) { + if (!data) { + return; + } + org1 = data.org1; + org2 = data.org2; + + //tests + postMaskinportenSchemaToOrgNumberTest(); + postMaskinportenSchemaToPartyIdTest(); + // postMaskinportenSchemaWithOrgNoInHeaderTest(); // Uncomment when #400 "post maskinportenschema with orgno in header returns 403" has been fixed + postMaskinportenSchemaAsHadmTest(); + postMaskinportenSchemaAsApiadmTest(); + postMaskinportenCannotDelegateToPersonTest(); + postMaskinportenDAGLCannotDelegateNUFResource(); + postMaskinportenSystemResourceCannotBeDelegatedTest(); + getMaskinPortenSchemaOfferedInvalidPartyId(); + getMaskinPortenSchemaReceivedInvalidPartyId(); + postMaskinportenSchemaNotReadyTest(); + getMaskinPortenSchemaOfferedTest(); + getMaskinPortenSchemaReceivedTest(); + revokeOfferedMaskinPortenSchema(); + revokeReceivedMaskinPortenSchema(); + revokeOfferedMaskinPortenSchemaUsingPartyId(); + revokeReceivedMaskinPortenSchemaUsingPartyId(); + revokeNonExistentOfferedMaskinPortenSchema(); + revokeNonExistentReceivedMaskinPortenSchema(); + delegationCheckMaskinPortenSchema_DAGLhasScopeAccess(); + delegationCheckMaskinPortenSchema_HADMhasScopeAccess(); + delegationCheckMaskinPortenSchema_resourceDoesNotExist(); + delegationCheckMaskinPortenSchema_tooLowAuthLevel(); + +} + +/** Check that list of offered maschinportenschemas is correct */ +export function getMaskinPortenSchemaOfferedTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6-nuf'; + var res = maskinporten.revokeOfferedMaskinportenSchema(org1.dagl.token, org1.partyid, 'ttd-am-k6', 'urn:altinn:organizationnumber', org2.orgno); + + // Act + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + + // Assert + var success = check(res, { + 'get offered MaskinPortenSchemas - status is 200': (r) => r.status === 200, + 'get offered MaskinPortenSchemas - coveredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.coveredByName') === 'LARKOLLEN OG FAUSKE', + 'get offered MaskinPortenSchemas - offeredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.offeredByName') === 'ALDRA OG FORTUN', + 'get offered MaskinPortenSchemas - offeredByPartyId is ${offeredByPartyId}': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'get offered MaskinPortenSchemas - coveredByPartyId is ${coveredByPartyId}': (r) => r.json('0.coveredByPartyId') == org2.partyid, + 'get offered MaskinPortenSchemas - performedByUserId is ${performedByUserId}': (r) => r.json('0.performedByUserId') == org1.dagl.userid, + 'get offered MaskinPortenSchemas - offeredByOrganizationNumber is ${offeredByOrganizationNumber}': (r) => r.json('0.offeredByOrganizationNumber') == org1.orgno, + 'get offered MaskinPortenSchemas - coveredByOrganizationNumber is ${coveredByOrganizationNumber}': (r) => r.json('0.coveredByOrganizationNumber') == org2.orgno, + 'get offered MaskinPortenSchemas - resourceId is ttd-am-k6-nuf': (r) => r.json('0.resourceId') == appid, + }); + addErrorCount(success); +} + +/** Check that you can't get offered schemas using the wrong partyid */ +export function getMaskinPortenSchemaOfferedInvalidPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const wrongOfferedByPartyId = org2.partyid; + + // Act + var res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, wrongOfferedByPartyId); + + // Assert + var success = check(res, { + 'get offered MaskinPortenSchemas with invalid partyid- status is 403 forbidden': (r) => r.status === 403, + }); + addErrorCount(success); +} + +/** Check that list of received maschinportenschemas is correct */ +export function getMaskinPortenSchemaReceivedTest() { + // Arrange + const toToken = org2.dagl.token; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6-nuf'; + var res = maskinporten.revokeOfferedMaskinportenSchema(org1.dagl.token, org1.partyid, 'ttd-am-k6', 'urn:altinn:organizationnumber', org2.orgno); + + // Act + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + + // Assert + var success = check(res, { + 'get Received MaskinPortenSchemas - status is 200': (r) => r.status === 200, + 'get Received MaskinPortenSchemas - offeredByName is ALDRA OG FORTUN': (r) => r.json('0.offeredByName') === 'ALDRA OG FORTUN', + 'get Received MaskinPortenSchemas - coveredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.coveredByName') === 'LARKOLLEN OG FAUSKE', + 'get Received MaskinPortenSchemas - offeredByPartyId is ${offeredByPartyId}': (r) => r.json('0.offeredByPartyId') == org1.partyid, + 'get Received MaskinPortenSchemas - coveredByPartyId is ${coveredByPartyId}': (r) => r.json('0.coveredByPartyId') == org2.partyid, + 'get Received MaskinPortenSchemas - performedByUserId is ${performedByUserId}': (r) => r.json('0.performedByUserId') == org1.dagl.userid, + 'get Received MaskinPortenSchemas - offeredByOrganizationNumber is ${offeredByOrganizationNumber}': (r) => r.json('0.offeredByOrganizationNumber') == org1.orgno, + 'get Received MaskinPortenSchemas - coveredByOrganizationNumber is ${coveredByOrganizationNumber}': (r) => r.json('0.coveredByOrganizationNumber') == org2.orgno, + 'get Received MaskinPortenSchemas - resourceId is ttd-am-k6-nuf': (r) => r.json('0.resourceId') == appid, + + }); + addErrorCount(success); +} + +/** Check that you can't get received schemas using the wrong partyid */ +export function getMaskinPortenSchemaReceivedInvalidPartyId() { + // Arrange + const toToken = org1.dagl.token; + const wrongToPartyId = org2.partyid; + + // Act + var res = maskinporten.getMaskinportenSchemaOffered(toToken, wrongToPartyId); + + // Assert + var success = check(res, { + 'get received MaskinPortenSchemas with invalid partyid- status is 403 forbidden': (r) => r.status === 403, + }); + addErrorCount(success); +} + +/** offer a maskinportenschema using a party id */ +export function postMaskinportenSchemaToPartyIdTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema To PartyId - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema To PartyId - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema To PartyId - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema To PartyId - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema To PartyId - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema To PartyId - action is ScopeAccess': (r) => r.json('rightDelegationResults.0.action') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema using an organization number */ +export function postMaskinportenSchemaToOrgNumberTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'post MaskinportenSchema To Org Number - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema To Org Number - to id is organizationnumber': (r) => r.json('to.0.id') === 'urn:altinn:organizationnumber', + 'post MaskinportenSchema To Org Number - organization number matches': (r) => r.json('to.0.value') === toOrgNumber, + 'post MaskinportenSchema To Org Number - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema To Org Number - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema To Org Number - action is ScopeAccess': (r) => r.json('rightDelegationResults.0.action') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema using the offeredby's organization number in the header */ +export function postMaskinportenSchemaWithOrgNoInHeaderTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByOrganizationNumber = org1.orgno; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchemaOrgNoInHeader(offeredByToken, offeredByOrganizationNumber, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema with offeredbys orgno in header - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema with offeredbys orgno in header - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema with offeredbys orgno in header - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema with offeredbys orgno in header - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema with offeredbys orgno in header - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema with offeredbys orgno in header - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema with offeredbys orgno in header - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema as HADM (instead of DAGL) */ +export function postMaskinportenSchemaAsHadmTest() { + // Arrange + const offeredByToken = org1.hadm.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema As HADM - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema As HADM - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema As HADM - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema As HADM - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema As HADM - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema As HADM - action is ScopeAccess': (r) => r.json('rightDelegationResults.0.action') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema as APIADM (instead of DAGL) */ +export function postMaskinportenSchemaAsApiadmTest() { + // Arrange + const offeredByToken = org1.apiadm.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema As APIADM - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema As APIADM - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema As APIADM - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema As APIADM - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema As APIADM - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema As APIADM - action is ScopeAccess': (r) => r.json('rightDelegationResults.0.action') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** try and fail to delegate maskinportenschema to a person */ +export function postMaskinportenCannotDelegateToPersonTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.dagl.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema Cannot Delegate To Person - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema Cannot Delegate To Person - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema Cannot Delegate To Person - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema Cannot Delegate To Person - Invalid organization': (r) => r.body.includes('Maskinporten schema delegation can only be delegated to a valid organization'), + }); + + addErrorCount(success); +} + +/** try and fail to delegate maskinportenschema to a person */ +export function postMaskinportenDAGLCannotDelegateNUFResource() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6-nuf'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - Unauthorized to delegate the resource': (r) => r.body.includes('Authenticated user does not have any delegable rights for the resource: ttd-am-k6-nuf'), + }); + + addErrorCount(success); +} + +/** try and fail to delegate a system resource */ +export function postMaskinportenSystemResourceCannotBeDelegatedTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'altinn_maskinporten_scope_delegation'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post Maskinporten Systemresource Cannot be delegated - status is 400': (r) => r.status === 400, + 'post Maskinporten Systemresource Cannot be delegated - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post Maskinporten Systemresource Cannot be delegated - errors is not null': (r) => r.json('errors') != null, + 'post Maskinporten Systemresource Cannot be delegated - Invalid resource type': (r) => r.body.includes('This operation only support requests for Maskinporten schema resources. Invalid resource: Identifier: altinn_maskinporten_scope_delegation, ResourceType: Systemresource'), + }); + + addErrorCount(success); +} + +/** try to offer a maskinportenschema that is not ready */ +export function postMaskinportenSchemaNotReadyTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'appid-302'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'post MaskinportenSchema that is Not Ready - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema that is Not Ready - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema that is Not Ready - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema that is Not Ready - resource is incomplete or not found': (r) => r.body.includes('The resource: appid-302, does not exist or is not available for delegation'), + }); + + addErrorCount(success); +} + +/** revoke an offered maskinportenschema */ +export function revokeOfferedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + success = check(res, { + 'revoke Offered MaskinPortenSchema - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'revoke Offered MaskinPortenSchema - revoke status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke a received maskinportenschema */ +export function revokeReceivedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const toToken = org2.dagl.token; + const offeredByPartyId = org1.partyid; + const offeredByOrgNumber = org1.orgno; + const toOrgNumber = org2.orgno; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + success = check(res, { + 'revoke Received MaskinPortenSchema - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, appid, 'urn:altinn:organizationnumber', offeredByOrgNumber); + + // Assert + var success = check(res, { + 'revoke Received MaskinPortenSchema - status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke an offered maskinportenschema using partyid*/ +export function revokeOfferedMaskinPortenSchemaUsingPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid- revoke status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid- getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke a received maskinportenschema using partyid*/ +export function revokeReceivedMaskinPortenSchemaUsingPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const toToken = org2.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, appid, 'urn:altinn:partyid', offeredByPartyId); + + // Assert + var success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + sleep(3); + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** try to revoke a non-existent offered maskinportenschema */ +export function revokeNonExistentOfferedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + + // Act + var res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, 'nonexistentmaskinportenschema', 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'revoke non-existent Offered MaskinPortenSchema - status is 400': (r) => r.status === 400, + 'revoke non-existent Offered MaskinPortenSchema - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'revoke non-existent Offered MaskinPortenSchema - errors is not null': (r) => r.json('errors') != null, + 'revoke non-existent Offered MaskinPortenSchema - resource is incomplete or not found': (r) => r.body.includes('The resource: nonexistentmaskinportenschema, does not exist or is not available for delegation'), + }); + addErrorCount(success); +} + +/** try to revoke a non-existent received maskinportenschema */ +export function revokeNonExistentReceivedMaskinPortenSchema() { + // Arrange + const toToken = org2.dagl.token; + const toPartyId = org2.partyid; + const offeredByOrgNumber = org1.orgno; + + // Act + var res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, 'nonexistentmaskinportenschema', 'urn:altinn:organizationnumber', offeredByOrgNumber); + + // Assert + var success = check(res, { + 'revoke non-existent Received MaskinPortenSchema - status is 400': (r) => r.status === 400, + 'revoke non-existent Received MaskinPortenSchema - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'revoke non-existent Received MaskinPortenSchema - errors is not null': (r) => r.json('errors') != null, + 'revoke non-existent Received MaskinPortenSchema - resource is incomplete or not found': (r) => r.body.includes('The resource: nonexistentmaskinportenschema, does not exist or is not available for delegation'), + }); + addErrorCount(success); +} + +/** check delegation rights on a maskinportenschema for DAGL role */ +export function delegationCheckMaskinPortenSchema_DAGLhasScopeAccess() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: DAGL has scope access - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: DAGL has scope access - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: DAGL has scope access - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: DAGL has scope access - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'delegationCheckMaskinportenSchema: DAGL has scope access - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'delegationCheckMaskinportenSchema: DAGL has scope access - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + }); + addErrorCount(success); +} + +/** check delegation rights on a maskinportenschema for HADM role*/ +export function delegationCheckMaskinPortenSchema_HADMhasScopeAccess() { + // Arrange + const offeredByToken = org1.hadm.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: HADM has scope access - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: HADM has scope access - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: HADM has scope access - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: HADM has scope access - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'delegationCheckMaskinportenSchema: HADM has scope access - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'delegationCheckMaskinportenSchema: HADM has scope access - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + }); + addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate a non-existing resource */ +export function delegationCheckMaskinPortenSchema_resourceDoesNotExist() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'aresourcethattotallydoesnotexist'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: Resource Is NonDelegable - status is 400 ': (r) => r.status === 400, + 'delegationCheckMaskinportenSchema: Resource Is NonDelegable - Error message is "The resource does not exist or is not available for delegation"': (r) => r.body.includes('The resource does not exist or is not available for delegation'), + }); + addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate with a too low authentication level */ +export function delegationCheckMaskinPortenSchema_tooLowAuthLevel() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'altinn_automation_test_lv4'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: user has too low authentication level - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: user has too low authentication level - rightskey is altinn_automation_test_lv4:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: user has too low authentication level - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: user has too low authentication level - resource value is altinn_automation_test_lv4': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: user has too low authentication level - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: user has too low authentication level - status is NotDelegable': (r) => r.json('0.status') == 'NotDelegable', + 'delegationCheckMaskinportenSchema: user has too low authentication level - code is InsufficientAuthenticationLevel': (r) => r.json('0.details.0.code') == 'InsufficientAuthenticationLevel', + 'delegationCheckMaskinportenSchema: user has too low authentication level - MinimumAuthenticationLevel id is urn:altinn:minimum-authenticationlevel': (r) => r.json('0.details.0.parameters.MinimumAuthenticationLevel.0.id') == 'urn:altinn:minimum-authenticationlevel', + 'delegationCheckMaskinportenSchema: user has too low authentication level - MinimumAuthenticationLevel value is 4': (r) => r.json('0.details.0.parameters.MinimumAuthenticationLevel.0.value') == '4', + }); + addErrorCount(success); +} + + +export function handleSummary(data) { + let result = {}; + result[reportPath('maskinportenschema.xml')] = generateJUnitXML(data, 'access-management-maskinportenschema'); + return result; +} + +export function showTestdata() { + console.log(environment) + console.log('personalToken1: ' + org1.dagl.token); + console.log('personalToken2: ' + org2.dagl.token); + console.log('org: ' + testdata.org); + console.log('app: ' + testdata.app); + console.log('user1pid: ' + org1.dagl.pid); + console.log('user1userid: ' + org1.dagl.userid); + console.log('user1partyid: ' + org1.dagl.partyid); + console.log('orgno1: ' + org1.orgno); + console.log('orgpartyid1: ' + org1.partyid); + console.log('hadm1userid: ' + org1.hadm.userid); + console.log('hadm1partyid: ' + org1.hadm.partyid); + console.log('user2pid: ' + org2.dagl.pid); + console.log('user2userid: ' + org2.dagl.userid); + console.log('user2partyid: ' + org2.dagl.partyid); + console.log('orgno2: ' + org2.orgno); + console.log('orgpartyid2: ' + org2.partyid); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/rights-delegations/userdelegationcheck.js b/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/rights-delegations/userdelegationcheck.js new file mode 100644 index 00000000..d72fe05f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/tests/access-management/rights-delegations/userdelegationcheck.js @@ -0,0 +1,372 @@ +/* + Test data required: deployed app (reference app: ttd/apps-test) + userid, partyid for two users that are DAGL for two orgs, and partyid and orgno for those orgs (user1 and user2) + Org number for user2's org +docker-compose run k6 run /src/tests/access-management/rights-delegations.js -e env=*** -e tokengenuser=*** -e tokengenuserpwd=*** -e appsaccesskey=*** + + +*/ +import { check, sleep, fail } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../../../errorcounter.js'; +import { generateToken } from '../../../api/altinn-testtools/token-generator.js'; +import { generateJUnitXML, reportPath } from '../../../report.js'; +import * as userDelegationCheck from '../../../api/access-management/rights-delegations/userdelegationcheck.js'; + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; +let testdataFile = open(`../../../data/testdata/access-management/rights-delegations/${__ENV.env}testdata.json`); +var testdata = JSON.parse(testdataFile); +var org1; +var org2; + +export const options = { + thresholds: { + errors: ['count<1'], + }, + setupTimeout: '1m', +}; + +export function setup() { + + //generate personal token for user 1 (DAGL for org1) + var tokenGenParams = { + env: testdata.env, + scopes: 'altinn:instances.read', + pid: testdata.org1.dagl.pid, + userid: testdata.org1.dagl.userid, + partyid: testdata.org1.dagl.partyid, + authLvl: 3, + }; + + testdata.org1.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: testdata.env, + scopes: 'altinn:instances.read', + pid: testdata.org2.dagl.pid, + userid: testdata.org2.dagl.userid, + partyid: testdata.org2.dagl.partyid, + authLvl: 3, + }; + testdata.org2.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: testdata.env, + scopes: 'altinn:instances.read', + pid: testdata.org1.hadm.pid, + userid: testdata.org1.hadm.userid, + partyid: testdata.org1.hadm.partyid, + authLvl: 3, + }; + testdata.org1.hadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: testdata.env, + scopes: 'altinn:instances.read', + pid: testdata.org1.apiadm.pid, + userid: testdata.org1.apiadm.userid, + partyid: testdata.org1.apiadm.partyid, + authLvl: 3, + }; + testdata.org1.apiadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + return testdata; +} + +export default function (data) { + if (!data) { + return; + } + org1 = data.org1; + org2 = data.org2; + + //tests + daglForOrgHasScopeAccessForResource() + daglStatusIsNotDelegableForPrivResource() + hadmForOrgHasScopeAccess() + privUserHasScopeAccessForResource() + resourceIsNonDelegable() + resourceDoesNotExist() + daglForOrgHasScopeAccessForApp() + daglStatusIsNotDelegableForPrivApp() + privUserHasScopeAccessForApp() + daglForOrgHasScopeAccessForAltinn2Service() + privUserHasScopeAccessForAltinn2Service() +} + +/** Checks that DAGl for an org has ScopeAccess for the resource k6-userdelegationcheck-apiadm */ +export function daglForOrgHasScopeAccessForResource() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'k6-userdelegationcheck-apiadm'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'daglForOrgHasScopeAccessForResource - status is 200': (r) => r.status === 200, + 'daglForOrgHasScopeAccessForResource - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'daglForOrgHasScopeAccessForResource - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'daglForOrgHasScopeAccessForResource - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'daglForOrgHasScopeAccessForResource - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'daglForOrgHasScopeAccessForResource - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'daglForOrgHasScopeAccessForResource - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'daglForOrgHasScopeAccessForResource - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'daglForOrgHasScopeAccessForResource - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'daglForOrgHasScopeAccessForResource - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + }); + addErrorCount(success); +} + +/** Checks that DAGl for an org can not delegate a resource that requires PRIV role */ +export function daglStatusIsNotDelegableForPrivResource() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'k6-userdelegationcheck-priv'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert +var success = check(res, { + 'daglStatusIsNotDelegableForPrivResource - status is 200': (r) => r.status === 200, + 'daglStatusIsNotDelegableForPrivResource - rightskey is k6-userdelegationcheck-priv:ScopeAccess': (r) => r.json('0.rightKey') === 'k6-userdelegationcheck-priv:ScopeAccess', + 'daglStatusIsNotDelegableForPrivResource - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'daglStatusIsNotDelegableForPrivResource - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'daglStatusIsNotDelegableForPrivResource - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'daglStatusIsNotDelegableForPrivResource - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'daglStatusIsNotDelegableForPrivResource - status is NotDelegable': (r) => r.json('0.status') == 'NotDelegable', + 'daglStatusIsNotDelegableForPrivResource - code is MissingDelegationAccess': (r) => r.json('0.details.1.code') == 'MissingDelegationAccess', + 'daglStatusIsNotDelegableForPrivResource - code is MissingRoleAccess': (r) => r.json('0.details.0.code') == 'MissingRoleAccess', + 'daglStatusIsNotDelegableForPrivResource - RequiredRoles id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RequiredRoles.0.id') == 'urn:altinn:rolecode', + 'daglStatusIsNotDelegableForPrivResource - RequiredRoles value is PRIV': (r) => r.json('0.details.0.parameters.RequiredRoles.0.value') == 'PRIV', +}); +addErrorCount(success); +} + +/** Checks that HADM for an org has ScopeAccess for the resource k6-userdelegationcheck-apiadm */ +export function hadmForOrgHasScopeAccess() { + const offeredByToken = org1.hadm.token; + const offeredByPartyId = org1.hadm.partyid; + const appid = 'k6-userdelegationcheck-apiadm'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert +var success = check(res, { + 'hadmForOrgHasScopeAccess - status is 200': (r) => r.status === 200, + 'hadmForOrgHasScopeAccess - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'hadmForOrgHasScopeAccess - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'hadmForOrgHasScopeAccess - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'hadmForOrgHasScopeAccess - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'hadmForOrgHasScopeAccess - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'hadmForOrgHasScopeAccess - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'hadmForOrgHasScopeAccess - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'hadmForOrgHasScopeAccess - RoleRequirementsMatches is urn:altinn:rolecode:APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches') == 'urn:altinn:rolecode:APIADM', +}); +addErrorCount(success); +} + +/** Checks that a PRIV user has ScopeAccess for the a resource that requires the PRIV role */ +export function privUserHasScopeAccessForResource() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.dagl.partyid; + const appid = 'k6-userdelegationcheck-priv'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert +var success = check(res, { + 'privUserHasScopeAccessForResource - status is 200': (r) => r.status === 200, + 'privUserHasScopeAccessForResource - rightskey is k6-userdelegationcheck-priv:ScopeAccess': (r) => r.json('0.rightKey') === 'k6-userdelegationcheck-priv:ScopeAccess', + 'privUserHasScopeAccessForResource - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'privUserHasScopeAccessForResource - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'privUserHasScopeAccessForResource - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'privUserHasScopeAccessForResource - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'privUserHasScopeAccessForResource - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'privUserHasScopeAccessForResource - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'privUserHasScopeAccessForResource - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'privUserHasScopeAccessForResource - RoleRequirementsMatches value is PRIV': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'PRIV', +}); +addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate a non-delegable resource */ +export function resourceIsNonDelegable() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'k6-userdelegationcheck-apiadm-non-delegable'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'ResourceIsNonDelegable - status is 400 ': (r) => r.status === 400, + 'ResourceIsNonDelegable - Error message is "The resource: Identifier: k6-userdelegationcheck-apiadm-non-delegable"': (r) => r.body.includes('The resource: Identifier: k6-userdelegationcheck-apiadm-non-delegable'), +}); +addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate a non-existing resource */ +export function resourceDoesNotExist() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'jfkdsaljfdksjafkjdiejfoewjifeovneuwvbu4bvu4buvbvbdbvubduwsdhuh'; + var res = userDelegationCheck.resourceUserDelegationCheck(offeredByToken, offeredByPartyId, appid); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'ResourceIsNonDelegable - status is 400 ': (r) => r.status === 400, + 'ResourceIsNonDelegable - Error message is "The resource: Identifier: jfkdsaljfdksjafkjdiejfoewjifeovneuwvbu4bvu4buvbvbdbvubduwsdhuh"': (r) => r.body.includes('The resource: Identifier: jfkdsaljfdksjafkjdiejfoewjifeovneuwvbu4bvu4buvbvbdbvubduwsdhuh'), +}); +addErrorCount(success); +} + +/** Checks that DAGl for an org has ScopeAccess for the altinn3 app ttd/apps-test */ +export function daglForOrgHasScopeAccessForApp() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const org = 'ttd'; + const app = 'apps-test'; + var res = userDelegationCheck.appUserDelegationCheck(offeredByToken, offeredByPartyId, org, app); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'daglForOrgHasScopeAccessForApp - status is 200': (r) => r.status === 200, + 'daglForOrgHasScopeAccessForApp - rightskey is apps-test,ttd:ScopeAccess': (r) => r.json('0.rightKey') === 'apps-test,ttd:ScopeAccess', + 'daglForOrgHasScopeAccessForApp - resource org id is urn:altinn:org': (r) => r.json('0.resource.0.id') === 'urn:altinn:org', + 'daglForOrgHasScopeAccessForApp - resource org value is ttd': (r) => r.json('0.resource.0.value') == org, + 'daglForOrgHasScopeAccessForApp - resource app id is urn:altinn:org': (r) => r.json('0.resource.1.id') === 'urn:altinn:app', + 'daglForOrgHasScopeAccessForApp - resource app value is apps-test-tba': (r) => r.json('0.resource.1.value') == app, + 'daglForOrgHasScopeAccessForApp - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'daglForOrgHasScopeAccessForApp - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'daglForOrgHasScopeAccessForApp - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'daglForOrgHasScopeAccessForApp - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches value is PRIV': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches id is urn:altinn:org': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.1.id') == 'urn:altinn:org', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches value is ttd': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.1.value') == 'ttd', +}); +addErrorCount(success); +} + +/** Checks that a PRIV user has ScopeAccess for the altinn3 app ttd/apps-test-tba */ +export function privUserHasScopeAccessForApp() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.dagl.partyid; + const org = 'ttd'; + const app = 'apps-test-tba'; + var res = userDelegationCheck.appUserDelegationCheck(offeredByToken, offeredByPartyId, org, app); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'privUserHasScopeAccessForApp - status is 200': (r) => r.status === 200, + 'privUserHasScopeAccessForApp - rightskey is apps-test-tba,ttd:ScopeAccess': (r) => r.json('0.rightKey') === 'apps-test-tba,ttd:ScopeAccess', + 'privUserHasScopeAccessForApp - resource org id is urn:altinn:org': (r) => r.json('0.resource.0.id') === 'urn:altinn:org', + 'privUserHasScopeAccessForApp - resource org value is ttd': (r) => r.json('0.resource.0.value') == org, + 'privUserHasScopeAccessForApp - resource app id is urn:altinn:app': (r) => r.json('0.resource.1.id') === 'urn:altinn:app', + 'privUserHasScopeAccessForApp - resource app value is apps-test': (r) => r.json('0.resource.1.value') == app, + 'privUserHasScopeAccessForApp - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'privUserHasScopeAccessForApp - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'privUserHasScopeAccessForApp - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'privUserHasScopeAccessForApp - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'daglForOrgHasScopeAccessForApp - RoleRequirementsMatches value is PRIV': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'PRIV', +}); +addErrorCount(success); +} + +/** Checks that DAGl for an org can not delegate an Altinn3 app that requires PRIV role */ +export function daglStatusIsNotDelegableForPrivApp() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const org = 'ttd'; + const app = 'apps-test-tba'; + var res = userDelegationCheck.appUserDelegationCheck(offeredByToken, offeredByPartyId, org, app); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'daglStatusIsNotDelegableForPrivApp - status is 200': (r) => r.status === 200, + 'daglStatusIsNotDelegableForPrivApp - rightskey is apps-test-tba,ttd:ScopeAccess': (r) => r.json('0.rightKey') === 'apps-test-tba,ttd:ScopeAccess', + 'daglStatusIsNotDelegableForPrivApp - resource org id is urn:altinn:org': (r) => r.json('0.resource.0.id') === 'urn:altinn:org', + 'daglStatusIsNotDelegableForPrivApp - resource org value is ttd': (r) => r.json('0.resource.0.value') == org, + 'daglStatusIsNotDelegableForPrivApp - resource app id is urn:altinn:app': (r) => r.json('0.resource.1.id') === 'urn:altinn:app', + 'daglStatusIsNotDelegableForPrivApp - resource app value is apps-test': (r) => r.json('0.resource.1.value') == app, + 'daglStatusIsNotDelegableForPrivApp - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'daglStatusIsNotDelegableForPrivApp - action value is ScopeAccess': (r) => r.json('0.action.value') == 'ScopeAccess', + 'daglStatusIsNotDelegableForPrivApp - status is NotDelegable': (r) => r.json('0.status') == 'NotDelegable', + 'daglStatusIsNotDelegableForPrivApp - code is MissingRoleAccess': (r) => r.json('0.details.0.code') == 'MissingRoleAccess', + 'daglStatusIsNotDelegableForPrivApp - RequiredRoles id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RequiredRoles.0.id') == 'urn:altinn:rolecode', + 'daglStatusIsNotDelegableForPrivApp - RequiredRoles value is PRIV': (r) => r.json('0.details.0.parameters.RequiredRoles.0.value') == 'PRIV', + 'daglStatusIsNotDelegableForPrivApp - RequiredRoles id is urn:altinn:org': (r) => r.json('0.details.0.parameters.RequiredRoles.1.id') == 'urn:altinn:org', + 'daglStatusIsNotDelegableForPrivApp - RequiredRoles value is ttd': (r) => r.json('0.details.0.parameters.RequiredRoles.1.value') == 'ttd', +}); +addErrorCount(success); +} + +/** Checks that DAGl for an org has ScopeAccess for the altinn2 service ACC Security level 2 MAG */ +export function daglForOrgHasScopeAccessForAltinn2Service() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.dagl.partyid; + const serviceCode = '2802'; + const serviceEditionCode = '2203'; + var res = userDelegationCheck.altinn2ServiceUserDelegationCheck(offeredByToken, offeredByPartyId, serviceCode, serviceEditionCode); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'daglForOrgHasScopeAccessForAltinn2Service - status is 200': (r) => r.status === 200, + 'daglForOrgHasScopeAccessForAltinn2Service - rightskey is 2802:2203:read': (r) => r.json('0.rightKey') === '2802:2203:read', + 'daglForOrgHasScopeAccessForAltinn2Service - resource id is urn:altinn:servicecode': (r) => r.json('0.resource.0.id') === 'urn:altinn:servicecode', + 'daglForOrgHasScopeAccessForAltinn2Service - servicecode is 3225': (r) => r.json('0.resource.0.value') == serviceCode, + 'daglForOrgHasScopeAccessForAltinn2Service - resource id is urn:altinn:serviceeditioncode': (r) => r.json('0.resource.1.id') === 'urn:altinn:serviceeditioncode', + 'daglForOrgHasScopeAccessForAltinn2Service - serviceeditioncoee is 536': (r) => r.json('0.resource.1.value') == serviceEditionCode, + 'daglForOrgHasScopeAccessForAltinn2Service - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'daglForOrgHasScopeAccessForAltinn2Service - action value is read': (r) => r.json('0.action.value') == 'read', + 'daglForOrgHasScopeAccessForAltinn2Service - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'daglForOrgHasScopeAccessForAltinn2Service - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'daglForOrgHasScopeAccessForAltinn2Service - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'daglForOrgHasScopeAccessForAltinn2Service - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'UTINN', +}); +addErrorCount(success); +} + +/** Checks that a PRIV user has ScopeAccess for the altinn2 service ACC Security level 2 MAG */ +export function privUserHasScopeAccessForAltinn2Service() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const serviceCode = '2802'; + const serviceEditionCode = '2203'; + var res = userDelegationCheck.altinn2ServiceUserDelegationCheck(offeredByToken, offeredByPartyId, serviceCode, serviceEditionCode); + console.log(res.status); + console.log(res.body); + + // Assert +var success = check(res, { + 'privUserHasScopeAccessForAltinn2Service - status is 200': (r) => r.status === 200, + 'privUserHasScopeAccessForAltinn2Service - rightskey is 2802:2203:read': (r) => r.json('0.rightKey') === '2802:2203:read', + 'privUserHasScopeAccessForAltinn2Service - resource id is urn:altinn:servicecode': (r) => r.json('0.resource.0.id') === 'urn:altinn:servicecode', + 'privUserHasScopeAccessForAltinn2Service - servicecode is 3225': (r) => r.json('0.resource.0.value') == serviceCode, + 'privUserHasScopeAccessForAltinn2Service - resource id is urn:altinn:serviceeditioncode': (r) => r.json('0.resource.1.id') === 'urn:altinn:serviceeditioncode', + 'privUserHasScopeAccessForAltinn2Service - serviceeditioncoee is 536': (r) => r.json('0.resource.1.value') == serviceEditionCode, + 'privUserHasScopeAccessForAltinn2Service - action id is urn:oasis:names:tc:xacml:1.0:action:action-id': (r) => r.json('0.action.id') == 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'privUserHasScopeAccessForAltinn2Service - action value is read': (r) => r.json('0.action.value') == 'read', + 'privUserHasScopeAccessForAltinn2Service - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'privUserHasScopeAccessForAltinn2Service - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'privUserHasScopeAccessForAltinn2Service - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'privUserHasScopeAccessForAltinn2Service - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'UTINN', +}); +addErrorCount(success); +} + +export function handleSummary(data) { + let result = {}; + result[reportPath('userdelegationcheck.xml')] = generateJUnitXML(data, 'access-management-rights-delegations-userdelegationcheck'); + return result; +} \ No newline at end of file diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/delegationsv2.js b/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/delegationsv2.js new file mode 100644 index 00000000..43ce5382 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/delegationsv2.js @@ -0,0 +1,348 @@ +/* + Test data required: deployed app (reference app: ttd/apps-test) + Username and password for a user with the DAGL role for an organization (user1 and user2) + Org number for user2's org + Command: docker-compose run k6 run /src/tests/platform/authorization/delegations/delegationsv2.js + -e env=*** -e tokengenuser=*** -e tokengenuserpwd=*** -e appsaccesskey=*** + -e showresults=*** + +*/ +import { check, sleep, fail } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../../errorcounter.js'; +import { generateToken } from '../../api/altinn-testtools/token-generator.js'; +import { generateJUnitXML, reportPath } from '../../report.js'; +import * as delegation from '../../api/platform/authorization/delegations.js'; +import * as helper from '../../Helpers/TestdataHelper.js'; + +let pdpInputJson = open('../../data/pdpinput.json'); + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; + +let testDataFile = open(`../../data/testdata/delegations/${environment}testdata.json`); +var testdata = JSON.parse(testDataFile); +var org1; +var org2; +var org3; +var token; +var org; +var app; +var showResults; + +export const options = { + thresholds: { + errors: ['count<1'], + }, + setupTimeout: '1m', +}; + +export function setup() { + var tokenGenParams = { + env: environment, + app: 'sbl.authorization', + }; + + testdata.token = generateToken('platform', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + return testdata; + +} + +//Tests for platform Authorization:Delegations:Inheritance +export default function (data) { + org1 = data.org1; + org2 = data.org2; + org3 = data.org3; + token = data.token; + org = data.org; + app = data.app; + showResults = 0; + + CleanupBeforeTests(); + + //tests + getPolicyOfAnApp(); + addReadAccessToUserThenDeleteIt(); + addGetDeleteRuleAndCheckDecisions(); + delegateTwoRulesInOneRequest(); + delegateTwoRulesPartialSuccess(); + delegateRuleToAUserAndOrg(); +} + +export function CleanupBeforeTests() { + helper.deleteAllRules(token, org1.dagl.userid, org1.partyid, org2.dagl.userid, 'userid', org, app); + helper.deleteAllRules(token, org1.dagl.userid, org1.partyid, org2.partyid, 'partyid', org, app); +} + +/** Retrieve policy of an app */ +export function getPolicyOfAnApp() { + var resources = [{ appOwner: org, appName: app }]; + var res = delegation.getPolicies(resources); + var success = check(res, { + 'GET app policy - status is 200': (r) => r.status === 200, + }); + addErrorCount(success); + if(showResults == 1) { console.log('getPolicyOfAnApp: ' + success) } +} + +/** Add read access to a user for app in a particular task */ +export function addReadAccessToUserThenDeleteIt() { + // Arrange + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + + // Act + var res = delegation.addRules(token, policyMatchKeys, performedByUserId, offeredByPartyId, coveredByUserId, org, app, 'Task_1', 'read'); + var success = check(res, { + 'Add delegation rule - status is 201': (r) => r.status === 201, + 'Add delegation rule - rule id is not empty': (r) => r.json('0.ruleId') != null, + 'Add delegation rule - createdSuccessfully is true': (r) => r.json('0.createdSuccessfully') === true, + 'Add delegation rule - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'Add delegation rule - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByUserId.toString(), + }); + + // Assert + addErrorCount(success); + stopIterationOnFail('Add delegation rule Failed', success, res); + var ruleId = res.json('0.ruleId'); + sleep(3); + + // Act (deletion) + res = delegation.deleteRules(token, policyMatchKeys, [ruleId], performedByUserId, offeredByPartyId, coveredByUserId, org, app, 'Task_1', 'read'); + + // Assert (deletion) + success = check(res, { + 'Delete delegated rule - status is 200': (r) => r.status === 200, + }); + addErrorCount(success); + if(showResults == 1) { console.log('addReadAccessToUserThenDeleteIt: ' + success) } +} + +/** Deleting a non existing rules fails */ +export function deletingNonExistingRuleFails() { + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + + var res = delegation.deleteRules(token, policyMatchKeys, ['12345678-a1b2-1234-1a23-1234a56b78c9'], org1.dagl.userid, org1.partyid, org2.dagl.userid, org, app, 'Task_1', 'read'); + var success = check(res, { + 'Delete a not existing rule - status is 400': (r) => r.status === 400, + }); + addErrorCount(success); + if(showResults == 1) { console.log('deletingNonExistingRuleFails: ' + success) } +} + +/** Rules cannot be delegated with invalid app details */ +export function addingRuleWithInvalidValuesFails() { + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + var res = delegation.addRules(token, policyMatchKeys, org1.dagl.userid, org1.partyid, org2.dagl.userid, org, app, 'test', 'Task_1', 'read'); + var success = check(res, { + 'Add delegation rule for an invalid app - status is 400': (r) => r.status === 400, + 'Add delegation rule for an invalid app - failed': (r) => r.body == 'Delegation could not be completed', + }); + addErrorCount(success); + if(showResults == 1) { console.log('addRuleWithInvalidValuesFails: ' + success) } +} + +export function addGetDeleteRuleAndCheckDecisions() { + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + + var resources = [{ appOwner: org, appName: app }]; + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org', 'urn:altinn:task'], + }; + //add a rule to give write access + var res = delegation.addRules(token, policyMatchKeys, performedByUserId, offeredByPartyId, coveredByUserId, org, app, 'Task_1', 'write'); + var ruleId = res.json('0.ruleId'); + sleep(3); + + //Retrieve all the rules that are delegated to an user from a party + policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + var success = check(res, { + 'Get delegated rule - status is 200': (r) => r.status === 200, + 'Get delegated rule - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Get delegated rule - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Get delegated rule - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'Get delegated rule - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByUserId.toString(), + 'Get delegated rule - type is 1': (r) => r.json('0.type') === 1, + }); + addErrorCount(success); + + //Delete all the delegated rules from an user by a party + res = delegation.deletePolicy(token, policyMatchKeys, performedByUserId, offeredByPartyId, coveredByUserId, org, app, null); + success = check(res, { + 'Delete delegated policy with all rules - status is 200': (r) => r.status === 200, + }); + addErrorCount(success); + sleep(3); + + //Get rules that are deleted where response should be an empty array + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + success = check(res, { + 'Get deleted rules - status is 200': (r) => r.status === 200, + 'Get deleted rules - response is empty': (r) => r.json().length === 0, + }); + addErrorCount(success); +} + +export function delegateTwoRulesInOneRequest() { + // Arrange + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var resources = [{ appOwner: org, appName: app }]; + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + var rulesList = []; + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'read', org, app)); + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'write', org, app)); + + // Act + var res = delegation.addMultipleRules(token, rulesList); + + // Assert + var success = check(res, { + 'Add multiple rules success - status is 201': (r) => r.status === 201, + 'Add multiple rules success - rule 1 created successfully is true': (r) => r.json('0.createdSuccessfully') === true, + 'Add multiple rules success - rule 2 created successfully is true': (r) => r.json('1.createdSuccessfully') === true + }); + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByUserId, 'userid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + success = check(res, { + 'Direct delegation from org to org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from org to org - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('delegateTwoRulesInOneRequest:' + success)} + sleep(3); + +} + +export function delegateTwoRulesPartialSuccess() { + + // Arrange + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var resources = [{ appOwner: org, appName: app }]; + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + var rulesList = []; + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'read','ttd','nonExistentApp', org, app)); + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'write', org, app)); + + // Act + var res = delegation.addMultipleRules(token, rulesList); + + // Assert + var success = check(res, { + 'Add multiple rules partial - status is 206': (r) => r.status === 206, + 'Add multiple rules partial - rule 1 created successfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Add multiple rules partial - rule 2 created successfully is true': (r) => r.json('1.createdSuccessfully') === true + }); + + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByUserId, 'userid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + success = check(res, { + 'Direct delegation from org to org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from org to org - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('delegateTwoRulesPartialSuccess:' + success)} + sleep(3); + +} + +export function delegateRuleToAUserAndOrg() { + + // Arrange + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var resources = [{ appOwner: org, appName: app }]; + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + const coveredByPartyId =org2.partyid; + var rulesList = []; + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'read', org, app)); + rulesList.push(helper.generateDataForAddMultipleRules(performedByUserId, offeredByPartyId, coveredByPartyId, 'partyid', 'Task_1', 'read', org, app)); + + // Act + var res = delegation.addMultipleRules(token, rulesList); + + // Assert + var success = check(res, { + 'Add multiple rules user and org - status is 201': (r) => r.status === 201, + 'Add multiple rules user and org - rule 1 created successfully is true': (r) => r.json('0.createdSuccessfully') === true, + 'Add multiple rules user and org - rule 2 created successfully is true': (r) => r.json('1.createdSuccessfully') === true + }); + + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByUserId, 'userid', org, app); + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByPartyId, 'partyid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + success = check(res, { + 'Delegate Rule To a User and Org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Delegate Rule To a User and Org - rules successfully deleted, body is empty (coveredByUserId)': (r) => r.body.includes('[]'), + }); + policyMatchKeys.coveredBy = 'urn:altinn:partyid' + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByPartyId, resources, null, null); + success = check(res, { + 'Delegate Rule To a User and Org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Delegate Rule To a User and Org - rules successfully deleted, body is empty (coveredByPartyId)': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('delegateRuleToAUserAndOrg:' + success)} + sleep(3); + +} + + +export function handleSummary(data) { + let result = {}; + result[reportPath('authzDelegationsv2.xml')] = generateJUnitXML(data, 'platform-authorization-delegation-delegations-v2'); + return result; +} + +export function showTestData() { + console.log('environment: ' + environment); + console.log('org1.orgno ' + org1.orgno); + console.log('org1.partyid ' + org1.partyid); + console.log('org2.orgno ' + org2.orgno); + console.log('org2.partyid ' + org2.partyid); + console.log('org1.dagl.userid ' + org1.dagl.userid); + console.log('org1.dagl.partyid ' + org1.dagl.partyid); + console.log('org2.dagl.userid ' + org2.dagl.userid); + console.log('org2.dagl.partyid ' + org2.dagl.partyid); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/inheritancev2.js b/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/inheritancev2.js new file mode 100644 index 00000000..e15aa903 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/tests/delegations/inheritancev2.js @@ -0,0 +1,365 @@ +/* + Test data required: deployed app (reference app: ttd/apps-test) + Username and password for a user with the DAGL role for an organization (user1 and user2) + Username and password for a user with the DAGL role for an organization with subunits (user3) + Username, password, and org number for an enterprise user (ecusername, ecuserpwd, ecuserorgno) + Org number for user2's org (same as org number for the enterprise user) + Command: docker-compose run k6 run /src/tests/platform/authorization/delegations/inheritancev2.js + -e env=*** -e tokengenuser=*** -e tokengenuserpwd=*** -e appsaccesskey=*** +*/ +import { check, sleep, fail } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../../errorcounter.js'; +import * as delegation from '../../api/platform/authorization/delegations.js'; +import { generateToken } from '../../api/altinn-testtools/token-generator.js'; +import { generateJUnitXML, reportPath } from '../../report.js'; +import * as helper from '../../Helpers/TestdataHelper.js'; + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; + +let testDataFile = open(`../../data/testdata/delegations/${environment}testdata.json`); +var testdata = JSON.parse(testDataFile); +var org1; +var org2; +var org3; +var token; +var org; +var app; +var showResults; + +export const options = { + thresholds: { + errors: ['count<1'], + }, + setupTimeout: '1m', +}; + +export function setup() { + var tokenGenParams = { + env: environment, + app: 'sbl.authorization', + }; + + testdata.token = generateToken('platform', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + return testdata; + +} + +//Tests for platform Authorization:Delegations:Inheritance +export default function (data) { + org1 = data.org1; + org2 = data.org2; + org3 = data.org3; + token = data.token; + org = data.org; + app = data.app; + showResults = 0; + + CleanupBeforeTests(); + + //tests + directDelegationFromOrgToUser(); + directDelegationFromOrgToOrg(); + directDelegationFromMainUnitToUser(); + directDelegationFromMainUnitToOrg(); + directDelegationFromMainUnitToOrgInheritedByDAGLViaKeyRole(); + delegationToOrgIsInheritedByECUserViaKeyrole(); +} + +export function CleanupBeforeTests() { + helper.deleteAllRules(token, org1.dagl.userid, org1.partyid, org2.dagl.userid, 'userid', org, app); + helper.deleteAllRules(token, org1.dagl.userid, org1.partyid, org2.partyid, 'partyid', org, app); + helper.deleteAllRules(token, org3.dagl.userid, org3.partyid, org2.dagl.userid, 'userid', org, app); + helper.deleteAllRules(token, org3.dagl.userid, org3.partyid, org2.partyid, 'partyid', org, app); +} + +/** + * Tests that an organization (org1) can successfully delegate directly to a user (user2) + */ +export function directDelegationFromOrgToUser() { + // Arrange + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByUserId = org2.dagl.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByPartyId, coveredByUserId, 'userid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + + // Assert + var success = check(res, { + 'Direct delegation from org to user - status is 200': (r) => r.status === 200, + 'Direct delegation from org to user - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Direct delegation from org to user - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Direct delegation from org to user - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'Direct delegation from org to user - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:userid', + 'Direct delegation from org to user - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByUserId.toString(), + 'Direct delegation from org to user - type is 1': (r) => r.json('0.type') === 1, + }); + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByUserId, 'userid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByUserId, resources, null, null); + success = check(res, { + 'Direct delegation from org to user - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from org to user - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('directDelegationFromOrgToUser:' + success)} + + sleep(3); +} + +/** + * Tests that an organization (org1) can successfully delegate directly to another organization (org2) + */ +export function directDelegationFromOrgToOrg() { + // Arrange + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByPartyId = org2.partyid; + const DAGLUserIdForCoveredBy= org2.dagl.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByPartyId, coveredByPartyId, 'partyid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:partyid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByPartyId, resources, null, null); + + + // Assert + var success = check(res, { + 'Direct delegation from org to org - status is 200': (r) => r.status === 200, + 'Direct delegation from org to org - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Direct delegation from org to org - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Direct delegation from org to org - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'Direct delegation from org to org - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:partyid', + 'Direct delegation from org to org - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByPartyId.toString(), + 'Direct delegation from org to org - type is 1': (r) => r.json('0.type') === 1, + }); + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByPartyId, coveredByPartyId, 'partyid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, coveredByPartyId, resources, null, null); + success = check(res, { + 'Direct delegation from org to org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from org to org - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('directDelegationFromOrgToOrg:' + success)} + sleep(3); +} + +/** + * Tests that when an organization (org3) delegates to a user (user2), that user also has access to the organization's subunit (org4) + */ +export function directDelegationFromMainUnitToUser() { + // Arrange + const performedByUserId = org3.dagl.userid; + const offeredByParentPartyId = org3.partyid; + const subUnitPartyId = org3.subunit.orgno; + const coveredByUserId = org2.dagl.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByParentPartyId, coveredByUserId, 'userid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, coveredByUserId, resources, offeredByParentPartyId, null); + + // Assert + var success = check(res, { + 'Direct delegation from mainunit to user - status is 200': (r) => r.status === 200, + 'Direct delegation from mainunit to user - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Direct delegation from mainunit to user - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Direct delegation from mainunit to user - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByParentPartyId, + 'Direct delegation from mainunit to user - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:userid', + 'Direct delegation from mainunit to user - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByUserId.toString(), + 'Direct delegation from mainunit to user - type is 3': (r) => r.json('0.type') === 3, + }); + addErrorCount(success); + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByParentPartyId, coveredByUserId, 'userid', org, app); + res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, coveredByUserId, resources, offeredByParentPartyId, null); + success = check(res, { + 'Direct delegation from mainunit to user - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from mainunit to user - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('directDelegationFromMainUnitToUser:' + success)} + sleep(3); +} + +/** + * Tests that when an organization (org3) delegates to another org (org2), that the DAGL of that org also has access to the subunit (org4) + */ +export function directDelegationFromMainUnitToOrg() { + // Arrange + const performedByUserId = org3.dagl.userid; + const offeredByParentPartyId = org3.partyid; + const subUnitPartyId = org3.subunit.orgno; + const coveredByPartyId = org2.partyid; + const DAGLUserIdForCoveredBy= org2.dagl.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByParentPartyId, coveredByPartyId, 'partyid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:partyid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, coveredByPartyId, resources, offeredByParentPartyId, null); + + // Assert + var success = check(res, { + 'Direct delegation from mainunit to org - status is 200': (r) => r.status === 200, + 'Direct delegation from mainunit to org - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Direct delegation from mainunit to org - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Direct delegation from mainunit to org - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByParentPartyId, + 'Direct delegation from mainunit to org - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:partyid', + 'Direct delegation from mainunit to org - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByPartyId.toString(), + 'Direct delegation from mainunit to org - type is 3': (r) => r.json('0.type') === 3, + }); + addErrorCount(success); + + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByParentPartyId, coveredByPartyId, 'partyid', org, app); + res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, coveredByPartyId, resources, offeredByParentPartyId, null); + success = check(res, { + 'Direct delegation from mainunit to org - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Direct delegation from mainunit to org - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('directDelegationFromMainUnitToOrg:' + success)} + sleep(3); +} + +/** + * Tests that when an organization (org3) delegates to another org (org2), that the DAGL of that org also has access to the subunit (org4) + */ +export function directDelegationFromMainUnitToOrgInheritedByDAGLViaKeyRole() { + // Arrange + const performedByUserId = org3.dagl.userid; + const offeredByParentPartyId = org3.partyid; + const subUnitPartyId = org3.subunit.orgno; + const coveredByPartyId = org2.partyid; + const DAGLUserIdForCoveredBy= org2.dagl.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByParentPartyId, coveredByPartyId, 'partyid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, DAGLUserIdForCoveredBy, resources, offeredByParentPartyId, [coveredByPartyId]); + // Assert + var success = check(res, { + 'mainunit to org inherited by DAGL via keyrole - status is 200': (r) => r.status === 200, + 'mainunit to org inherited by DAGL via keyrole - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'mainunit to org inherited by DAGL via keyrole - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'mainunit to org inherited by DAGL via keyrole - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByParentPartyId, + 'mainunit to org inherited by DAGL via keyrole - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:partyid', + 'mainunit to org inherited by DAGL via keyrole - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByPartyId.toString(), + 'mainunit to org inherited by DAGL via keyrole - type is 4': (r) => r.json('0.type') === 4, + }); + addErrorCount(success); + + + // Cleanup + helper.deleteAllRules(token, performedByUserId, offeredByParentPartyId, coveredByPartyId, 'partyid', org, app); + res = delegation.getRules(token, policyMatchKeys, subUnitPartyId, DAGLUserIdForCoveredBy, resources, offeredByParentPartyId, [coveredByPartyId]); + success = check(res, { + 'mainunit to org inherited by DAGL via keyrole - rules successfully deleted, status is 200': (r) => r.status == 200, + 'mainunit to org inherited by DAGL via keyrole - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('directDelegationFromMainUnitToOrgInheritedByDAGLViaKeyRole:' + success)} + sleep(3); +} + +/** + * Verifies that when a delegation is made from one org (org1) to another (org2), the Enterprise Certificate user (ECUser) for that organization is also given access + */ +export function delegationToOrgIsInheritedByECUserViaKeyrole() { + // Arrange + const performedByUserId = org1.dagl.userid; + const offeredByPartyId = org1.partyid; + const coveredByPartyId = org2.partyid; + const ecUserIdForCoveredBy= org2.ecuser.userid; + var resources = [{ appOwner: org, appName: app }]; + var ruleId = helper.addRulesForTest(token, performedByUserId, offeredByPartyId, coveredByPartyId, 'partyid', 'Task_1', 'read', org, app); + + // Act + var policyMatchKeys = { + coveredBy: 'urn:altinn:userid', + resource: ['urn:altinn:app', 'urn:altinn:org'], + }; + var res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, ecUserIdForCoveredBy, resources, null, [coveredByPartyId]); + + // Assert + var success = check(res, { + 'Delegation to Org is inherited by ECUser via keyrole - status is 200': (r) => r.status === 200, + 'Delegation to Org is inherited by ECUser via keyrole - rule id matches': (r) => r.json('0.ruleId') === ruleId, + 'Delegation to Org is inherited by ECUser via keyrole - createdSuccessfully is false': (r) => r.json('0.createdSuccessfully') === false, + 'Delegation to Org is inherited by ECUser via keyrole - offeredByPartyId matches': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'Delegation to Org is inherited by ECUser via keyrole - coveredBy is userid': (r) => r.json('0.coveredBy.0.id') === 'urn:altinn:partyid', + 'Delegation to Org is inherited by ECUser via keyrole - coveredBy matches': (r) => r.json('0.coveredBy.0.value') === coveredByPartyId.toString(), + 'Delegation to Org is inherited by ECUser via keyrole - type is 2': (r) => r.json('0.type') === 2, + }); + addErrorCount(success); + + // Cleanup + policyMatchKeys.coveredBy = 'urn:altinn:partyid'; + helper.deleteAllRules(token, org1.dagl.userid, org1.partyid, org2.partyid, 'partyid', org, app); + res = delegation.getRules(token, policyMatchKeys, offeredByPartyId, ecUserIdForCoveredBy, resources, null, [coveredByPartyId]); + success = check(res, { + 'Delegation to Org is inherited by ECUser via keyrole - rules successfully deleted, status is 200': (r) => r.status == 200, + 'Delegation to Org is inherited by ECUser via keyrole - rules successfully deleted, body is empty': (r) => r.body.includes('[]'), + }); + addErrorCount(success); + if(showResults == 1) {console.log('delegationToOrgIsInheritedByECUserViaKeyrole:' + success)} +} + +export function handleSummary(data) { + let result = {}; + result[reportPath('authzDelegationInheritancev2.xml')] = generateJUnitXML(data, 'platform-authorization-delegation-inheritance-v2'); + return result; +} + +export function showTestData() { + console.log('environment: ' + environment); + // console.log('altinnBuildVersion: ' + altinnBuildVersion); + console.log('org1.orgno ' + org1.orgno); + console.log('org1.partyid ' + org1.partyid); + console.log('org2.orgno ' + org2.orgno); + console.log('org2.partyid ' + org2.partyid); + console.log('org3.orgno ' + org3.orgno); + console.log('org3.partyid ' + org3.partyid); + console.log('org3.subunit.orgno ' + org3.subunit.orgno); + console.log('org3.subunit.orgno ' + org3.subunit.orgno); + console.log('org1.dagl.userid ' + org1.dagl.userid); + console.log('org1.dagl.partyid ' + org1.dagl.partyid); + console.log('org2.dagl.userid ' + org2.dagl.userid); + console.log('org2.dagl.partyid ' + org2.dagl.partyid); + console.log('org3.dagl.userid ' + org3.dagl.userid); + console.log('org3.dagl.partyid ' + org3.dagl.partyid); + console.log('org2.ecuser.userid ' + org2.ecuser.userid); + console.log('org2.ecuser.partyid ' + org2.ecuser.partyid); + console.log('token: ' + token); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/tests/maskinporten/maskinporten.js b/src/apps/Altinn.AccessManagement/test/K6/src/tests/maskinporten/maskinporten.js new file mode 100644 index 00000000..78adf3d9 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/tests/maskinporten/maskinporten.js @@ -0,0 +1,690 @@ +/* + Test data required: deployed app (reference app: ttd/apps-test) + userid, partyid for two users that are DAGL for two orgs, and partyid and orgno for those orgs (user1 and user2) + Org number for user2's org +docker-compose run k6 run /src/tests/maskinporten/maskinporten.js -e env=*** -e tokengenuser=*** -e tokengenuserpwd=*** -e appsaccesskey=*** + + +*/ +import { check, sleep, fail } from 'k6'; +import { addErrorCount, stopIterationOnFail } from '../../../errorcounter.js'; +import { generateToken } from '../../../api/altinn-testtools/token-generator.js'; +import { generateJUnitXML, reportPath } from '../../../report.js'; +import * as maskinporten from '../../../api/access-management/maskinporten/maskinporten.js'; + +const environment = __ENV.env.toLowerCase(); +const tokenGeneratorUserName = __ENV.tokengenuser; +const tokenGeneratorUserPwd = __ENV.tokengenuserpwd; +let testdataFile = open(`../../../data/testdata/maskinportenschema/${__ENV.env}testdata.json`); +var testdata = JSON.parse(testdataFile); +var org1; +var org2; + +export const options = { + thresholds: { + errors: ['count<1'], + }, + setupTimeout: '1m', +}; + +export function setup() { + + //generate personal token for user 1 (DAGL for org1) + var tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.dagl.pid, + userid: testdata.org1.dagl.userid, + partyid: testdata.org1.dagl.partyid, + authLvl: 3, + }; + testdata.org1.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org2.dagl.pid, + userid: testdata.org2.dagl.userid, + partyid: testdata.org2.dagl.partyid, + authLvl: 3, + }; + testdata.org2.dagl.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.hadm.pid, + userid: testdata.org1.hadm.userid, + partyid: testdata.org1.hadm.partyid, + authLvl: 3, + }; + testdata.org1.hadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + tokenGenParams = { + env: environment, + scopes: 'altinn:instances.read', + pid: testdata.org1.apiadm.pid, + userid: testdata.org1.apiadm.userid, + partyid: testdata.org1.apiadm.partyid, + authLvl: 3, + }; + testdata.org1.apiadm.token = generateToken('personal', tokenGeneratorUserName, tokenGeneratorUserPwd, tokenGenParams); + + return testdata; +} + +export default function (data) { + if (!data) { + return; + } + org1 = data.org1; + org2 = data.org2; + + //tests + postMaskinportenSchemaToOrgNumberTest(); + postMaskinportenSchemaToPartyIdTest(); + // postMaskinportenSchemaWithOrgNoInHeaderTest(); // Uncomment when #400 "post maskinportenschema with orgno in header returns 403" has been fixed + postMaskinportenSchemaAsHadmTest(); + postMaskinportenSchemaAsApiadmTest(); + postMaskinportenCannotDelegateToPersonTest(); + postMaskinportenDAGLCannotDelegateNUFResource(); + postMaskinportenSystemResourceCannotBeDelegatedTest(); + getMaskinPortenSchemaOfferedInvalidPartyId(); + getMaskinPortenSchemaReceivedInvalidPartyId(); + postMaskinportenSchemaNotReadyTest(); + getMaskinPortenSchemaOfferedTest(); + getMaskinPortenSchemaReceivedTest(); + revokeOfferedMaskinPortenSchema(); + revokeReceivedMaskinPortenSchema(); + revokeOfferedMaskinPortenSchemaUsingPartyId(); + revokeReceivedMaskinPortenSchemaUsingPartyId(); + revokeNonExistentOfferedMaskinPortenSchema(); + revokeNonExistentReceivedMaskinPortenSchema(); + delegationCheckMaskinPortenSchema_DAGLhasScopeAccess(); + delegationCheckMaskinPortenSchema_HADMhasScopeAccess(); + delegationCheckMaskinPortenSchema_resourceDoesNotExist(); + delegationCheckMaskinPortenSchema_tooLowAuthLevel(); + +} + +/** Check that list of offered maschinportenschemas is correct */ +export function getMaskinPortenSchemaOfferedTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6-nuf'; + var res = maskinporten.revokeOfferedMaskinportenSchema(org1.dagl.token, org1.partyid, 'ttd-am-k6', 'urn:altinn:organizationnumber', org2.orgno); + + // Act + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + + // Assert + var success = check(res, { + 'get offered MaskinPortenSchemas - status is 200': (r) => r.status === 200, + 'get offered MaskinPortenSchemas - coveredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.coveredByName') === 'LARKOLLEN OG FAUSKE', + 'get offered MaskinPortenSchemas - offeredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.offeredByName') === 'ALDRA OG FORTUN', + 'get offered MaskinPortenSchemas - offeredByPartyId is ${offeredByPartyId}': (r) => r.json('0.offeredByPartyId') == offeredByPartyId, + 'get offered MaskinPortenSchemas - coveredByPartyId is ${coveredByPartyId}': (r) => r.json('0.coveredByPartyId') == org2.partyid, + 'get offered MaskinPortenSchemas - performedByUserId is ${performedByUserId}': (r) => r.json('0.performedByUserId') == org1.dagl.userid, + 'get offered MaskinPortenSchemas - offeredByOrganizationNumber is ${offeredByOrganizationNumber}': (r) => r.json('0.offeredByOrganizationNumber') == org1.orgno, + 'get offered MaskinPortenSchemas - coveredByOrganizationNumber is ${coveredByOrganizationNumber}': (r) => r.json('0.coveredByOrganizationNumber') == org2.orgno, + 'get offered MaskinPortenSchemas - resourceId is ttd-am-k6-nuf': (r) => r.json('0.resourceId') == appid, + }); + addErrorCount(success); +} + +/** Check that you can't get offered schemas using the wrong partyid */ +export function getMaskinPortenSchemaOfferedInvalidPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const wrongOfferedByPartyId = org2.partyid; + + // Act + var res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, wrongOfferedByPartyId); + + // Assert + var success = check(res, { + 'get offered MaskinPortenSchemas with invalid partyid- status is 403 forbidden': (r) => r.status === 403, + }); + addErrorCount(success); +} + +/** Check that list of received maschinportenschemas is correct */ +export function getMaskinPortenSchemaReceivedTest() { + // Arrange + const toToken = org2.dagl.token; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6-nuf'; + var res = maskinporten.revokeOfferedMaskinportenSchema(org1.dagl.token, org1.partyid, 'ttd-am-k6', 'urn:altinn:organizationnumber', org2.orgno); + + // Act + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + + // Assert + var success = check(res, { + 'get Received MaskinPortenSchemas - status is 200': (r) => r.status === 200, + 'get Received MaskinPortenSchemas - offeredByName is ALDRA OG FORTUN': (r) => r.json('0.offeredByName') === 'ALDRA OG FORTUN', + 'get Received MaskinPortenSchemas - coveredByName is LARKOLLEN OG FAUSKE': (r) => r.json('0.coveredByName') === 'LARKOLLEN OG FAUSKE', + 'get Received MaskinPortenSchemas - offeredByPartyId is ${offeredByPartyId}': (r) => r.json('0.offeredByPartyId') == org1.partyid, + 'get Received MaskinPortenSchemas - coveredByPartyId is ${coveredByPartyId}': (r) => r.json('0.coveredByPartyId') == org2.partyid, + 'get Received MaskinPortenSchemas - performedByUserId is ${performedByUserId}': (r) => r.json('0.performedByUserId') == org1.dagl.userid, + 'get Received MaskinPortenSchemas - offeredByOrganizationNumber is ${offeredByOrganizationNumber}': (r) => r.json('0.offeredByOrganizationNumber') == org1.orgno, + 'get Received MaskinPortenSchemas - coveredByOrganizationNumber is ${coveredByOrganizationNumber}': (r) => r.json('0.coveredByOrganizationNumber') == org2.orgno, + 'get Received MaskinPortenSchemas - resourceId is ttd-am-k6-nuf': (r) => r.json('0.resourceId') == appid, + + }); + addErrorCount(success); +} + +/** Check that you can't get received schemas using the wrong partyid */ +export function getMaskinPortenSchemaReceivedInvalidPartyId() { + // Arrange + const toToken = org1.dagl.token; + const wrongToPartyId = org2.partyid; + + // Act + var res = maskinporten.getMaskinportenSchemaOffered(toToken, wrongToPartyId); + + // Assert + var success = check(res, { + 'get received MaskinPortenSchemas with invalid partyid- status is 403 forbidden': (r) => r.status === 403, + }); + addErrorCount(success); +} + +/** offer a maskinportenschema using a party id */ +export function postMaskinportenSchemaToPartyIdTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema To PartyId - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema To PartyId - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema To PartyId - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema To PartyId - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema To PartyId - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema To PartyId - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema To PartyId - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema using an organization number */ +export function postMaskinportenSchemaToOrgNumberTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'post MaskinportenSchema To Org Number - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema To Org Number - to id is organizationnumber': (r) => r.json('to.0.id') === 'urn:altinn:organizationnumber', + 'post MaskinportenSchema To Org Number - organization number matches': (r) => r.json('to.0.value') === toOrgNumber, + 'post MaskinportenSchema To Org Number - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema To Org Number - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema To Org Number - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema To Org Number - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema using the offeredby's organization number in the header */ +export function postMaskinportenSchemaWithOrgNoInHeaderTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByOrganizationNumber = org1.orgno; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchemaOrgNoInHeader(offeredByToken, offeredByOrganizationNumber, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema with offeredbys orgno in header - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema with offeredbys orgno in header - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema with offeredbys orgno in header - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema with offeredbys orgno in header - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema with offeredbys orgno in header - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema with offeredbys orgno in header - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema with offeredbys orgno in header - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema as HADM (instead of DAGL) */ +export function postMaskinportenSchemaAsHadmTest() { + // Arrange + const offeredByToken = org1.hadm.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema As HADM - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema As HADM - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema As HADM - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema As HADM - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema As HADM - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema As HADM - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema As HADM - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** offer a maskinportenschema as APIADM (instead of DAGL) */ +export function postMaskinportenSchemaAsApiadmTest() { + // Arrange + const offeredByToken = org1.apiadm.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema As APIADM - status is 201': (r) => r.status === 201, + 'post MaskinportenSchema As APIADM - to id is partyid': (r) => r.json('to.0.id') === 'urn:altinn:partyid', + 'post MaskinportenSchema As APIADM - organization number matches': (r) => r.json('to.0.value') === toPartyId, + 'post MaskinportenSchema As APIADM - resource type is urn:altinn:resource': (r) => r.json('rightDelegationResults.0.resource.0.id') === 'urn:altinn:resource', + 'post MaskinportenSchema As APIADM - appid matches': (r) => r.json('rightDelegationResults.0.resource.0.value') === appid, + 'post MaskinportenSchema As APIADM - action type is action-id': (r) => r.json('rightDelegationResults.0.action.id') === 'urn:oasis:names:tc:xacml:1.0:action:action-id', + 'post MaskinportenSchema As APIADM - action value is ScopeAccess': (r) => r.json('rightDelegationResults.0.action.value') === 'ScopeAccess', + }); + + addErrorCount(success); +} + +/** try and fail to delegate maskinportenschema to a person */ +export function postMaskinportenCannotDelegateToPersonTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.dagl.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post MaskinportenSchema Cannot Delegate To Person - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema Cannot Delegate To Person - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema Cannot Delegate To Person - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema Cannot Delegate To Person - Invalid organization': (r) => r.body.includes('Maskinporten schema delegation can only be delegated to a valid organization'), + }); + + addErrorCount(success); +} + +/** try and fail to delegate maskinportenschema to a person */ +export function postMaskinportenDAGLCannotDelegateNUFResource() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6-nuf'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + console.log(res.body); + + // Assert + var success = check(res, { + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema DAGL Cannot Delegate NUF Resource - Unauthorized to delegate the resource': (r) => r.body.includes('Authenticated user does not have any delegable rights for the resource: ttd-am-k6-nuf'), + }); + + addErrorCount(success); +} + +/** try and fail to delegate a system resource */ +export function postMaskinportenSystemResourceCannotBeDelegatedTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'altinn_maskinporten_scope_delegation'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'post Maskinporten Systemresource Cannot be delegated - status is 400': (r) => r.status === 400, + 'post Maskinporten Systemresource Cannot be delegated - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post Maskinporten Systemresource Cannot be delegated - errors is not null': (r) => r.json('errors') != null, + 'post Maskinporten Systemresource Cannot be delegated - Invalid resource type': (r) => r.body.includes('This operation only support requests for Maskinporten schema resources. Invalid resource: altinn_maskinporten_scope_delegation. Invalid resource type: SystemResource"'), + }); + + addErrorCount(success); +} + +/** try to offer a maskinportenschema that is not ready */ +export function postMaskinportenSchemaNotReadyTest() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'appid-302'; + + // Act + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'post MaskinportenSchema that is Not Ready - status is 400': (r) => r.status === 400, + 'post MaskinportenSchema that is Not Ready - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'post MaskinportenSchema that is Not Ready - errors is not null': (r) => r.json('errors') != null, + 'post MaskinportenSchema that is Not Ready - resource is incomplete or not found': (r) => r.body.includes('The resource: appid-302, does not exist or is not complete and available for delegation'), + }); + + addErrorCount(success); +} + +/** revoke an offered maskinportenschema */ +export function revokeOfferedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + success = check(res, { + 'revoke Offered MaskinPortenSchema - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'revoke Offered MaskinPortenSchema - revoke status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke a received maskinportenschema */ +export function revokeReceivedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const toToken = org2.dagl.token; + const offeredByPartyId = org1.partyid; + const offeredByOrgNumber = org1.orgno; + const toOrgNumber = org2.orgno; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:organizationnumber', toOrgNumber); + success = check(res, { + 'revoke Received MaskinPortenSchema - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, appid, 'urn:altinn:organizationnumber', offeredByOrgNumber); + + // Assert + var success = check(res, { + 'revoke Received MaskinPortenSchema - status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke an offered maskinportenschema using partyid*/ +export function revokeOfferedMaskinPortenSchemaUsingPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + + // Assert + var success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid- revoke status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + res = maskinporten.getMaskinportenSchemaOffered(offeredByToken, offeredByPartyId); + success = check(res, { + 'revoke Offered MaskinPortenSchema using partyid- getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** revoke a received maskinportenschema using partyid*/ +export function revokeReceivedMaskinPortenSchemaUsingPartyId() { + // Arrange + const offeredByToken = org1.dagl.token; + const toToken = org2.dagl.token; + const offeredByPartyId = org1.partyid; + const toPartyId = org2.partyid; + const appid = 'ttd-am-k6'; + + var res = maskinporten.postMaskinportenSchema(offeredByToken, offeredByPartyId, appid, 'urn:altinn:partyid', toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - getMaskinPortenSchema was added (status is 201 created)': (r) => r.status === 201, + }); + addErrorCount(success); + + // Act + res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, appid, 'urn:altinn:partyid', offeredByPartyId); + + // Assert + var success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - status is 204': (r) => r.status === 204, + }); + addErrorCount(success); + + sleep(3); + res = maskinporten.getMaskinportenSchemaReceived(toToken, toPartyId); + success = check(res, { + 'revoke Received MaskinPortenSchema using partyid - getMaskinPortenSchema returns only 1 element': (r) => r.json('1') == null, + }); + addErrorCount(success); +} + +/** try to revoke a non-existent offered maskinportenschema */ +export function revokeNonExistentOfferedMaskinPortenSchema() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const toOrgNumber = org2.orgno; + + // Act + var res = maskinporten.revokeOfferedMaskinportenSchema(offeredByToken, offeredByPartyId, 'nonexistentmaskinportenschema', 'urn:altinn:organizationnumber', toOrgNumber); + + // Assert + var success = check(res, { + 'revoke non-existent Offered MaskinPortenSchema - status is 400': (r) => r.status === 400, + 'revoke non-existent Offered MaskinPortenSchema - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'revoke non-existent Offered MaskinPortenSchema - errors is not null': (r) => r.json('errors') != null, + 'revoke non-existent Offered MaskinPortenSchema - resource is incomplete or not found': (r) => r.body.includes('The resource: nonexistentmaskinportenschema, does not exist or is not complete and available for delegation'), + }); + addErrorCount(success); +} + +/** try to revoke a non-existent received maskinportenschema */ +export function revokeNonExistentReceivedMaskinPortenSchema() { + // Arrange + const toToken = org2.dagl.token; + const toPartyId = org2.partyid; + const offeredByOrgNumber = org1.orgno; + + // Act + var res = maskinporten.revokeReceivedMaskinportenSchema(toToken, toPartyId, 'nonexistentmaskinportenschema', 'urn:altinn:organizationnumber', offeredByOrgNumber); + + // Assert + var success = check(res, { + 'revoke non-existent Received MaskinPortenSchema - status is 400': (r) => r.status === 400, + 'revoke non-existent Received MaskinPortenSchema - `One or more validation errors occurred.`': (r) => r.json('title') == 'One or more validation errors occurred.', + 'revoke non-existent Received MaskinPortenSchema - errors is not null': (r) => r.json('errors') != null, + 'revoke non-existent Received MaskinPortenSchema - resource is incomplete or not found': (r) => r.body.includes('The resource: nonexistentmaskinportenschema, does not exist or is not complete and available for delegation'), + }); + addErrorCount(success); +} + +/** check delegation rights on a maskinportenschema for DAGL role */ +export function delegationCheckMaskinPortenSchema_DAGLhasScopeAccess() { + // Arrange + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: DAGL has scope access - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: DAGL has scope access - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: DAGL has scope access - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: DAGL has scope access - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'delegationCheckMaskinportenSchema: DAGL has scope access - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'delegationCheckMaskinportenSchema: DAGL has scope access - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'delegationCheckMaskinportenSchema: DAGL has scope access - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + }); + addErrorCount(success); +} + +/** check delegation rights on a maskinportenschema for HADM role*/ +export function delegationCheckMaskinPortenSchema_HADMhasScopeAccess() { + // Arrange + const offeredByToken = org1.hadm.token; + const offeredByPartyId = org1.partyid; + const appid = 'ttd-am-k6'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: HADM has scope access - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: HADM has scope access - rightskey is ttd-am-k6:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: HADM has scope access - resource value is ttd-am-k6': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: HADM has scope access - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - status is Delegable': (r) => r.json('0.status') == 'Delegable', + 'delegationCheckMaskinportenSchema: HADM has scope access - code is RoleAccess': (r) => r.json('0.details.0.code') == 'RoleAccess', + 'delegationCheckMaskinportenSchema: HADM has scope access - RoleRequirementsMatches id is urn:altinn:rolecode': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.id') == 'urn:altinn:rolecode', + 'delegationCheckMaskinportenSchema: HADM has scope access - RoleRequirementsMatches value is APIADM': (r) => r.json('0.details.0.parameters.RoleRequirementsMatches.0.value') == 'APIADM', + }); + addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate a non-existing resource */ +export function delegationCheckMaskinPortenSchema_resourceDoesNotExist() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'aresourcethattotallydoesnotexist'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: Resource Is NonDelegable - status is 400 ': (r) => r.status === 400, + 'delegationCheckMaskinportenSchema: Resource Is NonDelegable - Error message is "The resource does not exist or is not available for delegation"': (r) => r.body.includes('The resource does not exist or is not available for delegation'), + }); + addErrorCount(success); +} + +/** Checks that the response is 400 and with an error message when trying to delegate with a too low authentication level */ +export function delegationCheckMaskinPortenSchema_tooLowAuthLevel() { + const offeredByToken = org1.dagl.token; + const offeredByPartyId = org1.partyid; + const appid = 'altinn_automation_test_lv4'; + + // Act + var res = maskinporten.postDelegationCheck(offeredByToken, offeredByPartyId, appid); + + // Assert + var success = check(res, { + 'delegationCheckMaskinportenSchema: user has too low authentication level - status is 200': (r) => r.status === 200, + 'delegationCheckMaskinportenSchema: user has too low authentication level - rightskey is altinn_automation_test_lv4:ScopeAccess': (r) => r.json('0.rightKey') === appid + ':ScopeAccess', + 'delegationCheckMaskinportenSchema: user has too low authentication level - resource id is urn:altinn:resource': (r) => r.json('0.resource.0.id') === 'urn:altinn:resource', + 'delegationCheckMaskinportenSchema: user has too low authentication level - resource value is altinn_automation_test_lv4': (r) => r.json('0.resource.0.value') == appid, + 'delegationCheckMaskinportenSchema: user has too low authentication level - action value is ScopeAccess': (r) => r.json('0.action') == 'ScopeAccess', + 'delegationCheckMaskinportenSchema: user has too low authentication level - status is NotDelegable': (r) => r.json('0.status') == 'NotDelegable', + 'delegationCheckMaskinportenSchema: user has too low authentication level - code is InsufficientAuthenticationLevel': (r) => r.json('0.details.0.code') == 'InsufficientAuthenticationLevel', + 'delegationCheckMaskinportenSchema: user has too low authentication level - MinimumAuthenticationLevel id is urn:altinn:minimum-authenticationlevel': (r) => r.json('0.details.0.parameters.MinimumAuthenticationLevel.0.id') == 'urn:altinn:minimum-authenticationlevel', + 'delegationCheckMaskinportenSchema: user has too low authentication level - MinimumAuthenticationLevel value is 4': (r) => r.json('0.details.0.parameters.MinimumAuthenticationLevel.0.value') == '4', + }); + addErrorCount(success); +} + + +export function handleSummary(data) { + let result = {}; + result[reportPath('maskinportenschema.xml')] = generateJUnitXML(data, 'access-management-maskinportenschema'); + return result; +} + +export function showTestdata() { + console.log(environment) + console.log('personalToken1: ' + org1.dagl.token); + console.log('personalToken2: ' + org2.dagl.token); + console.log('org: ' + testdata.org); + console.log('app: ' + testdata.app); + console.log('user1pid: ' + org1.dagl.pid); + console.log('user1userid: ' + org1.dagl.userid); + console.log('user1partyid: ' + org1.dagl.partyid); + console.log('orgno1: ' + org1.orgno); + console.log('orgpartyid1: ' + org1.partyid); + console.log('hadm1userid: ' + org1.hadm.userid); + console.log('hadm1partyid: ' + org1.hadm.partyid); + console.log('user2pid: ' + org2.dagl.pid); + console.log('user2userid: ' + org2.dagl.userid); + console.log('user2partyid: ' + org2.dagl.partyid); + console.log('orgno2: ' + org2.orgno); + console.log('orgpartyid2: ' + org2.partyid); +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/src/wrapper.js b/src/apps/Altinn.AccessManagement/test/K6/src/wrapper.js new file mode 100644 index 00000000..9e4c873f --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/src/wrapper.js @@ -0,0 +1,32 @@ +import http from 'k6/http'; +import { sleep } from 'k6'; + +//wrapper functions around k6 http methods enabling retrying requests when response code is 0, 408 and > 500 + +export function httpPost(url, body, params) { + var res, + retriedCount = 0; + for (var retries = 3; retries > 0; retries--) { + res = http.post(url, body, params); + if (res.status != 0 && res.status != 408 && res.status < 500) { + return res; + } + sleep(10); + console.log(`Retry number: ${++retriedCount}`); + } + return res; +} + +export function httpGet(url, params) { + var res, + retriedCount = 0; + for (var retries = 3; retries > 0; retries--) { + res = http.get(url, params); + if (res.status != 0 && res.status != 408 && res.status < 500) { + return res; + } + sleep(10); + console.log(`Retry number: ${++retriedCount}`); + } + return res; +} diff --git a/src/apps/Altinn.AccessManagement/test/K6/yarn.lock b/src/apps/Altinn.AccessManagement/test/K6/yarn.lock new file mode 100644 index 00000000..8fdb39d2 --- /dev/null +++ b/src/apps/Altinn.AccessManagement/test/K6/yarn.lock @@ -0,0 +1,1274 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: 8/ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd + languageName: node + linkType: hard + +"@ampproject/remapping@npm:^2.2.0": + version: 2.2.0 + resolution: "@ampproject/remapping@npm:2.2.0" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.1.0" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 8/d74d170d06468913921d72430259424b7e4c826b5a7d39ff839a29d547efb97dc577caa8ba3fb5cf023624e9af9d09651afc3d4112a45e2050328abc9b3a2292 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.25.9" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.0.0" + checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.25.9": + version: 7.26.2 + resolution: "@babel/compat-data@npm:7.26.2" + checksum: 10c0/c9b5f3724828d17f728a778f9d66c19b55c018d0d76de6d731178cca64f182c22b71400a73bf2b65dcc4fcfe52b630088a94d5902911b54206aa90e3ffe07d12 + languageName: node + linkType: hard + +"@babel/core@npm:7.26.0": + version: 7.26.0 + resolution: "@babel/core@npm:7.26.0" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.26.0" + "@babel/generator": "npm:^7.26.0" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-module-transforms": "npm:^7.26.0" + "@babel/helpers": "npm:^7.26.0" + "@babel/parser": "npm:^7.26.0" + "@babel/template": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/91de73a7ff5c4049fbc747930aa039300e4d2670c2a91f5aa622f1b4868600fc89b01b6278385fbcd46f9574186fa3d9b376a9e7538e50f8d118ec13cfbcb63e + languageName: node + linkType: hard + +"@babel/eslint-parser@npm:7.25.9": + version: 7.25.9 + resolution: "@babel/eslint-parser@npm:7.25.9" + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" + eslint-visitor-keys: "npm:^2.1.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/7dc525da9a076906aff562f82373765785732edf306e2be6497e347ed73be80d3544f2f845a77c2376bfa1c7c8c3580ea7346b12b78d8ddf4365c44fe9c35c4b + languageName: node + linkType: hard + +"@babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/generator@npm:7.26.2" + dependencies: + "@babel/parser": "npm:^7.26.2" + "@babel/types": "npm:^7.26.0" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + jsesc: "npm:^3.0.2" + checksum: 10c0/167ebce8977142f5012fad6bd91da51ac52bcd752f2261a54b7ab605d928aebe57e21636cdd2a9c7757e552652c68d9fcb5d40b06fcb66e02d9ee7526e118a5c + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-compilation-targets@npm:7.25.9" + dependencies: + "@babel/compat-data": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-module-imports@npm:7.25.9" + dependencies: + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" + dependencies: + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helpers@npm:7.26.0" + dependencies: + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" + checksum: 10c0/343333cced6946fe46617690a1d0789346960910225ce359021a88a60a65bc0d791f0c5d240c0ed46cf8cc63b5fd7df52734ff14e43b9c32feae2b61b1647097 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2": + version: 7.26.2 + resolution: "@babel/parser@npm:7.26.2" + dependencies: + "@babel/types": "npm:^7.26.0" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/751a743087b3a9172a7599f1421830d44c38f065ef781588d2bfb1c98f9b461719a226feb13c868d7a284783eee120c88ea522593118f2668f46ebfb1105c4d7 + languageName: node + linkType: hard + +"@babel/template@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/template@npm:7.25.9" + dependencies: + "@babel/code-frame": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/traverse@npm:7.25.9" + dependencies: + "@babel/code-frame": "npm:^7.25.9" + "@babel/generator": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: 10c0/e90be586a714da4adb80e6cb6a3c5cfcaa9b28148abdafb065e34cc109676fc3db22cf98cd2b2fff66ffb9b50c0ef882cab0f466b6844be0f6c637b82719bba1 + languageName: node + linkType: hard + +"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + checksum: 10c0/b694f41ad1597127e16024d766c33a641508aad037abd08d0d1f73af753e1119fa03b4a107d04b5f92cc19c095a594660547ae9bead1db2299212d644b0a5cb8 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.2.0": + version: 4.3.0 + resolution: "@eslint-community/eslint-utils@npm:4.3.0" + dependencies: + eslint-visitor-keys: "npm:^3.3.0" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 8/f487760a692f0f1fef76e248ad72976919576ba57edc2b1b1dc1d182553bae6b5bf7b078e654da85d04f0af8a485d20bd26280002768f4fbcd2e330078340cb0 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.12.1": + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6 + languageName: node + linkType: hard + +"@eslint/config-array@npm:^0.18.0": + version: 0.18.0 + resolution: "@eslint/config-array@npm:0.18.0" + dependencies: + "@eslint/object-schema": "npm:^2.1.4" + debug: "npm:^4.3.1" + minimatch: "npm:^3.1.2" + checksum: 10c0/0234aeb3e6b052ad2402a647d0b4f8a6aa71524bafe1adad0b8db1dfe94d7f5f26d67c80f79bb37ac61361a1d4b14bb8fb475efe501de37263cf55eabb79868f + languageName: node + linkType: hard + +"@eslint/core@npm:^0.7.0": + version: 0.7.0 + resolution: "@eslint/core@npm:0.7.0" + checksum: 10c0/3cdee8bc6cbb96ac6103d3ead42e59830019435839583c9eb352b94ed558bd78e7ffad5286dc710df21ec1e7bd8f52aa6574c62457a4dd0f01f3736fa4a7d87a + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^3.1.0": + version: 3.1.0 + resolution: "@eslint/eslintrc@npm:3.1.0" + dependencies: + ajv: "npm:^6.12.4" + debug: "npm:^4.3.2" + espree: "npm:^10.0.1" + globals: "npm:^14.0.0" + ignore: "npm:^5.2.0" + import-fresh: "npm:^3.2.1" + js-yaml: "npm:^4.1.0" + minimatch: "npm:^3.1.2" + strip-json-comments: "npm:^3.1.1" + checksum: 10c0/5b7332ed781edcfc98caa8dedbbb843abfb9bda2e86538529c843473f580e40c69eb894410eddc6702f487e9ee8f8cfa8df83213d43a8fdb549f23ce06699167 + languageName: node + linkType: hard + +"@eslint/js@npm:9.14.0": + version: 9.14.0 + resolution: "@eslint/js@npm:9.14.0" + checksum: 10c0/a423dd435e10aa3b461599aa02f6cbadd4b5128cb122467ee4e2c798e7ca4f9bb1fce4dcea003b29b983090238cf120899c1af657cf86300b399e4f996b83ddc + languageName: node + linkType: hard + +"@eslint/object-schema@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/object-schema@npm:2.1.4" + checksum: 10c0/e9885532ea70e483fb007bf1275968b05bb15ebaa506d98560c41a41220d33d342e19023d5f2939fed6eb59676c1bda5c847c284b4b55fce521d282004da4dda + languageName: node + linkType: hard + +"@eslint/plugin-kit@npm:^0.2.0": + version: 0.2.0 + resolution: "@eslint/plugin-kit@npm:0.2.0" + dependencies: + levn: "npm:^0.4.1" + checksum: 10c0/00b92bc52ad09b0e2bbbb30591c02a895f0bec3376759562590e8a57a13d096b22f8c8773b6bf791a7cf2ea614123b3d592fd006c51ac5fd0edbb90ea6d8760c + languageName: node + linkType: hard + +"@humanfs/core@npm:^0.19.1": + version: 0.19.1 + resolution: "@humanfs/core@npm:0.19.1" + checksum: 10c0/aa4e0152171c07879b458d0e8a704b8c3a89a8c0541726c6b65b81e84fd8b7564b5d6c633feadc6598307d34564bd53294b533491424e8e313d7ab6c7bc5dc67 + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.6": + version: 0.16.6 + resolution: "@humanfs/node@npm:0.16.6" + dependencies: + "@humanfs/core": "npm:^0.19.1" + "@humanwhocodes/retry": "npm:^0.3.0" + checksum: 10c0/8356359c9f60108ec204cbd249ecd0356667359b2524886b357617c4a7c3b6aace0fd5a369f63747b926a762a88f8a25bc066fa1778508d110195ce7686243e1 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 8/0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.3.0": + version: 0.3.0 + resolution: "@humanwhocodes/retry@npm:0.3.0" + checksum: 10c0/7111ec4e098b1a428459b4e3be5a5d2a13b02905f805a2468f4fa628d072f0de2da26a27d04f65ea2846f73ba51f4204661709f05bfccff645e3cedef8781bb6 + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.4.0": + version: 0.4.1 + resolution: "@humanwhocodes/retry@npm:0.4.1" + checksum: 10c0/be7bb6841c4c01d0b767d9bb1ec1c9359ee61421ce8ba66c249d035c5acdfd080f32d55a5c9e859cdd7868788b8935774f65b2caf24ec0b7bd7bf333791f063b + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.1.0": + version: 0.1.1 + resolution: "@jridgewell/gen-mapping@npm:0.1.1" + dependencies: + "@jridgewell/set-array": "npm:^1.0.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 8/3bcc21fe786de6ffbf35c399a174faab05eb23ce6a03e8769569de28abbf4facc2db36a9ddb0150545ae23a8d35a7cf7237b2aa9e9356a7c626fb4698287d5cc + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" + dependencies: + "@jridgewell/set-array": "npm:^1.2.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/1be4fd4a6b0f41337c4f5fdf4afc3bd19e39c3691924817108b82ffcb9c9e609c273f936932b9fba4b3a298ce2eb06d9bff4eb1cc3bd81c4f4ee1b4917e25feb + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.0.4 + resolution: "@jridgewell/resolve-uri@npm:3.0.4" + checksum: 8/799bcba2730280a42f11b4d41a5d34d68ce72cb1bd23186bd3356607c93b62765b2b050e5dfb67f04ce4e817f882bfc10a4d1c43fe2d8eeb38371c98d71217b4 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.0": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: 8/69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 10c0/2a5aa7b4b5c3464c895c802d8ae3f3d2b92fcbe84ad12f8d0bfbb1f5ad006717e7577ee1fd2eac00c088abe486c7adb27976f45d2941ff6b0b92b2c3302c60f4 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.4.11 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.11" + checksum: 8/3b2afaf8400fb07a36db60e901fcce6a746cdec587310ee9035939d89878e57b2dec8173b0b8f63176f647efa352294049a53c49739098eb907ff81fec2547c8 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: 10c0/0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.13 + resolution: "@jridgewell/trace-mapping@npm:0.3.13" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 8/e38254e830472248ca10a6ed1ae75af5e8514f0680245a5e7b53bc3c030fd8691d4d3115d80595b45d3badead68269769ed47ecbbdd67db1343a11f05700e75a + languageName: node + linkType: hard + +"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": + version: 5.1.1-v1 + resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" + dependencies: + eslint-scope: "npm:5.1.1" + checksum: 8/f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57 + languageName: node + linkType: hard + +"@types/estree@npm:^1.0.6": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a + languageName: node + linkType: hard + +"@types/json-schema@npm:^7.0.15": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 8/c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 + languageName: node + linkType: hard + +"acorn@npm:^8.12.0": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 + languageName: node + linkType: hard + +"acorn@npm:^8.14.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" + bin: + acorn: bin/acorn + checksum: 10c0/6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7 + languageName: node + linkType: hard + +"ajv@npm:^6.12.4": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" + dependencies: + fast-deep-equal: "npm:^3.1.1" + fast-json-stable-stringify: "npm:^2.0.0" + json-schema-traverse: "npm:^0.4.1" + uri-js: "npm:^4.2.2" + checksum: 8/874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 8/513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 8/83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 8/9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: "npm:^1.0.0" + concat-map: "npm:0.0.1" + checksum: 8/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"browserslist@npm:^4.24.0": + version: 4.24.0 + resolution: "browserslist@npm:4.24.0" + dependencies: + caniuse-lite: "npm:^1.0.30001663" + electron-to-chromium: "npm:^1.5.28" + node-releases: "npm:^2.0.18" + update-browserslist-db: "npm:^1.1.0" + bin: + browserslist: cli.js + checksum: 10c0/95e76ad522753c4c470427f6e3c8a4bb5478ff448841e22b3d3e53f89ecaf17b6984666d6c7e715c370f1e7fa0cf684f42e34e554236a8b2fab38ea76b9e4c52 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 8/072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001663": + version: 1.0.30001668 + resolution: "caniuse-lite@npm:1.0.30001668" + checksum: 10c0/247b3200aeec55038f3a11f3e6ab66f656c54d30df7b01d8d447efaba9af96ad3e17128da2ddd42ddc9cb6c286bac65b634a20955b3cc6619be7ca4601fddc8e + languageName: node + linkType: hard + +"chalk@npm:^4.0.0": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 8/fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 8/79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 8/b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 8/902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 8/63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.2": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 8/671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"debug@npm:^4.1.0, debug@npm:^4.3.2": + version: 4.3.2 + resolution: "debug@npm:4.3.2" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 8/820ea160e267e23c953c9ed87e7ad93494d8cda2f7349af5e7e3bb236d23707ee3022f477d5a7d2ee86ef2bf7d60aa9ab22d1f58080d7deb9dccd073585e1e43 + languageName: node + linkType: hard + +"debug@npm:^4.3.1": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: 8/edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.5.28": + version: 1.5.36 + resolution: "electron-to-chromium@npm:1.5.36" + checksum: 10c0/cd8d0de7801107f2b2744b5b18641c969a49b0503996cc1a586bb79d893020d0c4e916ac1935603eea65104b4fc1096bc339e0151531dca9e0f0ce0c1882e2d8 + languageName: node + linkType: hard + +"escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 8/98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"eslint-scope@npm:5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: "npm:^4.3.0" + estraverse: "npm:^4.1.1" + checksum: 8/47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + +"eslint-scope@npm:^8.2.0": + version: 8.2.0 + resolution: "eslint-scope@npm:8.2.0" + dependencies: + esrecurse: "npm:^4.3.0" + estraverse: "npm:^5.2.0" + checksum: 10c0/8d2d58e2136d548ac7e0099b1a90d9fab56f990d86eb518de1247a7066d38c908be2f3df477a79cf60d70b30ba18735d6c6e70e9914dca2ee515a729975d70d6 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^2.1.0": + version: 2.1.0 + resolution: "eslint-visitor-keys@npm:2.1.0" + checksum: 8/e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.3.0": + version: 3.3.0 + resolution: "eslint-visitor-keys@npm:3.3.0" + checksum: 8/d59e68a7c5a6d0146526b0eec16ce87fbf97fe46b8281e0d41384224375c4e52f5ffb9e16d48f4ea50785cde93f766b0c898e31ab89978d88b0e1720fbfb7808 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^4.1.0": + version: 4.1.0 + resolution: "eslint-visitor-keys@npm:4.1.0" + checksum: 10c0/5483ef114c93a136aa234140d7aa3bd259488dae866d35cb0d0b52e6a158f614760a57256ac8d549acc590a87042cb40f6951815caa821e55dc4fd6ef4c722eb + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^4.2.0": + version: 4.2.0 + resolution: "eslint-visitor-keys@npm:4.2.0" + checksum: 10c0/2ed81c663b147ca6f578312919483eb040295bbab759e5a371953456c636c5b49a559883e2677112453728d66293c0a4c90ab11cab3428cf02a0236d2e738269 + languageName: node + linkType: hard + +"eslint@npm:9.14.0": + version: 9.14.0 + resolution: "eslint@npm:9.14.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.2.0" + "@eslint-community/regexpp": "npm:^4.12.1" + "@eslint/config-array": "npm:^0.18.0" + "@eslint/core": "npm:^0.7.0" + "@eslint/eslintrc": "npm:^3.1.0" + "@eslint/js": "npm:9.14.0" + "@eslint/plugin-kit": "npm:^0.2.0" + "@humanfs/node": "npm:^0.16.6" + "@humanwhocodes/module-importer": "npm:^1.0.1" + "@humanwhocodes/retry": "npm:^0.4.0" + "@types/estree": "npm:^1.0.6" + "@types/json-schema": "npm:^7.0.15" + ajv: "npm:^6.12.4" + chalk: "npm:^4.0.0" + cross-spawn: "npm:^7.0.2" + debug: "npm:^4.3.2" + escape-string-regexp: "npm:^4.0.0" + eslint-scope: "npm:^8.2.0" + eslint-visitor-keys: "npm:^4.2.0" + espree: "npm:^10.3.0" + esquery: "npm:^1.5.0" + esutils: "npm:^2.0.2" + fast-deep-equal: "npm:^3.1.3" + file-entry-cache: "npm:^8.0.0" + find-up: "npm:^5.0.0" + glob-parent: "npm:^6.0.2" + ignore: "npm:^5.2.0" + imurmurhash: "npm:^0.1.4" + is-glob: "npm:^4.0.0" + json-stable-stringify-without-jsonify: "npm:^1.0.1" + lodash.merge: "npm:^4.6.2" + minimatch: "npm:^3.1.2" + natural-compare: "npm:^1.4.0" + optionator: "npm:^0.9.3" + text-table: "npm:^0.2.0" + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true + bin: + eslint: bin/eslint.js + checksum: 10c0/e1cbf571b75519ad0b24c27e66a6575e57cab2671ef5296e7b345d9ac3adc1a549118dcc74a05b651a7a13a5e61ebb680be6a3e04a80e1f22eba1931921b5187 + languageName: node + linkType: hard + +"espree@npm:^10.0.1": + version: 10.2.0 + resolution: "espree@npm:10.2.0" + dependencies: + acorn: "npm:^8.12.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.1.0" + checksum: 10c0/2b6bfb683e7e5ab2e9513949879140898d80a2d9867ea1db6ff5b0256df81722633b60a7523a7c614f05a39aeea159dd09ad2a0e90c0e218732fc016f9086215 + languageName: node + linkType: hard + +"espree@npm:^10.3.0": + version: 10.3.0 + resolution: "espree@npm:10.3.0" + dependencies: + acorn: "npm:^8.14.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.0" + checksum: 10c0/272beeaca70d0a1a047d61baff64db04664a33d7cfb5d144f84bc8a5c6194c6c8ebe9cc594093ca53add88baa23e59b01e69e8a0160ab32eac570482e165c462 + languageName: node + linkType: hard + +"esquery@npm:^1.5.0": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: "npm:^5.2.0" + checksum: 8/ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 + languageName: node + linkType: hard + +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: 8/a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 8/072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 8/22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: 8/e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: 8/b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 8/92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" + dependencies: + flat-cache: "npm:^4.0.0" + checksum: 10c0/9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: "npm:^6.0.0" + path-exists: "npm:^4.0.0" + checksum: 8/07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" + dependencies: + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.4" + checksum: 10c0/2c59d93e9faa2523e4fda6b4ada749bed432cfa28c8e251f33b25795e426a1c6dbada777afb1f74fcfff33934fdbdea921ee738fcc33e71adc9d6eca984a1cfc + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 10c0/324166b125ee07d4ca9bcf3a5f98d915d5db4f39d711fba640a3178b959919aae1f7cfd8aabcfef5826ed8aa8a2aa14cc85b2d7d18ff638ddf4ae3df39573eaf + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 8/a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: "npm:^4.0.3" + checksum: 8/c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 + languageName: node + linkType: hard + +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 8/67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 10c0/b96ff42620c9231ad468d4c58ff42afee7777ee1c963013ff8aabe095a451d0ceeb8dcd8ef4cbd64d2538cef45f787a78ba3a9574f4a634438963e334471302d + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 8/261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"ignore@npm:^5.2.0": + version: 5.2.0 + resolution: "ignore@npm:5.2.0" + checksum: 8/6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 + languageName: node + linkType: hard + +"import-fresh@npm:^3.2.1": + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" + dependencies: + parent-module: "npm:^1.0.0" + resolve-from: "npm:^4.0.0" + checksum: 8/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 8/7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 8/df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.3": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 8/d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 8/26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 8/8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 + languageName: node + linkType: hard + +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 8/c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"jsesc@npm:^3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" + bin: + jsesc: bin/jsesc + checksum: 10c0/ef22148f9e793180b14d8a145ee6f9f60f301abf443288117b4b6c53d0ecd58354898dc506ccbb553a5f7827965cd38bc5fb726575aae93c5e8915e2de8290e1 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 10c0/0d1c91569d9588e7eef2b49b59851f297f3ab93c7b35c7c221e288099322be6b562767d11e4821da500f3219542b9afd2e54c5dc573107c1126ed1080f8e96d7 + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 8/7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: 8/cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 + languageName: node + linkType: hard + +"json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 8/2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 + languageName: node + linkType: hard + +"k6-api-tests@workspace:.": + version: 0.0.0-use.local + resolution: "k6-api-tests@workspace:." + dependencies: + "@babel/core": "npm:7.26.0" + "@babel/eslint-parser": "npm:7.25.9" + eslint: "npm:9.14.0" + prettier: "npm:3.3.3" + languageName: unknown + linkType: soft + +"keyv@npm:^4.5.4": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: "npm:3.0.1" + checksum: 10c0/aa52f3c5e18e16bb6324876bb8b59dd02acf782a4b789c7b2ae21107fab95fab3890ed448d4f8dba80ce05391eeac4bfabb4f02a20221342982f806fa2cf271e + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: "npm:^1.2.1" + type-check: "npm:~0.4.0" + checksum: 8/12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: "npm:^5.0.0" + checksum: 8/72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: 8/ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: "npm:^3.0.2" + checksum: 8/c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb + languageName: node + linkType: hard + +"minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 8/c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 8/673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 8/23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: 10c0/786ac9db9d7226339e1dc84bbb42007cb054a346bd9257e6aa154d294f01bc6a6cddb1348fa099f079be6580acbb470e3c048effd5f719325abd0179e566fd27 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": "npm:^1.2.3" + deep-is: "npm:^0.1.3" + fast-levenshtein: "npm:^2.0.6" + levn: "npm:^0.4.1" + prelude-ls: "npm:^1.2.1" + type-check: "npm:^0.4.0" + checksum: 8/09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 8/7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: "npm:^3.0.2" + checksum: 8/1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: "npm:^3.0.0" + checksum: 8/6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 8/505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 8/55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: 8/a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: 8/cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a + languageName: node + linkType: hard + +"prettier@npm:3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 + languageName: node + linkType: hard + +"punycode@npm:^2.1.0": + version: 2.1.1 + resolution: "punycode@npm:2.1.1" + checksum: 8/823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: 8/f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f + languageName: node + linkType: hard + +"semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: 8/ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 8/6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 8/1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 8/492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 8/3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"text-table@npm:^0.2.0": + version: 0.2.0 + resolution: "text-table@npm:0.2.0" + checksum: 8/b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: "npm:^1.2.1" + checksum: 8/ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.1.0": + version: 1.1.0 + resolution: "update-browserslist-db@npm:1.1.0" + dependencies: + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/a7452de47785842736fb71547651c5bbe5b4dc1e3722ccf48a704b7b34e4dcf633991eaa8e4a6a517ffb738b3252eede3773bef673ef9021baa26b056d63a5b9 + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: "npm:^2.1.0" + checksum: 8/7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 8/1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 8/48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: 8/f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard diff --git a/src/apps/Altinn.Authorization.AccessPackages/src/Altinn.Authorization.AccessPackages/Altinn.Authorization.AccessPackages.csproj b/src/apps/Altinn.Authorization.AccessPackages/src/Altinn.Authorization.AccessPackages/Altinn.Authorization.AccessPackages.csproj index 8266ff73..af858d7a 100644 --- a/src/apps/Altinn.Authorization.AccessPackages/src/Altinn.Authorization.AccessPackages/Altinn.Authorization.AccessPackages.csproj +++ b/src/apps/Altinn.Authorization.AccessPackages/src/Altinn.Authorization.AccessPackages/Altinn.Authorization.AccessPackages.csproj @@ -31,4 +31,4 @@ Include="..\Altinn.Authorization.AccessPackages.Models\Altinn.Authorization.AccessPackages.Models.csproj" /> - + \ No newline at end of file diff --git a/src/apps/Altinn.Authorization.AccessPackages/src/Directory.Build.props b/src/apps/Altinn.Authorization.AccessPackages/src/Directory.Build.props index fed9437a..5e119da5 100644 --- a/src/apps/Altinn.Authorization.AccessPackages/src/Directory.Build.props +++ b/src/apps/Altinn.Authorization.AccessPackages/src/Directory.Build.props @@ -2,7 +2,7 @@ - true + true \ No newline at end of file diff --git a/src/apps/Altinn.Authorization.DeployApi/Dockerfile b/src/apps/Altinn.Authorization.DeployApi/Dockerfile index 3dfa71b4..950a466d 100644 --- a/src/apps/Altinn.Authorization.DeployApi/Dockerfile +++ b/src/apps/Altinn.Authorization.DeployApi/Dockerfile @@ -1,12 +1,12 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build WORKDIR /app WORKDIR /src COPY src/ . WORKDIR /src/apps/Altinn.Authorization.DeployApi/src/Altinn.Authorization.DeployApi RUN dotnet publish -c Release -o /app -FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final WORKDIR /app COPY --from=build /app . -ENTRYPOINT ["dotnet", "Altinn.Authorization.DeployApi.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "Altinn.Authorization.DeployApi.dll"] diff --git a/src/apps/Altinn.Authorization.DeployApi/src/Altinn.Authorization.DeployApi/Altinn.Authorization.DeployApi.csproj b/src/apps/Altinn.Authorization.DeployApi/src/Altinn.Authorization.DeployApi/Altinn.Authorization.DeployApi.csproj index 964edd00..55a753ea 100644 --- a/src/apps/Altinn.Authorization.DeployApi/src/Altinn.Authorization.DeployApi/Altinn.Authorization.DeployApi.csproj +++ b/src/apps/Altinn.Authorization.DeployApi/src/Altinn.Authorization.DeployApi/Altinn.Authorization.DeployApi.csproj @@ -22,4 +22,4 @@ Include="..\..\..\..\libs\Altinn.Authorization.Hosting\src\Altinn.Authorization.Hosting\Altinn.Authorization.Hosting.csproj" /> - + \ No newline at end of file diff --git a/src/apps/Altinn.Authorization.Index/src/Altinn.Authorization.Index/Altinn.Authorization.Index.csproj b/src/apps/Altinn.Authorization.Index/src/Altinn.Authorization.Index/Altinn.Authorization.Index.csproj index eb5d39cb..9f488f1e 100644 --- a/src/apps/Altinn.Authorization.Index/src/Altinn.Authorization.Index/Altinn.Authorization.Index.csproj +++ b/src/apps/Altinn.Authorization.Index/src/Altinn.Authorization.Index/Altinn.Authorization.Index.csproj @@ -29,4 +29,4 @@ Include="..\..\..\..\libs\Altinn.Authorization.Hosting\src\Altinn.Authorization.Hosting\Altinn.Authorization.Hosting.csproj" /> - + \ No newline at end of file diff --git a/src/apps/Altinn.Authorization.Index/src/Directory.Build.props b/src/apps/Altinn.Authorization.Index/src/Directory.Build.props index fed9437a..5e119da5 100644 --- a/src/apps/Altinn.Authorization.Index/src/Directory.Build.props +++ b/src/apps/Altinn.Authorization.Index/src/Directory.Build.props @@ -2,7 +2,7 @@ - true + true \ No newline at end of file diff --git a/src/apps/Directory.Build.targets b/src/apps/Directory.Build.targets index 4c4a7c5f..5ed3eede 100644 --- a/src/apps/Directory.Build.targets +++ b/src/apps/Directory.Build.targets @@ -7,7 +7,7 @@ true true - + Altinn-Authorization localhost ghcr.io altinn/altinn-authorization-tmp/$(ContainerName) @@ -25,4 +25,4 @@ - + \ No newline at end of file diff --git a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.OpenTelemetry/Altinn.Authorization.Configuration.OpenTelemetry.csproj b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.OpenTelemetry/Altinn.Authorization.Configuration.OpenTelemetry.csproj index 49b99d57..6e134164 100644 --- a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.OpenTelemetry/Altinn.Authorization.Configuration.OpenTelemetry.csproj +++ b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.OpenTelemetry/Altinn.Authorization.Configuration.OpenTelemetry.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.Postgres/Altinn.Authorization.Configuration.Postgres.csproj b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.Postgres/Altinn.Authorization.Configuration.Postgres.csproj index ee32b598..f0dbef92 100644 --- a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.Postgres/Altinn.Authorization.Configuration.Postgres.csproj +++ b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration.Postgres/Altinn.Authorization.Configuration.Postgres.csproj @@ -1,4 +1,4 @@ - + @@ -9,7 +9,8 @@ - + \ No newline at end of file diff --git a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration/Altinn.Authorization.Configuration.csproj b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration/Altinn.Authorization.Configuration.csproj index ddfa2493..18bddeba 100644 --- a/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration/Altinn.Authorization.Configuration.csproj +++ b/src/libs/Altinn.Authorization.Configuration/src/Altinn.Authorization.Configuration/Altinn.Authorization.Configuration.csproj @@ -1,4 +1,4 @@ - +