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

[PM-11798] Remove enable-consolidated-billing feature flag (#5028)

* Remove flag from CreateProviderCommand

* Remove flag from OrganizationsController

* Consolidate provider extensions

* Remove flag from ProvidersController

* Remove flag from CreateMsp.cshtml

* Remove flag from Provider Edit.cshtml

Also ensured the editable Gateway fields show for Multi-organization enterprises

* Remove flag from OrganizationsController

* Remove flag from billing-owned provider controllers

* Remove flag from OrganizationService

* Remove flag from RemoveOrganizationFromProviderCommand

* Remove flag from ProviderService

* Remove flag

* Run dotnet format

* Fix failing tests
This commit is contained in:
Alex Morask 2024-11-15 09:30:03 -05:00 committed by GitHub
parent eee7494c91
commit df21d574e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 119 additions and 302 deletions

View File

@ -1,5 +1,4 @@
using Bit.Core; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Providers.Interfaces; using Bit.Core.AdminConsole.Providers.Interfaces;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
@ -10,7 +9,6 @@ using Bit.Core.Billing.Repositories;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Repositories; using Bit.Core.Repositories;
using Bit.Core.Services;
namespace Bit.Commercial.Core.AdminConsole.Providers; namespace Bit.Commercial.Core.AdminConsole.Providers;
@ -21,35 +19,28 @@ public class CreateProviderCommand : ICreateProviderCommand
private readonly IProviderService _providerService; private readonly IProviderService _providerService;
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
private readonly IProviderPlanRepository _providerPlanRepository; private readonly IProviderPlanRepository _providerPlanRepository;
private readonly IFeatureService _featureService;
public CreateProviderCommand( public CreateProviderCommand(
IProviderRepository providerRepository, IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository, IProviderUserRepository providerUserRepository,
IProviderService providerService, IProviderService providerService,
IUserRepository userRepository, IUserRepository userRepository,
IProviderPlanRepository providerPlanRepository, IProviderPlanRepository providerPlanRepository)
IFeatureService featureService)
{ {
_providerRepository = providerRepository; _providerRepository = providerRepository;
_providerUserRepository = providerUserRepository; _providerUserRepository = providerUserRepository;
_providerService = providerService; _providerService = providerService;
_userRepository = userRepository; _userRepository = userRepository;
_providerPlanRepository = providerPlanRepository; _providerPlanRepository = providerPlanRepository;
_featureService = featureService;
} }
public async Task CreateMspAsync(Provider provider, string ownerEmail, int teamsMinimumSeats, int enterpriseMinimumSeats) public async Task CreateMspAsync(Provider provider, string ownerEmail, int teamsMinimumSeats, int enterpriseMinimumSeats)
{ {
var providerId = await CreateProviderAsync(provider, ownerEmail); var providerId = await CreateProviderAsync(provider, ownerEmail);
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); await Task.WhenAll(
CreateProviderPlanAsync(providerId, PlanType.TeamsMonthly, teamsMinimumSeats),
if (isConsolidatedBillingEnabled) CreateProviderPlanAsync(providerId, PlanType.EnterpriseMonthly, enterpriseMinimumSeats));
{
await CreateProviderPlanAsync(providerId, PlanType.TeamsMonthly, teamsMinimumSeats);
await CreateProviderPlanAsync(providerId, PlanType.EnterpriseMonthly, enterpriseMinimumSeats);
}
} }
public async Task CreateResellerAsync(Provider provider) public async Task CreateResellerAsync(Provider provider)
@ -61,13 +52,8 @@ public class CreateProviderCommand : ICreateProviderCommand
{ {
var providerId = await CreateProviderAsync(provider, ownerEmail); var providerId = await CreateProviderAsync(provider, ownerEmail);
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling);
if (isConsolidatedBillingEnabled)
{
await CreateProviderPlanAsync(providerId, plan, minimumSeats); await CreateProviderPlanAsync(providerId, plan, minimumSeats);
} }
}
private async Task<Guid> CreateProviderAsync(Provider provider, string ownerEmail) private async Task<Guid> CreateProviderAsync(Provider provider, string ownerEmail)
{ {
@ -77,12 +63,7 @@ public class CreateProviderCommand : ICreateProviderCommand
throw new BadRequestException("Invalid owner. Owner must be an existing Bitwarden user."); throw new BadRequestException("Invalid owner. Owner must be an existing Bitwarden user.");
} }
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling);
if (isConsolidatedBillingEnabled)
{
provider.Gateway = GatewayType.Stripe; provider.Gateway = GatewayType.Stripe;
}
await ProviderRepositoryCreateAsync(provider, ProviderStatusType.Pending); await ProviderRepositoryCreateAsync(provider, ProviderStatusType.Pending);

View File

