Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
Browse files Browse the repository at this point in the history
…llections
  • Loading branch information
eliykat committed Oct 18, 2023
2 parents 3b049a6 + 8c77c65 commit ae18e76
Show file tree
Hide file tree
Showing 79 changed files with 1,665 additions and 1,469 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
version: ${{ github.event.inputs.version_number }}
file_path: "Directory.Build.props"

- name: Refresh lockfiles
run: dotnet restore -f --force-evaluate --no-cache

- name: Setup git
run: |
git config --local user.email "[email protected]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ public MaxProjectsQuery(
throw new NotFoundException();
}

var plan = StaticStore.GetSecretsManagerPlan(org.PlanType);
if (plan == null)
var plan = StaticStore.GetPlan(org.PlanType);
if (plan?.SecretsManager == null)
{
throw new BadRequestException("Existing plan not found.");
}

if (plan.Type == PlanType.Free)
{
var projects = await _projectRepository.GetProjectCountByOrganizationIdAsync(organizationId);
return projects + projectsToAdd > plan.MaxProjects ? (plan.MaxProjects, true) : (plan.MaxProjects, false);
return ((short? max, bool? overMax))(projects + projectsToAdd > plan.SecretsManager.MaxProjects ? (plan.SecretsManager.MaxProjects, true) : (plan.SecretsManager.MaxProjects, false));
}

return (null, null);
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.413",
"version": "6.0.415",
"rollForward": "latestFeature"
}
}
5 changes: 2 additions & 3 deletions src/Admin/Controllers/OrganizationsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,8 @@ public async Task<IActionResult> Edit(Guid id, OrganizationEditModel model)
var organization = await GetOrganization(id, model);

