mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[PM-16684] Integrate Pricing Service behind FF (#5276)
* Remove gRPC and convert PricingClient to HttpClient wrapper * Add PlanType.GetProductTier extension Many instances of StaticStore use are just to get the ProductTierType of a PlanType, but this can be derived from the PlanType itself without having to fetch the entire plan. * Remove invocations of the StaticStore in non-Test code * Deprecate StaticStore entry points * Run dotnet format * Matt's feedback * Run dotnet format * Rui's feedback * Run dotnet format * Replacements since approval * Run dotnet format
This commit is contained in:
@ -17,6 +17,7 @@ using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
@ -54,6 +55,7 @@ public class OrganizationsControllerTests : IDisposable
|
||||
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
|
||||
private readonly ICloudOrganizationSignUpCommand _cloudOrganizationSignUpCommand;
|
||||
private readonly IOrganizationDeleteCommand _organizationDeleteCommand;
|
||||
private readonly IPricingClient _pricingClient;
|
||||
private readonly OrganizationsController _sut;
|
||||
|
||||
public OrganizationsControllerTests()
|
||||
@ -78,6 +80,7 @@ public class OrganizationsControllerTests : IDisposable
|
||||
_removeOrganizationUserCommand = Substitute.For<IRemoveOrganizationUserCommand>();
|
||||
_cloudOrganizationSignUpCommand = Substitute.For<ICloudOrganizationSignUpCommand>();
|
||||
_organizationDeleteCommand = Substitute.For<IOrganizationDeleteCommand>();
|
||||
_pricingClient = Substitute.For<IPricingClient>();
|
||||
|
||||
_sut = new OrganizationsController(
|
||||
_organizationRepository,
|
||||
@ -99,7 +102,8 @@ public class OrganizationsControllerTests : IDisposable
|
||||
_orgDeleteTokenDataFactory,
|
||||
_removeOrganizationUserCommand,
|
||||
_cloudOrganizationSignUpCommand,
|
||||
_organizationDeleteCommand);
|
||||
_organizationDeleteCommand,
|
||||
_pricingClient);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -10,6 +10,7 @@ using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Repositories;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Context;
|
||||
@ -49,6 +50,7 @@ public class OrganizationsControllerTests : IDisposable
|
||||
private readonly ISubscriberService _subscriberService;
|
||||
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
|
||||
private readonly IOrganizationInstallationRepository _organizationInstallationRepository;
|
||||
private readonly IPricingClient _pricingClient;
|
||||
|
||||
private readonly OrganizationsController _sut;
|
||||
|
||||
@ -73,6 +75,7 @@ public class OrganizationsControllerTests : IDisposable
|
||||
_subscriberService = Substitute.For<ISubscriberService>();
|
||||
_removeOrganizationUserCommand = Substitute.For<IRemoveOrganizationUserCommand>();
|
||||
_organizationInstallationRepository = Substitute.For<IOrganizationInstallationRepository>();
|
||||
_pricingClient = Substitute.For<IPricingClient>();
|
||||
|
||||
_sut = new OrganizationsController(
|
||||
_organizationRepository,
|
||||
@ -89,7 +92,8 @@ public class OrganizationsControllerTests : IDisposable
|
||||
_addSecretsManagerSubscriptionCommand,
|
||||
_referenceEventService,
|
||||
_subscriberService,
|
||||
_organizationInstallationRepository);
|
||||
_organizationInstallationRepository,
|
||||
_pricingClient);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -8,6 +8,7 @@ using Bit.Core.Billing.Constants;
|
||||
using Bit.Core.Billing.Entities;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Repositories;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Context;
|
||||
@ -331,6 +332,11 @@ public class ProviderBillingControllerTests
|
||||
|
||||
sutProvider.GetDependency<IProviderPlanRepository>().GetByProviderId(provider.Id).Returns(providerPlans);
|
||||
|
||||
foreach (var providerPlan in providerPlans)
|
||||
{
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(providerPlan.PlanType).Returns(StaticStore.GetPlan(providerPlan.PlanType));
|
||||
}
|
||||
|
||||
var result = await sutProvider.Sut.GetSubscriptionAsync(provider.Id);
|
||||
|
||||
Assert.IsType<Ok<ProviderSubscriptionResponse>>(result);
|
||||
|
@ -2,6 +2,7 @@
|
||||
using Bit.Api.SecretsManager.Controllers;
|
||||
using Bit.Api.SecretsManager.Models.Request;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
@ -15,6 +16,7 @@ using Bit.Core.SecretsManager.Models.Data;
|
||||
using Bit.Core.SecretsManager.Queries.ServiceAccounts.Interfaces;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Helpers;
|
||||
@ -119,6 +121,8 @@ public class ServiceAccountsControllerTests
|
||||
{
|
||||
ArrangeCreateServiceAccountAutoScalingTest(newSlotsRequired, sutProvider, data, organization);
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
await sutProvider.Sut.CreateAsync(organization.Id, data);
|
||||
|
||||
await sutProvider.GetDependency<ICreateServiceAccountCommand>().Received(1)
|
||||
|
@ -1,14 +1,16 @@
|
||||
using Bit.Billing.Services;
|
||||
using Bit.Billing.Services.Implementations;
|
||||
using Bit.Billing.Test.Utilities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Models.Data.Provider;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Billing.Entities;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Repositories;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
using Stripe;
|
||||
using Xunit;
|
||||
@ -17,6 +19,12 @@ namespace Bit.Billing.Test.Services;
|
||||
|
||||
public class ProviderEventServiceTests
|
||||
{
|
||||
private readonly IOrganizationRepository _organizationRepository =
|
||||
Substitute.For<IOrganizationRepository>();
|
||||
|
||||
private readonly IPricingClient _pricingClient =
|
||||
Substitute.For<IPricingClient>();
|
||||
|
||||
private readonly IProviderInvoiceItemRepository _providerInvoiceItemRepository =
|
||||
Substitute.For<IProviderInvoiceItemRepository>();
|
||||
|
||||
@ -37,7 +45,8 @@ public class ProviderEventServiceTests
|
||||
public ProviderEventServiceTests()
|
||||
{
|
||||
_providerEventService = new ProviderEventService(
|
||||
Substitute.For<ILogger<ProviderEventService>>(),
|
||||
_organizationRepository,
|
||||
_pricingClient,
|
||||
_providerInvoiceItemRepository,
|
||||
_providerOrganizationRepository,
|
||||
_providerPlanRepository,
|
||||
@ -147,6 +156,12 @@ public class ProviderEventServiceTests
|
||||
|
||||
_providerOrganizationRepository.GetManyDetailsByProviderAsync(providerId).Returns(clients);
|
||||
|
||||
_organizationRepository.GetByIdAsync(client1Id)
|
||||
.Returns(new Organization { PlanType = PlanType.TeamsMonthly });
|
||||
|
||||
_organizationRepository.GetByIdAsync(client2Id)
|
||||
.Returns(new Organization { PlanType = PlanType.EnterpriseMonthly });
|
||||
|
||||
var providerPlans = new List<ProviderPlan>
|
||||
{
|
||||
new ()
|
||||
@ -169,6 +184,11 @@ public class ProviderEventServiceTests
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var providerPlan in providerPlans)
|
||||
{
|
||||
_pricingClient.GetPlanOrThrow(providerPlan.PlanType).Returns(StaticStore.GetPlan(providerPlan.PlanType));
|
||||
}
|
||||
|
||||
_providerPlanRepository.GetByProviderId(providerId).Returns(providerPlans);
|
||||
|
||||
// Act
|
||||
|
@ -2,6 +2,7 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Models.Sales;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@ -38,6 +39,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.IsFromSecretsManagerTrial = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationRepository>().Received(1).CreateAsync(
|
||||
@ -66,7 +69,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
sale.CustomerSetup.TokenizedPaymentSource.Token == signup.PaymentToken &&
|
||||
sale.CustomerSetup.TaxInformation.Country == signup.TaxInfo.BillingAddressCountry &&
|
||||
sale.CustomerSetup.TaxInformation.PostalCode == signup.TaxInfo.BillingAddressPostalCode &&
|
||||
sale.SubscriptionSetup.Plan == plan &&
|
||||
sale.SubscriptionSetup.PlanType == plan.Type &&
|
||||
sale.SubscriptionSetup.PasswordManagerOptions.Seats == signup.AdditionalSeats &&
|
||||
sale.SubscriptionSetup.PasswordManagerOptions.Storage == signup.AdditionalStorageGb &&
|
||||
sale.SubscriptionSetup.SecretsManagerOptions == null));
|
||||
@ -84,6 +87,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.UseSecretsManager = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
// Extract orgUserId when created
|
||||
Guid? orgUserId = null;
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
@ -128,6 +133,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.IsFromSecretsManagerTrial = false;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var result = await sutProvider.Sut.SignUpOrganizationAsync(signup);
|
||||
|
||||
@ -157,7 +163,7 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
sale.CustomerSetup.TokenizedPaymentSource.Token == signup.PaymentToken &&
|
||||
sale.CustomerSetup.TaxInformation.Country == signup.TaxInfo.BillingAddressCountry &&
|
||||
sale.CustomerSetup.TaxInformation.PostalCode == signup.TaxInfo.BillingAddressPostalCode &&
|
||||
sale.SubscriptionSetup.Plan == plan &&
|
||||
sale.SubscriptionSetup.PlanType == plan.Type &&
|
||||
sale.SubscriptionSetup.PasswordManagerOptions.Seats == signup.AdditionalSeats &&
|
||||
sale.SubscriptionSetup.PasswordManagerOptions.Storage == signup.AdditionalStorageGb &&
|
||||
sale.SubscriptionSetup.SecretsManagerOptions.Seats == signup.AdditionalSmSeats &&
|
||||
@ -177,6 +183,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.PremiumAccessAddon = false;
|
||||
signup.IsFromProvider = true;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
Assert.Contains("Organizations with a Managed Service Provider do not support Secrets Manager.", exception.Message);
|
||||
}
|
||||
@ -195,6 +203,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.AdditionalStorageGb = 0;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
Assert.Contains("Plan does not allow additional Machine Accounts.", exception.Message);
|
||||
@ -213,6 +223,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.AdditionalServiceAccounts = 10;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
Assert.Contains("You cannot have more Secrets Manager seats than Password Manager seats", exception.Message);
|
||||
@ -231,6 +243,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
signup.AdditionalServiceAccounts = -10;
|
||||
signup.IsFromProvider = false;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpOrganizationAsync(signup));
|
||||
Assert.Contains("You can't subtract Machine Accounts!", exception.Message);
|
||||
@ -249,6 +263,8 @@ public class CloudICloudOrganizationSignUpCommandTests
|
||||
Owner = new User { Id = Guid.NewGuid() }
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(StaticStore.GetPlan(signup.Plan));
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id)
|
||||
.Returns(1);
|
||||
|
@ -10,6 +10,7 @@ using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@ -203,10 +204,12 @@ public class OrganizationServiceTests
|
||||
{
|
||||
signup.Plan = PlanType.TeamsMonthly;
|
||||
|
||||
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);
|
||||
|
||||
var plan = StaticStore.GetPlan(signup.Plan);
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(plan);
|
||||
|
||||
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationRepository>().Received(1).CreateAsync(Arg.Is<Organization>(org =>
|
||||
org.Id == organization.Id &&
|
||||
org.Name == signup.Name &&
|
||||
@ -894,6 +897,8 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
|
||||
SetupOrgUserRepositoryCreateManyAsyncMock(organizationUserRepository);
|
||||
SetupOrgUserRepositoryCreateAsyncMock(organizationUserRepository);
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
await sutProvider.Sut.InviteUsersAsync(organization.Id, savingUser.Id, systemUser: null, invites);
|
||||
|
||||
await sutProvider.GetDependency<IUpdateSecretsManagerSubscriptionCommand>().Received(1)
|
||||
@ -933,6 +938,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
|
||||
sutProvider.GetDependency<IReferenceEventService>().RaiseEventAsync(default)
|
||||
.ThrowsForAnyArgs<BadRequestException>();
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
await Assert.ThrowsAsync<AggregateException>(async () =>
|
||||
await sutProvider.Sut.InviteUsersAsync(organization.Id, savingUser.Id, systemUser: null, invites));
|
||||
|
||||
@ -1338,6 +1346,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
|
||||
organization.MaxAutoscaleSeats = currentMaxAutoscaleSeats;
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscription(organization.Id,
|
||||
seatAdjustment, maxAutoscaleSeats));
|
||||
|
||||
@ -1360,6 +1371,9 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
|
||||
organization.Seats = 100;
|
||||
organization.SmSeats = 100;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
|
||||
var actual = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscription(organization.Id, seatAdjustment, null));
|
||||
|
@ -1,8 +1,10 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Billing.Constants;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Billing.Services.Implementations;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
@ -15,43 +17,6 @@ namespace Bit.Core.Test.Billing.Services;
|
||||
public class OrganizationBillingServiceTests
|
||||
{
|
||||
#region GetMetadata
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetMetadata_OrganizationNull_ReturnsNull(
|
||||
Guid organizationId,
|
||||
SutProvider<OrganizationBillingService> sutProvider)
|
||||
{
|
||||
var metadata = await sutProvider.Sut.GetMetadata(organizationId);
|
||||
|
||||
Assert.Null(metadata);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetMetadata_CustomerNull_ReturnsNull(
|
||||
Guid organizationId,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationBillingService> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns(organization);
|
||||
|
||||
var metadata = await sutProvider.Sut.GetMetadata(organizationId);
|
||||
|
||||
Assert.False(metadata.IsOnSecretsManagerStandalone);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetMetadata_SubscriptionNull_ReturnsNull(
|
||||
Guid organizationId,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationBillingService> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<ISubscriberService>().GetCustomer(organization).Returns(new Customer());
|
||||
|
||||
var metadata = await sutProvider.Sut.GetMetadata(organizationId);
|
||||
|
||||
Assert.False(metadata.IsOnSecretsManagerStandalone);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetMetadata_Succeeds(
|
||||
@ -61,6 +26,11 @@ public class OrganizationBillingServiceTests
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().ListPlans().Returns(StaticStore.Plans.ToList());
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
var subscriberService = sutProvider.GetDependency<ISubscriberService>();
|
||||
|
||||
subscriberService
|
||||
@ -99,7 +69,8 @@ public class OrganizationBillingServiceTests
|
||||
|
||||
var metadata = await sutProvider.Sut.GetMetadata(organizationId);
|
||||
|
||||
Assert.True(metadata.IsOnSecretsManagerStandalone);
|
||||
Assert.True(metadata!.IsOnSecretsManagerStandalone);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedPasswordManagerSeats = 20
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsStarterPlan, updatedSubscriptionData);
|
||||
|
||||
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
|
||||
|
||||
@ -114,7 +114,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedAdditionalStorage = 10
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsMonthlyPlan, updatedSubscriptionData);
|
||||
|
||||
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
|
||||
|
||||
@ -221,7 +221,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedAdditionalStorage = 10
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsMonthlyPlan, updatedSubscriptionData);
|
||||
|
||||
var upgradeItemOptions = subscriptionUpdate.UpgradeItemsOptions(subscription);
|
||||
|
||||
@ -302,7 +302,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedPasswordManagerSeats = 20
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsStarterPlan, updatedSubscriptionData);
|
||||
|
||||
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
|
||||
|
||||
@ -372,7 +372,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedAdditionalStorage = 10
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsMonthlyPlan, updatedSubscriptionData);
|
||||
|
||||
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
|
||||
|
||||
@ -478,7 +478,7 @@ public class CompleteSubscriptionUpdateTests
|
||||
PurchasedAdditionalStorage = 10
|
||||
};
|
||||
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, updatedSubscriptionData);
|
||||
var subscriptionUpdate = new CompleteSubscriptionUpdate(organization, teamsMonthlyPlan, updatedSubscriptionData);
|
||||
|
||||
var revertItemOptions = subscriptionUpdate.RevertItemsOptions(subscription);
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.StaticStore;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Xunit;
|
||||
|
||||
@ -11,19 +13,40 @@ namespace Bit.Core.Test.Models.Business;
|
||||
[SecretsManagerOrganizationCustomize]
|
||||
public class SecretsManagerSubscriptionUpdateTests
|
||||
{
|
||||
private static TheoryData<Plan> ToPlanTheory(List<PlanType> types)
|
||||
{
|
||||
var theoryData = new TheoryData<Plan>();
|
||||
var plans = types.Select(StaticStore.GetPlan).ToArray();
|
||||
theoryData.AddRange(plans);
|
||||
return theoryData;
|
||||
}
|
||||
|
||||
public static TheoryData<Plan> NonSmPlans =>
|
||||
ToPlanTheory([PlanType.Custom, PlanType.FamiliesAnnually, PlanType.FamiliesAnnually2019]);
|
||||
|
||||
public static TheoryData<Plan> SmPlans => ToPlanTheory([
|
||||
PlanType.EnterpriseAnnually2019,
|
||||
PlanType.EnterpriseAnnually,
|
||||
PlanType.TeamsMonthly2019,
|
||||
PlanType.TeamsAnnually2020,
|
||||
PlanType.TeamsMonthly,
|
||||
PlanType.TeamsAnnually2019,
|
||||
PlanType.TeamsAnnually2020,
|
||||
PlanType.TeamsAnnually,
|
||||
PlanType.TeamsStarter
|
||||
]);
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.Custom)]
|
||||
[BitAutoData(PlanType.FamiliesAnnually)]
|
||||
[BitAutoData(PlanType.FamiliesAnnually2019)]
|
||||
[BitMemberAutoData(nameof(NonSmPlans))]
|
||||
public Task UpdateSubscriptionAsync_WithNonSecretsManagerPlanType_ThrowsBadRequestException(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
|
||||
// Act
|
||||
var exception = Assert.Throws<NotFoundException>(() => new SecretsManagerSubscriptionUpdate(organization, false));
|
||||
var exception = Assert.Throws<NotFoundException>(() => new SecretsManagerSubscriptionUpdate(organization, plan, false));
|
||||
|
||||
// Assert
|
||||
Assert.Contains("Invalid Secrets Manager plan", exception.Message, StringComparison.InvariantCultureIgnoreCase);
|
||||
@ -31,28 +54,16 @@ public class SecretsManagerSubscriptionUpdateTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(SmPlans))]
|
||||
public void UpdateSubscription_WithNonSecretsManagerPlanType_DoesNotThrowException(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
|
||||
// Act
|
||||
var ex = Record.Exception(() => new SecretsManagerSubscriptionUpdate(organization, false));
|
||||
var ex = Record.Exception(() => new SecretsManagerSubscriptionUpdate(organization, plan, false));
|
||||
|
||||
// Assert
|
||||
Assert.Null(ex);
|
||||
|
@ -3,6 +3,7 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.StaticStore;
|
||||
@ -41,7 +42,8 @@ public class AddSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
|
||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(plan);
|
||||
|
||||
await sutProvider.Sut.SignUpAsync(organization, additionalSmSeats, additionalServiceAccounts);
|
||||
|
||||
@ -85,6 +87,8 @@ public class AddSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.GatewayCustomerId = null;
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.SignUpAsync(organization, additionalSmSeats, additionalServiceAccounts));
|
||||
Assert.Contains("No payment method found.", exception.Message);
|
||||
@ -101,6 +105,8 @@ public class AddSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.GatewaySubscriptionId = null;
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.SignUpAsync(organization, additionalSmSeats, additionalServiceAccounts));
|
||||
Assert.Contains("No subscription found.", exception.Message);
|
||||
@ -132,6 +138,8 @@ public class AddSecretsManagerSubscriptionCommandTests
|
||||
organization.UseSecretsManager = false;
|
||||
provider.Type = ProviderType.Msp;
|
||||
sutProvider.GetDependency<IProviderRepository>().GetByOrganizationIdAsync(organization.Id).Returns(provider);
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType)
|
||||
.Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpAsync(organization, 10, 10));
|
||||
|
@ -21,26 +21,48 @@ namespace Bit.Core.Test.OrganizationFeatures.OrganizationSubscriptionUpdate;
|
||||
[SecretsManagerOrganizationCustomize]
|
||||
public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
private static TheoryData<Plan> ToPlanTheory(List<PlanType> types)
|
||||
{
|
||||
var theoryData = new TheoryData<Plan>();
|
||||
var plans = types.Select(StaticStore.GetPlan).ToArray();
|
||||
theoryData.AddRange(plans);
|
||||
return theoryData;
|
||||
}
|
||||
|
||||
public static TheoryData<Plan> AllTeamsAndEnterprise
|
||||
=> ToPlanTheory([
|
||||
PlanType.EnterpriseAnnually2019,
|
||||
PlanType.EnterpriseAnnually2020,
|
||||
PlanType.EnterpriseAnnually,
|
||||
PlanType.EnterpriseMonthly2019,
|
||||
PlanType.EnterpriseMonthly2020,
|
||||
PlanType.EnterpriseMonthly,
|
||||
PlanType.TeamsMonthly2019,
|
||||
PlanType.TeamsMonthly2020,
|
||||
PlanType.TeamsMonthly,
|
||||
PlanType.TeamsAnnually2019,
|
||||
PlanType.TeamsAnnually2020,
|
||||
PlanType.TeamsAnnually,
|
||||
PlanType.TeamsStarter
|
||||
]);
|
||||
|
||||
public static TheoryData<Plan> CurrentTeamsAndEnterprise
|
||||
=> ToPlanTheory([
|
||||
PlanType.EnterpriseAnnually,
|
||||
PlanType.EnterpriseMonthly,
|
||||
PlanType.TeamsMonthly,
|
||||
PlanType.TeamsAnnually,
|
||||
PlanType.TeamsStarter
|
||||
]);
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
|
||||
public async Task UpdateSubscriptionAsync_UpdateEverything_ValidInput_Passes(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
organization.Seats = 400;
|
||||
organization.SmSeats = 10;
|
||||
organization.MaxAutoscaleSmSeats = 20;
|
||||
@ -52,7 +74,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
var updateMaxAutoscaleSmSeats = 16;
|
||||
var updateMaxAutoscaleSmServiceAccounts = 301;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = updateSmSeats,
|
||||
SmServiceAccounts = updateSmServiceAccounts,
|
||||
@ -62,7 +84,6 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
|
||||
await sutProvider.Sut.UpdateSubscriptionAsync(update);
|
||||
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
await sutProvider.GetDependency<IPaymentService>().Received(1)
|
||||
.AdjustSmSeatsAsync(organization, plan, update.SmSeatsExcludingBase);
|
||||
await sutProvider.GetDependency<IPaymentService>().Received(1)
|
||||
@ -83,17 +104,13 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(CurrentTeamsAndEnterprise))]
|
||||
public async Task UpdateSubscriptionAsync_ValidInput_WithNullMaxAutoscale_Passes(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
organization.Seats = 20;
|
||||
|
||||
const int updateSmSeats = 15;
|
||||
@ -102,7 +119,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
// Ensure that SmSeats is different from the original organization.SmSeats
|
||||
organization.SmSeats = updateSmSeats + 5;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = updateSmSeats,
|
||||
MaxAutoscaleSmSeats = null,
|
||||
@ -112,7 +129,6 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
|
||||
await sutProvider.Sut.UpdateSubscriptionAsync(update);
|
||||
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
await sutProvider.GetDependency<IPaymentService>().Received(1)
|
||||
.AdjustSmSeatsAsync(organization, plan, update.SmSeatsExcludingBase);
|
||||
await sutProvider.GetDependency<IPaymentService>().Received(1)
|
||||
@ -141,7 +157,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, autoscaling).AdjustSeats(2);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, autoscaling).AdjustSeats(2);
|
||||
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted.Returns(true);
|
||||
|
||||
@ -156,8 +173,10 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider,
|
||||
Organization organization)
|
||||
{
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
|
||||
organization.UseSecretsManager = false;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
@ -167,27 +186,16 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
|
||||
public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewayCustomerId_ThrowsException(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
organization.GatewayCustomerId = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("No payment method found.", exception.Message);
|
||||
@ -195,27 +203,15 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
|
||||
public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewaySubscriptionId_ThrowsException(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
organization.GatewaySubscriptionId = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("No subscription found.", exception.Message);
|
||||
@ -223,24 +219,12 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
public async Task AdjustServiceAccountsAsync_WithEnterpriseOrTeamsPlans_Success(PlanType planType, Guid organizationId,
|
||||
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
|
||||
public async Task AdjustServiceAccountsAsync_WithEnterpriseOrTeamsPlans_Success(
|
||||
Plan plan,
|
||||
Guid organizationId,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var plan = StaticStore.GetPlan(planType);
|
||||
|
||||
var organizationSeats = plan.SecretsManager.BaseSeats + 10;
|
||||
var organizationMaxAutoscaleSeats = 20;
|
||||
var organizationServiceAccounts = plan.SecretsManager.BaseServiceAccount + 10;
|
||||
@ -249,7 +233,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
var organization = new Organization
|
||||
{
|
||||
Id = organizationId,
|
||||
PlanType = planType,
|
||||
PlanType = plan.Type,
|
||||
GatewayCustomerId = "1",
|
||||
GatewaySubscriptionId = "2",
|
||||
UseSecretsManager = true,
|
||||
@ -263,7 +247,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
var expectedSmServiceAccounts = organizationServiceAccounts + smServiceAccountsAdjustment;
|
||||
var expectedSmServiceAccountsExcludingBase = expectedSmServiceAccounts - plan.SecretsManager.BaseServiceAccount;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(10);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustServiceAccounts(10);
|
||||
|
||||
await sutProvider.Sut.UpdateSubscriptionAsync(update);
|
||||
|
||||
@ -290,8 +274,9 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
|
||||
// Make sure Password Manager seats is greater or equal to Secrets Manager seats
|
||||
organization.Seats = seatCount;
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = seatCount,
|
||||
MaxAutoscaleSmSeats = seatCount
|
||||
@ -310,7 +295,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmSeats = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
@ -325,7 +311,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustSeats(-2);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, true).AdjustSeats(-2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Cannot use autoscaling to subtract seats.", exception.Message);
|
||||
@ -340,7 +327,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("You have reached the maximum number of Secrets Manager seats (2) for this plan",
|
||||
@ -357,7 +345,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmSeats = 9;
|
||||
organization.MaxAutoscaleSmSeats = 10;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustSeats(2);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, true).AdjustSeats(2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Secrets Manager seat limit has been reached.", exception.Message);
|
||||
@ -370,7 +359,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = organization.SmSeats + 10,
|
||||
MaxAutoscaleSmSeats = organization.SmSeats + 5
|
||||
@ -388,7 +378,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = 0,
|
||||
};
|
||||
@ -407,7 +398,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmSeats = 8;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = 7,
|
||||
};
|
||||
@ -425,7 +417,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmServiceAccounts = 300,
|
||||
MaxAutoscaleSmServiceAccounts = 300
|
||||
@ -444,7 +437,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmServiceAccounts = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(1);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustServiceAccounts(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Organization has no machine accounts limit, no need to adjust machine accounts", exception.Message);
|
||||
@ -457,7 +451,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustServiceAccounts(-2);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, true).AdjustServiceAccounts(-2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Cannot use autoscaling to subtract machine accounts.", exception.Message);
|
||||
@ -472,7 +467,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(1);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false).AdjustServiceAccounts(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("You have reached the maximum number of machine accounts (3) for this plan",
|
||||
@ -489,7 +485,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmServiceAccounts = 9;
|
||||
organization.MaxAutoscaleSmServiceAccounts = 10;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustServiceAccounts(2);
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, true).AdjustServiceAccounts(2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Secrets Manager machine account limit has been reached.", exception.Message);
|
||||
@ -508,7 +505,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmServiceAccounts = smServiceAccount - 5;
|
||||
organization.MaxAutoscaleSmServiceAccounts = 2 * smServiceAccount;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmServiceAccounts = smServiceAccount,
|
||||
MaxAutoscaleSmServiceAccounts = maxAutoscaleSmServiceAccounts
|
||||
@ -530,7 +528,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
|
||||
organization.SmServiceAccounts = newSmServiceAccounts - 10;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmServiceAccounts = newSmServiceAccounts,
|
||||
};
|
||||
@ -542,28 +541,16 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2019)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually2020)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2019)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2020)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2019)]
|
||||
[BitAutoData(PlanType.TeamsMonthly2020)]
|
||||
[BitAutoData(PlanType.TeamsMonthly)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2019)]
|
||||
[BitAutoData(PlanType.TeamsAnnually2020)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.TeamsStarter)]
|
||||
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
|
||||
public async Task UpdateSmServiceAccounts_WhenCurrentServiceAccountsIsGreaterThanNew_ThrowsBadRequestException(
|
||||
PlanType planType,
|
||||
Plan plan,
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var currentServiceAccounts = 301;
|
||||
organization.PlanType = planType;
|
||||
organization.PlanType = plan.Type;
|
||||
organization.SmServiceAccounts = currentServiceAccounts;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false) { SmServiceAccounts = 201 };
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false) { SmServiceAccounts = 201 };
|
||||
|
||||
sutProvider.GetDependency<IServiceAccountRepository>()
|
||||
.GetServiceAccountCountByOrganizationIdAsync(organization.Id)
|
||||
@ -586,7 +573,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmSeats = smSeats - 1;
|
||||
organization.MaxAutoscaleSmSeats = smSeats * 2;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
SmSeats = smSeats,
|
||||
MaxAutoscaleSmSeats = maxAutoscaleSmSeats
|
||||
@ -606,7 +594,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.SmSeats = 2;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
MaxAutoscaleSmSeats = 3
|
||||
};
|
||||
@ -625,7 +614,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.SmSeats = 2;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false)
|
||||
{
|
||||
MaxAutoscaleSmSeats = 2
|
||||
};
|
||||
@ -645,7 +635,8 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.PlanType = planType;
|
||||
organization.SmServiceAccounts = 3;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false) { MaxAutoscaleSmServiceAccounts = 3 };
|
||||
var plan = StaticStore.GetPlan(organization.PlanType);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, plan, false) { MaxAutoscaleSmServiceAccounts = 3 };
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Your plan does not allow machine accounts autoscaling.", exception.Message);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions;
|
||||
@ -43,6 +44,7 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
|
||||
{
|
||||
upgrade.Plan = organization.PlanType;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpgradePlanAsync(organization.Id, upgrade));
|
||||
@ -58,6 +60,7 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
upgrade.AdditionalSmSeats = 10;
|
||||
upgrade.AdditionalServiceAccounts = 10;
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpgradePlanAsync(organization.Id, upgrade));
|
||||
Assert.Contains("already on this plan", exception.Message);
|
||||
@ -69,9 +72,11 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
upgrade.AdditionalSmSeats = 10;
|
||||
upgrade.AdditionalSeats = 10;
|
||||
upgrade.Plan = PlanType.TeamsAnnually;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(upgrade.Plan).Returns(StaticStore.GetPlan(upgrade.Plan));
|
||||
await sutProvider.Sut.UpgradePlanAsync(organization.Id, upgrade);
|
||||
await sutProvider.GetDependency<IOrganizationService>().Received(1).ReplaceAndUpdateCacheAsync(organization);
|
||||
}
|
||||
@ -92,6 +97,8 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
|
||||
organization.PlanType = PlanType.FamiliesAnnually;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
organizationUpgrade.AdditionalSeats = 30;
|
||||
organizationUpgrade.UseSecretsManager = true;
|
||||
organizationUpgrade.AdditionalSmSeats = 20;
|
||||
@ -99,6 +106,8 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
organizationUpgrade.AdditionalStorageGb = 3;
|
||||
organizationUpgrade.Plan = planType;
|
||||
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organizationUpgrade.Plan).Returns(StaticStore.GetPlan(organizationUpgrade.Plan));
|
||||
|
||||
await sutProvider.Sut.UpgradePlanAsync(organization.Id, organizationUpgrade);
|
||||
await sutProvider.GetDependency<IPaymentService>().Received(1).AdjustSubscription(
|
||||
organization,
|
||||
@ -120,7 +129,10 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
public async Task UpgradePlan_SM_Passes(PlanType planType, Organization organization, OrganizationUpgrade upgrade,
|
||||
SutProvider<UpgradeOrganizationPlanCommand> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
upgrade.Plan = planType;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(upgrade.Plan).Returns(StaticStore.GetPlan(upgrade.Plan));
|
||||
|
||||
var plan = StaticStore.GetPlan(upgrade.Plan);
|
||||
|
||||
@ -155,8 +167,10 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
upgrade.AdditionalSeats = 15;
|
||||
upgrade.AdditionalSmSeats = 1;
|
||||
upgrade.AdditionalServiceAccounts = 0;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(upgrade.Plan).Returns(StaticStore.GetPlan(upgrade.Plan));
|
||||
|
||||
organization.SmSeats = 2;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
@ -181,9 +195,11 @@ public class UpgradeOrganizationPlanCommandTests
|
||||
upgrade.AdditionalSeats = 15;
|
||||
upgrade.AdditionalSmSeats = 1;
|
||||
upgrade.AdditionalServiceAccounts = 0;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(upgrade.Plan).Returns(StaticStore.GetPlan(upgrade.Plan));
|
||||
|
||||
organization.SmSeats = 1;
|
||||
organization.SmServiceAccounts = currentServiceAccounts;
|
||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(organization.PlanType).Returns(StaticStore.GetPlan(organization.PlanType));
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
|
Reference in New Issue
Block a user