This repository has been archived by the owner on Jul 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5ba9704
commit b91df29
Showing
15 changed files
with
359 additions
and
10 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
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
28 changes: 28 additions & 0 deletions
28
src/PipelineRD.Validation.Tests/PipelineRD.Validation.Tests.csproj
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,28 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="Xunit.DependencyInjection" Version="7.6.0" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="coverlet.collector" Version="3.0.3"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\PipelineRD.Validation\PipelineRD.Validation.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
38 changes: 38 additions & 0 deletions
38
src/PipelineRD.Validation.Tests/PipelineRDBuilderExtensionsTests.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 @@ | ||
using FluentValidation; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
using PipelineRD.Cache; | ||
using PipelineRD.Extensions; | ||
|
||
using System.Linq; | ||
|
||
using Xunit; | ||
|
||
namespace PipelineRD.Validation.Tests | ||
{ | ||
public class PipelineRDBuilderExtensionsTests | ||
{ | ||
[Fact] | ||
public void Should_UsePipelineRD_AddPipelineServices_And_Check_If_IValidatorRequest_Is_Singleton() | ||
{ | ||
var services = new ServiceCollection(); | ||
|
||
services.UsePipelineRD(x => | ||
{ | ||
x.SetupCache(new PipelineRDCacheSettings()); | ||
x.SetupPipelineServices(x => x.InjectRequestValidators()); | ||
}); | ||
|
||
var provider = services.BuildServiceProvider(); | ||
|
||
var service = services.FirstOrDefault(x => x.ServiceType == typeof(IValidator<PipelineRDRequestTest>)); | ||
|
||
Assert.NotNull(service); | ||
Assert.Equal(ServiceLifetime.Singleton, service.Lifetime); | ||
} | ||
|
||
class PipelineRDRequestTest { } | ||
|
||
class PipelineRDRequestTestValidator : AbstractValidator<PipelineRDRequestTest> { } | ||
} | ||
} |
106 changes: 106 additions & 0 deletions
106
src/PipelineRD.Validation.Tests/PipelineRDExtensionsTests.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,106 @@ | ||
using FluentValidation; | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using Xunit; | ||
using System.Net; | ||
|
||
namespace PipelineRD.Validation.Tests | ||
{ | ||
public class PipelineRDExtensionsTests | ||
{ | ||
private readonly IServiceProvider _serviceProvider; | ||
|
||
public PipelineRDExtensionsTests(IServiceProvider serviceProvider) | ||
{ | ||
_serviceProvider = serviceProvider; | ||
} | ||
|
||
[Fact] | ||
public async Task Should_Pipeline_Validate_Request() | ||
{ | ||
var request = new SampleRequest() { ValidModel = false }; | ||
var pipeline = _serviceProvider.GetService<IPipeline<ContextSample, SampleRequest>>(); | ||
pipeline.WithHandler<FirstSampleStep>(); | ||
pipeline.WithHandler<SecondSampleStep>(); | ||
pipeline.WithHandler<ThirdSampleStep>(); | ||
|
||
var result = await pipeline.ExecuteWithValidation(request); | ||
|
||
Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); | ||
Assert.Single(result.Errors); | ||
} | ||
|
||
[Fact] | ||
public async Task Should_Pipeline_Validate_Request_Using_Validator_Implementation() | ||
{ | ||
var request = new SampleRequest() { ValidModel = false }; | ||
var pipeline = _serviceProvider.GetService<IPipeline<ContextSample, SampleRequest>>(); | ||
var validator = new SampleRequestValidator(); | ||
pipeline.WithHandler<FirstSampleStep>(); | ||
pipeline.WithHandler<SecondSampleStep>(); | ||
pipeline.WithHandler<ThirdSampleStep>(); | ||
|
||
var result = await pipeline.ExecuteWithValidation(request, validator); | ||
|
||
Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); | ||
Assert.Single(result.Errors); | ||
} | ||
} | ||
|
||
public class SampleRequest | ||
{ | ||
public Guid Guid { get; set; } = Guid.NewGuid(); | ||
|
||
public bool ValidFirst { get; set; } = true; | ||
public bool ValidSecond { get; set; } = true; | ||
|
||
public bool ValidModel { get; set; } | ||
} | ||
|
||
public class ContextSample : BaseContext | ||
{ | ||
public bool ValidFirst { get; set; } = true; | ||
|
||
public ContextSample() | ||
{ | ||
} | ||
} | ||
|
||
public class SampleRequestValidator : AbstractValidator<SampleRequest> | ||
{ | ||
public SampleRequestValidator() | ||
{ | ||
RuleFor(x => x.ValidModel) | ||
.Equal(true); | ||
} | ||
} | ||
|
||
public class FirstSampleStep : Handler<ContextSample, SampleRequest> | ||
{ | ||
public override Task<HandlerResult> Handle(SampleRequest request) | ||
{ | ||
return Proceed(); | ||
} | ||
} | ||
|
||
public class SecondSampleStep : Handler<ContextSample, SampleRequest> | ||
{ | ||
public override Task<HandlerResult> Handle(SampleRequest request) | ||
{ | ||
return Proceed(); | ||
} | ||
} | ||
|
||
public class ThirdSampleStep : Handler<ContextSample, SampleRequest> | ||
{ | ||
public override Task<HandlerResult> Handle(SampleRequest request) | ||
{ | ||
return this.Finish(200); | ||
} | ||
} | ||
} |
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,22 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using PipelineRD.Cache; | ||
using PipelineRD.Extensions; | ||
|
||
namespace PipelineRD.Validation.Tests | ||
{ | ||
class Startup | ||
{ | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.UsePipelineRD(x => | ||
{ | ||
x.SetupCache(new PipelineRDCacheSettings()); | ||
x.SetupPipelineServices(x => | ||
{ | ||
x.InjectAll(); | ||
x.InjectRequestValidators(); | ||
}); | ||
}); | ||
} | ||
} | ||
} |
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,63 @@ | ||
using FluentValidation; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using System.Linq; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
|
||
namespace PipelineRD.Validation | ||
{ | ||
|
||
public static class PipelineExtensions | ||
{ | ||
/// <summary> | ||
/// Execute the pipeline with a fail-fast validation for the request model using the fluent validation package. | ||
/// The second parameter is an optional validator that will be used if passed it. If not, it will try to get one from the DI container. | ||
/// </summary> | ||
/// <param name="request">A model that holds the data from the request.</param> | ||
/// <param name="validator">An optional validator that will be used if passed it. If not, it will try to get one from the DI container.</param> | ||
/// <returns>The result from the pipeline.</returns> | ||
public static async Task<HandlerResult> ExecuteWithValidation<TContext, TRequest>( | ||
this IPipeline<TContext, TRequest> pipeline, | ||
TRequest request, | ||
IValidator validator = null, | ||
HttpStatusCode defaultValidationFailStatus = HttpStatusCode.BadRequest) | ||
where TContext : BaseContext | ||
{ | ||
// Make sure that we execute the validation when | ||
// it is not the PipelineDiagram | ||
if (pipeline.GetType() == typeof(Pipeline<TContext, TRequest>)) | ||
{ | ||
if (validator == null) | ||
{ | ||
var injectedValidator = pipeline.ServiceProvider.GetService<IValidator<TRequest>>(); | ||
validator = injectedValidator ?? throw new PipelineException($"There is no validator injected in DI for this request type({request.GetType().Name}). Please pass a validator to the method 'ExecuteWithValidation' or inject it."); | ||
} | ||
|
||
if (validator != null) | ||
{ | ||
var validationContext = new ValidationContext<TRequest>(request); | ||
var validateResult = validator.Validate(validationContext); | ||
|
||
if (!validateResult.IsValid) | ||
{ | ||
var errors = validateResult.Errors | ||
.Select(p => new HandlerError() | ||
{ | ||
Message = p.ErrorMessage, | ||
Source = p.PropertyName | ||
}) | ||
.ToList(); | ||
|
||
return HandlerResultBuilder.CreateDefault() | ||
.WithErrors(errors) | ||
.WithStatusCode(defaultValidationFailStatus); | ||
} | ||
} | ||
} | ||
|
||
return await pipeline.Execute(request); | ||
} | ||
} | ||
} |
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 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Library</OutputType> | ||
<TargetFramework>net6</TargetFramework> | ||
<PackageId>PipelineRD.Validation</PackageId> | ||
<Authors>Eduardo Cabral</Authors> | ||
<PackageDescription>The complementary validation package for PipelineRD. It uses Fluent Validation to do it.</PackageDescription> | ||
<RepositoryUrl>https://github.com/eduardosbcabral/pipelineRD-validation</RepositoryUrl> | ||
<LangVersion>latest</LangVersion> | ||
<PackageIconUrl>https://user-images.githubusercontent.com/29133996/134798452-de38b1d7-4a8a-4410-b60b-1814b7339a18.png</PackageIconUrl> | ||
|
||
<Summary>The complementary validation package for PipelineRD. It uses Fluent Validation to do it.</Summary> | ||
<Description>The complementary validation package for PipelineRD. It uses Fluent Validation to do it.</Description> | ||
<PackageId>PipelineRD.Validation</PackageId> | ||
<PackageIcon>icon.png</PackageIcon> | ||
<PackageReadmeFile>README.md</PackageReadmeFile> | ||
<Authors>Eduardo Cabral</Authors> | ||
<RepositoryUrl>https://github.com/eduardosbcabral/pipelineRD-validation</RepositoryUrl> | ||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||
<IsPackable>true</IsPackable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="FluentValidation" Version="9.5.4" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\PipelineRD\PipelineRD.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Include="..\..\icon.png" Pack="true" PackagePath="" Visible="False" /> | ||
<None Include="..\..\README.md" Pack="true" PackagePath="" Visible="False" /> | ||
</ItemGroup> | ||
</Project> |
27 changes: 27 additions & 0 deletions
27
src/PipelineRD.Validation/PipelinesServicesBuilderExtensions.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,27 @@ | ||
using FluentValidation; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
using PipelineRD.Extensions.Builders; | ||
using System.Linq; | ||
|
||
namespace PipelineRD.Validation | ||
{ | ||
public static class PipelinesServicesBuilderExtensions | ||
{ | ||
public static void InjectRequestValidators(this IPipelineServicesBuilder builder) | ||
{ | ||
var validators = from type in builder.Types | ||
where !type.IsAbstract && !type.IsGenericTypeDefinition | ||
let interfaces = type.GetInterfaces() | ||
let genericInterfaces = interfaces.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IValidator<>)) | ||
let matchingInterface = genericInterfaces.FirstOrDefault() | ||
where matchingInterface != null | ||
select new { Interface = matchingInterface, Type = type }; | ||
|
||
foreach (var validator in validators) | ||
{ | ||
builder.Services.AddSingleton(validator.Interface, validator.Type); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.