[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\n# Create portable, custom editor settings with EditorConfig\n# https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options\n\n# .NET coding convention settings for EditorConfig\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2019\n\n# Language conventions\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019\n\n# Formatting conventions\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019\n\n# .NET naming conventions for EditorConfig\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019\n\n# Top-most EditorConfig file\nroot = true\n\n# Editor default newlines with a newline ending every file\n[*]\ninsert_final_newline = true\ncharset = utf-8\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\n\n[*.json]\ninsert_final_newline = false\n\n[*.cs]\nindent_size = 4\n\n[*.txt]\ninsert_final_newline = false\n\n# Code files\n[*.{cs,vb}]\n\n# .NET code style settings - \"This.\" and \"Me.\" qualifiers\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#this-and-me\ndotnet_style_qualification_for_field = false:warning\ndotnet_style_qualification_for_property = false:warning\ndotnet_style_qualification_for_method = false:warning\ndotnet_style_qualification_for_event = false:warning\n\n# .NET code style settings - Language keywords instead of framework type names for type references\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#language-keywords\ndotnet_style_predefined_type_for_locals_parameters_members = true:error\ndotnet_style_predefined_type_for_member_access = true:error\n\n# .NET code style settings - Modifier preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#normalize-modifiers\ndotnet_style_require_accessibility_modifiers = always:warning\ncsharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning\ndotnet_style_readonly_field = true:warning\n\n# .NET code style settings - Parentheses preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#parentheses-preferences\ndotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion\ndotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion\ndotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:suggestion\ndotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion\n\n# .NET code style settings - Expression-level preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#expression-level-preferences\ndotnet_style_object_initializer = true:error\ndotnet_style_collection_initializer = true:error\ndotnet_style_explicit_tuple_names = true:warning\ndotnet_style_prefer_inferred_tuple_names = true:suggestion\ndotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion\ndotnet_style_prefer_auto_properties = true:warning\ndotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning\ndotnet_style_prefer_conditional_expression_over_assignment = true:suggestion\ndotnet_style_prefer_conditional_expression_over_return = true:suggestion\ndotnet_style_prefer_compound_assignment = true:warning\n\n# .NET code style settings - Null-checking preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#null-checking-preferences\ndotnet_style_coalesce_expression = true:warning\ndotnet_style_null_propagation = true:error\n\n# .NET code quality settings - Parameter preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#parameter-preferences\ndotnet_code_quality_unused_parameters = all:warning\n\n# C# code style settings - Implicit and explicit types\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#implicit-and-explicit-types\ncsharp_style_var_for_built_in_types = false:suggestion\ncsharp_style_var_when_type_is_apparent = true:warning\ncsharp_style_var_elsewhere = true:suggestion\n\n# C# code style settings - Expression-bodied members\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#expression-bodied-members\ncsharp_style_expression_bodied_methods = when_on_single_line:suggestion\ncsharp_style_expression_bodied_constructors = false:warning\ncsharp_style_expression_bodied_operators = when_on_single_line:warning\ncsharp_style_expression_bodied_properties = when_on_single_line:warning\ncsharp_style_expression_bodied_indexers = when_on_single_line:warning\ncsharp_style_expression_bodied_accessors = when_on_single_line:warning\ncsharp_style_expression_bodied_lambdas = when_on_single_line:warning\ncsharp_style_expression_bodied_local_functions = when_on_single_line:warning\n\n# C# code style settings - Pattern matching\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#pattern-matching\ncsharp_style_pattern_matching_over_is_with_cast_check = true:error\ncsharp_style_pattern_matching_over_as_with_null_check = true:error\n\n# C# code style settings - Inlined variable declaration\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#inlined-variable-declarations\ncsharp_style_inlined_variable_declaration = true:error\n\n# C# code style settings - C# expression-level preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#c-expression-level-preferences\ncsharp_prefer_simple_default_expression = true:suggestion\n\n# C# code style settings - C# null-checking preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#c-null-checking-preferences\ncsharp_style_throw_expression = true:warning\ncsharp_style_conditional_delegate_call = true:warning\n\n# C# code style settings - Code block preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#code-block-preferences\ncsharp_prefer_braces = when_multiline:suggestion\n\n# C# code style - Unused value preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#unused-value-preferences\ncsharp_style_unused_value_expression_statement_preference = discard_variable:suggestion\ncsharp_style_unused_value_assignment_preference = discard_variable:suggestion\n\n# C# code style - Index and range preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#index-and-range-preferences\ncsharp_style_prefer_index_operator = true:suggestion\ncsharp_style_prefer_range_operator = true:suggestion\n\n# C# code style - Miscellaneous preferences\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#miscellaneous-preferences\ncsharp_style_deconstructed_variable_declaration = true:suggestion\ncsharp_style_pattern_local_over_anonymous_function = true:suggestion\ncsharp_using_directive_placement = outside_namespace:warning\ncsharp_prefer_static_local_function = true:suggestion\ncsharp_prefer_simple_using_statement = false:suggestion\ncsharp_style_prefer_switch_expression = true:suggestion\n\n# .NET formatting settings - Organize using directives\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#organize-using-directives\ndotnet_sort_system_directives_first = true\ndotnet_separate_import_directive_groups = false\n\n# C# formatting settings - New-line options\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#new-line-options\ncsharp_new_line_before_open_brace = all\ncsharp_new_line_before_else = true\ncsharp_new_line_before_catch = true\ncsharp_new_line_before_finally = true\ncsharp_new_line_before_members_in_object_initializers = true\ncsharp_new_line_before_members_in_anonymous_types = true\ncsharp_new_line_between_query_expression_clauses = true\n\n# C# formatting settings - Indentation options\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#indentation-options\ncsharp_indent_case_contents = true\ncsharp_indent_switch_labels = true\ncsharp_indent_labels = one_less_than_current\ncsharp_indent_block_contents = true\ncsharp_indent_braces = false\ncsharp_indent_case_contents_when_block = false\n\n# C# formatting settings - Spacing options\ncsharp_space_after_cast = false\ncsharp_space_after_keywords_in_control_flow_statements = true\ncsharp_space_between_parentheses = false\ncsharp_space_before_colon_in_inheritance_clause = true\ncsharp_space_after_colon_in_inheritance_clause = true\ncsharp_space_around_binary_operators = before_and_after\ncsharp_space_between_method_declaration_parameter_list_parentheses = false\ncsharp_space_between_method_declaration_empty_parameter_list_parentheses = false\ncsharp_space_between_method_declaration_name_and_open_parenthesis = false\ncsharp_space_between_method_call_parameter_list_parentheses = false\ncsharp_space_between_method_call_empty_parameter_list_parentheses = false\ncsharp_space_between_method_call_name_and_opening_parenthesis = false\ncsharp_space_after_comma = true\ncsharp_space_before_comma = false\ncsharp_space_after_dot = false\ncsharp_space_before_dot = false\ncsharp_space_after_semicolon_in_for_statement = true\ncsharp_space_before_semicolon_in_for_statement = false\ncsharp_space_around_declaration_statements = false\ncsharp_space_before_open_square_brackets = false\ncsharp_space_between_empty_square_brackets = false\ncsharp_space_between_square_brackets = false\n\n# C# formatting settings - Wrap options\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#wrap-options\ncsharp_preserve_single_line_blocks = true\ncsharp_preserve_single_line_statements = false\n\n# C# formatting settings - Namespace options\ncsharp_style_namespace_declarations = file_scoped:suggestion\n\n########## name all private fields using camelCase with underscore prefix ##########\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019\n# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>\ndotnet_naming_rule.private_fields_with_underscore.symbols = private_fields\n\n# dotnet_naming_symbols.<symbolTitle>.<property> = <value>\ndotnet_naming_symbols.private_fields.applicable_kinds = field\ndotnet_naming_symbols.private_fields.applicable_accessibilities = private\n\n# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>\ndotnet_naming_rule.private_fields_with_underscore.style = prefix_underscore\n\n# dotnet_naming_style.<styleTitle>.<property> = <value>\ndotnet_naming_style.prefix_underscore.capitalization = camel_case\ndotnet_naming_style.prefix_underscore.required_prefix = _\n\n# dotnet_naming_rule.<namingRuleTitle>.severity = <value>\ndotnet_naming_rule.private_fields_with_underscore.severity = warning\n\n########## name all constant fields using UPPER_CASE ##########\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019\n# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>\ndotnet_naming_rule.constant_fields_should_be_upper_case.symbols = constant_fields\n\n# dotnet_naming_symbols.<symbolTitle>.<property> = <value>\ndotnet_naming_symbols.constant_fields.applicable_kinds = field\ndotnet_naming_symbols.constant_fields.applicable_accessibilities = *\ndotnet_naming_symbols.constant_fields.required_modifiers = const\n\n# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>\ndotnet_naming_rule.constant_fields_should_be_upper_case.style = upper_case_style\n\n# dotnet_naming_style.<styleTitle>.<property> = <value>\ndotnet_naming_style.upper_case_style.capitalization = all_upper\ndotnet_naming_style.upper_case_style.word_separator = _\n\n# dotnet_naming_rule.<namingRuleTitle>.severity = <value>\ndotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning\n\n########## Async methods should have \"Async\" suffix ##########\n# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019\n# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>\ndotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods\n\n# dotnet_naming_symbols.<symbolTitle>.<property> = <value>\ndotnet_naming_symbols.any_async_methods.applicable_kinds = method\ndotnet_naming_symbols.any_async_methods.applicable_accessibilities = *\ndotnet_naming_symbols.any_async_methods.required_modifiers = async\n\n# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>\ndotnet_naming_rule.async_methods_end_in_async.style = end_in_async_style\n\n# dotnet_naming_style.<styleTitle>.<property> = <value>\ndotnet_naming_style.end_in_async_style.capitalization = pascal_case\ndotnet_naming_style.end_in_async_style.word_separator =\ndotnet_naming_style.end_in_async_style.required_prefix =\ndotnet_naming_style.end_in_async_style.required_suffix = Async\n\n# dotnet_naming_rule.<namingRuleTitle>.severity = <value>\ndotnet_naming_rule.async_methods_end_in_async.severity = warning\n\n# Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005\ndotnet_diagnostic.IDE0005.severity = error\n\n# Enforce formatting https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#rule-id-ide0055-fix-formatting\ndotnet_diagnostic.IDE0055.severity = error\n\n# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS0060.md\ndotnet_diagnostic.RCS0060.severity = warning\nroslynator_blank_line_after_file_scoped_namespace_declaration = true\n\n# https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1080.md\ndotnet_diagnostic.RCS1080.severity = warning\n\n# ConfigureAwait https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1090.md\ndotnet_diagnostic.RCS1090.severity = warning\nroslynator_configure_await = true\n\n# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1102.md\n# TODO: NullabilityInfo issue in Patching.cs in internal class SR\ndotnet_diagnostic.RCS1102.severity = suggestion\n\n# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1194.md\ndotnet_diagnostic.RCS1194.severity = suggestion\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\nopen_collective: graphql-net\n"
  },
  {
    "path": ".github/codecov.yaml",
    "content": "# https://docs.codecov.com/docs/codecov-yaml\ncomment:\n  behavior: new\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file\nversion: 2\nupdates:\n\n- package-ecosystem: \"nuget\"\n  directory: \"/\"\n  schedule:\n    interval: \"daily\"\n  ignore:\n    - dependency-name: \"GraphQL\"\n    - dependency-name: \"GraphQL.MicrosoftDI\"\n    - dependency-name: \"GraphQL.SystemTextJson\"\n    - dependency-name: \"GraphQL.Server.Transports.AspNetCore\"\n    - dependency-name: \"GraphQL.Server.Ui.GraphiQL\"\n    - dependency-name: \"GraphQL.Server.Ui.Playground\"\n\n- package-ecosystem: \"github-actions\"\n  directory: \"/\"\n  schedule:\n    interval: \"daily\"\n"
  },
  {
    "path": ".github/labeler.yml",
    "content": "test:\n  - src/GraphQL.Authorization.Tests/**/*\n  - src/GraphQL.Authorization.ApiTests/**/*\n\nCI:\n  - .github/workflows/**/*\n  - .github/dependabot.yml\n  - .github/labeler.yml\n  - .github/codecov.yml\n\ncode style:\n  - .editorconfig\n\ndocumentation:\n  - README.md\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build artifacts\n\n# ==== NOTE: do not rename this yml file or the run_number will be reset ====\n\non:\n  push:\n    branches:\n      - master\n      - develop\n    paths:\n      - src/**\n      - .github/workflows/**\n\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_CLI_TELEMETRY_OPTOUT: true\n\njobs:\n  pack:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup .NET SDK\n        uses: actions/setup-dotnet@v4\n        with:\n          dotnet-version: \"8.0.x\"\n          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json\n        env:\n          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}\n      - name: Install dependencies\n        working-directory: src\n        run: dotnet restore\n      - name: Build solution [Release]\n        working-directory: src\n        run: dotnet build --no-restore -c Release -p:VersionSuffix=$GITHUB_RUN_NUMBER\n      - name: Pack solution [Release]\n        working-directory: src\n        run: dotnet pack --no-restore --no-build -c Release -p:VersionSuffix=$GITHUB_RUN_NUMBER -o out\n      - name: Upload artifacts\n        uses: actions/upload-artifact@v3\n        with:\n          name: Nuget packages\n          path: |\n            src/out/*\n      - name: Publish Nuget packages to GitHub registry\n        working-directory: src\n        run: dotnet nuget push \"out/*\" -k ${{secrets.GITHUB_TOKEN}}\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# https://github.com/github/codeql\n# https://github.com/github/codeql-action\nname: CodeQL analysis\n\non:\n  push:\n    branches: [master, develop]\n  pull_request:\n    branches: [master, develop]\n\njobs:\n  analyze:\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout source\n      uses: actions/checkout@v4\n\n    - name: Setup .NET SDK\n      uses: actions/setup-dotnet@v4\n      with:\n        dotnet-version: \"8.0.x\"\n        source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json\n      env:\n        NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}\n\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        queries: security-and-quality\n        languages: csharp\n\n    - name: Install dependencies\n      working-directory: src\n      run: dotnet restore\n\n    - name: Build CodeQL solution\n      # https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/troubleshooting-the-codeql-workflow#reduce-the-amount-of-code-being-analyzed-in-a-single-workflow\n      working-directory: codeql\n      run: dotnet build --no-restore\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n"
  },
  {
    "path": ".github/workflows/format.yml",
    "content": "name: Check formatting\n\non:\n  pull_request:\n    paths:\n      - src/**\n      - .github/workflows/**\n\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_CLI_TELEMETRY_OPTOUT: true\n\njobs:\n  format:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout source\n        uses: actions/checkout@v4\n      - name: Setup .NET SDK\n        uses: actions/setup-dotnet@v4\n        with:\n          dotnet-version: 8.0.x\n          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json\n        env:\n          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}\n      - name: Install dependencies\n        working-directory: src\n        run: dotnet restore\n      - name: Check formatting\n        working-directory: src\n        run: |\n          dotnet format --no-restore --verify-no-changes --severity warn || (echo \"Run 'dotnet format' to fix issues\" && exit 1)\n"
  },
  {
    "path": ".github/workflows/label.yml",
    "content": "# This workflow will triage pull requests and apply a label based on the\n# paths that are modified in the pull request.\n#\n# To use this workflow, you will need to set up a .github/labeler.yml\n# file with configuration. For more information, see:\n# https://github.com/actions/labeler/blob/master/README.md\n\nname: Labeler\non:\n  pull_request_target:\n    types:\n      - opened        # when PR is opened\n\njobs:\n  label:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/labeler@v4\n      with:\n        sync-labels: \"\"\n        repo-token: \"${{ secrets.GITHUB_TOKEN }}\"\n      continue-on-error: true\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish release\n\non:\n  release:\n    types:\n      - published\n\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_CLI_TELEMETRY_OPTOUT: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Check github.ref starts with 'refs/tags/'\n        if: ${{ !startsWith(github.ref, 'refs/tags/') }}\n        run: |\n          echo Error! github.ref does not start with 'refs/tags'\n          echo github.ref: ${{ github.ref }}\n          exit 1\n      - name: Set version number environment variable\n        env:\n          github_ref: ${{ github.ref }}\n        run: |\n          version=\"${github_ref:10}\"\n          echo version=$version\n          echo \"version=$version\" >> $GITHUB_ENV\n      - name: Setup .NET SDK\n        uses: actions/setup-dotnet@v4\n        with:\n          dotnet-version: \"8.0.x\"\n          source-url: https://api.nuget.org/v3/index.json\n        env:\n          NUGET_AUTH_TOKEN: ${{secrets.NUGET_AUTH_TOKEN}}\n      - name: Install dependencies\n        working-directory: src\n        run: dotnet restore\n      - name: Build solution [Release]\n        working-directory: src\n        run: dotnet build --no-restore -c Release -p:Version=$version\n      - name: Pack solution [Release]\n        working-directory: src\n        run: dotnet pack --no-restore --no-build -c Release -p:Version=$version -o out\n      - name: Upload Nuget packages as workflow artifacts\n        uses: actions/upload-artifact@v3\n        with:\n          name: Nuget packages\n          path: |\n            src/out/*\n      - name: Publish Nuget packages to Nuget registry\n        working-directory: src\n        run: dotnet nuget push \"out/*\" -k ${{secrets.NUGET_AUTH_TOKEN}}\n      - name: Upload Nuget packages as release artifacts\n        uses: actions/github-script@v6\n        with:\n          github-token: ${{secrets.GITHUB_TOKEN}}\n          script: |\n            console.log('environment', process.versions);\n            const fs = require('fs').promises;\n            const { repo: { owner, repo }, sha } = context;\n\n            for (let file of await fs.readdir('src/out')) {\n              console.log('uploading', file);\n\n              await github.rest.repos.uploadReleaseAsset({\n                owner,\n                repo,\n                release_id: ${{ github.event.release.id }},\n                name: file,\n                data: await fs.readFile(`src/out/${file}`)\n              });\n            }\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Run code tests\n\non:\n  pull_request:\n    paths:\n      - src/**\n      - .github/workflows/**\n  # Upload code coverage results when PRs are merged\n  push:\n    branches:\n      - master\n      - develop\n    paths:\n      - src/**\n      - .github/workflows/**\n\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_CLI_TELEMETRY_OPTOUT: true\n\njobs:\n  test:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest]\n        graphqlversion:\n          - 8.0.0\n    name: ${{ matrix.os }}/${{ matrix.graphqlversion }}\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: Checkout source\n        uses: actions/checkout@v4\n      - name: Setup .NET SDKs\n        uses: actions/setup-dotnet@v4\n        with:\n          dotnet-version: |\n            3.1.x\n            5.0.x\n            6.0.x\n            7.0.x\n            8.0.x\n          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json\n        env:\n          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}\n      - name: Install dependencies with GraphQL version ${{ matrix.graphqlversion }}\n        working-directory: src\n        run: dotnet restore -p:GraphQLTestVersion=${{ matrix.graphqlversion }}\n      - name: Build solution [Release]\n        if: ${{ startsWith(matrix.os, 'ubuntu') }}\n        working-directory: src\n        run: dotnet build --no-restore -c Release -p:GraphQLTestVersion=${{ matrix.graphqlversion }}\n      - name: Build solution [Debug]\n        working-directory: src\n        run: dotnet build --no-restore -c Debug -p:GraphQLTestVersion=${{ matrix.graphqlversion }}\n      - name: Test solution [Debug] with code coverage\n        if: ${{ startsWith(matrix.os, 'ubuntu') }}\n        working-directory: src\n        run: >\n          dotnet test\n          --no-restore\n          --no-build\n          --collect \"XPlat Code Coverage\"\n          --results-directory .coverage\n          --\n          DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover\n          DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[BasicSample]*,[Harness]*\n      - name: Test solution [Debug] without code coverage\n        if: ${{ startsWith(matrix.os, 'windows') }}\n        working-directory: src\n        run: dotnet test --no-restore --no-build\n      - name: Upload coverage to codecov\n        if: ${{ startsWith(matrix.os, 'ubuntu') }}\n        uses: codecov/codecov-action@v3\n        with:\n          files: 'src/.coverage/**/coverage.opencover.xml'\n\n  buildcheck:\n    needs:\n      - test\n    runs-on: ubuntu-latest\n    if: always()\n    steps:\n      - name: Pass build check\n        if: ${{ needs.test.result == 'success' }}\n        run: exit 0\n      - name: Fail build check\n        if: ${{ needs.test.result != 'success' }}\n        run: exit 1\n"
  },
  {
    "path": ".github/workflows/wipcheck.yml",
    "content": "name: Check if PR title contains [WIP]\n\non:\n  pull_request:\n    types:\n      - opened        # when PR is opened\n      - edited        # when PR is edited\n      - synchronize   # when code is added\n      - reopened      # when a closed PR is reopened\n\njobs:\n  check-title:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Fail build if pull request title contains [WIP]\n        env:\n          TITLE: ${{ github.event.pull_request.title }}\n        if: ${{ contains(github.event.pull_request.title, '[WIP]') }} # This function is case insensitive.\n        run: |\n          echo Warning! PR title \"$TITLE\" contains [WIP]. Remove [WIP] from the title when PR is ready.\n          exit 1\n"
  },
  {
    "path": ".gitignore",
    "content": "*.DS_Store\n\n.vs/\n.idea/\n*.user\n*.suo\n*.nupkg\n\n[Oo]bj/\n[Bb]in/\n\n*.received.txt\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  // Use IntelliSense to find out which attributes exist for C# debugging\n  // Use hover for the description of the existing attributes\n  // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"name\": \".NET Core Launch (web)\",\n      \"type\": \"coreclr\",\n      \"request\": \"launch\",\n      \"preLaunchTask\": \"build-harness\",\n      \"program\": \"${workspaceFolder}/src/Harness/bin/Debug/netcoreapp3.1/Harness.dll\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}/src/Harness\",\n      \"stopAtEntry\": false,\n      \"internalConsoleOptions\": \"openOnSessionStart\",\n      \"launchBrowser\": {\n        \"enabled\": true,\n        \"args\": \"${auto-detect-url}\",\n        \"windows\": {\n          \"command\": \"cmd.exe\",\n          \"args\": \"/C start ${auto-detect-url}\"\n        },\n        \"osx\": {\n          \"command\": \"open\",\n          \"args\": \"http://localhost:3000/ui/graphiql\"\n        },\n        \"linux\": {\n          \"command\": \"xdg-open\"\n        }\n      },\n      \"env\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n        \"ASPNETCORE_URLS\": \"http://localhost:3000\"\n      },\n      \"sourceFileMap\": {\n        \"/Views\": \"${workspaceFolder}/Views\"\n      }\n    },\n    {\n      \"name\": \".NET Core Launch (console)\",\n      \"type\": \"coreclr\",\n      \"request\": \"launch\",\n      \"preLaunchTask\": \"build-tests\",\n      \"program\": \"${workspaceFolder}/src/GraphQL.Authorization.Tests/bin/Debug/netcoreapp3.1/GraphQL.Authorization.Tests.dll\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}/src/GraphQL.Authorization.Tests\",\n      \"console\": \"internalConsole\",\n      \"stopAtEntry\": false,\n      \"internalConsoleOptions\": \"openOnSessionStart\"\n    },\n    {\n      \"name\": \".NET Core Attach\",\n      \"type\": \"coreclr\",\n      \"request\": \"attach\",\n      \"processId\": \"${command:pickProcess}\"\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"build-harness\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/src/Harness/Harness.csproj\"\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"build-tests\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/src/GraphQL.Authorization.Tests/GraphQL.Authorization.Tests.csproj\"\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2017 Joseph T. McBride\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# GraphQL Authorization\n\n[![License](https://img.shields.io/github/license/graphql-dotnet/authorization)](LICENSE.md)\n[![codecov](https://codecov.io/gh/graphql-dotnet/authorization/branch/master/graph/badge.svg?token=TODO)](https://codecov.io/gh/graphql-dotnet/authorization)\n[![Nuget](https://img.shields.io/nuget/dt/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization)\n[![Nuget](https://img.shields.io/nuget/v/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization)\n[![GitHub Release Date](https://img.shields.io/github/release-date/graphql-dotnet/authorization?label=released)](https://github.com/graphql-dotnet/authorization/releases)\n[![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/graphql-dotnet/authorization/latest?label=new+commits)](https://github.com/graphql-dotnet/authorization/commits/master)\n![Size](https://img.shields.io/github/repo-size/graphql-dotnet/authorization)\n\n[![GitHub contributors](https://img.shields.io/github/contributors/graphql-dotnet/authorization)](https://github.com/graphql-dotnet/authorization/graphs/contributors)\n![Activity](https://img.shields.io/github/commit-activity/w/graphql-dotnet/authorization)\n![Activity](https://img.shields.io/github/commit-activity/m/graphql-dotnet/authorization)\n![Activity](https://img.shields.io/github/commit-activity/y/graphql-dotnet/authorization)\n\nA toolset for authorizing access to graph types for [GraphQL.NET](https://github.com/graphql-dotnet/graphql-dotnet).\n\nProvides the following packages:\n\n| Package               | Downloads                                                                                                               | NuGet Latest                                                                                                           |\n| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| GraphQL.Authorization | [![Nuget](https://img.shields.io/nuget/dt/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization) | [![Nuget](https://img.shields.io/nuget/v/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization) |\n\nYou can get all preview versions from [GitHub Packages](https://github.com/orgs/graphql-dotnet/packages?repo_name=authorization).\nNote that GitHub requires authentication to consume the feed. See [here](https://docs.github.com/en/free-pro-team@latest/packages/publishing-and-managing-packages/about-github-packages#authenticating-to-github-packages).\n\n# Usage\n\n- Register the authorization classes in your DI container - call `AddAuthorization` on the provided `IGraphQLBuilder` inside `AddGraphQL` extension method.\n- Provide the `ClaimsPrincipal` through `ExecutionOptions.User`.\n- Add policies to the `AuthorizationSettings`.\n- Apply a policy to a GraphType or Field - both implement `IProvideMetadata`:\n  - using `AuthorizeWithPolicy(string policy)` extension method\n  - or with `AuthorizeAttribute` attribute if using Schema + Handler syntax.\n- The `AuthorizationValidationRule` will run and verify the policies based on the registered policies.\n- You can write your own `IAuthorizationRequirement`.\n\n# Limitations\n\n`@skip` and `@include` directives are ignored; all selected fields of the selected operation will\nbe checked for authentication requirements, including referenced fragments. (Other operations\nin the same document will correctly be skipped.)\n\nThis authorization framework only supports policy-based authorization. It does not support role-based authorization, or the\n`[AllowAnonymous]` attribute/extension, or the `[Authorize]` attribute/extension indicating authorization is required\nbut without specifying a policy. It also does not integrate with ASP.NET Core's authorization framework.\n\nThe [GraphQL.Server](https://www.github.com/graphql-dotnet/server) repository contains an authorization rule which has the above\nmissing features, intended for use with ASP.NET Core. It may also be tailored with custom authentication code if desired, rather than\nrelying on ASP.NET Core's authentication framework.\n\n# Examples\n\n1. Fully functional basic [Console sample](src/BasicSample/Program.cs).\n\n2. Fully functional [ASP.NET Core sample](src/Harness/Program.cs).\n\n3. GraphType first syntax - use `AuthorizeWithPolicy` extension method on `IGraphType` or `IFieldType`.\n\n```csharp\npublic class MyType : ObjectGraphType\n{\n    public MyType()\n    {\n        this.AuthorizeWithPolicy(\"AdminPolicy\");\n        Field<StringGraphType>(\"name\").AuthorizeWithPolicy(\"SomePolicy\");\n    }\n}\n```\n\n4. Schema first syntax - use `AuthorizeAttribute` attribute on type, method or property.\n\n```csharp\n[Authorize(\"MyPolicy\")]\npublic class MutationType\n{\n    [Authorize(\"AnotherPolicy\")]\n    public async Task<string> CreateSomething(MyInput input)\n    {\n        return await SomeMethodAsync(input);\n    }\n\n    [Authorize(\"SuperPolicy\")]\n    public string SomeProperty => Guid.NewGuid().ToString();\n}\n```\n\n# Known Issues\n\n- It is currently not possible to add a policy to Input objects using Schema first approach.\n"
  },
  {
    "path": "codeql/GraphQL.Authorization.CodeQL.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.31919.166\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"GraphQL.Authorization\", \"..\\src\\GraphQL.Authorization\\GraphQL.Authorization.csproj\", \"{C9953353-2407-4A2D-8E2A-A5F62DEED89C}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {A0696AC3-8123-4422-B489-C58B78E24B27}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/BasicSample/BasicSample.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Harness\\GraphQL.cs\" Link=\"GraphQL.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\GraphQL.Authorization\\GraphQL.Authorization.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"GraphQL.MicrosoftDI\" Version=\"8.*\" />\n    <PackageReference Include=\"GraphQL.SystemTextJson\" Version=\"8.*\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"8.*\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/BasicSample/Program.cs",
    "content": "using System.Security.Claims;\nusing GraphQL;\nusing GraphQL.SystemTextJson;\nusing GraphQL.Types;\nusing GraphQL.Validation;\nusing Microsoft.Extensions.DependencyInjection;\n\nvar services = new ServiceCollection().AddGraphQL(builder => builder\n    .AddAuthorization(settings => settings.AddPolicy(\"AdminPolicy\", p => p.RequireClaim(\"role\", \"Admin\"))));\n\nusing var serviceProvider = services.BuildServiceProvider();\n\nconst string definitions = \"\"\"\n    type User {\n        id: ID\n        name: String\n    }\n\n    type Query {\n        viewer: User\n        users: [User]\n    }\n    \"\"\";\nvar schema = Schema.For(definitions, builder => builder.Types.Include<Query>());\n\n// Claims principal must look something like this to allow access.\n// GraphQLUserContext.User alternates below for demonstration purposes.\nint counter = 0;\nvar authorizedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(\"role\", \"Admin\") }));\nvar nonAuthorizedUser = new ClaimsPrincipal(new ClaimsIdentity());\n\nwhile (true)\n{\n    string json = await schema.ExecuteAsync(options =>\n    {\n        options.Query = \"{ viewer { id name } }\";\n        options.Root = new Query();\n        options.ValidationRules = DocumentValidator.CoreRules.Concat(serviceProvider.GetServices<IValidationRule>());\n        options.RequestServices = serviceProvider;\n        options.User = counter++ % 2 == 0 ? authorizedUser : nonAuthorizedUser;\n    }).ConfigureAwait(false);\n\n    Console.WriteLine(json);\n    Console.WriteLine();\n    Console.WriteLine(\"Press ENTER to continue\");\n    Console.ReadLine();\n}\n"
  },
  {
    "path": "src/Directory.Build.props",
    "content": "<Project>\n\n  <PropertyGroup>\n    <VersionPrefix>8.0.0-preview</VersionPrefix>\n    <NextVersion>9.0.0</NextVersion>\n    <LangVersion>latest</LangVersion>\n    <Authors>Joe McBride</Authors>\n    <PackageLicenseExpression>MIT</PackageLicenseExpression>\n    <PackageIcon>logo.64x64.png</PackageIcon>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <RepositoryType>git</RepositoryType>\n    <PublishRepositoryUrl>true</PublishRepositoryUrl>\n    <Deterministic>true</Deterministic>\n    <!-- https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables -->\n    <!-- https://github.com/clairernovotny/DeterministicBuilds -->\n    <ContinuousIntegrationBuild Condition=\"'$(GITHUB_ACTIONS)' == 'true'\">True</ContinuousIntegrationBuild>\n    <DebugType>embedded</DebugType>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <EmbedUntrackedSources>true</EmbedUntrackedSources>\n    <EnableNETAnalyzers>true</EnableNETAnalyzers>\n    <IsPackable>true</IsPackable>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n    <CheckEolTargetFramework>false</CheckEolTargetFramework>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Roslynator.Analyzers\" Version=\"4.4.0\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Roslynator.Formatting.Analyzers\" Version=\"4.4.0\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Directory.Build.targets",
    "content": "<Project>\n\n  <PropertyGroup Condition=\"'$(IsPackable)' == 'true'\">\n    <PackageReadmeFile>README.md</PackageReadmeFile>\n    <PackageReleaseNotes>See https://github.com/graphql-dotnet/authorization/releases</PackageReleaseNotes>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(IsPackable)' != 'true'\">\n    <NoWarn>$(NoWarn);1591</NoWarn>\n    <WarningsNotAsErrors>$(WarningsNotAsErrors);IDE0053</WarningsNotAsErrors>\n  </PropertyGroup>\n\n  <ItemGroup Condition=\"'$(IsPackable)' == 'true'\">\n    <None Include=\"..\\..\\assets\\logo.64x64.png\" Pack=\"true\" PackagePath=\"\\\" Visible=\"false\" />\n    <None Include=\"..\\..\\README.md\" Pack=\"true\" PackagePath=\"\\\" Visible=\"false\" />\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.1.1\" PrivateAssets=\"All\" />\n  </ItemGroup>\n\n  <!--Workaround for https://github.com/NuGet/Home/issues/5556 and https://github.com/NuGet/Home/issues/5525-->\n  <Target Name=\"UseExplicitPackageVersions\" BeforeTargets=\"GenerateNuspec\">\n    <ItemGroup>\n      <_ProjectReferenceWithExplicitPackageVersion Include=\"@(ProjectReference->'%(FullPath)')\" Condition=\"'%(ProjectReference.PackageVersion)' != ''\" />\n      <_ProjectReferenceWithExactPackageVersion Include=\"@(ProjectReference->'%(FullPath)')\" Condition=\"'%(ProjectReference.ExactVersion)' == 'true'\" />\n      <_ProjectReferenceWithReassignedVersion Include=\"@(_ProjectReferencesWithVersions)\" Condition=\"'%(Identity)' != '' And '@(_ProjectReferenceWithExplicitPackageVersion)' == '@(_ProjectReferencesWithVersions)'\">\n        <ProjectVersion>@(_ProjectReferenceWithExplicitPackageVersion->'%(PackageVersion)')</ProjectVersion>\n      </_ProjectReferenceWithReassignedVersion>\n      <_ProjectReferenceWithReassignedVersion Include=\"@(_ProjectReferencesWithVersions)\" Condition=\"'%(Identity)' != '' And '@(_ProjectReferenceWithExactPackageVersion)' == '@(_ProjectReferencesWithVersions)'\">\n        <ProjectVersion>[@(_ProjectReferencesWithVersions->'%(ProjectVersion)')]</ProjectVersion>\n      </_ProjectReferenceWithReassignedVersion>\n      <_ProjectReferencesWithVersions Remove=\"@(_ProjectReferenceWithReassignedVersion)\" />\n      <_ProjectReferencesWithVersions Include=\"@(_ProjectReferenceWithReassignedVersion)\" />\n    </ItemGroup>\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationContext.cs",
    "content": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Provides context information for <see cref=\"IAuthorizationRequirement\"/>.\n/// </summary>\npublic class AuthorizationContext\n{\n    private List<string>? _errors;\n\n    /// <summary>\n    /// Current user.\n    /// </summary>\n    public ClaimsPrincipal? User { get; set; }\n\n    /// <summary>\n    /// Arbitrary user defined context represented as dictionary.\n    /// </summary>\n    public IDictionary<string, object?>? UserContext { get; set; }\n\n    /// <summary>\n    /// Represents a readonly dictionary of variables to an executed document.\n    /// </summary>\n    public Inputs? Variables { get; set; }\n\n    /// <summary>\n    /// Returns a set of authorization errors.\n    /// </summary>\n    public IEnumerable<string> Errors => _errors ?? Enumerable.Empty<string>();\n\n    /// <summary>\n    /// Returns whether there are any errors.\n    /// </summary>\n    public bool HasErrors => _errors?.Count > 0;\n\n    /// <summary>\n    /// Reports an error during evaluation of policy requirement.\n    /// </summary>\n    /// <param name=\"error\">Error message.</param>\n    public void ReportError(string error) => (_errors ??= new()).Add(error);\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationEvaluator.cs",
    "content": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Default implementation of <see cref=\"IAuthorizationEvaluator\"/>.\n/// </summary>\npublic class AuthorizationEvaluator : IAuthorizationEvaluator\n{\n    private readonly AuthorizationSettings _settings;\n\n    /// <summary>\n    /// Creates an instance of <see cref=\"AuthorizationEvaluator\"/> with the\n    /// specified authorization settings.\n    /// </summary>\n    public AuthorizationEvaluator(AuthorizationSettings settings)\n    {\n        _settings = settings;\n    }\n\n    /// <inheritdoc />\n    public async Task<AuthorizationResult> Evaluate(\n        ClaimsPrincipal? principal,\n        IDictionary<string, object?>? userContext,\n        Inputs? variables,\n        IEnumerable<string>? requiredPolicies)\n    {\n        if (requiredPolicies == null)\n            return AuthorizationResult.Success();\n\n        var context = new AuthorizationContext\n        {\n            User = principal ?? new ClaimsPrincipal(new ClaimsIdentity()),\n            UserContext = userContext,\n            Variables = variables\n        };\n\n        var tasks = new List<Task>();\n\n        foreach (string requiredPolicy in requiredPolicies)\n        {\n            var authorizationPolicy = _settings.GetPolicy(requiredPolicy);\n            if (authorizationPolicy == null)\n            {\n                context.ReportError($\"Required policy '{requiredPolicy}' is not present.\");\n            }\n            else\n            {\n                foreach (var r in authorizationPolicy.Requirements)\n                {\n                    var task = r.Authorize(context);\n                    tasks.Add(task);\n                }\n            }\n        }\n\n        await Task.WhenAll(tasks).ConfigureAwait(false);\n\n        return context.HasErrors\n            ? AuthorizationResult.Fail(context.Errors)\n            : AuthorizationResult.Success();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationPolicy.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Default implementation for <see cref=\"IAuthorizationPolicy\"/>.\n/// </summary>\npublic class AuthorizationPolicy : IAuthorizationPolicy\n{\n    private readonly List<IAuthorizationRequirement> _requirements = new();\n\n    /// <summary>\n    /// Creates a policy with a set of specified requirements.\n    /// </summary>\n    /// <param name=\"requirements\">Specified requirements.</param>\n    public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requirements)\n    {\n        if (requirements != null)\n        {\n            _requirements.AddRange(requirements);\n            _requirements.ForEach(req =>\n            {\n                if (req == null)\n                    throw new ArgumentNullException(nameof(requirements), $\"One of the ({_requirements.Count}) requirements is null\");\n            });\n        }\n    }\n\n    /// <inheritdoc />\n    public IEnumerable<IAuthorizationRequirement> Requirements => _requirements;\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationPolicyBuilder.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Configures and then builds authorization policy from various authorization requirements.\n/// Provides fluent API.\n/// </summary>\npublic class AuthorizationPolicyBuilder\n{\n    private readonly List<IAuthorizationRequirement> _requirements = new();\n\n    /// <summary>\n    /// Build authorization policy.\n    /// </summary>\n    /// <returns>Created policy.</returns>\n    public AuthorizationPolicy Build() => new(_requirements);\n\n    /// <summary>\n    /// Adds <see cref=\"ClaimAuthorizationRequirement\"/> with the specified claim type.\n    /// </summary>\n    /// <param name=\"claimType\">Type of the claim.</param>\n    /// <returns>Reference to the same builder.</returns>\n    public AuthorizationPolicyBuilder RequireClaim(string claimType)\n    {\n        _requirements.Add(new ClaimAuthorizationRequirement(claimType));\n        return this;\n    }\n\n    /// <summary>\n    /// Adds <see cref=\"ClaimAuthorizationRequirement\"/> with the specified claim type and allowed values.\n    /// </summary>\n    /// <param name=\"claimType\">Type of the claim.</param>\n    /// <param name=\"allowedValues\">Allowed values for this claim.</param>\n    /// <returns>Reference to the same builder.</returns>\n    public AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues)\n    {\n        _requirements.Add(new ClaimAuthorizationRequirement(claimType, allowedValues));\n        return this;\n    }\n\n    /// <summary>\n    /// Adds <see cref=\"ClaimAuthorizationRequirement\"/> with the specified claim type, allowed values and display values.\n    /// </summary>\n    /// <param name=\"claimType\">Type of the claim.</param>\n    /// <param name=\"allowedValues\">Allowed values for this claim.</param>\n    /// <param name=\"displayValues\">\n    /// Display values for this claim. If no allowed claims are found, display values will be used to generate\n    /// an error message for <see cref=\"AuthorizationContext.Errors\"/>.\n    /// </param>\n    /// <returns>Reference to the same builder.</returns>\n    public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnumerable<string>? allowedValues, IEnumerable<string>? displayValues)\n    {\n        _requirements.Add(new ClaimAuthorizationRequirement(claimType, allowedValues, displayValues));\n        return this;\n    }\n\n    /// <summary>\n    /// Adds <see cref=\"AuthenticatedUserRequirement\"/>.\n    /// </summary>\n    /// <returns>Reference to the same builder.</returns>\n    public AuthorizationPolicyBuilder RequireAuthenticatedUser()\n    {\n        _requirements.Add(AuthenticatedUserRequirement.Instance);\n        return this;\n    }\n\n    /// <summary>\n    /// Adds specified authorization requirement.\n    /// </summary>\n    /// <param name=\"requirement\">Authorization requirement.</param>\n    /// <returns>Reference to the same builder.</returns>\n    public AuthorizationPolicyBuilder AddRequirement(IAuthorizationRequirement requirement)\n    {\n        _requirements.Add(requirement ?? throw new ArgumentNullException(nameof(requirement)));\n        return this;\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationResult.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Represents the result of an authorization evaluation.\n/// </summary>\npublic class AuthorizationResult\n{\n    // allocation optimization for green path\n    private static readonly AuthorizationResult _success = new() { Succeeded = true };\n\n    /// <summary>\n    /// Is the authorization result successful?\n    /// </summary>\n    public bool Succeeded { get; private set; }\n\n    /// <summary>\n    /// Returns a set of authorization errors if the authorization result is unsuccessful.\n    /// </summary>\n    public IEnumerable<string>? Errors { get; private set; }\n\n    /// <summary>\n    /// Creates successful authorization result.\n    /// </summary>\n    /// <returns>Instance of <see cref=\"AuthorizationResult\"/>.</returns>\n    public static AuthorizationResult Success() => _success;\n\n    /// <summary>\n    /// Creates unsuccessful authorization result\n    /// </summary>\n    /// <param name=\"errors\">A set of authorization errors.</param>\n    /// <returns>Instance of <see cref=\"AuthorizationResult\"/>.</returns>\n    public static AuthorizationResult Fail(IEnumerable<string> errors) => new() { Errors = errors };\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationSettings.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Authorization settings are represented by a set of named policies\n/// where each policy has a set of authorization requirements.\n/// </summary>\npublic class AuthorizationSettings\n{\n    private readonly IDictionary<string, IAuthorizationPolicy> _policies = new Dictionary<string, IAuthorizationPolicy>(StringComparer.OrdinalIgnoreCase);\n\n    /// <summary>\n    /// Returns all policies.\n    /// </summary>\n    public IEnumerable<IAuthorizationPolicy> Policies => _policies.Values;\n\n    /// <summary>\n    /// Returns policies with the specified names.\n    /// </summary>\n    /// <param name=\"policies\">A set of policies names.</param>\n    /// <returns>Policies with matched names.</returns>\n    public IEnumerable<IAuthorizationPolicy> GetPolicies(IEnumerable<string> policies)\n    {\n        List<IAuthorizationPolicy>? found = null;\n\n        if (policies != null)\n        {\n            foreach (string name in policies)\n            {\n                var policy = GetPolicy(name);\n                if (policy != null)\n                    (found ??= new()).Add(policy);\n            }\n        }\n\n        return found ?? Enumerable.Empty<IAuthorizationPolicy>();\n    }\n\n    /// <summary>\n    /// Returns one policy with the specified name.\n    /// </summary>\n    /// <param name=\"name\">Name of the required policy.</param>\n    /// <returns>Required policy if exists, otherwise <see langword=\"null\"/>.</returns>\n    public IAuthorizationPolicy? GetPolicy(string name) => _policies.TryGetValue(name, out var policy) ? policy : null;\n\n    /// <summary>\n    /// Adds a policy with the specified name. If a policy with that name already exists then it will be replaced.\n    /// </summary>\n    /// <param name=\"name\">Policy name.</param>\n    /// <param name=\"policy\">Policy to add.</param>\n    public void AddPolicy(string name, IAuthorizationPolicy policy) => _policies[name] = policy;\n\n    /// <summary>\n    /// Adds a policy built from <see cref=\"AuthorizationPolicyBuilder\"/> with the specified name.\n    /// </summary>\n    /// <param name=\"name\">Policy name.</param>\n    /// <param name=\"configure\">Delegate to configure provided policy builder.</param>\n    public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> configure)\n    {\n        if (configure == null)\n            throw new ArgumentNullException(nameof(configure));\n\n        var builder = new AuthorizationPolicyBuilder();\n        configure(builder);\n\n        _policies[name] = builder.Build();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationValidationRule.cs",
    "content": "using GraphQL.Types;\nusing GraphQL.Validation;\nusing GraphQLParser.AST;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// GraphQL authorization validation rule which evaluates configured\n/// (via policies) requirements on schema elements: types, fields, etc.\n/// </summary>\npublic class AuthorizationValidationRule : ValidationRuleBase\n{\n    private readonly IAuthorizationEvaluator _evaluator;\n\n    /// <summary>\n    /// Creates an instance of <see cref=\"AuthorizationValidationRule\"/> with\n    /// the specified authorization evaluator.\n    /// </summary>\n    public AuthorizationValidationRule(IAuthorizationEvaluator evaluator)\n    {\n        _evaluator = evaluator;\n    }\n\n    /// <inheritdoc />\n    public override async ValueTask<INodeVisitor?> GetPreNodeVisitorAsync(ValidationContext context)\n    {\n        var visitor = new Visitor(_evaluator);\n\n        await visitor.AuthorizeAsync(null, context.Schema, context).ConfigureAwait(false);\n\n        // this could leak info about hidden fields or types in error messages\n        // it would be better to implement a filter on the Schema so it\n        // acts as if they just don't exist vs. an auth denied error\n        // - filtering the Schema is not currently supported\n        // TODO: apply ISchemaFilter - context.Schema.Filter.AllowXXX\n        return visitor;\n    }\n\n    private class Visitor : INodeVisitor\n    {\n        private readonly IAuthorizationEvaluator _evaluator;\n        private bool _validate;\n\n        public Visitor(IAuthorizationEvaluator evaluator)\n        {\n            _evaluator = evaluator;\n        }\n\n        public async ValueTask EnterAsync(ASTNode node, ValidationContext context)\n        {\n            if ((node is GraphQLOperationDefinition astType && astType == context.Operation) ||\n                (node is GraphQLFragmentDefinition fragment && (context.GetRecursivelyReferencedFragments(context.Operation)?.Contains(fragment) ?? false)))\n            {\n                var type = context.TypeInfo.GetLastType();\n                await AuthorizeAsync(node, type, context).ConfigureAwait(false);\n                _validate = true;\n            }\n\n            if (!_validate)\n                return;\n\n            if (node is GraphQLObjectField objectFieldAst &&\n                context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is IComplexGraphType argumentType)\n            {\n                var fieldType = argumentType.GetField(objectFieldAst.Name);\n                await AuthorizeAsync(objectFieldAst, fieldType, context).ConfigureAwait(false);\n            }\n\n            if (node is GraphQLField fieldAst)\n            {\n                var fieldDef = context.TypeInfo.GetFieldDef();\n\n                if (fieldDef == null)\n                    return;\n\n                // check target field\n                await AuthorizeAsync(fieldAst, fieldDef, context).ConfigureAwait(false);\n                // check returned graph type\n                await AuthorizeAsync(fieldAst, fieldDef.ResolvedType?.GetNamedType(), context).ConfigureAwait(false);\n            }\n\n            if (node is GraphQLVariable variableRef)\n            {\n                if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is not IComplexGraphType variableType)\n                    return;\n\n                await AuthorizeAsync(variableRef, variableType, context).ConfigureAwait(false);\n\n                // Check each supplied field in the variable that exists in the variable type.\n                // If some supplied field does not exist in the variable type then some other\n                // validation rule should check that but here we should just ignore that\n                // \"unknown\" field.\n                if (context.Variables != null &&\n                    context.Variables.TryGetValue(variableRef.Name.StringValue, out object? input) && //ISSUE:allocation\n                    input is Dictionary<string, object> fieldsValues)\n                {\n                    foreach (var field in variableType.Fields)\n                    {\n                        if (fieldsValues.ContainsKey(field.Name))\n                        {\n                            await AuthorizeAsync(variableRef, field, context).ConfigureAwait(false);\n                        }\n                    }\n                }\n            }\n        }\n\n        public ValueTask LeaveAsync(ASTNode node, ValidationContext context)\n        {\n            if (node is GraphQLOperationDefinition || node is GraphQLFragmentDefinition)\n                _validate = false;\n\n            return default;\n        }\n\n        public async ValueTask AuthorizeAsync(ASTNode? node, IMetadataReader? provider, ValidationContext context)\n        {\n            if (provider == null || !provider.IsAuthorizationRequired())\n                return;\n\n            var result = await _evaluator.Evaluate(context.User, context.UserContext, context.Variables, provider.GetPolicies()).ConfigureAwait(false);\n\n            if (result.Succeeded)\n                return;\n\n            string errors = string.Join(\"\\n\", result.Errors);\n\n            context.ReportError(new ValidationError(\n                context.Document.Source,\n                \"authorization\",\n                $\"You are not authorized to run this {context.Operation.Operation.ToString().ToLower()}.\\n{errors}\",\n                node == null ? Array.Empty<ASTNode>() : new ASTNode[] { node }));\n        }\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/Extensions/AuthorizationGraphQLBuilderExtensions.cs",
    "content": "using GraphQL.Authorization;\nusing GraphQL.DI;\n\nnamespace GraphQL;\n\n/// <summary>\n/// Authorization extension methods for <see cref=\"IGraphQLBuilder\"/>.\n/// </summary>\npublic static class AuthorizationGraphQLBuilderExtensions\n{\n    /// <summary>\n    /// Registers <see cref=\"AuthorizationEvaluator\"/> and <see cref=\"AuthorizationValidationRule\"/> within the\n    /// dependency injection framework and configures the validation rule to be added to the list of validation rules\n    /// within <see cref=\"ExecutionOptions.ValidationRules\"/> and <see cref=\"ExecutionOptions.CachedDocumentValidationRules\"/>\n    /// upon document execution. Configures authorization settings with the specified configuration delegate.\n    /// </summary>\n    public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings, IServiceProvider> configure)\n    {\n        builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);\n        builder.AddValidationRule<AuthorizationValidationRule>(true);\n        builder.Services.Configure(configure);\n        return builder;\n    }\n\n    /// <inheritdoc cref=\"AddAuthorization(IGraphQLBuilder, Action{AuthorizationSettings, IServiceProvider})\"/>\n    public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings> configure)\n    {\n        builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);\n        builder.AddValidationRule<AuthorizationValidationRule>(true);\n        builder.Services.Configure(configure);\n        return builder;\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/GraphQL.Authorization.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <Description>A toolset for authorizing access to graph types for GraphQL.NET</Description>\n    <PackageTags>GraphQL;json;api</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"GraphQL\" Version=\"8.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/GraphQL.Authorization/IAuthorizationEvaluator.cs",
    "content": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Interface to evaluate the authorization result.\n/// </summary>\npublic interface IAuthorizationEvaluator\n{\n    /// <summary>\n    /// Evaluates authorization result.\n    /// </summary>\n    /// <param name=\"principal\">Represents the current user.</param>\n    /// <param name=\"userContext\">Arbitrary user defined context represented as dictionary.</param>\n    /// <param name=\"variables\">Represents a readonly dictionary of variables to an executed document.</param>\n    /// <param name=\"requiredPolicies\">A set of policies names to authorize.</param>\n    /// <returns></returns>\n    Task<AuthorizationResult> Evaluate(\n        ClaimsPrincipal? principal,\n        IDictionary<string, object?>? userContext,\n        Inputs? variables,\n        IEnumerable<string>? requiredPolicies);\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/IAuthorizationPolicy.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Policy is a named set of <see cref=\"IAuthorizationRequirement\"/>.\n/// </summary>\npublic interface IAuthorizationPolicy\n{\n    /// <summary>\n    /// Returns all requirements of this policy.\n    /// </summary>\n    IEnumerable<IAuthorizationRequirement> Requirements { get; }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/AuthenticatedUserRequirement.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Implements an <see cref=\"IAuthorizationRequirement\"/> which requires that\n/// current user from <see cref=\"AuthorizationContext.User\"/> must be authenticated.\n/// </summary>\npublic class AuthenticatedUserRequirement : IAuthorizationRequirement\n{\n    internal static readonly AuthenticatedUserRequirement Instance = new();\n\n    /// <inheritdoc />\n    public Task Authorize(AuthorizationContext context)\n    {\n        if (context.User == null || !context.User.Identities.Any(x => x.IsAuthenticated))\n        {\n            context.ReportError(\"An authenticated user is required.\");\n        }\n\n        return Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/ClaimAuthorizationRequirement.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Implements an <see cref=\"IAuthorizationRequirement\"/> which requires an instance of the specified\n/// claim type, and, if allowed values are specified, the claim value must be any of the allowed values.\n/// </summary>\npublic class ClaimAuthorizationRequirement : IAuthorizationRequirement\n{\n    /// <summary>\n    /// Creates a new instance of <see cref=\"ClaimAuthorizationRequirement\"/> with\n    /// the specified claim type.\n    /// </summary>\n    public ClaimAuthorizationRequirement(string claimType)\n        : this(claimType, (IEnumerable<string>?)null, null)\n    {\n    }\n\n    /// <summary>\n    /// Creates a new instance of <see cref=\"ClaimAuthorizationRequirement\"/> with\n    /// the specified claim type and optional list of claim values, which, if present,\n    /// the claim must match.\n    /// </summary>\n    public ClaimAuthorizationRequirement(string claimType, IEnumerable<string> allowedValues)\n        : this(claimType, allowedValues, null)\n    {\n    }\n\n    /// <summary>\n    /// Creates a new instance of <see cref=\"ClaimAuthorizationRequirement\"/> with\n    /// the specified claim type and optional list of claim values, which, if present,\n    /// the claim must match.\n    /// </summary>\n    public ClaimAuthorizationRequirement(string claimType, params string[] allowedValues)\n        : this(claimType, allowedValues, null)\n    {\n    }\n\n    /// <summary>\n    /// Creates a new instance of <see cref=\"ClaimAuthorizationRequirement\"/> with\n    /// the specified claim type and optional list of claim values, which, if present,\n    /// the claim must match. Additional <paramref name=\"displayValues\"/> argument\n    /// specifies the set of displayed claim values that will be used to generate an\n    /// error message if the requirement is not met.\n    /// </summary>\n    public ClaimAuthorizationRequirement(string claimType, IEnumerable<string>? allowedValues, IEnumerable<string>? displayValues)\n    {\n        ClaimType = claimType ?? throw new ArgumentNullException(nameof(claimType));\n        AllowedValues = allowedValues ?? Enumerable.Empty<string>();\n        DisplayValues = displayValues;\n    }\n\n    /// <summary>\n    /// Claim type that claims principal from <see cref=\"AuthorizationContext\"/> should have.\n    /// </summary>\n    public string ClaimType { get; }\n\n    /// <summary>\n    /// List of claim values, which, if present, the claim must match.\n    /// </summary>\n    public IEnumerable<string> AllowedValues { get; }\n\n    /// <summary>\n    /// Specifies the set of displayed claim values that will be used\n    /// to generate an error message if the requirement is not met.\n    /// If null then values from <see cref=\"AllowedValues\"/> are used.\n    /// </summary>\n    public IEnumerable<string>? DisplayValues { get; }\n\n    /// <inheritdoc />\n    public Task Authorize(AuthorizationContext context)\n    {\n        bool found = false;\n\n        if (context.User != null)\n        {\n            if (AllowedValues == null || !AllowedValues.Any())\n            {\n                found = context.User.Claims.Any(\n                    claim => string.Equals(claim.Type, ClaimType, StringComparison.OrdinalIgnoreCase));\n            }\n            else\n            {\n                found = context.User.Claims.Any(\n                    claim => string.Equals(claim.Type, ClaimType, StringComparison.OrdinalIgnoreCase)\n                         && AllowedValues.Contains(claim.Value, StringComparer.Ordinal));\n            }\n        }\n\n        if (!found)\n        {\n            if (AllowedValues != null && AllowedValues.Any())\n            {\n                string values = string.Join(\", \", DisplayValues ?? AllowedValues);\n                context.ReportError($\"Required claim '{ClaimType}' with any value of '{values}' is not present.\");\n            }\n            else\n            {\n                context.ReportError($\"Required claim '{ClaimType}' is not present.\");\n            }\n        }\n\n        return Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/IAuthorizationRequirement.cs",
    "content": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Represents an authorization requirement.\n/// One of the requirements in <see cref=\"IAuthorizationPolicy\"/>.\n/// </summary>\npublic interface IAuthorizationRequirement\n{\n    /// <summary>\n    /// Execute requirement. If the requirement is not met then this method\n    /// should call <see cref=\"AuthorizationContext.ReportError(string)\"/>.\n    /// </summary>\n    Task Authorize(AuthorizationContext context);\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/ApiApprovalTests.cs",
    "content": "using PublicApiGenerator;\n\nnamespace GraphQL.Authorization.ApiTests;\n\n/// <summary>\n/// See more info about API approval tests here <see href=\"https://github.com/JakeGinnivan/ApiApprover\"/>.\n/// </summary>\npublic class ApiApprovalTests\n{\n    [Theory]\n    [InlineData(typeof(IAuthorizationRequirement))]\n    public void public_api_should_not_change_unintentionally(Type type)\n    {\n        string publicApi = type.Assembly.GeneratePublicApi(new ApiGeneratorOptions\n        {\n            IncludeAssemblyAttributes = false,\n        });\n\n        // See: https://shouldly.readthedocs.io/en/latest/assertions/shouldMatchApproved.html\n        // Note: If the AssemblyName.approved.txt file doesn't match the latest publicApi value,\n        // this call will try to launch a diff tool to help you out but that can fail on\n        // your machine if a diff tool isn't configured/setup.\n        publicApi.ShouldMatchApproved(options => options.NoDiff().WithFilenameGenerator((_, _, fileType, fileExtension) => $\"{type.Assembly.GetName().Name}.{fileType}.{fileExtension}\"));\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.ApiTests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"../Tests.props\" />\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"PublicApiGenerator\" Version=\"11.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\GraphQL.Authorization\\GraphQL.Authorization.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.approved.txt",
    "content": "namespace GraphQL.Authorization\n{\n    public class AuthenticatedUserRequirement : GraphQL.Authorization.IAuthorizationRequirement\n    {\n        public AuthenticatedUserRequirement() { }\n        public System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context) { }\n    }\n    public class AuthorizationContext\n    {\n        public AuthorizationContext() { }\n        public System.Collections.Generic.IEnumerable<string> Errors { get; }\n        public bool HasErrors { get; }\n        public System.Security.Claims.ClaimsPrincipal? User { get; set; }\n        public System.Collections.Generic.IDictionary<string, object?>? UserContext { get; set; }\n        public GraphQL.Inputs? Variables { get; set; }\n        public void ReportError(string error) { }\n    }\n    public class AuthorizationEvaluator : GraphQL.Authorization.IAuthorizationEvaluator\n    {\n        public AuthorizationEvaluator(GraphQL.Authorization.AuthorizationSettings settings) { }\n        public System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, GraphQL.Inputs? variables, System.Collections.Generic.IEnumerable<string>? requiredPolicies) { }\n    }\n    public class AuthorizationPolicy : GraphQL.Authorization.IAuthorizationPolicy\n    {\n        public AuthorizationPolicy(System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> requirements) { }\n        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> Requirements { get; }\n    }\n    public class AuthorizationPolicyBuilder\n    {\n        public AuthorizationPolicyBuilder() { }\n        public GraphQL.Authorization.AuthorizationPolicyBuilder AddRequirement(GraphQL.Authorization.IAuthorizationRequirement requirement) { }\n        public GraphQL.Authorization.AuthorizationPolicy Build() { }\n        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireAuthenticatedUser() { }\n        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType) { }\n        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues) { }\n        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }\n    }\n    public class AuthorizationResult\n    {\n        public AuthorizationResult() { }\n        public System.Collections.Generic.IEnumerable<string>? Errors { get; }\n        public bool Succeeded { get; }\n        public static GraphQL.Authorization.AuthorizationResult Fail(System.Collections.Generic.IEnumerable<string> errors) { }\n        public static GraphQL.Authorization.AuthorizationResult Success() { }\n    }\n    public class AuthorizationSettings\n    {\n        public AuthorizationSettings() { }\n        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationPolicy> Policies { get; }\n        public void AddPolicy(string name, GraphQL.Authorization.IAuthorizationPolicy policy) { }\n        public void AddPolicy(string name, System.Action<GraphQL.Authorization.AuthorizationPolicyBuilder> configure) { }\n        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationPolicy> GetPolicies(System.Collections.Generic.IEnumerable<string> policies) { }\n        public GraphQL.Authorization.IAuthorizationPolicy? GetPolicy(string name) { }\n    }\n    public class AuthorizationValidationRule : GraphQL.Validation.ValidationRuleBase\n    {\n        public AuthorizationValidationRule(GraphQL.Authorization.IAuthorizationEvaluator evaluator) { }\n        public override System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor?> GetPreNodeVisitorAsync(GraphQL.Validation.ValidationContext context) { }\n    }\n    public class ClaimAuthorizationRequirement : GraphQL.Authorization.IAuthorizationRequirement\n    {\n        public ClaimAuthorizationRequirement(string claimType) { }\n        public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues) { }\n        public ClaimAuthorizationRequirement(string claimType, params string[] allowedValues) { }\n        public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }\n        public System.Collections.Generic.IEnumerable<string> AllowedValues { get; }\n        public string ClaimType { get; }\n        public System.Collections.Generic.IEnumerable<string>? DisplayValues { get; }\n        public System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context) { }\n    }\n    public interface IAuthorizationEvaluator\n    {\n        System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, GraphQL.Inputs? variables, System.Collections.Generic.IEnumerable<string>? requiredPolicies);\n    }\n    public interface IAuthorizationPolicy\n    {\n        System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> Requirements { get; }\n    }\n    public interface IAuthorizationRequirement\n    {\n        System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context);\n    }\n}\nnamespace GraphQL\n{\n    public static class AuthorizationGraphQLBuilderExtensions\n    {\n        public static GraphQL.DI.IGraphQLBuilder AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings> configure) { }\n        public static GraphQL.DI.IGraphQLBuilder AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings, System.IServiceProvider> configure) { }\n    }\n}"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthenticatedUserRequirementTests.cs",
    "content": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthenticatedUserRequirementTests\n{\n    [Fact]\n    public async Task produces_error_when_not_authenticated()\n    {\n        var req = new AuthenticatedUserRequirement();\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal()\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeTrue();\n        context.Errors.Single().ShouldBe(\"An authenticated user is required.\");\n    }\n\n    [Fact]\n    public async Task no_errors_when_authenticated()\n    {\n        var req = new AuthenticatedUserRequirement();\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal(\"jwt\")\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeFalse();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationEvaluatorTests.cs",
    "content": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationEvaluatorTests\n{\n    private readonly AuthorizationEvaluator _evaluator;\n    private readonly AuthorizationSettings _settings;\n\n    public AuthorizationEvaluatorTests()\n    {\n        _settings = new AuthorizationSettings();\n        _evaluator = new AuthorizationEvaluator(_settings);\n    }\n\n    [Fact]\n    public async Task fails_with_null_principal()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        var result = await _evaluator.Evaluate(\n            null,\n            null,\n            null,\n            new[] { \"MyPolicy\" }\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task fails_when_missing_claim()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(),\n            null,\n            null,\n            new[] { \"MyPolicy\" }\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task fails_when_missing_policy()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            }),\n            null,\n            null,\n            new[] { \"PolicyDoesNotExist\" }\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task succeeds_when_policy_applied()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            }),\n            null,\n            null,\n            new[] { \"MyPolicy\" }\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeTrue();\n    }\n\n    [Fact]\n    public async Task succeeds_with_claim_value()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\", \"true\"));\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            }),\n            null,\n            null,\n            new[] { \"MyPolicy\" }\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeTrue();\n    }\n\n    [Fact]\n    public async Task succeeds_when_null_policies()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            }),\n            null,\n            null,\n            null\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeTrue();\n    }\n\n    [Fact]\n    public async Task succeeds_when_empty_policies()\n    {\n        _settings.AddPolicy(\"MyPolicy\", _ => { });\n\n        var result = await _evaluator.Evaluate(\n            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            }),\n            null,\n            null,\n            Array.Empty<string>()\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeTrue();\n    }\n\n    [Fact]\n    public async Task succeeds_when_null_principal()\n    {\n        var result = await _evaluator.Evaluate(\n            null,\n            null,\n            null,\n            null\n        ).ConfigureAwait(false);\n\n        result.Succeeded.ShouldBeTrue();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationSchemaBuilderTests.cs",
    "content": "using GraphQL.Types;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationSchemaBuilderTests\n{\n    [Fact]\n    public void can_set_policy_from_authorize_attribute()\n    {\n        string defs = \"\"\"\n            type Query {\n              post(id: ID!): String\n            }\n            \"\"\";\n\n        var schema = Schema.For(defs, builder => builder.Types.Include<QueryWithAttributes>());\n\n        schema.Initialize();\n\n        var query = (IObjectGraphType)schema.AllTypes[\"Query\"]!;\n        query.IsAuthorizationRequired().ShouldBeTrue();\n        query.GetPolicies()!.Single().ShouldBe(\"ClassPolicy\");\n\n        var field = query.Fields.Single(x => x.Name == \"post\");\n        field.IsAuthorizationRequired().ShouldBeTrue();\n        field.GetPolicies()!.Single().ShouldBe(\"FieldPolicy\");\n    }\n\n    [GraphQLMetadata(\"Query\")]\n    [Authorize(\"ClassPolicy\")]\n    public class QueryWithAttributes\n    {\n        [Authorize(\"FieldPolicy\")]\n        [System.Diagnostics.CodeAnalysis.SuppressMessage(\"Style\", \"IDE0060:Remove unused parameter\", Justification = \"test\")]\n        public string Post(string id) => \"\";\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationSettingsTests.cs",
    "content": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationSettingsTests\n{\n    private readonly AuthorizationSettings _settings;\n\n    public AuthorizationSettingsTests()\n    {\n        _settings = new AuthorizationSettings();\n    }\n\n    [Fact]\n    public void can_add_a_claim_policy()\n    {\n        _settings.AddPolicy(\"MyPolicy\", builder => builder.RequireClaim(\"Admin\"));\n\n        _settings.Policies.Count().ShouldBe(1);\n\n        var policy = _settings.Policies.Single();\n        policy.Requirements.Single().ShouldBeOfType<ClaimAuthorizationRequirement>();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs",
    "content": "using GraphQL.Types;\nusing GraphQL.Types.Relay.DataObjects;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationValidationRuleTests : ValidationTestBase\n{\n    [Fact]\n    public void class_policy_success()\n    {\n        Settings.AddPolicy(\"ClassPolicy\", builder => builder.RequireClaim(\"admin\"));\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = BasicSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void class_policy_fail()\n    {\n        Settings.AddPolicy(\"ClassPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = BasicSchema();\n        });\n    }\n\n    [Fact]\n    public void field_policy_success()\n    {\n        Settings.AddPolicy(\"ClassPolicy\", builder => builder.RequireClaim(\"admin\"));\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = BasicSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n                {\n                    { \"Admin\", \"true\" }\n                });\n        });\n    }\n\n    [Fact]\n    public void field_policy_fail()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = BasicSchema();\n        });\n    }\n\n    [Fact]\n    public void nested_type_policy_success()\n    {\n        Settings.AddPolicy(\"PostPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = NestedSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void nested_type_policy_fail()\n    {\n        Settings.AddPolicy(\"PostPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { post }\";\n            config.Schema = NestedSchema();\n        });\n    }\n\n    [Fact]\n    public void nested_type_list_policy_fail()\n    {\n        Settings.AddPolicy(\"PostPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { posts }\";\n            config.Schema = NestedSchema();\n        });\n    }\n\n    // https://github.com/graphql-dotnet/authorization/issues/5\n    [Theory]\n    [InlineData(\"c\", \"query p { posts } query c { comment }\")]\n    [InlineData(null, \"query c { comment } query p { posts }\")]\n    public void issue5_should_pass(string operationName, string query)\n    {\n        Settings.AddPolicy(\"PostPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.OperationName = operationName;\n            config.Query = query;\n            config.Schema = NestedSchema();\n        });\n    }\n\n    // https://github.com/graphql-dotnet/authorization/issues/5\n    [Theory]\n    [InlineData(\"query a { article { id } } query b { article { ...frag } } fragment frag on Article { content }\")]\n    [InlineData(\"query a { article { ...frag1 author } } query b { article { ...frag2 } } fragment frag1 on Article { id } fragment frag2 on Article { content }\")]\n    public void issue5_with_fragment_should_pass(string query)\n    {\n        Settings.AddPolicy(\"AdminPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = query;\n            config.Schema = TypedSchema();\n        });\n    }\n\n    // https://github.com/graphql-dotnet/authorization/issues/5\n    [Fact]\n    public void issue5_with_fragment_should_fail()\n    {\n        Settings.AddPolicy(\"AdminPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query a { article { ...frag } } query b { article { ...frag } } fragment frag on Article { content }\";\n            config.Schema = TypedSchema();\n            config.ValidateResult = result => _ = result.Errors.Single(x => x.Message == $\"You are not authorized to run this query.\\nRequired claim 'admin' is not present.\");\n        });\n    }\n\n    [Fact]\n    public void nested_fragment_should_fail()\n    {\n        Settings.AddPolicy(\"AdminPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query a { article { ...frag } } query b { article { ...frag } } fragment frag on Article { ...frag2 } fragment frag2 on Article { content }\";\n            config.Schema = TypedSchema();\n            config.ValidateResult = result => _ = result.Errors.Single(x => x.Message == $\"You are not authorized to run this query.\\nRequired claim 'admin' is not present.\");\n        });\n    }\n\n    [Fact]\n    public void nested_type_list_non_null_policy_fail()\n    {\n        Settings.AddPolicy(\"PostPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { postsNonNull }\";\n            config.Schema = NestedSchema();\n        });\n    }\n\n    [Fact]\n    public void passes_with_claim_on_input_type()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"\"\"query { author(input: { name: \"Quinn\" }) }\"\"\";\n            config.Schema = TypedSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void fails_on_missing_claim_on_input_type()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"\"\"query { author(input: { name: \"Quinn\" }) }\"\"\";\n            config.Schema = TypedSchema();\n        });\n    }\n\n    [Fact]\n    public void passes_with_multiple_policies_on_field_and_single_on_input_type()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n        Settings.AddPolicy(\"AdminPolicy\", builder => builder.RequireClaim(\"admin\"));\n        Settings.AddPolicy(\"ConfidentialPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"\"\"query { author(input: { name: \"Quinn\" }) project(input: { name: \"TEST\" }) }\"\"\";\n            config.Schema = TypedSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void Issue61()\n    {\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query { unknown(obj: {id: 7}) }\";\n            config.Schema = TypedSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void passes_with_claim_on_variable_type()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query Author($input: AuthorInputType!) { author(input: $input) }\";\n            config.Schema = TypedSchema();\n            config.Variables = new Inputs(new Dictionary<string, object?>()\n            {\n                {\n                    \"input\",\n                    new Dictionary<string,object>{ { \"name\",\"Quinn\" } }\n                }\n            });\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void passes_with_claim_on_variable_type_without_inputs_but_fails_later_either()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.ValidateResult = result =>\n            {\n                // no auth error on null inputs, only INVALID_VALUE\n                result.Errors.Count.ShouldBe(1);\n                result.Errors[0].Code.ShouldBe(\"INVALID_VALUE\");\n                result.Errors[0].Message.ShouldBe(\"Variable '$input' is invalid. No value provided for a non-null variable.\");\n            };\n            config.Query = \"query Author($input: AuthorInputType!) { author(input: $input) }\";\n            config.Schema = TypedSchema();\n            config.Variables = null;\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void fails_on_missing_claim_on_variable_type()\n    {\n        Settings.AddPolicy(\"FieldPolicy\", builder => builder.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query Author($input: AuthorInputType!) { author(input: $input) }\";\n            config.Schema = TypedSchema();\n            config.Variables = new Inputs(new Dictionary<string, object?>()\n            {\n                {\n                    \"input\",\n                    new Dictionary<string,object>{ { \"name\",\"Quinn\" } }\n                }\n            });\n        });\n    }\n\n    [Fact]\n    public void passes_with_policy_on_connection_type()\n    {\n        Settings.AddPolicy(\"ConnectionPolicy\", _ => _.RequireClaim(\"admin\"));\n\n        ShouldPassRule(config =>\n        {\n            config.Query = \"query { posts { items { id } } }\";\n            config.Schema = TypedSchema();\n            config.User = CreatePrincipal(claims: new Dictionary<string, string>\n            {\n                { \"Admin\", \"true\" }\n            });\n        });\n    }\n\n    [Fact]\n    public void fails_on_missing_claim_on_connection_type()\n    {\n        Settings.AddPolicy(\"ConnectionPolicy\", _ => _.RequireClaim(\"admin\"));\n\n        ShouldFailRule(config =>\n        {\n            config.Query = \"query { posts { items { id } } }\";\n            config.Schema = TypedSchema();\n            config.User = CreatePrincipal();\n        });\n    }\n\n    private static ISchema BasicSchema()\n    {\n        string defs = \"\"\"\n            type Query {\n              post(id: ID!): String\n            }\n            \"\"\";\n\n        return Schema.For(defs, builder => builder.Types.Include<BasicQueryWithAttributes>());\n    }\n\n    [GraphQLMetadata(\"Query\")]\n    [Authorize(\"ClassPolicy\")]\n    public class BasicQueryWithAttributes\n    {\n        [Authorize(\"FieldPolicy\")]\n        [System.Diagnostics.CodeAnalysis.SuppressMessage(\"Style\", \"IDE0060:Remove unused parameter\", Justification = \"test\")]\n        public string Post(string id) => \"\";\n    }\n\n    private static ISchema NestedSchema()\n    {\n        string defs = \"\"\"\n            type Query {\n              post(id: ID!): Post\n              posts: [Post]\n              postsNonNull: [Post!]!\n              comment: String\n            }\n\n            type Post {\n              id: ID!\n            }\n            \"\"\";\n\n        return Schema.For(defs, builder =>\n        {\n            builder.Types.Include<NestedQueryWithAttributes>();\n            builder.Types.Include<Post>();\n        });\n    }\n\n    [GraphQLMetadata(\"Query\")]\n    public class NestedQueryWithAttributes\n    {\n        [System.Diagnostics.CodeAnalysis.SuppressMessage(\"Style\", \"IDE0060:Remove unused parameter\", Justification = \"test\")]\n        public Post? Post(string id) => null;\n\n        public IEnumerable<Post>? Posts() => null;\n\n        public IEnumerable<Post>? PostsNonNull() => null;\n\n        public string? Comment() => null;\n    }\n\n    [Authorize(\"PostPolicy\")]\n    public class Post\n    {\n        public string? Id { get; set; }\n    }\n\n    public class PostGraphType : ObjectGraphType<Post>\n    {\n        public PostGraphType()\n        {\n            Field(p => p.Id);\n        }\n    }\n\n    public class Article\n    {\n        public string? Id { get; set; }\n\n        public string? Author { get; set; }\n\n        public string? Content { get; set; }\n    }\n\n    public class ArticleGraphType : ObjectGraphType<Article>\n    {\n        public ArticleGraphType()\n        {\n            Field(p => p.Id);\n            Field(p => p.Author);\n            Field(p => p.Content).AuthorizeWithPolicy(\"AdminPolicy\");\n        }\n    }\n\n    public class Author\n    {\n        public string? Name { get; set; }\n    }\n\n    private static ISchema TypedSchema()\n    {\n        var query = new ObjectGraphType();\n        query.Field<StringGraphType>(\"author\")\n            .Arguments(new QueryArguments(new QueryArgument<AuthorInputType> { Name = \"input\" }))\n            .Resolve(_ => \"testing\");\n\n        query.Connection<PostGraphType>(\"posts\")\n            .AuthorizeWithPolicy(\"ConnectionPolicy\")\n            .Resolve(_ => new Connection<Post>());\n\n        query.Field<StringGraphType>(\"project\")\n            .Arguments(new QueryArguments(new QueryArgument<AuthorInputType> { Name = \"input\" }))\n            .Resolve(_ => \"testing\").AuthorizeWithPolicy(\"AdminPolicy\").AuthorizeWithPolicy(\"ConfidentialPolicy\");\n\n        query.Field<ArticleGraphType>(\"article\")\n            .Resolve(_ => null);\n\n        return new Schema { Query = query };\n    }\n\n    public class AuthorInputType : InputObjectGraphType<Author>\n    {\n        public AuthorInputType()\n        {\n            Name = \"AuthorInputType\";\n            Field(x => x.Name).AuthorizeWithPolicy(\"FieldPolicy\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ClaimAuthorizationRequirementTests.cs",
    "content": "namespace GraphQL.Authorization.Tests;\n\npublic class ClaimAuthorizationRequirementTests\n{\n    [Fact]\n    public async Task produces_error_when_missing_claim_ignoring_value()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal()\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeTrue();\n        context.Errors.Single().ShouldBe(\"Required claim 'Admin' is not present.\");\n    }\n\n    [Fact]\n    public async Task produces_error_when_missing_claim_with_single_value()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\", \"true\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal()\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeTrue();\n        context.Errors.Single().ShouldBe(\"Required claim 'Admin' with any value of 'true' is not present.\");\n    }\n\n    [Fact]\n    public async Task produces_error_when_missing_claim_with_multiple_values()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\", \"true\", \"maybe\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal()\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeTrue();\n        context.Errors.Single().ShouldBe(\"Required claim 'Admin' with any value of 'true, maybe' is not present.\");\n    }\n\n    [Fact]\n    public async Task succeeds_when_claim_with_ignoring_value()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { \"Admin\", \"true\" } })\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task succeeds_when_claim_with_single_value()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\", \"true\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { \"Admin\", \"true\" } })\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task succeeds_when_claim_with_multiple_values()\n    {\n        var req = new ClaimAuthorizationRequirement(\"Admin\", \"true\", \"maybe\");\n\n        var context = new AuthorizationContext\n        {\n            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { \"Admin\", \"maybe\" } })\n        };\n\n        await req.Authorize(context).ConfigureAwait(false);\n\n        context.HasErrors.ShouldBeFalse();\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/GraphQL.Authorization.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"../Tests.props\" />\n\n  <PropertyGroup Condition=\"'$(SingleTestPlatform)' == 'true'\">\n    <TargetFramework>net8.0</TargetFramework>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(SingleTestPlatform)' != 'true'\">\n    <TargetFrameworks>net8.0;net7.0;net6.0;net5.0;netcoreapp3.1</TargetFrameworks>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <GraphQLTestVersion>8.0.0</GraphQLTestVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\GraphQL.Authorization\\GraphQL.Authorization.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"GraphQL\" Version=\"$(GraphQLTestVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ValidationTestBase.cs",
    "content": "using System.Security.Claims;\nusing GraphQL.Execution;\nusing GraphQL.Validation;\nusing GraphQLParser;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class ValidationTestBase\n{\n    public ValidationTestBase()\n    {\n        Settings = new AuthorizationSettings();\n        Rule = new AuthorizationValidationRule(new AuthorizationEvaluator(Settings));\n    }\n\n    protected AuthorizationValidationRule Rule { get; }\n\n    protected AuthorizationSettings Settings { get; }\n\n    protected void ShouldPassRule(Action<ValidationTestConfig> configure)\n    {\n        var config = new ValidationTestConfig();\n        config.Rules.Add(Rule);\n        configure(config);\n\n        config.Rules.Any().ShouldBeTrue(\"Must provide at least one rule to validate against.\");\n\n        config.Schema.Initialize();\n\n        var result = Validate(config);\n\n        string message = \"\";\n        if (result.Errors?.Any() == true)\n        {\n            message = string.Join(\", \", result.Errors.Select(x => x.Message));\n        }\n        result.IsValid.ShouldBeTrue(message);\n        config.ValidateResult(result);\n    }\n\n    protected void ShouldFailRule(Action<ValidationTestConfig> configure)\n    {\n        var config = new ValidationTestConfig();\n        config.Rules.Add(Rule);\n        configure(config);\n\n        config.Rules.Any().ShouldBeTrue(\"Must provide at least one rule to validate against.\");\n\n        config.Schema.Initialize();\n\n        var result = Validate(config);\n\n        result.IsValid.ShouldBeFalse(\"Expected validation errors though there were none.\");\n        config.ValidateResult(result);\n    }\n\n    private static IValidationResult Validate(ValidationTestConfig config)\n    {\n        var documentBuilder = new GraphQLDocumentBuilder();\n        var document = documentBuilder.Build(config.Query);\n        var validator = new DocumentValidator();\n        return validator.ValidateAsync(new ValidationOptions\n        {\n            Schema = config.Schema,\n            Document = document,\n            Operation = document.OperationWithName(config.OperationName) ?? throw new InvalidOperationException(\"Could not find specified operation\"),\n            Rules = config.Rules,\n            Variables = config.Variables ?? Inputs.Empty,\n            User = config.User\n        }).GetAwaiter().GetResult();\n    }\n\n    internal static ClaimsPrincipal CreatePrincipal(string? authenticationType = null, IDictionary<string, string>? claims = null)\n    {\n        var claimsList = new List<Claim>();\n\n        if (claims != null)\n        {\n            foreach (var c in claims)\n                claimsList.Add(new Claim(c.Key, c.Value));\n        }\n\n        return new ClaimsPrincipal(new ClaimsIdentity(claimsList, authenticationType));\n    }\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ValidationTestConfig.cs",
    "content": "using System.Security.Claims;\nusing GraphQL.Types;\nusing GraphQL.Validation;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class ValidationTestConfig\n{\n    public string OperationName { get; set; } = null!;\n\n    public string Query { get; set; } = null!;\n\n    public ISchema Schema { get; set; } = null!;\n\n    public List<IValidationRule> Rules { get; set; } = new();\n\n    public ClaimsPrincipal? User { get; set; }\n\n    public Inputs? Variables { get; set; }\n\n    public Action<IValidationResult> ValidateResult = _ => { };\n}\n"
  },
  {
    "path": "src/GraphQL.Authorization.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.4.33205.214\nMinimumVisualStudioVersion = 15.0.26124.0\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"GraphQL.Authorization\", \"GraphQL.Authorization\\GraphQL.Authorization.csproj\", \"{21771B0C-0FCE-41DA-BF0B-67D70368BB00}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"GraphQL.Authorization.Tests\", \"GraphQL.Authorization.Tests\\GraphQL.Authorization.Tests.csproj\", \"{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Harness\", \"Harness\\Harness.csproj\", \"{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \".Solution Items\", \".Solution Items\", \"{F1263413-6A34-42F2-ABA7-E38AB3DCB548}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\.editorconfig = ..\\.editorconfig\n\t\t..\\.gitignore = ..\\.gitignore\n\t\tDirectory.Build.props = Directory.Build.props\n\t\tDirectory.Build.targets = Directory.Build.targets\n\t\t..\\LICENSE.md = ..\\LICENSE.md\n\t\t..\\README.md = ..\\README.md\n\t\tTests.props = Tests.props\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \".github\", \".github\", \"{84514A09-9BB4-4C85-8A8E-92AF5AA26445}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\.github\\codecov.yaml = ..\\.github\\codecov.yaml\n\t\t..\\.github\\dependabot.yml = ..\\.github\\dependabot.yml\n\t\t..\\.github\\FUNDING.yml = ..\\.github\\FUNDING.yml\n\t\t..\\.github\\labeler.yml = ..\\.github\\labeler.yml\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"workflows\", \"workflows\", \"{C1216C18-FAAE-46CA-95EB-B2202FBC994A}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\.github\\workflows\\build.yml = ..\\.github\\workflows\\build.yml\n\t\t..\\.github\\workflows\\codeql-analysis.yml = ..\\.github\\workflows\\codeql-analysis.yml\n\t\t..\\.github\\workflows\\format.yml = ..\\.github\\workflows\\format.yml\n\t\t..\\.github\\workflows\\label.yml = ..\\.github\\workflows\\label.yml\n\t\t..\\.github\\workflows\\publish.yml = ..\\.github\\workflows\\publish.yml\n\t\t..\\.github\\workflows\\test.yml = ..\\.github\\workflows\\test.yml\n\t\t..\\.github\\workflows\\wipcheck.yml = ..\\.github\\workflows\\wipcheck.yml\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BasicSample\", \"BasicSample\\BasicSample.csproj\", \"{49174102-8BD4-4193-8CB6-026881BF1B6B}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"GraphQL.Authorization.ApiTests\", \"GraphQL.Authorization.ApiTests\\GraphQL.Authorization.ApiTests.csproj\", \"{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Samples\", \"Samples\", \"{A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Tests\", \"Tests\", \"{70F571C2-0255-457D-BAAA-3BFDC60B6BC9}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x64.Build.0 = Release|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x86.Build.0 = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x64.Build.0 = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x86.Build.0 = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x64.Build.0 = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x86.Build.0 = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x64.Build.0 = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x86.Build.0 = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x64.Build.0 = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x86.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(NestedProjects) = preSolution\n\t\t{C482F1AF-6E9D-4D1C-96D7-3C0206312B66} = {70F571C2-0255-457D-BAAA-3BFDC60B6BC9}\n\t\t{DEA32495-F7AA-45F0-8AF6-DE4FB089994F} = {A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}\n\t\t{C1216C18-FAAE-46CA-95EB-B2202FBC994A} = {84514A09-9BB4-4C85-8A8E-92AF5AA26445}\n\t\t{49174102-8BD4-4193-8CB6-026881BF1B6B} = {A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}\n\t\t{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0} = {70F571C2-0255-457D-BAAA-3BFDC60B6BC9}\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {B582AABA-5414-45C5-920C-1A00B5B1FDB4}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Harness/GraphQL.cs",
    "content": "namespace GraphQL;\n\n/// <summary>\n/// CLR type to map to the 'Query' graph type.\n/// </summary>\npublic class Query\n{\n    /// <summary>\n    /// Resolver for 'Query.viewer' field.\n    /// </summary>\n    [Authorize(\"AdminPolicy\")]\n    public User Viewer() => new() { Id = Guid.NewGuid().ToString(), Name = \"Quinn\" };\n\n    /// <summary>\n    /// Resolver for 'Query.users' field.\n    /// </summary>\n    public List<User> Users() => new() { new User { Id = Guid.NewGuid().ToString(), Name = \"Quinn\" } };\n\n    /// <summary>\n    /// Resolver for 'Query.guest' field.\n    /// </summary>\n    public string Guest() => \"guest42\";\n}\n\n/// <summary>\n/// CLR type to map to the 'User' graph type.\n/// </summary>\npublic class User\n{\n    /// <summary>\n    /// Resolver for 'User.id' field. Just a simple property.\n    /// </summary>\n    public string? Id { get; set; }\n\n    /// <summary>\n    /// Resolver for 'User.name' field. Just a simple property.\n    /// </summary>\n    public string? Name { get; set; }\n}\n"
  },
  {
    "path": "src/Harness/Harness.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <Description>Example ASP.NET Core project to demonstrate GraphQL.NET Authorization setup</Description>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\GraphQL.Authorization\\GraphQL.Authorization.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"GraphQL.MicrosoftDI\" Version=\"8.*\" />\n    <PackageReference Include=\"GraphQL.Server.Ui.GraphiQL\" Version=\"8.*\" />\n    <PackageReference Include=\"GraphQL.Server.Ui.Playground\" Version=\"8.*\" />\n    <PackageReference Include=\"GraphQL.Server.Transports.AspNetCore\" Version=\"8.*\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Using Remove=\"System.Net.Http.Json\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Harness/Program.cs",
    "content": "using GraphQL;\r\nusing GraphQL.Types;\r\nusing Microsoft.Extensions.DependencyInjection.Extensions;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddHttpContextAccessor();\r\nbuilder.Services.TryAddSingleton<ISchema>(_ =>\r\n{\r\n    const string definitions = \"\"\"\r\n        type User {\r\n          id: ID\r\n          name: String\r\n        }\r\n\r\n        type Query {\r\n          viewer: User\r\n          users: [User]\r\n          guest: String\r\n        }\r\n        \"\"\";\r\n    var schema = Schema.For(definitions, builder => builder.Types.Include<Query>());\r\n    schema.AllTypes[\"User\"]!.AuthorizeWithPolicy(\"AdminPolicy\");\r\n    return schema;\r\n});\r\n\r\n// Claims principal must look something like this to allow access.\r\n// var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(\"role\", \"Admin\") }));\r\n\r\nbuilder.Services.AddGraphQL(builder => builder\r\n    .AddSystemTextJson()\r\n    .ConfigureExecutionOptions(opt =>\r\n    {\r\n        opt.Root = new Query();\r\n        // opt.User = user; // User property has already been initialized. Uncomment to play with ClaimsPrincipal.\r\n    })\r\n    .AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true)\r\n    .AddAuthorization(settings => settings.AddPolicy(\"AdminPolicy\", p => p.RequireClaim(\"role\", \"Admin\"))));\r\n\r\nvar app = builder.Build();\r\n\r\nif (app.Environment.IsDevelopment())\r\n    app.UseDeveloperExceptionPage();\r\n\r\napp.UseGraphQL();\r\napp.UseGraphQLGraphiQL();\r\napp.UseGraphQLPlayground(options: new GraphQL.Server.Ui.Playground.PlaygroundOptions { SchemaPollingEnabled = false });\r\n\r\napp.Run();\r\n"
  },
  {
    "path": "src/Harness/Properties/launchSettings.json",
    "content": "{\n  \"profiles\": {\n    \"Harness [GraphiQL]\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"ui/graphiql\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      },\n      \"applicationUrl\": \"http://localhost:5000\"\n    },\n    \"Harness [Playground]\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"ui/playground\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      },\n      \"applicationUrl\": \"http://localhost:5000\"\n    }\n  }\n}"
  },
  {
    "path": "src/Harness/appsettings.Development.json",
    "content": "﻿{\r\n  \"Logging\": {\r\n    \"IncludeScopes\": false,\r\n    \"LogLevel\": {\r\n      \"Default\": \"Debug\",\r\n      \"System\": \"Information\",\r\n      \"Microsoft\": \"Information\"\r\n    }\r\n  }\r\n}\r\n"
  },
  {
    "path": "src/Harness/appsettings.json",
    "content": "﻿{\r\n  \"Logging\": {\r\n    \"Debug\": {\r\n      \"LogLevel\": {\r\n        \"Default\": \"Warning\"\r\n      }\r\n    },\r\n    \"Console\": {\r\n      \"IncludeScopes\": false,\r\n      \"LogLevel\": {\r\n        \"Default\": \"Warning\"\r\n      }\r\n    }\r\n  }\r\n}\r\n"
  },
  {
    "path": "src/Tests.props",
    "content": "<Project>\n  <Import Project=\"$(MSBuildThisFileDirectory)Tests.local.props\" Condition=\"Exists('$(MSBuildThisFileDirectory)Tests.local.props')\" />\n\n  <PropertyGroup>\n    <NoWarn>$(NoWarn);IDE1006;CS0618</NoWarn>\n    <SingleTestPlatform Condition=\"'$(SingleTestPlatform)' == ''\">false</SingleTestPlatform>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"coverlet.collector\" Version=\"6.0.0\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.7.0\" />\n    <PackageReference Include=\"Shouldly\" Version=\"4.2.1\" />\n    <PackageReference Include=\"xunit\" Version=\"2.5.0\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.4.5\" />\n    <PackageReference Include=\"Moq\" Version=\"4.20.2\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Using Include=\"Shouldly\" />\n    <Using Include=\"Xunit\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Content Include=\"..\\xunit.runner.json\">\n      <CopyToOutputDirectory>Always</CopyToOutputDirectory>\n    </Content>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/xunit.runner.json",
    "content": "{\n  \"$schema\": \"https://xunit.net/schema/current/xunit.runner.schema.json\",\n  \"diagnosticMessages\": true,\n  \"longRunningTestSeconds\": 10\n}\n"
  }
]