diff --git a/Apps/GatewayApi/src/Services/IJobService.cs b/Apps/GatewayApi/src/Services/IJobService.cs index da07b108ad..a31991e914 100644 --- a/Apps/GatewayApi/src/Services/IJobService.cs +++ b/Apps/GatewayApi/src/Services/IJobService.cs @@ -69,6 +69,6 @@ public interface IJobService /// The code used to validate the ownership of the number. /// to manage the async request. /// A representing the asynchronous operation. - Task PushNotificationSettingsToPhsaAsync(UserProfile userProfile, string email, string smsNumber, string smsVerificationCode, CancellationToken ct = default); + Task PushNotificationSettingsToPhsaAsync(UserProfile userProfile, string? email, string? smsNumber, string? smsVerificationCode = null, CancellationToken ct = default); } } diff --git a/Apps/GatewayApi/src/Services/JobService.cs b/Apps/GatewayApi/src/Services/JobService.cs index 3f813c9a63..81f2b7acfe 100644 --- a/Apps/GatewayApi/src/Services/JobService.cs +++ b/Apps/GatewayApi/src/Services/JobService.cs @@ -65,7 +65,7 @@ public async Task SendEmailAsync(string emailAddress, string emailTemplateName, } /// - public async Task PushNotificationSettingsToPhsaAsync(UserProfile userProfile, string email, string smsNumber, string smsVerificationCode, CancellationToken ct = default) + public async Task PushNotificationSettingsToPhsaAsync(UserProfile userProfile, string? email, string? smsNumber, string? smsVerificationCode = null, CancellationToken ct = default) { NotificationSettingsRequest notificationSettingsRequest = new(userProfile, email, smsNumber) { SmsVerificationCode = smsVerificationCode }; await notificationSettingsService.QueueNotificationSettingsAsync(notificationSettingsRequest, ct); diff --git a/Apps/GatewayApi/src/Services/UserEmailServiceV2.cs b/Apps/GatewayApi/src/Services/UserEmailServiceV2.cs index f4ade2d2e7..5f5ab80606 100644 --- a/Apps/GatewayApi/src/Services/UserEmailServiceV2.cs +++ b/Apps/GatewayApi/src/Services/UserEmailServiceV2.cs @@ -22,10 +22,6 @@ namespace HealthGateway.GatewayApi.Services using HealthGateway.Common.Constants; using HealthGateway.Common.Data.Constants; using HealthGateway.Common.ErrorHandling.Exceptions; - using HealthGateway.Common.Messaging; - using HealthGateway.Common.Models; - using HealthGateway.Common.Models.Events; - using HealthGateway.Common.Services; using HealthGateway.Database.Constants; using HealthGateway.Database.Delegates; using HealthGateway.Database.Models; @@ -39,13 +35,11 @@ public class UserEmailServiceV2 : IUserEmailServiceV2 { private const int MaxVerificationAttempts = 5; - private readonly IEmailQueueService emailQueueService; private readonly ILogger logger; private readonly IMessagingVerificationDelegate messageVerificationDelegate; private readonly IMessagingVerificationService messagingVerificationService; - private readonly INotificationSettingsService notificationSettingsService; private readonly IUserProfileDelegate profileDelegate; - private readonly IMessageSender messageSender; + private readonly IJobService jobService; private readonly bool notificationsChangeFeedEnabled; /// @@ -55,27 +49,21 @@ public class UserEmailServiceV2 : IUserEmailServiceV2 /// The message verification delegate to interact with the DB. /// The messaging verification service. /// The profile delegate to interact with the DB. - /// The email service to queue emails. - /// Notification settings delegate. + /// The injected job service. /// Configuration settings. - /// The message sender. public UserEmailServiceV2( ILogger logger, IMessagingVerificationDelegate messageVerificationDelegate, IMessagingVerificationService messagingVerificationService, IUserProfileDelegate profileDelegate, - IEmailQueueService emailQueueService, - INotificationSettingsService notificationSettingsService, - IConfiguration configuration, - IMessageSender messageSender) + IJobService jobService, + IConfiguration configuration) { this.logger = logger; this.messageVerificationDelegate = messageVerificationDelegate; this.messagingVerificationService = messagingVerificationService; this.profileDelegate = profileDelegate; - this.emailQueueService = emailQueueService; - this.notificationSettingsService = notificationSettingsService; - this.messageSender = messageSender; + this.jobService = jobService; this.notificationsChangeFeedEnabled = configuration.GetSection(ChangeFeedOptions.ChangeFeed).Get()?.Notifications.Enabled ?? false; } @@ -159,7 +147,7 @@ public async Task UpdateEmailAddressAsync(string hdid, string emailAddress, Canc if (messagingVerification != null) { this.logger.LogInformation("Sending new email verification for user {Hdid}", hdid); - await this.emailQueueService.QueueNewEmailAsync(messagingVerification.Email, true, ct); + await this.jobService.SendEmailAsync(messagingVerification.Email, true, ct); } await this.QueueNotificationSettingsRequest(userProfile, ct); @@ -196,14 +184,13 @@ private async Task NotifyVerificationSuccessful(string hdid, string emailAddress { if (this.notificationsChangeFeedEnabled) { - MessageEnvelope[] events = [new(new NotificationChannelVerifiedEvent(hdid, NotificationChannel.Email, emailAddress), hdid)]; - await this.messageSender.SendAsync(events, ct); + await this.jobService.NotifyEmailVerificationAsync(hdid, emailAddress, ct); } } private async Task QueueNotificationSettingsRequest(UserProfile userProfile, CancellationToken ct) { - await this.notificationSettingsService.QueueNotificationSettingsAsync(new NotificationSettingsRequest(userProfile, userProfile.Email, userProfile.SmsNumber), ct); + await this.jobService.PushNotificationSettingsToPhsaAsync(userProfile, userProfile.Email, userProfile.SmsNumber, ct: ct); } } } diff --git a/Apps/GatewayApi/test/unit/Services.Test/UserEmailServiceV2Tests.cs b/Apps/GatewayApi/test/unit/Services.Test/UserEmailServiceV2Tests.cs index 1da917d535..472d4b2de6 100644 --- a/Apps/GatewayApi/test/unit/Services.Test/UserEmailServiceV2Tests.cs +++ b/Apps/GatewayApi/test/unit/Services.Test/UserEmailServiceV2Tests.cs @@ -18,16 +18,11 @@ namespace HealthGateway.GatewayApiTests.Services.Test using System; using System.Collections.Generic; using System.Globalization; - using System.Linq; using System.Threading; using System.Threading.Tasks; using HealthGateway.Common.Constants; using HealthGateway.Common.Data.Constants; using HealthGateway.Common.ErrorHandling.Exceptions; - using HealthGateway.Common.Messaging; - using HealthGateway.Common.Models; - using HealthGateway.Common.Models.Events; - using HealthGateway.Common.Services; using HealthGateway.Database.Constants; using HealthGateway.Database.Delegates; using HealthGateway.Database.Models; @@ -66,7 +61,7 @@ public async Task ShouldVerifyEmailAddress(bool changeFeedEnabled) Guid inviteKey = Guid.NewGuid(); Times expectedNotificationChannelVerifiedEventTimes = ConvertToTimes(changeFeedEnabled); - VerifyEmailAddressMock mock = SetupVerifyEmailAddressMock(inviteKey, changeFeedEnabled); + EmailAddressMock mock = SetupVerifyEmailAddressMock(inviteKey, changeFeedEnabled); // Act bool actual = await mock.Service.VerifyEmailAddressAsync(Hdid, inviteKey, CancellationToken.None); @@ -76,8 +71,8 @@ public async Task ShouldVerifyEmailAddress(bool changeFeedEnabled) VerifyVerificationUpdateValidatedTrue(mock.MessagingVerificationDelegateMock); VerifyUserProfileUpdate(mock.UserProfileDelegateMock); - VerifyQueueNotificationSettings(mock.NotificationSettingsServiceMock); - VerifyNotificationChannelVerifiedEvent(mock.MessageSenderMock, expectedNotificationChannelVerifiedEventTimes); + VerifyPushNotificationSettingsToPhsa(mock.JobServiceMock); + VerifyNotifyEmailVerification(mock.JobServiceMock, expectedNotificationChannelVerifiedEventTimes); } /// @@ -186,7 +181,7 @@ public async Task ShouldUpdateEmailAddress(bool latestVerificationExists, string Times expectedVerificationInsertTimes = ConvertToTimes(!string.IsNullOrEmpty(emailAddress)); Times expectedQueueNewEmailByEntityTimes = ConvertToTimes(!string.IsNullOrEmpty(emailAddress)); - UpdateEmailAddressMock mock = SetupUpdateEmailAddressMock( + EmailAddressMock mock = SetupUpdateEmailAddressMock( Hdid, latestVerificationExists, emailAddress); @@ -197,8 +192,8 @@ public async Task ShouldUpdateEmailAddress(bool latestVerificationExists, string VerifyVerificationExpire(mock.MessagingVerificationDelegateMock, expectedVerificationExpireTimes); VerifyVerificationInsert(mock.MessagingVerificationDelegateMock, expectedVerificationInsertTimes); VerifyUserProfileUpdate(mock.UserProfileDelegateMock); - VerifyQueueNotificationSettings(mock.NotificationSettingsServiceMock); - VerifyQueueNewEmailByEntity(mock.EmailQueueServiceMock, expectedQueueNewEmailByEntityTimes); + VerifyPushNotificationSettingsToPhsa(mock.JobServiceMock); + VerifySendEmail(mock.JobServiceMock, expectedQueueNewEmailByEntityTimes); } /// @@ -239,22 +234,22 @@ private static void VerifyUserProfileUpdate(Mock userProfi times ?? Times.Once()); } - private static void VerifyQueueNewEmailByEntity(Mock emailQueueServiceMock, Times? times = null) + private static void VerifySendEmail(Mock jobServiceMock, Times? times = null) { - emailQueueServiceMock.Verify( - v => v.QueueNewEmailAsync( + jobServiceMock.Verify( + v => v.SendEmailAsync( It.IsAny(), It.IsAny(), It.IsAny()), times ?? Times.Once()); } - private static void VerifyNotificationChannelVerifiedEvent(Mock messageSenderMock, Times? times = null) + private static void VerifyNotifyEmailVerification(Mock jobServiceMock, Times? times = null) { - messageSenderMock.Verify( - v => v.SendAsync( - It.Is>( - envelopes => envelopes.First().Content is NotificationChannelVerifiedEvent), + jobServiceMock.Verify( + v => v.NotifyEmailVerificationAsync( + It.IsAny(), + It.IsAny(), It.IsAny()), times ?? Times.Once()); } @@ -303,11 +298,14 @@ private static void VerifyVerificationUpdateValidatedTrue(Mock notificationSettingsServiceMock, Times? times = null) + private static void VerifyPushNotificationSettingsToPhsa(Mock jobServiceMock, Times? times = null) { - notificationSettingsServiceMock.Verify( - v => v.QueueNotificationSettingsAsync( - It.IsAny(), + jobServiceMock.Verify( + v => v.PushNotificationSettingsToPhsaAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny()), times ?? Times.Once()); } @@ -370,30 +368,24 @@ private static IConfiguration GetConfiguration(bool changeFeedEnabled) } private static IUserEmailServiceV2 GetUserEmailService( + Mock? jobServiceMock = null, Mock? messagingVerificationDelegateMock = null, Mock? messagingVerificationServiceMock = null, Mock? userProfileDelegateMock = null, - Mock? notificationSettingsServiceMock = null, - Mock? messageSenderMock = null, - Mock? emailQueueServiceMock = null, bool changeFeedEnabled = false) { + jobServiceMock ??= new(); messagingVerificationDelegateMock ??= new(); messagingVerificationServiceMock ??= new(); userProfileDelegateMock ??= new(); - notificationSettingsServiceMock ??= new(); - messageSenderMock ??= new(); - emailQueueServiceMock ??= new(); return new UserEmailServiceV2( new Mock>().Object, messagingVerificationDelegateMock.Object, messagingVerificationServiceMock.Object, userProfileDelegateMock.Object, - emailQueueServiceMock.Object, - notificationSettingsServiceMock.Object, - GetConfiguration(changeFeedEnabled), - messageSenderMock.Object); + jobServiceMock.Object, + GetConfiguration(changeFeedEnabled)); } private static Mock SetupMessagingVerificationDelegateMock( @@ -511,27 +503,24 @@ private static Mock SetupUserProfileDelegateMock( return userProfileDelegateMock; } - private static VerifyEmailAddressMock SetupVerifyEmailAddressMock(Guid inviteKey, bool changeFeedEnabled) + private static EmailAddressMock SetupVerifyEmailAddressMock(Guid inviteKey, bool changeFeedEnabled) { Mock messagingVerificationDelegateMock = SetupMessagingVerificationDelegateMock(matchingVerificationInviteKey: inviteKey); Mock userProfileDelegateMock = SetupUserProfileDelegateMock(dbUpdateStatus: DbStatusCode.Updated); - Mock notificationSettingsServiceMock = new(); - Mock messageSenderMock = new(); + Mock jobServiceMock = new(); IUserEmailServiceV2 service = GetUserEmailService( + jobServiceMock, messagingVerificationDelegateMock, userProfileDelegateMock: userProfileDelegateMock, - notificationSettingsServiceMock: notificationSettingsServiceMock, - messageSenderMock: messageSenderMock, changeFeedEnabled: changeFeedEnabled); return new( service, - messageSenderMock, + jobServiceMock, messagingVerificationDelegateMock, - notificationSettingsServiceMock, userProfileDelegateMock); } @@ -545,7 +534,7 @@ private static IUserEmailServiceV2 SetupVerifyEmailAddressTooManyAttemptsMock(Gu Mock userProfileDelegateMock = SetupUserProfileDelegateMock(); return GetUserEmailService( - messagingVerificationDelegateMock, + messagingVerificationDelegateMock: messagingVerificationDelegateMock, userProfileDelegateMock: userProfileDelegateMock); } @@ -559,7 +548,7 @@ private static IUserEmailServiceV2 SetupVerifyEmailAddressThrowsAlreadyExistsExc Mock userProfileDelegateMock = SetupUserProfileDelegateMock(); return GetUserEmailService( - messagingVerificationDelegateMock, + messagingVerificationDelegateMock: messagingVerificationDelegateMock, userProfileDelegateMock: userProfileDelegateMock); } @@ -578,7 +567,9 @@ private static VerifyEmailAddressInvalidInviteMock SetupVerifyEmailAddressInvali setupLatestVerification: true); Mock userProfileDelegateMock = SetupUserProfileDelegateMock(); - IUserEmailServiceV2 service = GetUserEmailService(messagingVerificationDelegateMock, userProfileDelegateMock: userProfileDelegateMock); + IUserEmailServiceV2 service = GetUserEmailService( + messagingVerificationDelegateMock: messagingVerificationDelegateMock, + userProfileDelegateMock: userProfileDelegateMock); return new(service, messagingVerificationDelegateMock); } @@ -590,11 +581,11 @@ private static IUserEmailServiceV2 SetupVerifyEmailAddressThrowsDatabaseExceptio SetupUserProfileDelegateMock(dbUpdateStatus: DbStatusCode.Error); // This will cause a DatabaseException to be thrown. return GetUserEmailService( - messagingVerificationDelegateMock, + messagingVerificationDelegateMock: messagingVerificationDelegateMock, userProfileDelegateMock: userProfileDelegateMock); } - private static UpdateEmailAddressMock SetupUpdateEmailAddressMock( + private static EmailAddressMock SetupUpdateEmailAddressMock( string hdid, bool latestVerificationExists, string? emailAddress, @@ -608,8 +599,7 @@ private static UpdateEmailAddressMock SetupUpdateEmailAddressMock( latestVerificationEmailAddress: MainEmailAddress); Mock userProfileDelegateMock = SetupUserProfileDelegateMock(dbUpdateStatus: updateProfileStatus); - Mock emailQueueServiceMock = new(); - Mock notificationSettingsServiceMock = new(); + Mock jobServiceMock = new(); Mock? messagingVerificationServiceMock = null; if (!string.IsNullOrWhiteSpace(emailAddress)) @@ -620,17 +610,15 @@ private static UpdateEmailAddressMock SetupUpdateEmailAddressMock( } IUserEmailServiceV2 service = GetUserEmailService( + jobServiceMock, messagingVerificationDelegateMock, messagingVerificationServiceMock, - userProfileDelegateMock, - notificationSettingsServiceMock, - emailQueueServiceMock: emailQueueServiceMock); + userProfileDelegateMock); return new( service, - emailQueueServiceMock, + jobServiceMock, messagingVerificationDelegateMock, - notificationSettingsServiceMock, userProfileDelegateMock); } @@ -644,34 +632,24 @@ private static IUserEmailServiceV2 SetupUpdateEmailAddressThrowsExceptionMock( setupLatestVerification: true); Mock userProfileDelegateMock = SetupUserProfileDelegateMock(userProfileExists, updateProfileStatus); - Mock emailQueueServiceMock = new(); - Mock notificationSettingsServiceMock = new(); + Mock jobServiceMock = new(); Mock messagingVerificationServiceMock = new(); return GetUserEmailService( + jobServiceMock, messagingVerificationDelegateMock, messagingVerificationServiceMock, - userProfileDelegateMock, - notificationSettingsServiceMock, - emailQueueServiceMock: emailQueueServiceMock); + userProfileDelegateMock); } - private sealed record VerifyEmailAddressMock( + private sealed record EmailAddressMock( IUserEmailServiceV2 Service, - Mock MessageSenderMock, + Mock JobServiceMock, Mock MessagingVerificationDelegateMock, - Mock NotificationSettingsServiceMock, Mock UserProfileDelegateMock); private sealed record VerifyEmailAddressInvalidInviteMock( IUserEmailServiceV2 Service, Mock MessagingVerificationDelegateMock); - - private sealed record UpdateEmailAddressMock( - IUserEmailServiceV2 Service, - Mock EmailQueueServiceMock, - Mock MessagingVerificationDelegateMock, - Mock NotificationSettingsServiceMock, - Mock UserProfileDelegateMock); } }