1
0
mirror of https://github.com/bitwarden/server synced 2025-12-06 00:03:34 +00:00

[PM-27849] Check for sm-standalone on subscription (#6545)

* Fix coupon check

* Fixed in FF off scenario

* Run dotnet format
This commit is contained in:
Alex Morask
2025-11-11 16:01:48 -06:00
committed by GitHub
parent ea233580d2
commit 691047039b
4 changed files with 107 additions and 113 deletions

View File

@@ -22,11 +22,6 @@ public class GetOrganizationMetadataQuery(
{ {
public async Task<OrganizationMetadata?> Run(Organization organization) public async Task<OrganizationMetadata?> Run(Organization organization)
{ {
if (organization == null)
{
return null;
}
if (globalSettings.SelfHosted) if (globalSettings.SelfHosted)
{ {
return OrganizationMetadata.Default; return OrganizationMetadata.Default;
@@ -42,10 +37,12 @@ public class GetOrganizationMetadataQuery(
}; };
} }
var customer = await subscriberService.GetCustomer(organization, var customer = await subscriberService.GetCustomer(organization);
new CustomerGetOptions { Expand = ["discount.coupon.applies_to"] });
var subscription = await subscriberService.GetSubscription(organization); var subscription = await subscriberService.GetSubscription(organization, new SubscriptionGetOptions
{
Expand = ["discounts.coupon.applies_to"]
});
if (customer == null || subscription == null) if (customer == null || subscription == null)
{ {
@@ -79,16 +76,17 @@ public class GetOrganizationMetadataQuery(
return false; return false;
} }
var hasCoupon = customer.Discount?.Coupon?.Id == StripeConstants.CouponIDs.SecretsManagerStandalone; var coupon = subscription.Discounts?.FirstOrDefault(discount =>
discount.Coupon?.Id == StripeConstants.CouponIDs.SecretsManagerStandalone)?.Coupon;
if (!hasCoupon) if (coupon == null)
{ {
return false; return false;
} }
var subscriptionProductIds = subscription.Items.Data.Select(item => item.Plan.ProductId); var subscriptionProductIds = subscription.Items.Data.Select(item => item.Plan.ProductId);
var couponAppliesTo = customer.Discount?.Coupon?.AppliesTo?.Products; var couponAppliesTo = coupon.AppliesTo?.Products;
return subscriptionProductIds.Intersect(couponAppliesTo ?? []).Any(); return subscriptionProductIds.Intersect(couponAppliesTo ?? []).Any();
} }

View File

@@ -79,10 +79,12 @@ public class OrganizationBillingService(
}; };
} }
var customer = await subscriberService.GetCustomer(organization, var customer = await subscriberService.GetCustomer(organization);
new CustomerGetOptions { Expand = ["discount.coupon.applies_to"] });
var subscription = await subscriberService.GetSubscription(organization); var subscription = await subscriberService.GetSubscription(organization, new SubscriptionGetOptions
{
Expand = ["discounts.coupon.applies_to"]
});
if (customer == null || subscription == null) if (customer == null || subscription == null)
{ {
@@ -542,16 +544,17 @@ public class OrganizationBillingService(
return false; return false;
} }
var hasCoupon = customer.Discount?.Coupon?.Id == StripeConstants.CouponIDs.SecretsManagerStandalone; var coupon = subscription.Discounts?.FirstOrDefault(discount =>
discount.Coupon?.Id == StripeConstants.CouponIDs.SecretsManagerStandalone)?.Coupon;
if (!hasCoupon) if (coupon == null)
{ {
return false; return false;
} }
var subscriptionProductIds = subscription.Items.Data.Select(item => item.Plan.ProductId); var subscriptionProductIds = subscription.Items.Data.Select(item => item.Plan.ProductId);
var couponAppliesTo = customer.Discount?.Coupon?.AppliesTo?.Products; var couponAppliesTo = coupon.AppliesTo?.Products;
return subscriptionProductIds.Intersect(couponAppliesTo ?? []).Any(); return subscriptionProductIds.Intersect(couponAppliesTo ?? []).Any();
} }

View File

