Skip to content

Commit a390cb9

Browse files
authored
NRT (#181)
1 parent 5094301 commit a390cb9

19 files changed

+99
-73
lines changed

src/BasicSample/Program.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace BasicSample
1414
{
1515
internal class Program
1616
{
17-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "main")]
1817
private static async Task Main()
1918
{
2019
using var serviceProvider = new ServiceCollection()
@@ -61,10 +60,10 @@ type Query {
6160
/// <summary>
6261
/// Custom context class that implements <see cref="IProvideClaimsPrincipal"/>.
6362
/// </summary>
64-
public class GraphQLUserContext : Dictionary<string, object>, IProvideClaimsPrincipal
63+
public class GraphQLUserContext : Dictionary<string, object?>, IProvideClaimsPrincipal
6564
{
6665
/// <inheritdoc />
67-
public ClaimsPrincipal User { get; set; }
66+
public ClaimsPrincipal? User { get; set; }
6867
}
6968

7069
/// <summary>
@@ -92,11 +91,11 @@ public class User
9291
/// <summary>
9392
/// Resolver for 'User.id' field. Just a simple property.
9493
/// </summary>
95-
public string Id { get; set; }
94+
public string? Id { get; set; }
9695

9796
/// <summary>
9897
/// Resolver for 'User.name' field. Just a simple property.
9998
/// </summary>
100-
public string Name { get; set; }
99+
public string? Name { get; set; }
101100
}
102101
}

src/Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<DebugType>embedded</DebugType>
1717
<EmbedUntrackedSources>true</EmbedUntrackedSources>
1818
<EnableNETAnalyzers>true</EnableNETAnalyzers>
19+
<Nullable>enable</Nullable>
1920
</PropertyGroup>
2021

2122
<ItemGroup>

src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.approved.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ namespace GraphQL.Authorization
1010
public AuthorizationContext() { }
1111
public System.Collections.Generic.IEnumerable<string> Errors { get; }
1212
public bool HasErrors { get; }
13-
public System.Collections.Generic.IReadOnlyDictionary<string, object> Inputs { get; set; }
14-
public System.Security.Claims.ClaimsPrincipal User { get; set; }
15-
public System.Collections.Generic.IDictionary<string, object> UserContext { get; set; }
13+
public System.Collections.Generic.IReadOnlyDictionary<string, object>? Inputs { get; set; }
14+
public System.Security.Claims.ClaimsPrincipal? User { get; set; }
15+
public System.Collections.Generic.IDictionary<string, object?>? UserContext { get; set; }
1616
public void ReportError(string error) { }
1717
}
1818
public class AuthorizationEvaluator : GraphQL.Authorization.IAuthorizationEvaluator
1919
{
2020
public AuthorizationEvaluator(GraphQL.Authorization.AuthorizationSettings settings) { }
21-
public System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal principal, System.Collections.Generic.IDictionary<string, object> userContext, System.Collections.Generic.IReadOnlyDictionary<string, object> inputs, System.Collections.Generic.IEnumerable<string> requiredPolicies) { }
21+
public System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, System.Collections.Generic.IReadOnlyDictionary<string, object>? inputs, System.Collections.Generic.IEnumerable<string>? requiredPolicies) { }
2222
}
2323
public class AuthorizationPolicy : GraphQL.Authorization.IAuthorizationPolicy
2424
{
@@ -33,12 +33,12 @@ namespace GraphQL.Authorization
3333
public GraphQL.Authorization.AuthorizationPolicyBuilder RequireAuthenticatedUser() { }
3434
public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType) { }
3535
public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues) { }
36-
public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues, System.Collections.Generic.IEnumerable<string> displayValues) { }
36+
public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }
3737
}
3838
public class AuthorizationResult
3939
{
4040
public AuthorizationResult() { }
41-
public System.Collections.Generic.IEnumerable<string> Errors { get; }
41+
public System.Collections.Generic.IEnumerable<string>? Errors { get; }
4242
public bool Succeeded { get; }
4343
public static GraphQL.Authorization.AuthorizationResult Fail(System.Collections.Generic.IEnumerable<string> errors) { }
4444
public static GraphQL.Authorization.AuthorizationResult Success() { }
@@ -50,27 +50,27 @@ namespace GraphQL.Authorization
5050
public void AddPolicy(string name, GraphQL.Authorization.IAuthorizationPolicy policy) { }
5151
public void AddPolicy(string name, System.Action<GraphQL.Authorization.AuthorizationPolicyBuilder> configure) { }
5252
public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationPolicy> GetPolicies(System.Collections.Generic.IEnumerable<string> policies) { }
53-
public GraphQL.Authorization.IAuthorizationPolicy GetPolicy(string name) { }
53+
public GraphQL.Authorization.IAuthorizationPolicy? GetPolicy(string name) { }
5454
}
5555
public class AuthorizationValidationRule : GraphQL.Validation.IValidationRule
5656
{
5757
public AuthorizationValidationRule(GraphQL.Authorization.IAuthorizationEvaluator evaluator) { }
58-
public System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor> ValidateAsync(GraphQL.Validation.ValidationContext context) { }
58+
public System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor?> ValidateAsync(GraphQL.Validation.ValidationContext context) { }
5959
}
6060
public class ClaimAuthorizationRequirement : GraphQL.Authorization.IAuthorizationRequirement
6161
{
6262
public ClaimAuthorizationRequirement(string claimType) { }
6363
public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues) { }
6464
public ClaimAuthorizationRequirement(string claimType, params string[] allowedValues) { }
65-
public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues, System.Collections.Generic.IEnumerable<string> displayValues) { }
65+
public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }
6666
public System.Collections.Generic.IEnumerable<string> AllowedValues { get; }
6767
public string ClaimType { get; }
68-
public System.Collections.Generic.IEnumerable<string> DisplayValues { get; }
68+
public System.Collections.Generic.IEnumerable<string>? DisplayValues { get; }
6969
public System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context) { }
7070
}
7171
public interface IAuthorizationEvaluator
7272
{
73-
System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal principal, System.Collections.Generic.IDictionary<string, object> userContext, System.Collections.Generic.IReadOnlyDictionary<string, object> inputs, System.Collections.Generic.IEnumerable<string> requiredPolicies);
73+
System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, System.Collections.Generic.IReadOnlyDictionary<string, object>? inputs, System.Collections.Generic.IEnumerable<string>? requiredPolicies);
7474
}
7575
public interface IAuthorizationPolicy
7676
{
@@ -82,6 +82,6 @@ namespace GraphQL.Authorization
8282
}
8383
public interface IProvideClaimsPrincipal
8484
{
85-
System.Security.Claims.ClaimsPrincipal User { get; }
85+
System.Security.Claims.ClaimsPrincipal? User { get; }
8686
}
8787
}

