1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-04 01:22:50 -05:00

[PM-7004] Org Admin Initiate Delete (#3905)

* org delete

* move org id to URL path

* tweaks

* lint fixes

* Update src/Core/Services/Implementations/HandlebarsMailService.cs

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

* Update src/Core/Services/Implementations/HandlebarsMailService.cs

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

* PR feedback

* fix id

* [PM-7004] Move OrgDeleteTokenable to AdminConsole ownership

* [PM-7004] Add consolidated billing logic into organization delete request acceptance endpoint

* [PM-7004] Delete unused IOrganizationService.DeleteAsync(Organization organization, string token) method

* [PM-7004] Fix unit tests

* [PM-7004] Update delete organization request email templates

* Add success message when initiating organization deletion

* Refactor OrganizationsController request delete initiation action to handle exceptions

---------

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
Co-authored-by: Rui Tome <rtome@bitwarden.com>
This commit is contained in:
Kyle Spearrin
2024-05-22 12:59:19 -04:00
committed by GitHub
parent 56c523f76f
commit 4264fc0729
18 changed files with 334 additions and 28 deletions

View File

@ -4,6 +4,7 @@ using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Models.Business;
using Bit.Core.AdminConsole.Models.Business.Tokenables;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
@ -60,6 +61,7 @@ public class OrganizationService : IOrganizationService
private readonly IProviderUserRepository _providerUserRepository;
private readonly ICountNewSmSeatsRequiredQuery _countNewSmSeatsRequiredQuery;
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand;
private readonly IDataProtectorTokenFactory<OrgDeleteTokenable> _orgDeleteTokenDataFactory;
private readonly IProviderRepository _providerRepository;
private readonly IOrgUserInviteTokenableFactory _orgUserInviteTokenableFactory;
private readonly IDataProtectorTokenFactory<OrgUserInviteTokenable> _orgUserInviteTokenDataFactory;
@ -94,6 +96,7 @@ public class OrganizationService : IOrganizationService
IOrgUserInviteTokenableFactory orgUserInviteTokenableFactory,
IDataProtectorTokenFactory<OrgUserInviteTokenable> orgUserInviteTokenDataFactory,
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand,
IDataProtectorTokenFactory<OrgDeleteTokenable> orgDeleteTokenDataFactory,
IProviderRepository providerRepository,
IFeatureService featureService)
{
@ -123,6 +126,7 @@ public class OrganizationService : IOrganizationService
_providerUserRepository = providerUserRepository;
_countNewSmSeatsRequiredQuery = countNewSmSeatsRequiredQuery;
_updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand;
_orgDeleteTokenDataFactory = orgDeleteTokenDataFactory;
_providerRepository = providerRepository;
_orgUserInviteTokenableFactory = orgUserInviteTokenableFactory;
_orgUserInviteTokenDataFactory = orgUserInviteTokenDataFactory;
@ -811,6 +815,23 @@ public class OrganizationService : IOrganizationService
}
}
public async Task InitiateDeleteAsync(Organization organization, string orgAdminEmail)
{
var orgAdmin = await _userRepository.GetByEmailAsync(orgAdminEmail);
if (orgAdmin == null)
{
throw new BadRequestException("Org admin not found.");
}
var orgAdminOrgUser = await _organizationUserRepository.GetDetailsByUserAsync(orgAdmin.Id, organization.Id);
if (orgAdminOrgUser == null || orgAdminOrgUser.Status != OrganizationUserStatusType.Confirmed ||
(orgAdminOrgUser.Type != OrganizationUserType.Admin && orgAdminOrgUser.Type != OrganizationUserType.Owner))
{
throw new BadRequestException("Org admin not found.");
}
var token = _orgDeleteTokenDataFactory.Protect(new OrgDeleteTokenable(organization, 1));
await _mailService.SendInitiateDeleteOrganzationEmailAsync(orgAdminEmail, organization, token);
}
public async Task DeleteAsync(Organization organization)
{
await ValidateDeleteOrganizationAsync(organization);