Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 9 additions & 54 deletions API/Controllers/AuthorController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Application.Commands.AuthorCommands.UpdateAuthor;
using Application.Dtos;
using Application.Dtos.AuthorDtos;
using Application.Queries.AuthorQueries;
using Application.Queries.AuthorQueries.GetAllAuthors;
using Application.Queries.AuthorQueries.GetAuthorById;
using MediatR;
Expand All @@ -21,6 +20,7 @@ public class AuthorController(IMediator mediator, ILogger<AuthorController> logg
private readonly IMediator _mediator = mediator;
private readonly ILogger<AuthorController> _logger = logger;


// [Authorize]
[Route("GetAllAuthors")]
[HttpGet]
Expand All @@ -32,22 +32,6 @@ public async Task<IActionResult> GetAllAuthors()
{
_logger.LogInformation("Fetching all Authors at {time}", DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));

if (!ModelState.IsValid)
{
var errors = new List<string>();
foreach (var value in ModelState.Values)
{
foreach (var error in value.Errors)
{
errors.Add(error.ErrorMessage);
}
}
string errorMessages = string.Join("\n", errors);

_logger.LogWarning(errorMessages);
return BadRequest(errorMessages);
}

try
{
var operationResult = await _mediator.Send(new GetAllAuthorsQuery());
Expand All @@ -66,6 +50,7 @@ public async Task<IActionResult> GetAllAuthors()
}
}


// [Authorize]
[Route("GetAuthorById/{id}")]
[HttpGet]
Expand All @@ -76,20 +61,12 @@ public async Task<IActionResult> GetAllAuthors()
public async Task<IActionResult> GetAuthor([FromRoute] Guid id)
{
_logger.LogInformation("Fetching AuthorId with ID: {id} at {time}", id, DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));

if (!ModelState.IsValid)
{
_logger.LogWarning("Invalid ID: {Id}", id);
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new GetAuthorByIdQuery(id));

if (operationResult.IsSuccess)
{
_logger.LogInformation("AuthorId with ID: {id} found", id);
return Ok(operationResult.Data);
}
return BadRequest(new { message = operationResult.Message, errors = operationResult.ErrorMessage });
Expand All @@ -102,39 +79,32 @@ public async Task<IActionResult> GetAuthor([FromRoute] Guid id)
}
}


