graphql fluent validation implementation with middleware.

This commit is contained in:
David Lebee
2021-02-03 20:28:56 -05:00
parent afb8b534bb
commit ffcfc60df1
19 changed files with 332 additions and 19 deletions
@@ -21,7 +21,7 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
desc.Name("Mutation");
foreach (var m in commandDiscovery.GetCommands())
{
var queryField = desc.Field(m.LowerCamelCaseName);
var mutationField = desc.Field(m.LowerCamelCaseName);
Type typeToGet;
if (m.CommandResultType == null)
@@ -30,15 +30,15 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
typeToGet = typeof(ICommandHandler<,>).MakeGenericType(m.CommandType, m.CommandResultType);
if (m.CommandResultType == null)
queryField.Type(typeof(int?));
mutationField.Type(typeof(int?));
else
queryField.Type(m.CommandResultType);
mutationField.Type(m.CommandResultType);
//queryField.Use((sp, d) => new MutationAuthorizationMiddleware(m.CommandType, d));
if (m.CommandType.GetProperties().Length == 0)
{
queryField.Resolve(async ctx =>
mutationField.Resolve(async ctx =>
{
var queryArgument = Activator.CreateInstance(m.CommandType);
return await HandleMutation(m.CommandResultType != null, ctx, typeToGet, queryArgument);
@@ -47,21 +47,16 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
continue;
}
queryField.Argument("params", t => t.Type(m.CommandType));
mutationField.Argument("params", t => t.Type(m.CommandType));
queryField.Resolve(async ctx =>
mutationField.Resolve(async ctx =>
{
var queryArgument = ctx.ArgumentValue<object>("params");
return await HandleMutation(m.CommandResultType != null, ctx, typeToGet, queryArgument);
});
// TODO.
//if (m.MutationObjectRequired)
// queryField.Use<MutationParamRequiredMiddleware>();
// TODO.
//if (m.ValidateMutationObject)
// queryField.Use<MutationValidationMiddleware>();
mutationField.Use<MutationParamRequiredMiddleware>();
mutationField.Use<MutationValidationMiddleware>();
}
}
@@ -0,0 +1,37 @@
using HotChocolate;
using HotChocolate.Resolvers;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
{
public class MutationParamRequiredMiddleware
{
private readonly FieldDelegate _next;
public MutationParamRequiredMiddleware(FieldDelegate next)
{
_next = next;
}
public async Task InvokeAsync(IMiddlewareContext context)
{
var queryArgument = context.ArgumentValue<object>("params");
if (queryArgument == null)
{
context.Result = ErrorBuilder.New()
.SetMessage("mutation argument is required")
.SetCode("400")
.SetPath(context.Path)
.AddLocation(context.Selection.SyntaxNode)
.Build();
return;
}
await _next.Invoke(context);
}
}
}
@@ -0,0 +1,47 @@
using HotChocolate;
using HotChocolate.Resolvers;
using PoweredSoft.CQRS.GraphQL.Abstractions;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
{
public class MutationValidationMiddleware
{
private readonly FieldDelegate _next;
public MutationValidationMiddleware(FieldDelegate next)
{
_next = next;
}
public async Task InvokeAsync(IMiddlewareContext context)
{
var queryArgument = context.ArgumentValue<object>("params");
if (queryArgument != null)
{
var service = context.Service<IGraphQLValidationService>();
var result = await service.ValidateObjectAsync(queryArgument, context.RequestAborted);
if (!result.IsValid)
{
var eb = ErrorBuilder.New()
.SetMessage("There are some validations errors")
.SetCode("ValidationError")
.SetPath(context.Path)
.AddLocation(context.Selection.SyntaxNode);
foreach (var error in result.Errors)
eb.SetExtension(error.Field, error.Errors);
context.Result = eb.Build();
return;
}
}
await _next.Invoke(context);
}
}
}
@@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\PoweredSoft.CQRS.Abstractions\PoweredSoft.CQRS.Abstractions.csproj" />
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.Abstractions\PoweredSoft.CQRS.GraphQL.Abstractions.csproj" />
</ItemGroup>
</Project>
@@ -57,10 +57,7 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
if (q.QueryObjectRequired)
queryField.Use<QueryParamRequiredMiddleware>();*/
/* TODO
if (q.ValidateQueryObject)
queryField.Use<QueryValidationMiddleware>();
*/
queryField.Use<QueryValidationMiddleware>();
}
}
@@ -0,0 +1,47 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HotChocolate;
using HotChocolate.Resolvers;
using Newtonsoft.Json;
using PoweredSoft.CQRS.GraphQL.Abstractions;
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
{
public class QueryValidationMiddleware
{
private readonly FieldDelegate _next;
public QueryValidationMiddleware(FieldDelegate next)
{
_next = next;
}
public async Task InvokeAsync(IMiddlewareContext context)
{
var queryArgument = context.ArgumentValue<object>("params");
if (queryArgument != null)
{
var service = context.Service<IGraphQLValidationService>();
var result = await service.ValidateObjectAsync(queryArgument, context.RequestAborted);
if (!result.IsValid)
{
var eb = ErrorBuilder.New()
.SetMessage("There are some validations errors")
.SetCode("ValidationError")
.SetPath(context.Path)
.AddLocation(context.Selection.SyntaxNode);
foreach (var error in result.Errors)
eb.SetExtension(error.Field, error.Errors);
context.Result = eb.Build();
return;
}
}
await _next.Invoke(context);
}
}
}