using Bit.Api.Billing.Controllers; using Bit.Api.Models.Request.Organizations; using Bit.Core.AdminConsole.Entities; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Utilities; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Api.Test.Billing.Controllers; [ControllerCustomize(typeof(OrganizationSponsorshipsController))] [SutProviderCustomize] public class OrganizationSponsorshipsControllerTests { public static IEnumerable EnterprisePlanTypes => Enum.GetValues().Where(p => StaticStore.GetPlan(p).Product == ProductType.Enterprise).Select(p => new object[] { p }); public static IEnumerable NonEnterprisePlanTypes => Enum.GetValues().Where(p => StaticStore.GetPlan(p).Product != ProductType.Enterprise).Select(p => new object[] { p }); public static IEnumerable NonFamiliesPlanTypes => Enum.GetValues().Where(p => StaticStore.GetPlan(p).Product != ProductType.Families).Select(p => new object[] { p }); public static IEnumerable NonConfirmedOrganizationUsersStatuses => Enum.GetValues() .Where(s => s != OrganizationUserStatusType.Confirmed) .Select(s => new object[] { s }); [Theory] [BitAutoData] public async Task RedeemSponsorship_BadToken_ThrowsBadRequest(string sponsorshipToken, User user, OrganizationSponsorshipRedeemRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().UserId.Returns(user.Id); sutProvider.GetDependency().GetUserByIdAsync(user.Id) .Returns(user); sutProvider.GetDependency().ValidateRedemptionTokenAsync(sponsorshipToken, user.Email).Returns((false, null)); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.RedeemSponsorship(sponsorshipToken, model)); Assert.Contains("Failed to parse sponsorship token.", exception.Message); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .SetUpSponsorshipAsync(default, default); } [Theory] [BitAutoData] public async Task RedeemSponsorship_NotSponsoredOrgOwner_ThrowsBadRequest(string sponsorshipToken, User user, OrganizationSponsorship sponsorship, OrganizationSponsorshipRedeemRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().UserId.Returns(user.Id); sutProvider.GetDependency().GetUserByIdAsync(user.Id) .Returns(user); sutProvider.GetDependency().ValidateRedemptionTokenAsync(sponsorshipToken, user.Email).Returns((true, sponsorship)); sutProvider.GetDependency().OrganizationOwner(model.SponsoredOrganizationId).Returns(false); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.RedeemSponsorship(sponsorshipToken, model)); Assert.Contains("Can only redeem sponsorship for an organization you own.", exception.Message); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .SetUpSponsorshipAsync(default, default); } [Theory] [BitAutoData] public async Task RedeemSponsorship_NotSponsoredOrgOwner_Success(string sponsorshipToken, User user, OrganizationSponsorship sponsorship, Organization sponsoringOrganization, OrganizationSponsorshipRedeemRequestModel model, SutProvider sutProvider) { sutProvider.GetDependency().UserId.Returns(user.Id); sutProvider.GetDependency().GetUserByIdAsync(user.Id) .Returns(user); sutProvider.GetDependency().ValidateRedemptionTokenAsync(sponsorshipToken, user.Email).Returns((true, sponsorship)); sutProvider.GetDependency().OrganizationOwner(model.SponsoredOrganizationId).Returns(true); sutProvider.GetDependency().GetByIdAsync(model.SponsoredOrganizationId).Returns(sponsoringOrganization); await sutProvider.Sut.RedeemSponsorship(sponsorshipToken, model); await sutProvider.GetDependency().Received(1) .SetUpSponsorshipAsync(sponsorship, sponsoringOrganization); } [Theory] [BitAutoData] public async Task PreValidateSponsorshipToken_ValidatesToken_Success(string sponsorshipToken, User user, OrganizationSponsorship sponsorship, SutProvider sutProvider) { sutProvider.GetDependency().UserId.Returns(user.Id); sutProvider.GetDependency().GetUserByIdAsync(user.Id) .Returns(user); sutProvider.GetDependency() .ValidateRedemptionTokenAsync(sponsorshipToken, user.Email).Returns((true, sponsorship)); await sutProvider.Sut.PreValidateSponsorshipToken(sponsorshipToken); await sutProvider.GetDependency().Received(1) .ValidateRedemptionTokenAsync(sponsorshipToken, user.Email); } [Theory] [BitAutoData] public async Task RevokeSponsorship_WrongSponsoringUser_ThrowsBadRequest(OrganizationUser sponsoringOrgUser, Guid currentUserId, SutProvider sutProvider) { sutProvider.GetDependency().UserId.Returns(currentUserId); sutProvider.GetDependency().GetByIdAsync(sponsoringOrgUser.Id) .Returns(sponsoringOrgUser); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.RevokeSponsorship(sponsoringOrgUser.Id)); Assert.Contains("Can only revoke a sponsorship you granted.", exception.Message); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .RemoveSponsorshipAsync(default); } [Theory] [BitAutoData] public async Task RemoveSponsorship_WrongOrgUserType_ThrowsBadRequest(Organization sponsoredOrg, SutProvider sutProvider) { sutProvider.GetDependency().OrganizationOwner(Arg.Any()).Returns(false); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.RemoveSponsorship(sponsoredOrg.Id)); Assert.Contains("Only the owner of an organization can remove sponsorship.", exception.Message); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .RemoveSponsorshipAsync(default); } }