diff --git a/LearningHub.Nhs.UserApi.Services.Interface/IOpenApiHttpClient.cs b/LearningHub.Nhs.UserApi.Services.Interface/IOpenApiHttpClient.cs
new file mode 100644
index 0000000..8027c52
--- /dev/null
+++ b/LearningHub.Nhs.UserApi.Services.Interface/IOpenApiHttpClient.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.UserApi.Services.Interface
+{
+ using System.Net.Http;
+
+ ///
+ /// The IOpenApiHttpClient.
+ ///
+ public interface IOpenApiHttpClient
+ {
+ ///
+ /// The get client.
+ ///
+ ///
+ /// The .
+ ///
+ HttpClient GetClient();
+ }
+}
diff --git a/LearningHub.Nhs.UserApi.Services.UnitTests/RegistrationServiceTests.cs b/LearningHub.Nhs.UserApi.Services.UnitTests/RegistrationServiceTests.cs
index b1da4c2..36d8932 100644
--- a/LearningHub.Nhs.UserApi.Services.UnitTests/RegistrationServiceTests.cs
+++ b/LearningHub.Nhs.UserApi.Services.UnitTests/RegistrationServiceTests.cs
@@ -51,7 +51,7 @@ public async Task GetRegistrationStatus_ExistingEmail_BlueUser()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var status = await registrationService.GetRegistrationStatus("test@here.com", this.ipAddress);
Assert.IsType(status);
@@ -79,7 +79,7 @@ public async Task GetRegistrationStatus_ExistingEmail_NonBlueUser()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, userGroupRepositoryMock.Object, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, userGroupRepositoryMock.Object, null, null, null, this.countryLookupRepoMock.Object, null);
var status = await registrationService.GetRegistrationStatus("test@here.com", this.ipAddress);
Assert.IsType(status);
@@ -103,7 +103,7 @@ public async Task GetRegistrationStatus_NonExistingEmail_BlueUser()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var status = await registrationService.GetRegistrationStatus("test@here.com", this.ipAddress);
Assert.IsType(status);
@@ -127,7 +127,7 @@ public async Task GetRegistrationStatus_NonExistingEmail_NonBlueUser()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var status = await registrationService.GetRegistrationStatus("test@here.com", this.ipAddress);
Assert.IsType(status);
@@ -145,7 +145,7 @@ public async Task RegisterUser_Invalid_NoEmailOrNames()
{
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -177,7 +177,7 @@ public async Task RegisterUser_MissingRegionForEngland()
{
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -207,7 +207,7 @@ public async Task RegisterUser_MissingCountryJobRoleSpecialtyAndLocation()
{
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, null, null, null, null, null, null, null, null, null, null, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -252,7 +252,7 @@ public async Task RegisterUser_GMCFailure()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -294,7 +294,7 @@ public async Task RegisterUser_GDCFailure()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -336,7 +336,7 @@ public async Task RegisterUser_NMCFailure()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, medicalcouncilServiceMock.Object, null, null, optionsMock.Object, null, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -381,7 +381,7 @@ public async Task RegisterUser_UserAlreadyExists()
var optionsMock = new Mock>();
- var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, null, userServiceMock.Object, null, optionsMock.Object, null, medicalCouncilRepositoryMock.Object, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(null, null, jobRoleRepositoryMock.Object, null, null, null, null, null, null, null, null, null, userServiceMock.Object, null, optionsMock.Object, null, medicalCouncilRepositoryMock.Object, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
@@ -456,7 +456,7 @@ public async Task RegisterUser_Success()
var emailLogRepositoryMock = new Mock();
emailLogRepositoryMock.Setup(r => r.CreateAsync(It.IsAny(), It.IsAny()));
- var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, jobRoleRepositoryMock.Object, userUserGroupRepositoryMock.Object, userEmploymentRepositoryMock.Object, emailTemplateRepositoryMock.Object, emailLogRepositoryMock.Object, systemSettingsRepositoryMock.Object, userPasswordValidationTokenRepositoryMock.Object, tenantRepositoryMock.Object, tenantSmtpRepositoryMock.Object, null, userServiceMock.Object, userHistoryServiceMock.Object, this.GetSettings(), loginWizardServiceMock.Object, null, null, null, null, null, this.countryLookupRepoMock.Object);
+ var registrationService = new RegistrationService(userRepositoryMock.Object, userGroupTypeInputValidationRepositoryMock.Object, jobRoleRepositoryMock.Object, userUserGroupRepositoryMock.Object, userEmploymentRepositoryMock.Object, emailTemplateRepositoryMock.Object, emailLogRepositoryMock.Object, systemSettingsRepositoryMock.Object, userPasswordValidationTokenRepositoryMock.Object, tenantRepositoryMock.Object, tenantSmtpRepositoryMock.Object, null, userServiceMock.Object, userHistoryServiceMock.Object, this.GetSettings(), loginWizardServiceMock.Object, null, null, null, null, null, this.countryLookupRepoMock.Object, null);
var validationResult = await registrationService.RegisterUser(
new RegistrationRequestViewModel()
{
diff --git a/LearningHub.Nhs.UserApi.Services.UnitTests/UserServiceTests.cs b/LearningHub.Nhs.UserApi.Services.UnitTests/UserServiceTests.cs
index 7e85e6d..3f0cb64 100644
--- a/LearningHub.Nhs.UserApi.Services.UnitTests/UserServiceTests.cs
+++ b/LearningHub.Nhs.UserApi.Services.UnitTests/UserServiceTests.cs
@@ -543,6 +543,7 @@ public async Task GetUserRole_Administrator()
null,
null,
null,
+ null,
null);
var role = await userService.GetUserRoleAsync(1);
@@ -591,6 +592,7 @@ public async Task GetUserRole_BlueUser()
null,
null,
null,
+ null,
null);
var role = await userService.GetUserRoleAsync(1);
@@ -836,6 +838,7 @@ public async Task GetUserRole_none()
null,
null,
null,
+ null,
null);
var role = await userService.GetUserRoleAsync(1);
@@ -885,6 +888,7 @@ public async Task UpdateUserSecurityQuestions_Create()
null,
null,
this.NewMapper(),
+ null,
null);
await userService.UpdateUserSecurityQuestions(userSecurityQuestions, userId);
@@ -936,6 +940,7 @@ public async Task UpdateUserSecurityQuestions_CreateAndUpdate()
null,
null,
this.NewMapper(),
+ null,
null);
await userService.UpdateUserSecurityQuestions(userSecurityQuestions, userId);
@@ -977,6 +982,7 @@ public async Task InvalidateElfhUserCache_InvalidateSuccess()
this.elfhCacheSettingOptions,
elfhCacheMock.Object,
this.NewMapper(),
+ null,
null);
await userService.InvalidateElfhUserCacheAsync(123456, "test.user", CancellationToken.None);
diff --git a/LearningHub.Nhs.UserApi.Services/ElfhUserService.cs b/LearningHub.Nhs.UserApi.Services/ElfhUserService.cs
index 05fc896..b3fee9e 100644
--- a/LearningHub.Nhs.UserApi.Services/ElfhUserService.cs
+++ b/LearningHub.Nhs.UserApi.Services/ElfhUserService.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+ using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
@@ -14,6 +15,7 @@
using elfhHub.Nhs.Models.Entities;
using elfhHub.Nhs.Models.Enums;
using LearningHub.Nhs.Models.Common;
+ using LearningHub.Nhs.Models.GovNotifyMessaging;
using LearningHub.Nhs.Models.OpenAthens;
using LearningHub.Nhs.Models.Validation;
using LearningHub.Nhs.UserApi.Repository;
@@ -59,6 +61,7 @@ public class ElfhUserService : IElfhUserService
private readonly IElfhRedisCache elfhCache;
private readonly IMapper mapper;
private readonly ILogger logger;
+ private readonly IOpenApiHttpClient openApiHttpClient;
///
/// Initializes a new instance of the class.
@@ -86,6 +89,7 @@ public class ElfhUserService : IElfhUserService
/// The ELFH cache.
/// The mapper.
/// The logger.
+ /// The openApiHttpClient.
public ElfhUserService(
IElfhUserRepository elfhUserRepository,
IUserGroupRepository userGroupRepository,
@@ -109,7 +113,8 @@ public ElfhUserService(
IOptions settings,
IElfhRedisCache elfhCache,
IMapper mapper,
- ILogger logger)
+ ILogger logger,
+ IOpenApiHttpClient openApiHttpClient)
{
this.elfhUserRepository = elfhUserRepository;
this.userGroupRepository = userGroupRepository;
@@ -134,6 +139,7 @@ public ElfhUserService(
this.elfhCache = elfhCache;
this.mapper = mapper;
this.logger = logger;
+ this.openApiHttpClient = openApiHttpClient;
}
///
@@ -663,42 +669,64 @@ public async Task SendAdminPasswordResetEmail(int u
return new LearningHubValidationResult(false, $"userId {userId} not found.");
}
- // Send registration confirmation email
- /* This code was copied from the RegistrationService.RegisterUser method and tweaked for this email template.
- * The GenerateUserPasswordValidationToken method (and its child methods) are all direct copies of those found in
- * the RegistrationService. This is definitely a candidate for turning into a shared component after RR. */
var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryAdminDefault)).IntValue;
UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, userId);
await this.userPasswordValidationTokenRepository.CreateAsync(userId, userPasswordValidationToken);
- string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId)).From;
- EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.AdminPasswordValidateEmail, this.settings.Value.LearningHubTenantId);
- string bodyText = emailTemplate.Body;
- bodyText = bodyText.Replace("[FullName]", (user.FirstName + " " + user.LastName).ToTitleCase());
- bodyText = bodyText.Replace("[FirstName]", user.FirstName.ToTitleCase());
- bodyText = bodyText.Replace("[UserName]", user.UserName);
- bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
- bodyText = bodyText.Replace("[TimeLimit]", $"{expiryMinutes / 60} hours");
- bodyText = bodyText.Replace("[TenantUrl]", this.settings.Value.LearningHubUrl);
-
- Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId);
- if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
- {
- bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
- }
+ var personalisation = new Dictionary();
+ personalisation["name"] = user.FirstName;
+ personalisation["username"] = user.UserName;
+ personalisation["new password"] = userPasswordValidationToken.ValidateUrl;
- EmailLog emailLog = new EmailLog()
+ var emailRequest = new EmailRequest
{
- EmailTemplateId = emailTemplate.Id,
- FromEmailAddress = websiteEmailsFrom,
- ToUserId = userId,
- ToEmailAddress = user.EmailAddress,
- Subject = emailTemplate.Subject,
- Body = bodyText,
- TenantId = this.settings.Value.LearningHubTenantId,
- Priority = 1,
+ Recipient = user.EmailAddress,
+ TemplateId = this.settings.Value.GovNotifyTemplates.ForgottenUsernameOrPassword,
+ Personalisation = personalisation,
};
- await this.emailLogRepository.CreateAsync(userId, emailLog);
+
+ var client = this.openApiHttpClient.GetClient();
+
+ using var reqContent = new StringContent(JsonConvert.SerializeObject(emailRequest), Encoding.UTF8, "application/json");
+
+ await client.PostAsync("GovNotifyMessage/SendEmail", reqContent).ConfigureAwait(false);
+
+ ////// Send registration confirmation email
+ /////* This code was copied from the RegistrationService.RegisterUser method and tweaked for this email template.
+ //// * The GenerateUserPasswordValidationToken method (and its child methods) are all direct copies of those found in
+ //// * the RegistrationService. This is definitely a candidate for turning into a shared component after RR. */
+ ////var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryAdminDefault)).IntValue;
+ ////UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, userId);
+ ////await this.userPasswordValidationTokenRepository.CreateAsync(userId, userPasswordValidationToken);
+
+ ////string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId)).From;
+ ////EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.AdminPasswordValidateEmail, this.settings.Value.LearningHubTenantId);
+ ////string bodyText = emailTemplate.Body;
+ ////bodyText = bodyText.Replace("[FullName]", (user.FirstName + " " + user.LastName).ToTitleCase());
+ ////bodyText = bodyText.Replace("[FirstName]", user.FirstName.ToTitleCase());
+ ////bodyText = bodyText.Replace("[UserName]", user.UserName);
+ ////bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
+ ////bodyText = bodyText.Replace("[TimeLimit]", $"{expiryMinutes / 60} hours");
+ ////bodyText = bodyText.Replace("[TenantUrl]", this.settings.Value.LearningHubUrl);
+
+ ////Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId);
+ ////if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
+ ////{
+ //// bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
+ ////}
+
+ ////EmailLog emailLog = new EmailLog()
+ ////{
+ //// EmailTemplateId = emailTemplate.Id,
+ //// FromEmailAddress = websiteEmailsFrom,
+ //// ToUserId = userId,
+ //// ToEmailAddress = user.EmailAddress,
+ //// Subject = emailTemplate.Subject,
+ //// Body = bodyText,
+ //// TenantId = this.settings.Value.LearningHubTenantId,
+ //// Priority = 1,
+ ////};
+ ////await this.emailLogRepository.CreateAsync(userId, emailLog);
return new LearningHubValidationResult(true);
}
@@ -712,39 +740,61 @@ public async Task SendForgotPasswordEmail(string emailAddress)
return;
}
- // Copied from the above SendAdminPasswordResetEmail
var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryAdminDefault)).IntValue;
UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, user.Id);
await this.userPasswordValidationTokenRepository.CreateAsync(user.Id, userPasswordValidationToken);
- string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId)).From;
- EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.AdminPasswordValidateEmail, this.settings.Value.LearningHubTenantId);
- string bodyText = emailTemplate.Body;
- bodyText = bodyText.Replace("[FullName]", (user.FirstName + " " + user.LastName).ToTitleCase());
- bodyText = bodyText.Replace("[FirstName]", user.FirstName.ToTitleCase());
- bodyText = bodyText.Replace("[UserName]", user.UserName);
- bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
- bodyText = bodyText.Replace("[TimeLimit]", (expiryMinutes / 60).ToString() + " hours");
- bodyText = bodyText.Replace("[TenantUrl]", this.settings.Value.LearningHubUrl);
-
- Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId);
- if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
- {
- bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
- }
+ var personalisation = new Dictionary();
+ personalisation["name"] = user.FirstName;
+ personalisation["username"] = user.UserName;
+ personalisation["new password"] = userPasswordValidationToken.ValidateUrl;
- EmailLog emailLog = new EmailLog()
+ var emailRequest = new EmailRequest
{
- EmailTemplateId = emailTemplate.Id,
- FromEmailAddress = websiteEmailsFrom,
- ToUserId = user.Id,
- ToEmailAddress = user.EmailAddress,
- Subject = emailTemplate.Subject,
- Body = bodyText,
- TenantId = this.settings.Value.LearningHubTenantId,
- Priority = 1,
+ Recipient = user.EmailAddress,
+ TemplateId = this.settings.Value.GovNotifyTemplates.ForgottenUsernameOrPassword,
+ Personalisation = personalisation,
};
- await this.emailLogRepository.CreateAsync(user.Id, emailLog);
+
+ var client = this.openApiHttpClient.GetClient();
+
+ using var reqContent = new StringContent(JsonConvert.SerializeObject(emailRequest), Encoding.UTF8, "application/json");
+
+ await client.PostAsync("GovNotifyMessage/SendEmail", reqContent).ConfigureAwait(false);
+
+ ////// Copied from the above SendAdminPasswordResetEmail
+ ////var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryAdminDefault)).IntValue;
+ ////UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, user.Id);
+ ////await this.userPasswordValidationTokenRepository.CreateAsync(user.Id, userPasswordValidationToken);
+
+ ////string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId)).From;
+ ////EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.AdminPasswordValidateEmail, this.settings.Value.LearningHubTenantId);
+ ////string bodyText = emailTemplate.Body;
+ ////bodyText = bodyText.Replace("[FullName]", (user.FirstName + " " + user.LastName).ToTitleCase());
+ ////bodyText = bodyText.Replace("[FirstName]", user.FirstName.ToTitleCase());
+ ////bodyText = bodyText.Replace("[UserName]", user.UserName);
+ ////bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
+ ////bodyText = bodyText.Replace("[TimeLimit]", (expiryMinutes / 60).ToString() + " hours");
+ ////bodyText = bodyText.Replace("[TenantUrl]", this.settings.Value.LearningHubUrl);
+
+ ////Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.Value.LearningHubTenantId);
+ ////if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
+ ////{
+ //// bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
+ ////}
+
+ ////EmailLog emailLog = new EmailLog()
+ ////{
+ //// EmailTemplateId = emailTemplate.Id,
+ //// FromEmailAddress = websiteEmailsFrom,
+ //// ToUserId = user.Id,
+ //// ToEmailAddress = user.EmailAddress,
+ //// Subject = emailTemplate.Subject,
+ //// Body = bodyText,
+ //// TenantId = this.settings.Value.LearningHubTenantId,
+ //// Priority = 1,
+ ////};
+ ////await this.emailLogRepository.CreateAsync(user.Id, emailLog);
}
///
diff --git a/LearningHub.Nhs.UserApi.Services/OpenApiConfig.cs b/LearningHub.Nhs.UserApi.Services/OpenApiConfig.cs
new file mode 100644
index 0000000..ac3d1cf
--- /dev/null
+++ b/LearningHub.Nhs.UserApi.Services/OpenApiConfig.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.UserApi.Services
+{
+ ///
+ /// The OpenApiConfig.
+ ///
+ public class OpenApiConfig
+ {
+ ///
+ /// Gets or sets the OpenApiUrl.
+ ///
+ public string OpenApiUrl { get; set; }
+
+ ///
+ /// Gets or sets the OpenApiKey.
+ ///
+ public string OpenApiKey { get; set; }
+ }
+}
diff --git a/LearningHub.Nhs.UserApi.Services/OpenApiHttpClient.cs b/LearningHub.Nhs.UserApi.Services/OpenApiHttpClient.cs
new file mode 100644
index 0000000..c7b034c
--- /dev/null
+++ b/LearningHub.Nhs.UserApi.Services/OpenApiHttpClient.cs
@@ -0,0 +1,54 @@
+namespace LearningHub.Nhs.UserApi.Services
+{
+ using System;
+ using System.Net.Http;
+ using System.Net.Http.Headers;
+ using LearningHub.Nhs.UserApi.Services.Interface;
+ using Microsoft.Extensions.Options;
+
+ ///
+ /// The OpenApiHttpClient.
+ ///
+ public class OpenApiHttpClient : IOpenApiHttpClient
+ {
+ ///
+ /// The Http client.
+ ///
+ private readonly HttpClient client;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The config.
+ /// The client.
+ public OpenApiHttpClient(IOptions config, HttpClient client)
+ {
+ if (client == null)
+ {
+ throw new ArgumentNullException(nameof(client));
+ }
+
+ if (config == null)
+ {
+ throw new ArgumentNullException(nameof(config));
+ }
+
+ client.BaseAddress = new Uri(config.Value.OpenApiUrl);
+ client.DefaultRequestHeaders.Accept.Clear();
+ client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ client.DefaultRequestHeaders.Add("X-API-KEY", config.Value.OpenApiKey.ToString());
+ this.client = client;
+ }
+
+ ///
+ /// The get client.
+ ///
+ ///
+ /// The .
+ ///
+ public HttpClient GetClient()
+ {
+ return this.client;
+ }
+ }
+}
diff --git a/LearningHub.Nhs.UserApi.Services/RegistrationService.cs b/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
index f3dccd3..bb1084f 100644
--- a/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
+++ b/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
@@ -1,8 +1,10 @@
namespace LearningHub.Nhs.UserApi.Services
{
using System;
+ using System.Collections.Generic;
using System.Linq;
using System.Net;
+ using System.Net.Http;
using System.Net.Mail;
using System.Security.Cryptography;
using System.Text;
@@ -13,6 +15,7 @@
using elfhHub.Nhs.Models.Enums;
using elfhHub.Nhs.Models.Validation;
using LearningHub.Nhs.Models.Entities.External;
+ using LearningHub.Nhs.Models.GovNotifyMessaging;
using LearningHub.Nhs.Models.Validation;
using LearningHub.Nhs.UserApi.Repository;
using LearningHub.Nhs.UserApi.Repository.Interface;
@@ -21,6 +24,7 @@
using LearningHub.Nhs.UserApi.Services.Models;
using LearningHub.Nhs.UserApi.Shared.Configuration;
using Microsoft.Extensions.Options;
+ using Newtonsoft.Json;
///
/// The registration service.
@@ -50,6 +54,7 @@ public class RegistrationService : IRegistrationService
private readonly IEmailLogRepository emailLogRepository;
private readonly IUserGroupTypeInputValidationRepository userGroupTypeInputValidationRepository;
private readonly Settings settings;
+ private readonly IOpenApiHttpClient openApiHttpClient;
///
/// Initializes a new instance of the class.
@@ -76,6 +81,7 @@ public class RegistrationService : IRegistrationService
/// The email log repository.
/// The userGroupType Input Validation repository.
/// The settings.
+ /// The openApiHttpClient.
public RegistrationService(
IElfhUserRepository elfhUserRepository,
IUserGroupTypeInputValidationRepository userGroupTypeInputValidationRepository,
@@ -98,7 +104,8 @@ public RegistrationService(
IExternalSystemRepository externalSystemRepository,
IUserExternalSystemRepository userExternalSystemRepository,
Repository.Interface.LH.IExternalSystemUserRepository externalSystemUserRepository,
- IIpCountryLookupRepository ipCountryLookupRepository)
+ IIpCountryLookupRepository ipCountryLookupRepository,
+ IOpenApiHttpClient openApiHttpClient)
{
this.userService = userService;
this.medicalCouncilService = medicalCouncilService;
@@ -122,6 +129,7 @@ public RegistrationService(
this.userGroupTypeInputValidationRepository = userGroupTypeInputValidationRepository;
this.ipCountryLookupRepository = ipCountryLookupRepository;
this.settings = settings.Value;
+ this.openApiHttpClient = openApiHttpClient;
}
///
@@ -341,53 +349,71 @@ public async Task RegisterUser(RegistrationRequestV
if (registrationRequest.IsExternalUser == false)
{
- // Send registration confirmation email
- /* This code was duplicated in the elfhHub.Nhs.Services.UserService.SendAdminPasswordResetEmail method, but tweaked for that email template.
- * The GenerateUserPasswordValidationToken method (and its child methods) were all directly copied into the UserService. This is
- * definitely a candidate for turning into a shared component after RR. */
var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryUserDefault)).IntValue;
UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, userId);
await this.userPasswordValidationTokenRepository.CreateAsync(userId, userPasswordValidationToken);
- string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.LearningHubTenantId)).From;
- EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.SuccessEmail_New, this.settings.LearningHubTenantId);
- string bodyText = emailTemplate.Body;
- bodyText = bodyText.Replace("[FullName]", (newUser.FirstName + " " + newUser.LastName).ToTitleCase());
- bodyText = bodyText.Replace("[FirstName]", newUser.FirstName.ToTitleCase());
- bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
- string resetUrl = this.settings.LearningHubUrl + userPasswordValidationToken.HashedToken;
- //// emailTemplate.Body = emailTemplate.Body.Replace("[LHValidateURL]", resetUrl);
-
- bodyText = bodyText.Replace("[TimeLimit]", GenericHelper.GetPasswordTimeoutString(expiryMinutes));
- bodyText = bodyText.Replace("[ResetPasswordUrl]", userPasswordValidationToken.PasswordResetUrl);
- bodyText = bodyText.Replace("[LogInUrl]", userPasswordValidationToken.LogOnUrl);
- bodyText = bodyText.Replace("[UserName]", newUser.UserName);
- bodyText = bodyText.Replace("[TenantUrl]", this.settings.LearningHubUrl);
-
- Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.LearningHubTenantId);
- bodyText = bodyText.Replace("[TenantUrl]", this.settings.LearningHubUrl);
- if (!string.IsNullOrEmpty(tenant.QuickStartGuideUrl))
- {
- bodyText = bodyText.Replace("[QuickStartGuideUrl]", tenant.QuickStartGuideUrl);
- }
-
- if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
- {
- bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
- }
+ var personalisation = new Dictionary();
+ personalisation["name"] = newUser.FirstName;
+ personalisation["username"] = newUser.UserName;
+ personalisation["password"] = userPasswordValidationToken.ValidateUrl;
- EmailLog emailLog = new EmailLog()
+ var emailRequest = new EmailRequest
{
- EmailTemplateId = emailTemplate.Id,
- FromEmailAddress = websiteEmailsFrom,
- ToUserId = userId,
- ToEmailAddress = registrationRequest.EmailAddress,
- Subject = emailTemplate.Subject,
- Body = bodyText,
- TenantId = this.settings.LearningHubTenantId,
- Priority = 1,
+ Recipient = registrationRequest.EmailAddress,
+ TemplateId = this.settings.GovNotifyTemplates.NHSLearningHubRegistration,
+ Personalisation = personalisation,
};
- await this.emailLogRepository.CreateAsync(userId, emailLog);
+
+ var client = this.openApiHttpClient.GetClient();
+
+ using var reqContent = new StringContent(JsonConvert.SerializeObject(emailRequest), Encoding.UTF8, "application/json");
+
+ await client.PostAsync("GovNotifyMessage/SendEmail", reqContent).ConfigureAwait(false);
+
+ ////var expiryMinutes = (int)(await this.systemSettingRepository.GetByIdAsync((int)SystemSettingEnum.PasswordValidationExpiryUserDefault)).IntValue;
+ ////UserPasswordValidationTokenExtended userPasswordValidationToken = this.GenerateUserPasswordValidationToken(expiryMinutes, userId);
+ ////await this.userPasswordValidationTokenRepository.CreateAsync(userId, userPasswordValidationToken);
+
+ ////string websiteEmailsFrom = (await this.tenantSmtpRepository.GetByIdAsync(this.settings.LearningHubTenantId)).From;
+ ////EmailTemplate emailTemplate = await this.emailTemplateRepository.GetByTypeAndTenantAsync((int)EmailTemplateTypeEnum.SuccessEmail_New, this.settings.LearningHubTenantId);
+ ////string bodyText = emailTemplate.Body;
+ ////bodyText = bodyText.Replace("[FullName]", (newUser.FirstName + " " + newUser.LastName).ToTitleCase());
+ ////bodyText = bodyText.Replace("[FirstName]", newUser.FirstName.ToTitleCase());
+ ////bodyText = bodyText.Replace("[PasswordValidateUrl]", userPasswordValidationToken.ValidateUrl);
+ ////string resetUrl = this.settings.LearningHubUrl + userPasswordValidationToken.HashedToken;
+ ////// emailTemplate.Body = emailTemplate.Body.Replace("[LHValidateURL]", resetUrl);
+
+ ////bodyText = bodyText.Replace("[TimeLimit]", GenericHelper.GetPasswordTimeoutString(expiryMinutes));
+ ////bodyText = bodyText.Replace("[ResetPasswordUrl]", userPasswordValidationToken.PasswordResetUrl);
+ ////bodyText = bodyText.Replace("[LogInUrl]", userPasswordValidationToken.LogOnUrl);
+ ////bodyText = bodyText.Replace("[UserName]", newUser.UserName);
+ ////bodyText = bodyText.Replace("[TenantUrl]", this.settings.LearningHubUrl);
+
+ ////Tenant tenant = await this.tenantRepository.GetByIdAsync(this.settings.LearningHubTenantId);
+ ////bodyText = bodyText.Replace("[TenantUrl]", this.settings.LearningHubUrl);
+ ////if (!string.IsNullOrEmpty(tenant.QuickStartGuideUrl))
+ ////{
+ //// bodyText = bodyText.Replace("[QuickStartGuideUrl]", tenant.QuickStartGuideUrl);
+ ////}
+
+ ////if (!string.IsNullOrEmpty(tenant.SupportFormUrl))
+ ////{
+ //// bodyText = bodyText.Replace("[SupportFormUrl]", tenant.SupportFormUrl);
+ ////}
+
+ ////EmailLog emailLog = new EmailLog()
+ ////{
+ //// EmailTemplateId = emailTemplate.Id,
+ //// FromEmailAddress = websiteEmailsFrom,
+ //// ToUserId = userId,
+ //// ToEmailAddress = registrationRequest.EmailAddress,
+ //// Subject = emailTemplate.Subject,
+ //// Body = bodyText,
+ //// TenantId = this.settings.LearningHubTenantId,
+ //// Priority = 1,
+ ////};
+ ////await this.emailLogRepository.CreateAsync(userId, emailLog);
}
}
diff --git a/LearningHub.Nhs.UserApi.Shared/Configuration/GovNotifyTemplates.cs b/LearningHub.Nhs.UserApi.Shared/Configuration/GovNotifyTemplates.cs
new file mode 100644
index 0000000..9166666
--- /dev/null
+++ b/LearningHub.Nhs.UserApi.Shared/Configuration/GovNotifyTemplates.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.UserApi.Shared.Configuration
+{
+ ///
+ /// GovNotifyTemplates.
+ ///
+ public class GovNotifyTemplates
+ {
+ ///
+ /// Gets or sets the ForgottenUsernameOrPassword ID.
+ ///
+ public string ForgottenUsernameOrPassword { get; set; }
+
+ ///
+ /// Gets or sets the NHSLearningHubRegistration ID.
+ ///
+ public string NHSLearningHubRegistration { get; set; }
+ }
+}
diff --git a/LearningHub.Nhs.UserApi.Shared/Configuration/Settings.cs b/LearningHub.Nhs.UserApi.Shared/Configuration/Settings.cs
index b2a9c1b..ca4bf53 100644
--- a/LearningHub.Nhs.UserApi.Shared/Configuration/Settings.cs
+++ b/LearningHub.Nhs.UserApi.Shared/Configuration/Settings.cs
@@ -49,5 +49,10 @@ public class Settings
/// Gets or sets the security questions required.
///
public int SecurityQuestionsRequired { get; set; }
+
+ ///
+ /// Gets or sets the GovNotifyTemplates.
+ ///
+ public GovNotifyTemplates GovNotifyTemplates { get; set; }
}
}
diff --git a/LearningHub.Nhs.UserApi/Program.cs b/LearningHub.Nhs.UserApi/Program.cs
index c82ae49..d560f0e 100644
--- a/LearningHub.Nhs.UserApi/Program.cs
+++ b/LearningHub.Nhs.UserApi/Program.cs
@@ -22,7 +22,7 @@
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.Host.UseNLog();
- builder.Services.ConfigureServices(builder.Configuration);
+ builder.Services.ConfigureServices(builder.Configuration, builder.Environment);
var app = builder.Build();
diff --git a/LearningHub.Nhs.UserApi/ServiceCollectionExtension.cs b/LearningHub.Nhs.UserApi/ServiceCollectionExtension.cs
index c4bc100..696a582 100644
--- a/LearningHub.Nhs.UserApi/ServiceCollectionExtension.cs
+++ b/LearningHub.Nhs.UserApi/ServiceCollectionExtension.cs
@@ -9,6 +9,7 @@
using LearningHub.Nhs.UserApi.Services;
using LearningHub.Nhs.UserApi.Services.Interface;
using LearningHub.Nhs.UserApi.Shared.Configuration;
+ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@@ -24,13 +25,14 @@ public static class ServiceCollectionExtension
///
/// IServiceCollection.
/// IConfiguration.
- public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration)
+ /// IWebHostEnvironment.
+ public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment env)
{
services.AddOptions();
services.AddApplicationInsightsTelemetry();
- services.AddMappings(configuration);
+ services.AddMappings(configuration, env);
services.Configure(configuration.GetSection("Settings"));
diff --git a/LearningHub.Nhs.UserApi/ServiceMappings.cs b/LearningHub.Nhs.UserApi/ServiceMappings.cs
index b7cd803..bbdba5f 100644
--- a/LearningHub.Nhs.UserApi/ServiceMappings.cs
+++ b/LearningHub.Nhs.UserApi/ServiceMappings.cs
@@ -1,5 +1,6 @@
namespace LearningHub.Nhs.UserApi
{
+ using System.Net.Http;
using AutoMapper;
using elfhHub.Nhs.Models.Automapper;
using IdentityServer4.AccessTokenValidation;
@@ -11,9 +12,11 @@ namespace LearningHub.Nhs.UserApi
using LearningHub.Nhs.UserApi.Services.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
+ using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using ElfhMap = LearningHub.Nhs.UserApi.Repository.ElfhMap;
using LHMap = LearningHub.Nhs.UserApi.Repository.LHMap;
@@ -28,13 +31,14 @@ public static class ServiceMappings
///
/// The services.
/// The configuration.
- public static void AddMappings(this IServiceCollection services, IConfiguration configuration)
+ /// The IWebHostEnvironment.
+ public static void AddMappings(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment env)
{
services.AddLearningHubDBMappings(configuration);
services.AddElfhDBMappings(configuration);
- services.AddServices();
+ services.AddServices(configuration, env);
services.AddAuthentication(configuration);
@@ -169,7 +173,7 @@ private static void AddLearningHubDBMappings(this IServiceCollection services, I
services.AddScoped();
}
- private static void AddServices(this IServiceCollection services)
+ private static void AddServices(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment env)
{
services.AddScoped();
services.AddScoped();
@@ -195,6 +199,22 @@ private static void AddServices(this IServiceCollection services)
services.AddScoped();
services.AddScoped();
services.AddScoped();
+
+ services.Configure(configuration.GetSection("OpenApiConfig"));
+ if (env.IsDevelopment())
+ {
+ services.AddHttpClient()
+ .ConfigurePrimaryHttpMessageHandler(
+ () => new HttpClientHandler
+ {
+ ServerCertificateCustomValidationCallback =
+ HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
+ });
+ }
+ else
+ {
+ services.AddHttpClient();
+ }
}
private static void AddAuthentication(this IServiceCollection services, IConfiguration configuration)
diff --git a/LearningHub.Nhs.UserApi/appsettings.json b/LearningHub.Nhs.UserApi/appsettings.json
index 00f0cc4..f7fce96 100644
--- a/LearningHub.Nhs.UserApi/appsettings.json
+++ b/LearningHub.Nhs.UserApi/appsettings.json
@@ -36,6 +36,14 @@
"ElfhUserLoadByUserIdKey": "",
"ElfhUserLoadByUserNameKey": ""
},
- "SecurityQuestionsRequired": 2
+ "SecurityQuestionsRequired": 2,
+ "GovNotifyTemplates": {
+ "ForgottenUsernameOrPassword": "",
+ "NHSLearningHubRegistration": ""
+ }
+ },
+ "OpenApiConfig": {
+ "OpenApiUrl": "",
+ "OpenApiKey": ""
}
}
\ No newline at end of file