diff --git a/src/Admin/Controllers/OrganizationsController.cs b/src/Admin/Controllers/OrganizationsController.cs index 2eb223716d..44b83c2f34 100644 --- a/src/Admin/Controllers/OrganizationsController.cs +++ b/src/Admin/Controllers/OrganizationsController.cs @@ -5,6 +5,7 @@ using Bit.Admin.Utilities; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.Exceptions; using Bit.Core.Models.OrganizationConnectionConfigs; using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces; using Bit.Core.Repositories; @@ -199,6 +200,14 @@ public class OrganizationsController : Controller { var organization = await GetOrganization(id, model); + if (organization.UseSecretsManager && + !organization.SecretsManagerBeta + && StaticStore.GetSecretsManagerPlan(organization.PlanType) == null + ) + { + throw new BadRequestException("Plan does not support Secrets Manager"); + } + await _organizationRepository.ReplaceAsync(organization); await _applicationCacheService.UpsertOrganizationAbilityAsync(organization); await _referenceEventService.RaiseEventAsync(new ReferenceEvent(ReferenceEventType.OrganizationEditedByAdmin, organization, _currentContext) diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index 7481ff6779..76222fbb18 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -28,9 +28,9 @@ public class OrganizationEditModel : OrganizationViewModel public OrganizationEditModel(Organization org, Provider provider, IEnumerable orgUsers, IEnumerable ciphers, IEnumerable collections, IEnumerable groups, IEnumerable policies, BillingInfo billingInfo, IEnumerable connections, - GlobalSettings globalSettings, int secrets, int projects, int serviceAccounts, int smSeats) + GlobalSettings globalSettings, int secrets, int projects, int serviceAccounts, int occupiedSmSeats) : base(org, provider, connections, orgUsers, ciphers, collections, groups, policies, secrets, projects, - serviceAccounts, smSeats) + serviceAccounts, occupiedSmSeats) { BillingInfo = billingInfo; BraintreeMerchantId = globalSettings.Braintree.MerchantId; @@ -145,13 +145,26 @@ public class OrganizationEditModel : OrganizationViewModel public int? SmSeats { get; set; } [Display(Name = "Max Autoscale Seats")] public int? MaxAutoscaleSmSeats { get; set; } - [Display(Name = "Max Service Accounts")] + [Display(Name = "Service Accounts")] public int? SmServiceAccounts { get; set; } [Display(Name = "Max Autoscale Service Accounts")] public int? MaxAutoscaleSmServiceAccounts { get; set; } [Display(Name = "Secrets Manager Beta")] public bool SecretsManagerBeta { get; set; } + /** + * Creates a Plan[] object for use in Javascript + * This is mapped manually below to provide some type safety in case the plan objects change + * Add mappings for individual properties as you need them + */ + public IEnumerable> GetPlansHelper() => + StaticStore.SecretManagerPlans.Select(p => + new Dictionary + { + { "type", p.Type }, + { "baseServiceAccount", p.BaseServiceAccount } + }); + public Organization CreateOrganization(Provider provider) { BillingEmail = provider.BillingEmail; diff --git a/src/Admin/Models/OrganizationViewModel.cs b/src/Admin/Models/OrganizationViewModel.cs index 491ff9191b..7320b8594d 100644 --- a/src/Admin/Models/OrganizationViewModel.cs +++ b/src/Admin/Models/OrganizationViewModel.cs @@ -13,7 +13,7 @@ public class OrganizationViewModel public OrganizationViewModel(Organization org, Provider provider, IEnumerable connections, IEnumerable orgUsers, IEnumerable ciphers, IEnumerable collections, IEnumerable groups, IEnumerable policies, int secretsCount, int projectCount, int serviceAccountsCount, - int smSeatsCount) + int occupiedSmSeatsCount) { Organization = org; @@ -39,10 +39,10 @@ public class OrganizationViewModel orgUsers .Where(u => u.Type == OrganizationUserType.Admin && u.Status == organizationUserStatus) .Select(u => u.Email)); - Secrets = secretsCount; - Projects = projectCount; - ServiceAccounts = serviceAccountsCount; - SmSeats = smSeatsCount; + SecretsCount = secretsCount; + ProjectsCount = projectCount; + ServiceAccountsCount = serviceAccountsCount; + OccupiedSmSeatsCount = occupiedSmSeatsCount; } public Organization Organization { get; set; } @@ -59,9 +59,9 @@ public class OrganizationViewModel public int GroupCount { get; set; } public int PolicyCount { get; set; } public bool HasPublicPrivateKeys { get; set; } - public int Secrets { get; set; } - public int Projects { get; set; } - public int ServiceAccounts { get; set; } - public int SmSeats { get; set; } + public int SecretsCount { get; set; } + public int ProjectsCount { get; set; } + public int ServiceAccountsCount { get; set; } + public int OccupiedSmSeatsCount { get; set; } public bool UseSecretsManager => Organization.UseSecretsManager; } diff --git a/src/Admin/Views/Organizations/Edit.cshtml b/src/Admin/Views/Organizations/Edit.cshtml index e4c329007c..e3f6d50905 100644 --- a/src/Admin/Views/Organizations/Edit.cshtml +++ b/src/Admin/Views/Organizations/Edit.cshtml @@ -12,25 +12,45 @@ @section Scripts { @await Html.PartialAsync("_OrganizationFormScripts") - + } diff --git a/src/Admin/Views/Organizations/_ViewInformation.cshtml b/src/Admin/Views/Organizations/_ViewInformation.cshtml index df4513ccaa..19432cd4f7 100644 --- a/src/Admin/Views/Organizations/_ViewInformation.cshtml +++ b/src/Admin/Views/Organizations/_ViewInformation.cshtml @@ -33,16 +33,16 @@
@Model.CollectionCount
Secrets
-
@(Model.UseSecretsManager ? Model.Secrets: "N/A")
+
@(Model.UseSecretsManager ? Model.SecretsCount: "N/A")
Projects
-
@(Model.UseSecretsManager ? Model.Projects: "N/A")
+
@(Model.UseSecretsManager ? Model.ProjectsCount: "N/A")
Service Accounts
-
@(Model.UseSecretsManager ? Model.ServiceAccounts: "N/A")
+
@(Model.UseSecretsManager ? Model.ServiceAccountsCount: "N/A")
Secrets Manager Seats
-
@(Model.UseSecretsManager ? Model.SmSeats: "N/A" )
+
@(Model.UseSecretsManager ? Model.OccupiedSmSeatsCount: "N/A" )
Groups
@Model.GroupCount
diff --git a/src/Admin/Views/Providers/CreateOrganization.cshtml b/src/Admin/Views/Providers/CreateOrganization.cshtml index 2257f6e334..e4298960a0 100644 --- a/src/Admin/Views/Providers/CreateOrganization.cshtml +++ b/src/Admin/Views/Providers/CreateOrganization.cshtml @@ -5,10 +5,10 @@ @section Scripts { @await Html.PartialAsync("_OrganizationFormScripts") - + } diff --git a/src/Admin/Views/Shared/_OrganizationForm.cshtml b/src/Admin/Views/Shared/_OrganizationForm.cshtml index 3e816c9d76..9b76d1c2a8 100644 --- a/src/Admin/Views/Shared/_OrganizationForm.cshtml +++ b/src/Admin/Views/Shared/_OrganizationForm.cshtml @@ -83,7 +83,7 @@ var planTypes = Enum.GetValues() .Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.EnterpriseAnnually) .Select(e => new SelectListItem - { + { Value = ((int)e).ToString(), Text = e.GetDisplayAttribute()?.GetName() ?? e.ToString() }) @@ -176,7 +176,7 @@ } - + @if (canViewPlan) {

Password Manager Configuration

@@ -212,7 +212,7 @@ @if (canViewPlan) { -