From 9f858df5f8559ef4eece66d288194275a0509245 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Tue, 10 Mar 2026 09:52:31 +0100 Subject: [PATCH] added validators in project --- .idea/.idea.BookHive/.idea/workspace.xml | 229 ++++-------------- BookHive/DTO/Book/GetBookDto.cs | 2 + .../MappingProfiles/EntityToDtoMappings.cs | 8 +- .../Authors/CreateAuthorDtoValidator.cs | 45 ++++ .../Authors/GetAuthorDtoValidator.cs | 23 ++ .../Authors/UpdateAuthorDtoValidator.cs | 49 ++++ .../Books/CreateBookDtoValidator.cs | 46 ++++ .../Validators/Books/GetBookDtoValidator.cs | 28 +++ .../Books/UpdateBookDtoValidator.cs | 50 ++++ BookHive/Validators/CustomValidators.cs | 28 +++ .../Loans/CreateLoanDtoValidator.cs | 31 +++ .../Validators/Loans/PatchLoanDtoValidator.cs | 15 ++ .../Loans/UpdateLoanDtoValidator.cs | 42 ++++ .../Members/CreateMemberDtoValidator.cs | 41 ++++ .../Members/UpdateMemberDtoValidator.cs | 45 ++++ .../Reviews/CreateReviewDtoValidator.cs | 30 +++ .../Reviews/UpdateReviewDtoValidator.cs | 34 +++ 17 files changed, 558 insertions(+), 188 deletions(-) create mode 100644 BookHive/Validators/Authors/CreateAuthorDtoValidator.cs create mode 100644 BookHive/Validators/Authors/GetAuthorDtoValidator.cs create mode 100644 BookHive/Validators/Authors/UpdateAuthorDtoValidator.cs create mode 100644 BookHive/Validators/Books/CreateBookDtoValidator.cs create mode 100644 BookHive/Validators/Books/GetBookDtoValidator.cs create mode 100644 BookHive/Validators/Books/UpdateBookDtoValidator.cs create mode 100644 BookHive/Validators/CustomValidators.cs create mode 100644 BookHive/Validators/Loans/CreateLoanDtoValidator.cs create mode 100644 BookHive/Validators/Loans/PatchLoanDtoValidator.cs create mode 100644 BookHive/Validators/Loans/UpdateLoanDtoValidator.cs create mode 100644 BookHive/Validators/Members/CreateMemberDtoValidator.cs create mode 100644 BookHive/Validators/Members/UpdateMemberDtoValidator.cs create mode 100644 BookHive/Validators/Reviews/CreateReviewDtoValidator.cs create mode 100644 BookHive/Validators/Reviews/UpdateReviewDtoValidator.cs diff --git a/.idea/.idea.BookHive/.idea/workspace.xml b/.idea/.idea.BookHive/.idea/workspace.xml index 3c1d6e7..d4cc24f 100644 --- a/.idea/.idea.BookHive/.idea/workspace.xml +++ b/.idea/.idea.BookHive/.idea/workspace.xml @@ -6,191 +6,23 @@ - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -284,7 +130,7 @@ 1773087844958 - + - @@ -331,7 +185,8 @@ - diff --git a/BookHive/DTO/Book/GetBookDto.cs b/BookHive/DTO/Book/GetBookDto.cs index ad5eeec..7b8b6d0 100644 --- a/BookHive/DTO/Book/GetBookDto.cs +++ b/BookHive/DTO/Book/GetBookDto.cs @@ -6,4 +6,6 @@ public class GetBookDto public string? Title { get; set; } public DateOnly PublishedDate { get; set; } public string? Genre { get; set; } + public string? Isbn { get; set; } + public string? AuthorFullName { get; set; } } \ No newline at end of file diff --git a/BookHive/MappingProfiles/EntityToDtoMappings.cs b/BookHive/MappingProfiles/EntityToDtoMappings.cs index c3a6226..c48653c 100644 --- a/BookHive/MappingProfiles/EntityToDtoMappings.cs +++ b/BookHive/MappingProfiles/EntityToDtoMappings.cs @@ -12,7 +12,13 @@ public class EntityToDtoMappings : Profile { public EntityToDtoMappings() { - CreateMap(); + CreateMap() + .ForMember( + dest => dest.AuthorFullName, + opt => + opt.MapFrom(src => + src.Author!.FirstName + " " + src.Author.LastName) + ); CreateMap(); CreateMap(); diff --git a/BookHive/Validators/Authors/CreateAuthorDtoValidator.cs b/BookHive/Validators/Authors/CreateAuthorDtoValidator.cs new file mode 100644 index 0000000..ad388db --- /dev/null +++ b/BookHive/Validators/Authors/CreateAuthorDtoValidator.cs @@ -0,0 +1,45 @@ +using BookHive.DTO.Author; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Authors; + +public class CreateAuthorDtoValidator : Validator +{ + public CreateAuthorDtoValidator() + { + RuleFor(x => x.FirstName) + .NotEmpty() + .WithMessage("First name is required.") + .MaximumLength(100) + .WithMessage("First name cannot exceed 100 characters.") + .MinimumLength(2) + .WithMessage("First name must exceed 2 characters."); + + RuleFor(x => x.LastName) + .NotEmpty() + .WithMessage("Last name is required.") + .MaximumLength(100) + .WithMessage("Last name cannot exceed 100 characters.") + .MinimumLength(2) + .WithMessage("Last name must exceed 2 characters."); + + RuleFor(x => x.Biography) + .MaximumLength(2000) + .WithMessage("Biography cannot exceed 2000 characters.") + .MinimumLength(2) + .WithMessage("Biography must exceed 2 characters."); + + RuleFor(x => x.BirthDate) + .NotEmpty() + .WithMessage("Birth date is required.") + .LessThan(DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("Birth date cannot be in the future."); + + RuleFor(x => x.Nationality) + .NotEmpty() + .WithMessage("Nationality is required.") + .MaximumLength(60) + .WithMessage("Nationality cannot exceed 60 characters."); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Authors/GetAuthorDtoValidator.cs b/BookHive/Validators/Authors/GetAuthorDtoValidator.cs new file mode 100644 index 0000000..46273b9 --- /dev/null +++ b/BookHive/Validators/Authors/GetAuthorDtoValidator.cs @@ -0,0 +1,23 @@ +using BookHive.DTO.Author; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Authors; + +public class GetAuthorDtoValidator : Validator +{ + public GetAuthorDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid"); + + RuleFor(x => x.FirstName) + .NotEmpty() + .WithMessage("First name is required"); + + RuleFor(x => x.LastName) + .NotEmpty() + .WithMessage("Last name is required"); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Authors/UpdateAuthorDtoValidator.cs b/BookHive/Validators/Authors/UpdateAuthorDtoValidator.cs new file mode 100644 index 0000000..dfe405e --- /dev/null +++ b/BookHive/Validators/Authors/UpdateAuthorDtoValidator.cs @@ -0,0 +1,49 @@ +using BookHive.DTO.Author; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Authors; + +public class UpdateAuthorDtoValidator : Validator +{ + public UpdateAuthorDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid."); + + RuleFor(x => x.FirstName) + .NotEmpty() + .WithMessage("First name is required.") + .MaximumLength(100) + .WithMessage("First name cannot exceed 100 characters.") + .MinimumLength(2) + .WithMessage("First name must exceed 2 characters."); + + RuleFor(x => x.LastName) + .NotEmpty() + .WithMessage("Last name is required.") + .MaximumLength(100) + .WithMessage("Last name cannot exceed 100 characters.") + .MinimumLength(2) + .WithMessage("Last name must exceed 2 characters."); + + RuleFor(x => x.Biography) + .MaximumLength(2000) + .WithMessage("Biography cannot exceed 2000 characters.") + .MinimumLength(2) + .WithMessage("Biography must exceed 2 characters."); + + RuleFor(x => x.BirthDate) + .NotEmpty() + .WithMessage("Birth date is required.") + .LessThan(DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("Birth date cannot be in the future."); + + RuleFor(x => x.Nationality) + .NotEmpty() + .WithMessage("Nationality is required.") + .MaximumLength(60) + .WithMessage("Nationality cannot exceed 60 characters."); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Books/CreateBookDtoValidator.cs b/BookHive/Validators/Books/CreateBookDtoValidator.cs new file mode 100644 index 0000000..92dcdeb --- /dev/null +++ b/BookHive/Validators/Books/CreateBookDtoValidator.cs @@ -0,0 +1,46 @@ +using BookHive.DTO.Book; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Books; + +public class CreateBookDtoValidator : Validator +{ + public CreateBookDtoValidator() + { + RuleFor(x => x.Title) + .NotEmpty().WithMessage("Le titre est obligatoire.") + .MaximumLength(200) + .WithMessage("Le titre ne peut pas dépasser 200 caractères."); + + RuleFor(x => x.Isbn) + .NotEmpty().WithMessage("L’ISBN est obligatoire.") + .Matches(@"^\d{13}$") + .WithMessage("L’ISBN doit contenir exactement 13 chiffres."); + + RuleFor(x => x.PageCount) + .GreaterThan(0) + .WithMessage("Le nombre de pages doit être supérieur à 0."); + + RuleFor(x => x.PublishedDate) + .NotEmpty().WithMessage("La date de publication est obligatoire.") + .Must(d => d <= DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("La date de publication ne peut pas être dans le futur."); + + RuleFor(x => x.Genre) + .NotEmpty() + .WithMessage("Le genre est obligatoire.") + .MaximumLength(50) + .WithMessage("Le genre ne peut pas dépasser 50 caractères."); + + RuleFor(x => x.AuthorId) + .GreaterThan(0) + .WithMessage("L’identifiant de l’auteur est invalide."); + + When(x => x.Summary != null, () => + { + RuleFor(x => x.Summary) + .MaximumLength(3000).WithMessage("Le résumé ne peut pas dépasser 3000 caractères."); + }); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Books/GetBookDtoValidator.cs b/BookHive/Validators/Books/GetBookDtoValidator.cs new file mode 100644 index 0000000..64aae50 --- /dev/null +++ b/BookHive/Validators/Books/GetBookDtoValidator.cs @@ -0,0 +1,28 @@ +using BookHive.DTO.Book; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Books; + +public class GetBookDtoValidator : Validator +{ + public GetBookDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid"); + + RuleFor(x => x.Title) + .NotEmpty() + .WithMessage("Title is required"); + + RuleFor(x => x.Isbn) + .NotEmpty().WithMessage("L’ISBN est obligatoire.") + .Matches(@"^\d{13}$") + .WithMessage("L’ISBN doit contenir exactement 13 chiffres."); + + RuleFor(x => x.AuthorFullName) + .NotEmpty() + .WithMessage("AuthorFullName is required"); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Books/UpdateBookDtoValidator.cs b/BookHive/Validators/Books/UpdateBookDtoValidator.cs new file mode 100644 index 0000000..1d18483 --- /dev/null +++ b/BookHive/Validators/Books/UpdateBookDtoValidator.cs @@ -0,0 +1,50 @@ +using BookHive.DTO.Book; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Books; + +public class UpdateBookDtoValidator : Validator +{ + public UpdateBookDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid."); + + RuleFor(x => x.Title) + .NotEmpty().WithMessage("Le titre est obligatoire.") + .MaximumLength(200) + .WithMessage("Le titre ne peut pas dépasser 200 caractères."); + + RuleFor(x => x.Isbn) + .NotEmpty().WithMessage("L’ISBN est obligatoire.") + .Matches(@"^\d{13}$") + .WithMessage("L’ISBN doit contenir exactement 13 chiffres."); + + RuleFor(x => x.PageCount) + .GreaterThan(0) + .WithMessage("Le nombre de pages doit être supérieur à 0."); + + RuleFor(x => x.PublishedDate) + .NotEmpty().WithMessage("La date de publication est obligatoire.") + .Must(d => d <= DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("La date de publication ne peut pas être dans le futur."); + + RuleFor(x => x.Genre) + .NotEmpty() + .WithMessage("Le genre est obligatoire.") + .MaximumLength(50) + .WithMessage("Le genre ne peut pas dépasser 50 caractères."); + + RuleFor(x => x.AuthorId) + .GreaterThan(0) + .WithMessage("L’identifiant de l’auteur est invalide."); + + When(x => x.Summary != null, () => + { + RuleFor(x => x.Summary) + .MaximumLength(3000).WithMessage("Le résumé ne peut pas dépasser 3000 caractères."); + }); + } +} \ No newline at end of file diff --git a/BookHive/Validators/CustomValidators.cs b/BookHive/Validators/CustomValidators.cs new file mode 100644 index 0000000..5b01e8f --- /dev/null +++ b/BookHive/Validators/CustomValidators.cs @@ -0,0 +1,28 @@ +using FluentValidation; + +namespace BookHive.Validators; + +public static class CustomValidators +{ + public static IRuleBuilderOptions + IsValidIsbn13(this IRuleBuilder ruleBuilder) + { + return ruleBuilder + .Matches(@"^\d{13}$") + .WithMessage("L’ISBN doit contenir 13 chiffres.") + .Must(isbn => + { + if (string.IsNullOrEmpty(isbn) || isbn.Length != 13) + return false; + var sum = 0; + for (int i = 0; i < 12; i++) + { + var digit = isbn[i] - '0'; + sum += (i % 2 == 0) ? digit : digit * 3; + } + var checkDigit = (10 - (sum % 10)) % 10; + return checkDigit == (isbn[12] - '0'); + }) + .WithMessage("Le chiffre de contrôle ISBN est invalide."); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Loans/CreateLoanDtoValidator.cs b/BookHive/Validators/Loans/CreateLoanDtoValidator.cs new file mode 100644 index 0000000..7cfd56a --- /dev/null +++ b/BookHive/Validators/Loans/CreateLoanDtoValidator.cs @@ -0,0 +1,31 @@ +using BookHive.DTO.Loan; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Loans; + +public class CreateLoanDtoValidator : Validator +{ + public CreateLoanDtoValidator() + { + RuleFor(x => x.BookId) + .GreaterThan(0) + .WithMessage("Invalid book id."); + + RuleFor(x => x.MemberId) + .GreaterThan(0) + .WithMessage("Invalid member id."); + + RuleFor(x => x.LoanDate) + .NotEmpty() + .WithMessage("Date is required."); + + RuleFor(x => x.DueDate) + .NotEmpty() + .WithMessage("Due date is required.") + .GreaterThan(d => d.LoanDate) + .WithMessage("Due date must be in the future.") + .Must((loan, dueDate) => dueDate <= loan.LoanDate.AddDays(30)) + .WithMessage("Due date must be in the future.");; + } +} \ No newline at end of file diff --git a/BookHive/Validators/Loans/PatchLoanDtoValidator.cs b/BookHive/Validators/Loans/PatchLoanDtoValidator.cs new file mode 100644 index 0000000..589e56e --- /dev/null +++ b/BookHive/Validators/Loans/PatchLoanDtoValidator.cs @@ -0,0 +1,15 @@ +using BookHive.Endpoints.Loans; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Loans; + +public class PatchLoanDtoValidator : Validator +{ + public PatchLoanDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid"); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Loans/UpdateLoanDtoValidator.cs b/BookHive/Validators/Loans/UpdateLoanDtoValidator.cs new file mode 100644 index 0000000..3fc93f8 --- /dev/null +++ b/BookHive/Validators/Loans/UpdateLoanDtoValidator.cs @@ -0,0 +1,42 @@ +using BookHive.DTO.Loan; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Loans; + +public class UpdateLoanDtoValidator : Validator +{ + public UpdateLoanDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid."); + + RuleFor(x => x.BookId) + .GreaterThan(0) + .WithMessage("Invalid book id."); + + RuleFor(x => x.MemberId) + .GreaterThan(0) + .WithMessage("Invalid member id."); + + RuleFor(x => x.LoanDate) + .NotEmpty() + .WithMessage("Date is required."); + + RuleFor(x => x.DueDate) + .NotEmpty() + .WithMessage("Due date is required.") + .GreaterThan(d => d.LoanDate) + .WithMessage("Due date must be in the future.") + .Must((loan, dueDate) => dueDate <= loan.LoanDate.AddDays(30)) + .WithMessage("Due date must be in the future."); + + When(x => x.ReturnDate != null, () => + { + RuleFor(x => x.ReturnDate) + .GreaterThan(d => d.LoanDate) + .WithMessage("Return date must be in the future."); + }); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Members/CreateMemberDtoValidator.cs b/BookHive/Validators/Members/CreateMemberDtoValidator.cs new file mode 100644 index 0000000..eb89b14 --- /dev/null +++ b/BookHive/Validators/Members/CreateMemberDtoValidator.cs @@ -0,0 +1,41 @@ +using BookHive.DTO.Member; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Members; + +public class CreateMemberDtoValidator : Validator +{ + public CreateMemberDtoValidator() + { + RuleFor(x => x.Email) + .NotEmpty() + .WithMessage("Email is required.") + .EmailAddress() + .WithMessage("Email is invalid.") + .MaximumLength(255) + .WithMessage("Email cannot be longer than 255 characters."); + + RuleFor(x => x.FirstName) + .NotEmpty() + .WithMessage("First name is required.") + .MaximumLength(100) + .WithMessage("First name cannot be longer than 100 characters.") + .MinimumLength(2) + .WithMessage("First name cannot be shorter than 2 characters."); + + RuleFor(x => x.LastName) + .NotEmpty() + .WithMessage("Last name is required.") + .MaximumLength(100) + .WithMessage("Last name cannot be longer than 100 characters.") + .MinimumLength(2) + .WithMessage("Last name cannot be shorter than 2 characters."); + + RuleFor(x => x.MembershipDate) + .NotEmpty() + .WithMessage("Membership date is required.") + .Must(d => d <= DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("Membership date cannot be in the future."); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Members/UpdateMemberDtoValidator.cs b/BookHive/Validators/Members/UpdateMemberDtoValidator.cs new file mode 100644 index 0000000..88c7370 --- /dev/null +++ b/BookHive/Validators/Members/UpdateMemberDtoValidator.cs @@ -0,0 +1,45 @@ +using BookHive.DTO.Member; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Members; + +public class UpdateMemberDtoValidator : Validator +{ + public UpdateMemberDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid."); + + RuleFor(x => x.Email) + .NotEmpty() + .WithMessage("Email is required.") + .EmailAddress() + .WithMessage("Email is invalid.") + .MaximumLength(255) + .WithMessage("Email cannot be longer than 255 characters."); + + RuleFor(x => x.FirstName) + .NotEmpty() + .WithMessage("First name is required.") + .MaximumLength(100) + .WithMessage("First name cannot be longer than 100 characters.") + .MinimumLength(2) + .WithMessage("First name cannot be shorter than 2 characters."); + + RuleFor(x => x.LastName) + .NotEmpty() + .WithMessage("Last name is required.") + .MaximumLength(100) + .WithMessage("Last name cannot be longer than 100 characters.") + .MinimumLength(2) + .WithMessage("Last name cannot be shorter than 2 characters."); + + RuleFor(x => x.MembershipDate) + .NotEmpty() + .WithMessage("Membership date is required.") + .Must(d => d <= DateOnly.FromDateTime(DateTime.Now)) + .WithMessage("Membership date cannot be in the future."); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Reviews/CreateReviewDtoValidator.cs b/BookHive/Validators/Reviews/CreateReviewDtoValidator.cs new file mode 100644 index 0000000..4a2caca --- /dev/null +++ b/BookHive/Validators/Reviews/CreateReviewDtoValidator.cs @@ -0,0 +1,30 @@ +using BookHive.DTO.Review; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Reviews; + +public class CreateReviewDtoValidator : Validator +{ + public CreateReviewDtoValidator() + { + RuleFor(x => x.MemberId) + .GreaterThan(0) + .WithMessage("Member id is invalid."); + + RuleFor(x => x.BookId) + .GreaterThan(0) + .WithMessage("Book id is invalid."); + + RuleFor(x => x.Rating) + .InclusiveBetween(1, 5) + .WithMessage("Rating must be between 1 and 5."); + + When(x => x.Comment is not null, () => + { + RuleFor(x => x.Comment) + .MaximumLength(3000) + .WithMessage("Comment cannot exceed 3000 characters."); + }); + } +} \ No newline at end of file diff --git a/BookHive/Validators/Reviews/UpdateReviewDtoValidator.cs b/BookHive/Validators/Reviews/UpdateReviewDtoValidator.cs new file mode 100644 index 0000000..c1d0980 --- /dev/null +++ b/BookHive/Validators/Reviews/UpdateReviewDtoValidator.cs @@ -0,0 +1,34 @@ +using BookHive.DTO.Review; +using FastEndpoints; +using FluentValidation; + +namespace BookHive.Validators.Reviews; + +public class UpdateReviewDtoValidator : Validator +{ + public UpdateReviewDtoValidator() + { + RuleFor(x => x.Id) + .GreaterThan(0) + .WithMessage("Id is invalid."); + + RuleFor(x => x.BookId) + .GreaterThan(0) + .WithMessage("Book id is invalid."); + + RuleFor(x => x.MemberId) + .GreaterThan(0) + .WithMessage("Member id is invalid."); + + RuleFor(x => x.Rating) + .InclusiveBetween(1, 5) + .WithMessage("Rating must be between 1 and 5."); + + When(x => x.Comment is not null, () => + { + RuleFor(x => x.Comment) + .MaximumLength(3000) + .WithMessage("Comment cannot exceed 3000 characters."); + }); + } +} \ No newline at end of file