if (organization.UseSecretsManager &&
!organization.SecretsManagerBeta
&& StaticStore.GetSecretsManagerPlan(organization.PlanType) == null
)
!organization.SecretsManagerBeta &&
!StaticStore.GetPlan(organization.PlanType).SupportsSecretsManager)
{
throw new BadRequestException("Plan does not support Secrets Manager");
}
Expand Down
7 changes: 4 additions & 3 deletions src/Admin/Models/OrganizationEditModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,12 @@ public OrganizationEditModel(Organization org, Provider provider, IEnumerable<Or
* Add mappings for individual properties as you need them
*/
public IEnumerable<Dictionary<string, object>> GetPlansHelper() =>
StaticStore.SecretManagerPlans.Select(p =>
new Dictionary<string, object>
StaticStore.Plans
.Where(p => p.SupportsSecretsManager)
.Select(p => new Dictionary<string, object>
{
{ "type", p.Type },
{ "baseServiceAccount", p.BaseServiceAccount }
{ "baseServiceAccount", p.SecretsManager.BaseServiceAccount }
});

public Organization CreateOrganization(Provider provider)
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Controllers/OrganizationsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ public async Task<ApiKeyResponseModel> ApiKey(string id, [FromBody] Organization
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
var plan = StaticStore.GetPasswordManagerPlan(organization.PlanType);
var plan = StaticStore.GetPlan(organization.PlanType);
if (plan.Product != ProductType.Enterprise)
{
throw new NotFoundException();
Expand Down
18 changes: 0 additions & 18 deletions src/Api/Controllers/PlansController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,12 @@ public PlansController(ITaxRateRepository taxRateRepository)
[HttpGet("")]
[AllowAnonymous]
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 responses = data.Select(plan => new PlanResponseModel(plan));
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")]
public async Task<ListResponseModel<TaxRateResponseModel>> GetTaxRates()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ public OrganizationResponseModel(Organization organization, string obj = "organi
BusinessCountry = organization.BusinessCountry;
BusinessTaxNumber = organization.BusinessTaxNumber;
BillingEmail = organization.BillingEmail;
Plan = new PlanResponseModel(StaticStore.PasswordManagerPlans.FirstOrDefault(plan => plan.Type == organization.PlanType));
var matchingPlan = StaticStore.GetSecretsManagerPlan(organization.PlanType);
if (matchingPlan != null)
{
SecretsManagerPlan = new PlanResponseModel(matchingPlan);
}
Plan = new PlanResponseModel(StaticStore.GetPlan(organization.PlanType));
PlanType = organization.PlanType;
Seats = organization.Seats;
MaxAutoscaleSeats = organization.MaxAutoscaleSeats;
Expand Down
145 changes: 95 additions & 50 deletions src/Api/Models/Response/PlanResponseModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,6 @@ public PlanResponseModel(Plan plan, string obj = "plan")
NameLocalizationKey = plan.NameLocalizationKey;
DescriptionLocalizationKey = plan.DescriptionLocalizationKey;
CanBeUsedByBusiness = plan.CanBeUsedByBusiness;
BaseSeats = plan.BaseSeats;
BaseStorageGb = plan.BaseStorageGb;
MaxCollections = plan.MaxCollections;
MaxUsers = plan.MaxUsers;
HasAdditionalSeatsOption = plan.HasAdditionalSeatsOption;
HasAdditionalStorageOption = plan.HasAdditionalStorageOption;
MaxAdditionalSeats = plan.MaxAdditionalSeats;
MaxAdditionalStorage = plan.MaxAdditionalStorage;
HasPremiumAccessOption = plan.HasPremiumAccessOption;
TrialPeriodDays = plan.TrialPeriodDays;
HasSelfHost = plan.HasSelfHost;
HasPolicies = plan.HasPolicies;
Expand All @@ -45,22 +36,12 @@ public PlanResponseModel(Plan plan, string obj = "plan")
DisplaySortOrder = plan.DisplaySortOrder;
LegacyYear = plan.LegacyYear;
Disabled = plan.Disabled;
StripePlanId = plan.StripePlanId;
StripeSeatPlanId = plan.StripeSeatPlanId;
StripeStoragePlanId = plan.StripeStoragePlanId;
BasePrice = plan.BasePrice;
SeatPrice = plan.SeatPrice;
AdditionalStoragePricePerGb = plan.AdditionalStoragePricePerGb;
PremiumAccessOptionPrice = plan.PremiumAccessOptionPrice;
if (plan.SecretsManager != null)
{
SecretsManager = new SecretsManagerPlanFeaturesResponseModel(plan.SecretsManager);
}

AdditionalPricePerServiceAccount = plan.AdditionalPricePerServiceAccount;
BaseServiceAccount = plan.BaseServiceAccount;
MaxServiceAccounts = plan.MaxServiceAccounts;
MaxAdditionalServiceAccounts = plan.MaxAdditionalServiceAccount;
HasAdditionalServiceAccountOption = plan.HasAdditionalServiceAccountOption;
MaxProjects = plan.MaxProjects;
BitwardenProduct = plan.BitwardenProduct;
StripeServiceAccountPlanId = plan.StripeServiceAccountPlanId;
PasswordManager = new PasswordManagerPlanFeaturesResponseModel(plan.PasswordManager);
}

public PlanType Type { get; set; }
Expand All @@ -70,16 +51,6 @@ public PlanResponseModel(Plan plan, string obj = "plan")
public string NameLocalizationKey { get; set; }
public string DescriptionLocalizationKey { get; set; }
public bool CanBeUsedByBusiness { get; set; }
public int BaseSeats { get; set; }
public short? BaseStorageGb { get; set; }
public short? MaxCollections { get; set; }
public short? MaxUsers { get; set; }

public bool HasAdditionalSeatsOption { get; set; }
public int? MaxAdditionalSeats { get; set; }
public bool HasAdditionalStorageOption { get; set; }
public short? MaxAdditionalStorage { get; set; }
public bool HasPremiumAccessOption { get; set; }
public int? TrialPeriodDays { get; set; }

public bool HasSelfHost { get; set; }
Expand All @@ -98,21 +69,95 @@ public PlanResponseModel(Plan plan, string obj = "plan")
public int DisplaySortOrder { get; set; }
public int? LegacyYear { get; set; }
public bool Disabled { get; set; }
public SecretsManagerPlanFeaturesResponseModel SecretsManager { get; protected init; }
public PasswordManagerPlanFeaturesResponseModel PasswordManager { get; protected init; }

public class SecretsManagerPlanFeaturesResponseModel
{
public SecretsManagerPlanFeaturesResponseModel(Plan.SecretsManagerPlanFeatures plan)
{
MaxServiceAccounts = plan.MaxServiceAccounts;
AllowServiceAccountsAutoscale = plan is { AllowServiceAccountsAutoscale: true };
StripeServiceAccountPlanId = plan.StripeServiceAccountPlanId;
AdditionalPricePerServiceAccount = plan.AdditionalPricePerServiceAccount;
BaseServiceAccount = plan.BaseServiceAccount;
MaxAdditionalServiceAccount = plan.MaxAdditionalServiceAccount;
HasAdditionalServiceAccountOption = plan is { HasAdditionalServiceAccountOption: true };
StripeSeatPlanId = plan.StripeSeatPlanId;
HasAdditionalSeatsOption = plan is { HasAdditionalSeatsOption: true };
BasePrice = plan.BasePrice;
SeatPrice = plan.SeatPrice;
BaseSeats = plan.BaseSeats;
MaxSeats = plan.MaxSeats;
MaxAdditionalSeats = plan.MaxAdditionalSeats;
AllowSeatAutoscale = plan.AllowSeatAutoscale;
MaxProjects = plan.MaxProjects;
}
// Service accounts
public short? MaxServiceAccounts { get; init; }
public bool AllowServiceAccountsAutoscale { get; init; }
public string StripeServiceAccountPlanId { get; init; }
public decimal? AdditionalPricePerServiceAccount { get; init; }
public short? BaseServiceAccount { get; init; }
public short? MaxAdditionalServiceAccount { get; init; }
public bool HasAdditionalServiceAccountOption { get; init; }
// Seats
public string StripeSeatPlanId { get; init; }
public bool HasAdditionalSeatsOption { get; init; }
public decimal BasePrice { get; init; }
public decimal SeatPrice { get; init; }
public int BaseSeats { get; init; }
public short? MaxSeats { get; init; }
public int? MaxAdditionalSeats { get; init; }
public bool AllowSeatAutoscale { get; init; }

public string StripePlanId { get; set; }
public string StripeSeatPlanId { get; set; }
public string StripeStoragePlanId { get; set; }
public string StripePremiumAccessPlanId { get; set; }
public decimal BasePrice { get; set; }
public decimal SeatPrice { get; set; }
public decimal AdditionalStoragePricePerGb { get; set; }
public decimal PremiumAccessOptionPrice { get; set; }
public string StripeServiceAccountPlanId { get; set; }
public decimal? AdditionalPricePerServiceAccount { get; set; }
public short? BaseServiceAccount { get; set; }
public short? MaxServiceAccounts { get; set; }
public short? MaxAdditionalServiceAccounts { get; set; }
public bool HasAdditionalServiceAccountOption { get; set; }
public short? MaxProjects { get; set; }
public BitwardenProductType BitwardenProduct { get; set; }
// Features
public int MaxProjects { get; init; }
}

public record PasswordManagerPlanFeaturesResponseModel
{
public PasswordManagerPlanFeaturesResponseModel(Plan.PasswordManagerPlanFeatures plan)
{
StripePlanId = plan.StripePlanId;
StripeSeatPlanId = plan.StripeSeatPlanId;
BasePrice = plan.BasePrice;
SeatPrice = plan.SeatPrice;
AllowSeatAutoscale = plan.AllowSeatAutoscale;
HasAdditionalSeatsOption = plan.HasAdditionalSeatsOption;
MaxAdditionalSeats = plan.MaxAdditionalSeats;
BaseSeats = plan.BaseSeats;
HasPremiumAccessOption = plan.HasPremiumAccessOption;
StripePremiumAccessPlanId = plan.StripePremiumAccessPlanId;
PremiumAccessOptionPrice = plan.PremiumAccessOptionPrice;
MaxSeats = plan.MaxSeats;
BaseStorageGb = plan.BaseStorageGb;
HasAdditionalStorageOption = plan.HasAdditionalStorageOption;
AdditionalStoragePricePerGb = plan.AdditionalStoragePricePerGb;
StripeStoragePlanId = plan.StripeStoragePlanId;
MaxAdditionalStorage = plan.MaxAdditionalStorage;
MaxCollections = plan.MaxCollections;
}
// Seats
public string StripePlanId { get; init; }
public string StripeSeatPlanId { get; init; }
public decimal BasePrice { get; init; }
public decimal SeatPrice { get; init; }
public bool AllowSeatAutoscale { get; init; }
public bool HasAdditionalSeatsOption { get; init; }
public int? MaxAdditionalSeats { get; init; }
public int BaseSeats { get; init; }
public bool HasPremiumAccessOption { get; init; }
public string StripePremiumAccessPlanId { get; init; }
public decimal PremiumAccessOptionPrice { get; init; }
public short? MaxSeats { get; init; }
// Storage
public short? BaseStorageGb { get; init; }
public bool HasAdditionalStorageOption { get; init; }
public decimal AdditionalStoragePricePerGb { get; init; }
public string StripeStoragePlanId { get; init; }
public short? MaxAdditionalStorage { get; init; }
// Feature
public short? MaxCollections { get; init; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public ProfileOrganizationResponseModel(OrganizationUserOrganizationDetails orga
FamilySponsorshipAvailable = FamilySponsorshipFriendlyName == null &&
StaticStore.GetSponsoredPlan(PlanSponsorshipType.FamiliesForEnterprise)
.UsersCanSponsor(organization);
PlanProductType = StaticStore.GetPasswordManagerPlan(organization.PlanType).Product;
PlanProductType = StaticStore.GetPlan(organization.PlanType).Product;
FamilySponsorshipLastSyncDate = organization.FamilySponsorshipLastSyncDate;
FamilySponsorshipToDelete = organization.FamilySponsorshipToDelete;
FamilySponsorshipValidUntil = organization.FamilySponsorshipValidUntil;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ public ProfileProviderOrganizationResponseModel(ProviderUserOrganizationDetails
UserId = organization.UserId;
ProviderId = organization.ProviderId;
ProviderName = organization.ProviderName;
PlanProductType = StaticStore.GetPasswordManagerPlan(organization.PlanType).Product;
PlanProductType = StaticStore.GetPlan(organization.PlanType).Product;
}
}
3 changes: 0 additions & 3 deletions src/Api/Models/Response/SubscriptionResponseModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api;
using Bit.Core.Models.Business;
using Bit.Core.Utilities;
Expand Down Expand Up @@ -98,7 +97,6 @@ public BillingSubscriptionItem(SubscriptionInfo.BillingSubscription.BillingSubsc
Quantity = item.Quantity;
SponsoredSubscriptionItem = item.SponsoredSubscriptionItem;
AddonSubscriptionItem = item.AddonSubscriptionItem;
BitwardenProduct = item.BitwardenProduct;
}

public string Name { get; set; }
Expand All @@ -107,7 +105,6 @@ public BillingSubscriptionItem(SubscriptionInfo.BillingSubscription.BillingSubsc
public string Interval { get; set; }
public bool SponsoredSubscriptionItem { get; set; }
public bool AddonSubscriptionItem { get; set; }
public BitwardenProductType BitwardenProduct { get; set; }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
using Bit.Core.SecretsManager.Entities;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Bit.Api.SecretsManager.Controllers;

[Authorize("secrets")]
[SelfHosted(NotSelfHostedOnly = true)]
[Route("access-policies")]
public class AccessPoliciesController : Controller
{
Expand Down
2 changes: 0 additions & 2 deletions src/Api/SecretsManager/Controllers/ProjectsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
using Bit.Core.SecretsManager.Queries.Projects.Interfaces;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Bit.Api.SecretsManager.Controllers;

[Authorize("secrets")]
[SelfHosted(NotSelfHostedOnly = true)]
public class ProjectsController : Controller
{
private readonly ICurrentContext _currentContext;
Expand Down
2 changes: 0 additions & 2 deletions src/Api/SecretsManager/Controllers/SecretsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Business;
using Bit.Core.Tools.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Bit.Api.SecretsManager.Controllers;

[Authorize("secrets")]
[SelfHosted(NotSelfHostedOnly = true)]
public class SecretsController : Controller
{
private readonly ICurrentContext _currentContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
using Bit.Core.SecretsManager.Queries.Projects.Interfaces;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Bit.Api.SecretsManager.Controllers;

[Authorize("secrets")]
[SelfHosted(NotSelfHostedOnly = true)]
public class SecretsManagerPortingController : Controller
{
private readonly ISecretRepository _secretRepository;
Expand Down
Loading

0 comments on commit ae18e76

Please sign in to comment.