From 9d2d7ac83ab05742a11720d5a473c500bc3786d5 Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Fri, 4 Apr 2025 12:53:07 -0400 Subject: [PATCH] [PM-15621] WIP: Fixed the build and muted the tests --- .../OrganizationUsersController.cs | 6 +++-- .../Data/Organizations/DeleteUserResponse.cs | 6 +++++ ...teManagedOrganizationUserAccountCommand.cs | 27 +++++++++---------- ...ManagedOrganizationUserAccountValidator.cs | 18 ++++++++++--- .../DeleteUserValidationRequest.cs | 4 +-- ...teManagedOrganizationUserAccountCommand.cs | 6 ++--- ...OrganizationServiceCollectionExtensions.cs | 1 + 7 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 src/Core/AdminConsole/Models/Data/Organizations/DeleteUserResponse.cs rename src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/{RestoreUser => }/DeleteManagedOrganizationUserAccountValidator.cs (90%) diff --git a/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs b/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs index cd3b179f52..89d0f5a77b 100644 --- a/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +++ b/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs @@ -615,8 +615,10 @@ public class OrganizationUsersController : Controller var results = await _deleteManagedOrganizationUserAccountCommand.DeleteManyUsersAsync(orgId, model.Ids, currentUser.Id); - return new ListResponseModel(results.Select(r => - new OrganizationUserBulkResponseModel(r.OrganizationUserId, r.result))); + // Temporary code. + throw new UnauthorizedAccessException(); + // return new ListResponseModel(results.Select(r => + // new OrganizationUserBulkResponseModel(r.OrganizationUserId, r.result))); } [HttpPatch("{id}/revoke")] diff --git a/src/Core/AdminConsole/Models/Data/Organizations/DeleteUserResponse.cs b/src/Core/AdminConsole/Models/Data/Organizations/DeleteUserResponse.cs new file mode 100644 index 0000000000..b8a82ee1f5 --- /dev/null +++ b/src/Core/AdminConsole/Models/Data/Organizations/DeleteUserResponse.cs @@ -0,0 +1,6 @@ +namespace Bit.Core.Models.Data.Organizations; + +public class DeleteUserResponse +{ + public Guid OrganizationId { get; init; } +} diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountCommand.cs index a114646995..c5508a6688 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountCommand.cs @@ -50,28 +50,28 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz _pushService = pushService; } - public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId) + public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId) { var result = await InternalDeleteManyUsersAsync(organizationId, new[] { organizationUserId }, deletingUserId); + var error = result.InvalidResults.FirstOrDefault()?.Errors.FirstOrDefault(); - if (result.InvalidResults.Count > 0) + if (error != null) { - - var error = result.InvalidResults.FirstOrDefault()?.Errors.FirstOrDefault(); - - return new Failure(); + return new Failure(error.Message); } return new Success(); } - public async Task> DeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid? deletingUserId) + public async Task DeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid deletingUserId) { var results = await InternalDeleteManyUsersAsync(organizationId, orgUserIds, deletingUserId); + + return new Success(); } - private async Task> InternalDeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid? deletingUserId) + private async Task> InternalDeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid deletingUserId) { var orgUsers = await _organizationUserRepository.GetManyAsync(orgUserIds); var users = await GetUsersAsync(orgUsers); @@ -89,7 +89,7 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz private List CreateRequests( Guid organizationId, - Guid? deletingUserId, + Guid deletingUserId, IEnumerable orgUserIds, ICollection orgUsers, IEnumerable users, @@ -145,22 +145,19 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz var users = requests .Select(request => request.Value.User!); - if (users.Any()) + if (!users.Any()) { - await DeleteManyAsync(users); + return; } - } - private async Task DeleteManyAsync(IEnumerable users) - { await _userRepository.DeleteManyAsync(users); + foreach (var user in users) { await _referenceEventService.RaiseEventAsync( new ReferenceEvent(ReferenceEventType.DeleteAccount, user, _currentContext)); await _pushService.PushLogOutAsync(user.Id); } - } private async Task CancelPremiumsAsync(List> requests) diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/RestoreUser/DeleteManagedOrganizationUserAccountValidator.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountValidator.cs similarity index 90% rename from src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/RestoreUser/DeleteManagedOrganizationUserAccountValidator.cs rename to src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountValidator.cs index e19f0619c0..3bf0202c14 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/RestoreUser/DeleteManagedOrganizationUserAccountValidator.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteManagedOrganizationUserAccountValidator.cs @@ -6,7 +6,7 @@ using Bit.Core.Context; using Bit.Core.Enums; using Bit.Core.Repositories; -namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.RestoreUser; +namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers; public class DeleteManagedOrganizationUserAccountValidator( ICurrentContext currentContext, @@ -34,7 +34,8 @@ public class DeleteManagedOrganizationUserAccountValidator( { EnsureOnlyOwnersCanDeleteOwnersAsync, EnsureUserIsNotSoleOrganizationOwnerAsync, - EnsureUserIsNotSoleProviderOwnerAsync + EnsureUserIsNotSoleProviderOwnerAsync, + EnsureCustomUsersCannotDeleteAdminsAsync }; var result = await ExecuteValidatorsAsync(validators, asyncValidators, request); @@ -130,7 +131,7 @@ public class DeleteManagedOrganizationUserAccountValidator( return new Valid(request); } - if (request.DeletingUserId.HasValue && !await currentContext.OrganizationOwner(request.OrganizationId)) + if (!await currentContext.OrganizationOwner(request.OrganizationId)) { return new Invalid(new BadRequestError("Only owners can delete other owners.", request)); } @@ -158,4 +159,15 @@ public class DeleteManagedOrganizationUserAccountValidator( return new Valid(request); } + + private async Task> EnsureCustomUsersCannotDeleteAdminsAsync(DeleteUserValidationRequest request) + { + if (request.OrganizationUser.Type == OrganizationUserType.Admin && await currentContext.OrganizationCustom(request.OrganizationId)) + { + return new Invalid(new BadRequestError("Custom users can not delete admins.", request)); + } + + return new Valid(); + } + } diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteUserValidationRequest.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteUserValidationRequest.cs index 0861cb2fbd..5eed1162ab 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteUserValidationRequest.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/DeleteUserValidationRequest.cs @@ -8,8 +8,6 @@ public class DeleteUserValidationRequest public Guid OrganizationId { get; init; } public OrganizationUser? OrganizationUser { get; init; } public User? User { get; init; } - public Guid? DeletingUserId { get; init; } - - public IDictionary? ManagementStatus { get; init; } + public Guid DeletingUserId { get; init; } public bool? IsManaged { get; init; } } diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/Interfaces/IDeleteManagedOrganizationUserAccountCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/Interfaces/IDeleteManagedOrganizationUserAccountCommand.cs index 8afd208ab5..5c6e0a2ea8 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/Interfaces/IDeleteManagedOrganizationUserAccountCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/Interfaces/IDeleteManagedOrganizationUserAccountCommand.cs @@ -9,8 +9,7 @@ public interface IDeleteManagedOrganizationUserAccountCommand /// /// Removes a user from an organization and deletes all of their associated user data. /// - /// Jimmy temporary comment: consider removing the nullable from deletingUserId. - Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId); + Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId); /// /// Removes multiple users from an organization and deletes all of their associated user data. @@ -18,6 +17,5 @@ public interface IDeleteManagedOrganizationUserAccountCommand /// /// An error message for each user that could not be removed, otherwise null. /// - /// Jimmy temporary comment: consider removing the nullable from deletingUserId. - Task> DeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid? deletingUserId); + Task DeleteManyUsersAsync(Guid organizationId, IEnumerable orgUserIds, Guid deletingUserId); } diff --git a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs index 59cfdace65..ae30421ccb 100644 --- a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs +++ b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs @@ -117,6 +117,7 @@ public static class OrganizationServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); }