From c68071952da8da3e6ca9d125587e626a8d02d8cd Mon Sep 17 00:00:00 2001 From: Aryan Iyappan <69184573+aryan340@users.noreply.github.com> Date: Sat, 14 Aug 2021 08:20:46 +0530 Subject: [PATCH] mention how to implement custom validators --- docs/execution/index.rst | 2 +- docs/execution/queryvalidation.rst | 87 ++++++++++++++++++++++++++++++ docs/execution/validation.rst | 45 ---------------- 3 files changed, 88 insertions(+), 46 deletions(-) create mode 100644 docs/execution/queryvalidation.rst delete mode 100644 docs/execution/validation.rst diff --git a/docs/execution/index.rst b/docs/execution/index.rst index f775cc00..f26259d3 100644 --- a/docs/execution/index.rst +++ b/docs/execution/index.rst @@ -10,4 +10,4 @@ Execution dataloader fileuploading subscriptions - validation + queryvalidation diff --git a/docs/execution/queryvalidation.rst b/docs/execution/queryvalidation.rst new file mode 100644 index 00000000..35f3577e --- /dev/null +++ b/docs/execution/queryvalidation.rst @@ -0,0 +1,87 @@ +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. + +Example +------- + +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 + ), + ) + ) + + +Implementing custom validators +------------------------------ +All custom query validators should extend the `ValidationRule `_ +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 introspection fields: + +.. 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 key.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, + ) + ) + diff --git a/docs/execution/validation.rst b/docs/execution/validation.rst deleted file mode 100644 index 7be4fd66..00000000 --- a/docs/execution/validation.rst +++ /dev/null @@ -1,45 +0,0 @@ -Validation -========== - -Validation rules help validate a given GraphQL query, before executing it. 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. - -Example -------- - -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 - ), - ) - )