Skip to content

Commit

Permalink
Allow private methods in Parser/Validator/ValidateArguments attributes (
Browse files Browse the repository at this point in the history
#4055)

Fix Parse/Validate attributes
  • Loading branch information
gao-artur authored Sep 7, 2024
1 parent 36db79b commit 841e422
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 13 deletions.
14 changes: 12 additions & 2 deletions src/GraphQL.Tests/Attributes/ParserAttributeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,16 @@ public async Task parser_works_for_arguments()
hello1(value: "abc")
hello2(value: "def")
hello3(value: "ghi")
hello4(value: "jkl")
}
""";
var expected = """
{
"data": {
"hello1": "abctest1",
"hello2": "deftest2",
"hello3": "ghitest3"
"hello3": "ghitest3",
"hello4": "jkltest1"
}
}
""";
Expand All @@ -168,6 +170,7 @@ public class ArgTests
public static string Hello1([Parser(nameof(ParseHelloArgument))] string value) => value;
public static string Hello2([Parser(typeof(ParserClass))] string value) => value;
public static string Hello3([Parser(typeof(HelperClass), nameof(HelperClass.ParseHelloArgument))] string value) => value;
public static string Hello4([Parser(typeof(ArgTests), nameof(ParseHelloArgument))] string value) => value;

private static object ParseHelloArgument(object value) => (string)value + "test1";
}
Expand All @@ -185,21 +188,26 @@ public async Task parser_works_for_input_fields()
queryType.Field<StringGraphType>("hello3")
.Argument<AutoRegisteringInputObjectGraphType<FieldTests>>("value")
.Resolve(ctx => ctx.GetArgument<FieldTests>("value").Field3);
queryType.Field<StringGraphType>("hello4")
.Argument<AutoRegisteringInputObjectGraphType<FieldTests>>("value")
.Resolve(ctx => ctx.GetArgument<FieldTests>("value").Field4);
var schema = new Schema { Query = queryType };
schema.Initialize();
var query = """
{
hello1(value: { field1: "abc" })
hello2(value: { field2: "def" })
hello3(value: { field3: "ghi" })
hello4(value: { field4: "jkl" })
}
""";
var expected = """
{
"data": {
"hello1": "abctest1",
"hello2": "deftest2",
"hello3": "ghitest3"
"hello3": "ghitest3",
"hello4": "jkltest1"
}
}
""";
Expand All @@ -220,6 +228,8 @@ public class FieldTests
public string? Field2 { get; set; }
[Parser(typeof(HelperClass), nameof(HelperClass.ParseHelloArgument))]
public string? Field3 { get; set; }
[Parser(typeof(FieldTests), nameof(ParseHelloArgument))]
public string? Field4 { get; set; }

private static object ParseHelloArgument(object value) => (string)value + "test1";
}
Expand Down
18 changes: 18 additions & 0 deletions src/GraphQL.Tests/Attributes/ValidateArgumentsAttributeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public async Task ValidateArguments_works()
hello1(value: "abc")
hello2(value: "def")
hello3(value: "ghi")
hello4(value: "jkl")
}
""";
var expected = """
Expand Down Expand Up @@ -144,6 +145,21 @@ public async Task ValidateArguments_works()
"VALIDATION_ERROR"
]
}
},
{
"message": "jklpass1",
"locations": [
{
"line": 5,
"column": 3
}
],
"extensions": {
"code": "VALIDATION_ERROR",
"codes": [
"VALIDATION_ERROR"
]
}
}
]
}
Expand All @@ -165,6 +181,8 @@ public class ArgTests
public static string Hello2(string value) => value;
[ValidateArguments(typeof(HelperClass), nameof(HelperClass.ValidateHelloArgument))]
public static string Hello3(string value) => value;
[ValidateArguments(typeof(ArgTests), nameof(ValidateHelloArgument))]
public static string Hello4(string value) => value;

private static ValueTask ValidateHelloArgument(FieldArgumentsValidationContext context) => throw new ValidationError(context.GetArgument<string>("value") + "pass1");
}
Expand Down
42 changes: 42 additions & 0 deletions src/GraphQL.Tests/Attributes/ValidatorAttributeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ public async Task validator_works_for_arguments()
hello1(value: "abc")
hello2(value: "def")
hello3(value: "ghi")
hello4(value: "jkl")
}
""";
var expected = """
Expand Down Expand Up @@ -198,6 +199,23 @@ public async Task validator_works_for_arguments()
],
"number": "5.6"
}
},
{
"message": "Invalid value for argument 'value' of field 'hello4'. jklpass1",
"locations": [
{
"line": 5,
"column": 17
}
],
"extensions": {
"code": "INVALID_VALUE",
"codes": [
"INVALID_VALUE",
"INVALID_OPERATION"
],
"number": "5.6"
}
}
]
}
Expand All @@ -216,6 +234,7 @@ public class ArgTests
public static string Hello1([Validator(nameof(ValidateHelloArgument))] string value) => value;
public static string Hello2([Validator(typeof(ValidatorClass))] string value) => value;
public static string Hello3([Validator(typeof(HelperClass), nameof(HelperClass.ValidateHelloArgument))] string value) => value;
public static string Hello4([Validator(typeof(ArgTests), nameof(ValidateHelloArgument))] string value) => value;

private static void ValidateHelloArgument(object value) => throw new InvalidOperationException((string)value + "pass1");
}
Expand All @@ -233,13 +252,17 @@ public async Task validator_works_for_input_fields()
queryType.Field<StringGraphType>("hello3")
.Argument<AutoRegisteringInputObjectGraphType<FieldTests>>("value")
.Resolve(ctx => ctx.GetArgument<FieldTests>("value").Field3);
queryType.Field<StringGraphType>("hello4")
.Argument<AutoRegisteringInputObjectGraphType<FieldTests>>("value")
.Resolve(ctx => ctx.GetArgument<FieldTests>("value").Field3);
var schema = new Schema { Query = queryType };
schema.Initialize();
var query = """
{
hello1(value: { field1: "abc" })
hello2(value: { field2: "def" })
hello3(value: { field3: "ghi" })
hello4(value: { field4: "jkl" })
}
""";
var expected = """
Expand Down Expand Up @@ -295,6 +318,23 @@ public async Task validator_works_for_input_fields()
],
"number": "5.6"
}
},
{
"message": "Invalid value for argument 'value' of field 'hello4'. jklpass1",
"locations": [
{
"line": 5,
"column": 27
}
],
"extensions": {
"code": "INVALID_VALUE",
"codes": [
"INVALID_VALUE",
"INVALID_OPERATION"
],
"number": "5.6"
}
}
]
}
Expand All @@ -316,6 +356,8 @@ public class FieldTests
public string? Field2 { get; set; }
[Validator(typeof(HelperClass), nameof(HelperClass.ValidateHelloArgument))]
public string? Field3 { get; set; }
[Validator(typeof(FieldTests), nameof(ValidateHelloArgument))]
public string? Field4 { get; set; }

