1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-22 12:15:36 +01:00

[AC-2211] SM Changes (#3938)

* SM changes

* Teams starter bugs
This commit is contained in:
Conner Turnbull 2024-04-08 14:42:01 -04:00 committed by GitHub
parent d9658ce3fe
commit 9a2d383417
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 308 additions and 23 deletions

View File

@ -28,14 +28,24 @@ public enum PlanType : byte
EnterpriseMonthly2020 = 10, EnterpriseMonthly2020 = 10,
[Display(Name = "Enterprise (Annually) 2020")] [Display(Name = "Enterprise (Annually) 2020")]
EnterpriseAnnually2020 = 11, EnterpriseAnnually2020 = 11,
[Display(Name = "Teams (Monthly) 2023")]
TeamsMonthly2023 = 12,
[Display(Name = "Teams (Annually) 2023")]
TeamsAnnually2023 = 13,
[Display(Name = "Enterprise (Monthly) 2023")]
EnterpriseMonthly2023 = 14,
[Display(Name = "Enterprise (Annually) 2023")]
EnterpriseAnnually2023 = 15,
[Display(Name = "Teams Starter 2023")]
TeamsStarter2023 = 16,
[Display(Name = "Teams (Monthly)")] [Display(Name = "Teams (Monthly)")]
TeamsMonthly = 12, TeamsMonthly = 17,
[Display(Name = "Teams (Annually)")] [Display(Name = "Teams (Annually)")]
TeamsAnnually = 13, TeamsAnnually = 18,
[Display(Name = "Enterprise (Monthly)")] [Display(Name = "Enterprise (Monthly)")]
EnterpriseMonthly = 14, EnterpriseMonthly = 19,
[Display(Name = "Enterprise (Annually)")] [Display(Name = "Enterprise (Annually)")]
EnterpriseAnnually = 15, EnterpriseAnnually = 20,
[Display(Name = "Teams Starter")] [Display(Name = "Teams Starter")]
TeamsStarter = 16, TeamsStarter = 21,
} }

View File

