mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 12:26:46 -05:00
* feat(admin-console): Add bulk confirmation and pending auto-confirmation methods for organization users - Implemented ConfirmManyOrganizationUsersAsync to confirm multiple users in a single operation. - Added GetManyPendingAutoConfirmAsync to retrieve users pending automatic confirmation. - Created stored procedures for bulk confirmation and fetching pending users. - Updated relevant repository interfaces and implementations across Dapper and Entity Framework. * refactor(admin-console): Change parameter type for ConfirmManyOrganizationUsersAsync to IReadOnlyCollection - Updated the ConfirmManyOrganizationUsersAsync method signature in the IOrganizationUserRepository and its implementations to use IReadOnlyCollection instead of IEnumerable for better performance and clarity. - Adjusted related repository methods in both Dapper and Entity Framework implementations to reflect this change. - Added unit tests to ensure the new implementation behaves as expected, including scenarios for mixed batches and idempotency. * Remove OrganizationUser_ReadByOrganizationIdStatus stored procedure as part of database cleanup. * Add integration tests for ConfirmManyOrganizationUsers and GetManyPendingAutoConfirm methods - Introduced ConfirmManyOrganizationUsersTests to validate the confirmation of multiple organization users, ensuring only accepted users are confirmed and idempotency is maintained. - Added GetManyPendingAutoConfirmTests to verify retrieval of pending auto-confirm users, ensuring only eligible users are returned based on specific criteria. - Removed duplicate test implementations from OrganizationUserRepositoryTests to maintain clarity and organization in the test suite. * Implement OrganizationUser_UpdateStatusKey stored procedure and update related repository method - Added OrganizationUser_UpdateStatusKey stored procedure to handle updating the status and key of organization users based on a JSON input. - Updated OrganizationUserRepository to call the new stored procedure instead of the previous confirmation procedure. - Modified OrganizationUser_ReadByPendingAutoConfirm stored procedure to filter users by a new type value. - Enhanced integration tests to verify the correct behavior of the updated confirmation logic, ensuring revision dates are accurately tracked. * Refactor OrganizationUser_UpdateStatusKey to OrganizationUser_UpdateManyStatusKey - Renamed the stored procedure to OrganizationUser_UpdateManyStatusKey to better reflect its functionality of updating multiple organization users' statuses. - Updated the OrganizationUserRepository to call the new stored procedure. - Adjusted the migration script to create or alter the procedure accordingly. * Update data type for Key column in AddOrganizationUserUpdateStatusKey migration script - Changed the data type of the Key column from NVARCHAR(MAX) to VARCHAR(MAX) in the UsersToUpdate table and the corresponding JSON parsing logic to improve compatibility and performance. * Updated spacing * Add stored procedures for organization user status updates and retrieval - Created OrganizationUser_UpdateManyStatusKey to update multiple organization users' statuses based on a JSON input, including handling revision dates and tracking updated IDs for idempotency. - Added OrganizationUser_ReadByPendingAutoConfirm to retrieve organization users pending auto-confirmation based on organization ID and specific status and type filters. --------- Co-authored-by: mkincaid-bw <mkincaid@bitwarden.com>
65 lines
2.7 KiB
C#
65 lines
2.7 KiB
C#
using Bit.Core.Entities;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Repositories;
|
|
using Xunit;
|
|
|
|
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.OrganizationUserRepository;
|
|
|
|
public class GetManyPendingAutoConfirmTests
|
|
{
|
|
[Theory, DatabaseData]
|
|
public async Task GetManyPendingAutoConfirmAsync_ReturnsOnlyAcceptedUsersWithUserType(
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
IOrganizationRepository organizationRepository,
|
|
IUserRepository userRepository)
|
|
{
|
|
// Arrange
|
|
var org = await organizationRepository.CreateTestOrganizationAsync();
|
|
var otherOrg = await organizationRepository.CreateTestOrganizationAsync();
|
|
|
|
// Should be returned: Accepted + Type=User + non-null UserId
|
|
var eligibleUser = await userRepository.CreateTestUserAsync("eligible");
|
|
var eligibleOrgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
|
{
|
|
OrganizationId = org.Id,
|
|
UserId = eligibleUser.Id,
|
|
Status = OrganizationUserStatusType.Accepted,
|
|
Type = OrganizationUserType.User,
|
|
});
|
|
|
|
// Should NOT be returned: already Confirmed
|
|
var confirmedUser = await userRepository.CreateTestUserAsync("confirmed");
|
|
await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(org, confirmedUser);
|
|
|
|
// Should NOT be returned: Accepted but Type=Owner (not Type=User)
|
|
var acceptedOwner = await userRepository.CreateTestUserAsync("acceptedOwner");
|
|
await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(org, acceptedOwner);
|
|
|
|
// Should NOT be returned: Accepted + Type=User but UserId is null (invite-only)
|
|
await organizationUserRepository.CreateAsync(new OrganizationUser
|
|
{
|
|
OrganizationId = org.Id,
|
|
UserId = null,
|
|
Status = OrganizationUserStatusType.Accepted,
|
|
Type = OrganizationUserType.User,
|
|
});
|
|
|
|
// Should NOT be returned: belongs to a different organization
|
|
var otherOrgUser = await userRepository.CreateTestUserAsync("otherOrg");
|
|
await organizationUserRepository.CreateAsync(new OrganizationUser
|
|
{
|
|
OrganizationId = otherOrg.Id,
|
|
UserId = otherOrgUser.Id,
|
|
Status = OrganizationUserStatusType.Accepted,
|
|
Type = OrganizationUserType.User,
|
|
});
|
|
|
|
// Act
|
|
var results = await organizationUserRepository.GetManyPendingAutoConfirmAsync(org.Id);
|
|
|
|
// Assert — only the eligible user is returned
|
|
Assert.Single(results);
|
|
Assert.Equal(eligibleOrgUser.Id, results.Single().Id);
|
|
}
|
|
}
|