mirror of
https://github.com/bitwarden/server.git
synced 2024-11-25 12:45:18 +01:00
[AC-1408] Update plan to include secrets manager (#2942)
* Adding the Secret manager to the Plan List * Adding the unit test for the StaticStoreTests class * Fix whitespace formatting * Fix whitespace formatting * Price update * Resolving the PR comments * Resolving PR comments * Fixing the whitespace * only password manager plans are return for now * format whitespace * Resolve the test issue * Fixing the failing test * Refactoring the Plan separation * add a unit test for SingleOrDefault * Fix the whitespace format * Separate the PM and SM plans * Fixing the whitespace * Remove unnecessary directive * Fix imports ordering * Fix imports ordering * Resolve imports ordering * Fixing imports ordering * Fix response model, add MaxProjects * Fix filename * Fix format * Fix: seat price should match annual/monthly * Fix service account annual pricing * Name the sm service account planId properly * Update the secrets manager plan * correcting the wrong amount for the seats --------- Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
This commit is contained in:
parent
904b2fe205
commit
5a12db18d1
@ -487,7 +487,7 @@ public class OrganizationsController : Controller
|
|||||||
if (model.Type == OrganizationApiKeyType.BillingSync || model.Type == OrganizationApiKeyType.Scim)
|
if (model.Type == OrganizationApiKeyType.BillingSync || model.Type == OrganizationApiKeyType.Scim)
|
||||||
{
|
{
|
||||||
// Non-enterprise orgs should not be able to create or view an apikey of billing sync/scim key types
|
// Non-enterprise orgs should not be able to create or view an apikey of billing sync/scim key types
|
||||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
var plan = StaticStore.GetPasswordManagerPlan(organization.PlanType);
|
||||||
if (plan.Product != ProductType.Enterprise)
|
if (plan.Product != ProductType.Enterprise)
|
||||||
{
|
{
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
|
@ -19,12 +19,30 @@ public class PlansController : Controller
|
|||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public ListResponseModel<PlanResponseModel> Get()
|
public ListResponseModel<PlanResponseModel> Get()
|
||||||
|
{
|
||||||
|
var data = StaticStore.PasswordManagerPlans;
|
||||||
|
var responses = data.Select(plan => new PlanResponseModel(plan));
|
||||||
|
return new ListResponseModel<PlanResponseModel>(responses);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("all")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public ListResponseModel<PlanResponseModel> GetAllPlans()
|
||||||
{
|
{
|
||||||
var data = StaticStore.Plans;
|
var data = StaticStore.Plans;
|
||||||
var responses = data.Select(plan => new PlanResponseModel(plan));
|
var responses = data.Select(plan => new PlanResponseModel(plan));
|
||||||
return new ListResponseModel<PlanResponseModel>(responses);
|
return new ListResponseModel<PlanResponseModel>(responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("sm-plans")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public ListResponseModel<PlanResponseModel> GetSecretsManagerPlans()
|
||||||
|
{
|
||||||
|
var data = StaticStore.SecretManagerPlans;
|
||||||
|
var responses = data.Select(plan => new PlanResponseModel(plan));
|
||||||
|
return new ListResponseModel<PlanResponseModel>(responses);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("sales-tax-rates")]
|
[HttpGet("sales-tax-rates")]
|
||||||
public async Task<ListResponseModel<TaxRateResponseModel>> GetTaxRates()
|
public async Task<ListResponseModel<TaxRateResponseModel>> GetTaxRates()
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ public class OrganizationResponseModel : ResponseModel
|
|||||||
BusinessCountry = organization.BusinessCountry;
|
BusinessCountry = organization.BusinessCountry;
|
||||||
BusinessTaxNumber = organization.BusinessTaxNumber;
|
BusinessTaxNumber = organization.BusinessTaxNumber;
|
||||||
BillingEmail = organization.BillingEmail;
|
BillingEmail = organization.BillingEmail;
|
||||||
Plan = new PlanResponseModel(StaticStore.Plans.FirstOrDefault(plan => plan.Type == organization.PlanType));
|
Plan = new PlanResponseModel(StaticStore.PasswordManagerPlans.FirstOrDefault(plan => plan.Type == organization.PlanType));
|
||||||
PlanType = organization.PlanType;
|
PlanType = organization.PlanType;
|
||||||
Seats = organization.Seats;
|
Seats = organization.Seats;
|
||||||
MaxAutoscaleSeats = organization.MaxAutoscaleSeats;
|
MaxAutoscaleSeats = organization.MaxAutoscaleSeats;
|
||||||
|
@ -52,6 +52,13 @@ public class PlanResponseModel : ResponseModel
|
|||||||
SeatPrice = plan.SeatPrice;
|
SeatPrice = plan.SeatPrice;
|
||||||
AdditionalStoragePricePerGb = plan.AdditionalStoragePricePerGb;
|
AdditionalStoragePricePerGb = plan.AdditionalStoragePricePerGb;
|
||||||
PremiumAccessOptionPrice = plan.PremiumAccessOptionPrice;
|
PremiumAccessOptionPrice = plan.PremiumAccessOptionPrice;
|
||||||
|
|
||||||
|
AdditionalPricePerServiceAccount = plan.AdditionalPricePerServiceAccount;
|
||||||
|
BaseServiceAccount = plan.BaseServiceAccount;
|
||||||
|
MaxServiceAccount = plan.MaxServiceAccount;
|
||||||
|
HasAdditionalServiceAccountOption = plan.HasAdditionalServiceAccountOption;
|
||||||
|
MaxProjects = plan.MaxProjects;
|
||||||
|
BitwardenProduct = plan.BitwardenProduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlanType Type { get; set; }
|
public PlanType Type { get; set; }
|
||||||
@ -98,4 +105,11 @@ public class PlanResponseModel : ResponseModel
|
|||||||
public decimal SeatPrice { get; set; }
|
public decimal SeatPrice { get; set; }
|
||||||
public decimal AdditionalStoragePricePerGb { get; set; }
|
public decimal AdditionalStoragePricePerGb { get; set; }
|
||||||
public decimal PremiumAccessOptionPrice { get; set; }
|
public decimal PremiumAccessOptionPrice { get; set; }
|
||||||
|
|
||||||
|
public decimal? AdditionalPricePerServiceAccount { get; set; }
|
||||||
|
public short? BaseServiceAccount { get; set; }
|
||||||
|
public short? MaxServiceAccount { get; set; }
|
||||||
|
public bool HasAdditionalServiceAccountOption { get; set; }
|
||||||
|
public short? MaxProjects { get; set; }
|
||||||
|
public BitwardenProductType BitwardenProduct { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
|
|||||||
FamilySponsorshipAvailable = FamilySponsorshipFriendlyName == null &&
|
FamilySponsorshipAvailable = FamilySponsorshipFriendlyName == null &&
|
||||||
StaticStore.GetSponsoredPlan(PlanSponsorshipType.FamiliesForEnterprise)
|
StaticStore.GetSponsoredPlan(PlanSponsorshipType.FamiliesForEnterprise)
|
||||||
.UsersCanSponsor(organization);
|
.UsersCanSponsor(organization);
|
||||||
PlanProductType = StaticStore.GetPlan(organization.PlanType).Product;
|
PlanProductType = StaticStore.GetPasswordManagerPlan(organization.PlanType).Product;
|
||||||
FamilySponsorshipLastSyncDate = organization.FamilySponsorshipLastSyncDate;
|
FamilySponsorshipLastSyncDate = organization.FamilySponsorshipLastSyncDate;
|
||||||
FamilySponsorshipToDelete = organization.FamilySponsorshipToDelete;
|
FamilySponsorshipToDelete = organization.FamilySponsorshipToDelete;
|
||||||
FamilySponsorshipValidUntil = organization.FamilySponsorshipValidUntil;
|
FamilySponsorshipValidUntil = organization.FamilySponsorshipValidUntil;
|
||||||
|
@ -42,6 +42,6 @@ public class ProfileProviderOrganizationResponseModel : ProfileOrganizationRespo
|
|||||||
UserId = organization.UserId?.ToString();
|
UserId = organization.UserId?.ToString();
|
||||||
ProviderId = organization.ProviderId?.ToString();
|
ProviderId = organization.ProviderId?.ToString();
|
||||||
ProviderName = organization.ProviderName;
|
ProviderName = organization.ProviderName;
|
||||||
PlanProductType = StaticStore.GetPlan(organization.PlanType).Product;
|
PlanProductType = StaticStore.GetPasswordManagerPlan(organization.PlanType).Product;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ public class StripeController : Controller
|
|||||||
// org
|
// org
|
||||||
if (ids.Item1.HasValue)
|
if (ids.Item1.HasValue)
|
||||||
{
|
{
|
||||||
if (subscription.Items.Any(i => StaticStore.Plans.Any(p => p.StripePlanId == i.Plan.Id)))
|
if (subscription.Items.Any(i => StaticStore.PasswordManagerPlans.Any(p => p.StripePlanId == i.Plan.Id)))
|
||||||
{
|
{
|
||||||
await _organizationService.EnableAsync(ids.Item1.Value, subscription.CurrentPeriodEnd);
|
await _organizationService.EnableAsync(ids.Item1.Value, subscription.CurrentPeriodEnd);
|
||||||
|
|
||||||
|
11
src/Core/Enums/BitwardenProductType.cs
Normal file
11
src/Core/Enums/BitwardenProductType.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Bit.Core.Enums;
|
||||||
|
|
||||||
|
public enum BitwardenProductType : byte
|
||||||
|
{
|
||||||
|
[Display(Name = "Password Manager")]
|
||||||
|
PasswordManager = 0,
|
||||||
|
[Display(Name = "Secrets Manager")]
|
||||||
|
SecretsManager = 1,
|
||||||
|
}
|
@ -47,9 +47,16 @@ public class Plan
|
|||||||
public string StripePlanId { get; set; }
|
public string StripePlanId { get; set; }
|
||||||
public string StripeSeatPlanId { get; set; }
|
public string StripeSeatPlanId { get; set; }
|
||||||
public string StripeStoragePlanId { get; set; }
|
public string StripeStoragePlanId { get; set; }
|
||||||
|
public string StripeServiceAccountPlanId { get; set; }
|
||||||
public string StripePremiumAccessPlanId { get; set; }
|
public string StripePremiumAccessPlanId { get; set; }
|
||||||
public decimal BasePrice { get; set; }
|
public decimal BasePrice { get; set; }
|
||||||
public decimal SeatPrice { get; set; }
|
public decimal SeatPrice { get; set; }
|
||||||
public decimal AdditionalStoragePricePerGb { get; set; }
|
public decimal AdditionalStoragePricePerGb { get; set; }
|
||||||
public decimal PremiumAccessOptionPrice { get; set; }
|
public decimal PremiumAccessOptionPrice { get; set; }
|
||||||
|
public decimal? AdditionalPricePerServiceAccount { get; set; }
|
||||||
|
public short? BaseServiceAccount { get; set; }
|
||||||
|
public short? MaxServiceAccount { get; set; }
|
||||||
|
public bool HasAdditionalServiceAccountOption { get; set; }
|
||||||
|
public short? MaxProjects { get; set; }
|
||||||
|
public BitwardenProductType BitwardenProduct { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ public class CloudSyncSponsorshipsCommand : ICloudSyncSponsorshipsCommand
|
|||||||
{
|
{
|
||||||
var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(selfHostedSponsorship.PlanSponsorshipType)?.SponsoringProductType;
|
var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(selfHostedSponsorship.PlanSponsorshipType)?.SponsoringProductType;
|
||||||
if (requiredSponsoringProductType == null
|
if (requiredSponsoringProductType == null
|
||||||
|| StaticStore.GetPlan(sponsoringOrg.PlanType).Product != requiredSponsoringProductType.Value)
|
|| StaticStore.GetPasswordManagerPlan(sponsoringOrg.PlanType).Product != requiredSponsoringProductType.Value)
|
||||||
{
|
{
|
||||||
continue; // prevent unsupported sponsorships
|
continue; // prevent unsupported sponsorships
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public class SetUpSponsorshipCommand : ISetUpSponsorshipCommand
|
|||||||
var requiredSponsoredProductType = StaticStore.GetSponsoredPlan(sponsorship.PlanSponsorshipType.Value)?.SponsoredProductType;
|
var requiredSponsoredProductType = StaticStore.GetSponsoredPlan(sponsorship.PlanSponsorshipType.Value)?.SponsoredProductType;
|
||||||
if (requiredSponsoredProductType == null ||
|
if (requiredSponsoredProductType == null ||
|
||||||
sponsoredOrganization == null ||
|
sponsoredOrganization == null ||
|
||||||
StaticStore.GetPlan(sponsoredOrganization.PlanType).Product != requiredSponsoredProductType.Value)
|
StaticStore.GetPasswordManagerPlan(sponsoredOrganization.PlanType).Product != requiredSponsoredProductType.Value)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Can only redeem sponsorship offer on families organizations.");
|
throw new BadRequestException("Can only redeem sponsorship offer on families organizations.");
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class ValidateSponsorshipCommand : CancelSponsorshipCommand, IValidateSpo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sponsoringOrgPlan = Utilities.StaticStore.GetPlan(sponsoringOrganization.PlanType);
|
var sponsoringOrgPlan = Utilities.StaticStore.GetPasswordManagerPlan(sponsoringOrganization.PlanType);
|
||||||
if (OrgDisabledForMoreThanGracePeriod(sponsoringOrganization) ||
|
if (OrgDisabledForMoreThanGracePeriod(sponsoringOrganization) ||
|
||||||
sponsoredPlan.SponsoringProductType != sponsoringOrgPlan.Product ||
|
sponsoredPlan.SponsoringProductType != sponsoringOrgPlan.Product ||
|
||||||
existingSponsorship.ToDelete ||
|
existingSponsorship.ToDelete ||
|
||||||
|
@ -32,7 +32,7 @@ public class CreateSponsorshipCommand : ICreateSponsorshipCommand
|
|||||||
var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(sponsorshipType)?.SponsoringProductType;
|
var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(sponsorshipType)?.SponsoringProductType;
|
||||||
if (requiredSponsoringProductType == null ||
|
if (requiredSponsoringProductType == null ||
|
||||||
sponsoringOrg == null ||
|
sponsoringOrg == null ||
|
||||||
StaticStore.GetPlan(sponsoringOrg.PlanType).Product != requiredSponsoringProductType.Value)
|
StaticStore.GetPasswordManagerPlan(sponsoringOrg.PlanType).Product != requiredSponsoringProductType.Value)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Specified Organization cannot sponsor other organizations.");
|
throw new BadRequestException("Specified Organization cannot sponsor other organizations.");
|
||||||
}
|
}
|
||||||
|
@ -179,13 +179,13 @@ public class OrganizationService : IOrganizationService
|
|||||||
throw new BadRequestException("Your account has no payment method available.");
|
throw new BadRequestException("Your account has no payment method available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingPlan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
var existingPlan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
if (existingPlan == null)
|
if (existingPlan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Existing plan not found.");
|
throw new BadRequestException("Existing plan not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newPlan = StaticStore.Plans.FirstOrDefault(p => p.Type == upgrade.Plan && !p.Disabled);
|
var newPlan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == upgrade.Plan && !p.Disabled);
|
||||||
if (newPlan == null)
|
if (newPlan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Plan not found.");
|
throw new BadRequestException("Plan not found.");
|
||||||
@ -379,7 +379,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
var plan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
if (plan == null)
|
if (plan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Existing plan not found.");
|
throw new BadRequestException("Existing plan not found.");
|
||||||
@ -437,7 +437,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
throw new BadRequestException($"Cannot set max seat autoscaling below current seat count.");
|
throw new BadRequestException($"Cannot set max seat autoscaling below current seat count.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
var plan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
if (plan == null)
|
if (plan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Existing plan not found.");
|
throw new BadRequestException("Existing plan not found.");
|
||||||
@ -489,7 +489,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
throw new BadRequestException("No subscription found.");
|
throw new BadRequestException("No subscription found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
var plan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
if (plan == null)
|
if (plan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Existing plan not found.");
|
throw new BadRequestException("Existing plan not found.");
|
||||||
@ -607,7 +607,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup,
|
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup,
|
||||||
bool provider = false)
|
bool provider = false)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan);
|
var plan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == signup.Plan);
|
||||||
if (plan is not { LegacyYear: null })
|
if (plan is not { LegacyYear: null })
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Invalid plan selected.");
|
throw new BadRequestException("Invalid plan selected.");
|
||||||
@ -712,7 +712,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (license.PlanType != PlanType.Custom &&
|
if (license.PlanType != PlanType.Custom &&
|
||||||
StaticStore.Plans.FirstOrDefault(p => p.Type == license.PlanType && !p.Disabled) == null)
|
StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == license.PlanType && !p.Disabled) == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Plan not found.");
|
throw new BadRequestException("Plan not found.");
|
||||||
}
|
}
|
||||||
@ -2519,7 +2519,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
|
|
||||||
public async Task CreatePendingOrganization(Organization organization, string ownerEmail, ClaimsPrincipal user, IUserService userService, bool salesAssistedTrialStarted)
|
public async Task CreatePendingOrganization(Organization organization, string ownerEmail, ClaimsPrincipal user, IUserService userService, bool salesAssistedTrialStarted)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
var plan = StaticStore.PasswordManagerPlans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
if (plan is not { LegacyYear: null })
|
if (plan is not { LegacyYear: null })
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Invalid plan selected.");
|
throw new BadRequestException("Invalid plan selected.");
|
||||||
|
@ -201,7 +201,7 @@ public class StripePaymentService : IPaymentService
|
|||||||
|
|
||||||
private async Task ChangeOrganizationSponsorship(Organization org, OrganizationSponsorship sponsorship, bool applySponsorship)
|
private async Task ChangeOrganizationSponsorship(Organization org, OrganizationSponsorship sponsorship, bool applySponsorship)
|
||||||
{
|
{
|
||||||
var existingPlan = Utilities.StaticStore.GetPlan(org.PlanType);
|
var existingPlan = Utilities.StaticStore.GetPasswordManagerPlan(org.PlanType);
|
||||||
var sponsoredPlan = sponsorship != null ?
|
var sponsoredPlan = sponsorship != null ?
|
||||||
Utilities.StaticStore.GetSponsoredPlan(sponsorship.PlanSponsorshipType.Value) :
|
Utilities.StaticStore.GetSponsoredPlan(sponsorship.PlanSponsorshipType.Value) :
|
||||||
null;
|
null;
|
||||||
|
398
src/Core/Utilities/PasswordManagerPlanStore.cs
Normal file
398
src/Core/Utilities/PasswordManagerPlanStore.cs
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.StaticStore;
|
||||||
|
|
||||||
|
namespace Bit.Core.Utilities;
|
||||||
|
|
||||||
|
public static class PasswordManagerPlanStore
|
||||||
|
{
|
||||||
|
public static IEnumerable<Plan> CreatePlan()
|
||||||
|
{
|
||||||
|
return new List<Plan>
|
||||||
|
{
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.Free,
|
||||||
|
Product = ProductType.Free,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Free",
|
||||||
|
NameLocalizationKey = "planNameFree",
|
||||||
|
DescriptionLocalizationKey = "planDescFree",
|
||||||
|
BaseSeats = 2,
|
||||||
|
MaxCollections = 2,
|
||||||
|
MaxUsers = 2,
|
||||||
|
|
||||||
|
UpgradeSortOrder = -1, // Always the lowest plan, cannot be upgraded to
|
||||||
|
DisplaySortOrder = -1,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = false,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.FamiliesAnnually2019,
|
||||||
|
Product = ProductType.Families,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Families 2019",
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameFamilies",
|
||||||
|
DescriptionLocalizationKey = "planDescFamilies",
|
||||||
|
BaseSeats = 5,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
MaxUsers = 5,
|
||||||
|
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
HasPremiumAccessOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasSelfHost = true,
|
||||||
|
HasTotp = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 1,
|
||||||
|
DisplaySortOrder = 1,
|
||||||
|
LegacyYear = 2020,
|
||||||
|
|
||||||
|
StripePlanId = "personal-org-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
StripePremiumAccessPlanId = "personal-org-premium-access-annually",
|
||||||
|
BasePrice = 12,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
PremiumAccessOptionPrice = 40,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = false,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsAnnually2019,
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Teams (Annually) 2019",
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 5,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasTotp = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
LegacyYear = 2020,
|
||||||
|
|
||||||
|
StripePlanId = "teams-org-annually",
|
||||||
|
StripeSeatPlanId = "teams-org-seat-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
BasePrice = 60,
|
||||||
|
SeatPrice = 24,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsMonthly2019,
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Teams (Monthly) 2019",
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 5,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasTotp = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
LegacyYear = 2020,
|
||||||
|
|
||||||
|
StripePlanId = "teams-org-monthly",
|
||||||
|
StripeSeatPlanId = "teams-org-seat-monthly",
|
||||||
|
StripeStoragePlanId = "storage-gb-monthly",
|
||||||
|
BasePrice = 8,
|
||||||
|
SeatPrice = 2.5M,
|
||||||
|
AdditionalStoragePricePerGb = 0.5M,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseAnnually2019,
|
||||||
|
Name = "Enterprise (Annually) 2019",
|
||||||
|
IsAnnual = true,
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasPolicies = true,
|
||||||
|
HasSelfHost = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasTotp = true,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
HasCustomPermissions = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
LegacyYear = 2020,
|
||||||
|
|
||||||
|
StripePlanId = null,
|
||||||
|
StripeSeatPlanId = "enterprise-org-seat-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 36,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseMonthly2019,
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Enterprise (Monthly) 2019",
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasPolicies = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasTotp = true,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasSelfHost = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
HasCustomPermissions = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
LegacyYear = 2020,
|
||||||
|
|
||||||
|
StripePlanId = null,
|
||||||
|
StripeSeatPlanId = "enterprise-org-seat-monthly",
|
||||||
|
StripeStoragePlanId = "storage-gb-monthly",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 4M,
|
||||||
|
AdditionalStoragePricePerGb = 0.5M,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.FamiliesAnnually,
|
||||||
|
Product = ProductType.Families,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Families",
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameFamilies",
|
||||||
|
DescriptionLocalizationKey = "planDescFamilies",
|
||||||
|
BaseSeats = 6,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
MaxUsers = 6,
|
||||||
|
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasSelfHost = true,
|
||||||
|
HasTotp = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 1,
|
||||||
|
DisplaySortOrder = 1,
|
||||||
|
|
||||||
|
StripePlanId = "2020-families-org-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
BasePrice = 40,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = false,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsAnnually,
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Teams (Annually)",
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
BaseSeats = 0,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasTotp = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
|
||||||
|
StripeSeatPlanId = "2020-teams-org-seat-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
SeatPrice = 36,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsMonthly,
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Teams (Monthly)",
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
BaseSeats = 0,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasTotp = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
|
||||||
|
StripeSeatPlanId = "2020-teams-org-seat-monthly",
|
||||||
|
StripeStoragePlanId = "storage-gb-monthly",
|
||||||
|
SeatPrice = 4,
|
||||||
|
AdditionalStoragePricePerGb = 0.5M,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseAnnually,
|
||||||
|
Name = "Enterprise (Annually)",
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = 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 = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
|
||||||
|
StripeSeatPlanId = "2020-enterprise-org-seat-annually",
|
||||||
|
StripeStoragePlanId = "storage-gb-annually",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 60,
|
||||||
|
AdditionalStoragePricePerGb = 4,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseMonthly,
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.PasswordManager,
|
||||||
|
Name = "Enterprise (Monthly)",
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseStorageGb = 1,
|
||||||
|
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalStorageOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
|
||||||
|
HasPolicies = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasTotp = true,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasSelfHost = true,
|
||||||
|
HasSso = true,
|
||||||
|
HasKeyConnector = true,
|
||||||
|
HasScim = true,
|
||||||
|
HasResetPassword = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
HasCustomPermissions = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
|
||||||
|
StripeSeatPlanId = "2020-enterprise-seat-monthly",
|
||||||
|
StripeStoragePlanId = "storage-gb-monthly",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 6,
|
||||||
|
AdditionalStoragePricePerGb = 0.5M,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.Custom,
|
||||||
|
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
168
src/Core/Utilities/SecretsManagerPlanStore.cs
Normal file
168
src/Core/Utilities/SecretsManagerPlanStore.cs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.StaticStore;
|
||||||
|
|
||||||
|
namespace Bit.Core.Utilities;
|
||||||
|
|
||||||
|
public static class SecretsManagerPlanStore
|
||||||
|
{
|
||||||
|
public static IEnumerable<Plan> CreatePlan()
|
||||||
|
{
|
||||||
|
return new List<Plan>
|
||||||
|
{
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseMonthly,
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.SecretsManager,
|
||||||
|
Name = "Enterprise (Monthly)",
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseServiceAccount = 200,
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalServiceAccountOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
HasPolicies = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasTotp = true,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasSelfHost = true,
|
||||||
|
HasSso = true,
|
||||||
|
HasKeyConnector = true,
|
||||||
|
HasScim = true,
|
||||||
|
HasResetPassword = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
HasCustomPermissions = true,
|
||||||
|
UpgradeSortOrder = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
StripeSeatPlanId = "sm-enterprise-seat-monthly",
|
||||||
|
StripeServiceAccountPlanId = "service-account-monthly",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 13,
|
||||||
|
AdditionalPricePerServiceAccount = 0.5M,
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.EnterpriseAnnually,
|
||||||
|
Name = "Enterprise (Annually)",
|
||||||
|
Product = ProductType.Enterprise,
|
||||||
|
BitwardenProduct = BitwardenProductType.SecretsManager,
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameEnterprise",
|
||||||
|
DescriptionLocalizationKey = "planDescEnterprise",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseServiceAccount = 200,
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalServiceAccountOption = 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 = 3,
|
||||||
|
DisplaySortOrder = 3,
|
||||||
|
StripeSeatPlanId = "sm-enterprise-seat-annually",
|
||||||
|
StripeServiceAccountPlanId = "service-account-annually",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 144,
|
||||||
|
AdditionalPricePerServiceAccount = 6,
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsMonthly,
|
||||||
|
Name = "Teams (Monthly)",
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.SecretsManager,
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseServiceAccount = 50,
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalServiceAccountOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasTotp = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
StripeSeatPlanId = "sm-teams-seat-monthly",
|
||||||
|
StripeServiceAccountPlanId = "service-account-monthly",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 7,
|
||||||
|
AdditionalPricePerServiceAccount = 0.5M,
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.TeamsAnnually,
|
||||||
|
Name = "Teams (Annually)",
|
||||||
|
Product = ProductType.Teams,
|
||||||
|
BitwardenProduct = BitwardenProductType.SecretsManager,
|
||||||
|
IsAnnual = true,
|
||||||
|
NameLocalizationKey = "planNameTeams",
|
||||||
|
DescriptionLocalizationKey = "planDescTeams",
|
||||||
|
CanBeUsedByBusiness = true,
|
||||||
|
BaseSeats = 0,
|
||||||
|
BaseServiceAccount = 50,
|
||||||
|
HasAdditionalSeatsOption = true,
|
||||||
|
HasAdditionalServiceAccountOption = true,
|
||||||
|
TrialPeriodDays = 7,
|
||||||
|
Has2fa = true,
|
||||||
|
HasApi = true,
|
||||||
|
HasDirectory = true,
|
||||||
|
HasEvents = true,
|
||||||
|
HasGroups = true,
|
||||||
|
HasTotp = true,
|
||||||
|
UsersGetPremium = true,
|
||||||
|
|
||||||
|
UpgradeSortOrder = 2,
|
||||||
|
DisplaySortOrder = 2,
|
||||||
|
StripeSeatPlanId = "sm-teams-seat-annually",
|
||||||
|
StripeServiceAccountPlanId = "service-account-annually",
|
||||||
|
BasePrice = 0,
|
||||||
|
SeatPrice = 72,
|
||||||
|
AdditionalPricePerServiceAccount = 6,
|
||||||
|
AllowSeatAutoscale = true,
|
||||||
|
},
|
||||||
|
new Plan
|
||||||
|
{
|
||||||
|
Type = PlanType.Free,
|
||||||
|
Product = ProductType.Free,
|
||||||
|
BitwardenProduct = BitwardenProductType.SecretsManager,
|
||||||
|
Name = "Free",
|
||||||
|
NameLocalizationKey = "planNameFree",
|
||||||
|
DescriptionLocalizationKey = "planDescFree",
|
||||||
|
BaseSeats = 2,
|
||||||
|
BaseServiceAccount = 3,
|
||||||
|
MaxProjects = 3,
|
||||||
|
MaxUsers = 2,
|
||||||
|
MaxServiceAccount = 3,
|
||||||
|
UpgradeSortOrder = -1, // Always the lowest plan, cannot be upgraded to
|
||||||
|
DisplaySortOrder = -1,
|
||||||
|
AllowSeatAutoscale = false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -106,388 +106,19 @@ public class StaticStore
|
|||||||
|
|
||||||
#region Plans
|
#region Plans
|
||||||
|
|
||||||
Plans = new List<Plan>
|
PasswordManagerPlans = PasswordManagerPlanStore.CreatePlan();
|
||||||
{
|
SecretManagerPlans = SecretsManagerPlanStore.CreatePlan();
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.Free,
|
|
||||||
Product = ProductType.Free,
|
|
||||||
Name = "Free",
|
|
||||||
NameLocalizationKey = "planNameFree",
|
|
||||||
DescriptionLocalizationKey = "planDescFree",
|
|
||||||
BaseSeats = 2,
|
|
||||||
MaxCollections = 2,
|
|
||||||
MaxUsers = 2,
|
|
||||||
|
|
||||||
UpgradeSortOrder = -1, // Always the lowest plan, cannot be upgraded to
|
Plans = PasswordManagerPlans.Concat(SecretManagerPlans);
|
||||||
DisplaySortOrder = -1,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = false,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.FamiliesAnnually2019,
|
|
||||||
Product = ProductType.Families,
|
|
||||||
Name = "Families 2019",
|
|
||||||
IsAnnual = true,
|
|
||||||
NameLocalizationKey = "planNameFamilies",
|
|
||||||
DescriptionLocalizationKey = "planDescFamilies",
|
|
||||||
BaseSeats = 5,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
MaxUsers = 5,
|
|
||||||
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
HasPremiumAccessOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasSelfHost = true,
|
|
||||||
HasTotp = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 1,
|
|
||||||
DisplaySortOrder = 1,
|
|
||||||
LegacyYear = 2020,
|
|
||||||
|
|
||||||
StripePlanId = "personal-org-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
StripePremiumAccessPlanId = "personal-org-premium-access-annually",
|
|
||||||
BasePrice = 12,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
PremiumAccessOptionPrice = 40,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = false,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.TeamsAnnually2019,
|
|
||||||
Product = ProductType.Teams,
|
|
||||||
Name = "Teams (Annually) 2019",
|
|
||||||
IsAnnual = true,
|
|
||||||
NameLocalizationKey = "planNameTeams",
|
|
||||||
DescriptionLocalizationKey = "planDescTeams",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 5,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasTotp = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 2,
|
|
||||||
DisplaySortOrder = 2,
|
|
||||||
LegacyYear = 2020,
|
|
||||||
|
|
||||||
StripePlanId = "teams-org-annually",
|
|
||||||
StripeSeatPlanId = "teams-org-seat-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
BasePrice = 60,
|
|
||||||
SeatPrice = 24,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.TeamsMonthly2019,
|
|
||||||
Product = ProductType.Teams,
|
|
||||||
Name = "Teams (Monthly) 2019",
|
|
||||||
NameLocalizationKey = "planNameTeams",
|
|
||||||
DescriptionLocalizationKey = "planDescTeams",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 5,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasTotp = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 2,
|
|
||||||
DisplaySortOrder = 2,
|
|
||||||
LegacyYear = 2020,
|
|
||||||
|
|
||||||
StripePlanId = "teams-org-monthly",
|
|
||||||
StripeSeatPlanId = "teams-org-seat-monthly",
|
|
||||||
StripeStoragePlanId = "storage-gb-monthly",
|
|
||||||
BasePrice = 8,
|
|
||||||
SeatPrice = 2.5M,
|
|
||||||
AdditionalStoragePricePerGb = 0.5M,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.EnterpriseAnnually2019,
|
|
||||||
Name = "Enterprise (Annually) 2019",
|
|
||||||
IsAnnual = true,
|
|
||||||
Product = ProductType.Enterprise,
|
|
||||||
NameLocalizationKey = "planNameEnterprise",
|
|
||||||
DescriptionLocalizationKey = "planDescEnterprise",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 0,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasPolicies = true,
|
|
||||||
HasSelfHost = true,
|
|
||||||
HasGroups = true,
|
|
||||||
HasDirectory = true,
|
|
||||||
HasEvents = true,
|
|
||||||
HasTotp = true,
|
|
||||||
Has2fa = true,
|
|
||||||
HasApi = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
HasCustomPermissions = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 3,
|
|
||||||
DisplaySortOrder = 3,
|
|
||||||
LegacyYear = 2020,
|
|
||||||
|
|
||||||
StripePlanId = null,
|
|
||||||
StripeSeatPlanId = "enterprise-org-seat-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
BasePrice = 0,
|
|
||||||
SeatPrice = 36,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.EnterpriseMonthly2019,
|
|
||||||
Product = ProductType.Enterprise,
|
|
||||||
Name = "Enterprise (Monthly) 2019",
|
|
||||||
NameLocalizationKey = "planNameEnterprise",
|
|
||||||
DescriptionLocalizationKey = "planDescEnterprise",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 0,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasPolicies = true,
|
|
||||||
HasGroups = true,
|
|
||||||
HasDirectory = true,
|
|
||||||
HasEvents = true,
|
|
||||||
HasTotp = true,
|
|
||||||
Has2fa = true,
|
|
||||||
HasApi = true,
|
|
||||||
HasSelfHost = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
HasCustomPermissions = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 3,
|
|
||||||
DisplaySortOrder = 3,
|
|
||||||
LegacyYear = 2020,
|
|
||||||
|
|
||||||
StripePlanId = null,
|
|
||||||
StripeSeatPlanId = "enterprise-org-seat-monthly",
|
|
||||||
StripeStoragePlanId = "storage-gb-monthly",
|
|
||||||
BasePrice = 0,
|
|
||||||
SeatPrice = 4M,
|
|
||||||
AdditionalStoragePricePerGb = 0.5M,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.FamiliesAnnually,
|
|
||||||
Product = ProductType.Families,
|
|
||||||
Name = "Families",
|
|
||||||
IsAnnual = true,
|
|
||||||
NameLocalizationKey = "planNameFamilies",
|
|
||||||
DescriptionLocalizationKey = "planDescFamilies",
|
|
||||||
BaseSeats = 6,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
MaxUsers = 6,
|
|
||||||
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasSelfHost = true,
|
|
||||||
HasTotp = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 1,
|
|
||||||
DisplaySortOrder = 1,
|
|
||||||
|
|
||||||
StripePlanId = "2020-families-org-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
BasePrice = 40,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = false,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.TeamsAnnually,
|
|
||||||
Product = ProductType.Teams,
|
|
||||||
Name = "Teams (Annually)",
|
|
||||||
IsAnnual = true,
|
|
||||||
NameLocalizationKey = "planNameTeams",
|
|
||||||
DescriptionLocalizationKey = "planDescTeams",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
BaseSeats = 0,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
Has2fa = true,
|
|
||||||
HasApi = true,
|
|
||||||
HasDirectory = true,
|
|
||||||
HasEvents = true,
|
|
||||||
HasGroups = true,
|
|
||||||
HasTotp = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 2,
|
|
||||||
DisplaySortOrder = 2,
|
|
||||||
|
|
||||||
StripeSeatPlanId = "2020-teams-org-seat-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
SeatPrice = 36,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.TeamsMonthly,
|
|
||||||
Product = ProductType.Teams,
|
|
||||||
Name = "Teams (Monthly)",
|
|
||||||
NameLocalizationKey = "planNameTeams",
|
|
||||||
DescriptionLocalizationKey = "planDescTeams",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
BaseSeats = 0,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
Has2fa = true,
|
|
||||||
HasApi = true,
|
|
||||||
HasDirectory = true,
|
|
||||||
HasEvents = true,
|
|
||||||
HasGroups = true,
|
|
||||||
HasTotp = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 2,
|
|
||||||
DisplaySortOrder = 2,
|
|
||||||
|
|
||||||
StripeSeatPlanId = "2020-teams-org-seat-monthly",
|
|
||||||
StripeStoragePlanId = "storage-gb-monthly",
|
|
||||||
SeatPrice = 4,
|
|
||||||
AdditionalStoragePricePerGb = 0.5M,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.EnterpriseAnnually,
|
|
||||||
Name = "Enterprise (Annually)",
|
|
||||||
Product = ProductType.Enterprise,
|
|
||||||
IsAnnual = true,
|
|
||||||
NameLocalizationKey = "planNameEnterprise",
|
|
||||||
DescriptionLocalizationKey = "planDescEnterprise",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 0,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = 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 = 3,
|
|
||||||
DisplaySortOrder = 3,
|
|
||||||
|
|
||||||
StripeSeatPlanId = "2020-enterprise-org-seat-annually",
|
|
||||||
StripeStoragePlanId = "storage-gb-annually",
|
|
||||||
BasePrice = 0,
|
|
||||||
SeatPrice = 60,
|
|
||||||
AdditionalStoragePricePerGb = 4,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.EnterpriseMonthly,
|
|
||||||
Product = ProductType.Enterprise,
|
|
||||||
Name = "Enterprise (Monthly)",
|
|
||||||
NameLocalizationKey = "planNameEnterprise",
|
|
||||||
DescriptionLocalizationKey = "planDescEnterprise",
|
|
||||||
CanBeUsedByBusiness = true,
|
|
||||||
BaseSeats = 0,
|
|
||||||
BaseStorageGb = 1,
|
|
||||||
|
|
||||||
HasAdditionalSeatsOption = true,
|
|
||||||
HasAdditionalStorageOption = true,
|
|
||||||
TrialPeriodDays = 7,
|
|
||||||
|
|
||||||
HasPolicies = true,
|
|
||||||
HasGroups = true,
|
|
||||||
HasDirectory = true,
|
|
||||||
HasEvents = true,
|
|
||||||
HasTotp = true,
|
|
||||||
Has2fa = true,
|
|
||||||
HasApi = true,
|
|
||||||
HasSelfHost = true,
|
|
||||||
HasSso = true,
|
|
||||||
HasKeyConnector = true,
|
|
||||||
HasScim = true,
|
|
||||||
HasResetPassword = true,
|
|
||||||
UsersGetPremium = true,
|
|
||||||
HasCustomPermissions = true,
|
|
||||||
|
|
||||||
UpgradeSortOrder = 3,
|
|
||||||
DisplaySortOrder = 3,
|
|
||||||
|
|
||||||
StripeSeatPlanId = "2020-enterprise-seat-monthly",
|
|
||||||
StripeStoragePlanId = "storage-gb-monthly",
|
|
||||||
BasePrice = 0,
|
|
||||||
SeatPrice = 6,
|
|
||||||
AdditionalStoragePricePerGb = 0.5M,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
new Plan
|
|
||||||
{
|
|
||||||
Type = PlanType.Custom,
|
|
||||||
|
|
||||||
AllowSeatAutoscale = true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDictionary<GlobalEquivalentDomainsType, IEnumerable<string>> GlobalDomains { get; set; }
|
public static IDictionary<GlobalEquivalentDomainsType, IEnumerable<string>> GlobalDomains { get; set; }
|
||||||
public static IEnumerable<Plan> Plans { get; set; }
|
public static IEnumerable<Plan> Plans { get; set; }
|
||||||
|
public static IEnumerable<Plan> SecretManagerPlans { get; set; }
|
||||||
|
public static IEnumerable<Plan> PasswordManagerPlans { get; set; }
|
||||||
public static IEnumerable<SponsoredPlan> SponsoredPlans { get; set; } = new[]
|
public static IEnumerable<SponsoredPlan> SponsoredPlans { get; set; } = new[]
|
||||||
{
|
{
|
||||||
new SponsoredPlan
|
new SponsoredPlan
|
||||||
@ -497,11 +128,15 @@ public class StaticStore
|
|||||||
SponsoringProductType = ProductType.Enterprise,
|
SponsoringProductType = ProductType.Enterprise,
|
||||||
StripePlanId = "2021-family-for-enterprise-annually",
|
StripePlanId = "2021-family-for-enterprise-annually",
|
||||||
UsersCanSponsor = (OrganizationUserOrganizationDetails org) =>
|
UsersCanSponsor = (OrganizationUserOrganizationDetails org) =>
|
||||||
GetPlan(org.PlanType).Product == ProductType.Enterprise,
|
GetPasswordManagerPlan(org.PlanType).Product == ProductType.Enterprise,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public static Plan GetPlan(PlanType planType) =>
|
public static Plan GetPasswordManagerPlan(PlanType planType) =>
|
||||||
Plans.FirstOrDefault(p => p.Type == planType);
|
PasswordManagerPlans.SingleOrDefault(p => p.Type == planType);
|
||||||
|
|
||||||
|
public static Plan GetSecretsManagerPlan(PlanType planType) =>
|
||||||
|
SecretManagerPlans.SingleOrDefault(p => p.Type == planType);
|
||||||
|
|
||||||
public static SponsoredPlan GetSponsoredPlan(PlanSponsorshipType planSponsorshipType) =>
|
public static SponsoredPlan GetSponsoredPlan(PlanSponsorshipType planSponsorshipType) =>
|
||||||
SponsoredPlans.FirstOrDefault(p => p.PlanSponsorshipType == planSponsorshipType);
|
SponsoredPlans.FirstOrDefault(p => p.PlanSponsorshipType == planSponsorshipType);
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ namespace Bit.Api.Test.Controllers;
|
|||||||
public class OrganizationSponsorshipsControllerTests
|
public class OrganizationSponsorshipsControllerTests
|
||||||
{
|
{
|
||||||
public static IEnumerable<object[]> EnterprisePlanTypes =>
|
public static IEnumerable<object[]> EnterprisePlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product == ProductType.Enterprise).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product == ProductType.Enterprise).Select(p => new object[] { p });
|
||||||
public static IEnumerable<object[]> NonEnterprisePlanTypes =>
|
public static IEnumerable<object[]> NonEnterprisePlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product != ProductType.Enterprise).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product != ProductType.Enterprise).Select(p => new object[] { p });
|
||||||
public static IEnumerable<object[]> NonFamiliesPlanTypes =>
|
public static IEnumerable<object[]> NonFamiliesPlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product != ProductType.Families).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product != ProductType.Families).Select(p => new object[] { p });
|
||||||
|
|
||||||
public static IEnumerable<object[]> NonConfirmedOrganizationUsersStatuses =>
|
public static IEnumerable<object[]> NonConfirmedOrganizationUsersStatuses =>
|
||||||
Enum.GetValues<OrganizationUserStatusType>()
|
Enum.GetValues<OrganizationUserStatusType>()
|
||||||
|
@ -305,7 +305,7 @@ public class SyncControllerTests
|
|||||||
|
|
||||||
if (matchedProviderUserOrgDetails != null)
|
if (matchedProviderUserOrgDetails != null)
|
||||||
{
|
{
|
||||||
var providerOrgProductType = StaticStore.GetPlan(matchedProviderUserOrgDetails.PlanType).Product;
|
var providerOrgProductType = StaticStore.GetPasswordManagerPlan(matchedProviderUserOrgDetails.PlanType).Product;
|
||||||
Assert.Equal(providerOrgProductType, profProviderOrg.PlanProductType);
|
Assert.Equal(providerOrgProductType, profProviderOrg.PlanProductType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ internal class PaidOrganization : ICustomization
|
|||||||
public PlanType CheckedPlanType { get; set; }
|
public PlanType CheckedPlanType { get; set; }
|
||||||
public void Customize(IFixture fixture)
|
public void Customize(IFixture fixture)
|
||||||
{
|
{
|
||||||
var validUpgradePlans = StaticStore.Plans.Where(p => p.Type != PlanType.Free && p.LegacyYear == null).OrderBy(p => p.UpgradeSortOrder).Select(p => p.Type).ToList();
|
var validUpgradePlans = StaticStore.PasswordManagerPlans.Where(p => p.Type != PlanType.Free && p.LegacyYear == null).OrderBy(p => p.UpgradeSortOrder).Select(p => p.Type).ToList();
|
||||||
var lowestActivePaidPlan = validUpgradePlans.First();
|
var lowestActivePaidPlan = validUpgradePlans.First();
|
||||||
CheckedPlanType = CheckedPlanType.Equals(PlanType.Free) ? lowestActivePaidPlan : CheckedPlanType;
|
CheckedPlanType = CheckedPlanType.Equals(PlanType.Free) ? lowestActivePaidPlan : CheckedPlanType;
|
||||||
validUpgradePlans.Remove(lowestActivePaidPlan);
|
validUpgradePlans.Remove(lowestActivePaidPlan);
|
||||||
@ -93,7 +93,7 @@ internal class FreeOrganizationUpgrade : ICustomization
|
|||||||
.With(o => o.PlanType, PlanType.Free));
|
.With(o => o.PlanType, PlanType.Free));
|
||||||
|
|
||||||
var plansToIgnore = new List<PlanType> { PlanType.Free, PlanType.Custom };
|
var plansToIgnore = new List<PlanType> { PlanType.Free, PlanType.Custom };
|
||||||
var selectedPlan = StaticStore.Plans.Last(p => !plansToIgnore.Contains(p.Type) && !p.Disabled);
|
var selectedPlan = StaticStore.PasswordManagerPlans.Last(p => !plansToIgnore.Contains(p.Type) && !p.Disabled);
|
||||||
|
|
||||||
fixture.Customize<OrganizationUpgrade>(composer => composer
|
fixture.Customize<OrganizationUpgrade>(composer => composer
|
||||||
.With(ou => ou.Plan, selectedPlan.Type)
|
.With(ou => ou.Plan, selectedPlan.Type)
|
||||||
|
@ -6,16 +6,16 @@ namespace Bit.Core.Test.OrganizationFeatures.OrganizationSponsorships.FamiliesFo
|
|||||||
public abstract class FamiliesForEnterpriseTestsBase
|
public abstract class FamiliesForEnterpriseTestsBase
|
||||||
{
|
{
|
||||||
public static IEnumerable<object[]> EnterprisePlanTypes =>
|
public static IEnumerable<object[]> EnterprisePlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product == ProductType.Enterprise).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product == ProductType.Enterprise).Select(p => new object[] { p });
|
||||||
|
|
||||||
public static IEnumerable<object[]> NonEnterprisePlanTypes =>
|
public static IEnumerable<object[]> NonEnterprisePlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product != ProductType.Enterprise).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product != ProductType.Enterprise).Select(p => new object[] { p });
|
||||||
|
|
||||||
public static IEnumerable<object[]> FamiliesPlanTypes =>
|
public static IEnumerable<object[]> FamiliesPlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product == ProductType.Families).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product == ProductType.Families).Select(p => new object[] { p });
|
||||||
|
|
||||||
public static IEnumerable<object[]> NonFamiliesPlanTypes =>
|
public static IEnumerable<object[]> NonFamiliesPlanTypes =>
|
||||||
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPlan(p).Product != ProductType.Families).Select(p => new object[] { p });
|
Enum.GetValues<PlanType>().Where(p => StaticStore.GetPasswordManagerPlan(p).Product != ProductType.Families).Select(p => new object[] { p });
|
||||||
|
|
||||||
public static IEnumerable<object[]> NonConfirmedOrganizationUsersStatuses =>
|
public static IEnumerable<object[]> NonConfirmedOrganizationUsersStatuses =>
|
||||||
Enum.GetValues<OrganizationUserStatusType>()
|
Enum.GetValues<OrganizationUserStatusType>()
|
||||||
|
@ -39,7 +39,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe_ProviderOrg_Coupon_Add(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo, bool provider = true)
|
public async void PurchaseOrganizationAsync_Stripe_ProviderOrg_Coupon_Add(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo, bool provider = true)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
||||||
@ -89,7 +89,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Stripe(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
||||||
@ -141,7 +141,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe_PM(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Stripe_PM(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
paymentToken = "pm_" + paymentToken;
|
paymentToken = "pm_" + paymentToken;
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
@ -194,7 +194,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe_TaxRate(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Stripe_TaxRate(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
||||||
@ -223,7 +223,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe_Declined(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Stripe_Declined(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
paymentToken = "pm_" + paymentToken;
|
paymentToken = "pm_" + paymentToken;
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
@ -256,7 +256,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Stripe_RequiresAction(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Stripe_RequiresAction(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
||||||
@ -287,7 +287,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Paypal(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Paypal(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
|
||||||
@ -346,7 +346,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_Paypal_FailedCreate(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_Paypal_FailedCreate(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
|
|
||||||
var customerResult = Substitute.For<Result<Customer>>();
|
var customerResult = Substitute.For<Result<Customer>>();
|
||||||
customerResult.IsSuccess().Returns(false);
|
customerResult.IsSuccess().Returns(false);
|
||||||
@ -363,7 +363,7 @@ public class StripePaymentServiceTests
|
|||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async void PurchaseOrganizationAsync_PayPal_Declined(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
public async void PurchaseOrganizationAsync_PayPal_Declined(SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
paymentToken = "pm_" + paymentToken;
|
paymentToken = "pm_" + paymentToken;
|
||||||
|
|
||||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||||
@ -425,7 +425,7 @@ public class StripePaymentServiceTests
|
|||||||
});
|
});
|
||||||
stripeAdapter.SubscriptionCreateAsync(default).ReturnsForAnyArgs(new Stripe.Subscription { });
|
stripeAdapter.SubscriptionCreateAsync(default).ReturnsForAnyArgs(new Stripe.Subscription { });
|
||||||
|
|
||||||
var plan = StaticStore.Plans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
var plan = StaticStore.PasswordManagerPlans.First(p => p.Type == PlanType.EnterpriseAnnually);
|
||||||
var result = await sutProvider.Sut.UpgradeFreeOrganizationAsync(organization, plan, 0, 0, false, taxInfo);
|
var result = await sutProvider.Sut.UpgradeFreeOrganizationAsync(organization, plan, 0, 0, false, taxInfo);
|
||||||
|
|
||||||
Assert.Null(result);
|
Assert.Null(result);
|
||||||
|
70
test/Core.Test/Utilities/StaticStoreTests.cs
Normal file
70
test/Core.Test/Utilities/StaticStoreTests.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.StaticStore;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Bit.Core.Test.Utilities;
|
||||||
|
|
||||||
|
|
||||||
|
public class StaticStoreTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void StaticStore_Initialization_Success()
|
||||||
|
{
|
||||||
|
var plans = StaticStore.Plans;
|
||||||
|
Assert.NotNull(plans);
|
||||||
|
Assert.NotEmpty(plans);
|
||||||
|
Assert.Equal(17, plans.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(PlanType.EnterpriseAnnually)]
|
||||||
|
public void StaticStore_GetPasswordManagerPlanByPlanType_Success(PlanType planType)
|
||||||
|
{
|
||||||
|
var plan = StaticStore.GetPasswordManagerPlan(planType);
|
||||||
|
|
||||||
|
Assert.NotNull(plan);
|
||||||
|
Assert.Equal(planType, plan.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(PlanType.EnterpriseAnnually)]
|
||||||
|
public void StaticStore_GetSecretsManagerPlanByPlanType_Success(PlanType planType)
|
||||||
|
{
|
||||||
|
var plan = StaticStore.GetSecretsManagerPlan(planType);
|
||||||
|
|
||||||
|
Assert.NotNull(plan);
|
||||||
|
Assert.Equal(planType, plan.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(PlanType.EnterpriseAnnually)]
|
||||||
|
public void StaticStore_GetPasswordManagerPlan_ReturnsPasswordManagerPlans(PlanType planType)
|
||||||
|
{
|
||||||
|
var plan = StaticStore.GetPasswordManagerPlan(planType);
|
||||||
|
Assert.NotNull(plan);
|
||||||
|
Assert.Equal(BitwardenProductType.PasswordManager, plan.BitwardenProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(PlanType.EnterpriseAnnually)]
|
||||||
|
public void StaticStore_GetSecretsManagerPlan_ReturnsSecretManagerPlans(PlanType planType)
|
||||||
|
{
|
||||||
|
var plan = StaticStore.GetSecretsManagerPlan(planType);
|
||||||
|
Assert.NotNull(plan);
|
||||||
|
Assert.Equal(BitwardenProductType.SecretsManager, plan.BitwardenProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(PlanType.EnterpriseAnnually, BitwardenProductType.PasswordManager)]
|
||||||
|
public void StaticStore_AddDuplicatePlans_SingleOrDefaultThrowsException(PlanType planType, BitwardenProductType bitwardenProductType)
|
||||||
|
{
|
||||||
|
var plansStore = new List<Plan>
|
||||||
|
{
|
||||||
|
new Plan { Type = PlanType.EnterpriseAnnually, BitwardenProduct = BitwardenProductType.PasswordManager },
|
||||||
|
new Plan { Type = PlanType.EnterpriseAnnually, BitwardenProduct = BitwardenProductType.PasswordManager }
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(() => plansStore.SingleOrDefault(p => p.Type == planType && p.BitwardenProduct == bitwardenProductType));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user