@@ -21,15 +21,6 @@ namespace Bit.Core.Test.Billing.Organizations.Queries;
[SutProviderCustomize] [SutProviderCustomize]
public class GetOrganizationMetadataQueryTests public class GetOrganizationMetadataQueryTests
{ {
[Theory, BitAutoData]
public async Task Run_NullOrganization_ReturnsNull(
SutProvider<GetOrganizationMetadataQuery> sutProvider)
{
var result = await sutProvider.Sut.Run(null);
Assert.Null(result);
}
[Theory, BitAutoData] [Theory, BitAutoData]
public async Task Run_SelfHosted_ReturnsDefault( public async Task Run_SelfHosted_ReturnsDefault(
Organization organization, Organization organization,
@@ -74,8 +65,7 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 5, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 5, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.ReturnsNull(); .ReturnsNull();
var result = await sutProvider.Sut.Run(organization); var result = await sutProvider.Sut.Run(organization);
@@ -100,12 +90,12 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 7, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 7, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer); .Returns(customer);
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetSubscription(organization) .GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to")))
.ReturnsNull(); .ReturnsNull();
var result = await sutProvider.Sut.Run(organization); var result = await sutProvider.Sut.Run(organization);
@@ -124,9 +114,13 @@ public class GetOrganizationMetadataQueryTests
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseAnnually;
var productId = "product_123"; var productId = "product_123";
var customer = new Customer var customer = new Customer();
var subscription = new Subscription
{ {
Discount = new Discount Discounts =
[
new Discount
{ {
Coupon = new Coupon Coupon = new Coupon
{ {
@@ -137,10 +131,7 @@ public class GetOrganizationMetadataQueryTests
} }
} }
} }
}; ],
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem> Items = new StripeList<SubscriptionItem>
{ {
Data = Data =
@@ -162,12 +153,12 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 15, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 15, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer); .Returns(customer);
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetSubscription(organization) .GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to")))
.Returns(subscription); .Returns(subscription);
sutProvider.GetDependency<IPricingClient>() sutProvider.GetDependency<IPricingClient>()
@@ -189,13 +180,11 @@ public class GetOrganizationMetadataQueryTests
organization.GatewaySubscriptionId = "sub_123"; organization.GatewaySubscriptionId = "sub_123";
organization.PlanType = PlanType.TeamsAnnually; organization.PlanType = PlanType.TeamsAnnually;
var customer = new Customer var customer = new Customer();
{
Discount = null
};
var subscription = new Subscription var subscription = new Subscription
{ {
Discounts = null,
Items = new StripeList<SubscriptionItem> Items = new StripeList<SubscriptionItem>
{ {
Data = Data =
@@ -217,12 +206,12 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 20, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 20, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer); .Returns(customer);
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetSubscription(organization) .GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to")))
.Returns(subscription); .Returns(subscription);
sutProvider.GetDependency<IPricingClient>() sutProvider.GetDependency<IPricingClient>()
@@ -244,9 +233,13 @@ public class GetOrganizationMetadataQueryTests
organization.GatewaySubscriptionId = "sub_123"; organization.GatewaySubscriptionId = "sub_123";
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseAnnually;
var customer = new Customer var customer = new Customer();
var subscription = new Subscription
{ {
Discount = new Discount Discounts =
[
new Discount
{ {
Coupon = new Coupon Coupon = new Coupon
{ {
@@ -257,10 +250,7 @@ public class GetOrganizationMetadataQueryTests
} }
} }
} }
}; ],
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem> Items = new StripeList<SubscriptionItem>
{ {
Data = Data =
@@ -282,12 +272,12 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 12, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 12, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer); .Returns(customer);
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetSubscription(organization) .GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to")))
.Returns(subscription); .Returns(subscription);
sutProvider.GetDependency<IPricingClient>() sutProvider.GetDependency<IPricingClient>()
@@ -310,9 +300,13 @@ public class GetOrganizationMetadataQueryTests
organization.PlanType = PlanType.FamiliesAnnually; organization.PlanType = PlanType.FamiliesAnnually;
var productId = "product_123"; var productId = "product_123";
var customer = new Customer var customer = new Customer();
var subscription = new Subscription
{ {
Discount = new Discount Discounts =
[
new Discount
{ {
Coupon = new Coupon Coupon = new Coupon
{ {
@@ -323,10 +317,7 @@ public class GetOrganizationMetadataQueryTests
} }
} }
} }
}; ],
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem> Items = new StripeList<SubscriptionItem>
{ {
Data = Data =
@@ -348,12 +339,12 @@ public class GetOrganizationMetadataQueryTests
.Returns(new OrganizationSeatCounts { Users = 8, Sponsored = 0 }); .Returns(new OrganizationSeatCounts { Users = 8, Sponsored = 0 });
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => .GetCustomer(organization)
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer); .Returns(customer);
sutProvider.GetDependency<ISubscriberService>() sutProvider.GetDependency<ISubscriberService>()
.GetSubscription(organization) .GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to")))
.Returns(subscription); .Returns(subscription);
sutProvider.GetDependency<IPricingClient>() sutProvider.GetDependency<IPricingClient>()

View File

@@ -38,9 +38,18 @@ public class OrganizationBillingServiceTests
var subscriberService = sutProvider.GetDependency<ISubscriberService>(); var subscriberService = sutProvider.GetDependency<ISubscriberService>();
var organizationSeatCount = new OrganizationSeatCounts { Users = 1, Sponsored = 0 }; var organizationSeatCount = new OrganizationSeatCounts { Users = 1, Sponsored = 0 };
var customer = new Customer var customer = new Customer();
subscriberService
.GetCustomer(organization)
.Returns(customer);
subscriberService.GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to"))).Returns(new Subscription
{ {
Discount = new Discount Discounts =
[
new Discount
{ {
Coupon = new Coupon Coupon = new Coupon
{ {
@@ -51,15 +60,7 @@ public class OrganizationBillingServiceTests
} }
} }
} }
}; ],
subscriberService
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options =>
options.Expand.Contains("discount.coupon.applies_to")))
.Returns(customer);
subscriberService.GetSubscription(organization).Returns(new Subscription
{
Items = new StripeList<SubscriptionItem> Items = new StripeList<SubscriptionItem>
{ {
Data = Data =
@@ -109,11 +110,12 @@ public class OrganizationBillingServiceTests
// Set up subscriber service to return null for customer // Set up subscriber service to return null for customer
subscriberService subscriberService
.GetCustomer(organization, Arg.Is<CustomerGetOptions>(options => options.Expand.FirstOrDefault() == "discount.coupon.applies_to")) .GetCustomer(organization)
.Returns((Customer)null); .Returns((Customer)null);
// Set up subscriber service to return null for subscription // Set up subscriber service to return null for subscription
subscriberService.GetSubscription(organization).Returns((Subscription)null); subscriberService.GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
options.Expand.Contains("discounts.coupon.applies_to"))).Returns((Subscription)null);
var metadata = await sutProvider.Sut.GetMetadata(organizationId); var metadata = await sutProvider.Sut.GetMetadata(organizationId);