src/GraphQL.Authorization.Tests/AuthorizationSchemaBuilderTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ type Query {
2020

2121
schema.Initialize();
2222

23-
var query = schema.AllTypes["Query"] as IObjectGraphType;
23+
var query = (IObjectGraphType)schema.AllTypes["Query"]!;
2424
query.RequiresAuthorization().ShouldBeTrue();
25-
query.GetPolicies().Single().ShouldBe("ClassPolicy");
25+
query.GetPolicies()!.Single().ShouldBe("ClassPolicy");
2626

2727
var field = query.Fields.Single(x => x.Name == "post");
2828
field.RequiresAuthorization().ShouldBeTrue();
29-
field.GetPolicies().Single().ShouldBe("FieldPolicy");
29+
field.GetPolicies()!.Single().ShouldBe("FieldPolicy");
3030
}
3131

3232
[GraphQLMetadata("Query")]

src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using GraphQL.Types;
44
using GraphQL.Types.Relay.DataObjects;
5+
using Shouldly;
56
using Xunit;
67

78
namespace GraphQL.Authorization.Tests
@@ -246,6 +247,30 @@ public void passes_with_claim_on_variable_type()
246247
});
247248
}
248249

250+
[Fact]
251+
public void passes_with_claim_on_variable_type_without_inputs_but_fails_later_either()
252+
{
253+
Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));
254+
255+
ShouldFailRule(config =>
256+
{
257+
config.ValidateResult = result =>
258+
{
259+
// no auth error on null inputs, only INVALID_VALUE
260+
result.Errors.Count.ShouldBe(1);
261+
result.Errors[0].Code.ShouldBe("INVALID_VALUE");
262+
result.Errors[0].Message.ShouldBe("Variable '$input' is invalid. No value provided for a non-null variable.");
263+
};
264+
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
265+
config.Schema = TypedSchema();
266+
config.Inputs = null;
267+
config.User = CreatePrincipal(claims: new Dictionary<string, string>
268+
{
269+
{ "Admin", "true" }
270+
});
271+
});
272+
}
273+
249274
[Fact]
250275
public void fails_on_missing_claim_on_variable_type()
251276
{
@@ -340,19 +365,19 @@ type Post {
340365
public class NestedQueryWithAttributes
341366
{
342367
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "test")]
343-
public Post Post(string id) => null;
368+
public Post? Post(string id) => null;
344369

345-
public IEnumerable<Post> Posts() => null;
370+
public IEnumerable<Post>? Posts() => null;
346371

347-
public IEnumerable<Post> PostsNonNull() => null;
372+
public IEnumerable<Post>? PostsNonNull() => null;
348373

349-
public string Comment() => null;
374+
public string? Comment() => null;
350375
}
351376

