Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,10 @@ public void UpdateDelegateUsers_updates_users()
const string firstName = "TestFirstName";
const string lastName = "TestLastName";
const string email = "test@email.com";
const string professionalRegNumber = "test-1234";

// When
userDataService.UpdateDelegateUsers(firstName, lastName, email, null, new[] { 2, 3 });
userDataService.UpdateDelegateUsers(firstName, lastName, email, null, professionalRegNumber, true, new[] { 2, 3 });
var updatedUser = userDataService.GetDelegateUserById(2)!;
var secondUpdatedUser = userDataService.GetDelegateUserById(3)!;

Expand Down
32 changes: 22 additions & 10 deletions DigitalLearningSolutions.Data.Tests/Services/UserServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,17 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_null_delegate_only_
var firstName = "TestFirstName";
var lastName = "TestLastName";
var email = "test@email.com";
var professionalRegNumber = "test-1234";
var accountDetailsData =
new MyAccountDetailsData(adminUser.Id, null, password, firstName, lastName, email, null);
new MyAccountDetailsData(adminUser.Id,
null,
password,
firstName,
lastName,
email,
professionalRegNumber,
true,
null);

A.CallTo(() => userDataService.GetAdminUserById(adminUser.Id)).Returns(adminUser);
A.CallTo(() => userDataService.GetAdminUserByEmailAddress(adminUser.EmailAddress!)).Returns(adminUser);
Expand All @@ -239,7 +248,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_null_delegate_only_
// Then
A.CallTo(() => userDataService.UpdateAdminUser(A<string>._, A<string>._, A<string>._, null, A<int>._))
.MustHaveHappened();
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<string>._, A<bool>._, A<int[]>._))
.MustNotHaveHappened();
A.CallTo(() => userDataService.GetDelegateUserById(A<int>._)).MustNotHaveHappened();
}
Expand All @@ -253,8 +262,9 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_null_admin_only_upd
var firstName = "TestFirstName";
var lastName = "TestLastName";
var email = "test@email.com";
var professionalRegNumber = "123-number";
var accountDetailsData =
new MyAccountDetailsData(null, delegateUser.Id, password, firstName, lastName, email, null);
new MyAccountDetailsData(null, delegateUser.Id, password, firstName, lastName, email, professionalRegNumber, true, null);
var centreAnswersData = new CentreAnswersData(2, 1, null, null, null, null, null, null);

A.CallTo(() => userDataService.GetDelegateUserById(delegateUser.Id)).Returns(delegateUser);
Expand All @@ -263,7 +273,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_null_admin_only_upd
.Returns(new List<DelegateUser> { delegateUser });
A.CallTo(() => userVerificationService.VerifyUsers(password, A<AdminUser?>._, A<List<DelegateUser>>._))
.Returns(new UserAccountSet(null, new List<DelegateUser> { delegateUser }));
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<string>._, A<bool>._, A<int[]>._))
.DoesNothing();
A.CallTo(
() => groupsService.SynchroniseUserChangesWithGroups(
Expand All @@ -277,7 +287,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_null_admin_only_upd
userService.UpdateUserAccountDetailsForAllVerifiedUsers(accountDetailsData, centreAnswersData);

// Then
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<string>._, A<bool>._, A<int[]>._))
.MustHaveHappened();
A.CallTo(() => userDataService.UpdateAdminUser(A<string>._, A<string>._, A<string>._, null, A<int>._))
.MustNotHaveHappened();
Expand All @@ -304,8 +314,9 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_both_admin_and_dele
var firstName = "TestFirstName";
var lastName = "TestLastName";
var email = "test@email.com";
var professionalRegNumber = "test-1234";
var accountDetailsData =
new MyAccountDetailsData(adminUser.Id, delegateUser.Id, password, firstName, lastName, email, null);
new MyAccountDetailsData(adminUser.Id, delegateUser.Id, password, firstName, lastName, email, professionalRegNumber, true, null);
var centreAnswersData = new CentreAnswersData(2, 1, null, null, null, null, null, null);

A.CallTo(() => userDataService.GetAdminUserById(adminUser.Id)).Returns(adminUser);
Expand All @@ -317,7 +328,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_both_admin_and_dele
.Returns(
new UserAccountSet(adminUser, new List<DelegateUser> { delegateUser })
);
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null,A<string>._, A<bool>._, A<int[]>._))
.DoesNothing();
A.CallTo(() => userDataService.UpdateAdminUser(A<string>._, A<string>._, A<string>._, null, A<int>._))
.DoesNothing();
Expand All @@ -333,7 +344,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_both_admin_and_dele
userService.UpdateUserAccountDetailsForAllVerifiedUsers(accountDetailsData, centreAnswersData);

