1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-06 02:22:49 -05:00

[AC-1758] Implement RemoveOrganizationFromProviderCommand (#3515)

* Add RemovePaymentMethod to StripePaymentService

* Add SendProviderUpdatePaymentMethod to HandlebarsMailService

* Add RemoveOrganizationFromProviderCommand

* Use RemoveOrganizationFromProviderCommand in ProviderOrganizationController

* Remove RemoveOrganizationAsync from ProviderService

* Add RemoveOrganizationFromProviderCommandTests

* PR review feedback and refactoring

* Remove RemovePaymentMethod from StripePaymentService

* Review feedback

* Add Organization RisksSubscriptionFailure endpoint

* fix build error

* Review feedback

* [AC-1359] Bitwarden Portal Unlink Provider Buttons (#3588)

* Added ability to unlink organization from provider from provider edit page

* Refreshing provider edit page after removing an org

* Added button to organization to remove the org from the provider

* Updated based on product feedback

* Removed organization name from alert message

* Temporary logging

* Remove coupon from Stripe org after disconnected from MSP

* Updated test

* Change payment terms on org disconnect from MSP

* Set Stripe account email to new billing email

* Remove logging

---------

Co-authored-by: Conner Turnbull <133619638+cturnbull-bitwarden@users.noreply.github.com>
Co-authored-by: Conner Turnbull <cturnbull@bitwarden.com>
This commit is contained in:
Alex Morask
2024-01-12 10:38:47 -05:00
committed by GitHub
parent 505508a416
commit 95139def0f
35 changed files with 1168 additions and 119 deletions

View File

@ -40,7 +40,6 @@ public class OrganizationsController : Controller
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IPolicyRepository _policyRepository;
private readonly IProviderRepository _providerRepository;
private readonly IOrganizationService _organizationService;
private readonly IUserService _userService;
private readonly IPaymentService _paymentService;
@ -51,7 +50,6 @@ public class OrganizationsController : Controller
private readonly IRotateOrganizationApiKeyCommand _rotateOrganizationApiKeyCommand;
private readonly ICreateOrganizationApiKeyCommand _createOrganizationApiKeyCommand;
private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
private readonly IUpdateOrganizationLicenseCommand _updateOrganizationLicenseCommand;
private readonly ICloudGetOrganizationLicenseQuery _cloudGetOrganizationLicenseQuery;
private readonly IFeatureService _featureService;
private readonly GlobalSettings _globalSettings;
@ -64,7 +62,6 @@ public class OrganizationsController : Controller
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IPolicyRepository policyRepository,
IProviderRepository providerRepository,
IOrganizationService organizationService,
IUserService userService,
IPaymentService paymentService,
@ -75,7 +72,6 @@ public class OrganizationsController : Controller
IRotateOrganizationApiKeyCommand rotateOrganizationApiKeyCommand,
ICreateOrganizationApiKeyCommand createOrganizationApiKeyCommand,
IOrganizationApiKeyRepository organizationApiKeyRepository,
IUpdateOrganizationLicenseCommand updateOrganizationLicenseCommand,
ICloudGetOrganizationLicenseQuery cloudGetOrganizationLicenseQuery,
IFeatureService featureService,
GlobalSettings globalSettings,
@ -87,7 +83,6 @@ public class OrganizationsController : Controller
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_policyRepository = policyRepository;
_providerRepository = providerRepository;
_organizationService = organizationService;
_userService = userService;
_paymentService = paymentService;
@ -98,7 +93,6 @@ public class OrganizationsController : Controller
_rotateOrganizationApiKeyCommand = rotateOrganizationApiKeyCommand;
_createOrganizationApiKeyCommand = createOrganizationApiKeyCommand;
_organizationApiKeyRepository = organizationApiKeyRepository;
_updateOrganizationLicenseCommand = updateOrganizationLicenseCommand;
_cloudGetOrganizationLicenseQuery = cloudGetOrganizationLicenseQuery;
_featureService = featureService;
_globalSettings = globalSettings;
@ -245,6 +239,21 @@ public class OrganizationsController : Controller
return new OrganizationAutoEnrollStatusResponseModel(organization.Id, data?.AutoEnrollEnabled ?? false);
}
[HttpGet("{id}/risks-subscription-failure")]
public async Task<OrganizationRisksSubscriptionFailureResponseModel> RisksSubscriptionFailure(Guid id)
{
if (!await _currentContext.EditPaymentMethods(id))
{
return new OrganizationRisksSubscriptionFailureResponseModel(id, false);
}
var organization = await _organizationRepository.GetByIdAsync(id);
var risksSubscriptionFailure = await _paymentService.RisksSubscriptionFailure(organization);
return new OrganizationRisksSubscriptionFailureResponseModel(id, risksSubscriptionFailure);
}
[HttpPost("")]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<OrganizationResponseModel> Post([FromBody] OrganizationCreateRequestModel model)

View File

@ -1,10 +1,13 @@
using Bit.Api.AdminConsole.Models.Request.Providers;
using Bit.Api.AdminConsole.Models.Response.Providers;
using Bit.Api.Models.Response;
using Bit.Core.AdminConsole.Providers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Services;
using Bit.Core.Billing.Commands;
using Bit.Core.Context;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
@ -16,22 +19,33 @@ namespace Bit.Api.AdminConsole.Controllers;
[Authorize("Application")]
public class ProviderOrganizationsController : Controller
{
private readonly IProviderOrganizationRepository _providerOrganizationRepository;
private readonly IProviderService _providerService;
private readonly IUserService _userService;
private readonly ICurrentContext _currentContext;
private readonly IOrganizationRepository _organizationRepository;
private readonly IProviderOrganizationRepository _providerOrganizationRepository;
private readonly IProviderRepository _providerRepository;
private readonly IProviderService _providerService;
private readonly IRemoveOrganizationFromProviderCommand _removeOrganizationFromProviderCommand;
private readonly IRemovePaymentMethodCommand _removePaymentMethodCommand;
private readonly IUserService _userService;
public ProviderOrganizationsController(
ICurrentContext currentContext,
IOrganizationRepository organizationRepository,
IProviderOrganizationRepository providerOrganizationRepository,
IProviderRepository providerRepository,
IProviderService providerService,
IUserService userService,
ICurrentContext currentContext)
IRemoveOrganizationFromProviderCommand removeOrganizationFromProviderCommand,
IRemovePaymentMethodCommand removePaymentMethodCommand,
IUserService userService)
{
_providerOrganizationRepository = providerOrganizationRepository;
_providerService = providerService;
_userService = userService;
_currentContext = currentContext;
_organizationRepository = organizationRepository;
_providerOrganizationRepository = providerOrganizationRepository;
_providerRepository = providerRepository;
_providerService = providerService;
_removeOrganizationFromProviderCommand = removeOrganizationFromProviderCommand;
_removePaymentMethodCommand = removePaymentMethodCommand;
_userService = userService;
}
[HttpGet("")]
@ -87,7 +101,17 @@ public class ProviderOrganizationsController : Controller
throw new NotFoundException();
}
var userId = _userService.GetProperUserId(User);
await _providerService.RemoveOrganizationAsync(providerId, id, userId.Value);
var provider = await _providerRepository.GetByIdAsync(providerId);
var providerOrganization = await _providerOrganizationRepository.GetByIdAsync(id);
var organization = await _organizationRepository.GetByIdAsync(providerOrganization.OrganizationId);
await _removeOrganizationFromProviderCommand.RemoveOrganizationFromProvider(
provider,
providerOrganization,
organization);
await _removePaymentMethodCommand.RemovePaymentMethod(organization);
}
}

View File

@ -0,0 +1,17 @@
using Bit.Core.Models.Api;
namespace Bit.Api.AdminConsole.Models.Response.Organizations;
public class OrganizationRisksSubscriptionFailureResponseModel : ResponseModel
{
public Guid OrganizationId { get; }
public bool RisksSubscriptionFailure { get; }
public OrganizationRisksSubscriptionFailureResponseModel(
Guid organizationId,
bool risksSubscriptionFailure) : base("organizationRisksSubscriptionFailure")
{
OrganizationId = organizationId;
RisksSubscriptionFailure = risksSubscriptionFailure;
}
}

View File

@ -26,6 +26,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Bit.Core.Auth.Identity;
using Bit.Core.Auth.UserFeatures;
using Bit.Core.Entities;
using Bit.Core.Billing.Extensions;
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions;
using Bit.Core.Tools.Entities;
using Bit.Core.Vault.Entities;
@ -169,6 +170,7 @@ public class Startup
services.AddDefaultServices(globalSettings);
services.AddOrganizationSubscriptionServices();
services.AddCoreLocalizationServices();
services.AddBillingCommands();
// Authorization Handlers
services.AddAuthorizationHandlers();