mirror of
https://github.com/bitwarden/server
synced 2025-12-25 04:33:26 +00:00
[PM-20140] Prevent accidental bulk removal of users without a Master Password (#6173)
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
#nullable enable
|
||||
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Models.Business;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
@@ -17,7 +12,7 @@ using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Import;
|
||||
|
||||
public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersAndGroupsCommand
|
||||
{
|
||||
@@ -26,10 +21,8 @@ public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersA
|
||||
private readonly IPaymentService _paymentService;
|
||||
private readonly IGroupRepository _groupRepository;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IInviteOrganizationUsersCommand _inviteOrganizationUsersCommand;
|
||||
private readonly IPricingClient _pricingClient;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
private readonly EventSystemUser _EventSystemUser = EventSystemUser.PublicApi;
|
||||
|
||||
@@ -38,21 +31,16 @@ public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersA
|
||||
IPaymentService paymentService,
|
||||
IGroupRepository groupRepository,
|
||||
IEventService eventService,
|
||||
ICurrentContext currentContext,
|
||||
IOrganizationService organizationService,
|
||||
IInviteOrganizationUsersCommand inviteOrganizationUsersCommand,
|
||||
IPricingClient pricingClient
|
||||
)
|
||||
IFeatureService featureService)
|
||||
{
|
||||
_organizationRepository = organizationRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_paymentService = paymentService;
|
||||
_groupRepository = groupRepository;
|
||||
_eventService = eventService;
|
||||
_currentContext = currentContext;
|
||||
_organizationService = organizationService;
|
||||
_inviteOrganizationUsersCommand = inviteOrganizationUsersCommand;
|
||||
_pricingClient = pricingClient;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -243,10 +231,23 @@ public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersA
|
||||
List<(OrganizationUserUserDetails ou, EventType e, DateTime? d)> events,
|
||||
OrganizationUserImportData importUserData)
|
||||
{
|
||||
var usersToDelete = importUserData.ExistingExternalUsers.Where(u =>
|
||||
u.Type != OrganizationUserType.Owner &&
|
||||
!importUserData.ImportedExternalIds.Contains(u.ExternalId) &&
|
||||
importUserData.ExistingExternalUsersIdDict.ContainsKey(u.ExternalId));
|
||||
var usersToDelete = importUserData.ExistingExternalUsers
|
||||
.Where(u =>
|
||||
u.Type != OrganizationUserType.Owner &&
|
||||
!importUserData.ImportedExternalIds.Contains(u.ExternalId) &&
|
||||
importUserData.ExistingExternalUsersIdDict.ContainsKey(u.ExternalId))
|
||||
.ToList();
|
||||
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.DirectoryConnectorPreventUserRemoval) &&
|
||||
usersToDelete.Any(u => !u.HasMasterPassword))
|
||||
{
|
||||
// Removing users without an MP will put their account in an unrecoverable state.
|
||||
// We allow this during normal syncs for offboarding, but overwriteExisting risks bricking every user in
|
||||
// the organization, so you don't get to do it here.
|
||||
throw new BadRequestException(
|
||||
"Sync failed. To proceed, disable the 'Remove and re-add users during next sync' setting and try again.");
|
||||
}
|
||||
|
||||
await _organizationUserRepository.DeleteManyAsync(usersToDelete.Select(u => u.Id));
|
||||
events.AddRange(usersToDelete.Select(u => (
|
||||
u,
|
||||
|
||||
@@ -116,6 +116,7 @@ public static class FeatureFlagKeys
|
||||
public const string ImportAsyncRefactor = "pm-22583-refactor-import-async";
|
||||
public const string CreateDefaultLocation = "pm-19467-create-default-location";
|
||||
public const string MembersGetEndpointOptimization = "pm-23113-optimize-get-members-endpoint";
|
||||
public const string DirectoryConnectorPreventUserRemoval = "pm-24592-directory-connector-prevent-user-removal";
|
||||
|
||||
/* Auth Team */
|
||||
public const string PM9112DeviceApprovalPersistence = "pm-9112-device-approval-persistence";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Bit.Core.AdminConsole.OrganizationAuth.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Groups;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Groups.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Import;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationApiKeys;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationApiKeys.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationConnections;
|
||||
|
||||
Reference in New Issue
Block a user