Skip to content

Commit 2d3740c

Browse files
authored
Update parser (#714)
1 parent 00f0455 commit 2d3740c

28 files changed

+138
-100
lines changed

.editorconfig

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,12 @@ dotnet_naming_style.end_in_async_style.required_suffix = Async
256256
# dotnet_naming_rule.<namingRuleTitle>.severity = <value>
257257
dotnet_naming_rule.async_methods_end_in_async.severity = warning
258258

259-
# Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
260-
dotnet_diagnostic.IDE0005.severity = warning
261-
262259
# IDE1006: Naming Styles (Async methods should have "Async" suffix, see rule above)
263260
dotnet_diagnostic.IDE1006.severity = suggestion
261+
262+
# Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
263+
dotnet_diagnostic.IDE0005.severity = error
264+
265+
# Enforce formatting https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#rule-id-ide0055-fix-formatting
266+
dotnet_diagnostic.IDE0055.severity = error
267+

samples/Samples.Server/Samples.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<ItemGroup>
1212
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
1313
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
14-
<PackageReference Include="GraphQL.MicrosoftDI" Version="5.0.0-preview-414" />
14+
<PackageReference Include="GraphQL.MicrosoftDI" Version="5.0.0-preview-452" />
1515
</ItemGroup>
1616

1717
<ItemGroup>

src/All/All.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
<ProjectReference Include="..\Ui.Playground\Ui.Playground.csproj" />
2222
<ProjectReference Include="..\Ui.Voyager\Ui.Voyager.csproj" />
2323

24-
<PackageReference Include="GraphQL.MemoryCache" Version="5.0.0-preview-414" />
25-
<PackageReference Include="GraphQL.MicrosoftDI" Version="5.0.0-preview-414" />
26-
<PackageReference Include="GraphQL.SystemReactive" Version="5.0.0-preview-414" />
24+
<PackageReference Include="GraphQL.MemoryCache" Version="5.0.0-preview-452" />
25+
<PackageReference Include="GraphQL.MicrosoftDI" Version="5.0.0-preview-452" />
26+
<PackageReference Include="GraphQL.SystemReactive" Version="5.0.0-preview-452" />
2727
</ItemGroup>
2828

2929
</Project>

src/Authorization.AspNetCore/AuthorizationError.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#nullable enable
22

33
using System;
4-
using GraphQL.Language.AST;
54
using GraphQL.Validation;
5+
using GraphQLParser.AST;
66
using Microsoft.AspNetCore.Authorization;
77

88
namespace GraphQL.Server.Authorization.AspNetCore
@@ -15,8 +15,8 @@ public class AuthorizationError : ValidationError
1515
/// <summary>
1616
/// Initializes a new instance of the <see cref="AuthorizationError"/> class for a specified authorization result with a specific error message.
1717
/// </summary>
18-
public AuthorizationError(INode? node, ValidationContext context, string message, AuthorizationResult result, OperationType? operationType = null)
19-
: base(context.Document.OriginalQuery!, "6.1.1", message, node == null ? Array.Empty<INode>() : new INode[] { node })
18+
public AuthorizationError(ASTNode? node, ValidationContext context, string message, AuthorizationResult result, OperationType? operationType = null)
19+
: base(context.Document.Source, "6.1.1", message, node == null ? Array.Empty<ASTNode>() : new ASTNode[] { node })
2020
{
2121
Code = "authorization";
2222
AuthorizationResult = result;
@@ -32,7 +32,5 @@ public AuthorizationError(INode? node, ValidationContext context, string message
3232
/// The GraphQL operation type.
3333
/// </summary>
3434
public OperationType? OperationType { get; }
35-
36-
3735
}
3836
}

src/Authorization.AspNetCore/AuthorizationValidationRule.cs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#nullable enable
22

33
using System.Collections.Generic;
4-
using System.Linq;
54
using System.Security.Claims;
5+
using System.Threading;
66
using System.Threading.Tasks;
7-
using GraphQL.Language.AST;
87
using GraphQL.Types;
98
using GraphQL.Validation;
9+
using GraphQLParser;
10+
using GraphQLParser.AST;
11+
using GraphQLParser.Visitors;
1012
using Microsoft.AspNetCore.Authorization;
1113

1214
namespace GraphQL.Server.Authorization.AspNetCore
@@ -37,9 +39,9 @@ public AuthorizationValidationRule(
3739
_messageBuilder = messageBuilder;
3840
}
3941

40-
private bool ShouldBeSkipped(Operation? actualOperation, ValidationContext context)
42+
private bool ShouldBeSkipped(GraphQLOperationDefinition actualOperation, ValidationContext context)
4143
{
42-
if (context.Document.Operations.Count <= 1)
44+
if (context.Document.OperationsCount() <= 1)
4345
{
4446
return false;
4547
}
@@ -59,76 +61,85 @@ private bool ShouldBeSkipped(Operation? actualOperation, ValidationContext conte
5961
return true;
6062
}
6163

62-
if (ancestor is FragmentDefinition fragment)
64+
if (ancestor is GraphQLFragmentDefinition fragment)
6365
{
64-
return !FragmentBelongsToOperation(fragment, actualOperation);
66+
//TODO: may be rewritten completely later
67+
var c = new FragmentBelongsToOperationVisitorContext(fragment);
68+
_visitor.VisitAsync(actualOperation, c).GetAwaiter().GetResult(); // TODO: need to think of something to avoid this
69+
return !c.Found;
6570
}
6671
} while (true);
6772
}
6873

