1
0
mirror of https://github.com/bitwarden/server synced 2025-12-27 21:53:24 +00:00

Sync Stripe customer details for Provider / Organization in API & Admin

This commit is contained in:
Alex Morask
2025-12-03 09:19:14 -06:00
parent 28e9c24f33
commit 7d60297d6f
9 changed files with 373 additions and 27 deletions

View File

@@ -1,5 +1,4 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Billing;
using Bit.Core.Billing.Constants;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Models.Sales;
@@ -392,12 +391,13 @@ public class OrganizationBillingServiceTests
}
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenNameIsLong_TruncatesTo30Characters(
public async Task UpdateOrganizationNameAndEmail_WhenNameIsLong_UsesFullName(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
// Arrange
organization.Name = "This is a very long organization name that exceeds thirty characters";
var longName = "This is a very long organization name that exceeds thirty characters";
organization.Name = longName;
CustomerUpdateOptions capturedOptions = null;
sutProvider.GetDependency<IStripeAdapter>()
@@ -421,14 +421,11 @@ public class OrganizationBillingServiceTests
Assert.NotNull(capturedOptions.InvoiceSettings.CustomFields);
var customField = capturedOptions.InvoiceSettings.CustomFields.First();
Assert.Equal(30, customField.Value.Length);
var expectedCustomFieldDisplayName = "This is a very long organizati";
Assert.Equal(expectedCustomFieldDisplayName, customField.Value);
Assert.Equal(longName, customField.Value);
}
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenGatewayCustomerIdIsNull_ThrowsBillingException(
public async Task UpdateOrganizationNameAndEmail_WhenGatewayCustomerIdIsNull_LogsWarningAndReturns(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
@@ -436,15 +433,93 @@ public class OrganizationBillingServiceTests
organization.GatewayCustomerId = null;
organization.Name = "Test Organization";
organization.BillingEmail = "billing@example.com";
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
// Act & Assert
var exception = await Assert.ThrowsAsync<BillingException>(
() => sutProvider.Sut.UpdateOrganizationNameAndEmail(organization));
// Act
await sutProvider.Sut.UpdateOrganizationNameAndEmail(organization);
Assert.Contains("Cannot update an organization in Stripe without a GatewayCustomerId.", exception.Response);
// Assert
await stripeAdapter.DidNotReceive().CustomerUpdateAsync(
Arg.Any<string>(),
Arg.Any<CustomerUpdateOptions>());
}
await sutProvider.GetDependency<IStripeAdapter>()
.DidNotReceiveWithAnyArgs()
.CustomerUpdateAsync(Arg.Any<string>(), Arg.Any<CustomerUpdateOptions>());
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenGatewayCustomerIdIsEmpty_LogsWarningAndReturns(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
// Arrange
organization.GatewayCustomerId = "";
organization.Name = "Test Organization";
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
// Act
await sutProvider.Sut.UpdateOrganizationNameAndEmail(organization);
// Assert
await stripeAdapter.DidNotReceive().CustomerUpdateAsync(
Arg.Any<string>(),
Arg.Any<CustomerUpdateOptions>());
}
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenNameIsNull_LogsWarningAndReturns(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
// Arrange
organization.Name = null;
organization.GatewayCustomerId = "cus_test123";
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
// Act
await sutProvider.Sut.UpdateOrganizationNameAndEmail(organization);
// Assert
await stripeAdapter.DidNotReceive().CustomerUpdateAsync(
Arg.Any<string>(),
Arg.Any<CustomerUpdateOptions>());
}
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenNameIsEmpty_LogsWarningAndReturns(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
// Arrange
organization.Name = "";
organization.GatewayCustomerId = "cus_test123";
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
// Act
await sutProvider.Sut.UpdateOrganizationNameAndEmail(organization);
// Assert
await stripeAdapter.DidNotReceive().CustomerUpdateAsync(
Arg.Any<string>(),
Arg.Any<CustomerUpdateOptions>());
}
[Theory, BitAutoData]
public async Task UpdateOrganizationNameAndEmail_WhenBillingEmailIsNull_UpdatesWithNull(
Organization organization,
SutProvider<OrganizationBillingService> sutProvider)
{
// Arrange
organization.Name = "Test Organization";
organization.BillingEmail = null;
organization.GatewayCustomerId = "cus_test123";
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
// Act
await sutProvider.Sut.UpdateOrganizationNameAndEmail(organization);
// Assert
await stripeAdapter.Received(1).CustomerUpdateAsync(
organization.GatewayCustomerId,
Arg.Is<CustomerUpdateOptions>(options =>
options.Email == null &&
options.Description == organization.Name));
}
}