mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[PM-15614] Allow Users to opt out of new device verification (#5176)
feat(NewDeviceVerification) : * Created database migration scripts for VerifyDevices column in [dbo].[User]. * Updated DeviceValidator to check if user has opted out of device verification. * Added endpoint to AccountsController.cs to allow editing of new User.VerifyDevices property. * Added tests for new methods and endpoint. * Updating queries to track [dbo].[User].[VerifyDevices]. * Updated DeviceValidator to set `User.EmailVerified` property during the New Device Verification flow.
This commit is contained in:
@ -563,6 +563,49 @@ public class AccountsControllerTests : IDisposable
|
||||
await _userService.Received(1).DeleteAsync(user);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SetVerifyDevices_WhenUserDoesNotExist_ShouldThrowUnauthorizedAccessException(
|
||||
SetVerifyDevicesRequestModel model)
|
||||
{
|
||||
// Arrange
|
||||
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(Task.FromResult((User)null));
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => _sut.SetUserVerifyDevicesAsync(model));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SetVerifyDevices_WhenInvalidSecret_ShouldFail(
|
||||
User user, SetVerifyDevicesRequestModel model)
|
||||
{
|
||||
// Arrange
|
||||
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(Task.FromResult((user)));
|
||||
_userService.VerifySecretAsync(user, Arg.Any<string>()).Returns(Task.FromResult(false));
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<BadRequestException>(() => _sut.SetUserVerifyDevicesAsync(model));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SetVerifyDevices_WhenRequestValid_ShouldSucceed(
|
||||
User user, SetVerifyDevicesRequestModel model)
|
||||
{
|
||||
// Arrange
|
||||
user.VerifyDevices = false;
|
||||
model.VerifyDevices = true;
|
||||
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(Task.FromResult((user)));
|
||||
_userService.VerifySecretAsync(user, Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
|
||||
// Act
|
||||
await _sut.SetUserVerifyDevicesAsync(model);
|
||||
|
||||
await _userService.Received(1).SaveUserAsync(user);
|
||||
Assert.Equal(model.VerifyDevices, user.VerifyDevices);
|
||||
}
|
||||
|
||||
// Below are helper functions that currently belong to this
|
||||
// test class, but ultimately may need to be split out into
|
||||
// something greater in order to share common test steps with
|
||||
|
@ -36,6 +36,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.UseSecretsManager = false;
|
||||
signup.IsFromSecretsManagerTrial = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
|
||||
|
||||
@ -85,6 +86,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PaymentMethodType = PaymentMethodType.Card;
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.UseSecretsManager = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
// Extract orgUserId when created
|
||||
Guid? orgUserId = null;
|
||||
@ -128,6 +130,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PaymentMethodType = PaymentMethodType.Card;
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.IsFromSecretsManagerTrial = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
|
||||
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
|
||||
|
||||
@ -196,6 +200,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.AdditionalServiceAccounts = 10;
|
||||
signup.AdditionalStorageGb = 0;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
@ -213,6 +218,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PaymentMethodType = PaymentMethodType.Card;
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.AdditionalServiceAccounts = 10;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
@ -230,6 +236,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PaymentMethodType = PaymentMethodType.Card;
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.AdditionalServiceAccounts = -10;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
|
@ -429,6 +429,30 @@ public class DeviceValidatorTests
|
||||
Assert.Equal(expectedErrorMessage, actualResponse.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void HandleNewDeviceVerificationAsync_VerifyDevicesFalse_ReturnsSuccess(
|
||||
CustomValidatorRequestContext context,
|
||||
[AuthFixtures.ValidatedTokenRequest] ValidatedTokenRequest request)
|
||||
{
|
||||
// Arrange
|
||||
ArrangeForHandleNewDeviceVerificationTest(context, request);
|
||||
_featureService.IsEnabled(FeatureFlagKeys.NewDeviceVerification).Returns(true);
|
||||
_globalSettings.EnableNewDeviceVerification = true;
|
||||
context.User.VerifyDevices = false;
|
||||
|
||||
// Act
|
||||
var result = await _sut.ValidateRequestDeviceAsync(request, context);
|
||||
|
||||
// Assert
|
||||
await _userService.Received(0).SendOTPAsync(context.User);
|
||||
await _deviceService.Received(1).SaveAsync(Arg.Any<Device>());
|
||||
|
||||
Assert.True(result);
|
||||
Assert.False(context.CustomResponse.ContainsKey("ErrorModel"));
|
||||
Assert.Equal(context.User.Id, context.Device.UserId);
|
||||
Assert.NotNull(context.Device);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async void HandleNewDeviceVerificationAsync_UserHasCacheValue_ReturnsSuccess(
|
||||
CustomValidatorRequestContext context,
|
||||
|
Reference in New Issue
Block a user