Files
server/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyPendingAutoConfirmTests.cs
Jared eacafaecfe [PM-33951] feat(admin-console): Add bulk confirmation and pending auto-confirmation (#7661)
* 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>
2026-05-27 18:05:57 -04:00

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);
}
}