@ -2,7 +2,7 @@
namespace Bit.Core.Models.StaticStore.Plans; namespace Bit.Core.Models.StaticStore.Plans;
public record EnterprisePlan : Models.StaticStore.Plan public record EnterprisePlan : Plan
{ {
public EnterprisePlan(bool isAnnual) public EnterprisePlan(bool isAnnual)
{ {
@ -44,7 +44,7 @@ public record EnterprisePlan : Models.StaticStore.Plan
{ {
BaseSeats = 0; BaseSeats = 0;
BasePrice = 0; BasePrice = 0;
BaseServiceAccount = 200; BaseServiceAccount = 50;
HasAdditionalSeatsOption = true; HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true; HasAdditionalServiceAccountOption = true;
@ -55,16 +55,16 @@ public record EnterprisePlan : Models.StaticStore.Plan
if (isAnnual) if (isAnnual)
{ {
StripeSeatPlanId = "secrets-manager-enterprise-seat-annually"; StripeSeatPlanId = "secrets-manager-enterprise-seat-annually";
StripeServiceAccountPlanId = "secrets-manager-service-account-annually"; StripeServiceAccountPlanId = "secrets-manager-service-account-2024-annually";
SeatPrice = 144; SeatPrice = 144;
AdditionalPricePerServiceAccount = 6; AdditionalPricePerServiceAccount = 12;
} }
else else
{ {
StripeSeatPlanId = "secrets-manager-enterprise-seat-monthly"; StripeSeatPlanId = "secrets-manager-enterprise-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly"; StripeServiceAccountPlanId = "secrets-manager-service-account-2024-monthly";
SeatPrice = 13; SeatPrice = 13;
AdditionalPricePerServiceAccount = 0.5M; AdditionalPricePerServiceAccount = 1;
} }
} }
} }

View File

@ -0,0 +1,102 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.StaticStore.Plans;
public record Enterprise2023Plan : Plan
{
public Enterprise2023Plan(bool isAnnual)
{
Type = isAnnual ? PlanType.EnterpriseAnnually2023 : PlanType.EnterpriseMonthly2023;
Product = ProductType.Enterprise;
Name = isAnnual ? "Enterprise (Annually)" : "Enterprise (Monthly)";
IsAnnual = isAnnual;
NameLocalizationKey = "planNameEnterprise";
DescriptionLocalizationKey = "planDescEnterprise";
CanBeUsedByBusiness = true;
TrialPeriodDays = 7;
HasPolicies = true;
HasSelfHost = true;
HasGroups = true;
HasDirectory = true;
HasEvents = true;
HasTotp = true;
Has2fa = true;
HasApi = true;
HasSso = true;
HasKeyConnector = true;
HasScim = true;
HasResetPassword = true;
UsersGetPremium = true;
HasCustomPermissions = true;
UpgradeSortOrder = 4;
DisplaySortOrder = 4;
LegacyYear = 2024;
PasswordManager = new Enterprise2023PasswordManagerFeatures(isAnnual);
SecretsManager = new Enterprise2023SecretsManagerFeatures(isAnnual);
}
private record Enterprise2023SecretsManagerFeatures : SecretsManagerPlanFeatures
{
public Enterprise2023SecretsManagerFeatures(bool isAnnual)
{
BaseSeats = 0;
BasePrice = 0;
BaseServiceAccount = 200;
HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true;
AllowSeatAutoscale = true;
AllowServiceAccountsAutoscale = true;
if (isAnnual)
{
StripeSeatPlanId = "secrets-manager-enterprise-seat-annually";
StripeServiceAccountPlanId = "secrets-manager-service-account-annually";
SeatPrice = 144;
AdditionalPricePerServiceAccount = 6;
}
else
{
StripeSeatPlanId = "secrets-manager-enterprise-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly";
SeatPrice = 13;
AdditionalPricePerServiceAccount = 0.5M;
}
}
}
private record Enterprise2023PasswordManagerFeatures : PasswordManagerPlanFeatures
{
public Enterprise2023PasswordManagerFeatures(bool isAnnual)
{
BaseSeats = 0;
BaseStorageGb = 1;
HasAdditionalStorageOption = true;
HasAdditionalSeatsOption = true;
AllowSeatAutoscale = true;
if (isAnnual)
{
AdditionalStoragePricePerGb = 4;
StripeStoragePlanId = "storage-gb-annually";
StripeSeatPlanId = "2023-enterprise-org-seat-annually";
SeatPrice = 72;
}
else
{
StripeSeatPlanId = "2023-enterprise-seat-monthly";
StripeStoragePlanId = "storage-gb-monthly";
SeatPrice = 7;
AdditionalStoragePricePerGb = 0.5M;
}
}
}
}

View File

@ -2,7 +2,7 @@
namespace Bit.Core.Models.StaticStore.Plans; namespace Bit.Core.Models.StaticStore.Plans;
public record TeamsPlan : Models.StaticStore.Plan public record TeamsPlan : Plan
{ {
public TeamsPlan(bool isAnnual) public TeamsPlan(bool isAnnual)
{ {
@ -37,7 +37,7 @@ public record TeamsPlan : Models.StaticStore.Plan
{ {
BaseSeats = 0; BaseSeats = 0;
BasePrice = 0; BasePrice = 0;
BaseServiceAccount = 50; BaseServiceAccount = 20;
HasAdditionalSeatsOption = true; HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true; HasAdditionalServiceAccountOption = true;
@ -48,16 +48,16 @@ public record TeamsPlan : Models.StaticStore.Plan
if (isAnnual) if (isAnnual)
{ {
StripeSeatPlanId = "secrets-manager-teams-seat-annually"; StripeSeatPlanId = "secrets-manager-teams-seat-annually";
StripeServiceAccountPlanId = "secrets-manager-service-account-annually"; StripeServiceAccountPlanId = "secrets-manager-service-account-2024-annually";
SeatPrice = 72; SeatPrice = 72;
AdditionalPricePerServiceAccount = 6; AdditionalPricePerServiceAccount = 12;
} }
else else
{ {
StripeSeatPlanId = "secrets-manager-teams-seat-monthly"; StripeSeatPlanId = "secrets-manager-teams-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly"; StripeServiceAccountPlanId = "secrets-manager-service-account-2024-monthly";
SeatPrice = 7; SeatPrice = 7;
AdditionalPricePerServiceAccount = 0.5M; AdditionalPricePerServiceAccount = 1;
} }
} }
} }

View File

@ -0,0 +1,96 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.StaticStore.Plans;
public record Teams2023Plan : Plan
{
public Teams2023Plan(bool isAnnual)
{
Type = isAnnual ? PlanType.TeamsAnnually2023 : PlanType.TeamsMonthly2023;
Product = ProductType.Teams;
Name = isAnnual ? "Teams (Annually)" : "Teams (Monthly)";
IsAnnual = isAnnual;
NameLocalizationKey = "planNameTeams";
DescriptionLocalizationKey = "planDescTeams";
CanBeUsedByBusiness = true;
TrialPeriodDays = 7;
HasGroups = true;
HasDirectory = true;
HasEvents = true;
HasTotp = true;
Has2fa = true;
HasApi = true;
UsersGetPremium = true;
UpgradeSortOrder = 3;
DisplaySortOrder = 3;
LegacyYear = 2024;
PasswordManager = new Teams2023PasswordManagerFeatures(isAnnual);
SecretsManager = new Teams2023SecretsManagerFeatures(isAnnual);
}
private record Teams2023SecretsManagerFeatures : SecretsManagerPlanFeatures
{
public Teams2023SecretsManagerFeatures(bool isAnnual)
{
BaseSeats = 0;
BasePrice = 0;
BaseServiceAccount = 50;
HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true;
AllowSeatAutoscale = true;
AllowServiceAccountsAutoscale = true;
if (isAnnual)
{
StripeSeatPlanId = "secrets-manager-teams-seat-annually";
StripeServiceAccountPlanId = "secrets-manager-service-account-annually";
SeatPrice = 72;
AdditionalPricePerServiceAccount = 6;
}
else
{
StripeSeatPlanId = "secrets-manager-teams-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly";
SeatPrice = 7;
AdditionalPricePerServiceAccount = 0.5M;
}
}
}
private record Teams2023PasswordManagerFeatures : PasswordManagerPlanFeatures
{
public Teams2023PasswordManagerFeatures(bool isAnnual)
{
BaseSeats = 0;
BaseStorageGb = 1;
BasePrice = 0;
HasAdditionalStorageOption = true;
HasAdditionalSeatsOption = true;
AllowSeatAutoscale = true;
if (isAnnual)
{
StripeStoragePlanId = "storage-gb-annually";
StripeSeatPlanId = "2023-teams-org-seat-annually";
SeatPrice = 48;
AdditionalStoragePricePerGb = 4;
}
else
{
StripeSeatPlanId = "2023-teams-org-seat-monthly";
StripeStoragePlanId = "storage-gb-monthly";
SeatPrice = 5;
AdditionalStoragePricePerGb = 0.5M;
}
}
}
}

View File

@ -36,7 +36,7 @@ public record TeamsStarterPlan : Plan
{ {
BaseSeats = 0; BaseSeats = 0;
BasePrice = 0; BasePrice = 0;
BaseServiceAccount = 50; BaseServiceAccount = 20;
HasAdditionalSeatsOption = true; HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true; HasAdditionalServiceAccountOption = true;
@ -45,9 +45,9 @@ public record TeamsStarterPlan : Plan
AllowServiceAccountsAutoscale = true; AllowServiceAccountsAutoscale = true;
StripeSeatPlanId = "secrets-manager-teams-seat-monthly"; StripeSeatPlanId = "secrets-manager-teams-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly"; StripeServiceAccountPlanId = "secrets-manager-service-account-2024-monthly";
SeatPrice = 7; SeatPrice = 7;
AdditionalPricePerServiceAccount = 0.5M; AdditionalPricePerServiceAccount = 1;
} }
} }

View File

@ -0,0 +1,72 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.StaticStore.Plans;
public record TeamsStarterPlan2023 : Plan
{
public TeamsStarterPlan2023()
{
Type = PlanType.TeamsStarter2023;
Product = ProductType.TeamsStarter;
Name = "Teams (Starter)";
NameLocalizationKey = "planNameTeamsStarter";
DescriptionLocalizationKey = "planDescTeams";
CanBeUsedByBusiness = true;
TrialPeriodDays = 7;
HasGroups = true;
HasDirectory = true;
HasEvents = true;
HasTotp = true;
Has2fa = true;
HasApi = true;
UsersGetPremium = true;
UpgradeSortOrder = 2;
DisplaySortOrder = 2;
PasswordManager = new TeamsStarter2023PasswordManagerFeatures();
SecretsManager = new TeamsStarter2023SecretsManagerFeatures();
LegacyYear = 2024;
}
private record TeamsStarter2023SecretsManagerFeatures : SecretsManagerPlanFeatures
{
public TeamsStarter2023SecretsManagerFeatures()
{
BaseSeats = 0;
BasePrice = 0;
BaseServiceAccount = 50;
HasAdditionalSeatsOption = true;
HasAdditionalServiceAccountOption = true;
AllowSeatAutoscale = true;
AllowServiceAccountsAutoscale = true;
StripeSeatPlanId = "secrets-manager-teams-seat-monthly";
StripeServiceAccountPlanId = "secrets-manager-service-account-monthly";
SeatPrice = 7;
AdditionalPricePerServiceAccount = 0.5M;
}
}
private record TeamsStarter2023PasswordManagerFeatures : PasswordManagerPlanFeatures
{
public TeamsStarter2023PasswordManagerFeatures()
{
BaseSeats = 10;
BaseStorageGb = 1;
BasePrice = 20;
MaxSeats = 10;
HasAdditionalStorageOption = true;
StripePlanId = "teams-org-starter";
StripeStoragePlanId = "storage-gb-monthly";
AdditionalStoragePricePerGb = 0.5M;
}
}
}

View File

@ -114,8 +114,13 @@ public static class StaticStore
new TeamsPlan(true), new TeamsPlan(true),
new TeamsPlan(false), new TeamsPlan(false),
new Enterprise2023Plan(true),
new Enterprise2023Plan(false),
new Enterprise2020Plan(true), new Enterprise2020Plan(true),
new Enterprise2020Plan(false), new Enterprise2020Plan(false),
new TeamsStarterPlan2023(),
new Teams2023Plan(true),
new Teams2023Plan(false),
new Teams2020Plan(true), new Teams2020Plan(true),
new Teams2020Plan(false), new Teams2020Plan(false),
new FamiliesPlan(), new FamiliesPlan(),

View File

@ -526,7 +526,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
Organization organization, Organization organization,
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider) SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
{ {
const int newSmServiceAccounts = 199; const int newSmServiceAccounts = 49;
organization.SmServiceAccounts = newSmServiceAccounts - 10; organization.SmServiceAccounts = newSmServiceAccounts - 10;
@ -537,7 +537,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
var exception = await Assert.ThrowsAsync<BadRequestException>( var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.UpdateSubscriptionAsync(update)); () => sutProvider.Sut.UpdateSubscriptionAsync(update));
Assert.Contains("Plan has a minimum of 200 machine accounts", exception.Message); Assert.Contains("Plan has a minimum of 50 machine accounts", exception.Message);
await VerifyDependencyNotCalledAsync(sutProvider); await VerifyDependencyNotCalledAsync(sutProvider);
} }

View File

@ -13,7 +13,7 @@ public class StaticStoreTests
var plans = StaticStore.Plans.ToList(); var plans = StaticStore.Plans.ToList();
Assert.NotNull(plans); Assert.NotNull(plans);
Assert.NotEmpty(plans); Assert.NotEmpty(plans);
Assert.Equal(17, plans.Count); Assert.Equal(22, plans.Count);
} }
[Theory] [Theory]