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; }
+}