[Route("Create")]
[HttpPost]
[SwaggerOperation(Description = "Adds a new AuthorId to library")]
[SwaggerResponse(200, "Successfully added AuthorId.")]
[SwaggerResponse(400, "Invalid input data")]
public async Task<IActionResult> AddAuthor([FromBody] AddAuthorDto authorToAdd)
{
if (!ModelState.IsValid)
{
_logger.LogWarning("Invalid AuthorId data: {authorToAdd}", authorToAdd);
return BadRequest(ModelState);
}

try
{
_logger.LogInformation("Adding new AuthorId at {time}", DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
var operationResult = await _mediator.Send(new AddAuthorCommand(authorToAdd));

if (operationResult.IsSuccess)
{
_logger.LogInformation("AuthorId added successfully");
return Ok(operationResult.Data);
}
return BadRequest(new { message = operationResult.Message, errors = operationResult.ErrorMessage });

}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while adding new AuthorId at {time}", DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
return StatusCode(500, "An error occurred while processing your request.");
_logger.LogError(ex, "An error occurred while adding new Author at {time}", DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
return StatusCode(500, ex.Message);
}
}


[Route("Update")]
[HttpPut]
[SwaggerOperation(Description = "Updates an existing AuthorId in the collection")]
Expand All @@ -143,19 +113,11 @@ public async Task<IActionResult> AddAuthor([FromBody] AddAuthorDto authorToAdd)
[SwaggerResponse(404, "AuthorId not found")]
public async Task<IActionResult> UpdateAuthor([FromBody, Required] UpdateAuthorDto authorToUpdate)
{
_logger.LogInformation("Updating AuthorId at {time}", DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
if (!ModelState.IsValid)
{
_logger.LogWarning("Invalid AuthorId data: {ModelState}", ModelState);
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new UpdateAuthorCommand(authorToUpdate));
if (operationResult.IsSuccess)
{
_logger.LogInformation("AuthorId updated successfully");
return Ok(operationResult.Data);
}

Expand All @@ -168,6 +130,7 @@ public async Task<IActionResult> UpdateAuthor([FromBody, Required] UpdateAuthorD
}
}


[Route("Delete/{id}")]
[HttpDelete]
[SwaggerOperation(Description = "Deletes AuthorId from collection")]
Expand All @@ -176,29 +139,21 @@ public async Task<IActionResult> UpdateAuthor([FromBody, Required] UpdateAuthorD
[SwaggerResponse(404, "AuthorId not found")]
public async Task<IActionResult> DeleteAuthor([FromRoute] Guid id)
{
_logger.LogInformation("Deleting AuthorId with ID: {id} at {time}", id, DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
if (!ModelState.IsValid)
{
_logger.LogWarning("Invalid AuthorId ID: {id}", id);
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new DeleteAuthorCommand(id));

if (operationResult.IsSuccess)
{
_logger.LogInformation("AuthorId with ID: {id} deleted successfully", id);
return Ok(operationResult.Message);
}
_logger.LogWarning("AuthorId with ID: {id} not found. Error message: {operationResult.ErrorMessage}", id, operationResult.ErrorMessage);
return BadRequest(new { message = operationResult.Message, errors = operationResult.ErrorMessage });
}

catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while deleting AuthorId with ID: {id} at {time}", id, DateTime.Now.ToString("MM/dd/yyyy hh:mm tt"));
return StatusCode(500, "An error occurred while processing your request.");
return StatusCode(500, ex.Message);
}
}
}
Expand Down
36 changes: 5 additions & 31 deletions API/Controllers/BookController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Application.Commands.BookCommands.AddBook;
using Application.Commands.BookCommands.DeleteBook;
using Application.Commands.BookCommands.UpdateBook;
using Application.Dtos;
using Application.Dtos.BookDtos;
using MediatR;
using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -49,6 +48,7 @@ public async Task<IActionResult> GetAllBooks()
}
}


[Route("GetBookById/{bookId}")]
[HttpGet]
[SwaggerOperation(Description = "Gets a book by Id")]
Expand All @@ -57,22 +57,13 @@ public async Task<IActionResult> GetAllBooks()
[SwaggerResponse(404, "Book not found")]
public async Task<IActionResult> GetBook([FromRoute] Guid bookId)
{
if (!ModelState.IsValid)
{
_logger.LogWarning("Invalid ID: {id}", bookId);
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new GetBookByIdQuery(bookId));
if (operationResult.IsSuccess)
{
_logger.LogInformation("Successfully retrieved Book with ID: {id}", bookId);
return Ok(operationResult.Data);

}
_logger.LogWarning("Book with ID: {id} not found", bookId);
return BadRequest(new { message = operationResult.Message, errors = operationResult.ErrorMessage });
}

Expand All @@ -83,19 +74,14 @@ public async Task<IActionResult> GetBook([FromRoute] Guid bookId)
}
}


[Route("Create")]
[HttpPost]
[SwaggerOperation(Description = "Adds a new Book to library")]
[SwaggerResponse(200, "Successfully added Book.")]
[SwaggerResponse(400, "Invalid input data.")]
public async Task<IActionResult> AddBook([FromBody, Required] AddBookDto bookToAdd)
{
if (!ModelState.IsValid)
{
_logger.LogWarning($"Invalid Book data: {ModelState}");
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new AddBookCommand(bookToAdd));
Expand All @@ -115,6 +101,7 @@ public async Task<IActionResult> AddBook([FromBody, Required] AddBookDto bookToA
}
}


