using Bit.Api.AdminConsole.Controllers; using Bit.Api.AdminConsole.Models.Request; using Bit.Api.AdminConsole.Models.Request.Organizations; using Bit.Api.AdminConsole.Models.Response.Organizations; using Bit.Api.Models.Response; using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Models.Data.Organizations; using Bit.Core.Repositories; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using NSubstitute.ReturnsExtensions; using Xunit; namespace Bit.Api.Test.AdminConsole.Controllers; [ControllerCustomize(typeof(OrganizationDomainController))] [SutProviderCustomize] public class OrganizationDomainControllerTests { [Theory, BitAutoData] public async Task Get_ShouldThrowUnauthorized_WhenOrgIdCannotManageSso(Guid orgId, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(false); var requestAction = async () => await sutProvider.Sut.Get(orgId); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Get_ShouldNotFound_WhenOrganizationDoesNotExist(Guid orgId, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Get(orgId); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Get_ShouldReturnOrganizationDomainList_WhenOrgIdIsValid(Guid orgId, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainsByOrganizationIdAsync(orgId).Returns(new List { new() { Id = Guid.NewGuid(), OrganizationId = orgId, CreationDate = DateTime.UtcNow.AddDays(-7), DomainName = "test.com", Txt = "btw+12342" } }); var result = await sutProvider.Sut.Get(orgId); Assert.IsType>(result); Assert.Equal(orgId, result.Data.Select(x => x.OrganizationId).FirstOrDefault()); } [Theory, BitAutoData] public async Task GetByOrgIdAndId_ShouldThrowUnauthorized_WhenOrgIdCannotManageSso(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(false); var requestAction = async () => await sutProvider.Sut.Get(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task GetByOrgIdAndId_ShouldThrowNotFound_WhenOrganizationDoesNotExist(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Get(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task GetByOrgIdAndId_ShouldThrowNotFound_WhenOrganizationDomainEntryNotExist(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).Returns(new Organization()); sutProvider.GetDependency().GetOrganizationDomainByIdOrganizationIdAsync(id, orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Get(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task GetByOrgIdAndId_ShouldThrowNotFound_WhenOrgIdDoesNotMatch(OrganizationDomain organizationDomain, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(organizationDomain.OrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(organizationDomain.OrganizationId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId) .ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Get(organizationDomain.OrganizationId, organizationDomain.Id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Get_ShouldReturnOrganizationDomain_WhenOrgIdAndIdAreValid(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).Returns(new Organization()); sutProvider.GetDependency().GetOrganizationDomainByIdOrganizationIdAsync(id, orgId) .Returns(new OrganizationDomain { Id = Guid.NewGuid(), OrganizationId = orgId, CreationDate = DateTime.UtcNow.AddDays(-7), DomainName = "test.com", Txt = "btw+12342" }); var result = await sutProvider.Sut.Get(orgId, id); Assert.IsType(result); Assert.Equal(orgId, result.OrganizationId); } [Theory, BitAutoData] public async Task Post_ShouldThrowUnauthorized_OrgIdCannotManageSso(Guid orgId, OrganizationDomainRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(false); var requestAction = async () => await sutProvider.Sut.Post(orgId, model); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Post_ShouldThrowNotFound_WhenOrganizationDoesNotExist(Guid orgId, OrganizationDomainRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Post(orgId, model); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Post_ShouldCreateEntry_WhenRequestIsValid(Guid orgId, OrganizationDomainRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).Returns(new Organization()); sutProvider.GetDependency().CreateAsync(Arg.Any()) .Returns(new OrganizationDomain()); var result = await sutProvider.Sut.Post(orgId, model); await sutProvider.GetDependency().ReceivedWithAnyArgs(1) .CreateAsync(Arg.Any()); Assert.IsType(result); } [Theory, BitAutoData] public async Task Verify_ShouldThrowUnauthorized_WhenOrgIdCannotManageSso(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(false); var requestAction = async () => await sutProvider.Sut.Verify(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Verify_ShouldThrowNotFound_WhenOrganizationDoesNotExist(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Verify(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task VerifyOrganizationDomain_ShouldThrowNotFound_WhenOrgIdDoesNotMatch(OrganizationDomain organizationDomain, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(organizationDomain.OrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(organizationDomain.OrganizationId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId) .ReturnsNull(); var requestAction = async () => await sutProvider.Sut.Verify(organizationDomain.OrganizationId, organizationDomain.Id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task Verify_WhenRequestIsValid(OrganizationDomain organizationDomain, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(organizationDomain.OrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(organizationDomain.OrganizationId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId) .Returns(organizationDomain); sutProvider.GetDependency().VerifyOrganizationDomainAsync(organizationDomain) .Returns(new OrganizationDomain()); var result = await sutProvider.Sut.Verify(organizationDomain.OrganizationId, organizationDomain.Id); await sutProvider.GetDependency().Received(1) .VerifyOrganizationDomainAsync(organizationDomain); Assert.IsType(result); } [Theory, BitAutoData] public async Task RemoveDomain_ShouldThrowUnauthorized_OrgIdCannotManageSso(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(false); var requestAction = async () => await sutProvider.Sut.RemoveDomain(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task RemoveDomain_ShouldThrowNotFound_WhenOrganizationDoesNotExist(Guid orgId, Guid id, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(orgId).Returns(true); sutProvider.GetDependency().GetByIdAsync(orgId).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.RemoveDomain(orgId, id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task RemoveDomain_ShouldThrowNotFound_WhenOrgIdDoesNotMatch(OrganizationDomain organizationDomain, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(organizationDomain.OrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(organizationDomain.OrganizationId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId) .ReturnsNull(); var requestAction = async () => await sutProvider.Sut.RemoveDomain(organizationDomain.OrganizationId, organizationDomain.Id); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task RemoveDomain_WhenRequestIsValid(OrganizationDomain organizationDomain, SutProvider sutProvider) { sutProvider.GetDependency().ManageSso(organizationDomain.OrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(organizationDomain.OrganizationId).Returns(new Organization()); sutProvider.GetDependency() .GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId) .Returns(organizationDomain); await sutProvider.Sut.RemoveDomain(organizationDomain.OrganizationId, organizationDomain.Id); await sutProvider.GetDependency().Received(1) .DeleteAsync(organizationDomain); } [Theory, BitAutoData] public async Task GetOrgDomainSsoDetails_ShouldThrowNotFound_WhenEmailHasNotClaimedDomain( OrganizationDomainSsoDetailsRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency() .GetOrganizationDomainSsoDetailsAsync(model.Email).ReturnsNull(); var requestAction = async () => await sutProvider.Sut.GetOrgDomainSsoDetails(model); await Assert.ThrowsAsync(requestAction); } [Theory, BitAutoData] public async Task GetOrgDomainSsoDetails_ShouldReturnOrganizationDomainSsoDetails_WhenEmailHasClaimedDomain( OrganizationDomainSsoDetailsRequestModel model, OrganizationDomainSsoDetailsData ssoDetailsData, SutProvider sutProvider) { sutProvider.GetDependency() .GetOrganizationDomainSsoDetailsAsync(model.Email).Returns(ssoDetailsData); var result = await sutProvider.Sut.GetOrgDomainSsoDetails(model); Assert.IsType(result); } [Theory, BitAutoData] public async Task GetVerifiedOrgDomainSsoDetails_ShouldThrowNotFound_WhenEmailHasNotClaimedDomain( OrganizationDomainSsoDetailsRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency() .GetVerifiedOrganizationDomainSsoDetailsAsync(model.Email).Returns(Array.Empty()); await Assert.ThrowsAsync(() => sutProvider.Sut.GetOrgDomainSsoDetails(model)); } [Theory, BitAutoData] public async Task GetVerifiedOrgDomainSsoDetails_ShouldReturnOrganizationDomainSsoDetails_WhenEmailHasClaimedDomain( OrganizationDomainSsoDetailsRequestModel model, IEnumerable ssoDetailsData, SutProvider sutProvider) { sutProvider.GetDependency() .GetVerifiedOrganizationDomainSsoDetailsAsync(model.Email).Returns(ssoDetailsData); var result = await sutProvider.Sut.GetVerifiedOrgDomainSsoDetailsAsync(model); Assert.IsType(result); } }