69-
private bool FragmentBelongsToOperation(FragmentDefinition fragment, Operation? operation)
74+
private sealed class FragmentBelongsToOperationVisitorContext : IASTVisitorContext
7075
{
71-
bool belongs = false;
72-
void Visit(INode? node, int _)
76+
public FragmentBelongsToOperationVisitorContext(GraphQLFragmentDefinition fragment)
7377
{
74-
if (belongs)
75-
{
76-
return;
77-
}
78+
Fragment = fragment;
79+
}
7880

79-
belongs = node is FragmentSpread fragmentSpread && fragmentSpread.Name == fragment.Name;
81+
public GraphQLFragmentDefinition Fragment { get; }
8082

81-
if (node != null)
82-
{
83-
node.Visit(Visit, 0);
84-
}
85-
}
83+
public bool Found { get; set; }
84+
85+
public CancellationToken CancellationToken => default;
86+
}
8687

87-
operation?.Visit(Visit, 0);
88+
private static readonly FragmentBelongsToOperationVisitor _visitor = new();
8889

89-
return belongs;
90+
private sealed class FragmentBelongsToOperationVisitor : ASTVisitor<FragmentBelongsToOperationVisitorContext>
91+
{
92+
protected override ValueTask VisitFragmentSpreadAsync(GraphQLFragmentSpread fragmentSpread, FragmentBelongsToOperationVisitorContext context)
93+
{
94+
context.Found = context.Fragment.FragmentName.Name == fragmentSpread.FragmentName.Name;
95+
return default;
96+
}
97+
98+
public override ValueTask VisitAsync(ASTNode? node, FragmentBelongsToOperationVisitorContext context)
99+
{
100+
return context.Found ? default : base.VisitAsync(node, context);
101+
}
90102
}
91103

