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

[AC-1754] Provide upgrade flow for paid organizations (#3468)

* wip

* Add CompleteSubscriptionUpdate

* Add AdjustSubscription to PaymentService

* Use PaymentService.AdjustSubscription in UpgradeOrganizationPlanCommand

* Add CompleteSubscriptionUpdateTests

* Remove unused changes

* Update UpgradeOrganizationPlanCommandTests

* Fixing missing usings after master merge

* Defects: AC-1958, AC-1959

* Allow user to unsubscribe from Secrets Manager and Storage during upgrade

* Handled null exception when upgrading away from a plan that doesn't allow secrets manager

* Resolved issue where Teams Starter couldn't increase storage

---------

Co-authored-by: Conner Turnbull <cturnbull@bitwarden.com>
Co-authored-by: Conner Turnbull <133619638+cturnbull-bitwarden@users.noreply.github.com>
This commit is contained in:
Alex Morask
2023-12-27 09:30:23 -05:00
committed by GitHub
parent cf4d8a4f92
commit c60f260c0f
15 changed files with 995 additions and 45 deletions

View File

@ -147,6 +147,40 @@ public class SecretsManagerOrganizationCustomization : ICustomization
}
}
internal class TeamsStarterOrganizationCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var organizationId = Guid.NewGuid();
const PlanType planType = PlanType.TeamsStarter;
fixture.Customize<Organization>(composer =>
composer
.With(organization => organization.Id, organizationId)
.With(organization => organization.PlanType, planType)
.With(organization => organization.Seats, 10)
.Without(organization => organization.MaxStorageGb));
}
}
internal class TeamsMonthlyWithAddOnsOrganizationCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var organizationId = Guid.NewGuid();
const PlanType planType = PlanType.TeamsMonthly;
fixture.Customize<Organization>(composer =>
composer
.With(organization => organization.Id, organizationId)
.With(organization => organization.PlanType, planType)
.With(organization => organization.Seats, 20)
.With(organization => organization.UseSecretsManager, true)
.With(organization => organization.SmSeats, 5)
.With(organization => organization.SmServiceAccounts, 53));
}
}
internal class OrganizationCustomizeAttribute : BitCustomizeAttribute
{
public bool UseGroups { get; set; }
@ -189,6 +223,16 @@ internal class SecretsManagerOrganizationCustomizeAttribute : BitCustomizeAttrib
new SecretsManagerOrganizationCustomization();
}
internal class TeamsStarterOrganizationCustomizeAttribute : BitCustomizeAttribute
{
public override ICustomization GetCustomization() => new TeamsStarterOrganizationCustomization();
}
internal class TeamsMonthlyWithAddOnsOrganizationCustomizeAttribute : BitCustomizeAttribute
{
public override ICustomization GetCustomization() => new TeamsMonthlyWithAddOnsOrganizationCustomization();
}
internal class EphemeralDataProtectionCustomization : ICustomization
{
public void Customize(IFixture fixture)

View File

@ -0,0 +1,530 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Business;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Utilities;
using Bit.Test.Common.AutoFixture.Attributes;
using Stripe;
using Xunit;
namespace Bit.Core.Test.Models.Business;
public class CompleteSubscriptionUpdateTests
{
[Theory]
[BitAutoData]
[TeamsStarterOrganizationCustomize]
public void UpgradeItemOptions_TeamsStarterToTeams_ReturnsCorrectOptions(
Organization organization)
{
var teamsStarterPlan = StaticStore.GetPlan(PlanType.TeamsStarter);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "subscription_item",
Price = new Price { Id = teamsStarterPlan.PasswordManager.StripePlanId },
Quantity = 1
}
}
}
};
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var updatedSubscriptionData = new SubscriptionData
{
Plan = teamsMonthlyPlan,
PurchasedPasswordManagerSeats = 20
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
Assert.Single(upgradeItemOptions);
var passwordManagerOptions = upgradeItemOptions.First();
Assert.Equal(subscription.Items.Data.FirstOrDefault()?.Id, passwordManagerOptions.Id);
Assert.Equal(teamsMonthlyPlan.PasswordManager.StripeSeatPlanId, passwordManagerOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedPasswordManagerSeats, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
}
[Theory]
[BitAutoData]
[TeamsMonthlyWithAddOnsOrganizationCustomize]
public void UpgradeItemOptions_TeamsWithSMToEnterpriseWithSM_ReturnsCorrectOptions(
Organization organization)
{
// 5 purchased, 1 base
organization.MaxStorageGb = 6;
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "password_manager_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.PasswordManager.StripeSeatPlanId },
Quantity = organization.Seats!.Value
},
new ()
{
Id = "secrets_manager_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.SecretsManager.StripeSeatPlanId },
Quantity = organization.SmSeats!.Value
},
new ()
{
Id = "secrets_manager_service_accounts_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId },
Quantity = organization.SmServiceAccounts!.Value
},
new ()
{
Id = "password_manager_storage_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.PasswordManager.StripeStoragePlanId },
Quantity = organization.Storage!.Value
}
}
}
};
var enterpriseMonthlyPlan = StaticStore.GetPlan(PlanType.EnterpriseMonthly);
var updatedSubscriptionData = new SubscriptionData
{
Plan = enterpriseMonthlyPlan,
PurchasedPasswordManagerSeats = 50,
SubscribedToSecretsManager = true,
PurchasedSecretsManagerSeats = 30,
PurchasedAdditionalSecretsManagerServiceAccounts = 10,
PurchasedAdditionalStorage = 10
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
Assert.Equal(4, upgradeItemOptions.Count);
var passwordManagerOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId);
var passwordManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_subscription_item");
Assert.Equal(passwordManagerSubscriptionItem?.Id, passwordManagerOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId, passwordManagerOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedPasswordManagerSeats, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
var secretsManagerOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId);
var secretsManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "secrets_manager_subscription_item");
Assert.Equal(secretsManagerSubscriptionItem?.Id, secretsManagerOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId, secretsManagerOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedSecretsManagerSeats, secretsManagerOptions.Quantity);
Assert.Null(secretsManagerOptions.Deleted);
var serviceAccountsOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId);
var serviceAccountsSubscriptionItem = subscription.Items.Data.FirstOrDefault(item =>
item.Id == "secrets_manager_service_accounts_subscription_item");
Assert.Equal(serviceAccountsSubscriptionItem?.Id, serviceAccountsOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId, serviceAccountsOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedAdditionalSecretsManagerServiceAccounts, serviceAccountsOptions.Quantity);
Assert.Null(serviceAccountsOptions.Deleted);
var storageOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId);
var storageSubscriptionItem = subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_storage_subscription_item");
Assert.Equal(storageSubscriptionItem?.Id, storageOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId, storageOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedAdditionalStorage, storageOptions.Quantity);
Assert.Null(storageOptions.Deleted);
}
[Theory]
[BitAutoData]
[TeamsMonthlyWithAddOnsOrganizationCustomize]
public void UpgradeItemOptions_TeamsWithSMToEnterpriseWithoutSM_ReturnsCorrectOptions(
Organization organization)
{
// 5 purchased, 1 base
organization.MaxStorageGb = 6;
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "password_manager_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.PasswordManager.StripeSeatPlanId },
Quantity = organization.Seats!.Value
},
new ()
{
Id = "secrets_manager_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.SecretsManager.StripeSeatPlanId },
Quantity = organization.SmSeats!.Value
},
new ()
{
Id = "secrets_manager_service_accounts_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId },
Quantity = organization.SmServiceAccounts!.Value
},
new ()
{
Id = "password_manager_storage_subscription_item",
Price = new Price { Id = teamsMonthlyPlan.PasswordManager.StripeStoragePlanId },
Quantity = organization.Storage!.Value
}
}
}
};
var enterpriseMonthlyPlan = StaticStore.GetPlan(PlanType.EnterpriseMonthly);
var updatedSubscriptionData = new SubscriptionData
{
Plan = enterpriseMonthlyPlan,
PurchasedPasswordManagerSeats = 50,
SubscribedToSecretsManager = false,
PurchasedSecretsManagerSeats = 0,
PurchasedAdditionalSecretsManagerServiceAccounts = 0,
PurchasedAdditionalStorage = 10
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
Assert.Equal(4, upgradeItemOptions.Count);
var passwordManagerOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId);
var passwordManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_subscription_item");
Assert.Equal(passwordManagerSubscriptionItem?.Id, passwordManagerOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId, passwordManagerOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedPasswordManagerSeats, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
var secretsManagerOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId);
var secretsManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "secrets_manager_subscription_item");
Assert.Equal(secretsManagerSubscriptionItem?.Id, secretsManagerOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId, secretsManagerOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedSecretsManagerSeats, secretsManagerOptions.Quantity);
Assert.True(secretsManagerOptions.Deleted);
var serviceAccountsOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId);
var serviceAccountsSubscriptionItem = subscription.Items.Data.FirstOrDefault(item =>
item.Id == "secrets_manager_service_accounts_subscription_item");
Assert.Equal(serviceAccountsSubscriptionItem?.Id, serviceAccountsOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId, serviceAccountsOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedAdditionalSecretsManagerServiceAccounts, serviceAccountsOptions.Quantity);
Assert.True(serviceAccountsOptions.Deleted);
var storageOptions = upgradeItemOptions.FirstOrDefault(options =>
options.Price == enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId);
var storageSubscriptionItem = subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_storage_subscription_item");
Assert.Equal(storageSubscriptionItem?.Id, storageOptions!.Id);
Assert.Equal(enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId, storageOptions.Price);
Assert.Equal(updatedSubscriptionData.PurchasedAdditionalStorage, storageOptions.Quantity);
Assert.Null(storageOptions.Deleted);
}
[Theory]
[BitAutoData]
[TeamsStarterOrganizationCustomize]
public void RevertItemOptions_TeamsStarterToTeams_ReturnsCorrectOptions(
Organization organization)
{
var teamsStarterPlan = StaticStore.GetPlan(PlanType.TeamsStarter);
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "subscription_item",
Price = new Price { Id = teamsMonthlyPlan.PasswordManager.StripeSeatPlanId },
Quantity = 20
}
}
}
};
var updatedSubscriptionData = new SubscriptionData
{
Plan = teamsMonthlyPlan,
PurchasedPasswordManagerSeats = 20
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
Assert.Single(revertItemOptions);
var passwordManagerOptions = revertItemOptions.First();
Assert.Equal(subscription.Items.Data.FirstOrDefault()?.Id, passwordManagerOptions.Id);
Assert.Equal(teamsStarterPlan.PasswordManager.StripePlanId, passwordManagerOptions.Price);
Assert.Equal(1, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
}
[Theory]
[BitAutoData]
[TeamsMonthlyWithAddOnsOrganizationCustomize]
public void RevertItemOptions_TeamsWithSMToEnterpriseWithSM_ReturnsCorrectOptions(
Organization organization)
{
// 5 purchased, 1 base
organization.MaxStorageGb = 6;
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var enterpriseMonthlyPlan = StaticStore.GetPlan(PlanType.EnterpriseMonthly);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "password_manager_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId },
Quantity = organization.Seats!.Value
},
new ()
{
Id = "secrets_manager_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId },
Quantity = organization.SmSeats!.Value
},
new ()
{
Id = "secrets_manager_service_accounts_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId },
Quantity = organization.SmServiceAccounts!.Value
},
new ()
{
Id = "password_manager_storage_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId },
Quantity = organization.Storage!.Value
}
}
}
};
var updatedSubscriptionData = new SubscriptionData
{
Plan = enterpriseMonthlyPlan,
PurchasedPasswordManagerSeats = 50,
SubscribedToSecretsManager = true,
PurchasedSecretsManagerSeats = 30,
PurchasedAdditionalSecretsManagerServiceAccounts = 10,
PurchasedAdditionalStorage = 10
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
Assert.Equal(4, revertItemOptions.Count);
var passwordManagerOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.PasswordManager.StripeSeatPlanId);
var passwordManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_subscription_item");
Assert.Equal(passwordManagerSubscriptionItem?.Id, passwordManagerOptions!.Id);
Assert.Equal(teamsMonthlyPlan.PasswordManager.StripeSeatPlanId, passwordManagerOptions.Price);
Assert.Equal(organization.Seats - teamsMonthlyPlan.PasswordManager.BaseSeats, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
var secretsManagerOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.SecretsManager.StripeSeatPlanId);
var secretsManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "secrets_manager_subscription_item");
Assert.Equal(secretsManagerSubscriptionItem?.Id, secretsManagerOptions!.Id);
Assert.Equal(teamsMonthlyPlan.SecretsManager.StripeSeatPlanId, secretsManagerOptions.Price);
Assert.Equal(organization.SmSeats - teamsMonthlyPlan.SecretsManager.BaseSeats, secretsManagerOptions.Quantity);
Assert.Null(secretsManagerOptions.Deleted);
var serviceAccountsOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId);
var serviceAccountsSubscriptionItem = subscription.Items.Data.FirstOrDefault(item =>
item.Id == "secrets_manager_service_accounts_subscription_item");
Assert.Equal(serviceAccountsSubscriptionItem?.Id, serviceAccountsOptions!.Id);
Assert.Equal(teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId, serviceAccountsOptions.Price);
Assert.Equal(organization.SmServiceAccounts - teamsMonthlyPlan.SecretsManager.BaseServiceAccount, serviceAccountsOptions.Quantity);
Assert.Null(serviceAccountsOptions.Deleted);
var storageOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.PasswordManager.StripeStoragePlanId);
var storageSubscriptionItem = subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_storage_subscription_item");
Assert.Equal(storageSubscriptionItem?.Id, storageOptions!.Id);
Assert.Equal(teamsMonthlyPlan.PasswordManager.StripeStoragePlanId, storageOptions.Price);
Assert.Equal(organization.MaxStorageGb - teamsMonthlyPlan.PasswordManager.BaseStorageGb, storageOptions.Quantity);
Assert.Null(storageOptions.Deleted);
}
[Theory]
[BitAutoData]
[TeamsMonthlyWithAddOnsOrganizationCustomize]
public void RevertItemOptions_TeamsWithSMToEnterpriseWithoutSM_ReturnsCorrectOptions(
Organization organization)
{
// 5 purchased, 1 base
organization.MaxStorageGb = 6;
var teamsMonthlyPlan = StaticStore.GetPlan(PlanType.TeamsMonthly);
var enterpriseMonthlyPlan = StaticStore.GetPlan(PlanType.EnterpriseMonthly);
var subscription = new Subscription
{
Items = new StripeList<SubscriptionItem>
{
Data = new List<SubscriptionItem>
{
new ()
{
Id = "password_manager_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.PasswordManager.StripeSeatPlanId },
Quantity = organization.Seats!.Value
},
new ()
{
Id = "secrets_manager_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.SecretsManager.StripeSeatPlanId },
Quantity = organization.SmSeats!.Value
},
new ()
{
Id = "secrets_manager_service_accounts_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.SecretsManager.StripeServiceAccountPlanId },
Quantity = organization.SmServiceAccounts!.Value
},
new ()
{
Id = "password_manager_storage_subscription_item",
Price = new Price { Id = enterpriseMonthlyPlan.PasswordManager.StripeStoragePlanId },
Quantity = organization.Storage!.Value
}
}
}
};
var updatedSubscriptionData = new SubscriptionData
{
Plan = enterpriseMonthlyPlan,
PurchasedPasswordManagerSeats = 50,
SubscribedToSecretsManager = false,
PurchasedSecretsManagerSeats = 0,
PurchasedAdditionalSecretsManagerServiceAccounts = 0,
PurchasedAdditionalStorage = 10
};
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
Assert.Equal(4, revertItemOptions.Count);
var passwordManagerOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.PasswordManager.StripeSeatPlanId);
var passwordManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_subscription_item");
Assert.Equal(passwordManagerSubscriptionItem?.Id, passwordManagerOptions!.Id);
Assert.Equal(teamsMonthlyPlan.PasswordManager.StripeSeatPlanId, passwordManagerOptions.Price);
Assert.Equal(organization.Seats - teamsMonthlyPlan.PasswordManager.BaseSeats, passwordManagerOptions.Quantity);
Assert.Null(passwordManagerOptions.Deleted);
var secretsManagerOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.SecretsManager.StripeSeatPlanId);
var secretsManagerSubscriptionItem =
subscription.Items.Data.FirstOrDefault(item => item.Id == "secrets_manager_subscription_item");
Assert.Equal(secretsManagerSubscriptionItem?.Id, secretsManagerOptions!.Id);
Assert.Equal(teamsMonthlyPlan.SecretsManager.StripeSeatPlanId, secretsManagerOptions.Price);
Assert.Equal(organization.SmSeats - teamsMonthlyPlan.SecretsManager.BaseSeats, secretsManagerOptions.Quantity);
Assert.Null(secretsManagerOptions.Deleted);
var serviceAccountsOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId);
var serviceAccountsSubscriptionItem = subscription.Items.Data.FirstOrDefault(item =>
item.Id == "secrets_manager_service_accounts_subscription_item");
Assert.Equal(serviceAccountsSubscriptionItem?.Id, serviceAccountsOptions!.Id);
Assert.Equal(teamsMonthlyPlan.SecretsManager.StripeServiceAccountPlanId, serviceAccountsOptions.Price);
Assert.Equal(organization.SmServiceAccounts - teamsMonthlyPlan.SecretsManager.BaseServiceAccount, serviceAccountsOptions.Quantity);
Assert.Null(serviceAccountsOptions.Deleted);
var storageOptions = revertItemOptions.FirstOrDefault(options =>
options.Price == teamsMonthlyPlan.PasswordManager.StripeStoragePlanId);
var storageSubscriptionItem = subscription.Items.Data.FirstOrDefault(item => item.Id == "password_manager_storage_subscription_item");
Assert.Equal(storageSubscriptionItem?.Id, storageOptions!.Id);
Assert.Equal(teamsMonthlyPlan.PasswordManager.StripeStoragePlanId, storageOptions.Price);
Assert.Equal(organization.MaxStorageGb - teamsMonthlyPlan.PasswordManager.BaseStorageGb, storageOptions.Quantity);
Assert.Null(storageOptions.Deleted);
}
}

