1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-01 08:02: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

@ -60,6 +60,11 @@ public interface IMailService
Task SendProviderInviteEmailAsync(string providerName, ProviderUser providerUser, string token, string email);
Task SendProviderConfirmedEmailAsync(string providerName, string email);
Task SendProviderUserRemoved(string providerName, string email);
Task SendProviderUpdatePaymentMethod(
Guid organizationId,
string organizationName,
string providerName,
IEnumerable<string> emails);
Task SendUpdatedTempPasswordEmailAsync(string email, string userName);
Task SendFamiliesForEnterpriseOfferEmailAsync(string sponsorOrgName, string email, bool existingAccount, string token);
Task BulkSendFamiliesForEnterpriseOfferEmailAsync(string SponsorOrgName, IEnumerable<(string Email, bool ExistingAccount, string Token)> invites);

View File

@ -49,4 +49,5 @@ public interface IPaymentService
Task ArchiveTaxRateAsync(TaxRate taxRate);
Task<string> AddSecretsManagerToSubscription(Organization org, Plan plan, int additionalSmSeats,
int additionalServiceAccount, DateTime? prorationDate = null);
Task<bool> RisksSubscriptionFailure(Organization organization);
}

View File

@ -23,6 +23,7 @@ public interface IStripeAdapter
Task<Stripe.Invoice> InvoiceDeleteAsync(string id, Stripe.InvoiceDeleteOptions options = null);
Task<Stripe.Invoice> InvoiceVoidInvoiceAsync(string id, Stripe.InvoiceVoidOptions options = null);
IEnumerable<Stripe.PaymentMethod> PaymentMethodListAutoPaging(Stripe.PaymentMethodListOptions options);
IAsyncEnumerable<Stripe.PaymentMethod> PaymentMethodListAutoPagingAsync(Stripe.PaymentMethodListOptions options);
Task<Stripe.PaymentMethod> PaymentMethodAttachAsync(string id, Stripe.PaymentMethodAttachOptions options = null);
Task<Stripe.PaymentMethod> PaymentMethodDetachAsync(string id, Stripe.PaymentMethodDetachOptions options = null);
Task<Stripe.TaxRate> TaxRateCreateAsync(Stripe.TaxRateCreateOptions options);

View File

@ -754,6 +754,30 @@ public class HandlebarsMailService : IMailService
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendProviderUpdatePaymentMethod(
Guid organizationId,
string organizationName,
string providerName,
IEnumerable<string> emails)
{
var message = CreateDefaultMessage("Update your billing information", emails);
var model = new ProviderUpdatePaymentMethodViewModel
{
OrganizationId = organizationId.ToString(),
OrganizationName = CoreHelpers.SanitizeForEmail(organizationName),
ProviderName = CoreHelpers.SanitizeForEmail(providerName),
SiteName = _globalSettings.SiteName,
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash
};
await AddMessageContentAsync(message, "Provider.ProviderUpdatePaymentMethod", model);
message.Category = "ProviderUpdatePaymentMethod";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendUpdatedTempPasswordEmailAsync(string email, string userName)
{
var message = CreateDefaultMessage("Master Password Has Been Changed", email);

View File

@ -138,6 +138,9 @@ public class StripeAdapter : IStripeAdapter
return _paymentMethodService.ListAutoPaging(options);
}
public IAsyncEnumerable<Stripe.PaymentMethod> PaymentMethodListAutoPagingAsync(Stripe.PaymentMethodListOptions options)
=> _paymentMethodService.ListAutoPagingAsync(options);
public Task<Stripe.PaymentMethod> PaymentMethodAttachAsync(string id, Stripe.PaymentMethodAttachOptions options = null)
{
return _paymentMethodService.AttachAsync(id, options);

View File

@ -1614,6 +1614,23 @@ public class StripePaymentService : IPaymentService
return await FinalizeSubscriptionChangeAsync(org, new SecretsManagerSubscribeUpdate(org, plan, additionalSmSeats, additionalServiceAccount), prorationDate);
}
public async Task<bool> RisksSubscriptionFailure(Organization organization)
{
var subscriptionInfo = await GetSubscriptionAsync(organization);
if (subscriptionInfo.Subscription is not { Status: "active" or "trialing" or "past_due" } ||
subscriptionInfo.UpcomingInvoice == null)
{
return false;
}
var customer = await GetCustomerAsync(organization.GatewayCustomerId);
var paymentSource = await GetBillingPaymentSourceAsync(customer);
return paymentSource == null;
}
private Stripe.PaymentMethod GetLatestCardPaymentMethod(string customerId)
{
var cardPaymentMethods = _stripeAdapter.PaymentMethodListAutoPaging(

View File

@ -197,6 +197,9 @@ public class NoopMailService : IMailService
return Task.FromResult(0);
}
public Task SendProviderUpdatePaymentMethod(Guid organizationId, string organizationName, string providerName,
IEnumerable<string> emails) => Task.FromResult(0);
public Task SendUpdatedTempPasswordEmailAsync(string email, string userName)
{
return Task.FromResult(0);