From e30bc9a83931ae15fbb15d7be0c0087b39acd55c Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 15 Nov 2024 10:13:05 -0500 Subject: [PATCH 1/7] added GET operation to org subscription endpoint --- .../Controllers/OrganizationController.cs | 39 ++++++++++++++++++- ...anizationSubscriptionUpdateRequestModel.cs | 0 ...izationSubscriptionDetailsResponseModel.cs | 36 +++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) rename src/Api/Billing/Public/Models/{ => Request}/OrganizationSubscriptionUpdateRequestModel.cs (100%) create mode 100644 src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs diff --git a/src/Api/Billing/Public/Controllers/OrganizationController.cs b/src/Api/Billing/Public/Controllers/OrganizationController.cs index c696f2af5065..21eecfa05c27 100644 --- a/src/Api/Billing/Public/Controllers/OrganizationController.cs +++ b/src/Api/Billing/Public/Controllers/OrganizationController.cs @@ -1,4 +1,5 @@ using System.Net; +using Bit.Api.Billing.Public.Models; using Bit.Api.Models.Public.Response; using Bit.Core.Context; using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface; @@ -7,8 +8,6 @@ using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using OrganizationSubscriptionUpdateRequestModel = Bit.Api.Billing.Public.Models.OrganizationSubscriptionUpdateRequestModel; - namespace Bit.Api.Billing.Public.Controllers; [Route("public/organization")] @@ -35,6 +34,42 @@ public OrganizationController( _logger = logger; } + [HttpGet("subscription")] + [ProducesResponseType(typeof(OrganizationSubscriptionDetailsResponseModel), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.NotFound)] + public async Task GetSubscriptionAsync() + { + try + { + var organizationId = _currentContext.OrganizationId.Value; + var organization = await _organizationRepository.GetByIdAsync(organizationId); + + var subscriptionDetails = new OrganizationSubscriptionDetailsResponseModel + { + PasswordManager = new PasswordManagerSubscriptionDetails + { + Seats = organization.Seats, + MaxAutoScaleSeats = organization.MaxAutoscaleSeats, + Storage = organization.MaxStorageGb + }, + SecretsManager = new SecretsManagerSubscriptionDetails + { + Seats = organization.SmSeats, + MaxAutoScaleSeats = organization.MaxAutoscaleSmSeats, + ServiceAccounts = organization.SmServiceAccounts, + MaxAutoScaleServiceAccounts = organization.MaxAutoscaleSmServiceAccounts + } + }; + + return Ok(subscriptionDetails); + } + catch (Exception ex) + { + _logger.LogError(ex, "Unhandled error while retrieving the subscription details"); + return StatusCode(500, new { Message = "An error occurred while retrieving the subscription details." }); + } + } + /// /// Update the organization's current subscription for Password Manager and/or Secrets Manager. /// diff --git a/src/Api/Billing/Public/Models/OrganizationSubscriptionUpdateRequestModel.cs b/src/Api/Billing/Public/Models/Request/OrganizationSubscriptionUpdateRequestModel.cs similarity index 100% rename from src/Api/Billing/Public/Models/OrganizationSubscriptionUpdateRequestModel.cs rename to src/Api/Billing/Public/Models/Request/OrganizationSubscriptionUpdateRequestModel.cs diff --git a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs new file mode 100644 index 000000000000..fe6c32c8a4cf --- /dev/null +++ b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs @@ -0,0 +1,36 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.AdminConsole.Entities; +using Bit.Core.Models.Business; + +namespace Bit.Api.Billing.Public.Models; + +public class OrganizationSubscriptionDetailsResponseModel : IValidatableObject +{ + public PasswordManagerSubscriptionDetails PasswordManager { get; set; } + public SecretsManagerSubscriptionDetails SecretsManager { get; set; } + public IEnumerable Validate(ValidationContext validationContext) + { + if (PasswordManager == null && SecretsManager == null) + { + yield return new ValidationResult("At least one of PasswordManager or SecretsManager must be provided."); + } + + yield return ValidationResult.Success; + } + } + + public class PasswordManagerSubscriptionDetails + { + public int? Seats { get; set; } + public int? MaxAutoScaleSeats { get; set; } + public short? Storage { get; set; } + } + + public class SecretsManagerSubscriptionDetails + { + public int? Seats { get; set; } + public int? MaxAutoScaleSeats { get; set; } + public int? ServiceAccounts { get; set; } + public int? MaxAutoScaleServiceAccounts { get; set; } + } + From 2bcb1c9f50ae561ce3c49913fefddba6a9e0dbf1 Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 15 Nov 2024 10:23:11 -0500 Subject: [PATCH 2/7] adding back removed using statement --- src/Api/Billing/Public/Controllers/OrganizationController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Api/Billing/Public/Controllers/OrganizationController.cs b/src/Api/Billing/Public/Controllers/OrganizationController.cs index 21eecfa05c27..5f9c3cf7f942 100644 --- a/src/Api/Billing/Public/Controllers/OrganizationController.cs +++ b/src/Api/Billing/Public/Controllers/OrganizationController.cs @@ -8,6 +8,8 @@ using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using OrganizationSubscriptionUpdateRequestModel = Bit.Api.Billing.Public.Models.OrganizationSubscriptionUpdateRequestModel; + namespace Bit.Api.Billing.Public.Controllers; [Route("public/organization")] From 47a2d259c7061bc4c89d6e816079880da29dd614 Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 15 Nov 2024 10:36:00 -0500 Subject: [PATCH 3/7] addressing unused import and lint warnings --- .../Response/OrganizationSubscriptionDetailsResponseModel.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs index fe6c32c8a4cf..b2551b5a6b23 100644 --- a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs +++ b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs @@ -1,6 +1,4 @@ using System.ComponentModel.DataAnnotations; -using Bit.Core.AdminConsole.Entities; -using Bit.Core.Models.Business; namespace Bit.Api.Billing.Public.Models; @@ -18,7 +16,6 @@ public IEnumerable Validate(ValidationContext validationContex yield return ValidationResult.Success; } } - public class PasswordManagerSubscriptionDetails { public int? Seats { get; set; } From 2bb18848869ef30245e9dac9ce54e1521ba33750 Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 15 Nov 2024 10:42:28 -0500 Subject: [PATCH 4/7] whitespace lint fix --- .../Response/OrganizationSubscriptionDetailsResponseModel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs index b2551b5a6b23..1b1fab6d3d5e 100644 --- a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs +++ b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs @@ -30,4 +30,3 @@ public class SecretsManagerSubscriptionDetails public int? ServiceAccounts { get; set; } public int? MaxAutoScaleServiceAccounts { get; set; } } - From 744d44ccef5d75fef1997660ff27b0c61041741f Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 15 Nov 2024 10:46:24 -0500 Subject: [PATCH 5/7] successful local format --- ...izationSubscriptionDetailsResponseModel.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs index 1b1fab6d3d5e..09aa7decc17d 100644 --- a/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs +++ b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs @@ -14,19 +14,19 @@ public IEnumerable Validate(ValidationContext validationContex } yield return ValidationResult.Success; - } - } - public class PasswordManagerSubscriptionDetails - { - public int? Seats { get; set; } - public int? MaxAutoScaleSeats { get; set; } - public short? Storage { get; set; } } +} +public class PasswordManagerSubscriptionDetails +{ + public int? Seats { get; set; } + public int? MaxAutoScaleSeats { get; set; } + public short? Storage { get; set; } +} - public class SecretsManagerSubscriptionDetails - { - public int? Seats { get; set; } - public int? MaxAutoScaleSeats { get; set; } - public int? ServiceAccounts { get; set; } - public int? MaxAutoScaleServiceAccounts { get; set; } - } +public class SecretsManagerSubscriptionDetails +{ + public int? Seats { get; set; } + public int? MaxAutoScaleSeats { get; set; } + public int? ServiceAccounts { get; set; } + public int? MaxAutoScaleServiceAccounts { get; set; } +} From 47c89d838f8f34a4656ed2739d95eb16c865b238 Mon Sep 17 00:00:00 2001 From: AJ Date: Thu, 21 Nov 2024 12:28:03 -0500 Subject: [PATCH 6/7] add NotSelfHostOnly attribute --- src/Api/Billing/Public/Controllers/OrganizationController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Api/Billing/Public/Controllers/OrganizationController.cs b/src/Api/Billing/Public/Controllers/OrganizationController.cs index 5f9c3cf7f942..c0601413e050 100644 --- a/src/Api/Billing/Public/Controllers/OrganizationController.cs +++ b/src/Api/Billing/Public/Controllers/OrganizationController.cs @@ -37,6 +37,7 @@ public OrganizationController( } [HttpGet("subscription")] + [SelfHosted(NotSelfHostedOnly = true)] [ProducesResponseType(typeof(OrganizationSubscriptionDetailsResponseModel), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.NotFound)] public async Task GetSubscriptionAsync() From 7f6e67f17f8cdc4b6f119089f3a59b3cdc75040f Mon Sep 17 00:00:00 2001 From: AJ Date: Wed, 11 Dec 2024 09:11:46 -0500 Subject: [PATCH 7/7] add endpoint summary and return details --- .../Billing/Public/Controllers/OrganizationController.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Api/Billing/Public/Controllers/OrganizationController.cs b/src/Api/Billing/Public/Controllers/OrganizationController.cs index c0601413e050..7fcd94acd38d 100644 --- a/src/Api/Billing/Public/Controllers/OrganizationController.cs +++ b/src/Api/Billing/Public/Controllers/OrganizationController.cs @@ -36,6 +36,12 @@ public OrganizationController( _logger = logger; } + /// + /// Retrieves the subscription details for the current organization. + /// + /// + /// Returns an object containing the subscription details if successful. + /// [HttpGet("subscription")] [SelfHosted(NotSelfHostedOnly = true)] [ProducesResponseType(typeof(OrganizationSubscriptionDetailsResponseModel), (int)HttpStatusCode.OK)]