From 36b763fc9bb859e74ef936771437ebf475980862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A6?= =?UTF-8?q?=D0=B5=D0=BF=D0=B5=D0=BD=D1=89=D0=B8=D0=BA=D0=BE=D0=B2?= <58182585+QimbE@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:28:57 +0500 Subject: [PATCH] User as aggregate root (#26) * feat!: user as aggregate * fix: registration logic * fix: tests --- .../Register/RegisterCommandHandler.cs | 8 -------- Domain/Users/RefreshToken.cs | 2 +- Domain/Users/User.cs | 9 ++++++++- .../Configurations/UserConfiguration.cs | 3 ++- .../LogoutCommandHandlerTests.cs | 19 +++++-------------- .../RefreshCommandHandlerTests.cs | 14 +++++--------- Tests/DomainTests/RefreshTokenTests.cs | 1 + .../LogoutEndpointTests.cs | 9 ++------- .../RefreshEndpointTests.cs | 13 ++++--------- 9 files changed, 28 insertions(+), 50 deletions(-) diff --git a/Application/Authentication/Register/RegisterCommandHandler.cs b/Application/Authentication/Register/RegisterCommandHandler.cs index 0b32a6e..1ec2811 100644 --- a/Application/Authentication/Register/RegisterCommandHandler.cs +++ b/Application/Authentication/Register/RegisterCommandHandler.cs @@ -37,14 +37,6 @@ public async Task> Handle(RegisterCommand request, CancellationToke var user = User.Create(request.Name, request.Email, hash, Role.DefaultUser); _context.Users.Add(user); - - // refreshToken - var refreshToken = RefreshToken.Create("sample", user.Id); - - // Security reasons - refreshToken.MakeExpire(); - - _context.RefreshTokens.Add(refreshToken); await _context.SaveChangesAsync(cancellationToken); diff --git a/Domain/Users/RefreshToken.cs b/Domain/Users/RefreshToken.cs index 27f3d7c..e22e426 100644 --- a/Domain/Users/RefreshToken.cs +++ b/Domain/Users/RefreshToken.cs @@ -58,7 +58,7 @@ public static RefreshToken Create(string value, Guid userId) { return new( value, - DateTime.UtcNow.AddDays(LifeTime), + DateTime.UtcNow, userId ); } diff --git a/Domain/Users/User.cs b/Domain/Users/User.cs index f843095..9a63ba3 100644 --- a/Domain/Users/User.cs +++ b/Domain/Users/User.cs @@ -79,9 +79,16 @@ protected User(string name, string email, string password, int roleId, bool isVe IsVerified = isVerified; } - public static User Create(string name, string email, string password, int roleId) + public static User Create( + string name, + string email, + string password, + int roleId + ) { User result = new(name, email, password, roleId, false); + + result.RefreshToken = RefreshToken.Create("sample", result.Id); result.RaiseEvent(new UserCreatedDomainEvent(result.Id)); diff --git a/Infrastructure/Configurations/UserConfiguration.cs b/Infrastructure/Configurations/UserConfiguration.cs index 6b5e3f7..5ce918d 100644 --- a/Infrastructure/Configurations/UserConfiguration.cs +++ b/Infrastructure/Configurations/UserConfiguration.cs @@ -26,7 +26,8 @@ public void Configure(EntityTypeBuilder builder) builder .HasOne(u => u.RefreshToken) .WithOne(r => r.Owner) - .HasForeignKey(r => r.Id); + .HasForeignKey(r => r.Id) + .IsRequired(); // Many-to-one with role builder diff --git a/Tests/ApplicationTests/Authentication/LogoutCommandHandlerTests.cs b/Tests/ApplicationTests/Authentication/LogoutCommandHandlerTests.cs index 5a85d4e..0b34508 100644 --- a/Tests/ApplicationTests/Authentication/LogoutCommandHandlerTests.cs +++ b/Tests/ApplicationTests/Authentication/LogoutCommandHandlerTests.cs @@ -18,14 +18,10 @@ public static IEnumerable InvalidUsersAndTokens() { var user1 = User.Create("123", "test", "123123", 1); - // Expired token - var expiredToken = RefreshToken.Create("123123", user1.Id); - expiredToken.MakeExpire(); - // Token that does not exist var nonExistentToken = RefreshToken.Create("123", Guid.NewGuid()); - return [[user1, expiredToken], [user1, nonExistentToken]]; + return [[user1, user1.RefreshToken], [user1, nonExistentToken]]; } [Theory] @@ -35,11 +31,6 @@ public void Logout_ShouldReturnException_OnInvalidToken(User user, RefreshToken // Arrange RecreateDbContext(); Context.Users.Add(user); - - if (token.Id == user.Id) - { - Context.RefreshTokens.Add(token); - } Context.SaveChangesAsync().GetAwaiter().GetResult(); @@ -68,17 +59,17 @@ public void Refresh_ShouldReturnTokenResponse_OnValidToken() RecreateDbContext(); var user = User.Create("123", "test", "123123", 1); - - var token = RefreshToken.Create("123123123123", user.Id); + + user.RefreshToken.Update("123123123"); + user.VerifyEmail(); Context.Users.Add(user); - Context.RefreshTokens.Add(token); Context.SaveChangesAsync().GetAwaiter().GetResult(); var handler = new LogoutCommandHandler(Context); - var request = new LogoutCommand(token.Value); + var request = new LogoutCommand(user.RefreshToken.Value); // Act var res = handler.Handle(request, default).GetAwaiter().GetResult(); diff --git a/Tests/ApplicationTests/Authentication/RefreshCommandHandlerTests.cs b/Tests/ApplicationTests/Authentication/RefreshCommandHandlerTests.cs index f325f7d..a69f2ad 100644 --- a/Tests/ApplicationTests/Authentication/RefreshCommandHandlerTests.cs +++ b/Tests/ApplicationTests/Authentication/RefreshCommandHandlerTests.cs @@ -17,14 +17,10 @@ public static IEnumerable InvalidUsersAndTokens() { var user1 = User.Create("123", "test", "123123", 1); - // Expired token - var expiredToken = RefreshToken.Create("123123", user1.Id); - expiredToken.MakeExpire(); - // Token that does not exist var nonExistentToken = RefreshToken.Create("123", Guid.NewGuid()); - return [[user1, expiredToken], [user1, nonExistentToken]]; + return [[user1, user1.RefreshToken], [user1, nonExistentToken]]; } [Theory] @@ -67,17 +63,17 @@ public void Refresh_ShouldReturnTokenResponse_OnValidToken() RecreateDbContext(); var user = User.Create("123", "test", "123123", 1); - - var token = RefreshToken.Create("123123123123", user.Id); + user.VerifyEmail(); + + user.RefreshToken.Update(JwtProvider.GenerateRefreshToken()); Context.Users.Add(user); - Context.RefreshTokens.Add(token); Context.SaveChangesAsync().GetAwaiter().GetResult(); var handler = new RefreshCommandHandler(Context, JwtProvider); - var request = new RefreshCommand(token.Value); + var request = new RefreshCommand(user.RefreshToken.Value); // Act var res = handler.Handle(request, default).GetAwaiter().GetResult(); diff --git a/Tests/DomainTests/RefreshTokenTests.cs b/Tests/DomainTests/RefreshTokenTests.cs index 0c682ed..2a64bde 100644 --- a/Tests/DomainTests/RefreshTokenTests.cs +++ b/Tests/DomainTests/RefreshTokenTests.cs @@ -39,6 +39,7 @@ public void MakeExpire_Should_MakeTokenExpire() { // Arrange var token = RefreshToken.Create("random123", Guid.NewGuid()); + token.Update("bimbimbambam"); // Act token.MakeExpire(); diff --git a/Tests/IntegrationTests/AuthenticationTests/LogoutEndpointTests.cs b/Tests/IntegrationTests/AuthenticationTests/LogoutEndpointTests.cs index a964601..148a07c 100644 --- a/Tests/IntegrationTests/AuthenticationTests/LogoutEndpointTests.cs +++ b/Tests/IntegrationTests/AuthenticationTests/LogoutEndpointTests.cs @@ -35,11 +35,8 @@ public async Task Logout_Should_ReturnBadRequest_IfRefreshTokenIsInvalid() var httpClient = Factory.CreateClient(); var fakeToken = "bimbimbimbambambam"; - var actualToken = "hehehehuh"; var user = User.Create("bimbim", "bambam", "123123", Role.DefaultUser); - - var token = RefreshToken.Create(actualToken, user.Id); httpClient.DefaultRequestHeaders.Add("cookie", [$"refreshToken={fakeToken}"]); @@ -48,7 +45,6 @@ public async Task Logout_Should_ReturnBadRequest_IfRefreshTokenIsInvalid() var context = scope.ServiceProvider.GetRequiredService(); context.Users.Add(user); - context.RefreshTokens.Add(token); await context.SaveChangesAsync(); @@ -72,7 +68,8 @@ public async Task Logout_Should_ReturnBaseResponse_IfRefreshTokenValid() var user = User.Create("bimbim", "bambam", "123123", Role.DefaultUser); - var token = RefreshToken.Create(actualToken, user.Id); + user.RefreshToken.Update(actualToken); + user.VerifyEmail(); httpClient.DefaultRequestHeaders.Add("cookie", [$"refreshToken={actualToken}"]); @@ -81,11 +78,9 @@ public async Task Logout_Should_ReturnBaseResponse_IfRefreshTokenValid() var context = scope.ServiceProvider.GetRequiredService(); context.Users.Add(user); - context.RefreshTokens.Add(token); await context.SaveChangesAsync(); - // Act var response = await httpClient.PutAsync("Authentication/Logout", null); diff --git a/Tests/IntegrationTests/AuthenticationTests/RefreshEndpointTests.cs b/Tests/IntegrationTests/AuthenticationTests/RefreshEndpointTests.cs index 864f029..489c87e 100644 --- a/Tests/IntegrationTests/AuthenticationTests/RefreshEndpointTests.cs +++ b/Tests/IntegrationTests/AuthenticationTests/RefreshEndpointTests.cs @@ -36,11 +36,8 @@ public async Task Refresh_Should_ReturnBadRequest_IfRefreshTokenIsInvalid() var httpClient = Factory.CreateClient(); var fakeToken = "bimbimbimbambambam"; - var actualToken = "hehehehuh"; var user = User.Create("bimbim", "bambam", "123123", Role.DefaultUser); - - var token = RefreshToken.Create(actualToken, user.Id); httpClient.DefaultRequestHeaders.Add("cookie", [$"refreshToken={fakeToken}"]); @@ -49,7 +46,6 @@ public async Task Refresh_Should_ReturnBadRequest_IfRefreshTokenIsInvalid() var context = scope.ServiceProvider.GetRequiredService(); context.Users.Add(user); - context.RefreshTokens.Add(token); await context.SaveChangesAsync(); @@ -69,11 +65,12 @@ public async Task Refresh_Should_ReturnTokenResponse_IfRefreshTokenValid() // Arrange var httpClient = Factory.CreateClient(); - var actualToken = "hehehehuh"; - var user = User.Create("bimbim", "bambam", "123123", Role.DefaultUser); - var token = RefreshToken.Create(actualToken, user.Id); + user.RefreshToken.Update("123123123"); + user.VerifyEmail(); + + var actualToken = user.RefreshToken.Value; httpClient.DefaultRequestHeaders.Add("cookie", [$"refreshToken={actualToken}"]); @@ -82,11 +79,9 @@ public async Task Refresh_Should_ReturnTokenResponse_IfRefreshTokenValid() var context = scope.ServiceProvider.GetRequiredService(); context.Users.Add(user); - context.RefreshTokens.Add(token); await context.SaveChangesAsync(); - // Act var response = await httpClient.PutAsync("Authentication/Refresh", null);