From e7302862dc7f747d6ccf6c3f8d987fd9b04e8716 Mon Sep 17 00:00:00 2001 From: Ike Kottlowski Date: Fri, 6 Jun 2025 19:09:21 -0400 Subject: [PATCH] fix: entity framework query returns same results as the dapper implementation. test: added testing for repositories. --- .../AuthRequestReadPendingByUserIdQuery.cs | 8 +- .../AuthRequestRepositoryTests.cs | 90 ++++++++++++++++++- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure.EntityFramework/Auth/Repositories/Queries/AuthRequestReadPendingByUserIdQuery.cs b/src/Infrastructure.EntityFramework/Auth/Repositories/Queries/AuthRequestReadPendingByUserIdQuery.cs index 7228c296e7..2073067de0 100644 --- a/src/Infrastructure.EntityFramework/Auth/Repositories/Queries/AuthRequestReadPendingByUserIdQuery.cs +++ b/src/Infrastructure.EntityFramework/Auth/Repositories/Queries/AuthRequestReadPendingByUserIdQuery.cs @@ -13,13 +13,13 @@ public class AuthRequestReadPendingByUserIdQuery { var pendingAuthRequestQuery = from authRequest in dbContext.AuthRequests + where authRequest.UserId == userId + where authRequest.Type == AuthRequestType.AuthenticateAndUnlock || authRequest.Type == AuthRequestType.Unlock + where authRequest.Approved == null + where authRequest.CreationDate.AddMinutes(expirationMinutes) > DateTime.UtcNow group authRequest by authRequest.RequestDeviceIdentifier into groupedRequests select (from pendingRequests in groupedRequests - where pendingRequests.UserId == userId - where pendingRequests.Type == AuthRequestType.AuthenticateAndUnlock || pendingRequests.Type == AuthRequestType.Unlock - where pendingRequests.Approved == null - where pendingRequests.CreationDate.AddMinutes(expirationMinutes) > DateTime.UtcNow orderby pendingRequests.CreationDate descending select pendingRequests).First(); diff --git a/test/Infrastructure.IntegrationTest/Auth/Repositories/AuthRequestRepositoryTests.cs b/test/Infrastructure.IntegrationTest/Auth/Repositories/AuthRequestRepositoryTests.cs index 8cd8cb607c..ad1c10d4a9 100644 --- a/test/Infrastructure.IntegrationTest/Auth/Repositories/AuthRequestRepositoryTests.cs +++ b/test/Infrastructure.IntegrationTest/Auth/Repositories/AuthRequestRepositoryTests.cs @@ -182,7 +182,95 @@ public class AuthRequestRepositoryTests Assert.Null(uncreatedAuthRequest); } - private static AuthRequest CreateAuthRequest(Guid userId, AuthRequestType authRequestType, DateTime creationDate, bool? approved = null, DateTime? responseDate = null) + /// + /// Test to determine that when no valid authRequest exists in the database the return value is null. + /// + [DatabaseTheory, DatabaseData] + public async Task GetManyPendingAuthRequestByUserId_AuthRequstsInvalid_ReturnsEmptyEnumerable_Success( + IAuthRequestRepository authRequestRepository, + IUserRepository userRepository) + { + var user = await userRepository.CreateAsync(new User + { + Name = "Test User", + Email = $"test+{Guid.NewGuid()}@email.com", + ApiKey = "TEST", + SecurityStamp = "stamp", + }); + + List authRequests = []; + + // A user auth request type that has passed its expiration time, should not be returned. + var authRequest = CreateAuthRequest( + user.Id, + AuthRequestType.AuthenticateAndUnlock, + CreateExpiredDate(_userRequestExpiration)); + authRequest.RequestDeviceIdentifier = "auth_request_expired"; + authRequests.Add(await authRequestRepository.CreateAsync(authRequest)); + + // A valid time AuthRequest but for pending we do not fetch admin auth requests + authRequest.Type = AuthRequestType.AdminApproval; + authRequest.CreationDate = DateTime.UtcNow.AddMinutes(-1); + authRequest.RequestDeviceIdentifier = "admin_auth_request"; + authRequests.Add(await authRequestRepository.CreateAsync(authRequest)); + + // A valid time AuthRequest but for pending we do not fetch admin auth requests + authRequest.Type = AuthRequestType.AuthenticateAndUnlock; + authRequest.Approved = false; + authRequest.RequestDeviceIdentifier = "approved_auth_request"; + authRequests.Add(await authRequestRepository.CreateAsync(authRequest)); + + var result = await authRequestRepository.GetManyPendingAuthRequestByUserId(user.Id); + Assert.NotNull(result); + Assert.Empty(result); + + // Verify that there are authrequest associated with the user. + Assert.NotEmpty(await authRequestRepository.GetManyByUserIdAsync(user.Id)); + } + + /// + /// Test to determine that when multiple valid authRequest exist for a device only the soonest one is returned. + /// + [DatabaseTheory, DatabaseData] + public async Task GetManyPendingAuthRequestByUserId_MultipleRequestForSingleDevice_ReturnsMostRecent( + IAuthRequestRepository authRequestRepository, + IUserRepository userRepository) + { + var user = await userRepository.CreateAsync(new User + { + Name = "Test User", + Email = $"test+{Guid.NewGuid()}@email.com", + ApiKey = "TEST", + SecurityStamp = "stamp", + }); + + var authRequest = CreateAuthRequest( + user.Id, + AuthRequestType.AuthenticateAndUnlock, + DateTime.UtcNow.AddMinutes(-1)); + var oneMinuteOldAuthRequest = await authRequestRepository.CreateAsync(authRequest); + + authRequest.CreationDate = DateTime.UtcNow.AddMinutes(-5); + var fiveMinuteOldAuthRequest = await authRequestRepository.CreateAsync(authRequest); + + authRequest.CreationDate = DateTime.UtcNow.AddMinutes(-10); + var tenMinuteOldAuthRequest = await authRequestRepository.CreateAsync(authRequest); + + var result = await authRequestRepository.GetManyPendingAuthRequestByUserId(user.Id); + Assert.NotNull(result); + // since we group by device there should only be a sinlge return since the device Id is the same + Assert.Single(result); + // we return null values per device per user, there is one device in the database so there should be one response and it should be null + var everyValueNotNull = result.Any(ar => ar != null); + Assert.True(everyValueNotNull); + } + + private static AuthRequest CreateAuthRequest( + Guid userId, + AuthRequestType authRequestType, + DateTime creationDate, + bool? approved = null, + DateTime? responseDate = null) { return new AuthRequest {