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

598 lines
21 KiB
C#

using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using e_suite.Database.Core.Models;
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 CompleteEmailActionUnitTests : UserManagerTestBase<object>
{
[SetUp]
public override async Task Setup()
{
await base.Setup();
}
[Test]
public Task CompleteEmailAction_TokenNotFound_ThrowsTokenInvalidException()
{
//Arrange
var token = new EmailActionToken
{
Email = "evil.hacker@sun-strategy.com",
Token = new Guid("{84CC5C02-0A14-465B-AB14-6D5125D50E7B}")
};
//Act & Assert
Assert.ThrowsAsync<TokenInvalidException>(async () =>
{
await UserManager.CompleteEmailAction(token);
});
return Task.CompletedTask;
}
[Test]
public async Task CompleteEmailAction_TokenOutOfDate_ThrowsTokenInvalidException()
{
//Arrange
var actualUser = new User
{
Id = 1,
Email = "testuser@sun-strategy.com"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{F5035CA7-E2B1-46B3-8E1A-B121107E66AD}")
};
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.ConfirmEmailAddress,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 06, 11, 43, 0, TimeSpan.Zero);
//Act & Assert
Assert.ThrowsAsync<TokenInvalidException>(async () =>
{
await UserManager.CompleteEmailAction(token);
});
}
[Test]
public async Task CompleteEmailAction_UserEmailDoesNotMatchTheToken_ThrowsInvalidEmailException()
{
//Arrange
var actualUser = new User
{
Id = 2,
Email = "testuser@sun-strategy.com"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.ConfirmEmailAddress,
Token = new Guid("{632B559B-4641-4973-A1C0-38D198816201}"),
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
var token = new EmailActionToken
{
Email = "evil.hacker@sun-strategy.com",
Token = emailUserAction.Token,
Password = "P@ssword12345"
};
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
//Act & Assert
Assert.ThrowsAsync<InvalidEmailException>(async () =>
{
await UserManager.CompleteEmailAction(token);
});
}
[Test]
public async Task CompleteEmailAction_ConfirmEmail_CompletedSuccessfully()
{
//Arrange
var actualUser = new User
{
Id = 3,
Email = "testuser2@sun-strategy.com",
EmailConfirmed = false,
Password = "aA1!12345789"
};
var oldPassword = actualUser.Password;
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = "testuser2@sun-strategy.com",
Token = new Guid("{9275C68F-A88A-4AD5-963B-64678E3ABFF9}"),
Password = "Pa55W0rD-3d1ce44c-86ce-4136!b6ad-8b24303e1cfc"
};
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.ConfirmEmailAddress,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
//Act
var exception = Assert.ThrowsAsync<ArgumentException>(async () =>
{
await UserManager.CompleteEmailAction(token);
});
//Assert
Assert.That(exception!.Message, Is.EqualTo($"EmailActionType {emailUserAction.EmailActionType} not supported, use the UI instead."));
}
[Test]
public async Task CompleteEmailAction_ResetPasswordNewPasswordMissing_ThrowsException()
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo($"Password must be at least 12 characters"));
}
[Test]
public async Task CompleteEmailAction_ResetPasswordNewPasswordIsTooShort_ThrowsException()
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = "test"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo("Password must be at least 12 characters"));
}
[Test]
public async Task CompleteEmailAction_ResetPasswordDoesNotContainAValidSymbol_ThrowsException()
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = "testtesttest"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo($"Password must contain at least one symbol: ~`! @#$%^&*()_+={{[}}|\\:;\"'<,->.?/"));
}
[TestCase('~')]
[TestCase('`')]
[TestCase('!')]
[TestCase(' ')]
[TestCase('@')]
[TestCase('#')]
[TestCase('$')]
[TestCase('%')]
[TestCase('^')]
[TestCase('&')]
[TestCase('(')]
[TestCase(')')]
[TestCase('_')]
[TestCase('+')]
[TestCase('=')]
[TestCase('{')]
[TestCase('[')]
[TestCase('}')]
[TestCase('|')]
[TestCase('\\')]
[TestCase(':')]
[TestCase(';')]
[TestCase('\"')]
[TestCase('\'')]
[TestCase('<')]
[TestCase(',')]
[TestCase('-')]
[TestCase('>')]
[TestCase('.')]
[TestCase('?')]
[TestCase('/')]
[TestCase('"')]
public async Task CompleteEmailAction_ResetPasswordDoesNotContainAValidNumber_ThrowsException(char symbol)
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = $"t{symbol}sttesttest"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo($"Password must contain at least one number"));
}
[TestCase('0')]
[TestCase('1')]
[TestCase('2')]
[TestCase('3')]
[TestCase('4')]
[TestCase('5')]
[TestCase('6')]
[TestCase('7')]
[TestCase('8')]
[TestCase('9')]
public async Task CompleteEmailAction_ResetPasswordDoesNotContainAUpperCaseCharacter_ThrowsException(char number)
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = $"t*{number}ttesttest"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo($"Password must contain at least one upper case character"));
}
[Test]
public async Task CompleteEmailAction_ResetPasswordDoesNotContainALowerCaseCharacter_ThrowsException()
{
//Arrange
var actualUser = new User
{
Id = 4,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I don't know aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = $"T*1TTESTTEST"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
var exception = Assert.ThrowsAsync<WeakPasswordException>(async () => await UserManager.CompleteEmailAction(token));
//Assert
Assert.That(exception?.Message, Is.EqualTo($"Password must contain at least one lower case character"));
}
[Test]
public async Task CompleteEmailAction_ResetPassword_CompletedSuccessfully()
{
//Arrange
var actualUser = new User
{
Id = 5,
Email = "testuser@sun-strategy.com",
EmailConfirmed = false,
Password = "I've forgotten aA1!12345789"
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = new Guid("{CAA1C1E2-7876-4ACB-A050-8CF94466CC4E}"),
Password = "Pa55W0rD-3d1ce44c-86ce-4136-b6ad-8b24303e1cfc"
};
var oldPassword = actualUser.Password;
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.PasswordReset,
Token = token.Token,
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
var hashedPassword = "owekjhrtlkerjthbwerlkjrthbw3";
CustomPasswordHasherMock.Setup(x => x.HashPassword(It.IsAny<User>(), It.IsAny<string>()))
.Returns(hashedPassword);
//Act
await UserManager.CompleteEmailAction(token);
//Assert
var databaseRow = UserManagerRepository.EmailUserActions.SingleOrDefault(x => x.Token == token.Token);
Assert.That(databaseRow, Is.Null);
var user = UserManagerRepository.Users.Single(x => x.Email == token.Email);
Assert.That(user.Password, Is.Not.EqualTo(oldPassword));
Assert.That(user.Password, Is.EqualTo(hashedPassword));
MailServiceMock.Verify(x => x.RequestEMailAsync(It.IsAny<MailRequest>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task CompleteEmailAction_DisableTwoFactorAuthentivation_CompletedSuccessfully()
{
//Arrange
var actualUser = new User
{
Id = 6,
Email = "testuser3@sun-strategy.com",
EmailConfirmed = false,
Password = "I've forgotten aA1!12345789",
UsingTwoFactorAuthentication = true
};
await UserManagerRepository.AddUser(AuditUserDetails, actualUser, default);
var emailUserAction = new EmailUserAction
{
EmailActionType = EmailUserActionType.DisableAuthenticator,
Token = new Guid("{9B44A60C-AB66-4161-BF17-EEAC2162EAC2}"),
User = actualUser,
UserId = actualUser.Id,
Created = new DateTimeOffset(2022, 08, 03, 11, 43, 0, TimeSpan.Zero),
Expires = new DateTimeOffset(2022, 08, 05, 11, 43, 0, TimeSpan.Zero),
};
await UserManagerRepository.AddEmailUserAction(AuditUserDetails, emailUserAction, default);
var token = new EmailActionToken
{
Email = actualUser.Email,
Token = emailUserAction.Token
};
_fakeClock.DateTime = new DateTimeOffset(2022, 08, 04, 11, 43, 0, TimeSpan.Zero);
//Act
await UserManager.CompleteEmailAction(token);
//Assert
var databaseRow = UserManagerRepository.EmailUserActions.SingleOrDefault(x => x.Token == token.Token);
Assert.That(databaseRow, Is.Null);
var user = UserManagerRepository.Users.Single(x => x.Email == token.Email);
Assert.That(user.UsingTwoFactorAuthentication, Is.False);
}
}