Skip to content

Commit

Permalink
added a new validation phase
Browse files Browse the repository at this point in the history
fixes

update to latest

run validations as soon as possible

use specified rules instead of default set

cleanup

fix fmt

added more rules

move validation check to Query struct
Added Leaf-Field-Selections rule

fixes

fixes

Added an option to disable graphql validations: `DISABLE_GRAPHQL_VALIDATIONS`

fixes

use more rules!

fixes

fix

cleanup
  • Loading branch information
dotansimha committed Jan 10, 2022
1 parent c51fe36 commit d8d6003
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 9 deletions.
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions graph/src/data/query/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub enum QueryExecutionError {
AbstractTypeError(String),
InvalidArgumentError(Pos, String, q::Value),
MissingArgumentError(Pos, String),
ValidationError(Option<Pos>, String),
InvalidVariableTypeError(Pos, String),
MissingVariableError(Pos, String),
ResolveEntitiesError(String),
Expand Down Expand Up @@ -137,6 +138,7 @@ impl QueryExecutionError {
| DeploymentReverted
| SubgraphManifestResolveError(_)
| InvalidSubgraphManifest
| ValidationError(_, _)
| ResultTooBig(_, _) => false,
}
}
Expand All @@ -161,6 +163,9 @@ impl fmt::Display for QueryExecutionError {
OperationNotFound(s) => {
write!(f, "Operation name not found `{}`", s)
}
ValidationError(_pos, message) => {
write!(f, "{}", message)
}
NotSupported(s) => write!(f, "Not supported: {}", s),
NoRootSubscriptionObjectType => {
write!(f, "No root Subscription type defined in the schema")
Expand Down
1 change: 1 addition & 0 deletions graphql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ crossbeam = "0.8"
futures01 = { package="futures", version="0.1.29" }
graph = { path = "../graph" }
graphql-parser = "0.4.0"
graphql-tools = "0.0.10"
indexmap = "1.7"
Inflector = "0.11.3"
lazy_static = "1.2.0"
Expand Down
61 changes: 58 additions & 3 deletions graphql/src/execution/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use graphql_parser::Pos;
use graphql_tools::validation::rules::*;
use graphql_tools::validation::validate::{validate, ValidationPlan};
use lazy_static::lazy_static;
use std::collections::{HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
Expand All @@ -9,11 +12,10 @@ use graph::data::graphql::{
ext::{DocumentExt, TypeExt},
ObjectOrInterface,
};
use graph::data::query::QueryExecutionError;
use graph::data::query::{Query as GraphDataQuery, QueryVariables};
use graph::data::schema::ApiSchema;
use graph::prelude::{
info, o, q, r, s, BlockNumber, CheapClone, Logger, QueryExecutionError, TryFromValue,
};
use graph::prelude::{info, o, q, r, s, BlockNumber, CheapClone, Logger, TryFromValue};

use crate::introspection::introspection_schema;
use crate::query::{ast as qast, ext::BlockConstraint};
Expand All @@ -23,6 +25,41 @@ use crate::{
schema::api::ErrorPolicy,
};

lazy_static! {
static ref GRAPHQL_VALIDATION_PLAN: ValidationPlan = ValidationPlan::from(
if std::env::var("DISABLE_GRAPHQL_VALIDATIONS")
.unwrap_or_else(|_| "false".into())
.parse::<bool>()
.unwrap_or_else(|_| false)
{
vec![]
} else {
vec![
Box::new(UniqueOperationNames {}),
Box::new(LoneAnonymousOperation {}),
Box::new(SingleFieldSubscriptions {}),
Box::new(KnownTypeNames {}),
Box::new(FragmentsOnCompositeTypes {}),
Box::new(VariablesAreInputTypes {}),
Box::new(LeafFieldSelections {}),
Box::new(FieldsOnCorrectType {}),
Box::new(UniqueFragmentNames {}),
Box::new(KnownFragmentNames {}),
Box::new(NoUnusedFragments {}),
Box::new(OverlappingFieldsCanBeMerged {}),
Box::new(NoFragmentsCycle {}),
Box::new(PossibleFragmentSpreads {}),
Box::new(NoUnusedVariables {}),
Box::new(NoUndefinedVariables {}),
Box::new(KnownArgumentNames {}),
Box::new(UniqueArgumentNames {}),
Box::new(UniqueVariableNames {}),
Box::new(ProvidedRequiredArguments {}),
]
}
);
}

#[derive(Clone, Debug)]
pub enum ComplexityError {
TooDeep,
Expand Down Expand Up @@ -115,6 +152,24 @@ impl Query {
max_complexity: Option<u64>,
max_depth: u8,
) -> Result<Arc<Self>, Vec<QueryExecutionError>> {
let validation_errors = validate(
&schema.document(),
&query.document,
&GRAPHQL_VALIDATION_PLAN,
);

if validation_errors.len() > 0 {
return Err(validation_errors
.into_iter()
.map(|e| {
QueryExecutionError::ValidationError(
e.locations.clone().into_iter().nth(0),
e.message,
)
})
.collect());
}

let mut operation = None;
let mut fragments = HashMap::new();
for defn in query.document.definitions.into_iter() {
Expand Down
2 changes: 1 addition & 1 deletion server/index-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ graphql-parser = "0.4.0"
http = "0.2"
hyper = "0.14"
serde = "1.0"
either = "1.6.1"
either = "1.6.1"
2 changes: 1 addition & 1 deletion store/test-store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ graph-store-postgres = { path = "../postgres" }
lazy_static = "1.1"
hex-literal = "0.3"
diesel = { version = "1.4.8", features = ["postgres", "serde_json", "numeric", "r2d2"] }
graph-chain-ethereum = { path = "../../chain/ethereum" }
graph-chain-ethereum = { path = "../../chain/ethereum" }

0 comments on commit d8d6003

Please sign in to comment.