diff --git a/CommonTestUtilities/LoggedUser/LoggedUserBuilder.cs b/CommonTestUtilities/LoggedUser/LoggedUserBuilder.cs new file mode 100644 index 0000000..8596660 --- /dev/null +++ b/CommonTestUtilities/LoggedUser/LoggedUserBuilder.cs @@ -0,0 +1,17 @@ +using Moq; +using ProductClientHub.Domain.Entities; +using ProductClientHub.Domain.Services.LoggedUser; + +namespace CommonTestUtilities.LoggedUser; + +public class LoggedUserBuilder +{ + public static ILoggedUser Build(Client client) + { + var mock = new Mock(); + + mock.Setup(c => c.User()).ReturnsAsync(client); + + return mock.Object; + } +} \ No newline at end of file diff --git a/CommonTestUtilities/Token/JwtTokenGeneratorBuilder.cs b/CommonTestUtilities/Token/JwtTokenGeneratorBuilder.cs new file mode 100644 index 0000000..33e4f60 --- /dev/null +++ b/CommonTestUtilities/Token/JwtTokenGeneratorBuilder.cs @@ -0,0 +1,9 @@ +using ProductClientHub.Domain.Security.Tokens; +using ProductClientHub.Infrastructure.Security.Tokens.Acess.Generator; + +namespace CommonTestUtilities.Token; + +public class JwtTokenGeneratorBuilder +{ + public static IAccessTokenGenerator Build() => new JwtTokenGenerator(expirationTimeMinutes: 5, signingKey: "ttttttttttttttttttttttttttttttttttttttttt"); +} diff --git a/ProductClientHub.API/Controllers/ClientsController.cs b/ProductClientHub.API/Controllers/ClientsController.cs index f660739..acd8151 100644 --- a/ProductClientHub.API/Controllers/ClientsController.cs +++ b/ProductClientHub.API/Controllers/ClientsController.cs @@ -27,13 +27,12 @@ public async Task ChangePassword([FromRoute] Guid clientId, [From } [HttpPut] - [Route("{clientId:guid}")] [ProducesResponseType(typeof(ResponseClientUpdatedJson), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseErrorMessagesJson), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ResponseErrorMessagesJson), StatusCodes.Status400BadRequest)] - public async Task Update([FromRoute] Guid clientId, [FromBody] RequestShortClientJson request, [FromServices] IUpdateClientUseCase useCase) + public async Task Update([FromBody] RequestShortClientJson request, [FromServices] IUpdateClientUseCase useCase) { - var response = await useCase.Execute(clientId, request); + var response = await useCase.Execute(request); return Ok(response); } diff --git a/ProductClientHub.Application/UseCases/Clients/Update/IUpdateClientUseCase.cs b/ProductClientHub.Application/UseCases/Clients/Update/IUpdateClientUseCase.cs index f71a9f0..7fec365 100644 --- a/ProductClientHub.Application/UseCases/Clients/Update/IUpdateClientUseCase.cs +++ b/ProductClientHub.Application/UseCases/Clients/Update/IUpdateClientUseCase.cs @@ -5,5 +5,5 @@ namespace ProductClientHub.Application.UseCases.Users.Update; public interface IUpdateClientUseCase { - Task Execute(Guid clientId, RequestShortClientJson request); + Task Execute(RequestShortClientJson request); } diff --git a/ProductClientHub.Application/UseCases/Clients/Update/UpdateClientUseCase.cs b/ProductClientHub.Application/UseCases/Clients/Update/UpdateClientUseCase.cs index a3a9f48..9ca9d96 100644 --- a/ProductClientHub.Application/UseCases/Clients/Update/UpdateClientUseCase.cs +++ b/ProductClientHub.Application/UseCases/Clients/Update/UpdateClientUseCase.cs @@ -5,6 +5,7 @@ using ProductClientHub.Domain.Extensions; using ProductClientHub.Domain.Repositories.Client; using ProductClientHub.Domain.Repositories.UnitOfWork; +using ProductClientHub.Domain.Services.LoggedUser; using ProductClientHub.Exceptions.ExceptionsBase; namespace ProductClientHub.Application.UseCases.Users.Update; @@ -14,25 +15,30 @@ public class UpdateClientUseCase : IUpdateClientUseCase private readonly IClientWriteOnlyRepository _clientWriteOnlyRepository; private readonly IClientReadOnlyRepository _clientReadOnlyRepository; private readonly IUnitOfWork _unitOfWork; + private readonly ILoggedUser _loggedUser; public UpdateClientUseCase(IClientWriteOnlyRepository clientWriteOnlyRepository, IClientReadOnlyRepository clientReadOnlyRepository, - IUnitOfWork unitOfWork) + IUnitOfWork unitOfWork, + ILoggedUser loggedUser) { _clientWriteOnlyRepository = clientWriteOnlyRepository; _clientReadOnlyRepository = clientReadOnlyRepository; _unitOfWork = unitOfWork; + _loggedUser = loggedUser; } - public async Task Execute(Guid clientId, RequestShortClientJson request) + public async Task Execute(RequestShortClientJson request) { Validate(request); - var client = await _clientReadOnlyRepository.GetById(clientId) ?? throw new NotFoundException(ResourceMessagesExceptions.CLIENT_NOCONTENT); + var userLogged = await _loggedUser.User(); + + var client = await _clientReadOnlyRepository.GetById(userLogged.Id) ?? throw new NotFoundException(ResourceMessagesExceptions.CLIENT_NOCONTENT); var emailExist = await _clientReadOnlyRepository.EmailAlreadyExists(request.Email); - if(emailExist is not null) + if(emailExist is not null && emailExist.Id != userLogged.Id) throw new EmailAlreadyExistsException(ResourceMessagesExceptions.EMAIL_INVALID); client.Name = request.Name; diff --git a/UseCase.Test/Client/Update/UpdateClientUseCaseTest.cs b/UseCase.Test/Client/Update/UpdateClientUseCaseTest.cs index 97679ed..b362745 100644 --- a/UseCase.Test/Client/Update/UpdateClientUseCaseTest.cs +++ b/UseCase.Test/Client/Update/UpdateClientUseCaseTest.cs @@ -1,10 +1,12 @@ using CommonTestUtilities.Cryptografhy; using CommonTestUtilities.Entities; +using CommonTestUtilities.LoggedUser; using CommonTestUtilities.Repositories; using CommonTestUtilities.Requests; using ProductClientHub.Application.UseCases.Users.Update; using ProductClientHub.Domain.Extensions; using ProductClientHub.Exceptions.ExceptionsBase; +using ProductClientHub.Infrastructure.Services; using Shouldly; namespace UseCase.Test.Client.Update; @@ -20,7 +22,7 @@ public async Task UpdateClient_Sucess() var useCase = CreateUseCase(client, emailExistsTest: false, clientExist: true); - var result = await useCase.Execute(client.Id, clientRequest); + var result = await useCase.Execute(clientRequest); result.ShouldNotBeNull(); result.ShouldSatisfyAllConditions( @@ -38,7 +40,7 @@ public async Task UpdateClient_Error_ClientNotExists() var useCase = CreateUseCase(client, emailExistsTest: false, clientExist: false); - var resultException = await Should.ThrowAsync(async () => await useCase.Execute(client.Id, clientRequest)); + var resultException = await Should.ThrowAsync(async () => await useCase.Execute(clientRequest)); resultException.ShouldNotBeNull(); resultException.ShouldSatisfyAllConditions(() => resultException.Message.ShouldBe(ResourceMessagesExceptions.CLIENT_NOCONTENT)); @@ -53,7 +55,7 @@ public async Task UpdateClient_Error_EmailExist() var useCase = CreateUseCase(client, emailExistsTest: true, clientExist: true); - var resultException = await Should.ThrowAsync(async () => await useCase.Execute(client.Id, clientRequest)); + var resultException = await Should.ThrowAsync(async () => await useCase.Execute(clientRequest)); resultException.ShouldNotBeNull(); resultException.ShouldSatisfyAllConditions(() => resultException.Message.ShouldBe(ResourceMessagesExceptions.EMAIL_INVALID)); @@ -64,13 +66,14 @@ private static UpdateClientUseCase CreateUseCase(ProductClientHub.Domain.Entitie var clientWriteOnlyRepository = ClientWriteOnlyRepositoryBuilder.Build(); var clientReadOnlyRepository = new ClientReadOnlyRepositoryBuilder(); var unitOfWork = UnitOfWorkBuilder.Build(); + var loggedUser = LoggedUserBuilder.Build(client!); - if(client is not null && clientExist.IsTrue()) + if (client is not null && clientExist.IsTrue()) clientReadOnlyRepository.GetById(client); if(emailExistsTest.IsTrue()) clientReadOnlyRepository.EmailAlreadyExists(client); - return new UpdateClientUseCase(clientWriteOnlyRepository, clientReadOnlyRepository.Build(), unitOfWork); + return new UpdateClientUseCase(clientWriteOnlyRepository, clientReadOnlyRepository.Build(), unitOfWork, loggedUser); } } diff --git a/WebApi.Test/Client/Update/UpdateClientIntegrationTest.cs b/WebApi.Test/Client/Update/UpdateClientIntegrationTest.cs index 32eef69..a2c7d91 100644 --- a/WebApi.Test/Client/Update/UpdateClientIntegrationTest.cs +++ b/WebApi.Test/Client/Update/UpdateClientIntegrationTest.cs @@ -1,7 +1,11 @@ -using Microsoft.AspNetCore.Mvc.Testing; +using CommonTestUtilities.Token; +using Microsoft.AspNetCore.Mvc.Testing; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Shouldly; +using System.Net; using System.Net.Http.Headers; +using System.Text; using ClientEntity = ProductClientHub.Domain.Entities.Client; namespace WebApi.Test.Client.Update; @@ -18,8 +22,6 @@ public UpdateClientIntegrationTest(CustomWebApplicationFactory factory) { BaseAddress = new Uri("https://localhost") }); - - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "fake-token"); } [Fact] @@ -30,13 +32,17 @@ public async Task UpdateClientTest_Sucess() new ClientEntity { Name = "Update Client", - Email = "updateclient@gmail.com" - } + Email = "updateclientTEST@gmail.com" + }, ]; client[0].Id = Guid.NewGuid(); - var response = await _httpClient.PutAsync($"/api/clients/{client[0].Id}", new StringContent(JsonConvert.SerializeObject(client[0]), System.Text.Encoding.UTF8, "application/json")); + var token = JwtTokenGeneratorBuilder.Build().Generate(client[0].Id); + + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + var response = await _httpClient.PutAsync($"/api/clients", new StringContent(JsonConvert.SerializeObject(client[0]), System.Text.Encoding.UTF8, "application/json")); response.StatusCode.ShouldBe(System.Net.HttpStatusCode.OK); } @@ -47,23 +53,39 @@ public async Task UpdateClientTest_Error_EmailExist() var client = _factory.ClientsToReturn = [ new ClientEntity - { - Name = "Update Client", - Email = "updateclient@gmail.com" - }, + { + Name = "User Logado", + Email = "user1@gmail.com" + }, new ClientEntity - { - Name = "Update Client 2", - Email = "updateclient@gmail.com" - } + { + Name = "Outro User", + Email = "user2@gmail.com" + } ]; client[0].Id = Guid.NewGuid(); client[1].Id = Guid.NewGuid(); - var response = await _httpClient.PutAsync($"/api/clients/{client[1].Id}", new StringContent(JsonConvert.SerializeObject(client[1]), System.Text.Encoding.UTF8, "application/json")); + var token = JwtTokenGeneratorBuilder.Build().Generate(client[0].Id); + + _httpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", token); + + var updateRequest = new ClientEntity + { + Id = client[0].Id, + Name = "Update", + Email = client[1].Email + }; + + var response = await _httpClient.PutAsync( + "/api/clients", + new StringContent(JsonConvert.SerializeObject(updateRequest), + Encoding.UTF8, + "application/json")); - response.StatusCode.ShouldBe(System.Net.HttpStatusCode.BadRequest); + response.StatusCode.ShouldBe(HttpStatusCode.BadRequest); } } diff --git a/WebApi.Test/CustomWebApplicationFactory.cs b/WebApi.Test/CustomWebApplicationFactory.cs index dacaa7e..f8c1096 100644 --- a/WebApi.Test/CustomWebApplicationFactory.cs +++ b/WebApi.Test/CustomWebApplicationFactory.cs @@ -7,6 +7,7 @@ using ProductClientHub.Domain.Repositories.Client; using ProductClientHub.Domain.Repositories.UnitOfWork; using ProductClientHub.Domain.Security.Tokens; +using ProductClientHub.Domain.Services.LoggedUser; using ClientEntity = ProductClientHub.Domain.Entities.Client; namespace WebApi.Test; @@ -45,6 +46,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) services.RemoveAll(); services.RemoveAll(); services.RemoveAll(); + services.RemoveAll(); // Remove all hosted services to prevent background services from running during tests services.RemoveAll(typeof(IHostedService)); @@ -54,6 +56,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); }); } @@ -137,6 +140,22 @@ public Task Add(ClientEntity client) } } + private sealed class FakeLoggedUser : ILoggedUser + { + private readonly TestClientStore _clientStore; + + public FakeLoggedUser(TestClientStore clientStore) + { + _clientStore = clientStore; + } + + public Task User() + { + var user = _clientStore.Clients.First(); + return Task.FromResult(user); + } + } + private sealed class FakeUnitOfWork : IUnitOfWork { public Task Commit() => Task.CompletedTask; diff --git a/WebApi.Test/WebApi.Test.csproj b/WebApi.Test/WebApi.Test.csproj index b8dcfae..a356379 100644 --- a/WebApi.Test/WebApi.Test.csproj +++ b/WebApi.Test/WebApi.Test.csproj @@ -21,6 +21,7 @@ +