diff --git a/src/Api/Billing/Controllers/OrganizationBillingController.cs b/src/Api/Billing/Controllers/OrganizationBillingController.cs index e06d946ea0..838efcdbf7 100644 --- a/src/Api/Billing/Controllers/OrganizationBillingController.cs +++ b/src/Api/Billing/Controllers/OrganizationBillingController.cs @@ -21,25 +21,6 @@ public class OrganizationBillingController( IStripePaymentService paymentService, IPaymentHistoryService paymentHistoryService) : BaseBillingController { - // TODO: Remove when pm-25379-use-new-organization-metadata-structure is removed. - [HttpGet("metadata")] - public async Task GetMetadataAsync([FromRoute] Guid organizationId) - { - if (!await currentContext.OrganizationUser(organizationId)) - { - return Error.Unauthorized(); - } - - var metadata = await organizationBillingService.GetMetadata(organizationId); - - if (metadata == null) - { - return Error.NotFound(); - } - - return TypedResults.Ok(metadata); - } - // TODO: Migrate to Query / OrganizationBillingVNextController [HttpGet("history")] public async Task GetHistoryAsync([FromRoute] Guid organizationId) diff --git a/src/Api/Billing/Controllers/VNext/OrganizationBillingVNextController.cs b/src/Api/Billing/Controllers/VNext/OrganizationBillingVNextController.cs index 64ec068a5e..be4aac9d92 100644 --- a/src/Api/Billing/Controllers/VNext/OrganizationBillingVNextController.cs +++ b/src/Api/Billing/Controllers/VNext/OrganizationBillingVNextController.cs @@ -4,7 +4,6 @@ using Bit.Api.Billing.Attributes; using Bit.Api.Billing.Models.Requests.Payment; using Bit.Api.Billing.Models.Requests.Subscriptions; using Bit.Api.Billing.Models.Requirements; -using Bit.Core; using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Commands; using Bit.Core.Billing.Organizations.Queries; @@ -117,7 +116,6 @@ public class OrganizationBillingVNextController( [Authorize] [HttpGet("metadata")] - [RequireFeature(FeatureFlagKeys.PM25379_UseNewOrganizationMetadataStructure)] [InjectOrganization] public async Task GetMetadataAsync( [BindNever] Organization organization) diff --git a/src/Api/Billing/Controllers/VNext/SelfHostedOrganizationBillingVNextController.cs b/src/Api/Billing/Controllers/VNext/SelfHostedOrganizationBillingVNextController.cs index 625a97c998..e6f0ee3bbd 100644 --- a/src/Api/Billing/Controllers/VNext/SelfHostedOrganizationBillingVNextController.cs +++ b/src/Api/Billing/Controllers/VNext/SelfHostedOrganizationBillingVNextController.cs @@ -1,7 +1,6 @@ using Bit.Api.AdminConsole.Authorization; using Bit.Api.AdminConsole.Authorization.Requirements; using Bit.Api.Billing.Attributes; -using Bit.Core; using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Organizations.Queries; using Bit.Core.Utilities; @@ -19,7 +18,6 @@ public class SelfHostedOrganizationBillingVNextController( { [Authorize] [HttpGet("metadata")] - [RequireFeature(FeatureFlagKeys.PM25379_UseNewOrganizationMetadataStructure)] [InjectOrganization] public async Task GetMetadataAsync([BindNever] Organization organization) { diff --git a/src/Core/Billing/Organizations/Services/IOrganizationBillingService.cs b/src/Core/Billing/Organizations/Services/IOrganizationBillingService.cs index 39d2a789e6..fbd242799a 100644 --- a/src/Core/Billing/Organizations/Services/IOrganizationBillingService.cs +++ b/src/Core/Billing/Organizations/Services/IOrganizationBillingService.cs @@ -26,13 +26,6 @@ public interface IOrganizationBillingService /// Task Finalize(OrganizationSale sale); - /// - /// Retrieve metadata about the organization represented bsy the provided . - /// - /// The ID of the organization to retrieve metadata for. - /// An record. - Task GetMetadata(Guid organizationId); - /// /// Updates the provided 's payment source and tax information. /// If the does not have a Stripe , this method will create one using the provided diff --git a/src/Core/Billing/Organizations/Services/OrganizationBillingService.cs b/src/Core/Billing/Organizations/Services/OrganizationBillingService.cs index a1b57c2415..579977ccc1 100644 --- a/src/Core/Billing/Organizations/Services/OrganizationBillingService.cs +++ b/src/Core/Billing/Organizations/Services/OrganizationBillingService.cs @@ -54,52 +54,6 @@ public class OrganizationBillingService( } } - public async Task GetMetadata(Guid organizationId) - { - var organization = await organizationRepository.GetByIdAsync(organizationId); - - if (organization == null) - { - return null; - } - - if (globalSettings.SelfHosted) - { - return OrganizationMetadata.Default; - } - - var orgOccupiedSeats = await organizationRepository.GetOccupiedSeatCountByOrganizationIdAsync(organization.Id); - - if (string.IsNullOrWhiteSpace(organization.GatewaySubscriptionId)) - { - return OrganizationMetadata.Default with - { - OrganizationOccupiedSeats = orgOccupiedSeats.Total - }; - } - - var customer = await subscriberService.GetCustomer(organization); - - var subscription = await subscriberService.GetSubscription(organization, new SubscriptionGetOptions - { - Expand = ["discounts.coupon.applies_to"] - }); - - if (customer == null || subscription == null) - { - return OrganizationMetadata.Default with - { - OrganizationOccupiedSeats = orgOccupiedSeats.Total - }; - } - - var isOnSecretsManagerStandalone = await IsOnSecretsManagerStandalone(organization, customer, subscription); - - return new OrganizationMetadata( - isOnSecretsManagerStandalone, - orgOccupiedSeats.Total); - } - public async Task UpdatePaymentMethod( Organization organization, TokenizedPaymentSource tokenizedPaymentSource, @@ -565,38 +519,6 @@ public class OrganizationBillingService( return customer; } - private async Task IsOnSecretsManagerStandalone( - Organization organization, - Customer? customer, - Subscription? subscription) - { - if (customer == null || subscription == null) - { - return false; - } - - var plan = await pricingClient.GetPlanOrThrow(organization.PlanType); - - if (!plan.SupportsSecretsManager) - { - return false; - } - - var coupon = subscription.Discounts?.FirstOrDefault(discount => - discount.Coupon?.Id == StripeConstants.CouponIDs.SecretsManagerStandalone)?.Coupon; - - if (coupon == null) - { - return false; - } - - var subscriptionProductIds = subscription.Items.Data.Select(item => item.Plan.ProductId); - - var couponAppliesTo = coupon.AppliesTo?.Products; - - return subscriptionProductIds.Intersect(couponAppliesTo ?? []).Any(); - } - private async Task UpdateMissingPaymentMethodBehaviourAsync(Organization organization) { var subscription = await subscriberService.GetSubscriptionOrThrow(organization); diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 25d5f8d4b9..71e1d15991 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -182,7 +182,6 @@ public static class FeatureFlagKeys /* Billing Team */ public const string TrialPayment = "PM-8163-trial-payment"; - public const string PM25379_UseNewOrganizationMetadataStructure = "pm-25379-use-new-organization-metadata-structure"; public const string PM24032_NewNavigationPremiumUpgradeButton = "pm-24032-new-navigation-premium-upgrade-button"; public const string PM23713_PremiumBadgeOpensNewPremiumUpgradeDialog = "pm-23713-premium-badge-opens-new-premium-upgrade-dialog"; public const string PM26793_FetchPremiumPriceFromPricingService = "pm-26793-fetch-premium-price-from-pricing-service"; diff --git a/test/Api.Test/Billing/Controllers/OrganizationBillingControllerTests.cs b/test/Api.Test/Billing/Controllers/OrganizationBillingControllerTests.cs index ee0bdc61e4..6678b3e15c 100644 --- a/test/Api.Test/Billing/Controllers/OrganizationBillingControllerTests.cs +++ b/test/Api.Test/Billing/Controllers/OrganizationBillingControllerTests.cs @@ -1,8 +1,6 @@ using Bit.Api.Billing.Controllers; using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Models; -using Bit.Core.Billing.Organizations.Models; -using Bit.Core.Billing.Organizations.Services; using Bit.Core.Billing.Services; using Bit.Core.Context; using Bit.Core.Repositories; @@ -20,50 +18,6 @@ namespace Bit.Api.Test.Billing.Controllers; [SutProviderCustomize] public class OrganizationBillingControllerTests { - [Theory, BitAutoData] - public async Task GetMetadataAsync_Unauthorized_ReturnsUnauthorized( - Guid organizationId, - SutProvider sutProvider) - { - sutProvider.GetDependency().AccessMembersTab(organizationId).Returns(false); - - var result = await sutProvider.Sut.GetMetadataAsync(organizationId); - - AssertUnauthorized(result); - } - - [Theory, BitAutoData] - public async Task GetMetadataAsync_MetadataNull_NotFound( - Guid organizationId, - SutProvider sutProvider) - { - sutProvider.GetDependency().OrganizationUser(organizationId).Returns(true); - sutProvider.GetDependency().GetMetadata(organizationId).Returns((OrganizationMetadata)null); - - var result = await sutProvider.Sut.GetMetadataAsync(organizationId); - - AssertNotFound(result); - } - - [Theory, BitAutoData] - public async Task GetMetadataAsync_OK( - Guid organizationId, - SutProvider sutProvider) - { - sutProvider.GetDependency().OrganizationUser(organizationId).Returns(true); - sutProvider.GetDependency().GetMetadata(organizationId) - .Returns(new OrganizationMetadata(true, 10)); - - var result = await sutProvider.Sut.GetMetadataAsync(organizationId); - - Assert.IsType>(result); - - var response = ((Ok)result).Value; - - Assert.True(response.IsOnSecretsManagerStandalone); - Assert.Equal(10, response.OrganizationOccupiedSeats); - } - [Theory, BitAutoData] public async Task GetHistoryAsync_Unauthorized_ReturnsUnauthorized( Guid organizationId, diff --git a/test/Core.Test/Billing/Services/OrganizationBillingServiceTests.cs b/test/Core.Test/Billing/Services/OrganizationBillingServiceTests.cs index f1b9446b6d..f72c8cdf76 100644 --- a/test/Core.Test/Billing/Services/OrganizationBillingServiceTests.cs +++ b/test/Core.Test/Billing/Services/OrganizationBillingServiceTests.cs @@ -7,7 +7,6 @@ using Bit.Core.Billing.Organizations.Services; using Bit.Core.Billing.Payment.Queries; using Bit.Core.Billing.Pricing; using Bit.Core.Billing.Services; -using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; using Bit.Core.Test.Billing.Mocks; using Bit.Test.Common.AutoFixture; @@ -21,110 +20,6 @@ namespace Bit.Core.Test.Billing.Services; [SutProviderCustomize] public class OrganizationBillingServiceTests { - #region GetMetadata - - [Theory, BitAutoData] - public async Task GetMetadata_Succeeds( - Guid organizationId, - Organization organization, - SutProvider sutProvider) - { - sutProvider.GetDependency().GetByIdAsync(organizationId).Returns(organization); - sutProvider.GetDependency().ListPlans().Returns(MockPlans.Plans.ToList()); - - sutProvider.GetDependency().GetPlanOrThrow(organization.PlanType) - .Returns(MockPlans.Get(organization.PlanType)); - - var subscriberService = sutProvider.GetDependency(); - var organizationSeatCount = new OrganizationSeatCounts { Users = 1, Sponsored = 0 }; - var customer = new Customer(); - - subscriberService - .GetCustomer(organization) - .Returns(customer); - - subscriberService.GetSubscription(organization, Arg.Is(options => - options.Expand.Contains("discounts.coupon.applies_to"))).Returns(new Subscription - { - Discounts = - [ - new Discount - { - Coupon = new Coupon - { - Id = StripeConstants.CouponIDs.SecretsManagerStandalone, - AppliesTo = new CouponAppliesTo - { - Products = ["product_id"] - } - } - } - ], - Items = new StripeList - { - Data = - [ - new SubscriptionItem - { - Plan = new Plan - { - ProductId = "product_id" - } - } - ] - } - }); - - sutProvider.GetDependency() - .GetOccupiedSeatCountByOrganizationIdAsync(organization.Id) - .Returns(new OrganizationSeatCounts { Users = 1, Sponsored = 0 }); - - var metadata = await sutProvider.Sut.GetMetadata(organizationId); - - Assert.True(metadata!.IsOnSecretsManagerStandalone); - } - - #endregion - - #region GetMetadata - Null Customer or Subscription - - [Theory, BitAutoData] - public async Task GetMetadata_WhenCustomerOrSubscriptionIsNull_ReturnsDefaultMetadata( - Guid organizationId, - Organization organization, - SutProvider sutProvider) - { - sutProvider.GetDependency().GetByIdAsync(organizationId).Returns(organization); - - sutProvider.GetDependency().ListPlans().Returns(MockPlans.Plans.ToList()); - - sutProvider.GetDependency().GetPlanOrThrow(organization.PlanType) - .Returns(MockPlans.Get(organization.PlanType)); - - sutProvider.GetDependency() - .GetOccupiedSeatCountByOrganizationIdAsync(organization.Id) - .Returns(new OrganizationSeatCounts { Users = 1, Sponsored = 0 }); - - var subscriberService = sutProvider.GetDependency(); - - // Set up subscriber service to return null for customer - subscriberService - .GetCustomer(organization) - .Returns((Customer)null); - - // Set up subscriber service to return null for subscription - subscriberService.GetSubscription(organization, Arg.Is(options => - options.Expand.Contains("discounts.coupon.applies_to"))).Returns((Subscription)null); - - var metadata = await sutProvider.Sut.GetMetadata(organizationId); - - Assert.NotNull(metadata); - Assert.False(metadata!.IsOnSecretsManagerStandalone); - Assert.Equal(1, metadata.OrganizationOccupiedSeats); - } - - #endregion - #region Finalize - Trial Settings [Theory, BitAutoData]