mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-22 17:46:57 +03:00
add tests and docs for disable introspection rule
This commit is contained in:
parent
ec982ac50b
commit
4e32dac251
|
@ -16,7 +16,7 @@ queries. It takes in the following arguments.
|
|||
- ``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
|
||||
Usage
|
||||
-------
|
||||
|
||||
Here is how you would implement depth-limiting on your schema.
|
||||
|
@ -33,7 +33,7 @@ Here is how you would implement depth-limiting on your schema.
|
|||
|
||||
schema = Schema(query=MyQuery)
|
||||
|
||||
# Queries which have a depth more than 20
|
||||
# queries which have a depth more than 20
|
||||
# will not be executed.
|
||||
|
||||
validation_errors = validate(
|
||||
|
@ -47,6 +47,39 @@ Here is how you would implement depth-limiting on your schema.
|
|||
)
|
||||
|
||||
|
||||
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>`_
|
||||
|
@ -56,7 +89,7 @@ perform validation, your validator class should define one or more of enter_* an
|
|||
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 fields:
|
||||
if any of those fields are blacklisted:
|
||||
|
||||
.. code:: python
|
||||
from graphql import GraphQLError
|
||||
|
@ -70,7 +103,7 @@ if any of those fields are blacklisted fields:
|
|||
|
||||
|
||||
def is_blacklisted_field(field_name: str):
|
||||
return key.lower() in my_blacklist
|
||||
return field_name.lower() in my_blacklist
|
||||
|
||||
|
||||
class BlackListRule(ValidationRule):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from .depth_limit import depth_limit_validator
|
||||
from .disable_introspection import disable_introspection
|
||||
from .disable_introspection import DisableIntrospection
|
||||
|
||||
|
||||
__all__ = [
|
||||
"depth_limit_validator",
|
||||
"disable_introspection"
|
||||
"DisableIntrospection",
|
||||
"depth_limit_validator"
|
||||
]
|
||||
|
|
|
@ -116,7 +116,7 @@ def determine_depth(
|
|||
if depth_so_far > max_depth:
|
||||
context.report_error(
|
||||
GraphQLError(
|
||||
f"'{operation_name}' exceeds maximum operation depth of {max_depth}",
|
||||
f"'{operation_name}' exceeds maximum operation depth of {max_depth}.",
|
||||
[node],
|
||||
)
|
||||
)
|
||||
|
@ -172,7 +172,7 @@ def determine_depth(
|
|||
)
|
||||
)
|
||||
else:
|
||||
raise Exception(f"Depth crawler cannot handle: {node.kind}") # pragma: no cover
|
||||
raise Exception(f"Depth crawler cannot handle: {node.kind}.") # pragma: no cover
|
||||
|
||||
|
||||
def is_ignored(node: FieldNode, ignore: Optional[List[IgnoreType]] = None) -> bool:
|
||||
|
@ -191,6 +191,6 @@ def is_ignored(node: FieldNode, ignore: Optional[List[IgnoreType]] = None) -> bo
|
|||
if rule(field_name):
|
||||
return True
|
||||
else:
|
||||
raise ValueError(f"Invalid ignore option: {rule}")
|
||||
raise ValueError(f"Invalid ignore option: {rule}.")
|
||||
|
||||
return False
|
||||
|
|
|
@ -5,18 +5,15 @@ from graphql.validation import ValidationRule
|
|||
from ..utils.is_introspection_key import is_introspection_key
|
||||
|
||||
|
||||
def disable_introspection():
|
||||
class DisableIntrospection(ValidationRule):
|
||||
def enter_field(self, node: FieldNode, *_args):
|
||||
field_name = node.name.value
|
||||
if not is_introspection_key(field_name):
|
||||
return
|
||||
class DisableIntrospection(ValidationRule):
|
||||
def enter_field(self, node: FieldNode, *_args):
|
||||
field_name = node.name.value
|
||||
if not is_introspection_key(field_name):
|
||||
return
|
||||
|
||||
self.report_error(
|
||||
GraphQLError(
|
||||
f"Cannot query '{field_name}': introspection is disabled.",
|
||||
node,
|
||||
)
|
||||
self.report_error(
|
||||
GraphQLError(
|
||||
f"Cannot query '{field_name}': introspection is disabled.",
|
||||
node,
|
||||
)
|
||||
|
||||
return DisableIntrospection
|
||||
)
|
||||
|
|
|
@ -235,7 +235,7 @@ def test_should_catch_very_deep_query():
|
|||
errors, result = run_query(query, 4)
|
||||
|
||||
assert len(errors) == 1
|
||||
assert errors[0].message == "'anonymous' exceeds maximum operation depth of 4"
|
||||
assert errors[0].message == "'anonymous' exceeds maximum operation depth of 4."
|
||||
|
||||
|
||||
def test_should_ignore_field():
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from graphql import parse, validate
|
||||
|
||||
from ...types import Schema, ObjectType, String
|
||||
from ..disable_introspection import disable_introspection
|
||||
from ..disable_introspection import DisableIntrospection
|
||||
|
||||
|
||||
class Query(ObjectType):
|
||||
|
@ -9,6 +9,10 @@ class Query(ObjectType):
|
|||
required=True
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_name(root, info):
|
||||
return "Hello world!"
|
||||
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
||||
|
@ -16,14 +20,24 @@ schema = Schema(query=Query)
|
|||
def run_query(query: str):
|
||||
document = parse(query)
|
||||
|
||||
result = None
|
||||
|
||||
errors = validate(
|
||||
schema=schema.graphql_schema,
|
||||
document_ast=document,
|
||||
rules=(
|
||||
disable_introspection(),
|
||||
DisableIntrospection,
|
||||
),
|
||||
)
|
||||
|
||||
return errors, result
|
||||
return errors
|
||||
|
||||
|
||||
def test_disallows_introspection_queries():
|
||||
errors = run_query("{ __schema { queryType { name } } }")
|
||||
|
||||
assert len(errors) == 1
|
||||
assert errors[0].message == "Cannot query '__schema': introspection is disabled."
|
||||
|
||||
|
||||
def test_allows_non_introspection_queries():
|
||||
errors = run_query("{ name }")
|
||||
assert len(errors) == 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user