1
0
mirror of https://github.com/bitwarden/server synced 2025-12-22 19:23:45 +00:00

[PM-25097] Remove DeleteClaimedUserAccountRefactor flag (#6364)

* Remove feature flag
* Remove old code
This commit is contained in:
Thomas Rittson
2025-09-25 10:14:02 +10:00
committed by GitHub
parent f0953ed6b0
commit b83f95f78c
18 changed files with 86 additions and 930 deletions

View File

@@ -11,7 +11,7 @@ using Bit.Api.Vault.AuthorizationHandlers.Collections;
using Bit.Core;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.RestoreUser.v1;
@@ -61,7 +61,6 @@ public class OrganizationUsersController : Controller
private readonly IOrganizationUserUserDetailsQuery _organizationUserUserDetailsQuery;
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
private readonly IDeleteClaimedOrganizationUserAccountCommand _deleteClaimedOrganizationUserAccountCommand;
private readonly IDeleteClaimedOrganizationUserAccountCommandvNext _deleteClaimedOrganizationUserAccountCommandvNext;
private readonly IGetOrganizationUsersClaimedStatusQuery _getOrganizationUsersClaimedStatusQuery;
private readonly IPolicyRequirementQuery _policyRequirementQuery;
private readonly IFeatureService _featureService;
@@ -90,7 +89,6 @@ public class OrganizationUsersController : Controller
IOrganizationUserUserDetailsQuery organizationUserUserDetailsQuery,
IRemoveOrganizationUserCommand removeOrganizationUserCommand,
IDeleteClaimedOrganizationUserAccountCommand deleteClaimedOrganizationUserAccountCommand,
IDeleteClaimedOrganizationUserAccountCommandvNext deleteClaimedOrganizationUserAccountCommandvNext,
IGetOrganizationUsersClaimedStatusQuery getOrganizationUsersClaimedStatusQuery,
IPolicyRequirementQuery policyRequirementQuery,
IFeatureService featureService,
@@ -119,7 +117,6 @@ public class OrganizationUsersController : Controller
_organizationUserUserDetailsQuery = organizationUserUserDetailsQuery;
_removeOrganizationUserCommand = removeOrganizationUserCommand;
_deleteClaimedOrganizationUserAccountCommand = deleteClaimedOrganizationUserAccountCommand;
_deleteClaimedOrganizationUserAccountCommandvNext = deleteClaimedOrganizationUserAccountCommandvNext;
_getOrganizationUsersClaimedStatusQuery = getOrganizationUsersClaimedStatusQuery;
_policyRequirementQuery = policyRequirementQuery;
_featureService = featureService;
@@ -539,21 +536,22 @@ public class OrganizationUsersController : Controller
[HttpDelete("{id}/delete-account")]
[Authorize<ManageUsersRequirement>]
public async Task DeleteAccount(Guid orgId, Guid id)
public async Task<IResult> DeleteAccount(Guid orgId, Guid id)
{
if (_featureService.IsEnabled(FeatureFlagKeys.DeleteClaimedUserAccountRefactor))
var currentUserId = _userService.GetProperUserId(User);
if (currentUserId == null)
{
await DeleteAccountvNext(orgId, id);
return;
return TypedResults.Unauthorized();
}
var currentUser = await _userService.GetUserByPrincipalAsync(User);
if (currentUser == null)
{
throw new UnauthorizedAccessException();
}
var commandResult = await _deleteClaimedOrganizationUserAccountCommand.DeleteUserAsync(orgId, id, currentUserId.Value);
await _deleteClaimedOrganizationUserAccountCommand.DeleteUserAsync(orgId, id, currentUser.Id);
return commandResult.Result.Match<IResult>(
error => error is NotFoundError
? TypedResults.NotFound(new ErrorResponseModel(error.Message))
: TypedResults.BadRequest(new ErrorResponseModel(error.Message)),
TypedResults.Ok
);
}
[HttpPost("{id}/delete-account")]
@@ -564,43 +562,24 @@ public class OrganizationUsersController : Controller
await DeleteAccount(orgId, id);
}
private async Task<IResult> DeleteAccountvNext(Guid orgId, Guid id)
{
var currentUserId = _userService.GetProperUserId(User);
if (currentUserId == null)
{
return TypedResults.Unauthorized();
}
var commandResult = await _deleteClaimedOrganizationUserAccountCommandvNext.DeleteUserAsync(orgId, id, currentUserId.Value);
return commandResult.Result.Match<IResult>(
error => error is NotFoundError
? TypedResults.NotFound(new ErrorResponseModel(error.Message))
: TypedResults.BadRequest(new ErrorResponseModel(error.Message)),
TypedResults.Ok
);
}
[HttpDelete("delete-account")]
[Authorize<ManageUsersRequirement>]
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkDeleteAccount(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
if (_featureService.IsEnabled(FeatureFlagKeys.DeleteClaimedUserAccountRefactor))
{
return await BulkDeleteAccountvNext(orgId, model);
}
var currentUser = await _userService.GetUserByPrincipalAsync(User);
if (currentUser == null)
var currentUserId = _userService.GetProperUserId(User);
if (currentUserId == null)
{
throw new UnauthorizedAccessException();
}
var results = await _deleteClaimedOrganizationUserAccountCommand.DeleteManyUsersAsync(orgId, model.Ids, currentUser.Id);
var result = await _deleteClaimedOrganizationUserAccountCommand.DeleteManyUsersAsync(orgId, model.Ids, currentUserId.Value);
return new ListResponseModel<OrganizationUserBulkResponseModel>(results.Select(r =>
new OrganizationUserBulkResponseModel(r.OrganizationUserId, r.ErrorMessage)));
var responses = result.Select(r => r.Result.Match(
error => new OrganizationUserBulkResponseModel(r.Id, error.Message),
_ => new OrganizationUserBulkResponseModel(r.Id, string.Empty)
));
return new ListResponseModel<OrganizationUserBulkResponseModel>(responses);
}
[HttpPost("delete-account")]
@@ -611,24 +590,6 @@ public class OrganizationUsersController : Controller
return await BulkDeleteAccount(orgId, model);
}
private async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkDeleteAccountvNext(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
var currentUserId = _userService.GetProperUserId(User);
if (currentUserId == null)
{
throw new UnauthorizedAccessException();
}
var result = await _deleteClaimedOrganizationUserAccountCommandvNext.DeleteManyUsersAsync(orgId, model.Ids, currentUserId.Value);
var responses = result.Select(r => r.Result.Match(
error => new OrganizationUserBulkResponseModel(r.Id, error.Message),
_ => new OrganizationUserBulkResponseModel(r.Id, string.Empty)
));
return new ListResponseModel<OrganizationUserBulkResponseModel>(responses);
}
[HttpPut("{id}/revoke")]
[Authorize<ManageUsersRequirement>]
public async Task RevokeAsync(Guid orgId, Guid id)

