validators

This commit is contained in:
2026-05-28 21:53:46 +02:00
parent 2f7f996faf
commit 76b5c0b49d
12 changed files with 172 additions and 3 deletions
+3 -1
View File
@@ -3,6 +3,7 @@ using Musify.Application.PlayLists.Commands;
using Musify.Application.PlayLists.Queries;
using WebApi.DataTransferObjects.PlayLists;
using WebApi.Extensions;
using WebApi.Filters;
namespace WebApi.Endpoints;
@@ -11,7 +12,8 @@ public static class PlayListEndpoints
public static IEndpointRouteBuilder MapPlayListEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/playlists")
.WithTags("PlayLists");
.WithTags("PlayLists")
.AddEndpointFilter<ValidationFilter>();
group.MapGet("/", GetPlayLists)
.WithName("GetPlayLists")
+3 -1
View File
@@ -3,6 +3,7 @@ using Musify.Application.Tracks.Commands;
using Musify.Application.Tracks.Queries;
using WebApi.DataTransferObjects.Tracks;
using WebApi.Extensions;
using WebApi.Filters;
namespace WebApi.Endpoints;
@@ -11,7 +12,8 @@ public static class TrackEndpoints
public static IEndpointRouteBuilder MapTrackEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/tracks")
.WithTags("Tracks");
.WithTags("Tracks")
.AddEndpointFilter<ValidationFilter>();
group.MapGet("/", GetTracks)
.WithName("GetTracks")
+3 -1
View File
@@ -3,6 +3,7 @@ using Musify.Application.Users.Commands;
using Musify.Application.Users.Queries;
using WebApi.DataTransferObjects.Users;
using WebApi.Extensions;
using WebApi.Filters;
namespace WebApi.Endpoints;
@@ -11,7 +12,8 @@ public static class UserEndpoints
public static IEndpointRouteBuilder MapUserEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/users")
.WithTags("Users");
.WithTags("Users")
.AddEndpointFilter<ValidationFilter>();
group.MapGet("/", GetUsers)
.WithName("GetUsers")
@@ -1,3 +1,4 @@
using FluentValidation;
using Mediator;
using Musify.Application;
using Musify.Infrastructure.MassTransit;
@@ -6,6 +7,7 @@ using Musify.Infrastructure.Services;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using WebApi.DataTransferObjects.PlayLists;
using WebApi.Options;
namespace WebApi.Extensions;
@@ -21,6 +23,7 @@ public static class ServiceCollectionExtensions
services.AddMassTransitClient(configuration);
services.AddMediator();
services.AddOpenApi();
services.AddValidatorsFromAssemblyContaining<CreatePlayListRequest>();
return services;
}
+28
View File
@@ -0,0 +1,28 @@
using FluentValidation;
namespace WebApi.Filters;
public sealed class ValidationFilter : IEndpointFilter
{
public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
{
foreach (var argument in context.Arguments)
{
if (argument is null)
continue;
var validatorType = typeof(IValidator<>).MakeGenericType(argument.GetType());
if (context.HttpContext.RequestServices.GetService(validatorType) is not IValidator validator)
continue;
var validationContext = new ValidationContext<object>(argument);
var result = await validator.ValidateAsync(validationContext, context.HttpContext.RequestAborted);
if (!result.IsValid)
return Results.ValidationProblem(result.ToDictionary());
}
return await next(context);
}
}
@@ -0,0 +1,18 @@
using FluentValidation;
using WebApi.DataTransferObjects.PlayLists;
namespace WebApi.Validators.PlayLists;
public sealed class CreatePlayListRequestValidator : AbstractValidator<CreatePlayListRequest>
{
public CreatePlayListRequestValidator()
{
RuleFor(x => x.Name)
.NotEmpty()
.MaximumLength(50);
RuleFor(x => x.Description)
.NotEmpty()
.MaximumLength(256);
}
}
@@ -0,0 +1,20 @@
using FluentValidation;
using WebApi.DataTransferObjects.PlayLists;
namespace WebApi.Validators.PlayLists;
public sealed class RequestPlayListPictureUploadRequestValidator : AbstractValidator<RequestPlayListPictureUploadRequest>
{
public RequestPlayListPictureUploadRequestValidator()
{
RuleFor(x => x.FileType)
.NotEmpty();
RuleFor(x => x.ContentType)
.NotEmpty();
RuleFor(x => x.ExpectedSizeBytes)
.GreaterThan(0)
.When(x => x.ExpectedSizeBytes.HasValue);
}
}
@@ -0,0 +1,18 @@
using FluentValidation;
using WebApi.DataTransferObjects.PlayLists;
namespace WebApi.Validators.PlayLists;
public sealed class UpdatePlayListRequestValidator : AbstractValidator<UpdatePlayListRequest>
{
public UpdatePlayListRequestValidator()
{
RuleFor(x => x.NewName)
.MaximumLength(50)
.When(x => x.NewName is not null);
RuleFor(x => x.NewDescription)
.MaximumLength(256)
.When(x => x.NewDescription is not null);
}
}
@@ -0,0 +1,20 @@
using FluentValidation;
using WebApi.DataTransferObjects.Tracks;
namespace WebApi.Validators.Tracks;
public sealed class CreateTrackRequestValidator : AbstractValidator<CreateTrackRequest>
{
public CreateTrackRequestValidator()
{
RuleFor(x => x.Title)
.NotEmpty()
.MaximumLength(50);
RuleFor(x => x.PictureIntentId)
.NotEmpty();
RuleFor(x => x.AudioIntentId)
.NotEmpty();
}
}
@@ -0,0 +1,30 @@
using FluentValidation;
using WebApi.DataTransferObjects.Tracks;
namespace WebApi.Validators.Tracks;
public sealed class RequestTrackUploadUrlsRequestValidator : AbstractValidator<RequestTrackUploadUrlsRequest>
{
public RequestTrackUploadUrlsRequestValidator()
{
RuleFor(x => x.PictureFileType)
.NotEmpty();
RuleFor(x => x.PictureContentType)
.NotEmpty();
RuleFor(x => x.AudioFileType)
.NotEmpty();
RuleFor(x => x.AudioContentType)
.NotEmpty();
RuleFor(x => x.ExpectedPictureSizeBytes)
.GreaterThan(0)
.When(x => x.ExpectedPictureSizeBytes.HasValue);
RuleFor(x => x.ExpectedAudioSizeBytes)
.GreaterThan(0)
.When(x => x.ExpectedAudioSizeBytes.HasValue);
}
}
@@ -0,0 +1,25 @@
using FluentValidation;
using WebApi.DataTransferObjects.Users;
namespace WebApi.Validators.Users;
public sealed class CreateUserRequestValidator : AbstractValidator<CreateUserRequest>
{
public CreateUserRequestValidator()
{
RuleFor(x => x.Id)
.NotEmpty();
RuleFor(x => x.Name)
.NotEmpty()
.MaximumLength(48);
RuleFor(x => x.FirstName)
.MaximumLength(48)
.When(x => x.FirstName is not null);
RuleFor(x => x.SecondName)
.MaximumLength(48)
.When(x => x.SecondName is not null);
}
}
+1
View File
@@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="Ardalis.Result" Version="10.1.0" />
<PackageReference Include="AWSSDK.S3" Version="4.0.23.4" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.1.1" />
<PackageReference Include="MassTransit" Version="9.1.1" />
<PackageReference Include="MassTransit.RabbitMQ" Version="9.1.1" />
<PackageReference Include="Mediator.Abstractions" Version="3.0.2" />