#nullable enable using System.Text.Json; using Bit.Core.AdminConsole.Entities; using Bit.Core.Exceptions; using Bit.Core.Models.Business; using Bit.Core.Models.Data.Organizations; using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces; using Bit.Core.Services; using Bit.Core.Settings; using Bit.Core.Utilities; namespace Bit.Core.OrganizationFeatures.OrganizationLicenses; public class UpdateOrganizationLicenseCommand : IUpdateOrganizationLicenseCommand { private readonly ILicensingService _licensingService; private readonly IGlobalSettings _globalSettings; private readonly IOrganizationService _organizationService; private readonly IFeatureService _featureService; public UpdateOrganizationLicenseCommand( ILicensingService licensingService, IGlobalSettings globalSettings, IOrganizationService organizationService, IFeatureService featureService) { _licensingService = licensingService; _globalSettings = globalSettings; _organizationService = organizationService; _featureService = featureService; } public async Task UpdateLicenseAsync(SelfHostedOrganizationDetails selfHostedOrganization, OrganizationLicense license, Organization? currentOrganizationUsingLicenseKey) { if (currentOrganizationUsingLicenseKey != null && currentOrganizationUsingLicenseKey.Id != selfHostedOrganization.Id) { throw new BadRequestException("License is already in use by another organization."); } var claimsPrincipal = _licensingService.GetClaimsPrincipalFromLicense(license); var canUse = license.CanUse(_globalSettings, claimsPrincipal, out var exception) && selfHostedOrganization.CanUseLicense(license, out exception); if (!canUse) { throw new BadRequestException(exception); } await WriteLicenseFileAsync(selfHostedOrganization, license); await UpdateOrganizationAsync(selfHostedOrganization, license); } private async Task WriteLicenseFileAsync(Organization organization, OrganizationLicense license) { var dir = $"{_globalSettings.LicenseDirectory}/organization"; Directory.CreateDirectory(dir); await using var fs = new FileStream(Path.Combine(dir, $"{organization.Id}.json"), FileMode.Create); await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented); } private async Task UpdateOrganizationAsync(SelfHostedOrganizationDetails selfHostedOrganizationDetails, OrganizationLicense license) { var organization = selfHostedOrganizationDetails.ToOrganization(); organization.UpdateFromLicense(license, _featureService); await _organizationService.ReplaceAndUpdateCacheAsync(organization); } }