using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains; using Bit.Core.AdminConsole.Services; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationDomains; [SutProviderCustomize] public class VerifyOrganizationDomainCommandTests { [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_ShouldThrowConflict_WhenDomainHasBeenClaimed(Guid id, SutProvider sutProvider) { var expected = new OrganizationDomain { Id = id, OrganizationId = Guid.NewGuid(), DomainName = "Test Domain", Txt = "btw+test18383838383" }; expected.SetVerifiedDate(); sutProvider.GetDependency() .GetByIdAsync(id) .Returns(expected); var requestAction = async () => await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected); var exception = await Assert.ThrowsAsync(requestAction); Assert.Contains("Domain has already been verified.", exception.Message); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_ShouldThrowConflict_WhenDomainHasBeenClaimedByAnotherOrganization(Guid id, SutProvider sutProvider) { var expected = new OrganizationDomain { Id = id, OrganizationId = Guid.NewGuid(), DomainName = "Test Domain", Txt = "btw+test18383838383" }; sutProvider.GetDependency() .GetByIdAsync(id) .Returns(expected); sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(expected.DomainName) .Returns(new List { expected }); var requestAction = async () => await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected); var exception = await Assert.ThrowsAsync(requestAction); Assert.Contains("The domain is not available to be claimed.", exception.Message); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_ShouldVerifyDomainUpdateAndLogEvent_WhenTxtRecordExists(Guid id, SutProvider sutProvider) { var expected = new OrganizationDomain { Id = id, OrganizationId = Guid.NewGuid(), DomainName = "Test Domain", Txt = "btw+test18383838383" }; sutProvider.GetDependency() .GetByIdAsync(id) .Returns(expected); sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(expected.DomainName) .Returns(new List()); sutProvider.GetDependency() .ResolveAsync(expected.DomainName, Arg.Any()) .Returns(true); var result = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected); Assert.NotNull(result.VerifiedDate); await sutProvider.GetDependency().Received(1) .ReplaceAsync(Arg.Any()); await sutProvider.GetDependency().Received(1) .LogOrganizationDomainEventAsync(Arg.Any(), EventType.OrganizationDomain_Verified); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_ShouldNotSetVerifiedDate_WhenTxtRecordDoesNotExist(Guid id, SutProvider sutProvider) { var expected = new OrganizationDomain { Id = id, OrganizationId = Guid.NewGuid(), DomainName = "Test Domain", Txt = "btw+test18383838383" }; sutProvider.GetDependency() .GetByIdAsync(id) .Returns(expected); sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(expected.DomainName) .Returns(new List()); sutProvider.GetDependency() .ResolveAsync(expected.DomainName, Arg.Any()) .Returns(false); var result = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected); Assert.Null(result.VerifiedDate); await sutProvider.GetDependency().Received(1) .LogOrganizationDomainEventAsync(Arg.Any(), EventType.OrganizationDomain_NotVerified); } [Theory, BitAutoData] public async Task SystemVerifyOrganizationDomainAsync_CallsEventServiceWithUpdatedJobRunCount(SutProvider sutProvider) { var domain = new OrganizationDomain() { Id = Guid.NewGuid(), OrganizationId = Guid.NewGuid(), CreationDate = DateTime.UtcNow, DomainName = "test.com", Txt = "btw+12345", }; _ = await sutProvider.Sut.SystemVerifyOrganizationDomainAsync(domain); await sutProvider.GetDependency().ReceivedWithAnyArgs(1) .LogOrganizationDomainEventAsync(default, EventType.OrganizationDomain_NotVerified, EventSystemUser.DomainVerification); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_GivenOrganizationDomainWithAccountDeprovisioningEnabled_WhenDomainIsVerified_ThenSingleOrgPolicyShouldBeEnabled( OrganizationDomain domain, SutProvider sutProvider) { sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(domain.DomainName) .Returns([]); sutProvider.GetDependency() .ResolveAsync(domain.DomainName, domain.Txt) .Returns(true); sutProvider.GetDependency() .IsEnabled(FeatureFlagKeys.AccountDeprovisioning) .Returns(true); _ = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(domain); await sutProvider.GetDependency() .Received(1) .SaveAsync(Arg.Is(x => x.Type == PolicyType.SingleOrg && x.OrganizationId == domain.OrganizationId && x.Enabled), null); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_GivenOrganizationDomainWithAccountDeprovisioningDisabled_WhenDomainIsVerified_ThenSingleOrgPolicyShouldBeNotBeEnabled( OrganizationDomain domain, SutProvider sutProvider) { sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(domain.DomainName) .Returns([]); sutProvider.GetDependency() .ResolveAsync(domain.DomainName, domain.Txt) .Returns(true); sutProvider.GetDependency() .IsEnabled(FeatureFlagKeys.AccountDeprovisioning) .Returns(false); _ = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(domain); await sutProvider.GetDependency() .DidNotReceive() .SaveAsync(Arg.Any(), null); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_GivenOrganizationDomainWithAccountDeprovisioningEnabled_WhenDomainIsNotVerified_ThenSingleOrgPolicyShouldNotBeEnabled( OrganizationDomain domain, SutProvider sutProvider) { sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(domain.DomainName) .Returns([]); sutProvider.GetDependency() .ResolveAsync(domain.DomainName, domain.Txt) .Returns(false); sutProvider.GetDependency() .IsEnabled(FeatureFlagKeys.AccountDeprovisioning) .Returns(true); _ = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(domain); await sutProvider.GetDependency() .DidNotReceive() .SaveAsync(Arg.Any(), null); } [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_GivenOrganizationDomainWithAccountDeprovisioningDisabled_WhenDomainIsNotVerified_ThenSingleOrgPolicyShouldBeNotBeEnabled( OrganizationDomain domain, SutProvider sutProvider) { sutProvider.GetDependency() .GetClaimedDomainsByDomainNameAsync(domain.DomainName) .Returns([]); sutProvider.GetDependency() .ResolveAsync(domain.DomainName, domain.Txt) .Returns(false); sutProvider.GetDependency() .IsEnabled(FeatureFlagKeys.AccountDeprovisioning) .Returns(true); _ = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(domain); await sutProvider.GetDependency() .DidNotReceive() .SaveAsync(Arg.Any(), null); } }