Backend/e-suite.Modules.UserManager/UserManager.UnitTests/UserManager/LoginUnitTests.cs

345 lines
12 KiB
C#

using e_suite.API.Common.models;
using e_suite.Database.Core.Models;
using e_suite.Database.Core.Tables.UserManager;
using e_suite.Nuget.PasswordHasher;
using eSuite.Core.MailService;
using Microsoft.AspNetCore.Identity;
using Moq;
using NUnit.Framework;
using UserManager.UnitTests.Helpers;
namespace UserManager.UnitTests.UserManager;
[TestFixture]
public class LoginUnitTests : UserManagerTestBase<object>
{
[SetUp]
public override async Task Setup()
{
await base.Setup();
}
[Test]
public async Task Login_UserNotFound_ReturnsFailed()
{
//Arrange
var login = new Login
{
Email = "fred@bloggs.com" //User does not exist in fake database.
};
//Act
var result = await UserManager.Login(login);
//Assert
Assert.That(result.Result, Is.EqualTo(LoginResult.Failed));
}
[Test]
public async Task Login_VerifyHashedPasswordFails_ReturnsNull()
{
//Arrange
var existingUser = new User
{
Id = 15,
Email = "testuser@sun-strategy.com",
Password = "testing",
EmailConfirmed = true
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Failed);
//Act
var result = await UserManager.Login(login);
//Assert
CustomPasswordHasherMock.Verify(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password), Times.Once);
Assert.That(result.Result, Is.EqualTo(LoginResult.Failed));
}
[Test]
public async Task Login_VerifyHashedPasswordMatches_ReturnsSuccess()
{
//Arrange
var existingUser = new User
{
Id = 15,
Email = "testuser@sun-strategy.com",
Password = "testing",
EmailConfirmed = true
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
//Act
var result = await UserManager.Login(login);
//Assert
CustomPasswordHasherMock.Verify(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password), Times.Once);
CustomPasswordHasherMock.Verify(x => x.HashPassword(It.IsAny<IPassword>(), login.Password), Times.Never);
Assert.That(result.Result, Is.EqualTo(LoginResult.Success));
Assert.That(result.Token, Is.Not.Empty);
}
[Test]
public async Task Login_VerifyHashedPasswordRequestsRehash_ReturnsSuccessAndRehashesPassword()
{
//Arrange
var existingUser = new User
{
Id = 14,
Email = "testuser@sun-strategy.com",
Password = "testing",
EmailConfirmed = true
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing"
};
var newHashedPassword = "123456";
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.SuccessRehashNeeded);
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<IPassword>(), login.Password)).Returns(newHashedPassword);
//Act
var result = await UserManager.Login(login);
//Assert
CustomPasswordHasherMock.Verify(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password), Times.Once);
CustomPasswordHasherMock.Verify(x => x.HashPassword(It.IsAny<IPassword>(), login.Password), Times.Once);
Assert.That(result.Result, Is.EqualTo(LoginResult.Success));
Assert.That(result.Token, Is.Not.Empty);
}
[Test]
public async Task Login_EmailNotConfirmed_ReturnsError()
{
//Arrange
var existingUser = new User
{
Id = 16,
Email = "testuser2@sun-strategy.com",
Password = "testing",
EmailConfirmed = false
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
//Act
var result = await UserManager.Login(login);
//Assert
Assert.That(result.Result, Is.EqualTo(LoginResult.EmailNotConfirmed));
}
[Test]
public async Task Login_RequestTfaDisable_ReturnsTwoFactorAuthenticationRemovalRequested()
{
//Arrange
var existingUser = new User
{
Id = 16,
Email = "testuser3@sun-strategy.com",
Password = "testing",
EmailConfirmed = true,
UsingTwoFactorAuthentication = true,
FirstName = "Test3",
LastName = "User"
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing",
RequestTfaRemoval = true
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
MailRequest actualMailRequest = null!;
MailServiceMock.Setup(x => x.RequestEMailAsync(It.IsAny<MailRequest>(), It.IsAny<CancellationToken>()))
.Callback<MailRequest, CancellationToken>((mailRequest, cancellationToken) => { actualMailRequest = mailRequest; });
//Act
var result = await UserManager.Login(login);
//Assert that the new row was added to the database correctly.
var emailUserAction = UserManagerRepository.EmailUserActions.SingleOrDefault(x => x.User.Email == login.Email);
Assert.That(emailUserAction, Is.Not.Null);
Assert.That(emailUserAction?.EmailActionType, Is.EqualTo(EmailUserActionType.DisableAuthenticator));
Assert.That(emailUserAction?.User.Email, Is.EqualTo(login.Email));
Assert.That(emailUserAction?.Token, Is.Not.Empty);
//Assert that the e-mail request was sent.
MailServiceMock.Verify(x => x.RequestEMailAsync(It.IsAny<MailRequest>(), It.IsAny<CancellationToken>()), Times.Once);
Assert.That(actualMailRequest, Is.Not.Null);
Assert.That(actualMailRequest.EmailType, Is.EqualTo(MailType.DisableAuthenticator));
Assert.That(actualMailRequest.To.Count, Is.EqualTo(1));
Assert.That(actualMailRequest.To[0].DisplayName, Is.EqualTo(existingUser.DisplayName));
Assert.That(actualMailRequest.To[0].Email, Is.EqualTo(login.Email));
Assert.That(actualMailRequest.Parameters.Count, Is.EqualTo(1));
Assert.That(actualMailRequest.Parameters["url"], Is.Not.Empty);
Assert.That(result.Result, Is.EqualTo(LoginResult.TwoFactorAuthenticationRemovalRequested));
}
[Test]
public async Task Login_TfaEnabledButCodeNotProvided_ReturnsTwoFactorAuthenticationCodeRequired()
{
//Arrange
var existingUser = new User
{
Id = 16,
Email = "testuser3@sun-strategy.com",
Password = "testing",
EmailConfirmed = true,
UsingTwoFactorAuthentication = true,
FirstName = "Test3",
LastName = "User"
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing",
RequestTfaRemoval = false
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
//Act
var result = await UserManager.Login(login);
//Assert
Assert.That(result.Result, Is.EqualTo(LoginResult.TwoFactorAuthenticationCodeRequired));
}
[Test]
public async Task Login_TfaEnabledButCodeIncorrect_ReturnsTwoFactorAuthenticationCodeIncorrect()
{
//Arrange
var existingUser = new User
{
Id = 16,
Email = "testuser3@sun-strategy.com",
Password = "testing",
EmailConfirmed = true,
UsingTwoFactorAuthentication = true,
FirstName = "Test3",
LastName = "User"
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing",
RequestTfaRemoval = false,
SecurityCode = "123456"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
//Act
var result = await UserManager.Login(login);
//Assert
TwoFactorAuthenticatorMock.Verify(x => x.ValidateTwoFactorPIN(It.IsAny<string>(), login.SecurityCode, false), Times.Once);
Assert.That(result.Result, Is.EqualTo(LoginResult.TwoFactorAuthenticationCodeIncorrect));
}
[Test]
public async Task Login_TfaEnabledAndCodeCorrect_ReturnsSuccess()
{
//Arrange
var existingUser = new User
{
Id = 16,
Email = "testuser3@sun-strategy.com",
Password = "testing",
EmailConfirmed = true,
UsingTwoFactorAuthentication = true,
FirstName = "Test3",
LastName = "User"
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = "testuser3@sun-strategy.com", //User exists in fake database. But email is not confirmed.
Password = "testing",
RequestTfaRemoval = false,
SecurityCode = "123456"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
TwoFactorAuthenticatorMock.Setup(x => x.ValidateTwoFactorPIN(It.IsAny<string>(), login.SecurityCode, It.IsAny<bool>())).Returns(true);
//Act
var result = await UserManager.Login(login);
//Assert
Assert.That(result.Result, Is.EqualTo(LoginResult.Success));
Assert.That(result.Token, Is.Not.Empty);
}
[Test]
public async Task Login_AccountIsNotActive_ReturnsFailed()
{
//Arrange
var existingUser = new User
{
Id = 15,
Email = "testuser@sun-strategy.com",
Password = "testing",
EmailConfirmed = true,
Active = false
};
await UserManagerRepository.AddUser(AuditUserDetails, existingUser, default);
var login = new Login
{
Email = existingUser.Email,
Password = "testing"
};
CustomPasswordHasherMock.Setup(x => x.VerifyHashedPassword(It.IsAny<IPassword>(), It.IsAny<string>(), login.Password)).Returns(PasswordVerificationResult.Success);
//Act
var result = await UserManager.Login(login);
//Assert
Assert.That(result.Result, Is.EqualTo(LoginResult.Failed));
Assert.That(result.Token, Is.Empty);
}
}