2023-10-27 07:47:44 +10:00
|
|
|
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
2024-10-16 10:33:00 +01:00
|
|
|
|
using Bit.Core.Context;
|
|
|
|
|
|
using Bit.Core.Entities;
|
2023-10-27 07:47:44 +10:00
|
|
|
|
using Bit.Core.Enums;
|
2022-11-09 12:13:29 +00:00
|
|
|
|
using Bit.Core.Exceptions;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
using Bit.Core.Repositories;
|
|
|
|
|
|
using Bit.Core.Services;
|
|
|
|
|
|
|
2023-10-27 07:47:44 +10:00
|
|
|
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
|
2024-09-04 11:18:23 +01:00
|
|
|
|
public class RemoveOrganizationUserCommand : IRemoveOrganizationUserCommand
|
2022-10-31 09:58:21 +00:00
|
|
|
|
{
|
2024-10-16 10:33:00 +01:00
|
|
|
|
private readonly IDeviceRepository _deviceRepository;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
2024-10-16 10:33:00 +01:00
|
|
|
|
private readonly IEventService _eventService;
|
|
|
|
|
|
private readonly IPushNotificationService _pushNotificationService;
|
|
|
|
|
|
private readonly IPushRegistrationService _pushRegistrationService;
|
|
|
|
|
|
private readonly ICurrentContext _currentContext;
|
|
|
|
|
|
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
|
2024-09-04 11:18:23 +01:00
|
|
|
|
public RemoveOrganizationUserCommand(
|
2024-10-16 10:33:00 +01:00
|
|
|
|
IDeviceRepository deviceRepository,
|
2022-10-31 09:58:21 +00:00
|
|
|
|
IOrganizationUserRepository organizationUserRepository,
|
2024-10-16 10:33:00 +01:00
|
|
|
|
IEventService eventService,
|
|
|
|
|
|
IPushNotificationService pushNotificationService,
|
|
|
|
|
|
IPushRegistrationService pushRegistrationService,
|
|
|
|
|
|
ICurrentContext currentContext,
|
|
|
|
|
|
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery)
|
2022-10-31 09:58:21 +00:00
|
|
|
|
{
|
2024-10-16 10:33:00 +01:00
|
|
|
|
_deviceRepository = deviceRepository;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
_organizationUserRepository = organizationUserRepository;
|
2024-10-16 10:33:00 +01:00
|
|
|
|
_eventService = eventService;
|
|
|
|
|
|
_pushNotificationService = pushNotificationService;
|
|
|
|
|
|
_pushRegistrationService = pushRegistrationService;
|
|
|
|
|
|
_currentContext = currentContext;
|
|
|
|
|
|
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
|
2022-10-31 09:58:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-04 11:18:23 +01:00
|
|
|
|
public async Task RemoveUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId)
|
2022-11-09 12:13:29 +00:00
|
|
|
|
{
|
2024-10-16 10:33:00 +01:00
|
|
|
|
var organizationUser = await _organizationUserRepository.GetByIdAsync(organizationUserId);
|
|
|
|
|
|
ValidateDeleteUser(organizationId, organizationUser);
|
2022-11-09 12:13:29 +00:00
|
|
|
|
|
2024-10-16 10:33:00 +01:00
|
|
|
|
await RepositoryDeleteUserAsync(organizationUser, deletingUserId);
|
|
|
|
|
|
|
|
|
|
|
|
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Removed);
|
2022-11-09 12:13:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-04 11:18:23 +01:00
|
|
|
|
public async Task RemoveUserAsync(Guid organizationId, Guid organizationUserId, EventSystemUser eventSystemUser)
|
2022-11-09 12:13:29 +00:00
|
|
|
|
{
|
2024-10-16 10:33:00 +01:00
|
|
|
|
var organizationUser = await _organizationUserRepository.GetByIdAsync(organizationUserId);
|
|
|
|
|
|
ValidateDeleteUser(organizationId, organizationUser);
|
|
|
|
|
|
|
|
|
|
|
|
await RepositoryDeleteUserAsync(organizationUser, null);
|
|
|
|
|
|
|
|
|
|
|
|
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Removed, eventSystemUser);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task RemoveUserAsync(Guid organizationId, Guid userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var organizationUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, userId);
|
|
|
|
|
|
ValidateDeleteUser(organizationId, organizationUser);
|
|
|
|
|
|
|
|
|
|
|
|
await RepositoryDeleteUserAsync(organizationUser, null);
|
|
|
|
|
|
|
|
|
|
|
|
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Removed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<List<Tuple<OrganizationUser, string>>> RemoveUsersAsync(Guid organizationId,
|
|
|
|
|
|
IEnumerable<Guid> organizationUsersId,
|
|
|
|
|
|
Guid? deletingUserId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var orgUsers = await _organizationUserRepository.GetManyAsync(organizationUsersId);
|
|
|
|
|
|
var filteredUsers = orgUsers.Where(u => u.OrganizationId == organizationId)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
if (!filteredUsers.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Users invalid.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(organizationId, organizationUsersId))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Organization must have at least one confirmed owner.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var deletingUserIsOwner = false;
|
|
|
|
|
|
if (deletingUserId.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
deletingUserIsOwner = await _currentContext.OrganizationOwner(organizationId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var result = new List<Tuple<OrganizationUser, string>>();
|
|
|
|
|
|
var deletedUserIds = new List<Guid>();
|
|
|
|
|
|
foreach (var orgUser in filteredUsers)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (deletingUserId.HasValue && orgUser.UserId == deletingUserId)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("You cannot remove yourself.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (orgUser.Type == OrganizationUserType.Owner && deletingUserId.HasValue && !deletingUserIsOwner)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Only owners can delete other owners.");
|
|
|
|
|
|
}
|
2022-11-09 12:13:29 +00:00
|
|
|
|
|
2024-10-16 10:33:00 +01:00
|
|
|
|
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Removed);
|
|
|
|
|
|
|
|
|
|
|
|
if (orgUser.UserId.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
await DeleteAndPushUserRegistrationAsync(organizationId, orgUser.UserId.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
result.Add(Tuple.Create(orgUser, ""));
|
|
|
|
|
|
deletedUserIds.Add(orgUser.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (BadRequestException e)
|
|
|
|
|
|
{
|
|
|
|
|
|
result.Add(Tuple.Create(orgUser, e.Message));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await _organizationUserRepository.DeleteManyAsync(deletedUserIds);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-11-09 12:13:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 10:33:00 +01:00
|
|
|
|
private void ValidateDeleteUser(Guid organizationId, OrganizationUser orgUser)
|
2022-10-31 09:58:21 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (orgUser == null || orgUser.OrganizationId != organizationId)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotFoundException("User not found.");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-10-16 10:33:00 +01:00
|
|
|
|
|
|
|
|
|
|
private async Task RepositoryDeleteUserAsync(OrganizationUser orgUser, Guid? deletingUserId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (deletingUserId.HasValue && orgUser.UserId == deletingUserId.Value)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("You cannot remove yourself.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (orgUser.Type == OrganizationUserType.Owner)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (deletingUserId.HasValue && !await _currentContext.OrganizationOwner(orgUser.OrganizationId))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Only owners can delete other owners.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(orgUser.OrganizationId, new[] { orgUser.Id }, includeProvider: true))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Organization must have at least one confirmed owner.");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await _organizationUserRepository.DeleteAsync(orgUser);
|
|
|
|
|
|
|
|
|
|
|
|
if (orgUser.UserId.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
await DeleteAndPushUserRegistrationAsync(orgUser.OrganizationId, orgUser.UserId.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-22 09:20:57 -07:00
|
|
|
|
private async Task<IEnumerable<string>> GetUserDeviceIdsAsync(Guid userId)
|
2024-10-16 10:33:00 +01:00
|
|
|
|
{
|
|
|
|
|
|
var devices = await _deviceRepository.GetManyByUserIdAsync(userId);
|
|
|
|
|
|
return devices
|
|
|
|
|
|
.Where(d => !string.IsNullOrWhiteSpace(d.PushToken))
|
2024-10-22 09:20:57 -07:00
|
|
|
|
.Select(d => d.Id.ToString());
|
2024-10-16 10:33:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task DeleteAndPushUserRegistrationAsync(Guid organizationId, Guid userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var devices = await GetUserDeviceIdsAsync(userId);
|
|
|
|
|
|
await _pushRegistrationService.DeleteUserRegistrationOrganizationAsync(devices,
|
|
|
|
|
|
organizationId.ToString());
|
|
|
|
|
|
await _pushNotificationService.PushSyncOrgKeysAsync(userId);
|
|
|
|
|
|
}
|
2022-10-31 09:58:21 +00:00
|
|
|
|
}
|