View File

@ -63,29 +63,6 @@ public class UpgradeOrganizationPlanCommandTests
Assert.Contains("already on this plan", exception.Message);
}
[Theory, PaidOrganizationCustomize(CheckedPlanType = PlanType.Free), BitAutoData]
public async Task UpgradePlan_UpgradeFromPaidPlan_Throws(Organization organization, OrganizationUpgrade upgrade,
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
{
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.UpgradePlanAsync(organization.Id, upgrade));
Assert.Contains("can only upgrade", exception.Message);
}
[Theory, PaidOrganizationCustomize(CheckedPlanType = PlanType.Free), BitAutoData]
public async Task UpgradePlan_SM_UpgradeFromPaidPlan_Throws(Organization organization, OrganizationUpgrade upgrade,
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
{
upgrade.UseSecretsManager = true;
upgrade.AdditionalSmSeats = 10;
upgrade.AdditionalServiceAccounts = 10;
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.UpgradePlanAsync(organization.Id, upgrade));
Assert.Contains("can only upgrade", exception.Message);
}
[Theory]
[FreeOrganizationUpgradeCustomize, BitAutoData]
public async Task UpgradePlan_Passes(Organization organization, OrganizationUpgrade upgrade,
@ -99,6 +76,41 @@ public class UpgradeOrganizationPlanCommandTests
await sutProvider.GetDependency<IOrganizationService>().Received(1).ReplaceAndUpdateCacheAsync(organization);
}
[Theory]
[BitAutoData(PlanType.TeamsStarter)]
[BitAutoData(PlanType.TeamsMonthly)]
[BitAutoData(PlanType.TeamsAnnually)]
[BitAutoData(PlanType.EnterpriseMonthly)]
[BitAutoData(PlanType.EnterpriseAnnually)]
public async Task UpgradePlan_FromFamilies_Passes(
PlanType planType,
Organization organization,
OrganizationUpgrade organizationUpgrade,
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
{
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
organization.PlanType = PlanType.FamiliesAnnually;
organizationUpgrade.AdditionalSeats = 30;
organizationUpgrade.UseSecretsManager = true;
organizationUpgrade.AdditionalSmSeats = 20;
organizationUpgrade.AdditionalServiceAccounts = 5;
organizationUpgrade.AdditionalStorageGb = 3;
organizationUpgrade.Plan = planType;
await sutProvider.Sut.UpgradePlanAsync(organization.Id, organizationUpgrade);
await sutProvider.GetDependency<IPaymentService>().Received(1).AdjustSubscription(
organization,
StaticStore.GetPlan(planType),
organizationUpgrade.AdditionalSeats,
organizationUpgrade.UseSecretsManager,
organizationUpgrade.AdditionalSmSeats,
5,
3);
await sutProvider.GetDependency<IOrganizationService>().Received(1).ReplaceAndUpdateCacheAsync(organization);
}
[Theory, FreeOrganizationUpgradeCustomize]
[BitAutoData(PlanType.EnterpriseMonthly)]
[BitAutoData(PlanType.EnterpriseAnnually)]
@ -130,7 +142,6 @@ public class UpgradeOrganizationPlanCommandTests
Assert.NotNull(result.Item2);
}
[Theory, FreeOrganizationUpgradeCustomize]
[BitAutoData(PlanType.EnterpriseMonthly)]
[BitAutoData(PlanType.EnterpriseAnnually)]