1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

[PM-16684] Integrate Pricing Service behind FF (#5276)

* Remove gRPC and convert PricingClient to HttpClient wrapper

* Add PlanType.GetProductTier extension

Many instances of StaticStore use are just to get the ProductTierType of a PlanType, but this can be derived from the PlanType itself without having to fetch the entire plan.

* Remove invocations of the StaticStore in non-Test code

* Deprecate StaticStore entry points

* Run dotnet format

* Matt's feedback

* Run dotnet format

* Rui's feedback

* Run dotnet format

* Replacements since approval

* Run dotnet format
This commit is contained in:
Alex Morask
2025-02-27 07:55:46 -05:00
committed by GitHub
parent bd66f06bd9
commit a2e665cb96
78 changed files with 1178 additions and 712 deletions

View File

@ -2,6 +2,7 @@
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Models.Sales;
using Bit.Core.Billing.Pricing;
using Bit.Core.Billing.Services;
using Bit.Core.Entities;
using Bit.Core.Enums;
@ -38,6 +39,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.IsFromSecretsManagerTrial = false;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
await sutProvider.GetDependency<IOrganizationRepository>().Received(1).CreateAsync(
@ -66,7 +69,7 @@ public class CloudICloudOrganizationSignUpCommandTests
sale.CustomerSetup.TokenizedPaymentSource.Token == signup.PaymentToken &&
sale.CustomerSetup.TaxInformation.Country == signup.TaxInfo.BillingAddressCountry &&
sale.CustomerSetup.TaxInformation.PostalCode == signup.TaxInfo.BillingAddressPostalCode &&
sale.SubscriptionSetup.Plan == plan &&
sale.SubscriptionSetup.PlanType == plan.Type &&
sale.SubscriptionSetup.PasswordManagerOptions.Seats == signup.AdditionalSeats &&
sale.SubscriptionSetup.PasswordManagerOptions.Storage == signup.AdditionalStorageGb &&
sale.SubscriptionSetup.SecretsManagerOptions == null));
@ -84,6 +87,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.UseSecretsManager = false;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
// Extract orgUserId when created
Guid? orgUserId = null;
await sutProvider.GetDependency<IOrganizationUserRepository>()
@ -128,6 +133,7 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.IsFromSecretsManagerTrial = false;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
@ -157,7 +163,7 @@ public class CloudICloudOrganizationSignUpCommandTests
sale.CustomerSetup.TokenizedPaymentSource.Token == signup.PaymentToken &&
sale.CustomerSetup.TaxInformation.Country == signup.TaxInfo.BillingAddressCountry &&
sale.CustomerSetup.TaxInformation.PostalCode == signup.TaxInfo.BillingAddressPostalCode &&
sale.SubscriptionSetup.Plan == plan &&
sale.SubscriptionSetup.PlanType == plan.Type &&
sale.SubscriptionSetup.PasswordManagerOptions.Seats == signup.AdditionalSeats &&
sale.SubscriptionSetup.PasswordManagerOptions.Storage == signup.AdditionalStorageGb &&
sale.SubscriptionSetup.SecretsManagerOptions.Seats == signup.AdditionalSmSeats &&
@ -177,6 +183,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.PremiumAccessAddon = false;
signup.IsFromProvider = true;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.SignUpOrganizationAsync(signup));
Assert.Contains("Organizations with a Managed Service Provider do not support Secrets Manager.", exception.Message);
}
@ -195,6 +203,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.AdditionalStorageGb = 0;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
Assert.Contains("Plan does not allow additional Machine Accounts.", exception.Message);
@ -213,6 +223,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.AdditionalServiceAccounts = 10;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
Assert.Contains("You cannot have more Secrets Manager seats than Password Manager seats", exception.Message);
@ -231,6 +243,8 @@ public class CloudICloudOrganizationSignUpCommandTests
signup.AdditionalServiceAccounts = -10;
signup.IsFromProvider = false;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
Assert.Contains("You can't subtract Machine Accounts!", exception.Message);
@ -249,6 +263,8 @@ public class CloudICloudOrganizationSignUpCommandTests
Owner = new User { Id = Guid.NewGuid() }
};
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id)
.Returns(1);

View File

@ -10,6 +10,7 @@ using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Repositories;
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Pricing;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
@ -203,10 +204,12 @@ public class OrganizationServiceTests
{
signup.Plan = PlanType.TeamsMonthly;
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);
var plan = StaticStore.GetPlan(signup.Plan);
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(plan);
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);
await sutProvider.GetDependency<IOrganizationRepository>().Received(1).CreateAsync(Arg.Is<Organization>(org =>
org.Id == organization.Id &&
org.Name == signup.Name &&
@ -894,6 +897,8 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
SetupOrgUserRepositoryCreateManyAsyncMock(organizationUserRepository);
SetupOrgUserRepositoryCreateAsyncMock(organizationUserRepository);
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
await sutProvider.Sut.InviteUsersAsync(organization.Id, savingUser.Id, systemUser: null, invites);
await sutProvider.GetDependency<IUpdateSecretsManagerSubscriptionCommand>().Received(1)
@ -933,6 +938,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
sutProvider.GetDependency<IReferenceEventService>().RaiseEventAsync(default)
.ThrowsForAnyArgs<BadRequestException>();
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
.Returns(StaticStore.GetPlan(organization.PlanType));
await Assert.ThrowsAsync<AggregateException>(async () =>
await sutProvider.Sut.InviteUsersAsync(organization.Id, savingUser.Id, systemUser: null, invites));
@ -1338,6 +1346,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
organization.MaxAutoscaleSeats = currentMaxAutoscaleSeats;
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
.Returns(StaticStore.GetPlan(organization.PlanType));
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscription(organization.Id,
seatAdjustment, maxAutoscaleSeats));
@ -1360,6 +1371,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
organization.Seats = 100;
organization.SmSeats = 100;
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
.Returns(StaticStore.GetPlan(organization.PlanType));
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
var actual = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscription(organization.Id, seatAdjustment, null));