Skip to content

Commit 28b9a1e

Browse files
authored
Move ValidateName calls after NameConverter is applied (graphql-dotnet#1961)
1 parent b698cb9 commit 28b9a1e

File tree

9 files changed

+109
-18
lines changed

9 files changed

+109
-18
lines changed

src/GraphQL.Tests/Types/ComplexGraphTypeTests.cs

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.ComponentModel;
55
using System.ComponentModel.DataAnnotations;
66
using System.Linq;
7+
using GraphQL.Conversion;
78
using GraphQL.StarWars.Types;
89
using GraphQL.Types;
910
using GraphQL.Utilities;
@@ -302,13 +303,27 @@ public void throws_informative_exception_when_no_types_defined_on_more_generic_t
302303
exception.Message.ShouldStartWith("The declared field 'genericname' on 'ListOfDroid' requires a field 'Type' when no 'ResolvedType' is provided.");
303304
}
304305

306+
private Exception test_field_name(string fieldName)
307+
{
308+
// test failure
309+
return Should.Throw<ArgumentOutOfRangeException>(() =>
310+
{
311+
var type = new ObjectGraphType();
312+
type.Field<StringGraphType>(fieldName);
313+
var schema = new Schema
314+
{
315+
Query = type
316+
};
317+
schema.Initialize();
318+
});
319+
}
320+
305321
[Theory]
306322
[InlineData("__id")]
307323
[InlineData("___id")]
308324
public void throws_when_field_name_prefix_with_reserved_underscores(string fieldName)
309325
{
310-
var type = new ComplexType<TestObject>();
311-
var exception = Should.Throw<ArgumentOutOfRangeException>(() => type.Field<StringGraphType>(fieldName));
326+
var exception = test_field_name(fieldName);
312327

313328
exception.Message.ShouldStartWith($"A field name: {fieldName} must not begin with \"__\", which is reserved by GraphQL introspection.");
314329
}
@@ -319,12 +334,64 @@ public void throws_when_field_name_prefix_with_reserved_underscores(string field
319334
[InlineData("id$")]
320335
public void throws_when_field_name_doesnot_follow_spec(string fieldName)
321336
{
322-
var type = new ComplexType<TestObject>();
323-
var exception = Should.Throw<ArgumentOutOfRangeException>(() => type.Field<StringGraphType>(fieldName));
337+
var exception = test_field_name(fieldName);
324338

325339
exception.Message.ShouldStartWith($"A field name must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but {fieldName} does not.");
326340
}
327341

342+
[Theory]
343+
[InlineData("__id")]
344+
[InlineData("___id")]
345+
[InlineData("i#d")]
346+
[InlineData("i$d")]
347+
[InlineData("id$")]
348+
public void does_not_throw_with_filtering_nameconverter(string fieldName)
349+
{
350+
var type = new ObjectGraphType();
351+
type.Field<StringGraphType>(fieldName);
352+
var schema = new Schema
353+
{
354+
Query = type,
355+
NameConverter = new TestNameConverter(fieldName, "pass")
356+
};
357+
schema.Initialize();
358+
}
359+
360+
[Fact]
361+
public void throws_with_bad_namevalidator()
362+
{
363+
var exception = Should.Throw<ArgumentOutOfRangeException>(() =>
364+
{
365+
var type = new ObjectGraphType();
366+
type.Field<StringGraphType>("hello");
367+
var schema = new Schema
368+
{
369+
Query = type,
370+
NameConverter = new TestNameConverter("hello", "hello$")
371+
};
372+
schema.Initialize();
373+
});
374+
375+
exception.Message.ShouldStartWith($"A field name must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but hello$ does not.");
376+
}
377+
378+
private class TestNameConverter : INameConverter
379+
{
380+
private readonly string _from;
381+
private readonly string _to;
382+
public TestNameConverter(string from, string to)
383+
{
384+
_from = from;
385+
_to = to;
386+
}
387+
388+
public string NameForArgument(string argumentName, IComplexGraphType parentGraphType, FieldType field)
389+
=> argumentName == _from ? _to : argumentName;
390+
391+
public string NameForField(string fieldName, IComplexGraphType parentGraphType)
392+
=> fieldName == _from ? _to : fieldName;
393+
}
394+
328395
[Theory]
329396
[InlineData("")]
330397
[InlineData(null)]

src/GraphQL/Builders/ConnectionBuilder.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ public ConnectionBuilder<TSourceType> Bidirectional()
107107

108108
public ConnectionBuilder<TSourceType> Name(string name)
109109
{
110-
NameValidator.ValidateName(name);
111-
112110
FieldType.Name = name;
113111
return this;
114112
}

src/GraphQL/Builders/FieldBuilder.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ public virtual FieldBuilder<TSourceType, TReturnType> Type(IGraphType type)
5555

5656
public virtual FieldBuilder<TSourceType, TReturnType> Name(string name)
5757
{
58-
NameValidator.ValidateName(name);
59-
6058
FieldType.Name = name;
6159
return this;
6260
}

src/GraphQL/Types/Composite/ComplexGraphType.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ public virtual FieldType AddField(FieldType fieldType)
7575
}
7676
}
7777

