diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb644fe8b5e2..420b9b63750a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -580,7 +580,6 @@ jobs: ref: 'main', inputs: { server_branch: process.env.GITHUB_REF - is_workflow_call: true } }); diff --git a/src/Api/Billing/Public/Controllers/OrganizationController.cs b/src/Api/Billing/Public/Controllers/OrganizationController.cs index c696f2af5065..7fcd94acd38d 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; @@ -35,6 +36,49 @@ 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)] + [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..09aa7decc17d --- /dev/null +++ b/src/Api/Billing/Public/Models/Response/OrganizationSubscriptionDetailsResponseModel.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.DataAnnotations; + +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; } +}