using e_suite.API.Common.exceptions; using e_suite.API.Common.models; using e_suite.Database.Core.Tables.Domain; using e_suite.Database.Core.Tables.UserManager; using eSuite.Core.MailService; using Moq; using NUnit.Framework; using UserManager.UnitTests.Helpers; namespace UserManager.UnitTests.UserManager; [TestFixture] public class UpdateProfileUnitTests : UserManagerTestBase { [SetUp] public override async Task Setup() { await base.Setup(); } [Test] public async Task UpdateProfile_UpdatesMade_SavesChanges() { //Arrange const string existingEmail = "testuser@sun-strategy.com"; var existingUser = new User { Id = 12, Email = existingEmail }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { FirstName = "James", MiddleNames = "Tiberius", LastName = "Kirk", UsingTwoFactorAuthentication = true, Email = "james.t.kirk@enterprise.uss.fed" }; //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.Email, Is.Not.EqualTo(existingEmail)); Assert.That(alteredProfile?.Email, Is.EqualTo(updatedProfile.Email)); } [Test] public async Task UpdateProfile_NewPasswordSupplied_HashesNewPassword() { //Arrange const string existingEmail = "testuser@sun-strategy.com"; var existingUser = new User { Id = 12, Email = existingEmail, EmailConfirmed = true }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = existingEmail, Password = "This is my new password", }; var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3"; CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny(), It.IsAny())) .Returns(hashedPassword); //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.Password, Is.EqualTo(hashedPassword)); MailServiceMock.Verify( x => x.RequestEMailAsync( It.IsAny(), It.IsAny() ), Times.Once); } [Test] public async Task UpdateProfile_NewEmailExists_ThrowsError() { //Arrange const string existingEmail = "testuser@sun-strategy.com"; var existingUser = new User { Id = 12, Email = existingEmail, Domain = new Domain { Name = "TestDomain" } }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); const string existing2Email = "testuser2@sun-strategy.com"; var existingUser2 = new User { Id = 13, Email = existing2Email }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser2, default); var testProfile = await UserManager.GetProfile(existingUser.Email); var updatedProfile = new UpdatedUserProfile { Email = existing2Email }; //Act & Assert Assert.ThrowsAsync(async () => { await UserManager.UpdateProfile(AuditUserDetails, existingEmail, updatedProfile); }); } [Test] public async Task UpdateProfile_DisablingTFA_DisablesTFAAndChangesKey() { //Arrange var existingUser = new User { Id = 12, Email = "testuser@sun-strategy.com", UsingTwoFactorAuthentication = true, TwoFactorAuthenticationKey = "FirstKey" }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var newTwoFactorAuthenticationKey = "SecondKey"; RandomNumberGeneratorMock.Setup(x => x.GetRandomString(It.IsAny())) .Returns(newTwoFactorAuthenticationKey); var updatedProfile = new UpdatedUserProfile { Email = existingUser.Email, UsingTwoFactorAuthentication = false }; //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.UsingTwoFactorAuthentication, Is.False); Assert.That(alteredProfile?.TwoFactorAuthenticationKey, Is.EqualTo(newTwoFactorAuthenticationKey)); } [Test] public async Task UpdateProfile_EnablingTFANoSecurityCode_DoesNotEnableTFA() { //Arrange var existingUser = new User { Id = 12, Email = "testuser@sun-strategy.com", UsingTwoFactorAuthentication = false, TwoFactorAuthenticationKey = "FirstKey" }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = existingUser.Email, UsingTwoFactorAuthentication = true }; //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.UsingTwoFactorAuthentication, Is.False); TwoFactorAuthenticatorMock.Verify(x => x.ValidateTwoFactorPIN(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task UpdateProfile_EnablingTFAIncorrectSecurityCode_DoesNotEnableTFA() { //Arrange var existingUser = new User { Id = 12, Email = "testuser@sun-strategy.com", UsingTwoFactorAuthentication = false, TwoFactorAuthenticationKey = "FirstKey" }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = existingUser.Email, UsingTwoFactorAuthentication = true, SecurityCode = "12345" }; TwoFactorAuthenticatorMock.Setup(x => x.ValidateTwoFactorPIN(It.IsAny(), updatedProfile.SecurityCode, It.IsAny())).Returns(false); //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.UsingTwoFactorAuthentication, Is.False); TwoFactorAuthenticatorMock.Verify(x => x.ValidateTwoFactorPIN(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [Test] public async Task UpdateProfile_EnablingTFACorrectSecurityCode_EnablesTFA() { //Arrange var existingUser = new User { Id = 12, Email = "testuser@sun-strategy.com", UsingTwoFactorAuthentication = false, TwoFactorAuthenticationKey = "FirstKey" }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = existingUser.Email, UsingTwoFactorAuthentication = true, SecurityCode = "12345" }; TwoFactorAuthenticatorMock.Setup(x => x.ValidateTwoFactorPIN(It.IsAny(), updatedProfile.SecurityCode, It.IsAny())).Returns(true); //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.UsingTwoFactorAuthentication, Is.True); TwoFactorAuthenticatorMock.Verify(x => x.ValidateTwoFactorPIN(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [Test] public async Task UpdateProfile_WhenEmailIsEmpty_DoesNotAttemptToChangeEmailAddress() { //Arrange var existingUser = new User { Id = 13, Email = "testuser@sun-strategy.com", EmailConfirmed = true }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = string.Empty }; TwoFactorAuthenticatorMock.Setup(x => x.ValidateTwoFactorPIN(It.IsAny(), updatedProfile.SecurityCode, It.IsAny())).Returns(true); //Act await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile); //Assert var alteredProfile = UserManagerRepository.Users.SingleOrDefault(x => x.Id == existingUser.Id); Assert.That(alteredProfile?.EmailConfirmed, Is.True); } [Test] public async Task UpdateProfile_WhenEmailIsNotValid_ThrowsExpectedException() { //Arrange var existingUser = new User { Id = 13, Email = "testuser@sun-strategy.com", EmailConfirmed = true }; await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default); var updatedProfile = new UpdatedUserProfile { Email = "invalid at invalid dot invalid" }; TwoFactorAuthenticatorMock.Setup(x => x.ValidateTwoFactorPIN(It.IsAny(), updatedProfile.SecurityCode, It.IsAny())).Returns(true); //Act & Assert Assert.ThrowsAsync(async () => await UserManager.UpdateProfile(AuditUserDetails, existingUser.Email, updatedProfile)); } }