You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
8.5 KiB
256 lines
8.5 KiB
using Bit.Core.Auth.Entities; |
|
using Bit.Core.Auth.Enums; |
|
using Bit.Core.Entities; |
|
using Bit.Core.Enums; |
|
using Bit.Core.Repositories; |
|
using Xunit; |
|
|
|
namespace Bit.Infrastructure.IntegrationTest.Auth.Repositories; |
|
|
|
public class DeviceRepositoryTests |
|
{ |
|
[DatabaseTheory] |
|
[DatabaseData] |
|
public async Task GetManyByUserIdWithDeviceAuth_Works_ReturnsExpectedResults( |
|
IDeviceRepository sutRepository, |
|
IUserRepository userRepository, |
|
IAuthRequestRepository authRequestRepository) |
|
{ |
|
// Arrange |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var device = await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "chrome-test", |
|
UserId = user.Id, |
|
Type = DeviceType.ChromeBrowser, |
|
Identifier = Guid.NewGuid().ToString(), |
|
}); |
|
|
|
var staleAuthRequest = await authRequestRepository.CreateAsync(new AuthRequest |
|
{ |
|
ResponseDeviceId = null, |
|
Approved = null, |
|
Type = AuthRequestType.AuthenticateAndUnlock, |
|
OrganizationId = null, |
|
UserId = user.Id, |
|
RequestIpAddress = ":1", |
|
RequestDeviceIdentifier = device.Identifier, |
|
AccessCode = "AccessCode_1234", |
|
PublicKey = "PublicKey_1234" |
|
}); |
|
staleAuthRequest.CreationDate = DateTime.UtcNow.AddMinutes(-10); |
|
await authRequestRepository.ReplaceAsync(staleAuthRequest); |
|
|
|
var freshAuthRequest = await authRequestRepository.CreateAsync(new AuthRequest |
|
{ |
|
ResponseDeviceId = null, |
|
Approved = null, |
|
Type = AuthRequestType.AuthenticateAndUnlock, |
|
OrganizationId = null, |
|
UserId = user.Id, |
|
RequestIpAddress = ":1", |
|
RequestDeviceIdentifier = device.Identifier, |
|
AccessCode = "AccessCode_1234", |
|
PublicKey = "PublicKey_1234", |
|
Key = "Key_1234", |
|
MasterPasswordHash = "MasterPasswordHash_1234" |
|
}); |
|
|
|
// Act |
|
var response = await sutRepository.GetManyByUserIdWithDeviceAuth(user.Id); |
|
|
|
// Assert |
|
Assert.NotNull(response.First().AuthRequestId); |
|
Assert.NotNull(response.First().AuthRequestCreatedAt); |
|
Assert.Equal(response.First().AuthRequestId, freshAuthRequest.Id); |
|
} |
|
|
|
[DatabaseTheory] |
|
[DatabaseData] |
|
public async Task GetManyByUserIdWithDeviceAuth_WorksWithMultipleUsersOnSameDevice_ReturnsExpectedResults( |
|
IDeviceRepository sutRepository, |
|
IUserRepository userRepository, |
|
IAuthRequestRepository authRequestRepository) |
|
{ |
|
// Arrange |
|
var userA = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User A", |
|
Email = $"test_user_A+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var userB = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User B", |
|
Email = $"test_user_B+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var sharedDeviceIdentifier = Guid.NewGuid().ToString(); |
|
|
|
var deviceForUserA = await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "chrome-test", |
|
UserId = userA.Id, |
|
Type = DeviceType.ChromeBrowser, |
|
Identifier = sharedDeviceIdentifier, |
|
}); |
|
|
|
var deviceForUserB = await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "chrome-test", |
|
UserId = userB.Id, |
|
Type = DeviceType.ChromeBrowser, |
|
Identifier = sharedDeviceIdentifier, |
|
}); |
|
|
|
var userAAuthRequest = await authRequestRepository.CreateAsync(new AuthRequest |
|
{ |
|
ResponseDeviceId = null, |
|
Approved = null, |
|
Type = AuthRequestType.AuthenticateAndUnlock, |
|
OrganizationId = null, |
|
UserId = userA.Id, |
|
RequestIpAddress = ":1", |
|
RequestDeviceIdentifier = deviceForUserA.Identifier, |
|
AccessCode = "AccessCode_1234", |
|
PublicKey = "PublicKey_1234" |
|
}); |
|
|
|
// Act |
|
var response = await sutRepository.GetManyByUserIdWithDeviceAuth(userB.Id); |
|
|
|
// Assert |
|
Assert.Null(response.First().AuthRequestId); |
|
Assert.Null(response.First().AuthRequestCreatedAt); |
|
} |
|
|
|
[DatabaseTheory] |
|
[DatabaseData] |
|
public async Task GetManyByUserIdWithDeviceAuth_WorksWithNoAuthRequestAndMultipleDevices_ReturnsExpectedResults( |
|
IDeviceRepository sutRepository, |
|
IUserRepository userRepository) |
|
{ |
|
// Arrange |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "chrome-test", |
|
UserId = user.Id, |
|
Type = DeviceType.ChromeBrowser, |
|
Identifier = Guid.NewGuid().ToString(), |
|
}); |
|
|
|
await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "macos-test", |
|
UserId = user.Id, |
|
Type = DeviceType.MacOsDesktop, |
|
Identifier = Guid.NewGuid().ToString(), |
|
}); |
|
|
|
// Act |
|
var response = await sutRepository.GetManyByUserIdWithDeviceAuth(user.Id); |
|
|
|
// Assert |
|
Assert.NotNull(response.First()); |
|
Assert.Null(response.First().AuthRequestId); |
|
Assert.True(response.Count == 2); |
|
} |
|
|
|
[DatabaseTheory] |
|
[DatabaseData] |
|
public async Task GetManyByUserIdWithDeviceAuth_FailsToRespondWithAnyAuthData_ReturnsEmptyResults( |
|
IDeviceRepository sutRepository, |
|
IUserRepository userRepository, |
|
IAuthRequestRepository authRequestRepository) |
|
{ |
|
var casesThatCauseNoAuthDataInResponse = new[] |
|
{ |
|
new |
|
{ |
|
authRequestType = AuthRequestType.AdminApproval, // Device typing is wrong |
|
authRequestApproved = (bool?)null, |
|
expirey = DateTime.UtcNow.AddMinutes(0), |
|
}, |
|
new |
|
{ |
|
authRequestType = AuthRequestType.AuthenticateAndUnlock, |
|
authRequestApproved = (bool?)true, // Auth request is already approved |
|
expirey = DateTime.UtcNow.AddMinutes(0), |
|
}, |
|
new |
|
{ |
|
authRequestType = AuthRequestType.AuthenticateAndUnlock, |
|
authRequestApproved = (bool?)null, |
|
expirey = DateTime.UtcNow.AddMinutes(-30), // Past the point of expiring |
|
} |
|
}; |
|
|
|
foreach (var testCase in casesThatCauseNoAuthDataInResponse) |
|
{ |
|
// Arrange |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var device = await sutRepository.CreateAsync(new Device |
|
{ |
|
Active = true, |
|
Name = "chrome-test", |
|
UserId = user.Id, |
|
Type = DeviceType.ChromeBrowser, |
|
Identifier = Guid.NewGuid().ToString(), |
|
}); |
|
|
|
var authRequest = await authRequestRepository.CreateAsync(new AuthRequest |
|
{ |
|
ResponseDeviceId = null, |
|
Approved = testCase.authRequestApproved, |
|
Type = testCase.authRequestType, |
|
OrganizationId = null, |
|
UserId = user.Id, |
|
RequestIpAddress = ":1", |
|
RequestDeviceIdentifier = device.Identifier, |
|
AccessCode = "AccessCode_1234", |
|
PublicKey = "PublicKey_1234" |
|
}); |
|
|
|
authRequest.CreationDate = testCase.expirey; |
|
await authRequestRepository.ReplaceAsync(authRequest); |
|
|
|
// Act |
|
var response = await sutRepository.GetManyByUserIdWithDeviceAuth(user.Id); |
|
|
|
// Assert |
|
Assert.Null(response.First().AuthRequestId); |
|
Assert.Null(response.First().AuthRequestCreatedAt); |
|
} |
|
} |
|
}
|
|
|