Inheritance: AbstractNode
 public static void AddLocation(this ExecutionError error, AbstractNode abstractNode, Document document)
 {
     if (abstractNode != null)
     {
         if (document != null)
         {
             var location = new Location(new Source(document.OriginalQuery), abstractNode.SourceLocation.Start);
             error.AddLocation(location.Line, location.Column);
         }
         else if (abstractNode.SourceLocation.Line > 0 && abstractNode.SourceLocation.Column > 0)
         {
             error.AddLocation(abstractNode.SourceLocation.Line, abstractNode.SourceLocation.Column);
         }
     }
 }
        public void Validate(Document document, ComplexityConfiguration complexityParameters)
        {
            if (complexityParameters == null) return;
            var complexityResult = Analyze(document, complexityParameters.FieldImpact ?? 2.0f);
            #if DEBUG
            Debug.WriteLine($"Complexity: {complexityResult.Complexity}");
            Debug.WriteLine($"Sum(Query depth across all subqueries) : {complexityResult.TotalQueryDepth}");
            foreach (var node in complexityResult.ComplexityMap) Debug.WriteLine($"{node.Key} : {node.Value}");
            #endif
            if (complexityParameters.MaxComplexity.HasValue &&
                complexityResult.Complexity > complexityParameters.MaxComplexity.Value)
                throw new InvalidOperationException(
                    $"Query is too complex to execute. The field with the highest complexity is: {complexityResult.ComplexityMap.OrderByDescending(pair => pair.Value).First().Key}");

            if (complexityParameters.MaxDepth.HasValue &&
                complexityResult.TotalQueryDepth > complexityParameters.MaxDepth)
                throw new InvalidOperationException(
                    $"Query is too nested to execute. Depth is {complexityResult.TotalQueryDepth} levels, maximum allowed on this endpoint is {complexityParameters.MaxDepth}.");
        }
        /// <summary>
        /// Analyzes the complexity of a document.
        /// </summary>  
        internal ComplexityResult Analyze(Document doc, double avgImpact = 2.0d)
        {
            if (avgImpact <= 1) throw new ArgumentOutOfRangeException(nameof(avgImpact));

            doc.Children.Where(node => node is FragmentDefinition).Apply(node =>
            {
                var fragResult = new FragmentComplexity();
                FragmentIterator(node, fragResult, avgImpact, avgImpact, 1d);
                _fragmentMap[(node as FragmentDefinition)?.Name] = fragResult;
            });

            TreeIterator(doc, _result, avgImpact, avgImpact, 1d);

            // Cleanup in case Analyze is called again
            _loopCounter = 0;
            var retVal = _result;
            _result = new ComplexityResult();

            return retVal;
        }
        public IValidationResult Validate(
            string originalQuery,
            ISchema schema,
            Document document,
            IEnumerable<IValidationRule> rules = null,
            object userContext = null)
        {
            if (!schema.Initialized)
            {
                schema.Initialize();
            }

            var context = new ValidationContext
            {
                OriginalQuery = originalQuery,
                Schema = schema,
                Document = document,
                TypeInfo = new TypeInfo(schema),
                UserContext = userContext
            };

            if (rules == null)
            {
                rules = CoreRules();
            }

            var visitors = rules.Select(x => x.Validate(context)).ToList();

            visitors.Insert(0, context.TypeInfo);
            // #if DEBUG
            //             visitors.Insert(1, new DebugNodeVisitor());
            // #endif

            var basic = new BasicVisitor(visitors.ToArray());

            basic.Visit(document);

            var result = new ValidationResult();
            result.Errors.AddRange(context.Errors);
            return result;
        }
        public object GetVariableValue(Document document, ISchema schema, VariableDefinition variable, object input)
        {
            var type = variable.Type.GraphTypeFromType(schema);

            if (IsValidValue(schema, type, input))
            {
                if (input == null)
                {
                    if (variable.DefaultValue != null)
                    {
                        return ValueFromAst(variable.DefaultValue);
                    }
                }
                var coercedValue = CoerceValue(schema, type, input.AstFromValue(schema, type));
                return coercedValue;
            }

            if (input == null)
            {
                var error2 = new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName()));
                error2.AddLocation(variable, document);
                throw error2;
            }

            var error = new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName()));
            error.AddLocation(variable, document);
            throw error;
        }
        public Variables GetVariableValues(Document document, ISchema schema, VariableDefinitions variableDefinitions, Inputs inputs)
        {
            var variables = new Variables();
            variableDefinitions.Apply(v =>
            {
                var variable = new Variable();
                variable.Name = v.Name;

                object variableValue = null;
                inputs?.TryGetValue(v.Name, out variableValue);
                variable.Value = GetVariableValue(document, schema, v, variableValue);

                variables.Add(variable);
            });
            return variables;
        }
        public IObjectGraphType GetOperationRootType(Document document, ISchema schema, Operation operation)
        {
            IObjectGraphType type;

            ExecutionError error;

            switch (operation.OperationType)
            {
                case OperationType.Query:
                    type = schema.Query;
                    break;

                case OperationType.Mutation:
                    type = schema.Mutation;
                    if (type == null)
                    {
                        error = new ExecutionError("Schema is not configured for mutations");
                        error.AddLocation(operation, document);
                        throw error;
                    }
                    break;

                case OperationType.Subscription:
                    type = schema.Subscription;
                    if (type == null)
                    {
                        error = new ExecutionError("Schema is not configured for subscriptions");
                        error.AddLocation(operation, document);
                        throw error;
                    }
                    break;

                default:
                    error = new ExecutionError("Can only execute queries, mutations and subscriptions.");
                    error.AddLocation(operation, document);
                    throw error;
            }

            return type;
        }
        private Operation GetOperation(string operationName, Document document)
        {
            var operation = !string.IsNullOrWhiteSpace(operationName)
                ? document.Operations.WithName(operationName)
                : document.Operations.FirstOrDefault();

            return operation;
        }
        public ExecutionContext BuildExecutionContext(
            ISchema schema,
            object root,
            Document document,
            Operation operation,
            Inputs inputs,
            object userContext,
            CancellationToken cancellationToken,
            Metrics metrics)
        {
            var context = new ExecutionContext();
            context.Document = document;
            context.Schema = schema;
            context.RootValue = root;
            context.UserContext = userContext;

            context.Operation = operation;
            context.Variables = GetVariableValues(document, schema, operation.Variables, inputs);
            context.Fragments = document.Fragments;
            context.CancellationToken = cancellationToken;

            context.Metrics = metrics;

            return context;
        }
Example #10
0
        public ExecutionContext BuildExecutionContext(
            ISchema schema,
            object root,
            Document document,
            string operationName,
            Inputs inputs,
            CancellationToken cancellationToken)
        {
            var context = new ExecutionContext();
            context.Schema = schema;
            context.RootValue = root;

            var operation = !string.IsNullOrWhiteSpace(operationName)
                ? document.Operations.WithName(operationName)
                : document.Operations.FirstOrDefault();

            if (operation == null)
            {
                context.Errors.Add(new ExecutionError("Unknown operation name: {0}".ToFormat(operationName)));
                return context;
            }

            context.Operation = operation;
            context.Variables = GetVariableValues(schema, operation.Variables, inputs);
            context.Fragments = document.Fragments;
            context.CancellationToken = cancellationToken;

            return context;
        }