using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; using Bit.Core.Billing.Pricing; using Bit.Core.Billing.Pricing.Premium; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Tools.Entities; using Bit.Core.Tools.Enums; using Bit.Core.Tools.Services; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Core.Test.Tools.Services; [SutProviderCustomize] public class SendValidationServiceTests { [Theory, BitAutoData] public async Task StorageRemainingForSendAsync_OrgGrantedPremiumUser_UsesPricingService( SutProvider sutProvider, Send send, User user) { // Arrange send.UserId = user.Id; send.OrganizationId = null; send.Type = SendType.File; user.Premium = false; user.Storage = 1024L * 1024L * 1024L; // 1 GB used user.EmailVerified = true; sutProvider.GetDependency().SelfHosted = false; sutProvider.GetDependency().GetByIdAsync(user.Id).Returns(user); sutProvider.GetDependency().CanAccessPremium(user).Returns(true); var premiumPlan = new Plan { Storage = new Purchasable { Provided = 5 } }; sutProvider.GetDependency().GetAvailablePremiumPlan().Returns(premiumPlan); // Act var result = await sutProvider.Sut.StorageRemainingForSendAsync(send); // Assert await sutProvider.GetDependency().Received(1).GetAvailablePremiumPlan(); Assert.True(result > 0); } [Theory, BitAutoData] public async Task StorageRemainingForSendAsync_IndividualPremium_DoesNotCallPricingService( SutProvider sutProvider, Send send, User user) { // Arrange send.UserId = user.Id; send.OrganizationId = null; send.Type = SendType.File; user.Premium = true; user.MaxStorageGb = 10; user.EmailVerified = true; sutProvider.GetDependency().GetByIdAsync(user.Id).Returns(user); sutProvider.GetDependency().CanAccessPremium(user).Returns(true); // Act var result = await sutProvider.Sut.StorageRemainingForSendAsync(send); // Assert - should NOT call pricing service for individual premium users await sutProvider.GetDependency().DidNotReceive().GetAvailablePremiumPlan(); } [Theory, BitAutoData] public async Task StorageRemainingForSendAsync_SelfHosted_DoesNotCallPricingService( SutProvider sutProvider, Send send, User user) { // Arrange send.UserId = user.Id; send.OrganizationId = null; send.Type = SendType.File; user.Premium = false; user.EmailVerified = true; sutProvider.GetDependency().SelfHosted = true; sutProvider.GetDependency().GetByIdAsync(user.Id).Returns(user); sutProvider.GetDependency().CanAccessPremium(user).Returns(true); // Act var result = await sutProvider.Sut.StorageRemainingForSendAsync(send); // Assert - should NOT call pricing service for self-hosted await sutProvider.GetDependency().DidNotReceive().GetAvailablePremiumPlan(); } [Theory, BitAutoData] public async Task StorageRemainingForSendAsync_OrgSend_DoesNotCallPricingService( SutProvider sutProvider, Send send, Organization org) { // Arrange send.UserId = null; send.OrganizationId = org.Id; send.Type = SendType.File; org.MaxStorageGb = 100; sutProvider.GetDependency().GetByIdAsync(org.Id).Returns(org); // Act var result = await sutProvider.Sut.StorageRemainingForSendAsync(send); // Assert - should NOT call pricing service for org sends await sutProvider.GetDependency().DidNotReceive().GetAvailablePremiumPlan(); } [Theory, BitAutoData] public async Task ValidateUserCanSaveAsync_WhenDisableSendPolicyEnforced_CannotCreateSend( SutProvider sutProvider, Send send, Guid userId) { sutProvider.GetDependency().GetAsync(userId) .Returns(new DisableSendPolicyRequirement { DisableSend = true }); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.ValidateUserCanSaveAsync(userId, send)); Assert.Contains("you are only able to delete an existing Send", exception.Message); } [Theory, BitAutoData] public async Task ValidateUserCanSaveAsync_WhenSendOptionsPolicyProhibitsHidingEmail_CannotHideEmail( SutProvider sutProvider, Send send, Guid userId) { send.HideEmail = true; sutProvider.GetDependency().GetAsync(userId) .Returns(new DisableSendPolicyRequirement { DisableSend = false }); sutProvider.GetDependency().GetAsync(userId) .Returns(new SendOptionsPolicyRequirement { DisableHideEmail = true }); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.ValidateUserCanSaveAsync(userId, send)); Assert.Contains("you are not allowed to hide your email address", exception.Message); } [Theory, BitAutoData] public async Task ValidateUserCanSaveAsync_WhenSendOptionsPolicyProhibitsHidingEmail_CanShowEmail( SutProvider sutProvider, Send send, Guid userId) { send.HideEmail = false; sutProvider.GetDependency().GetAsync(userId) .Returns(new DisableSendPolicyRequirement { DisableSend = false }); sutProvider.GetDependency().GetAsync(userId) .Returns(new SendOptionsPolicyRequirement { DisableHideEmail = true }); // No exception implies success await sutProvider.Sut.ValidateUserCanSaveAsync(userId, send); } [Theory, BitAutoData] public async Task ValidateUserCanSaveAsync_WhenPoliciesDoNotApply_Success( SutProvider sutProvider, Send send, Guid userId) { send.HideEmail = true; sutProvider.GetDependency().GetAsync(userId) .Returns(new DisableSendPolicyRequirement { DisableSend = false }); sutProvider.GetDependency().GetAsync(userId) .Returns(new SendOptionsPolicyRequirement { DisableHideEmail = false }); // No exception implies success await sutProvider.Sut.ValidateUserCanSaveAsync(userId, send); } }