private static void ValidateHelloArgument(object value) => throw new InvalidOperationException((string)value + "pass1");
}
Expand Down
6 changes: 2 additions & 4 deletions src/GraphQL/Attributes/ParserAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public sealed class ParserAttribute : GraphQLAttribute
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
private readonly Type? _parserType;
private readonly string _parserMethodName;
private readonly bool _includePrivate;

/// <summary>
/// Specifies a custom parser method for a field of an input object in a GraphQL schema using the specified parser method name.
Expand All @@ -25,7 +24,6 @@ public ParserAttribute(string parserMethodName)
{
_parserMethodName = parserMethodName
?? throw new ArgumentNullException(nameof(parserMethodName));
_includePrivate = true;
}

/// <summary>
Expand Down Expand Up @@ -62,7 +60,7 @@ public override void Modify(FieldType fieldType, bool isInputType, IGraphType gr
return;
var parserType = _parserType ?? memberInfo.DeclaringType!;
var bindingFlags = BindingFlags.Public | BindingFlags.Static;
if (_includePrivate)
if (parserType == memberInfo.DeclaringType!)
bindingFlags |= BindingFlags.NonPublic;
#pragma warning disable IL2075 // UnrecognizedReflectionPattern
var method = parserType.GetMethod(_parserMethodName, bindingFlags, null, [typeof(object)], null)
Expand All @@ -78,7 +76,7 @@ public override void Modify(QueryArgument queryArgument, ParameterInfo parameter
{
var parserType = _parserType ?? parameterInfo.Member.DeclaringType!;
var bindingFlags = BindingFlags.Public | BindingFlags.Static;
if (_includePrivate)
if (parserType == parameterInfo.Member.DeclaringType)
bindingFlags |= BindingFlags.NonPublic;
#pragma warning disable IL2075 // UnrecognizedReflectionPattern
var method = parserType.GetMethod(_parserMethodName, bindingFlags, null, [typeof(object)], null)
Expand Down
4 changes: 1 addition & 3 deletions src/GraphQL/Attributes/ValidateArgumentsAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public sealed class ValidateArgumentsAttribute : GraphQLAttribute
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
private readonly Type? _validationType;
private readonly string _validationMethodName;
private readonly bool _includePrivate;

/// <summary>
/// Specifies a custom argument validation method for a field in a GraphQL schema using the specified validation method name.
Expand All @@ -25,7 +24,6 @@ public ValidateArgumentsAttribute(string validationMethodName)
{
_validationMethodName = validationMethodName
?? throw new ArgumentNullException(nameof(validationMethodName));
_includePrivate = true;
}

/// <summary>
Expand Down Expand Up @@ -62,7 +60,7 @@ public override void Modify(FieldType fieldType, bool isInputType, IGraphType gr
return;
var validationType = _validationType ?? memberInfo.DeclaringType!;
var bindingFlags = BindingFlags.Public | BindingFlags.Static;
if (_includePrivate)
if (validationType == memberInfo.DeclaringType!)
bindingFlags |= BindingFlags.NonPublic;
#pragma warning disable IL2075 // UnrecognizedReflectionPattern
var method = validationType.GetMethod(_validationMethodName, bindingFlags, null, [typeof(FieldArgumentsValidationContext)], null)
Expand Down
6 changes: 2 additions & 4 deletions src/GraphQL/Attributes/ValidatorAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public sealed class ValidatorAttribute : GraphQLAttribute
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
private readonly Type? _validatorType;
private readonly string _validatorMethodName;
private readonly bool _includePrivate;

/// <summary>
/// Specifies a custom validator method for a field of an input object in a GraphQL schema using the specified validator method name.
Expand All @@ -25,7 +24,6 @@ public ValidatorAttribute(string validatorMethodName)
{
_validatorMethodName = validatorMethodName
?? throw new ArgumentNullException(nameof(validatorMethodName));
_includePrivate = true;
}

/// <summary>
Expand Down Expand Up @@ -62,7 +60,7 @@ public override void Modify(FieldType fieldType, bool isInputType, IGraphType gr
return;
var validatorType = _validatorType ?? memberInfo.DeclaringType!;
var bindingFlags = BindingFlags.Public | BindingFlags.Static;
if (_includePrivate)
if (validatorType == memberInfo.DeclaringType!)
bindingFlags |= BindingFlags.NonPublic;
#pragma warning disable IL2075 // UnrecognizedReflectionPattern
var method = validatorType.GetMethod(_validatorMethodName, bindingFlags, null, [typeof(object)], null)
Expand All @@ -78,7 +76,7 @@ public override void Modify(QueryArgument queryArgument, ParameterInfo parameter
{
var validatorType = _validatorType ?? parameterInfo.Member.DeclaringType!;
var bindingFlags = BindingFlags.Public | BindingFlags.Static;
if (_includePrivate)
if (validatorType == parameterInfo.Member.DeclaringType!)
bindingFlags |= BindingFlags.NonPublic;
#pragma warning disable IL2075 // UnrecognizedReflectionPattern
var method = validatorType.GetMethod(_validatorMethodName, bindingFlags, null, [typeof(object)], null)
Expand Down

0 comments on commit 841e422

Please sign in to comment.