mirror of
https://github.com/bitwarden/server
synced 2025-12-10 21:33:41 +00:00
[PM-26632] - Adding Idempotent Confirm User (#6459)
* Added repo call for idempotent user confirm. PLUS TESTS! * Code review changes
This commit is contained in:
@@ -69,6 +69,42 @@ public static class OrganizationTestHelpers
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
public static Task<OrganizationUser> CreateAcceptedTestOrganizationUserAsync(
|
||||
this IOrganizationUserRepository organizationUserRepository,
|
||||
Organization organization,
|
||||
User user)
|
||||
=> organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Accepted,
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
public static Task<OrganizationUser> CreateRevokedTestOrganizationUserAsync(
|
||||
this IOrganizationUserRepository organizationUserRepository,
|
||||
Organization organization,
|
||||
User user)
|
||||
=> organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Revoked,
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
public static Task<OrganizationUser> CreateConfirmedTestOrganizationUserAsync(
|
||||
this IOrganizationUserRepository organizationUserRepository,
|
||||
Organization organization,
|
||||
User user)
|
||||
=> organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
public static Task<Group> CreateTestGroupAsync(
|
||||
this IGroupRepository groupRepository,
|
||||
Organization organization,
|
||||
@@ -81,9 +117,9 @@ public static class OrganizationTestHelpers
|
||||
this ICollectionRepository collectionRepository,
|
||||
Organization organization,
|
||||
string identifier = "test")
|
||||
=> collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
Name = $"{identifier} {Guid.NewGuid()}"
|
||||
});
|
||||
=> collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
Name = $"{identifier} {Guid.NewGuid()}"
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1417,4 +1417,146 @@ public class OrganizationUserRepositoryTests
|
||||
// Regular collection should be removed
|
||||
Assert.DoesNotContain(actualCollections, c => c.Id == regularCollection.Id);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_WhenUserIsAccepted_ReturnsTrue(IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository)
|
||||
{
|
||||
// Arrange
|
||||
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
||||
var user = await userRepository.CreateTestUserAsync();
|
||||
var orgUser = await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(organization, user);
|
||||
|
||||
// Act
|
||||
var result = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
var updatedUser = await organizationUserRepository.GetByIdAsync(orgUser.Id);
|
||||
Assert.NotNull(updatedUser);
|
||||
Assert.Equal(OrganizationUserStatusType.Confirmed, updatedUser.Status);
|
||||
|
||||
// Annul
|
||||
await organizationRepository.DeleteAsync(organization);
|
||||
await userRepository.DeleteAsync(user);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_WhenUserIsInvited_ReturnsFalse(IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository)
|
||||
{
|
||||
// Arrange
|
||||
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
||||
var orgUser = await organizationUserRepository.CreateTestOrganizationUserInviteAsync(organization);
|
||||
|
||||
// Act
|
||||
var result = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
var unchangedUser = await organizationUserRepository.GetByIdAsync(orgUser.Id);
|
||||
Assert.NotNull(unchangedUser);
|
||||
Assert.Equal(OrganizationUserStatusType.Invited, unchangedUser.Status);
|
||||
|
||||
// Annul
|
||||
await organizationRepository.DeleteAsync(organization);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_WhenUserIsAlreadyConfirmed_ReturnsFalse(IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository)
|
||||
{
|
||||
// Arrange
|
||||
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
||||
var user = await userRepository.CreateTestUserAsync();
|
||||
var orgUser = await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(organization, user);
|
||||
|
||||
// Act
|
||||
var result = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
var unchangedUser = await organizationUserRepository.GetByIdAsync(orgUser.Id);
|
||||
Assert.NotNull(unchangedUser);
|
||||
Assert.Equal(OrganizationUserStatusType.Confirmed, unchangedUser.Status);
|
||||
|
||||
// Annul
|
||||
await organizationRepository.DeleteAsync(organization);
|
||||
await userRepository.DeleteAsync(user);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_WhenUserIsRevoked_ReturnsFalse(IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository)
|
||||
{
|
||||
// Arrange
|
||||
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
||||
var user = await userRepository.CreateTestUserAsync();
|
||||
var orgUser = await organizationUserRepository.CreateRevokedTestOrganizationUserAsync(organization, user);
|
||||
|
||||
// Act
|
||||
var result = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
var unchangedUser = await organizationUserRepository.GetByIdAsync(orgUser.Id);
|
||||
Assert.NotNull(unchangedUser);
|
||||
Assert.Equal(OrganizationUserStatusType.Revoked, unchangedUser.Status);
|
||||
|
||||
// Annul
|
||||
await organizationRepository.DeleteAsync(organization);
|
||||
await userRepository.DeleteAsync(user);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_IsIdempotent_WhenCalledMultipleTimes(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository)
|
||||
{
|
||||
// Arrange
|
||||
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
||||
var user = await userRepository.CreateTestUserAsync();
|
||||
var orgUser = await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(organization, user);
|
||||
|
||||
// Act - First call should confirm
|
||||
var firstResult = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
var secondResult = await organizationUserRepository.ConfirmOrganizationUserAsync(orgUser);
|
||||
|
||||
// Assert
|
||||
Assert.True(firstResult);
|
||||
Assert.False(secondResult);
|
||||
var finalUser = await organizationUserRepository.GetByIdAsync(orgUser.Id);
|
||||
Assert.NotNull(finalUser);
|
||||
Assert.Equal(OrganizationUserStatusType.Confirmed, finalUser.Status);
|
||||
|
||||
// Annul
|
||||
await organizationRepository.DeleteAsync(organization);
|
||||
await userRepository.DeleteAsync(user);
|
||||
}
|
||||
|
||||
[Theory, DatabaseData]
|
||||
public async Task ConfirmOrganizationUserAsync_WhenUserDoesNotExist_ReturnsFalse(
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
// Arrange
|
||||
var nonExistentUser = new OrganizationUser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
OrganizationId = Guid.NewGuid(),
|
||||
UserId = Guid.NewGuid(),
|
||||
Email = "nonexistent@bitwarden.com",
|
||||
Status = OrganizationUserStatusType.Accepted,
|
||||
Type = OrganizationUserType.Owner
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await organizationUserRepository.ConfirmOrganizationUserAsync(nonExistentUser);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user