using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.OrganizationFeatures.Organizations; using Bit.Core.Billing.Enums; using Bit.Core.Billing.Pricing; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Models.Business; using Bit.Core.Models.Data; using Bit.Core.Models.StaticStore; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Tools.Enums; using Bit.Core.Tools.Models.Business; using Bit.Core.Tools.Services; using Bit.Core.Utilities; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Organizations; [SutProviderCustomize] public class ResellerClientOrganizationSignUpCommandTests { [Theory] [BitAutoData(PlanType.TeamsAnnually)] [BitAutoData(PlanType.TeamsMonthly)] [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.EnterpriseMonthly)] public async Task SignupClientAsync_ValidParameters_CreatesOrganizationSuccessfully( PlanType planType, OrganizationSignup signup, string collectionName, SutProvider sutProvider) { signup.Plan = planType; signup.AdditionalSeats = 15; signup.CollectionName = collectionName; var plan = StaticStore.GetPlan(signup.Plan); sutProvider.GetDependency() .GetPlanOrThrow(signup.Plan) .Returns(plan); var result = await sutProvider.Sut.SignupClientAsync(signup); Assert.NotNull(result.organization); Assert.NotNull(result.defaultCollection); Assert.Equal(collectionName, result.defaultCollection.Name); await sutProvider.GetDependency() .Received(1) .CreateAsync( Arg.Is(o => o.Name == signup.Name && o.BillingEmail == signup.BillingEmail && o.PlanType == plan.Type && o.Seats == signup.AdditionalSeats && o.MaxCollections == plan.PasswordManager.MaxCollections && o.UsePasswordManager == true && o.UseSecretsManager == false && o.Status == OrganizationStatusType.Created ) ); await sutProvider.GetDependency() .Received(1) .RaiseEventAsync(Arg.Is(referenceEvent => referenceEvent.Type == ReferenceEventType.Signup && referenceEvent.PlanName == plan.Name && referenceEvent.PlanType == plan.Type && referenceEvent.Seats == result.organization.Seats && referenceEvent.Storage == result.organization.MaxStorageGb && referenceEvent.SignupInitiationPath == signup.InitiationPath )); await sutProvider.GetDependency() .Received(1) .CreateAsync( Arg.Is(c => c.Name == collectionName && c.OrganizationId == result.organization.Id ), Arg.Any>(), Arg.Any>() ); await sutProvider.GetDependency() .Received(1) .CreateAsync( Arg.Is(k => k.OrganizationId == result.organization.Id && k.Type == OrganizationApiKeyType.Default ) ); await sutProvider.GetDependency() .Received(1) .UpsertOrganizationAbilityAsync(Arg.Is(o => o.Id == result.organization.Id)); } [Theory] [BitAutoData] public async Task SignupClientAsync_NullPlan_ThrowsBadRequestException( OrganizationSignup signup, SutProvider sutProvider) { sutProvider.GetDependency() .GetPlanOrThrow(signup.Plan) .Returns((Plan)null); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.SignupClientAsync(signup)); Assert.Contains("Password Manager Plan was null", exception.Message); } [Theory] [BitAutoData] public async Task SignupClientAsync_NegativeAdditionalSeats_ThrowsBadRequestException( OrganizationSignup signup, SutProvider sutProvider) { signup.Plan = PlanType.TeamsMonthly; signup.AdditionalSeats = -5; var plan = StaticStore.GetPlan(signup.Plan); sutProvider.GetDependency() .GetPlanOrThrow(signup.Plan) .Returns(plan); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.SignupClientAsync(signup)); Assert.Contains("You can't subtract Password Manager seats", exception.Message); } [Theory] [BitAutoData(PlanType.TeamsAnnually)] public async Task SignupClientAsync_WhenExceptionIsThrown_CleanupIsPerformed( PlanType planType, OrganizationSignup signup, SutProvider sutProvider) { signup.Plan = planType; var plan = StaticStore.GetPlan(signup.Plan); sutProvider.GetDependency() .GetPlanOrThrow(signup.Plan) .Returns(plan); sutProvider.GetDependency() .When(x => x.CreateAsync(Arg.Any())) .Do(_ => throw new Exception()); var thrownException = await Assert.ThrowsAsync( () => sutProvider.Sut.SignupClientAsync(signup)); await sutProvider.GetDependency() .Received(1) .DeleteAsync(Arg.Is(o => o.Name == signup.Name)); await sutProvider.GetDependency() .Received(1) .DeleteOrganizationAbilityAsync(Arg.Any()); } }