352377
[GraphQLAuthorize("PostPolicy")]
353378
public class Post
354379
{
355-
public string Id { get; set; }
380+
public string? Id { get; set; }
356381
}
357382

358383
public class PostGraphType : ObjectGraphType<Post>
@@ -365,11 +390,11 @@ public PostGraphType()
365390

366391
public class Article
367392
{
368-
public string Id { get; set; }
393+
public string? Id { get; set; }
369394

370-
public string Author { get; set; }
395+
public string? Author { get; set; }
371396

372-
public string Content { get; set; }
397+
public string? Content { get; set; }
373398
}
374399

375400
public class ArticleGraphType : ObjectGraphType<Article>
@@ -384,7 +409,7 @@ public ArticleGraphType()
384409

385410
public class Author
386411
{
387-
public string Name { get; set; }
412+
public string? Name { get; set; }
388413
}
389414

390415
private static ISchema TypedSchema()

src/GraphQL.Authorization.Tests/GraphQLUserContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
namespace GraphQL.Authorization.Tests
55
{
6-
internal class GraphQLUserContext : Dictionary<string, object>, IProvideClaimsPrincipal
6+
internal class GraphQLUserContext : Dictionary<string, object?>, IProvideClaimsPrincipal
77
{
8-
public ClaimsPrincipal User { get; set; }
8+
public ClaimsPrincipal? User { get; set; }
99
}
1010
}

src/GraphQL.Authorization.Tests/ValidationTestBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private static IValidationResult Validate(ValidationTestConfig config)
6666
return validator.ValidateAsync(config.Schema, document, document.Operations.First().Variables, config.Rules, userContext, config.Inputs, config.OperationName).GetAwaiter().GetResult().validationResult;
6767
}
6868

69-
internal static ClaimsPrincipal CreatePrincipal(string authenticationType = null, IDictionary<string, string> claims = null)
69+
internal static ClaimsPrincipal CreatePrincipal(string? authenticationType = null, IDictionary<string, string>? claims = null)
7070
{
7171
var claimsList = new List<Claim>();
7272

src/GraphQL.Authorization.Tests/ValidationTestConfig.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ namespace GraphQL.Authorization.Tests
88
{
99
public class ValidationTestConfig
1010
{
11-
public string OperationName { get; set; }
11+
public string OperationName { get; set; } = null!;
1212

13-
public string Query { get; set; }
13+
public string Query { get; set; } = null!;
1414

15-
public ISchema Schema { get; set; }
15+
public ISchema Schema { get; set; } = null!;
1616

1717
public List<IValidationRule> Rules { get; set; } = new List<IValidationRule>();
1818

19-
public ClaimsPrincipal User { get; set; }
19+
public ClaimsPrincipal? User { get; set; }
2020

21-
public Inputs Inputs { get; set; }
21+
public Inputs? Inputs { get; set; }
2222

2323
public Action<IValidationResult> ValidateResult = _ => { };
2424
}

src/GraphQL.Authorization/AuthorizationContext.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ namespace GraphQL.Authorization
99
/// </summary>
1010
public class AuthorizationContext
1111
{
12-
private List<string> _errors;
12+
private List<string>? _errors;
1313

1414
/// <summary>
1515
/// Current user.
1616
/// </summary>
17-
public ClaimsPrincipal User { get; set; }
17+
public ClaimsPrincipal? User { get; set; }
1818

1919
/// <summary>
2020
/// Arbitrary user defined context represented as dictionary.
2121
/// </summary>
22-
public IDictionary<string, object> UserContext { get; set; }
22+
public IDictionary<string, object?>? UserContext { get; set; }
2323

2424
/// <summary>
2525
/// Represents a readonly dictionary of variable inputs to an executed document.
2626
/// </summary>
27-
public IReadOnlyDictionary<string, object> Inputs { get; set; }
27+
public IReadOnlyDictionary<string, object>? Inputs { get; set; }
2828

2929
/// <summary>
3030
/// Returns a set of authorization errors.

src/GraphQL.Authorization/AuthorizationEvaluator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ public AuthorizationEvaluator(AuthorizationSettings settings)
2222

2323
/// <inheritdoc />
2424
public async Task<AuthorizationResult> Evaluate(
25-
ClaimsPrincipal principal,
26-
IDictionary<string, object> userContext,
27-
IReadOnlyDictionary<string, object> inputs,
28-
IEnumerable<string> requiredPolicies)
25+
ClaimsPrincipal? principal,
26+
IDictionary<string, object?>? userContext,
27+
IReadOnlyDictionary<string, object>? inputs,
28+
IEnumerable<string>? requiredPolicies)
2929
{
3030
if (requiredPolicies == null)
3131
return AuthorizationResult.Success();

0 commit comments

Comments
 (0)