// Then
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<string>._, A<bool>._, A<int[]>._))
.MustHaveHappened();
A.CallTo(() => userDataService.UpdateAdminUser(A<string>._, A<string>._, A<string>._, null, A<int>._))
.MustHaveHappened();
Expand All @@ -359,8 +370,9 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_incorrect_password_
var firstName = "TestFirstName";
var lastName = "TestLastName";
var email = "test@email.com";
var professionalRegNumber = "test-1234";
var accountDetailsData =
new MyAccountDetailsData(adminUser.Id, delegateUser.Id, password, firstName, lastName, email, null);
new MyAccountDetailsData(adminUser.Id, delegateUser.Id, password, firstName, lastName, email, professionalRegNumber, true, null);
var centreAnswersData = new CentreAnswersData(2, 1, null, null, null, null, null, null);

A.CallTo(() => userDataService.GetAdminUserById(adminUser.Id)).Returns(adminUser);
Expand All @@ -382,7 +394,7 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers_with_incorrect_password_
userService.UpdateUserAccountDetailsForAllVerifiedUsers(accountDetailsData, centreAnswersData);

// Then
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<int[]>._))
A.CallTo(() => userDataService.UpdateDelegateUsers(A<string>._, A<string>._, A<string>._, null, A<string>._, A<bool>._, A<int[]>._))
.MustNotHaveHappened();
A.CallTo(() => userDataService.UpdateAdminUser(A<string>._, A<string>._, A<string>._, null, A<int>._))
.MustNotHaveHappened();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ public static MyAccountDetailsData GetDefaultAccountDetailsData(
firstName,
surname,
email,
null,
true,
profileImage
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,26 @@ FROM Candidates AS cd
return users;
}

public void UpdateDelegateUsers(string firstName, string surname, string email, byte[]? profileImage, int[] ids)
public void UpdateDelegateUsers(
string firstName,
string surname,
string email,
byte[]? profileImage,
string? professionalRegNumber,
bool hasBeenPromptedForPrn,
int[] ids)
{
connection.Execute(
@"UPDATE Candidates
SET
FirstName = @firstName,
LastName = @surname,
EmailAddress = @email,
ProfileImage = @profileImage
ProfileImage = @profileImage,
ProfessionalRegistrationNumber = @professionalRegNumber,
HasBeenPromptedForPrn = @hasBeenPromptedForPrn
WHERE CandidateID in @ids",
new { firstName, surname, email, profileImage, ids }
new { firstName, surname, email, profileImage, ids, professionalRegNumber, hasBeenPromptedForPrn }
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ void UpdateDelegateUsers(
string surname,
string email,
byte[]? profileImage,
int[] ids
);
string? professionalRegNumber,
bool hasBeenPromptedForPrn,
int[] ids);

void UpdateDelegate(
int delegateId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@ public MyAccountDetailsData(
string firstName,
string surname,
string email,
string? professionalRegNumber,
bool hasBeenPromptedForPrn,
byte[]? profileImage
) : base(firstName, surname, email)
{
AdminId = adminId;
DelegateId = delegateId;
Password = password;

ProfessionalRegistrationNumber = professionalRegNumber;
HasBeenPromptedForPrn = hasBeenPromptedForPrn;
ProfileImage = profileImage;
}

public int? AdminId { get; set; }
public int? DelegateId { get; set; }
public string Password { get; set; }
public byte[]? ProfileImage { get; set; }
public string? ProfessionalRegistrationNumber { get; set; }
public bool HasBeenPromptedForPrn { get; set; }
}
}
2 changes: 2 additions & 0 deletions DigitalLearningSolutions.Data/Services/UserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ public void UpdateUserAccountDetailsForAllVerifiedUsers(
myAccountDetailsData.Surname,
myAccountDetailsData.Email,
myAccountDetailsData.ProfileImage,
myAccountDetailsData.ProfessionalRegistrationNumber,
myAccountDetailsData.HasBeenPromptedForPrn,
delegateIds
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
namespace DigitalLearningSolutions.Web.Tests.Helpers
{
using System.Linq;
using DigitalLearningSolutions.Web.Helpers;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using NUnit.Framework;

public class ProfessionalRegistrationNumberHelperTests
{
[TestCase(null)]
[TestCase(false)]
public void GetHasProfessionalRegistrationNumberForView_returns_null_when_has_not_been_prompted(
bool? hasBeenPromptedForPrn
)
{
// When
var result =
ProfessionalRegistrationNumberHelper.GetHasProfessionalRegistrationNumberForView(
hasBeenPromptedForPrn,
"prn"
);

// Then
result.Should().BeNull();
}

[Test]
public void GetHasProfessionalRegistrationNumberForView_returns_false_when_has_been_prompted_and_no_prn()
{
// When
var result =
ProfessionalRegistrationNumberHelper.GetHasProfessionalRegistrationNumberForView(true, null);

// Then
result.Should().BeFalse();
}

[Test]
public void GetHasProfessionalRegistrationNumberForView_returns_true_when_has_been_prompted_and_has_prn()
{
// When
var result =
ProfessionalRegistrationNumberHelper.GetHasProfessionalRegistrationNumberForView(true, "prn-12");

// Then
result.Should().BeTrue();
}

[TestCase(true, false)]
[TestCase(false, true)]
public void ValidateProfessionalRegistrationNumber_does_not_set_errors_when_not_delegate_or_has_no_prn(
bool isDelegate,
bool hasPrn
)
{
// Given
var state = new ModelStateDictionary();

// When
ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
state,
hasPrn,
null,
isDelegate
);

// Then
state.IsValid.Should().BeTrue();
}

[Test]
public void ValidateProfessionalRegistrationNumber_does_not_set_errors_when_valid_prn()
{
// Given
var state = new ModelStateDictionary();
const string validPrn = "abc-123";

// When
ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
state,
true,
validPrn
);

// Then
state.IsValid.Should().BeTrue();
}

[Test]
public void ValidateProfessionalRegistrationNumber_sets_error_when_hasPrn_is_not_set()
{
// Given
var state = new ModelStateDictionary();

// When
ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
state,
null,
null
);

// Then
using (new AssertionScope())
{
state.IsValid.Should().BeFalse();
state.Values.First().Errors.Should().OnlyContain(e => e.ErrorMessage == "Select your professional registration number status.");
}
}

