diff --git a/src/Orion.Api/Controllers/V1/UsersController.cs b/src/Orion.Api/Controllers/V1/UsersController.cs index bc1ac88..8a5fdb5 100644 --- a/src/Orion.Api/Controllers/V1/UsersController.cs +++ b/src/Orion.Api/Controllers/V1/UsersController.cs @@ -85,7 +85,7 @@ public async Task Delete(string id) return NoContent(); } - [HttpPatch("Me/PasswordChange")] + [HttpPatch("Me/Password")] [SwaggerResponse((int)HttpStatusCode.BadRequest, "A error response with the error description", typeof(ExceptionResponse))] [SwaggerResponse((int)HttpStatusCode.Accepted)] [SwaggerResponse((int)HttpStatusCode.NotFound)] diff --git a/src/Orion.Api/Models/UserApiTokenModel.cs b/src/Orion.Api/Models/UserApiTokenModel.cs index 107ee87..c48538b 100644 --- a/src/Orion.Api/Models/UserApiTokenModel.cs +++ b/src/Orion.Api/Models/UserApiTokenModel.cs @@ -2,7 +2,7 @@ namespace Orion.Api.Models; public class UserApiTokenModel { - public string Token { get; set; } - public string RefreshToken { get; set; } - public DateTime Expiration { get; set; } + public string Token { get; init; } + public string RefreshToken { get; init; } + public DateTime Expiration { get; init; } } diff --git a/src/Orion.Api/Properties/launchSettings.json b/src/Orion.Api/Properties/launchSettings.json index c83e824..f643621 100644 --- a/src/Orion.Api/Properties/launchSettings.json +++ b/src/Orion.Api/Properties/launchSettings.json @@ -3,7 +3,7 @@ "Dev": { "commandName": "Project", "launchUrl": "swagger", - "launchBrowser": false, + "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, diff --git a/src/Orion.Api/appsettings.Test.json b/src/Orion.Api/appsettings.Test.json index 91afafa..2cf1ff8 100644 --- a/src/Orion.Api/appsettings.Test.json +++ b/src/Orion.Api/appsettings.Test.json @@ -7,7 +7,7 @@ } }, "ConnectionStrings": { - "OrionDatabase": "Data Source=localhost,1433;Initial Catalog=Orion;User ID=sa;Password=SqlServer2019!;TrustServerCertificate=True" + "OrionDatabase": "Data Source=localhost,1433;Initial Catalog=OrionTests;User ID=sa;Password=SqlServer2019!;TrustServerCertificate=True" }, "JwtOptions": { "SymmetricSecurityKey": "5cCI6IkpXVCJ9.eyJlbWFpbCI6InZhbmRlcmxhbi5nc0BnbWFpbC5jb20iLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJhZG1p", diff --git a/src/Orion.Application.Core/Queries/UserGetPaginated/UserGetByIdRequestHandler.cs b/src/Orion.Application.Core/Queries/UserGetPaginated/UserGetPaginatedRequestHandler.cs similarity index 97% rename from src/Orion.Application.Core/Queries/UserGetPaginated/UserGetByIdRequestHandler.cs rename to src/Orion.Application.Core/Queries/UserGetPaginated/UserGetPaginatedRequestHandler.cs index 277598d..f497243 100644 --- a/src/Orion.Application.Core/Queries/UserGetPaginated/UserGetByIdRequestHandler.cs +++ b/src/Orion.Application.Core/Queries/UserGetPaginated/UserGetPaginatedRequestHandler.cs @@ -19,6 +19,6 @@ public async Task> Handle(UserGetPaginatedRe var usersPaginated = users.Items.Select(user => (UserGetPaginatedResponse)user).ToList(); - return new PagedList(usersPaginated); + return new PagedList(usersPaginated, users.Count); } } \ No newline at end of file diff --git a/tests/Orion.Test/Api/V1/AuthApiTest.cs b/tests/Orion.Test/Api/V1/AuthApiTest.cs index 2298822..5617038 100644 --- a/tests/Orion.Test/Api/V1/AuthApiTest.cs +++ b/tests/Orion.Test/Api/V1/AuthApiTest.cs @@ -57,7 +57,7 @@ public async Task AuthUser_WithRefreshTokenInvalid_ReturnsUnauthorized(string re } [Fact] - public async Task AuthUser_WithValidRefreshToken_ReturnsNewToken() + public async Task AuthUser_WithValidRefreshTokenAndExpiredToken_ReturnsNewToken() { //arrange var user = UserFaker.GetUserCreateRequest(); @@ -85,6 +85,31 @@ public async Task AuthUser_WithValidRefreshToken_ReturnsNewToken() Assert.NotNull(refreshTokenResponse.RefreshToken); } + [Fact] + public async Task AuthUser_WithInvalidRefreshTokenAndValidExpiredToken_ReturnsUnauthorized() + { + //arrange + var user = UserFaker.GetUserCreateRequest(); + + var userCreated = await CreateUserAsync(user); + + var httpClient = IntegrationTestsFixture.GetNewHttpClient(); + + var tokenResult = AuthUser(userCreated.Email, user.Password); + + var refreshTokenRequest = new LoginWithRefreshTokenRequest + { + RefreshToken = "invalid-refresh-token", + Token = tokenResult.Token + }; + + //act + var httpResponseRefreshToken = await httpClient.PostAsync("/api/Auth/RefreshToken", GetStringContent(refreshTokenRequest)); + + //assert + Assert.Equal(HttpStatusCode.Unauthorized, httpResponseRefreshToken.StatusCode); + } + private async Task CreateUserAsync(UserCreateRequest userCreateRequest = null) { userCreateRequest ??= UserFaker.GetUserCreateRequest(); diff --git a/tests/Orion.Test/Api/V1/UsersApiTest.cs b/tests/Orion.Test/Api/V1/UsersApiTest.cs index 761707c..4d021d9 100644 --- a/tests/Orion.Test/Api/V1/UsersApiTest.cs +++ b/tests/Orion.Test/Api/V1/UsersApiTest.cs @@ -6,6 +6,8 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Orion.Application.Core.Commands.UserChangePassword; +using Orion.Application.Core.Queries.UserGetPaginated; +using Orion.Domain.Core.ValueObjects.Pagination; using Xunit; namespace Orion.Test.Api.V1 @@ -16,6 +18,52 @@ public UsersApiTest(IntegrationTestsFixture fixture) : base(fixture) { LoginWithDefaultUser(); } + + [Fact] + public async Task GetUserPaginated_WithoutFilter_ReturnsDefaultUser() + { + //arrange & act + var getUsersHttpResponse = await AuthenticatedHttpClient.GetAsync("/api/Users"); + + var listUsersPaginated = await GetResultContentAsync>(getUsersHttpResponse); + + //assert + Assert.Contains(listUsersPaginated.Items, x => x.PublicId == DefaultSystemUser.PublicId); + Assert.Contains(listUsersPaginated.Items, x => x.Name == DefaultSystemUser.Name); + Assert.Contains(listUsersPaginated.Items, x => x.Email == DefaultSystemUser.Email); + Assert.True(listUsersPaginated.Count >= 1); + Assert.Equal(HttpStatusCode.OK, getUsersHttpResponse.StatusCode); + } + + [Fact] + public async Task GetUserPaginated_WithNameFilter_ReturnsDefaultUser() + { + //arrange & act + var getUsersHttpResponse = await AuthenticatedHttpClient.GetAsync($"/api/Users?filter.Query={DefaultSystemUser.Name}"); + + var listUsersPaginated = await GetResultContentAsync>(getUsersHttpResponse); + + //assert + Assert.Contains(listUsersPaginated.Items, x => x.PublicId == DefaultSystemUser.PublicId); + Assert.Contains(listUsersPaginated.Items, x => x.Name == DefaultSystemUser.Name); + Assert.Contains(listUsersPaginated.Items, x => x.Email == DefaultSystemUser.Email); + Assert.True(listUsersPaginated.Count >= 1); + Assert.Equal(HttpStatusCode.OK, getUsersHttpResponse.StatusCode); + } + + [Fact] + public async Task GetUserPaginated_WithInvalidUserName_ReturnsEmptyList() + { + //arrange & act + var getUsersHttpResponse = await AuthenticatedHttpClient.GetAsync($"/api/Users?filter.Query={Guid.NewGuid()}"); + + var listUsersPaginated = await GetResultContentAsync>(getUsersHttpResponse); + + //assert + Assert.Empty(listUsersPaginated.Items); + Assert.True(listUsersPaginated.Count == 0); + Assert.Equal(HttpStatusCode.OK, getUsersHttpResponse.StatusCode); + } [Fact] public async Task PostUser_WithValidData_CreateAUser() @@ -111,13 +159,13 @@ public async Task UpdateUserPassword_WithInvalidPasswordsAndConfirmation_Returns }; //act - var httpResponsePatch = await AuthenticatedHttpClient.PatchAsync("/api/Users/Me/PasswordChange", GetStringContent(changePasswordRequest)); + var httpResponsePatch = await AuthenticatedHttpClient.PatchAsync("/api/Users/Me/Password", GetStringContent(changePasswordRequest)); Assert.Equal(HttpStatusCode.BadRequest, httpResponsePatch.StatusCode); } [Fact] - public async Task UpdateUserPassword_WithValidPasswordsAndConfirmation_ReturnsAcepted() + public async Task UpdateUserPassword_WithValidPasswordsAndConfirmation_ReturnsAccepted() { //arrange var user = UserFaker.GetUserCreateRequest(); @@ -138,12 +186,40 @@ public async Task UpdateUserPassword_WithValidPasswordsAndConfirmation_ReturnsAc httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.Token); //act - var httpResponsePatch = await httpClient.PatchAsync("/api/Users/Me/PasswordChange", GetStringContent(changePasswordRequest)); + var httpResponsePatch = await httpClient.PatchAsync("/api/Users/Me/Password", GetStringContent(changePasswordRequest)); //assert Assert.Equal(HttpStatusCode.Accepted, httpResponsePatch.StatusCode); } + [Fact] + public async Task UpdateUserPassword_WithInValidCurrentPassword_ReturnsBadRequest() + { + //arrange + var user = UserFaker.GetUserCreateRequest(); + + var userCreated = await CreateUserAsync(user); + + var changePasswordRequest = new UserChangePasswordRequest + { + CurrentPassword = "invalid-pass", + NewPassword = "Ab647477382", + NewPasswordConfirm = "Ab647477382" + }; + + var httpClient = IntegrationTestsFixture.GetNewHttpClient(); + + var tokenResult = AuthUser(userCreated.Email, user.Password); + + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.Token); + + //act + var httpResponsePatch = await httpClient.PatchAsync("/api/Users/Me/Password", GetStringContent(changePasswordRequest)); + + //assert + Assert.Equal(HttpStatusCode.BadRequest, httpResponsePatch.StatusCode); + } + private async Task CreateUserAsync(UserCreateRequest userCreateRequest = null) { userCreateRequest ??= UserFaker.GetUserCreateRequest(); diff --git a/tests/Orion.Test/Integration/Setup/IntegrationTestsBootstrapper.cs b/tests/Orion.Test/Integration/Setup/IntegrationTestsBootstrapper.cs index 7fe2c08..8df22e6 100644 --- a/tests/Orion.Test/Integration/Setup/IntegrationTestsBootstrapper.cs +++ b/tests/Orion.Test/Integration/Setup/IntegrationTestsBootstrapper.cs @@ -15,7 +15,7 @@ public abstract class IntegrationTestsBootstrapper : IClassFixture AppFactory; + private readonly WebApplicationFactory _appFactory; public IntegrationTestsFixture() { @@ -47,14 +47,14 @@ public IntegrationTestsFixture() _sqlConnection = new SqlConnection(_configuration["ConnectionStrings:OrionDatabase"]); - AppFactory = appFactory; + _appFactory = appFactory; BeforeEachTest(); } public HttpClient GetNewHttpClient() { - return AppFactory.CreateClient(); + return _appFactory.CreateClient(); } private void BeforeEachTest()