mirror of
https://github.com/bitwarden/server.git
synced 2024-12-01 13:43:23 +01:00
[PM-13470] Allow creating clients for Multi-organization enterprise (#4977)
This commit is contained in:
parent
319b13d87e
commit
c5ae849b97
@ -392,7 +392,9 @@ public class ProviderService : IProviderService
|
||||
|
||||
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||
|
||||
ThrowOnInvalidPlanType(organization.PlanType);
|
||||
var provider = await _providerRepository.GetByIdAsync(providerId);
|
||||
|
||||
ThrowOnInvalidPlanType(provider.Type, organization.PlanType);
|
||||
|
||||
if (organization.UseSecretsManager)
|
||||
{
|
||||
@ -407,8 +409,6 @@ public class ProviderService : IProviderService
|
||||
Key = key,
|
||||
};
|
||||
|
||||
var provider = await _providerRepository.GetByIdAsync(providerId);
|
||||
|
||||
await ApplyProviderPriceRateAsync(organization, provider);
|
||||
await _providerOrganizationRepository.CreateAsync(providerOrganization);
|
||||
|
||||
@ -547,7 +547,7 @@ public class ProviderService : IProviderService
|
||||
|
||||
var consolidatedBillingEnabled = _featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling) && provider.IsBillable();
|
||||
|
||||
ThrowOnInvalidPlanType(organizationSignup.Plan, consolidatedBillingEnabled);
|
||||
ThrowOnInvalidPlanType(provider.Type, organizationSignup.Plan, consolidatedBillingEnabled);
|
||||
|
||||
var (organization, _, defaultCollection) = consolidatedBillingEnabled
|
||||
? await _organizationService.SignupClientAsync(organizationSignup)
|
||||
@ -687,11 +687,27 @@ public class ProviderService : IProviderService
|
||||
return confirmedOwnersIds.Except(providerUserIds).Any();
|
||||
}
|
||||
|
||||
private void ThrowOnInvalidPlanType(PlanType requestedType, bool consolidatedBillingEnabled = false)
|
||||
private void ThrowOnInvalidPlanType(ProviderType providerType, PlanType requestedType, bool consolidatedBillingEnabled = false)
|
||||
{
|
||||
if (consolidatedBillingEnabled && requestedType is not (PlanType.TeamsMonthly or PlanType.EnterpriseMonthly))
|
||||
if (consolidatedBillingEnabled)
|
||||
{
|
||||
throw new BadRequestException($"Providers cannot manage organizations with the plan type {requestedType}. Only Teams (Monthly) and Enterprise (Monthly) are allowed.");
|
||||
switch (providerType)
|
||||
{
|
||||
case ProviderType.Msp:
|
||||
if (requestedType is not (PlanType.TeamsMonthly or PlanType.EnterpriseMonthly))
|
||||
{
|
||||
throw new BadRequestException($"Managed Service Providers cannot manage organizations with the plan type {requestedType}. Only Teams (Monthly) and Enterprise (Monthly) are allowed.");
|
||||
}
|
||||
break;
|
||||
case ProviderType.MultiOrganizationEnterprise:
|
||||
if (requestedType is not (PlanType.EnterpriseMonthly or PlanType.EnterpriseAnnually))
|
||||
{
|
||||
throw new BadRequestException($"Multi-organization Enterprise Providers cannot manage organizations with the plan type {requestedType}. Only Enterprise (Monthly) and Enterprise (Annually) are allowed.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException($"Unsupported provider type {providerType}.");
|
||||
}
|
||||
}
|
||||
|
||||
if (ProviderDisallowedOrganizationTypes.Contains(requestedType))
|
||||
|
@ -209,16 +209,9 @@ public class ProviderBillingService(
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(provider);
|
||||
|
||||
if (provider.Type != ProviderType.Msp)
|
||||
if (!provider.SupportsConsolidatedBilling())
|
||||
{
|
||||
logger.LogError("Non-MSP provider ({ProviderID}) cannot scale their seats", provider.Id);
|
||||
|
||||
throw new BillingException();
|
||||
}
|
||||
|
||||
if (!planType.SupportsConsolidatedBilling())
|
||||
{
|
||||
logger.LogError("Cannot scale provider ({ProviderID}) seats for plan type {PlanType} as it does not support consolidated billing", provider.Id, planType.ToString());
|
||||
logger.LogError("Provider ({ProviderID}) cannot scale their seats", provider.Id);
|
||||
|
||||
throw new BillingException();
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ public class CreateClientOrganizationRequestBody
|
||||
[Required(ErrorMessage = "'ownerEmail' must be provided")]
|
||||
public string OwnerEmail { get; set; }
|
||||
|
||||
[EnumMatches<PlanType>(PlanType.TeamsMonthly, PlanType.EnterpriseMonthly, ErrorMessage = "'planType' must be Teams (Monthly) or Enterprise (Monthly)")]
|
||||
[EnumMatches<PlanType>(PlanType.TeamsMonthly, PlanType.EnterpriseMonthly, PlanType.EnterpriseAnnually, ErrorMessage = "'planType' must be Teams (Monthly), Enterprise (Monthly) or Enterprise (Annually)")]
|
||||
public PlanType PlanType { get; set; }
|
||||
|
||||
[Range(1, int.MaxValue, ErrorMessage = "'seats' must be greater than 0")]
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Billing.Entities;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Utilities;
|
||||
using Stripe;
|
||||
@ -35,6 +36,8 @@ public record ProviderSubscriptionResponse(
|
||||
var cadence = plan.IsAnnual ? _annualCadence : _monthlyCadence;
|
||||
return new ProviderPlanResponse(
|
||||
plan.Name,
|
||||
plan.Type,
|
||||
plan.ProductTier,
|
||||
configuredProviderPlan.SeatMinimum,
|
||||
configuredProviderPlan.PurchasedSeats,
|
||||
configuredProviderPlan.AssignedSeats,
|
||||
@ -59,6 +62,8 @@ public record ProviderSubscriptionResponse(
|
||||
|
||||
public record ProviderPlanResponse(
|
||||
string PlanName,
|
||||
PlanType Type,
|
||||
ProductTierType ProductTier,
|
||||
int SeatMinimum,
|
||||
int PurchasedSeats,
|
||||
int AssignedSeats,
|
||||
|
@ -43,5 +43,5 @@ public static class BillingExtensions
|
||||
};
|
||||
|
||||
public static bool SupportsConsolidatedBilling(this PlanType planType)
|
||||
=> planType is PlanType.TeamsMonthly or PlanType.EnterpriseMonthly;
|
||||
=> planType is PlanType.TeamsMonthly or PlanType.EnterpriseMonthly or PlanType.EnterpriseAnnually;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user