1
0
mirror of https://github.com/bitwarden/server.git synced 2025-02-08 00:31:27 +01:00

[PM-17709] Send New Device Login email for all new devices (#5340)

* Send New Device Login email regardless of New Device Verification

* Adjusted tests

* Linting

* Clarified test names.
This commit is contained in:
Todd Martin 2025-01-31 10:46:09 -05:00 committed by GitHub
parent d239170c1c
commit e43a8011f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 25 deletions

View File

@ -85,28 +85,17 @@ public class DeviceValidator(
}
}
// At this point we have established either new device verification is not required or the NewDeviceOtp is valid
// At this point we have established either new device verification is not required or the NewDeviceOtp is valid,
// so we save the device to the database and proceed with authentication
requestDevice.UserId = context.User.Id;
await _deviceService.SaveAsync(requestDevice);
context.Device = requestDevice;
// backwards compatibility -- If NewDeviceVerification not enabled send the new login emails
// PM-13340: removal Task; remove entire if block emails should no longer be sent
if (!_featureService.IsEnabled(FeatureFlagKeys.NewDeviceVerification))
if (!_globalSettings.DisableEmailNewDevice)
{
// This ensures the user doesn't receive a "new device" email on the first login
var now = DateTime.UtcNow;
if (now - context.User.CreationDate > TimeSpan.FromMinutes(10))
{
var deviceType = requestDevice.Type.GetType().GetMember(requestDevice.Type.ToString())
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
if (!_globalSettings.DisableEmailNewDevice)
{
await _mailService.SendNewDeviceLoggedInEmail(context.User.Email, deviceType, now,
_currentContext.IpAddress);
}
}
await SendNewDeviceLoginEmail(context.User, requestDevice);
}
return true;
}
@ -174,6 +163,19 @@ public class DeviceValidator(
return DeviceValidationResultType.NewDeviceVerificationRequired;
}
private async Task SendNewDeviceLoginEmail(User user, Device requestDevice)
{
// Ensure that the user doesn't receive a "new device" email on the first login
var now = DateTime.UtcNow;
if (now - user.CreationDate > TimeSpan.FromMinutes(10))
{
var deviceType = requestDevice.Type.GetType().GetMember(requestDevice.Type.ToString())
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
await _mailService.SendNewDeviceLoggedInEmail(user.Email, deviceType, now,
_currentContext.IpAddress);
}
}
public async Task<Device> GetKnownDeviceAsync(User user, Device device)
{
if (user == null || device == null)

View File

@ -227,7 +227,7 @@ public class DeviceValidatorTests
}
[Theory, BitAutoData]
public async void ValidateRequestDeviceAsync_NewDeviceVerificationFeatureFlagFalse_SendsEmail_ReturnsTrue(
public async void ValidateRequestDeviceAsync_ExistingUserNewDeviceLogin_SendNewDeviceLoginEmail_ReturnsTrue(
CustomValidatorRequestContext context,
[AuthFixtures.ValidatedTokenRequest] ValidatedTokenRequest request)
{
@ -237,8 +237,6 @@ public class DeviceValidatorTests
_globalSettings.DisableEmailNewDevice = false;
_deviceRepository.GetByIdentifierAsync(context.Device.Identifier, context.User.Id)
.Returns(null as Device);
_featureService.IsEnabled(FeatureFlagKeys.NewDeviceVerification)
.Returns(false);
// set user creation to more than 10 minutes ago
context.User.CreationDate = DateTime.UtcNow - TimeSpan.FromMinutes(11);
@ -253,7 +251,7 @@ public class DeviceValidatorTests
}
[Theory, BitAutoData]
public async void ValidateRequestDeviceAsync_NewDeviceVerificationFeatureFlagFalse_NewUser_DoesNotSendEmail_ReturnsTrue(
public async void ValidateRequestDeviceAsync_NewUserNewDeviceLogin_DoesNotSendNewDeviceLoginEmail_ReturnsTrue(
CustomValidatorRequestContext context,
[AuthFixtures.ValidatedTokenRequest] ValidatedTokenRequest request)
{
@ -263,8 +261,6 @@ public class DeviceValidatorTests
_globalSettings.DisableEmailNewDevice = false;
_deviceRepository.GetByIdentifierAsync(context.Device.Identifier, context.User.Id)
.Returns(null as Device);
_featureService.IsEnabled(FeatureFlagKeys.NewDeviceVerification)
.Returns(false);
// set user creation to less than 10 minutes ago
context.User.CreationDate = DateTime.UtcNow - TimeSpan.FromMinutes(9);
@ -279,7 +275,7 @@ public class DeviceValidatorTests
}
[Theory, BitAutoData]
public async void ValidateRequestDeviceAsync_NewDeviceVerificationFeatureFlagFalse_DisableEmailTrue_DoesNotSendEmail_ReturnsTrue(
public async void ValidateRequestDeviceAsynce_DisableNewDeviceLoginEmailTrue_DoesNotSendNewDeviceEmail_ReturnsTrue(
CustomValidatorRequestContext context,
[AuthFixtures.ValidatedTokenRequest] ValidatedTokenRequest request)
{
@ -289,8 +285,6 @@ public class DeviceValidatorTests
_globalSettings.DisableEmailNewDevice = true;
_deviceRepository.GetByIdentifierAsync(context.Device.Identifier, context.User.Id)
.Returns(null as Device);
_featureService.IsEnabled(FeatureFlagKeys.NewDeviceVerification)
.Returns(false);
// Act
var result = await _sut.ValidateRequestDeviceAsync(request, context);