From 64a7cba01361d13570f9af59df7e5de7a7cb40f8 Mon Sep 17 00:00:00 2001 From: Jonas Hendrickx Date: Thu, 5 Sep 2024 16:37:20 +0200 Subject: [PATCH] PM-7999 | Reseller billing e-mail can be blank causing downstream errors for org creation (#4733) --- .../Controllers/ProvidersController.cs | 58 ++++++++++++++----- .../AdminConsole/Models/ProviderEditModel.cs | 21 ++++++- .../AdminConsole/Views/Providers/Edit.cshtml | 2 + 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/Admin/AdminConsole/Controllers/ProvidersController.cs b/src/Admin/AdminConsole/Controllers/ProvidersController.cs index cee87fbb71..4adf0fce0c 100644 --- a/src/Admin/AdminConsole/Controllers/ProvidersController.cs +++ b/src/Admin/AdminConsole/Controllers/ProvidersController.cs @@ -162,27 +162,13 @@ public class ProvidersController : Controller [SelfHosted(NotSelfHostedOnly = true)] public async Task Edit(Guid id) { - var provider = await _providerRepository.GetByIdAsync(id); + var provider = await GetEditModel(id); if (provider == null) { return RedirectToAction("Index"); } - var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); - var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); - - var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); - - if (!isConsolidatedBillingEnabled || !provider.IsBillable()) - { - return View(new ProviderEditModel(provider, users, providerOrganizations, new List())); - } - - var providerPlans = await _providerPlanRepository.GetByProviderId(id); - - return View(new ProviderEditModel( - provider, users, providerOrganizations, - providerPlans.ToList(), GetGatewayCustomerUrl(provider), GetGatewaySubscriptionUrl(provider))); + return View(provider); } [HttpPost] @@ -198,6 +184,20 @@ public class ProvidersController : Controller return RedirectToAction("Index"); } + if (provider.Type != model.Type) + { + var oldModel = await GetEditModel(id); + ModelState.AddModelError(nameof(model.Type), "Provider type cannot be changed."); + return View(oldModel); + } + + if (!ModelState.IsValid) + { + var oldModel = await GetEditModel(id); + ModelState[nameof(ProviderEditModel.BillingEmail)]!.RawValue = oldModel.BillingEmail; + return View(oldModel); + } + model.ToProvider(provider); await _providerRepository.ReplaceAsync(provider); @@ -236,6 +236,32 @@ public class ProvidersController : Controller return RedirectToAction("Edit", new { id }); } + private async Task GetEditModel(Guid id) + { + var provider = await _providerRepository.GetByIdAsync(id); + if (provider == null) + { + return null; + } + + var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); + var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); + + var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); + + + if (!isConsolidatedBillingEnabled || !provider.IsBillable()) + { + return new ProviderEditModel(provider, users, providerOrganizations, new List()); + } + + var providerPlans = await _providerPlanRepository.GetByProviderId(id); + + return new ProviderEditModel( + provider, users, providerOrganizations, + providerPlans.ToList(), GetGatewayCustomerUrl(provider), GetGatewaySubscriptionUrl(provider)); + } + [RequirePermission(Permission.Provider_ResendEmailInvite)] public async Task ResendInvite(Guid ownerId, Guid providerId) { diff --git a/src/Admin/AdminConsole/Models/ProviderEditModel.cs b/src/Admin/AdminConsole/Models/ProviderEditModel.cs index 87de1fd983..dd9b9f5a5c 100644 --- a/src/Admin/AdminConsole/Models/ProviderEditModel.cs +++ b/src/Admin/AdminConsole/Models/ProviderEditModel.cs @@ -1,13 +1,15 @@ using System.ComponentModel.DataAnnotations; using Bit.Core.AdminConsole.Entities.Provider; +using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Models.Data.Provider; using Bit.Core.Billing.Entities; using Bit.Core.Billing.Enums; using Bit.Core.Enums; +using Bit.SharedWeb.Utilities; namespace Bit.Admin.AdminConsole.Models; -public class ProviderEditModel : ProviderViewModel +public class ProviderEditModel : ProviderViewModel, IValidatableObject { public ProviderEditModel() { } @@ -30,6 +32,7 @@ public class ProviderEditModel : ProviderViewModel GatewaySubscriptionId = provider.GatewaySubscriptionId; GatewayCustomerUrl = gatewayCustomerUrl; GatewaySubscriptionUrl = gatewaySubscriptionUrl; + Type = provider.Type; } [Display(Name = "Billing Email")] @@ -52,6 +55,8 @@ public class ProviderEditModel : ProviderViewModel public string GatewaySubscriptionId { get; set; } public string GatewayCustomerUrl { get; } public string GatewaySubscriptionUrl { get; } + [Display(Name = "Provider Type")] + public ProviderType Type { get; set; } public virtual Provider ToProvider(Provider existingProvider) { @@ -65,4 +70,18 @@ public class ProviderEditModel : ProviderViewModel private static int GetSeatMinimum(IEnumerable providerPlans, PlanType planType) => providerPlans.FirstOrDefault(providerPlan => providerPlan.PlanType == planType)?.SeatMinimum ?? 0; + + public IEnumerable Validate(ValidationContext validationContext) + { + switch (Type) + { + case ProviderType.Reseller: + if (string.IsNullOrWhiteSpace(BillingEmail)) + { + var billingEmailDisplayName = nameof(BillingEmail).GetDisplayAttribute()?.GetName() ?? nameof(BillingEmail); + yield return new ValidationResult($"The {billingEmailDisplayName} field is required."); + } + break; + } + } } diff --git a/src/Admin/AdminConsole/Views/Providers/Edit.cshtml b/src/Admin/AdminConsole/Views/Providers/Edit.cshtml index 90da796e2d..f4cf36f925 100644 --- a/src/Admin/AdminConsole/Views/Providers/Edit.cshtml +++ b/src/Admin/AdminConsole/Views/Providers/Edit.cshtml @@ -16,6 +16,8 @@ @await Html.PartialAsync("_ViewInformation", Model) @await Html.PartialAsync("Admins", Model)
+
+

General

Name