@ -1,7 +1,5 @@
using Bit.Core; using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Providers.Interfaces; using Bit.Core.AdminConsole.Providers.Interfaces;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
@ -102,11 +100,8 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
Provider provider, Provider provider,
IEnumerable<string> organizationOwnerEmails) IEnumerable<string> organizationOwnerEmails)
{ {
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (provider.IsBillable() &&
organization.IsValidClient() &&
if (isConsolidatedBillingEnabled &&
provider.Status == ProviderStatusType.Billable &&
organization.Status == OrganizationStatusType.Managed &&
!string.IsNullOrEmpty(organization.GatewayCustomerId)) !string.IsNullOrEmpty(organization.GatewayCustomerId))
{ {
await _stripeAdapter.CustomerUpdateAsync(organization.GatewayCustomerId, new CustomerUpdateOptions await _stripeAdapter.CustomerUpdateAsync(organization.GatewayCustomerId, new CustomerUpdateOptions

View File

@ -8,7 +8,6 @@ using Bit.Core.AdminConsole.Models.Business.Tokenables;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Services; using Bit.Core.AdminConsole.Services;
using Bit.Core.Billing.Enums; using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Extensions;
using Bit.Core.Billing.Services; using Bit.Core.Billing.Services;
using Bit.Core.Context; using Bit.Core.Context;
using Bit.Core.Entities; using Bit.Core.Entities;
@ -101,13 +100,6 @@ public class ProviderService : IProviderService
throw new BadRequestException("Invalid owner."); throw new BadRequestException("Invalid owner.");
} }
if (!_featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling))
{
provider.Status = ProviderStatusType.Created;
await _providerRepository.UpsertAsync(provider);
}
else
{
if (taxInfo == null || string.IsNullOrEmpty(taxInfo.BillingAddressCountry) || string.IsNullOrEmpty(taxInfo.BillingAddressPostalCode)) if (taxInfo == null || string.IsNullOrEmpty(taxInfo.BillingAddressCountry) || string.IsNullOrEmpty(taxInfo.BillingAddressPostalCode))
{ {
throw new BadRequestException("Both address and postal code are required to set up your provider."); throw new BadRequestException("Both address and postal code are required to set up your provider.");
@ -118,7 +110,6 @@ public class ProviderService : IProviderService
provider.GatewaySubscriptionId = subscription.Id; provider.GatewaySubscriptionId = subscription.Id;
provider.Status = ProviderStatusType.Billable; provider.Status = ProviderStatusType.Billable;
await _providerRepository.UpsertAsync(provider); await _providerRepository.UpsertAsync(provider);
}
providerUser.Key = key; providerUser.Key = key;
await _providerUserRepository.ReplaceAsync(providerUser); await _providerUserRepository.ReplaceAsync(providerUser);
@ -545,13 +536,9 @@ public class ProviderService : IProviderService
{ {
var provider = await _providerRepository.GetByIdAsync(providerId); var provider = await _providerRepository.GetByIdAsync(providerId);
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling) && provider.IsBillable(); ThrowOnInvalidPlanType(provider.Type, organizationSignup.Plan);
ThrowOnInvalidPlanType(provider.Type, organizationSignup.Plan, consolidatedBillingEnabled); var (organization, _, defaultCollection) = await _organizationService.SignupClientAsync(organizationSignup);
var (organization, _, defaultCollection) = consolidatedBillingEnabled
? await _organizationService.SignupClientAsync(organizationSignup)
: await _organizationService.SignUpAsync(organizationSignup);
var providerOrganization = new ProviderOrganization var providerOrganization = new ProviderOrganization
{ {
@ -687,9 +674,7 @@ public class ProviderService : IProviderService
return confirmedOwnersIds.Except(providerUserIds).Any(); return confirmedOwnersIds.Except(providerUserIds).Any();
} }
private void ThrowOnInvalidPlanType(ProviderType providerType, PlanType requestedType, bool consolidatedBillingEnabled = false) private void ThrowOnInvalidPlanType(ProviderType providerType, PlanType requestedType)
{
if (consolidatedBillingEnabled)
{ {
switch (providerType) switch (providerType)
{ {
@ -708,7 +693,6 @@ public class ProviderService : IProviderService
default: default:
throw new BadRequestException($"Unsupported provider type {providerType}."); throw new BadRequestException($"Unsupported provider type {providerType}.");
} }
}
if (ProviderDisallowedOrganizationTypes.Contains(requestedType)) if (ProviderDisallowedOrganizationTypes.Contains(requestedType))
{ {

View File

@ -1,5 +1,4 @@
using Bit.Commercial.Core.AdminConsole.Providers; using Bit.Commercial.Core.AdminConsole.Providers;
using Bit.Core;
using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Enums.Provider;
@ -155,9 +154,6 @@ public class RemoveOrganizationFromProviderCommandTests
"b@example.com" "b@example.com"
]); ]);
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(false);
sutProvider.GetDependency<IStripeAdapter>().SubscriptionGetAsync(organization.GatewaySubscriptionId) sutProvider.GetDependency<IStripeAdapter>().SubscriptionGetAsync(organization.GatewaySubscriptionId)
.Returns(GetSubscription(organization.GatewaySubscriptionId)); .Returns(GetSubscription(organization.GatewaySubscriptionId));
@ -222,9 +218,6 @@ public class RemoveOrganizationFromProviderCommandTests
"b@example.com" "b@example.com"
]); ]);
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>(); var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.SubscriptionCreateAsync(Arg.Any<SubscriptionCreateOptions>()).Returns(new Subscription stripeAdapter.SubscriptionCreateAsync(Arg.Any<SubscriptionCreateOptions>()).Returns(new Subscription

View File

@ -1,6 +1,5 @@
using Bit.Commercial.Core.AdminConsole.Services; using Bit.Commercial.Core.AdminConsole.Services;
using Bit.Commercial.Core.Test.AdminConsole.AutoFixture; using Bit.Commercial.Core.Test.AdminConsole.AutoFixture;
using Bit.Core;
using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Enums.Provider;
@ -55,8 +54,8 @@ public class ProviderServiceTests
} }
[Theory, BitAutoData] [Theory, BitAutoData]
public async Task CompleteSetupAsync_Success(User user, Provider provider, string key, public async Task CompleteSetupAsync_Success(User user, Provider provider, string key, TaxInfo taxInfo,
[ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)] ProviderUser providerUser, [ProviderUser] ProviderUser providerUser,
SutProvider<ProviderService> sutProvider) SutProvider<ProviderService> sutProvider)
{ {
providerUser.ProviderId = provider.Id; providerUser.ProviderId = provider.Id;
@ -71,37 +70,6 @@ public class ProviderServiceTests
var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector");
sutProvider.GetDependency<IDataProtectionProvider>().CreateProtector("ProviderServiceDataProtector") sutProvider.GetDependency<IDataProtectionProvider>().CreateProtector("ProviderServiceDataProtector")
.Returns(protector); .Returns(protector);
sutProvider.Create();
var token = protector.Protect($"ProviderSetupInvite {provider.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}");
await sutProvider.Sut.CompleteSetupAsync(provider, user.Id, token, key);
await sutProvider.GetDependency<IProviderRepository>().Received().UpsertAsync(provider);
await sutProvider.GetDependency<IProviderUserRepository>().Received()
.ReplaceAsync(Arg.Is<ProviderUser>(pu => pu.UserId == user.Id && pu.ProviderId == provider.Id && pu.Key == key));
}
[Theory, BitAutoData]
public async Task CompleteSetupAsync_ConsolidatedBilling_Success(User user, Provider provider, string key, TaxInfo taxInfo,
[ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)] ProviderUser providerUser,
SutProvider<ProviderService> sutProvider)
{
providerUser.ProviderId = provider.Id;
providerUser.UserId = user.Id;
var userService = sutProvider.GetDependency<IUserService>();
userService.GetUserByIdAsync(user.Id).Returns(user);
var providerUserRepository = sutProvider.GetDependency<IProviderUserRepository>();
providerUserRepository.GetByProviderUserAsync(provider.Id, user.Id).Returns(providerUser);
var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName");
var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector");
sutProvider.GetDependency<IDataProtectionProvider>().CreateProtector("ProviderServiceDataProtector")
.Returns(protector);
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
var providerBillingService = sutProvider.GetDependency<IProviderBillingService>(); var providerBillingService = sutProvider.GetDependency<IProviderBillingService>();
@ -489,7 +457,7 @@ public class ProviderServiceTests
public async Task AddOrganization_OrganizationHasSecretsManager_Throws(Provider provider, Organization organization, string key, public async Task AddOrganization_OrganizationHasSecretsManager_Throws(Provider provider, Organization organization, string key,
SutProvider<ProviderService> sutProvider) SutProvider<ProviderService> sutProvider)
{ {
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseMonthly;
organization.UseSecretsManager = true; organization.UseSecretsManager = true;
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
@ -506,7 +474,7 @@ public class ProviderServiceTests
public async Task AddOrganization_Success(Provider provider, Organization organization, string key, public async Task AddOrganization_Success(Provider provider, Organization organization, string key,
SutProvider<ProviderService> sutProvider) SutProvider<ProviderService> sutProvider)
{ {
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseMonthly;
var providerRepository = sutProvider.GetDependency<IProviderRepository>(); var providerRepository = sutProvider.GetDependency<IProviderRepository>();
providerRepository.GetByIdAsync(provider.Id).Returns(provider); providerRepository.GetByIdAsync(provider.Id).Returns(provider);
@ -549,8 +517,8 @@ public class ProviderServiceTests
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>(); var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
var expectedPlanType = PlanType.EnterpriseAnnually; var expectedPlanType = PlanType.EnterpriseMonthly;
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseMonthly;
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization); sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
await sutProvider.Sut.AddOrganization(provider.Id, organization.Id, key); await sutProvider.Sut.AddOrganization(provider.Id, organization.Id, key);
@ -579,12 +547,12 @@ public class ProviderServiceTests
BackdateProviderCreationDate(provider, newCreationDate); BackdateProviderCreationDate(provider, newCreationDate);
provider.Type = ProviderType.Msp; provider.Type = ProviderType.Msp;
organization.PlanType = PlanType.EnterpriseAnnually; organization.PlanType = PlanType.EnterpriseMonthly;
organization.Plan = "Enterprise (Annually)"; organization.Plan = "Enterprise (Monthly)";
var expectedPlanType = PlanType.EnterpriseAnnually2020; var expectedPlanType = PlanType.EnterpriseMonthly2020;
var expectedPlanId = "2020-enterprise-org-seat-annually"; var expectedPlanId = "2020-enterprise-org-seat-monthly";
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>(); var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
@ -663,11 +631,11 @@ public class ProviderServiceTests
public async Task CreateOrganizationAsync_Success(Provider provider, OrganizationSignup organizationSignup, public async Task CreateOrganizationAsync_Success(Provider provider, OrganizationSignup organizationSignup,
Organization organization, string clientOwnerEmail, User user, SutProvider<ProviderService> sutProvider) Organization organization, string clientOwnerEmail, User user, SutProvider<ProviderService> sutProvider)
{ {
organizationSignup.Plan = PlanType.EnterpriseAnnually; organizationSignup.Plan = PlanType.EnterpriseMonthly;
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>(); var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
sutProvider.GetDependency<IOrganizationService>().SignUpAsync(organizationSignup) sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
.Returns((organization, null as OrganizationUser, new Collection())); .Returns((organization, null as OrganizationUser, new Collection()));
var providerOrganization = var providerOrganization =
@ -688,7 +656,7 @@ public class ProviderServiceTests
} }
[Theory, OrganizationCustomize, BitAutoData] [Theory, OrganizationCustomize, BitAutoData]
public async Task CreateOrganizationAsync_ConsolidatedBillingEnabled_InvalidPlanType_ThrowsBadRequestException( public async Task CreateOrganizationAsync_InvalidPlanType_ThrowsBadRequestException(
Provider provider, Provider provider,
OrganizationSignup organizationSignup, OrganizationSignup organizationSignup,
Organization organization, Organization organization,
@ -696,8 +664,6 @@ public class ProviderServiceTests
User user, User user,
SutProvider<ProviderService> sutProvider) SutProvider<ProviderService> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
provider.Type = ProviderType.Msp; provider.Type = ProviderType.Msp;
provider.Status = ProviderStatusType.Billable; provider.Status = ProviderStatusType.Billable;
@ -717,7 +683,7 @@ public class ProviderServiceTests
} }
[Theory, OrganizationCustomize, BitAutoData] [Theory, OrganizationCustomize, BitAutoData]
public async Task CreateOrganizationAsync_ConsolidatedBillingEnabled_InvokeSignupClientAsync( public async Task CreateOrganizationAsync_InvokeSignupClientAsync(
Provider provider, Provider provider,
OrganizationSignup organizationSignup, OrganizationSignup organizationSignup,
Organization organization, Organization organization,
@ -725,8 +691,6 @@ public class ProviderServiceTests
User user, User user,
SutProvider<ProviderService> sutProvider) SutProvider<ProviderService> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
provider.Type = ProviderType.Msp; provider.Type = ProviderType.Msp;
provider.Status = ProviderStatusType.Billable; provider.Status = ProviderStatusType.Billable;
@ -771,11 +735,11 @@ public class ProviderServiceTests
(Provider provider, OrganizationSignup organizationSignup, Organization organization, string clientOwnerEmail, (Provider provider, OrganizationSignup organizationSignup, Organization organization, string clientOwnerEmail,
User user, SutProvider<ProviderService> sutProvider, Collection defaultCollection) User user, SutProvider<ProviderService> sutProvider, Collection defaultCollection)
{ {
organizationSignup.Plan = PlanType.EnterpriseAnnually; organizationSignup.Plan = PlanType.EnterpriseMonthly;
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>(); var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
sutProvider.GetDependency<IOrganizationService>().SignUpAsync(organizationSignup) sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
.Returns((organization, null as OrganizationUser, defaultCollection)); .Returns((organization, null as OrganizationUser, defaultCollection));
var providerOrganization = var providerOrganization =

View File

@ -55,8 +55,8 @@ public class OrganizationsController : Controller
private readonly IServiceAccountRepository _serviceAccountRepository; private readonly IServiceAccountRepository _serviceAccountRepository;
private readonly IProviderOrganizationRepository _providerOrganizationRepository; private readonly IProviderOrganizationRepository _providerOrganizationRepository;
private readonly IRemoveOrganizationFromProviderCommand _removeOrganizationFromProviderCommand; private readonly IRemoveOrganizationFromProviderCommand _removeOrganizationFromProviderCommand;
private readonly IFeatureService _featureService;
private readonly IProviderBillingService _providerBillingService; private readonly IProviderBillingService _providerBillingService;
private readonly IFeatureService _featureService;
public OrganizationsController( public OrganizationsController(
IOrganizationService organizationService, IOrganizationService organizationService,
@ -82,8 +82,8 @@ public class OrganizationsController : Controller
IServiceAccountRepository serviceAccountRepository, IServiceAccountRepository serviceAccountRepository,
IProviderOrganizationRepository providerOrganizationRepository, IProviderOrganizationRepository providerOrganizationRepository,
IRemoveOrganizationFromProviderCommand removeOrganizationFromProviderCommand, IRemoveOrganizationFromProviderCommand removeOrganizationFromProviderCommand,
IFeatureService featureService, IProviderBillingService providerBillingService,
IProviderBillingService providerBillingService) IFeatureService featureService)
{ {
_organizationService = organizationService; _organizationService = organizationService;
_organizationRepository = organizationRepository; _organizationRepository = organizationRepository;
@ -108,8 +108,8 @@ public class OrganizationsController : Controller
_serviceAccountRepository = serviceAccountRepository; _serviceAccountRepository = serviceAccountRepository;
_providerOrganizationRepository = providerOrganizationRepository; _providerOrganizationRepository = providerOrganizationRepository;
_removeOrganizationFromProviderCommand = removeOrganizationFromProviderCommand; _removeOrganizationFromProviderCommand = removeOrganizationFromProviderCommand;
_featureService = featureService;
_providerBillingService = providerBillingService; _providerBillingService = providerBillingService;
_featureService = featureService;
} }
[RequirePermission(Permission.Org_List_View)] [RequirePermission(Permission.Org_List_View)]
@ -285,9 +285,7 @@ public class OrganizationsController : Controller
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (organization.IsValidClient())
if (consolidatedBillingEnabled && organization.IsValidClient())
{ {
var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id); var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id);
@ -477,12 +475,10 @@ public class OrganizationsController : Controller
Organization organization, Organization organization,
OrganizationEditModel update) OrganizationEditModel update)
{ {
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling);
var scaleMSPOnClientOrganizationUpdate = var scaleMSPOnClientOrganizationUpdate =
_featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate); _featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate);
if (!consolidatedBillingEnabled || !scaleMSPOnClientOrganizationUpdate) if (!scaleMSPOnClientOrganizationUpdate)
{ {
return; return;
} }

View File

@ -282,9 +282,7 @@ public class ProvidersController : Controller
await _providerRepository.ReplaceAsync(provider); await _providerRepository.ReplaceAsync(provider);
await _applicationCacheService.UpsertProviderAbilityAsync(provider); await _applicationCacheService.UpsertProviderAbilityAsync(provider);
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (!provider.IsBillable())
if (!isConsolidatedBillingEnabled || !provider.IsBillable())
{ {
return RedirectToAction("Edit", new { id }); return RedirectToAction("Edit", new { id });
} }
@ -340,10 +338,7 @@ public class ProvidersController : Controller
var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id);
var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id);
var isConsolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (!provider.IsBillable())
if (!isConsolidatedBillingEnabled || !provider.IsBillable())
{ {
return new ProviderEditModel(provider, users, providerOrganizations, new List<ProviderPlan>()); return new ProviderEditModel(provider, users, providerOrganizations, new List<ProviderPlan>());
} }

View File

@ -1,10 +1,5 @@
@using Bit.Core.AdminConsole.Enums.Provider
@using Bit.Core
@model CreateMspProviderModel @model CreateMspProviderModel
@inject Bit.Core.Services.IFeatureService FeatureService
@{ @{
ViewData["Title"] = "Create Managed Service Provider"; ViewData["Title"] = "Create Managed Service Provider";
} }
@ -17,8 +12,6 @@
<label asp-for="OwnerEmail"></label> <label asp-for="OwnerEmail"></label>
<input type="text" class="form-control" asp-for="OwnerEmail"> <input type="text" class="form-control" asp-for="OwnerEmail">
</div> </div>
@if (FeatureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling))
{
<div class="row"> <div class="row">
<div class="col-sm"> <div class="col-sm">
<div class="form-group"> <div class="form-group">
@ -33,7 +26,6 @@
</div> </div>
</div> </div>
</div> </div>
}
<button type="submit" class="btn btn-primary mb-2">Create Provider</button> <button type="submit" class="btn btn-primary mb-2">Create Provider</button>
</form> </form>
</div> </div>

View File

@ -48,7 +48,7 @@
</div> </div>
</div> </div>
</div> </div>
@if (FeatureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling) && Model.Provider.IsBillable()) @if (Model.Provider.IsBillable())
{ {
switch (Model.Provider.Type) switch (Model.Provider.Type)
{ {
@ -68,6 +68,39 @@
</div> </div>
</div> </div>
</div> </div>
break;
}
case ProviderType.MultiOrganizationEnterprise:
{
@if (FeatureService.IsEnabled(FeatureFlagKeys.PM12275_MultiOrganizationEnterprises) && Model.Provider.Type == ProviderType.MultiOrganizationEnterprise)
{
<div class="row">
<div class="col-sm">
<div class="form-group">
@{
var multiOrgPlans = new List<PlanType>
{
PlanType.EnterpriseAnnually,
PlanType.EnterpriseMonthly
};
}
<label asp-for="Plan"></label>
<select class="form-control" asp-for="Plan" asp-items="Html.GetEnumSelectList(multiOrgPlans)">
<option value="">--</option>
</select>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="EnterpriseMinimumSeats"></label>
<input type="number" class="form-control" asp-for="EnterpriseMinimumSeats">
</div>
</div>
</div>
}
break;
}
}
<div class="row"> <div class="row">
<div class="col-sm"> <div class="col-sm">
<div class="form-group"> <div class="form-group">
@ -108,39 +141,6 @@
</div> </div>
</div> </div>
</div> </div>
break;
}
case ProviderType.MultiOrganizationEnterprise:
{
@if (FeatureService.IsEnabled(FeatureFlagKeys.PM12275_MultiOrganizationEnterprises) && Model.Provider.Type == ProviderType.MultiOrganizationEnterprise)
{
<div class="row">
<div class="col-sm">
<div class="form-group">
@{
var multiOrgPlans = new List<PlanType>
{
PlanType.EnterpriseAnnually,
PlanType.EnterpriseMonthly
};
}
<label asp-for="Plan"></label>
<select class="form-control" asp-for="Plan" asp-items="Html.GetEnumSelectList(multiOrgPlans)">
<option value="">--</option>
</select>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="EnterpriseMinimumSeats"></label>
<input type="number" class="form-control" asp-for="EnterpriseMinimumSeats">
</div>
</div>
</div>
}
break;
}
}
} }
</form> </form>
@await Html.PartialAsync("Organizations", Model) @await Html.PartialAsync("Organizations", Model)

