Skip to content

Commit 7376a43

Browse files
committed
Fixed GraphQL schema does not support operation validation. (#8125)
1 parent b58d72c commit 7376a43

File tree

8 files changed

+240
-233
lines changed

8 files changed

+240
-233
lines changed

src/HotChocolate/Core/src/Validation/ErrorHelper.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,17 @@ public static IError FieldsAreNotMergeable(
280280
.Build();
281281
}
282282

283+
public static IError OperationNotSupported(
284+
this IDocumentValidatorContext context,
285+
OperationType operationType)
286+
{
287+
return ErrorBuilder.New()
288+
.SetMessage(
289+
Resources.ErrorHelper_OperationNotSupported,
290+
operationType)
291+
.Build();
292+
}
293+
283294
public static IError FragmentNameNotUnique(
284295
this IDocumentValidatorContext context,
285296
FragmentDefinitionNode fragmentDefinition)

src/HotChocolate/Core/src/Validation/Properties/Resources.Designer.cs

Lines changed: 92 additions & 232 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/HotChocolate/Core/src/Validation/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,7 @@
230230
<data name="ErrorHelper_DeferAndStreamLabelIsVariable" xml:space="preserve">
231231
<value>If a label for @defer or @stream is passed, it must not be a variable.</value>
232232
</data>
233+
<data name="ErrorHelper_OperationNotSupported" xml:space="preserve">
234+
<value>This GraphQL schema does not support `{0}` operations.</value>
235+
</data>
233236
</root>

src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ protected override ISyntaxVisitorAction Enter(
3232
OperationDefinitionNode node,
3333
IDocumentValidatorContext context)
3434
{
35+
var operationType = context.Schema.GetOperationType(node.Operation);
36+
37+
if (operationType == null)
38+
{
39+
context.ReportError(context.OperationNotSupported(node.Operation));
40+
return Skip;
41+
}
42+
3543
context.FieldSets.Clear();
3644
context.SelectionSets.Clear();
3745

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"errors": [
33
{
4-
"message": "The specified root type `Mutation` is not supported by this server."
4+
"message": "This GraphQL schema does not support `Mutation` operations."
55
}
66
]
77
}

src/HotChocolate/Core/test/Validation.Tests/FieldMustBeDefinedRuleTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,41 @@ fragment interfaceFieldSelection on Cat {
243243
// assert
244244
Assert.Empty(context.Errors);
245245
}
246+
247+
[Fact]
248+
public void Ensure_Non_Existent_Root_Types_Cause_Error()
249+
{
250+
// arrange
251+
IDocumentValidatorContext context = ValidationUtils.CreateContext(CreateQueryOnlySchema());
252+
var query = Utf8GraphQLParser.Parse(
253+
"""
254+
subscription {
255+
foo
256+
}
257+
""");
258+
context.Prepare(query);
259+
260+
// act
261+
Rule.Validate(context, query);
262+
263+
// assert
264+
Assert.Collection(
265+
context.Errors,
266+
t => Assert.Equal(
267+
"This GraphQL schema does not support `Subscription` operations.",
268+
t.Message));
269+
}
270+
271+
private ISchema CreateQueryOnlySchema()
272+
{
273+
return SchemaBuilder.New()
274+
.AddDocumentFromString(
275+
"""
276+
type Query {
277+
foo: String
278+
}
279+
""")
280+
.Use(next => next)
281+
.Create();
282+
}
246283
}

src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/PagingTests.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,59 @@ await snapshot
9595
.MatchMarkdownAsync();
9696
}
9797

98+
[Fact]
99+
public async Task Execute_On_Missing_Root_Type()
100+
{
101+
// arrange
102+
var snapshot = new Snapshot();
103+
104+
var operation =
105+
Utf8GraphQLParser.Parse(
106+
"""
107+
subscription {
108+
books {
109+
nodes {
110+
title
111+
}
112+
}
113+
}
114+
""");
115+
116+
var request =
117+
OperationRequestBuilder.New()
118+
.SetDocument(operation)
119+
.ReportCost()
120+
.Build();
121+
122+
var executor =
123+
await new ServiceCollection()
124+
.AddGraphQLServer()
125+
.AddQueryType<Query>()
126+
.ModifyPagingOptions(o => o.RequirePagingBoundaries = false)
127+
.AddFiltering()
128+
.AddSorting()
129+
.BuildRequestExecutorAsync();
130+
131+
// act
132+
var response = await executor.ExecuteAsync(request);
133+
134+
// assert
135+
var expectation =
136+
JsonDocument.Parse(
137+
"""
138+
{
139+
"fieldCost": 6,
140+
"typeCost": 12
141+
}
142+
""");
143+
144+
await snapshot
145+
.Add(operation, "Operation")
146+
.Add(expectation.RootElement, "Expected")
147+
.Add(response, "Response")
148+
.MatchMarkdownAsync();
149+
}
150+
98151
[Fact]
99152
public async Task Require_Paging_Boundaries_By_Default_With_Connections()
100153
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Execute_On_Missing_Root_Type
2+
3+
## Operation
4+
5+
```graphql
6+
subscription {
7+
books {
8+
nodes {
9+
title
10+
}
11+
}
12+
}
13+
```
14+
15+
## Expected
16+
17+
```json
18+
{
19+
"fieldCost": 6,
20+
"typeCost": 12
21+
}
22+
```
23+
24+
## Response
25+
26+
```json
27+
{
28+
"errors": [
29+
{
30+
"message": "This GraphQL schema does not support `Subscription` operations."
31+
}
32+
]
33+
}
34+
```
35+

0 commit comments

Comments
 (0)