namespace Application.Students.Commands; using Application.Common; using Domain.Ports.Repositories; using FluentValidation; /// /// Validator for . /// Validates name format, email uniqueness, and prevents XSS attacks. /// public class CreateStudentValidator : AbstractValidator { 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"); } } /// /// Validator for . /// Validates name format, email uniqueness (excluding current student), and prevents XSS attacks. /// public class UpdateStudentValidator : AbstractValidator { 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"); } }