1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

Auth/PM-6198 - Registration with Email Verification - Add email clicked endpoint (#4520)

* PM-6198 - RegistrationEmailVerificationTokenable - add new static validate token method

* PM-6198 - Rename RegistrationStart to Registration as we now have to add another anonymous reference event.

* PM-6198 - rest of work

* PM-6198 - Unit test new account controller method.

* PM-6198 - Integration test new account controller endpoint
This commit is contained in:
Jared Snider
2024-07-22 17:24:42 -04:00
committed by GitHub
parent 45b99336da
commit 1b5f9e3f3e
9 changed files with 229 additions and 6 deletions

View File

@ -41,6 +41,8 @@ public class AccountsControllerTests : IDisposable
private readonly ISendVerificationEmailForRegistrationCommand _sendVerificationEmailForRegistrationCommand;
private readonly IReferenceEventService _referenceEventService;
private readonly IFeatureService _featureService;
private readonly IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> _registrationEmailVerificationTokenDataFactory;
public AccountsControllerTests()
{
@ -54,6 +56,8 @@ public class AccountsControllerTests : IDisposable
_sendVerificationEmailForRegistrationCommand = Substitute.For<ISendVerificationEmailForRegistrationCommand>();
_referenceEventService = Substitute.For<IReferenceEventService>();
_featureService = Substitute.For<IFeatureService>();
_registrationEmailVerificationTokenDataFactory = Substitute.For<IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable>>();
_sut = new AccountsController(
_currentContext,
_logger,
@ -64,7 +68,8 @@ public class AccountsControllerTests : IDisposable
_getWebAuthnLoginCredentialAssertionOptionsCommand,
_sendVerificationEmailForRegistrationCommand,
_referenceEventService,
_featureService
_featureService,
_registrationEmailVerificationTokenDataFactory
);
}
@ -380,4 +385,105 @@ public class AccountsControllerTests : IDisposable
Assert.Equal(duplicateUserEmailErrorDesc, modelError.ErrorMessage);
}
[Theory, BitAutoData]
public async Task PostRegisterVerificationEmailClicked_WhenTokenIsValid_ShouldReturnOk(string email, string emailVerificationToken)
{
// Arrange
var registrationEmailVerificationTokenable = new RegistrationEmailVerificationTokenable(email);
_registrationEmailVerificationTokenDataFactory
.TryUnprotect(emailVerificationToken, out Arg.Any<RegistrationEmailVerificationTokenable>())
.Returns(callInfo =>
{
callInfo[1] = registrationEmailVerificationTokenable;
return true;
});
_userRepository.GetByEmailAsync(email).ReturnsNull(); // no existing user
var requestModel = new RegisterVerificationEmailClickedRequestModel
{
Email = email,
EmailVerificationToken = emailVerificationToken
};
// Act
var result = await _sut.PostRegisterVerificationEmailClicked(requestModel);
// Assert
var okResult = Assert.IsType<OkResult>(result);
Assert.Equal(200, okResult.StatusCode);
await _referenceEventService.Received(1).RaiseEventAsync(Arg.Is<ReferenceEvent>(e =>
e.Type == ReferenceEventType.SignupEmailClicked
&& e.EmailVerificationTokenValid == true
&& e.UserAlreadyExists == false
));
}
[Theory, BitAutoData]
public async Task PostRegisterVerificationEmailClicked_WhenTokenIsInvalid_ShouldReturnBadRequest(string email, string emailVerificationToken)
{
// Arrange
var registrationEmailVerificationTokenable = new RegistrationEmailVerificationTokenable("wrongEmail");
_registrationEmailVerificationTokenDataFactory
.TryUnprotect(emailVerificationToken, out Arg.Any<RegistrationEmailVerificationTokenable>())
.Returns(callInfo =>
{
callInfo[1] = registrationEmailVerificationTokenable;
return true;
});
_userRepository.GetByEmailAsync(email).ReturnsNull(); // no existing user
var requestModel = new RegisterVerificationEmailClickedRequestModel
{
Email = email,
EmailVerificationToken = emailVerificationToken
};
// Act & assert
await Assert.ThrowsAsync<BadRequestException>(() => _sut.PostRegisterVerificationEmailClicked(requestModel));
await _referenceEventService.Received(1).RaiseEventAsync(Arg.Is<ReferenceEvent>(e =>
e.Type == ReferenceEventType.SignupEmailClicked
&& e.EmailVerificationTokenValid == false
&& e.UserAlreadyExists == false
));
}
[Theory, BitAutoData]
public async Task PostRegisterVerificationEmailClicked_WhenTokenIsValidButExistingUser_ShouldReturnBadRequest(string email, string emailVerificationToken, User existingUser)
{
// Arrange
var registrationEmailVerificationTokenable = new RegistrationEmailVerificationTokenable(email);
_registrationEmailVerificationTokenDataFactory
.TryUnprotect(emailVerificationToken, out Arg.Any<RegistrationEmailVerificationTokenable>())
.Returns(callInfo =>
{
callInfo[1] = registrationEmailVerificationTokenable;
return true;
});
_userRepository.GetByEmailAsync(email).Returns(existingUser);
var requestModel = new RegisterVerificationEmailClickedRequestModel
{
Email = email,
EmailVerificationToken = emailVerificationToken
};
// Act & assert
await Assert.ThrowsAsync<BadRequestException>(() => _sut.PostRegisterVerificationEmailClicked(requestModel));
await _referenceEventService.Received(1).RaiseEventAsync(Arg.Is<ReferenceEvent>(e =>
e.Type == ReferenceEventType.SignupEmailClicked
&& e.EmailVerificationTokenValid == true
&& e.UserAlreadyExists == true
));
}
}