-
Notifications
You must be signed in to change notification settings - Fork 819
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1357 from codebyaryan/master
add support for query validation
- Loading branch information
Showing
15 changed files
with
759 additions
and
257 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
name: 📄 Tests | ||
on: | ||
push: | ||
branches: | ||
- master | ||
- '*.x' | ||
paths-ignore: | ||
- 'docs/**' | ||
- '*.md' | ||
- '*.rst' | ||
pull_request: | ||
branches: | ||
- master | ||
- '*.x' | ||
paths-ignore: | ||
- 'docs/**' | ||
- '*.md' | ||
- '*.rst' | ||
jobs: | ||
tests: | ||
# runs the test suite | ||
name: ${{ matrix.name }} | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
include: | ||
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38} | ||
- {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} | ||
- {name: '3.6', python: '3.6', os: ubuntu-latest, tox: py36} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python }} | ||
|
||
- name: update pip | ||
run: | | ||
pip install -U wheel | ||
pip install -U setuptools | ||
python -m pip install -U pip | ||
- name: get pip cache dir | ||
id: pip-cache | ||
run: echo "::set-output name=dir::$(pip cache dir)" | ||
|
||
- name: cache pip dependencies | ||
uses: actions/cache@v2 | ||
with: | ||
path: ${{ steps.pip-cache.outputs.dir }} | ||
key: pip|${{ runner.os }}|${{ matrix.python }}|${{ hashFiles('setup.py') }} | ||
|
||
- run: pip install tox | ||
- run: tox -e ${{ matrix.tox }} | ||
|
||
coveralls_finish: | ||
# check coverage increase/decrease | ||
needs: tests | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Coveralls Finished | ||
uses: AndreMiras/coveralls-python-action@develop | ||
|
||
deploy: | ||
# builds and publishes to PyPi | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.7' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install build | ||
- name: Build package | ||
run: python -m build | ||
- name: Publish package | ||
uses: pypa/gh-action-pypi-publish@release/v1 | ||
with: | ||
user: __token__ | ||
password: ${{ secrets.PYPI_API_TOKEN }} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,4 @@ Execution | |
dataloader | ||
fileuploading | ||
subscriptions | ||
queryvalidation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
Query Validation | ||
========== | ||
GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements | ||
standard query validators. For example, there is an validator that tests if queried field exists on queried type, that | ||
makes query fail with "Cannot query field on type" error if it doesn't. | ||
|
||
To help with common use cases, graphene provides a few validation rules out of the box. | ||
|
||
|
||
Depth limit Validator | ||
----------------- | ||
The depth limit validator helps to prevent execution of malicious | ||
queries. It takes in the following arguments. | ||
|
||
- ``max_depth`` is the maximum allowed depth for any operation in a GraphQL document. | ||
- ``ignore`` Stops recursive depth checking based on a field name. Either a string or regexp to match the name, or a function that returns a boolean | ||
- ``callback`` Called each time validation runs. Receives an Object which is a map of the depths for each operation. | ||
|
||
Usage | ||
------- | ||
|
||
Here is how you would implement depth-limiting on your schema. | ||
|
||
.. code:: python | ||
from graphql import validate, parse | ||
from graphene import ObjectType, Schema, String | ||
from graphene.validation import depth_limit_validator | ||
class MyQuery(ObjectType): | ||
name = String(required=True) | ||
schema = Schema(query=MyQuery) | ||
# queries which have a depth more than 20 | ||
# will not be executed. | ||
validation_errors = validate( | ||
schema=schema, | ||
document_ast=parse('THE QUERY'), | ||
rules=( | ||
depth_limit_validator( | ||
max_depth=20 | ||
), | ||
) | ||
) | ||
Disable Introspection | ||
--------------------- | ||
the disable introspection validation rule ensures that your schema cannot be introspected. | ||
This is a useful security measure in production environments. | ||
|
||
Usage | ||
------- | ||
|
||
Here is how you would disable introspection for your schema. | ||
|
||
.. code:: python | ||
from graphql import validate, parse | ||
from graphene import ObjectType, Schema, String | ||
from graphene.validation import DisableIntrospection | ||
class MyQuery(ObjectType): | ||
name = String(required=True) | ||
schema = Schema(query=MyQuery) | ||
# introspection queries will not be executed. | ||
validation_errors = validate( | ||
schema=schema, | ||
document_ast=parse('THE QUERY'), | ||
rules=( | ||
DisableIntrospection, | ||
) | ||
) | ||
Implementing custom validators | ||
------------------------------ | ||
All custom query validators should extend the `ValidationRule <https://github.com/graphql-python/graphql-core/blob/v3.0.5/src/graphql/validation/rules/__init__.py#L37>`_ | ||
base class importable from the graphql.validation.rules module. Query validators are visitor classes. They are | ||
instantiated at the time of query validation with one required argument (context: ASTValidationContext). In order to | ||
perform validation, your validator class should define one or more of enter_* and leave_* methods. For possible | ||
enter/leave items as well as details on function documentation, please see contents of the visitor module. To make | ||
validation fail, you should call validator's report_error method with the instance of GraphQLError describing failure | ||
reason. Here is an example query validator that visits field definitions in GraphQL query and fails query validation | ||
if any of those fields are blacklisted: | ||
|
||
.. code:: python | ||
from graphql import GraphQLError | ||
from graphql.language import FieldNode | ||
from graphql.validation import ValidationRule | ||
my_blacklist = ( | ||
"disallowed_field", | ||
) | ||
def is_blacklisted_field(field_name: str): | ||
return field_name.lower() in my_blacklist | ||
class BlackListRule(ValidationRule): | ||
def enter_field(self, node: FieldNode, *_args): | ||
field_name = node.name.value | ||
if not is_blacklisted_field(field_name): | ||
return | ||
self.report_error( | ||
GraphQLError( | ||
f"Cannot query '{field_name}': field is blacklisted.", node, | ||
) | ||
) | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.