Skip to content

Commit 4d7207e

Browse files
Remove "And", "Or", and Relationships as valid OrderByInput types. (#2625)
## Why make this change? Closes #2286 ## What is this change? The `InputTypeBuilder` class holds a function called `GenerateOrderByInputTypeForObjectType`, which is responsible for populating the GraphQL Schema with the valid OrderByInput types. It was mistakenly adding in "and", "or", and columns that are in entities associated through relationships as valid OrderByInput types. "and" and "or" will never be valid input types, and we do not yet support order by using columns from related entities. ## How was this tested? Manually verified that the correct error was returned when trying to use the incorrect orderBy queries, and manually verified that we no longer have them in the schema. Added regression test to verify we get an error when attempting these queries. ## Sample Request(s) These are some example graph QL queries that are invalid but were showing as valid in our schema without this fix. >publishers (first: 5 orderBy: {books: { title: DESC }}){ > items { > id > books { > items { > title > } > } > } > } >books(orderBy: { or: { id: ASC, title: ASC } }) { items { id } } --------- Co-authored-by: Aniruddh Munde <[email protected]>
1 parent aee9690 commit 4d7207e

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

src/Service.GraphQLBuilder/Queries/InputTypeBuilder.cs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,25 @@ IDictionary<string, InputObjectTypeDefinitionNode> inputTypes
2424
{
2525
List<InputValueDefinitionNode> inputFields = GenerateFilterInputFieldsForBuiltInFields(node, inputTypes);
2626
string filterInputName = GenerateObjectInputFilterName(node);
27-
28-
GenerateInputTypeFromInputFields(inputTypes, inputFields, filterInputName, $"Filter input for {node.Name} GraphQL type");
27+
GenerateFilterInputTypeFromInputFields(inputTypes, inputFields, filterInputName, $"Filter input for {node.Name} GraphQL type");
2928
}
3029

3130
internal static void GenerateOrderByInputTypeForObjectType(ObjectTypeDefinitionNode node, IDictionary<string, InputObjectTypeDefinitionNode> inputTypes)
3231
{
3332
List<InputValueDefinitionNode> inputFields = GenerateOrderByInputFieldsForBuiltInFields(node);
3433
string orderByInputName = GenerateObjectInputOrderByName(node);
3534

36-
GenerateInputTypeFromInputFields(inputTypes, inputFields, orderByInputName, $"Order by input for {node.Name} GraphQL type");
35+
// OrderBy does not include "and" and "or" input types so we add only the orderByInputName here.
36+
inputTypes.Add(
37+
orderByInputName,
38+
new(
39+
location: null,
40+
new NameNode(orderByInputName),
41+
new StringValueNode($"Order by input for {node.Name} GraphQL type"),
42+
new List<DirectiveNode>(),
43+
inputFields
44+
)
45+
);
3746
}
3847

3948
private static List<InputValueDefinitionNode> GenerateOrderByInputFieldsForBuiltInFields(ObjectTypeDefinitionNode node)
@@ -53,27 +62,12 @@ private static List<InputValueDefinitionNode> GenerateOrderByInputFieldsForBuilt
5362
new List<DirectiveNode>())
5463
);
5564
}
56-
else
57-
{
58-
string targetEntityName = RelationshipDirectiveType.Target(field);
59-
60-
inputFields.Add(
61-
new(
62-
location: null,
63-
field.Name,
64-
new StringValueNode($"Order by options for {field.Name}"),
65-
new NamedTypeNode(GenerateObjectInputOrderByName(targetEntityName)),
66-
defaultValue: null,
67-
new List<DirectiveNode>())
68-
);
69-
}
70-
7165
}
7266

7367
return inputFields;
7468
}
7569

76-
private static void GenerateInputTypeFromInputFields(
70+
private static void GenerateFilterInputTypeFromInputFields(
7771
IDictionary<string, InputObjectTypeDefinitionNode> inputTypes,
7872
List<InputValueDefinitionNode> inputFields,
7973
string inputTypeName,

src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,62 @@ public virtual async Task TestInvalidFilterParamQuery()
21462146
SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString());
21472147
}
21482148

2149+
[TestMethod]
2150+
public virtual async Task TestInvalidOrderByQueryUsingAnd()
2151+
{
2152+
string graphQLQueryName = "publishers";
2153+
string graphQLQuery = @"{
2154+
books(orderBy: { and: { id: ASC, title: ASC } }) {
2155+
items {
2156+
id
2157+
}
2158+
}
2159+
}";
2160+
2161+
JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false);
2162+
SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString());
2163+
}
2164+
2165+
[TestMethod]
2166+
public virtual async Task TestInvalidOrderByQueryUsingOr()
2167+
{
2168+
string graphQLQueryName = "publishers";
2169+
string graphQLQuery = @"{
2170+
books(orderBy: { or: { id: ASC, title: ASC } }) {
2171+
items {
2172+
id
2173+
}
2174+
}
2175+
}";
2176+
2177+
JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false);
2178+
SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString());
2179+
}
2180+
2181+
[TestMethod]
2182+
public virtual async Task TestInvalidOrderByQueryUsingRelationship()
2183+
{
2184+
string graphQLQueryName = "publishers";
2185+
string graphQLQuery = @"{
2186+
publishers (first: 5 orderBy: {books: {
2187+
title: DESC
2188+
}
2189+
}){
2190+
items {
2191+
id
2192+
books {
2193+
items {
2194+
title
2195+
}
2196+
}
2197+
}
2198+
}
2199+
}";
2200+
2201+
JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false);
2202+
SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString());
2203+
}
2204+
21492205
/// <summary>
21502206
/// Test to check that sourceFields and targetFields for relationship provided in the config
21512207
/// overrides relationship fields defined in DB.

0 commit comments

Comments
 (0)