-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #219 from dolittle:authorization
authorization
- Loading branch information
Showing
12 changed files
with
309 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Authorization | ||
|
||
Authorization is done by leveraging the [ASP.NET `[Authorize]`](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-5.0) | ||
attribute. [Hot Chocolate GraphQL](https://chillicream.com/docs/hotchocolate/v10/server/#supported-core-components) is automatically hooked up for this. | ||
|
||
## Configuration | ||
|
||
With the ASP.NET Core policy system, you simply configure authorization and adds your policies: | ||
|
||
```csharp | ||
|
||
public class Startup | ||
{ | ||
public void ConfigureService(IServiceCollection services) | ||
{ | ||
services.AddAuthorization(options => options | ||
.AddPolicy("MyPolicy", policy => policy.RequireClaim("Admin"))); | ||
|
||
services.AddVanir(); | ||
} | ||
} | ||
``` | ||
|
||
## Mutations / Queries | ||
|
||
Once you have it configured, you can simply start leveraging the `[Authorize]` attribute and reference the required | ||
policy or policies. This can be done either on a class level and then automatically apply to all mutations or queries within | ||
the class, or you can set it specifically for the methods. | ||
|
||
> Note: If you add an authorization policy on a class level, any method policies will be in addition to the class level one. | ||
Class level: | ||
|
||
```csharp | ||
using Microsoft.AspNetCore.Authorization; | ||
using Dolittle.Vanir.Backend.GraphQL; | ||
|
||
[Authorize(Policy = "MyPolicy")] | ||
public class MyMutations : GraphController | ||
{ | ||
[Mutation] | ||
public async Task<bool> DoSomething() | ||
{ | ||
|
||
} | ||
} | ||
``` | ||
|
||
Method level: | ||
|
||
```csharp | ||
using Microsoft.AspNetCore.Authorization; | ||
using Dolittle.Vanir.Backend.GraphQL; | ||
|
||
public class MyMutations : GraphController | ||
{ | ||
[Mutation] | ||
[Authorize(Policy = "MyPolicy")] | ||
public async Task<bool> DoSomething() | ||
{ | ||
|
||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
Source/DotNET/Backend.Specs/GraphQL/for_SchemaRoute/given/an_empty_schema_route.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) Dolittle. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Reflection; | ||
using Dolittle.Vanir.Backend.GraphQL; | ||
using HotChocolate; | ||
using HotChocolate.Types; | ||
using Machine.Specifications; | ||
using Moq; | ||
using static Moq.It; | ||
|
||
namespace Dolittle.Vanir.Backend.Specs.GraphQL.for_SchemaRoute.given | ||
{ | ||
public class an_empty_schema_route | ||
{ | ||
protected static string path = "SomePath"; | ||
protected static string local_name = "LocalName"; | ||
protected static string type_name = "TypeName"; | ||
protected static SchemaRoute route; | ||
protected static Mock<IObjectTypeDescriptor> object_type_descriptor; | ||
protected static Mock<IObjectFieldDescriptor> object_field_descriptor; | ||
|
||
static MethodInfo configure_method; | ||
|
||
Establish context = () => | ||
{ | ||
route = new SchemaRoute(path, local_name, type_name); | ||
configure_method = typeof(SchemaRoute).GetMethod("Configure", BindingFlags.Instance | BindingFlags.NonPublic); | ||
object_type_descriptor = new(); | ||
object_field_descriptor = new(); | ||
object_type_descriptor.Setup(_ => _.Field(IsAny<NameString>())).Returns(object_field_descriptor.Object); | ||
object_type_descriptor.Setup(_ => _.Field(IsAny<MethodInfo>())).Returns(object_field_descriptor.Object); | ||
object_field_descriptor.Setup(_ => _.Type(IsAny<SchemaRoute>())).Returns(object_field_descriptor.Object); | ||
object_field_descriptor.Setup(_ => _.Name(IsAny<NameString>())).Returns(object_field_descriptor.Object); | ||
}; | ||
|
||
protected static void Configure(IObjectTypeDescriptor descriptor = default) | ||
{ | ||
if (descriptor == default) descriptor = object_type_descriptor.Object; | ||
configure_method.Invoke(route, new[] { descriptor }); | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...e/DotNET/Backend.Specs/GraphQL/for_SchemaRoute/when_configuring/and_there_are_children.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright (c) Dolittle. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using Dolittle.Vanir.Backend.GraphQL; | ||
using Machine.Specifications; | ||
using static Moq.Times; | ||
|
||
namespace Dolittle.Vanir.Backend.Specs.GraphQL.for_SchemaRoute.when_configuring | ||
{ | ||
public class and_there_are_children : given.an_empty_schema_route | ||
{ | ||
static SchemaRoute first_child; | ||
static SchemaRoute second_child; | ||
|
||
Establish context = () => | ||
{ | ||
first_child = new SchemaRoute("FirstChildPath", "FirstChildLocalName", "FirstChildTypeName"); | ||
second_child = new SchemaRoute("SecondChildPath", "SecondChildLocalName", "SecondChildTypeName"); | ||
route.AddChild(first_child); | ||
route.AddChild(second_child); | ||
}; | ||
Because of = () => Configure(); | ||
|
||
It should_add_a_field_for_first_child = () => object_type_descriptor.Verify(_ => _.Field(first_child.LocalName), Once()); | ||
It should_add_a_field_for_second_child = () => object_type_descriptor.Verify(_ => _.Field(second_child.LocalName), Once()); | ||
It should_set_type_for_first_child = () => object_field_descriptor.Verify(_ => _.Type(first_child), Once()); | ||
It should_set_type_for_second_child = () => object_field_descriptor.Verify(_ => _.Type(second_child), Once()); | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
Source/DotNET/Backend.Specs/GraphQL/for_SchemaRoute/when_configuring/and_there_are_items.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright (c) Dolittle. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Reflection; | ||
using Dolittle.Vanir.Backend.GraphQL; | ||
using Machine.Specifications; | ||
using static Moq.Times; | ||
|
||
namespace Dolittle.Vanir.Backend.Specs.GraphQL.for_SchemaRoute.when_configuring | ||
{ | ||
public class and_there_are_items : given.an_empty_schema_route | ||
{ | ||
class ClassWithMethods | ||
{ | ||
public void FirstMethod() { } | ||
public void SecondMethod() { } | ||
} | ||
|
||
static SchemaRouteItem first_item; | ||
static SchemaRouteItem second_item; | ||
|
||
Establish context = () => | ||
{ | ||
var methods = typeof(ClassWithMethods).GetMethods(BindingFlags.Instance|BindingFlags.Public); | ||
first_item = new SchemaRouteItem(methods[0], "FirstItem"); | ||
route.AddItem(first_item); | ||
second_item = new SchemaRouteItem(methods[1], "SecondItem"); | ||
route.AddItem(second_item); | ||
}; | ||
|
||
Because of = () => Configure(); | ||
|
||
It should_add_field_for_first_method = () => object_type_descriptor.Verify(_ => _.Field(first_item.Method), Once()); | ||
It should_add_field_for_second_method = () => object_type_descriptor.Verify(_ => _.Field(second_item.Method), Once()); | ||
It should_set_name_for_first_method = () => object_field_descriptor.Verify(_ => _.Name(first_item.Name), Once()); | ||
It should_set_name_for_second_method = () => object_field_descriptor.Verify(_ => _.Name(second_item.Name), Once()); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
...hemaRoute/when_configuring/and_there_are_items_with_authorization_on_class_and_methods.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) Dolittle. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Reflection; | ||
using Dolittle.Vanir.Backend.GraphQL; | ||
using HotChocolate; | ||
using HotChocolate.AspNetCore.Authorization; | ||
using HotChocolate.Types; | ||
using Machine.Specifications; | ||
using Moq; | ||
using static Moq.It; | ||
using static Moq.Times; | ||
using AuthorizeAttribute = Microsoft.AspNetCore.Authorization.AuthorizeAttribute; | ||
using It = Machine.Specifications.It; | ||
|
||
namespace Dolittle.Vanir.Backend.Specs.GraphQL.for_SchemaRoute.when_configuring | ||
{ | ||
public class and_there_are_items_with_authorization_on_class_and_methods : given.an_empty_schema_route | ||
{ | ||
[Authorize(Policy = ClassPolicy)] | ||
class ClassWithMethods | ||
{ | ||
public const string ClassPolicy = "ClassPolicy"; | ||
public const string FirstMethodPolicy = "FirstMethodPolicy"; | ||
public const string SecondMethodPolicy = "SecondMethodPolicy"; | ||
|
||
[Authorize(Policy = FirstMethodPolicy)] | ||
public void FirstMethod() { } | ||
|
||
[Authorize(Policy = SecondMethodPolicy)] | ||
public void SecondMethod() { } | ||
} | ||
|
||
static SchemaRouteItem first_item; | ||
static SchemaRouteItem second_item; | ||
|
||
static Mock<IObjectFieldDescriptor> first_method_descriptor; | ||
static Mock<IObjectFieldDescriptor> second_method_descriptor; | ||
|
||
Establish context = () => | ||
{ | ||
var methods = typeof(ClassWithMethods).GetMethods(BindingFlags.Instance | BindingFlags.Public); | ||
first_item = new SchemaRouteItem(methods[0], "FirstItem"); | ||
route.AddItem(first_item); | ||
second_item = new SchemaRouteItem(methods[1], "SecondItem"); | ||
route.AddItem(second_item); | ||
first_method_descriptor = new(); | ||
first_method_descriptor.Setup(_ => _.Type(IsAny<SchemaRoute>())).Returns(first_method_descriptor.Object); | ||
first_method_descriptor.Setup(_ => _.Name(IsAny<NameString>())).Returns(first_method_descriptor.Object); | ||
second_method_descriptor = new(); | ||
second_method_descriptor.Setup(_ => _.Type(IsAny<SchemaRoute>())).Returns(second_method_descriptor.Object); | ||
second_method_descriptor.Setup(_ => _.Name(IsAny<NameString>())).Returns(second_method_descriptor.Object); | ||
object_type_descriptor.Setup(_ => _.Field(first_item.Method)).Returns(first_method_descriptor.Object); | ||
object_type_descriptor.Setup(_ => _.Field(second_item.Method)).Returns(second_method_descriptor.Object); | ||
object_type_descriptor.Setup(_ => _.Directive(IsAny<AuthorizeDirective>())).Returns(object_type_descriptor.Object); | ||
}; | ||
|
||
Because of = () => Configure(); | ||
|
||
It should_set_method_authorization_for_first_method = () => first_method_descriptor.Verify(_ => _.Directive(Is<AuthorizeDirective>(a => a.Policy == ClassWithMethods.FirstMethodPolicy)), Once()); | ||
It should_set_method_authorization_for_second_method = () => second_method_descriptor.Verify(_ => _.Directive(Is<AuthorizeDirective>(a => a.Policy == ClassWithMethods.SecondMethodPolicy)), Once()); | ||
It should_set_class_authorization_for_first_method = () => first_method_descriptor.Verify(_ => _.Directive(Is<AuthorizeDirective>(a => a.Policy == ClassWithMethods.ClassPolicy)), Once()); | ||
It should_set_class_authorization_for_second_method = () => second_method_descriptor.Verify(_ => _.Directive(Is<AuthorizeDirective>(a => a.Policy == ClassWithMethods.ClassPolicy)), Once()); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
....Specs/GraphQL/for_SchemaRoute/when_configuring/and_there_are_no_children_and_no_items.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) Dolittle. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using Machine.Specifications; | ||
using static Moq.Times; | ||
|
||
namespace Dolittle.Vanir.Backend.Specs.GraphQL.for_SchemaRoute.when_configuring | ||
{ | ||
public class and_there_are_no_children_and_no_items : given.an_empty_schema_route | ||
{ | ||
Because of = () => Configure(); | ||
|
||
It should_set_name_on_descriptor = () => object_type_descriptor.Verify(_ => _.Name(type_name), Once()); | ||
It should_add_a_default_field = () => object_type_descriptor.Verify(_ => _.Field("Default"), Once()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters