using Bit.Api.Billing.Models.Requests; using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Services; using Bit.Core.Billing.Services; using Bit.Core.Context; using Bit.Core.Enums; using Bit.Core.Models.Business; using Bit.Core.Repositories; using Bit.Core.Services; using Microsoft.AspNetCore.Mvc; namespace Bit.Api.Billing.Controllers; [Route("providers/{providerId:guid}/clients")] public class ProviderClientsController( ICurrentContext currentContext, IFeatureService featureService, ILogger logger, IOrganizationRepository organizationRepository, IProviderBillingService providerBillingService, IProviderOrganizationRepository providerOrganizationRepository, IProviderRepository providerRepository, IProviderService providerService, IUserService userService) : BaseProviderController(currentContext, featureService, logger, providerRepository, userService) { [HttpPost] public async Task CreateAsync( [FromRoute] Guid providerId, [FromBody] CreateClientOrganizationRequestBody requestBody) { var (provider, result) = await TryGetBillableProviderForAdminOperation(providerId); if (provider == null) { return result; } var user = await UserService.GetUserByPrincipalAsync(User); if (user == null) { return Error.Unauthorized(); } var organizationSignup = new OrganizationSignup { Name = requestBody.Name, Plan = requestBody.PlanType, AdditionalSeats = requestBody.Seats, Owner = user, BillingEmail = provider.BillingEmail, OwnerKey = requestBody.Key, PublicKey = requestBody.KeyPair.PublicKey, PrivateKey = requestBody.KeyPair.EncryptedPrivateKey, CollectionName = requestBody.CollectionName, IsFromProvider = true }; var providerOrganization = await providerService.CreateOrganizationAsync( providerId, organizationSignup, requestBody.OwnerEmail, user); var clientOrganization = await organizationRepository.GetByIdAsync(providerOrganization.OrganizationId); await providerBillingService.ScaleSeats( provider, requestBody.PlanType, requestBody.Seats); await providerBillingService.CreateCustomerForClientOrganization( provider, clientOrganization); clientOrganization.Status = OrganizationStatusType.Managed; await organizationRepository.ReplaceAsync(clientOrganization); return TypedResults.Ok(); } [HttpPut("{providerOrganizationId:guid}")] public async Task UpdateAsync( [FromRoute] Guid providerId, [FromRoute] Guid providerOrganizationId, [FromBody] UpdateClientOrganizationRequestBody requestBody) { var (provider, result) = await TryGetBillableProviderForServiceUserOperation(providerId); if (provider == null) { return result; } var providerOrganization = await providerOrganizationRepository.GetByIdAsync(providerOrganizationId); if (providerOrganization == null) { return Error.NotFound(); } var clientOrganization = await organizationRepository.GetByIdAsync(providerOrganization.OrganizationId); if (clientOrganization.Seats != requestBody.AssignedSeats) { await providerBillingService.AssignSeatsToClientOrganization( provider, clientOrganization, requestBody.AssignedSeats); } clientOrganization.Name = requestBody.Name; await organizationRepository.ReplaceAsync(clientOrganization); return TypedResults.Ok(); } }