View File

@ -289,9 +289,7 @@ public class OrganizationsController : Controller
throw new BadRequestException(string.Empty, "User verification failed."); throw new BadRequestException(string.Empty, "User verification failed.");
} }
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (organization.IsValidClient())
if (consolidatedBillingEnabled && organization.IsValidClient())
{ {
var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id); var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id);
@ -322,8 +320,7 @@ public class OrganizationsController : Controller
throw new BadRequestException("Invalid token."); throw new BadRequestException("Invalid token.");
} }
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (organization.IsValidClient())
if (consolidatedBillingEnabled && organization.IsValidClient())
{ {
var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id); var provider = await _providerRepository.GetByOrganizationIdAsync(organization.Id);
if (provider.IsBillable()) if (provider.IsBillable())

View File

@ -1,5 +1,4 @@
using Bit.Core; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Billing.Extensions; using Bit.Core.Billing.Extensions;
using Bit.Core.Context; using Bit.Core.Context;
@ -9,7 +8,6 @@ namespace Bit.Api.Billing.Controllers;
public abstract class BaseProviderController( public abstract class BaseProviderController(
ICurrentContext currentContext, ICurrentContext currentContext,
IFeatureService featureService,
ILogger<BaseProviderController> logger, ILogger<BaseProviderController> logger,
IProviderRepository providerRepository, IProviderRepository providerRepository,
IUserService userService) : BaseBillingController IUserService userService) : BaseBillingController
@ -26,15 +24,6 @@ public abstract class BaseProviderController(
Guid providerId, Guid providerId,
Func<Guid, bool> checkAuthorization) Func<Guid, bool> checkAuthorization)
{ {
if (!featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling))
{
logger.LogError(
"Cannot run Consolidated Billing operation for provider ({ProviderID}) while feature flag is disabled",
providerId);
return (null, Error.NotFound());
}
var provider = await providerRepository.GetByIdAsync(providerId); var provider = await providerRepository.GetByIdAsync(providerId);
if (provider == null) if (provider == null)

View File

@ -19,14 +19,13 @@ namespace Bit.Api.Billing.Controllers;
[Authorize("Application")] [Authorize("Application")]
public class ProviderBillingController( public class ProviderBillingController(
ICurrentContext currentContext, ICurrentContext currentContext,
IFeatureService featureService,
ILogger<BaseProviderController> logger, ILogger<BaseProviderController> logger,
IProviderBillingService providerBillingService, IProviderBillingService providerBillingService,
IProviderPlanRepository providerPlanRepository, IProviderPlanRepository providerPlanRepository,
IProviderRepository providerRepository, IProviderRepository providerRepository,
ISubscriberService subscriberService, ISubscriberService subscriberService,
IStripeAdapter stripeAdapter, IStripeAdapter stripeAdapter,
IUserService userService) : BaseProviderController(currentContext, featureService, logger, providerRepository, userService) IUserService userService) : BaseProviderController(currentContext, logger, providerRepository, userService)
{ {
[HttpGet("invoices")] [HttpGet("invoices")]
public async Task<IResult> GetInvoicesAsync([FromRoute] Guid providerId) public async Task<IResult> GetInvoicesAsync([FromRoute] Guid providerId)

View File

@ -14,14 +14,13 @@ namespace Bit.Api.Billing.Controllers;
[Route("providers/{providerId:guid}/clients")] [Route("providers/{providerId:guid}/clients")]
public class ProviderClientsController( public class ProviderClientsController(
ICurrentContext currentContext, ICurrentContext currentContext,
IFeatureService featureService,
ILogger<BaseProviderController> logger, ILogger<BaseProviderController> logger,
IOrganizationRepository organizationRepository, IOrganizationRepository organizationRepository,
IProviderBillingService providerBillingService, IProviderBillingService providerBillingService,
IProviderOrganizationRepository providerOrganizationRepository, IProviderOrganizationRepository providerOrganizationRepository,
IProviderRepository providerRepository, IProviderRepository providerRepository,
IProviderService providerService, IProviderService providerService,
IUserService userService) : BaseProviderController(currentContext, featureService, logger, providerRepository, userService) IUserService userService) : BaseProviderController(currentContext, logger, providerRepository, userService)
{ {
[HttpPost] [HttpPost]
public async Task<IResult> CreateAsync( public async Task<IResult> CreateAsync(

View File

@ -15,6 +15,7 @@ using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Repositories; using Bit.Core.Auth.Repositories;
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces; using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
using Bit.Core.Billing.Enums; using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Extensions;
using Bit.Core.Billing.Models.Sales; using Bit.Core.Billing.Models.Sales;
using Bit.Core.Billing.Services; using Bit.Core.Billing.Services;
using Bit.Core.Context; using Bit.Core.Context;
@ -444,13 +445,6 @@ public class OrganizationService : IOrganizationService
public async Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignupClientAsync(OrganizationSignup signup) public async Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignupClientAsync(OrganizationSignup signup)
{ {
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling);
if (!consolidatedBillingEnabled)
{
throw new InvalidOperationException($"{nameof(SignupClientAsync)} is only for use within Consolidated Billing");
}
var plan = StaticStore.GetPlan(signup.Plan); var plan = StaticStore.GetPlan(signup.Plan);
ValidatePlan(plan, signup.AdditionalSeats, "Password Manager"); ValidatePlan(plan, signup.AdditionalSeats, "Password Manager");
@ -1443,10 +1437,7 @@ public class OrganizationService : IOrganizationService
if (provider is { Enabled: true }) if (provider is { Enabled: true })
{ {
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling); if (provider.IsBillable())
if (consolidatedBillingEnabled && provider.Type == ProviderType.Msp &&
provider.Status == ProviderStatusType.Billable)
{ {
return (false, "Seat limit has been reached. Please contact your provider to add more seats."); return (false, "Seat limit has been reached. Please contact your provider to add more seats.");
} }

View File

@ -11,10 +11,11 @@ namespace Bit.Core.Billing.Extensions;
public static class BillingExtensions public static class BillingExtensions
{ {
public static bool IsBillable(this Provider provider) => public static bool IsBillable(this Provider provider) =>
provider.SupportsConsolidatedBilling() && provider.Status == ProviderStatusType.Billable; provider is
{
public static bool SupportsConsolidatedBilling(this Provider provider) Type: ProviderType.Msp or ProviderType.MultiOrganizationEnterprise,
=> provider.Type.SupportsConsolidatedBilling(); Status: ProviderStatusType.Billable
};
public static bool SupportsConsolidatedBilling(this ProviderType providerType) public static bool SupportsConsolidatedBilling(this ProviderType providerType)
=> providerType is ProviderType.Msp or ProviderType.MultiOrganizationEnterprise; => providerType is ProviderType.Msp or ProviderType.MultiOrganizationEnterprise;
@ -24,12 +25,15 @@ public static class BillingExtensions
{ {
Seats: not null, Seats: not null,
Status: OrganizationStatusType.Managed, Status: OrganizationStatusType.Managed,
PlanType: PlanType.TeamsMonthly or PlanType.EnterpriseMonthly PlanType: PlanType.TeamsMonthly or PlanType.EnterpriseMonthly or PlanType.EnterpriseAnnually
}; };
public static bool IsStripeEnabled(this ISubscriber subscriber) public static bool IsStripeEnabled(this ISubscriber subscriber)
=> !string.IsNullOrEmpty(subscriber.GatewayCustomerId) && => subscriber is
!string.IsNullOrEmpty(subscriber.GatewaySubscriptionId); {
GatewayCustomerId: not null and not "",
GatewaySubscriptionId: not null and not ""
};
public static bool IsUnverifiedBankAccount(this SetupIntent setupIntent) => public static bool IsUnverifiedBankAccount(this SetupIntent setupIntent) =>
setupIntent is setupIntent is

View File

@ -107,7 +107,6 @@ public static class FeatureFlagKeys
public const string ItemShare = "item-share"; public const string ItemShare = "item-share";
public const string DuoRedirect = "duo-redirect"; public const string DuoRedirect = "duo-redirect";
public const string AC2101UpdateTrialInitiationEmail = "AC-2101-update-trial-initiation-email"; public const string AC2101UpdateTrialInitiationEmail = "AC-2101-update-trial-initiation-email";
public const string EnableConsolidatedBilling = "enable-consolidated-billing";
public const string AC1795_UpdatedSubscriptionStatusSection = "AC-1795_updated-subscription-status-section"; public const string AC1795_UpdatedSubscriptionStatusSection = "AC-1795_updated-subscription-status-section";
public const string EmailVerification = "email-verification"; public const string EmailVerification = "email-verification";
public const string EmailVerificationDisableTimingDelays = "email-verification-disable-timing-delays"; public const string EmailVerificationDisableTimingDelays = "email-verification-disable-timing-delays";

View File

@ -68,7 +68,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Created }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Created };
@ -104,7 +103,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };
@ -147,7 +145,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };
@ -190,7 +187,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };
@ -233,7 +229,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };
@ -278,7 +273,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };
@ -322,7 +316,6 @@ public class OrganizationsControllerTests
var featureService = sutProvider.GetDependency<IFeatureService>(); var featureService = sutProvider.GetDependency<IFeatureService>();
featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true); featureService.IsEnabled(FeatureFlagKeys.PM14401_ScaleMSPOnClientOrganizationUpdate).Returns(true);
var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable }; var provider = new Provider { Type = ProviderType.Msp, Status = ProviderStatusType.Billable };

View File

@ -218,8 +218,6 @@ public class OrganizationsControllerTests : IDisposable
_userService.VerifySecretAsync(user, requestModel.Secret).Returns(true); _userService.VerifySecretAsync(user, requestModel.Secret).Returns(true);
_featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
_providerRepository.GetByOrganizationIdAsync(organization.Id).Returns(provider); _providerRepository.GetByOrganizationIdAsync(organization.Id).Returns(provider);
await _sut.Delete(organizationId.ToString(), requestModel); await _sut.Delete(organizationId.ToString(), requestModel);

View File

@ -1,7 +1,6 @@
using Bit.Api.Billing.Controllers; using Bit.Api.Billing.Controllers;
using Bit.Api.Billing.Models.Requests; using Bit.Api.Billing.Models.Requests;
using Bit.Api.Billing.Models.Responses; using Bit.Api.Billing.Models.Responses;
using Bit.Core;
using Bit.Core.AdminConsole.Entities.Provider; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
@ -35,27 +34,11 @@ public class ProviderBillingControllerTests
{ {
#region GetInvoicesAsync & TryGetBillableProviderForAdminOperations #region GetInvoicesAsync & TryGetBillableProviderForAdminOperations
[Theory, BitAutoData]
public async Task GetInvoicesAsync_FFDisabled_NotFound(
Guid providerId,
SutProvider<ProviderBillingController> sutProvider)
{
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(false);
var result = await sutProvider.Sut.GetInvoicesAsync(providerId);
AssertNotFound(result);
}
[Theory, BitAutoData] [Theory, BitAutoData]
public async Task GetInvoicesAsync_NullProvider_NotFound( public async Task GetInvoicesAsync_NullProvider_NotFound(
Guid providerId, Guid providerId,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(providerId).ReturnsNull(); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(providerId).ReturnsNull();
var result = await sutProvider.Sut.GetInvoicesAsync(providerId); var result = await sutProvider.Sut.GetInvoicesAsync(providerId);
@ -68,9 +51,6 @@ public class ProviderBillingControllerTests
Provider provider, Provider provider,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
sutProvider.GetDependency<ICurrentContext>().ProviderProviderAdmin(provider.Id) sutProvider.GetDependency<ICurrentContext>().ProviderProviderAdmin(provider.Id)
@ -86,9 +66,6 @@ public class ProviderBillingControllerTests
Provider provider, Provider provider,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
provider.Type = ProviderType.Reseller; provider.Type = ProviderType.Reseller;
provider.Status = ProviderStatusType.Created; provider.Status = ProviderStatusType.Created;
@ -229,27 +206,11 @@ public class ProviderBillingControllerTests
#region GetSubscriptionAsync & TryGetBillableProviderForServiceUserOperation #region GetSubscriptionAsync & TryGetBillableProviderForServiceUserOperation
[Theory, BitAutoData]
public async Task GetSubscriptionAsync_FFDisabled_NotFound(
Guid providerId,
SutProvider<ProviderBillingController> sutProvider)
{
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(false);
var result = await sutProvider.Sut.GetSubscriptionAsync(providerId);
AssertNotFound(result);
}
[Theory, BitAutoData] [Theory, BitAutoData]
public async Task GetSubscriptionAsync_NullProvider_NotFound( public async Task GetSubscriptionAsync_NullProvider_NotFound(
Guid providerId, Guid providerId,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(providerId).ReturnsNull(); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(providerId).ReturnsNull();
var result = await sutProvider.Sut.GetSubscriptionAsync(providerId); var result = await sutProvider.Sut.GetSubscriptionAsync(providerId);
@ -262,9 +223,6 @@ public class ProviderBillingControllerTests
Provider provider, Provider provider,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider); sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
sutProvider.GetDependency<ICurrentContext>().ProviderUser(provider.Id) sutProvider.GetDependency<ICurrentContext>().ProviderUser(provider.Id)
@ -280,9 +238,6 @@ public class ProviderBillingControllerTests
Provider provider, Provider provider,
SutProvider<ProviderBillingController> sutProvider) SutProvider<ProviderBillingController> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
provider.Type = ProviderType.Reseller; provider.Type = ProviderType.Reseller;
provider.Status = ProviderStatusType.Created; provider.Status = ProviderStatusType.Created;

View File

@ -1,11 +1,9 @@
using Bit.Api.Billing.Controllers; using Bit.Api.Billing.Controllers;
using Bit.Core;
using Bit.Core.AdminConsole.Entities.Provider; using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Context; using Bit.Core.Context;
using Bit.Core.Models.Api; using Bit.Core.Models.Api;
using Bit.Core.Services;
using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Http.HttpResults;
@ -59,9 +57,6 @@ public static class Utilities
Provider provider, Provider provider,
SutProvider<T> sutProvider) where T : BaseProviderController SutProvider<T> sutProvider) where T : BaseProviderController
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling)
.Returns(true);
provider.Type = ProviderType.Msp; provider.Type = ProviderType.Msp;
provider.Status = ProviderStatusType.Billable; provider.Status = ProviderStatusType.Billable;

View File

@ -420,8 +420,6 @@ public class OrganizationServiceTests
OrganizationSignup signup, OrganizationSignup signup,
SutProvider<OrganizationService> sutProvider) SutProvider<OrganizationService> sutProvider)
{ {
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling).Returns(true);
signup.Plan = PlanType.TeamsMonthly; signup.Plan = PlanType.TeamsMonthly;
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup); var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);