View File

@@ -1,7 +1,7 @@
using OneOf;
using OneOf.Types;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
/// <summary>
/// Represents the result of a command.

View File

@@ -8,18 +8,18 @@ using Bit.Core.Services;
using Microsoft.Extensions.Logging;
using OneOf.Types;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
public class DeleteClaimedOrganizationUserAccountCommandvNext(
public class DeleteClaimedOrganizationUserAccountCommand(
IUserService userService,
IEventService eventService,
IGetOrganizationUsersClaimedStatusQuery getOrganizationUsersClaimedStatusQuery,
IOrganizationUserRepository organizationUserRepository,
IUserRepository userRepository,
IPushNotificationService pushService,
ILogger<DeleteClaimedOrganizationUserAccountCommandvNext> logger,
IDeleteClaimedOrganizationUserAccountValidatorvNext deleteClaimedOrganizationUserAccountValidatorvNext)
: IDeleteClaimedOrganizationUserAccountCommandvNext
ILogger<DeleteClaimedOrganizationUserAccountCommand> logger,
IDeleteClaimedOrganizationUserAccountValidator deleteClaimedOrganizationUserAccountValidator)
: IDeleteClaimedOrganizationUserAccountCommand
{
public async Task<BulkCommandResult> DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId)
{
@@ -35,7 +35,7 @@ public class DeleteClaimedOrganizationUserAccountCommandvNext(
var claimedStatuses = await getOrganizationUsersClaimedStatusQuery.GetUsersOrganizationClaimedStatusAsync(organizationId, orgUserIds);
var internalRequests = CreateInternalRequests(organizationId, deletingUserId, orgUserIds, orgUsers, users, claimedStatuses);
var validationResults = (await deleteClaimedOrganizationUserAccountValidatorvNext.ValidateAsync(internalRequests)).ToList();
var validationResults = (await deleteClaimedOrganizationUserAccountValidator.ValidateAsync(internalRequests)).ToList();
var validRequests = validationResults.ValidRequests();
await CancelPremiumsAsync(validRequests);

View File

@@ -2,14 +2,14 @@
using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Repositories;
using static Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext.ValidationResultHelpers;
using static Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount.ValidationResultHelpers;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
public class DeleteClaimedOrganizationUserAccountValidatorvNext(
public class DeleteClaimedOrganizationUserAccountValidator(
ICurrentContext currentContext,
IOrganizationUserRepository organizationUserRepository,
IProviderUserRepository providerUserRepository) : IDeleteClaimedOrganizationUserAccountValidatorvNext
IProviderUserRepository providerUserRepository) : IDeleteClaimedOrganizationUserAccountValidator
{
public async Task<IEnumerable<ValidationResult<DeleteUserValidationRequest>>> ValidateAsync(IEnumerable<DeleteUserValidationRequest> requests)
{

View File

@@ -1,6 +1,6 @@
using Bit.Core.Entities;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
public class DeleteUserValidationRequest
{

View File

@@ -1,4 +1,4 @@
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
/// <summary>
/// A strongly typed error containing a reason that an action failed.

View File

@@ -1,6 +1,6 @@
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
public interface IDeleteClaimedOrganizationUserAccountCommandvNext
public interface IDeleteClaimedOrganizationUserAccountCommand
{
/// <summary>
/// Removes a user from an organization and deletes all of their associated user data.

View File

@@ -1,6 +1,6 @@
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
public interface IDeleteClaimedOrganizationUserAccountValidatorvNext
public interface IDeleteClaimedOrganizationUserAccountValidator
{
Task<IEnumerable<ValidationResult<DeleteUserValidationRequest>>> ValidateAsync(IEnumerable<DeleteUserValidationRequest> requests);
}

View File

@@ -1,7 +1,7 @@
using OneOf;
using OneOf.Types;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
/// <summary>
/// Represents the result of validating a request.

View File

@@ -1,239 +0,0 @@
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Platform.Push;
using Bit.Core.Repositories;
using Bit.Core.Services;
#nullable enable
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
public class DeleteClaimedOrganizationUserAccountCommand : IDeleteClaimedOrganizationUserAccountCommand
{
private readonly IUserService _userService;
private readonly IEventService _eventService;
private readonly IGetOrganizationUsersClaimedStatusQuery _getOrganizationUsersClaimedStatusQuery;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IUserRepository _userRepository;
private readonly ICurrentContext _currentContext;
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
private readonly IPushNotificationService _pushService;
private readonly IOrganizationRepository _organizationRepository;
private readonly IProviderUserRepository _providerUserRepository;
public DeleteClaimedOrganizationUserAccountCommand(
IUserService userService,
IEventService eventService,
IGetOrganizationUsersClaimedStatusQuery getOrganizationUsersClaimedStatusQuery,
IOrganizationUserRepository organizationUserRepository,
IUserRepository userRepository,
ICurrentContext currentContext,
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery,
IPushNotificationService pushService,
IOrganizationRepository organizationRepository,
IProviderUserRepository providerUserRepository)
{
_userService = userService;
_eventService = eventService;
_getOrganizationUsersClaimedStatusQuery = getOrganizationUsersClaimedStatusQuery;
_organizationUserRepository = organizationUserRepository;
_userRepository = userRepository;
_currentContext = currentContext;
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
_pushService = pushService;
_organizationRepository = organizationRepository;
_providerUserRepository = providerUserRepository;
}
public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId)
{
var organizationUser = await _organizationUserRepository.GetByIdAsync(organizationUserId);
if (organizationUser == null || organizationUser.OrganizationId != organizationId)
{
throw new NotFoundException("Member not found.");
}
var claimedStatus = await _getOrganizationUsersClaimedStatusQuery.GetUsersOrganizationClaimedStatusAsync(organizationId, new[] { organizationUserId });
var hasOtherConfirmedOwners = await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(organizationId, new[] { organizationUserId }, includeProvider: true);
await ValidateDeleteUserAsync(organizationId, organizationUser, deletingUserId, claimedStatus, hasOtherConfirmedOwners);
var user = await _userRepository.GetByIdAsync(organizationUser.UserId!.Value);
if (user == null)
{
throw new NotFoundException("Member not found.");
}
await _userService.DeleteAsync(user);
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Deleted);
}
public async Task<IEnumerable<(Guid OrganizationUserId, string? ErrorMessage)>> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid? deletingUserId)
{
var orgUsers = await _organizationUserRepository.GetManyAsync(orgUserIds);
var userIds = orgUsers.Where(ou => ou.UserId.HasValue).Select(ou => ou.UserId!.Value).ToList();
var users = await _userRepository.GetManyAsync(userIds);
var claimedStatus = await _getOrganizationUsersClaimedStatusQuery.GetUsersOrganizationClaimedStatusAsync(organizationId, orgUserIds);
var hasOtherConfirmedOwners = await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(organizationId, orgUserIds, includeProvider: true);
var results = new List<(Guid OrganizationUserId, string? ErrorMessage)>();
foreach (var orgUserId in orgUserIds)
{
try
{
var orgUser = orgUsers.FirstOrDefault(ou => ou.Id == orgUserId);
if (orgUser == null || orgUser.OrganizationId != organizationId)
{
throw new NotFoundException("Member not found.");
}
await ValidateDeleteUserAsync(organizationId, orgUser, deletingUserId, claimedStatus, hasOtherConfirmedOwners);
var user = users.FirstOrDefault(u => u.Id == orgUser.UserId);
if (user == null)
{
throw new NotFoundException("Member not found.");
}
await ValidateUserMembershipAndPremiumAsync(user);
results.Add((orgUserId, string.Empty));
}
catch (Exception ex)
{
results.Add((orgUserId, ex.Message));
}
}
var orgUserResultsToDelete = results.Where(result => string.IsNullOrEmpty(result.ErrorMessage));
var orgUsersToDelete = orgUsers.Where(orgUser => orgUserResultsToDelete.Any(result => orgUser.Id == result.OrganizationUserId));
var usersToDelete = users.Where(user => orgUsersToDelete.Any(orgUser => orgUser.UserId == user.Id));
if (usersToDelete.Any())
{
await DeleteManyAsync(usersToDelete);
}
await LogDeletedOrganizationUsersAsync(orgUsers, results);
return results;
}
private async Task ValidateDeleteUserAsync(Guid organizationId, OrganizationUser orgUser, Guid? deletingUserId, IDictionary<Guid, bool> claimedStatus, bool hasOtherConfirmedOwners)
{
if (!orgUser.UserId.HasValue || orgUser.Status == OrganizationUserStatusType.Invited)
{
throw new BadRequestException("You cannot delete a member with Invited status.");
}
if (deletingUserId.HasValue && orgUser.UserId.Value == deletingUserId.Value)
{
throw new BadRequestException("You cannot delete yourself.");
}
if (orgUser.Type == OrganizationUserType.Owner)
{
if (deletingUserId.HasValue && !await _currentContext.OrganizationOwner(organizationId))
{
throw new BadRequestException("Only owners can delete other owners.");
}
if (!hasOtherConfirmedOwners)
{
throw new BadRequestException("Organization must have at least one confirmed owner.");
}
}
if (orgUser.Type == OrganizationUserType.Admin && await _currentContext.OrganizationCustom(organizationId))
{
throw new BadRequestException("Custom users can not delete admins.");
}
if (!claimedStatus.TryGetValue(orgUser.Id, out var isClaimed) || !isClaimed)
{
throw new BadRequestException("Member is not claimed by the organization.");
}
}
private async Task LogDeletedOrganizationUsersAsync(
IEnumerable<OrganizationUser> orgUsers,
IEnumerable<(Guid OrgUserId, string? ErrorMessage)> results)
{
var eventDate = DateTime.UtcNow;
var events = new List<(OrganizationUser OrgUser, EventType Event, DateTime? EventDate)>();
foreach (var (orgUserId, errorMessage) in results)
{
var orgUser = orgUsers.FirstOrDefault(ou => ou.Id == orgUserId);
// If the user was not found or there was an error, we skip logging the event
if (orgUser == null || !string.IsNullOrEmpty(errorMessage))
{
continue;
}
events.Add((orgUser, EventType.OrganizationUser_Deleted, eventDate));
}
if (events.Any())
{
await _eventService.LogOrganizationUserEventsAsync(events);
}
}
private async Task DeleteManyAsync(IEnumerable<User> users)
{
await _userRepository.DeleteManyAsync(users);
foreach (var user in users)
{
await _pushService.PushLogOutAsync(user.Id);
}
}
private async Task ValidateUserMembershipAndPremiumAsync(User user)
{
// Check if user is the only owner of any organizations.
var onlyOwnerCount = await _organizationUserRepository.GetCountByOnlyOwnerAsync(user.Id);
if (onlyOwnerCount > 0)
{
throw new BadRequestException("Cannot delete this user because it is the sole owner of at least one organization. Please delete these organizations or upgrade another user.");
}
var orgs = await _organizationUserRepository.GetManyDetailsByUserAsync(user.Id, OrganizationUserStatusType.Confirmed);
if (orgs.Count == 1)
{
var org = await _organizationRepository.GetByIdAsync(orgs.First().OrganizationId);
if (org != null && (!org.Enabled || string.IsNullOrWhiteSpace(org.GatewaySubscriptionId)))
{
var orgCount = await _organizationUserRepository.GetCountByOrganizationIdAsync(org.Id);
if (orgCount <= 1)
{
await _organizationRepository.DeleteAsync(org);
}
else
{
throw new BadRequestException("Cannot delete this user because it is the sole owner of at least one organization. Please delete these organizations or upgrade another user.");
}
}
}
var onlyOwnerProviderCount = await _providerUserRepository.GetCountByOnlyOwnerAsync(user.Id);
if (onlyOwnerProviderCount > 0)
{
throw new BadRequestException("Cannot delete this user because it is the sole owner of at least one provider. Please delete these providers or upgrade another user.");
}
if (!string.IsNullOrWhiteSpace(user.GatewaySubscriptionId))
{
try
{
await _userService.CancelPremiumAsync(user);
}
catch (GatewayException) { }
}
}
}

View File

@@ -1,19 +0,0 @@
#nullable enable
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
public interface IDeleteClaimedOrganizationUserAccountCommand
{
/// <summary>
/// Removes a user from an organization and deletes all of their associated user data.
/// </summary>
Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId);
/// <summary>
/// Removes multiple users from an organization and deletes all of their associated user data.
/// </summary>
/// <returns>
/// An error message for each user that could not be removed, otherwise null.
/// </returns>
Task<IEnumerable<(Guid OrganizationUserId, string? ErrorMessage)>> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid? deletingUserId);
}

View File

@@ -134,7 +134,6 @@ public static class FeatureFlagKeys
public const string PM23845_VNextApplicationCache = "pm-24957-refactor-memory-application-cache";
public const string CipherRepositoryBulkResourceCreation = "pm-24951-cipher-repository-bulk-resource-creation-service";
public const string CollectionVaultRefactor = "pm-25030-resolve-ts-upgrade-errors";
public const string DeleteClaimedUserAccountRefactor = "pm-25094-refactor-delete-managed-organization-user-command";
/* Auth Team */
public const string TwoFactorExtensionDataPersistence = "pm-9115-two-factor-extension-data-persistence";

View File

@@ -13,7 +13,7 @@ using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccountvNext;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Validation;
@@ -132,12 +132,10 @@ public static class OrganizationServiceCollectionExtensions
services.AddScoped<IRevokeOrganizationUserCommand, RevokeOrganizationUserCommand>();
services.AddScoped<IUpdateOrganizationUserCommand, UpdateOrganizationUserCommand>();
services.AddScoped<IUpdateOrganizationUserGroupsCommand, UpdateOrganizationUserGroupsCommand>();
services.AddScoped<IDeleteClaimedOrganizationUserAccountCommand, DeleteClaimedOrganizationUserAccountCommand>();
services.AddScoped<IConfirmOrganizationUserCommand, ConfirmOrganizationUserCommand>();
// vNext implementations (feature flagged)
services.AddScoped<IDeleteClaimedOrganizationUserAccountCommandvNext, DeleteClaimedOrganizationUserAccountCommandvNext>();
services.AddScoped<IDeleteClaimedOrganizationUserAccountValidatorvNext, DeleteClaimedOrganizationUserAccountValidatorvNext>();
services.AddScoped<IDeleteClaimedOrganizationUserAccountCommand, DeleteClaimedOrganizationUserAccountCommand>();
services.AddScoped<IDeleteClaimedOrganizationUserAccountValidator, DeleteClaimedOrganizationUserAccountValidator>();
}
private static void AddOrganizationApiKeyCommandsQueries(this IServiceCollection services)