[Route("Update")]
[HttpPut]
[SwaggerOperation(Description = "Updates an existing Book in collection")]
Expand All @@ -123,18 +110,11 @@ public async Task<IActionResult> AddBook([FromBody, Required] AddBookDto bookToA
[SwaggerResponse(404, "Book not found.")]
public async Task<IActionResult> UpdateBook([FromBody, Required] UpdateBookDto book)
{
if (!ModelState.IsValid)
{
_logger.LogWarning($"Invalid Book data: {ModelState}");
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new UpdateBookCommand(book));
if (operationResult.IsSuccess)
{
_logger.LogInformation("Book updated successfully");
return Ok(operationResult.Data);
}

Expand All @@ -148,28 +128,22 @@ public async Task<IActionResult> UpdateBook([FromBody, Required] UpdateBookDto b
}
}


[Route("Delete/{id}")]
[HttpDelete]
[SwaggerOperation(Description = "Deletes a Book from collection")]
[SwaggerResponse(200, "Successfully Deleted Book.")]
[SwaggerResponse(404, "Book not found.")]
public async Task<IActionResult> DeleteBook([FromRoute] Guid id)
{
if (!ModelState.IsValid)
{
_logger.LogWarning($"Invalid ID: {id}");
return BadRequest(ModelState);
}

try
{
var operationResult = await _mediator.Send(new DeleteBookCommand(id));

if (operationResult.IsSuccess)
{
_logger.LogInformation("Book deleted successfully");
return Ok(operationResult.Message);
}

return BadRequest(new { message = operationResult.Message, errors = operationResult.ErrorMessage });
}
catch (Exception ex)
Expand Down
2 changes: 2 additions & 0 deletions Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="FluentValidation" Version="11.11.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ public class AddAuthorCommandHandler(IAuthorRepository authorRepository, IMapper

public async Task<OperationResult<Author>> Handle(AddAuthorCommand request, CancellationToken cancellationToken)
{
if (request == null || request.NewAuthor == null || string.IsNullOrEmpty(request.NewAuthor.FirstName))
{
return OperationResult<Author>.Failure("Invalid input");
}

try
{
Author authorToCreate = new()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using FluentValidation;

namespace Application.Commands.AuthorCommands.AddAuthor
{
public class AddAuthorCommandValidator : AbstractValidator<AddAuthorCommand>
{
public AddAuthorCommandValidator()
{
RuleFor(x => x.NewAuthor.FirstName)
.NotEmpty().WithMessage("Name is required.")
.Length(2, 50).WithMessage("Name must be between 2 and 50 characters.");

RuleFor(x => x.NewAuthor.LastName)
.NotEmpty().WithMessage("Lastname is required.")
.MinimumLength(3).WithMessage("Password must be at least 3 characters long.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,9 @@ public class DeleteAuthorCommandHandler(IAuthorRepository authorRepository, IMap

public async Task<OperationResult<bool>> Handle(DeleteAuthorCommand request, CancellationToken cancellationToken)
{
if (request.Id.Equals(Guid.Empty))
{
return OperationResult<bool>.Failure("Id can not be empty");
}

try
{
var successfulDeletion = await _authorRepository.DeleteAuthor(request.Id);

var mappedBool = _mapper.Map<bool>(successfulDeletion);

if (successfulDeletion)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using FluentValidation;

namespace Application.Commands.AuthorCommands.DeleteAuthor
{
public class DeleteAuthorCommandValidator : AbstractValidator<DeleteAuthorCommand>
{
public DeleteAuthorCommandValidator()
{
RuleFor(x => x.Id)
.Must(id => id != Guid.Empty).WithMessage("Id is required, cannot be empty.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Application.Dtos;
using Application.Dtos.AuthorDtos;
using Application.Dtos.AuthorDtos;
using Application.Models;
using Domain.Entities.Core;
using MediatR;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ public class UpdateAuthorCommandHandler(IAuthorRepository authorRepository, IMap

public async Task<OperationResult<Author>> Handle(UpdateAuthorCommand request, CancellationToken cancellationToken)
{
if (request == null || request.NewAuthor == null || string.IsNullOrEmpty(request.NewAuthor.FirstName))
{
return OperationResult<Author>.Failure("Not valid input");
}

try
{
Author authorToUpdate = new()
Expand All @@ -31,7 +26,6 @@ public async Task<OperationResult<Author>> Handle(UpdateAuthorCommand request, C

var updatedAuthor = await _authorRepository.UpdateAuthor(authorToUpdate);
var mappedAuthor = _mapper.Map<Author>(updatedAuthor);

return OperationResult<Author>.Success(mappedAuthor);
}
catch (Exception ex)
Expand Down
Loading
Loading