92104
/// <inheritdoc />
93105
public async ValueTask<INodeVisitor?> ValidateAsync(ValidationContext context)
94106
{
95107
await AuthorizeAsync(null, context.Schema, context, null);
96108
var operationType = OperationType.Query;
97-
var actualOperation = context.Document.Operations.FirstOrDefault(x => x.Name == context.OperationName) ?? context.Document.Operations.FirstOrDefault();
98109

99110
// this could leak info about hidden fields or types in error messages
100111
// it would be better to implement a filter on the Schema so it
101112
// acts as if they just don't exist vs. an auth denied error
102113
// - filtering the Schema is not currently supported
103114
// TODO: apply ISchemaFilter - context.Schema.Filter.AllowXXX
104115
return new NodeVisitors(
105-
new MatchingNodeVisitor<Operation>((astType, context) =>
116+
new MatchingNodeVisitor<GraphQLOperationDefinition>((astType, context) =>
106117
{
107-
if (context.Document.Operations.Count > 1 && astType.Name != context.OperationName)
118+
if (context.Document.OperationsCount() > 1 && astType.Name != context.Operation.Name)
108119
{
109120
return;
110121
}
111122

112-
operationType = astType.OperationType;
123+
operationType = astType.Operation;
113124

114125
var type = context.TypeInfo.GetLastType();
115126
AuthorizeAsync(astType, type, context, operationType).GetAwaiter().GetResult(); // TODO: need to think of something to avoid this
116127
}),
117128

118-
new MatchingNodeVisitor<ObjectField>((objectFieldAst, context) =>
129+
new MatchingNodeVisitor<GraphQLObjectField>((objectFieldAst, context) =>
119130
{
120-
if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is IComplexGraphType argumentType && !ShouldBeSkipped(actualOperation, context))
131+
if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is IComplexGraphType argumentType && !ShouldBeSkipped(context.Operation, context))
121132
{
122133
var fieldType = argumentType.GetField(objectFieldAst.Name);
123134
AuthorizeAsync(objectFieldAst, fieldType, context, operationType).GetAwaiter().GetResult(); // TODO: need to think of something to avoid this
124135
}
125136
}),
126137

127-
new MatchingNodeVisitor<Field>((fieldAst, context) =>
138+
new MatchingNodeVisitor<GraphQLField>((fieldAst, context) =>
128139
{
129140
var fieldDef = context.TypeInfo.GetFieldDef();
130141

131-
if (fieldDef == null || ShouldBeSkipped(actualOperation, context))
142+
if (fieldDef == null || ShouldBeSkipped(context.Operation, context))
132143
return;
133144

134145
// check target field
@@ -137,9 +148,9 @@ void Visit(INode? node, int _)
137148
AuthorizeAsync(fieldAst, fieldDef.ResolvedType?.GetNamedType(), context, operationType).GetAwaiter().GetResult(); // TODO: need to think of something to avoid this
138149
}),
139150

140-
new MatchingNodeVisitor<VariableReference>((variableRef, context) =>
151+
new MatchingNodeVisitor<GraphQLVariable>((variableRef, context) =>
141152
{
142-
if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is not IComplexGraphType variableType || ShouldBeSkipped(actualOperation, context))
153+
if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is not IComplexGraphType variableType || ShouldBeSkipped(context.Operation, context))
143154
return;
144155

145156
AuthorizeAsync(variableRef, variableType, context, operationType).GetAwaiter().GetResult(); // TODO: need to think of something to avoid this;
@@ -149,7 +160,7 @@ void Visit(INode? node, int _)
149160
// validation rule should check that but here we should just ignore that
150161
// "unknown" field.
151162
if (context.Variables != null &&
152-
context.Variables.TryGetValue(variableRef.Name, out object? input) &&
163+
context.Variables.TryGetValue(variableRef.Name.StringValue, out object? input) && //ISSUE:allocation
153164
input is Dictionary<string, object> fieldsValues)
154165
{
155166
foreach (var field in variableType.Fields)
@@ -164,7 +175,7 @@ void Visit(INode? node, int _)
164175
);
165176
}
166177

167-
private async Task AuthorizeAsync(INode? node, IProvideMetadata? provider, ValidationContext context, OperationType? operationType)
178+
private async Task AuthorizeAsync(ASTNode? node, IProvideMetadata? provider, ValidationContext context, OperationType? operationType)
168179
{
169180
var policyNames = provider?.GetPolicies();
170181

@@ -198,7 +209,7 @@ private async Task AuthorizeAsync(INode? node, IProvideMetadata? provider, Valid
198209
/// <summary>
199210
/// Adds an authorization failure error to the document response
200211
/// </summary>
201-
protected virtual void AddValidationError(INode? node, ValidationContext context, OperationType? operationType, AuthorizationResult result)
212+
protected virtual void AddValidationError(ASTNode? node, ValidationContext context, OperationType? operationType, AuthorizationResult result)
202213
{
203214
string message = _messageBuilder.GenerateMessage(operationType, result);
204215
context.ReportError(new AuthorizationError(node, context, message, result, operationType));

src/Authorization.AspNetCore/DefaultAuthorizationErrorMessageBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using System.Linq;
44
using System.Text;
5-
using GraphQL.Language.AST;
5+
using GraphQLParser.AST;
66
using Microsoft.AspNetCore.Authorization;
77
using Microsoft.AspNetCore.Authorization.Infrastructure;
88

src/Authorization.AspNetCore/IAuthorizationErrorMessageBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#nullable enable
22

33
using System.Text;
4-
using GraphQL.Language.AST;
4+
using GraphQLParser.AST;
55
using Microsoft.AspNetCore.Authorization;
66

77
namespace GraphQL.Server.Authorization.AspNetCore;

src/Benchmarks/Benchmarks/DeserializeFromJsonBodyBenchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void GlobalSetup()
4545
_httpRequest = GetHttpRequestFor(gqlRequestJson);
4646

4747
gqlRequest.OperationName = "someOperationName";
48-
gqlRequest.Inputs = SHORT_JSON.ToInputs();
48+
gqlRequest.Inputs = new GraphQLSerializer().Deserialize<Inputs>(SHORT_JSON);
4949
var gqlRequestJson2 = Serializer.ToJson(gqlRequest);
5050
_httpRequest2 = GetHttpRequestFor(gqlRequestJson2);
5151
}

src/Core/Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="GraphQL.DataLoader" Version="5.0.0-preview-414" />
11+
<PackageReference Include="GraphQL.DataLoader" Version="5.0.0-preview-452" />
1212
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.0" />
1313
</ItemGroup>
1414

src/Transports.AspNetCore.NewtonsoftJson/GraphQLRequestDeserializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public GraphQLRequestDeserializer(Action<JsonSerializerSettings> configure)
2424
DateParseHandling = DateParseHandling.None,
2525
Converters =
2626
{
27-
new InputsConverter()
27+
new InputsJsonConverter()
2828
},
2929
};
3030
configure?.Invoke(settings);
@@ -77,7 +77,7 @@ public Task<GraphQLRequestDeserializationResult> DeserializeFromJsonBodyAsync(Ht
7777
return Task.FromResult(result);
7878
}
7979

80-
public Inputs DeserializeInputsFromJson(string json) => json?.ToInputs();
80+
public Inputs DeserializeInputsFromJson(string json) => new GraphQLSerializer().Deserialize<Inputs>(json);
8181

8282
private static GraphQLRequest ToGraphQLRequest(InternalGraphQLRequest internalGraphQLRequest)
8383
=> new GraphQLRequest

0 commit comments

Comments
 (0)