Graphql-dotnet: Validation on the query parameter

Created on 14 Jun 2018  路  4Comments  路  Source: graphql-dotnet/graphql-dotnet

I would like to know what is the best place to put validation to the input parameter for the query for example

{
  user(email: "useremail"){
  }
}

I want to make sure the passed in email is in the correct format, what is the best place to validate that?

while we are resolving the data? or there is some other options there?

question

Most helpful comment

You can use a ValidationRule for this to validate the inputs before it attempts to execute the query. Here's one of the core validation rules used for the GraphQL spec that deals with Arguments:

https://github.com/graphql-dotnet/graphql-dotnet/blob/3f2355aacd6cfd8e080dba1d802b2fa00f958f85/src/GraphQL/Validation/Rules/ArgumentsOfCorrectType.cs#L14-L38

You can pass the validation rules you want to run to the DocumentExecutor.

var executor = new DocumentExecutor();
var result = await executer.ExecuteAsync(_ =>
{
    _.Schema = schema;
    _.Query = request.Query;
    ...
    _.ValidationRules =
        DocumentValidator.CoreRules().Concat(new[]{ new EmailValidationRule() });
});

You could add metadata to the QueryArgument to provide a more generic way to configure what validations should be done for that argument, and use some validation library to do the actual check against the given value.

All 4 comments

You can use a ValidationRule for this to validate the inputs before it attempts to execute the query. Here's one of the core validation rules used for the GraphQL spec that deals with Arguments:

https://github.com/graphql-dotnet/graphql-dotnet/blob/3f2355aacd6cfd8e080dba1d802b2fa00f958f85/src/GraphQL/Validation/Rules/ArgumentsOfCorrectType.cs#L14-L38

You can pass the validation rules you want to run to the DocumentExecutor.

var executor = new DocumentExecutor();
var result = await executer.ExecuteAsync(_ =>
{
    _.Schema = schema;
    _.Query = request.Query;
    ...
    _.ValidationRules =
        DocumentValidator.CoreRules().Concat(new[]{ new EmailValidationRule() });
});

You could add metadata to the QueryArgument to provide a more generic way to configure what validations should be done for that argument, and use some validation library to do the actual check against the given value.

Thanks very much to your reply @joemcbride .

You mentioned about adding metadata to the QueryArgument, how is that done in the library? Currently, my argument is StringGraphType, do I need to create the argument as a separated type and then put the meta data there or I can just configure that when I defined the QueryArgument?

Thanks

I would say to add the metadata to the QueryArgument. QueryArgument does not currently have built-in metadata like fields and objects do but should be able to add it.

This is what I was thinking:

public class MyQueryArgument<T> : QueryArgument<T>, IProvideMetadata
{
    // members of IProvideMetadata
    IDictionary<string, object> Metadata { get; }
    TType GetMetadata<TType>(string key, TType defaultValue = default(TType));
    bool HasMetadata(string key);
}

public static class ArgumentValidationExtensions
{
    public static QueryArgument IsEmail(this QueryArgument argument)
    {
        argument.Metadata["validator"] = "EMAIL_VALIDATOR";
        return argument;
    }
}

arguments: new QueryArguments(new MyQueryArgument<StringGraphType>().IsEmail())

Then in your ValidationRule you can check to see if the QueryArgument has any associated validations.

  • Get the validator(s) from metadata, match it with the actual validator(s)
  • Get the argument value - it will either be a direct value or a variable, so you may have to pull the value out of a variable
  • run the validator(s) passing it the provided value

Some pseudo code:

// in the ValidationRule
var argumentAst = ...  // this is an Argument from the executed query
var argument = ...  // this is a QueryArgument from the Schema
var validator = GetValidator(argument);
var value = GetValue(argumentAst, argument, context.Inputs);  // context is ValidationContext

var validationResults = validator.Validate(value);
// add any errors to ValidationContext as needed

Thanks for your information on this.

Was this page helpful?
0 / 5 - 0 ratings