[TestCase(null, "Enter professional registration number.")]
[TestCase("", "Enter professional registration number.")]
[TestCase("123", "Professional registration number must be between 5 and 20 characters.")]
[TestCase("0123456789-0123456789", "Professional registration number must be between 5 and 20 characters.")]
[TestCase(
"01234_",
"Invalid professional registration number format. Only alphanumeric (a-z, A-Z and 0-9) and hyphens (-) allowed."
)]
[TestCase(
"01234 ",
"Invalid professional registration number format. Only alphanumeric (a-z, A-Z and 0-9) and hyphens (-) allowed."
)]
[TestCase(
"01234$",
"Invalid professional registration number format. Only alphanumeric (a-z, A-Z and 0-9) and hyphens (-) allowed."
)]
public void ValidateProfessionalRegistrationNumber_sets_error_when_prn_is_invalid(
string prn,
string expectedError
)
{
// Given
var state = new ModelStateDictionary();

// When
ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
state,
true,
prn
);

// Then
using (new AssertionScope())
{
state.IsValid.Should().BeFalse();
state.Values.First().Errors.Should().OnlyContain(e => e.ErrorMessage == expectedError);
}
}
}
}
10 changes: 8 additions & 2 deletions DigitalLearningSolutions.Web/Controllers/MyAccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using DigitalLearningSolutions.Web.Helpers;
using DigitalLearningSolutions.Web.Models.Enums;
using DigitalLearningSolutions.Web.ServiceFilter;
using DigitalLearningSolutions.Web.ViewModels.Common;
using DigitalLearningSolutions.Web.ViewModels.MyAccount;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -131,6 +130,13 @@ DlsSubApplication dlsSubApplication
);
}

ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
ModelState,
formData.HasProfessionalRegistrationNumber,
formData.ProfessionalRegistrationNumber,
userDelegateId.HasValue
);

if (!ModelState.IsValid)
{
return ReturnToEditDetailsViewWithErrors(formData, dlsSubApplication, userDelegateId);
Expand All @@ -139,7 +145,7 @@ DlsSubApplication dlsSubApplication
if (!userService.NewEmailAddressIsValid(formData.Email!, userAdminId, userDelegateId, User.GetCentreId()))
{
ModelState.AddModelError(
nameof(EditDetailsFormData.Email),
nameof(MyAccountEditDetailsFormData.Email),
"A user with this email address is already registered at this centre"
);
return ReturnToEditDetailsViewWithErrors(formData, dlsSubApplication, userDelegateId);
Expand Down
Loading