78-
NameValidator.ValidateName(fieldType.Name);
78+
//check if fieldType.Name has never been set
79+
NameValidator.ValidateNameNotNull(fieldType.Name);
7980

8081
if (HasField(fieldType.Name))
8182
{

src/GraphQL/Types/Fields/FieldType.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ public class FieldType : MetadataProvider, IFieldType, IProvideResolvedType
1212
private object _defaultValue;
1313
private IValue _defaultValueAST;
1414

15-
public string Name { get; set; }
15+
private string _name;
16+
public string Name
17+
{
18+
get => _name;
19+
set
20+
{
21+
NameValidator.ValidateNameNotNull(value);
22+
_name = value;
23+
}
24+
}
1625

1726
public string Description { get; set; }
1827

src/GraphQL/Types/GraphTypesLookup.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using GraphQL.Conversion;
66
using GraphQL.Introspection;
77
using GraphQL.Types.Relay;
8+
using GraphQL.Utilities;
89

910
namespace GraphQL.Types
1011
{
@@ -362,6 +363,7 @@ private void HandleField(IComplexGraphType parentType, FieldType field, TypeColl
362363
if (applyNameConverter)
363364
{
364365
field.Name = NameConverter.NameForField(field.Name, parentType);
366+
NameValidator.ValidateName(field.Name);
365367
}
366368

367369
if (field.ResolvedType == null)
@@ -382,6 +384,7 @@ private void HandleField(IComplexGraphType parentType, FieldType field, TypeColl
382384
if (applyNameConverter)
383385
{
384386
arg.Name = NameConverter.NameForArgument(arg.Name, parentType, field);
387+
NameValidator.ValidateName(arg.Name, "argument");
385388
}
386389

387390
if (arg.ResolvedType != null)

src/GraphQL/Types/QueryArgument.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,16 @@ public QueryArgument(Type type)
3737
Type = type;
3838
}
3939

40-
public string Name { get; set; }
40+
private string _name;
41+
public string Name
42+
{
43+
get => _name;
44+
set
45+
{
46+
NameValidator.ValidateNameNotNull(value, "argument");
47+
_name = value;
48+
}
49+
}
4150

4251
public string Description { get; set; }
4352

src/GraphQL/Types/QueryArguments.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public QueryArgument this[int index]
2828
get => ArgumentsList != null ? ArgumentsList[index] : throw new IndexOutOfRangeException();
2929
set
3030
{
31-
if (value != null)
31+
if (value != null && string.IsNullOrEmpty(value.Name))
3232
{
3333
NameValidator.ValidateName(value.Name, "argument");
3434
}
@@ -49,7 +49,8 @@ public void Add(QueryArgument argument)
4949
if (argument == null)
5050
throw new ArgumentNullException(nameof(argument));
5151

52-
NameValidator.ValidateName(argument.Name, "argument");
52+
if (string.IsNullOrEmpty(argument.Name))
53+
NameValidator.ValidateName(argument.Name, "argument");
5354

5455
if (ArgumentsList == null)
5556
ArgumentsList = new List<QueryArgument>();

src/GraphQL/Utilities/NameValidator.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ public static class NameValidator
1010

1111
public static void ValidateName(string name, string type = "field")
1212
{
13-
if (string.IsNullOrWhiteSpace(name))
14-
{
15-
throw new ArgumentOutOfRangeException(nameof(name),
16-
$"A {type} name can not be null or empty.");
17-
}
13+
ValidateNameNotNull(name, type);
1814

1915
if (name.Length > 1 && name.StartsWith(RESERVED_PREFIX, StringComparison.InvariantCulture))
2016
{
@@ -27,5 +23,14 @@ public static void ValidateName(string name, string type = "field")
2723
$"A {type} name must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but {name} does not.");
2824
}
2925
}
26+
27+
internal static void ValidateNameNotNull(string name, string type = "field")
28+
{
29+
if (string.IsNullOrWhiteSpace(name))
30+
{
31+
throw new ArgumentOutOfRangeException(nameof(name),
32+
$"A {type} name can not be null or empty.");
33+
}
34+
}
3035
}
3136
}

0 commit comments

Comments
 (0)