GQL Authorization Middleware implemented, will take care of controllers next.

This commit is contained in:
David Lebee
2021-02-04 21:00:24 -05:00
parent 45279da02b
commit 3e6c76ab18
9 changed files with 183 additions and 4 deletions
@@ -0,0 +1,46 @@
using HotChocolate;
using HotChocolate.Resolvers;
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.CQRS.Abstractions.Security;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
{
internal class MutationAuthorizationMiddleware
{
private readonly Type mutationType;
private readonly FieldDelegate _next;
public MutationAuthorizationMiddleware(Type mutationType,FieldDelegate next)
{
this.mutationType = mutationType;
_next = next;
}
public async Task InvokeAsync(IMiddlewareContext context)
{
var mutationAuthorizationService = context.Service<IServiceProvider>().GetService<ICommandAuthorizationService>();
if (mutationAuthorizationService != null)
{
var authorizationResult = await mutationAuthorizationService.IsAllowedAsync(mutationType);
if (authorizationResult != AuthorizationResult.Allowed)
{
var eb = ErrorBuilder.New()
.SetMessage(authorizationResult == AuthorizationResult.Unauthorized ? "Unauthorized" : "Forbidden")
.SetCode("AuthorizationResult")
.SetExtension("StatusCode", authorizationResult == AuthorizationResult.Unauthorized ? "401" : "403")
.SetPath(context.Path)
.AddLocation(context.Selection.SyntaxNode);
context.Result = eb.Build();
return;
}
}
await _next.Invoke(context);
}
}
}
@@ -0,0 +1,46 @@
using HotChocolate;
using HotChocolate.Resolvers;
using Microsoft.Extensions.DependencyInjection;
using PoweredSoft.CQRS.Abstractions.Security;
using System;
using System.Threading.Tasks;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
{
public class QueryAuthorizationMiddleware
{
private readonly Type queryType;
private readonly FieldDelegate _next;
public QueryAuthorizationMiddleware(Type queryType, FieldDelegate next)
{
this.queryType = queryType;
_next = next;
}
public async Task InvokeAsync(IMiddlewareContext context)
{
var queryAuthorizationService = context.Service<IServiceProvider>().GetService<IQueryAuthorizationService>();
if (queryAuthorizationService != null)
{
var authorizationResult = await queryAuthorizationService.IsAllowedAsync(queryType);
if (authorizationResult != AuthorizationResult.Allowed)
{
var eb = ErrorBuilder.New()
.SetMessage(authorizationResult == AuthorizationResult.Unauthorized ? "Unauthorized" : "Forbidden")
.SetCode("AuthorizationResult")
.SetExtension("StatusCode", authorizationResult == AuthorizationResult.Unauthorized ? "401" : "403")
.SetPath(context.Path)
.AddLocation(context.Selection.SyntaxNode);
context.Result = eb.Build();
return;
}
}
await _next.Invoke(context);
}
}
}
@@ -4,6 +4,8 @@ using HotChocolate.Types;
using PoweredSoft.CQRS.Abstractions;
using PoweredSoft.CQRS.Abstractions.Discovery;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
@@ -28,11 +30,25 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
var queryField = desc.Field(q.LowerCamelCaseName);
var typeToGet = typeof(IQueryHandler<,>).MakeGenericType(q.QueryType, q.QueryResultType);
queryField.Type(q.QueryResultType);
queryField.Use((sp, d) => new QueryAuthorizationMiddleware(q.QueryType, d));
// TODO.
// always required.
//queryField.Use((sp, d) => new QueryAuthorizationMiddleware(q.QueryType, d));
// if its a IQueryable.
if (q.QueryResultType.Namespace == "System.Linq" && q.QueryResultType.Name.Contains("IQueryable"))
{
//waiting on answer to be determined.
/*var genericArgument = q.QueryResultType.GetGenericArguments().First();
var type = new ListType(new NonNullType(new NamedTypeNode));
queryField.Type(type);
queryField.UsePaging();
*/
queryField.Type(q.QueryResultType);
}
else
{
queryField.Type(q.QueryResultType);
}
if (q.QueryType.GetProperties().Length == 0)
{