73 lines
3.3 KiB
C#
73 lines
3.3 KiB
C#
namespace Application.Students.Commands;
|
|
|
|
using Application.Common;
|
|
using Domain.Ports.Repositories;
|
|
using FluentValidation;
|
|
|
|
/// <summary>
|
|
/// Validator for <see cref="CreateStudentCommand"/>.
|
|
/// Validates name format, email uniqueness, and prevents XSS attacks.
|
|
/// </summary>
|
|
public class CreateStudentValidator : AbstractValidator<CreateStudentCommand>
|
|
{
|
|
public CreateStudentValidator(IStudentRepository studentRepository)
|
|
{
|
|
RuleFor(x => x.Name)
|
|
.NotEmpty().WithMessage("Name is required")
|
|
.MinimumLength(ValidationPatterns.MinNameLength)
|
|
.WithMessage($"Name must be at least {ValidationPatterns.MinNameLength} characters")
|
|
.MaximumLength(ValidationPatterns.MaxNameLength)
|
|
.WithMessage($"Name must not exceed {ValidationPatterns.MaxNameLength} characters")
|
|
.Matches(ValidationPatterns.SafeNamePattern())
|
|
.WithMessage("Name contains invalid characters")
|
|
.Must(ValidationPatterns.IsSafeContent)
|
|
.WithMessage("Name contains prohibited content");
|
|
|
|
RuleFor(x => x.Email)
|
|
.NotEmpty().WithMessage("Email is required")
|
|
.MaximumLength(ValidationPatterns.MaxEmailLength)
|
|
.WithMessage($"Email must not exceed {ValidationPatterns.MaxEmailLength} characters")
|
|
.EmailAddress().WithMessage("Invalid email format")
|
|
.Must(ValidationPatterns.IsSafeContent)
|
|
.WithMessage("Email contains prohibited content")
|
|
.MustAsync(async (email, ct) =>
|
|
!await studentRepository.EmailExistsAsync(email, null, ct))
|
|
.WithMessage("Email already exists");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validator for <see cref="UpdateStudentCommand"/>.
|
|
/// Validates name format, email uniqueness (excluding current student), and prevents XSS attacks.
|
|
/// </summary>
|
|
public class UpdateStudentValidator : AbstractValidator<UpdateStudentCommand>
|
|
{
|
|
public UpdateStudentValidator(IStudentRepository studentRepository)
|
|
{
|
|
RuleFor(x => x.Id)
|
|
.GreaterThan(0).WithMessage(ValidationPatterns.InvalidIdMessage);
|
|
|
|
RuleFor(x => x.Name)
|
|
.NotEmpty().WithMessage("Name is required")
|
|
.MinimumLength(ValidationPatterns.MinNameLength)
|
|
.WithMessage($"Name must be at least {ValidationPatterns.MinNameLength} characters")
|
|
.MaximumLength(ValidationPatterns.MaxNameLength)
|
|
.WithMessage($"Name must not exceed {ValidationPatterns.MaxNameLength} characters")
|
|
.Matches(ValidationPatterns.SafeNamePattern())
|
|
.WithMessage("Name contains invalid characters")
|
|
.Must(ValidationPatterns.IsSafeContent)
|
|
.WithMessage("Name contains prohibited content");
|
|
|
|
RuleFor(x => x.Email)
|
|
.NotEmpty().WithMessage("Email is required")
|
|
.MaximumLength(ValidationPatterns.MaxEmailLength)
|
|
.WithMessage($"Email must not exceed {ValidationPatterns.MaxEmailLength} characters")
|
|
.EmailAddress().WithMessage("Invalid email format")
|
|
.Must(ValidationPatterns.IsSafeContent)
|
|
.WithMessage("Email contains prohibited content")
|
|
.MustAsync(async (command, email, ct) =>
|
|
!await studentRepository.EmailExistsAsync(email, command.Id, ct))
|
|
.WithMessage("Email already exists");
|
|
}
|
|
}
|