mirror of
https://github.com/bitwarden/server
synced 2026-01-03 09:03:44 +00:00
[PM-28260] Optimize bulk reinvite endpoint (#6670)
* Implement optimized bulk invite resend command - Added IBulkResendOrganizationInvitesCommand interface to define the bulk resend operation. - Created BulkResendOrganizationInvitesCommand class to handle the logic for resending invites to multiple organization users. - Integrated logging and validation to ensure only valid users receive invites. - Included error handling for non-existent organizations and invalid user statuses. * Add unit tests for BulkResendOrganizationInvitesCommand - Implemented comprehensive test cases for the BulkResendOrganizationInvitesCommand class. - Validated user statuses and ensured correct handling of valid and invalid users during bulk invite resends. - Included tests for scenarios such as organization not found and empty user lists. - Utilized Xunit and NSubstitute for effective testing and mocking of dependencies. * Add IBulkResendOrganizationInvitesCommand to service collection - Registered IBulkResendOrganizationInvitesCommand in the service collection for dependency injection. * Update OrganizationUsersController to utilize IBulkResendOrganizationInvitesCommand - Added IBulkResendOrganizationInvitesCommand to the OrganizationUsersController for handling bulk invite resends based on feature flag. - Updated BulkReinvite method to conditionally use the new command or the legacy service based on the feature flag status. - Enhanced unit tests to verify correct command usage depending on feature flag state, ensuring robust testing for both scenarios.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models;
|
||||
using Bit.Core.AdminConsole.Utilities.DebuggingInstruments;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
|
||||
public class BulkResendOrganizationInvitesCommand : IBulkResendOrganizationInvitesCommand
|
||||
{
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly ISendOrganizationInvitesCommand _sendOrganizationInvitesCommand;
|
||||
private readonly ILogger<BulkResendOrganizationInvitesCommand> _logger;
|
||||
|
||||
public BulkResendOrganizationInvitesCommand(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
ISendOrganizationInvitesCommand sendOrganizationInvitesCommand,
|
||||
ILogger<BulkResendOrganizationInvitesCommand> logger)
|
||||
{
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_organizationRepository = organizationRepository;
|
||||
_sendOrganizationInvitesCommand = sendOrganizationInvitesCommand;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Tuple<OrganizationUser, string>>> BulkResendInvitesAsync(
|
||||
Guid organizationId,
|
||||
Guid? invitingUserId,
|
||||
IEnumerable<Guid> organizationUsersId)
|
||||
{
|
||||
var orgUsers = await _organizationUserRepository.GetManyAsync(organizationUsersId);
|
||||
_logger.LogUserInviteStateDiagnostics(orgUsers);
|
||||
|
||||
var org = await _organizationRepository.GetByIdAsync(organizationId);
|
||||
if (org == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var validUsers = new List<OrganizationUser>();
|
||||
var result = new List<Tuple<OrganizationUser, string>>();
|
||||
|
||||
foreach (var orgUser in orgUsers)
|
||||
{
|
||||
if (orgUser.Status != OrganizationUserStatusType.Invited || orgUser.OrganizationId != organizationId)
|
||||
{
|
||||
result.Add(Tuple.Create(orgUser, "User invalid."));
|
||||
}
|
||||
else
|
||||
{
|
||||
validUsers.Add(orgUser);
|
||||
}
|
||||
}
|
||||
|
||||
if (validUsers.Any())
|
||||
{
|
||||
await _sendOrganizationInvitesCommand.SendInvitesAsync(
|
||||
new SendInvitesRequest(validUsers, org));
|
||||
|
||||
result.AddRange(validUsers.Select(u => Tuple.Create(u, "")));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Bit.Core.Entities;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
|
||||
public interface IBulkResendOrganizationInvitesCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Resend invites to multiple organization users in bulk.
|
||||
/// </summary>
|
||||
/// <param name="organizationId">The ID of the organization.</param>
|
||||
/// <param name="invitingUserId">The ID of the user who is resending the invites.</param>
|
||||
/// <param name="organizationUsersId">The IDs of the organization users to resend invites to.</param>
|
||||
/// <returns>A tuple containing the OrganizationUser and an error message (empty string if successful)</returns>
|
||||
Task<IEnumerable<Tuple<OrganizationUser, string>>> BulkResendInvitesAsync(
|
||||
Guid organizationId,
|
||||
Guid? invitingUserId,
|
||||
IEnumerable<Guid> organizationUsersId);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user