1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-28 06:36:15 -05:00

Moved ValidateOrganizationsAsync out of LicensingService since its only usage was in ValidateOrganizationsJob

This commit is contained in:
Conner Turnbull 2025-06-12 13:50:40 -04:00
parent 208d70d50e
commit fa6427f3bf
No known key found for this signature in database
3 changed files with 89 additions and 71 deletions

View File

@ -1,5 +1,11 @@
using Bit.Core.Jobs; using Bit.Core;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Billing.Licenses.Extensions;
using Bit.Core.Jobs;
using Bit.Core.Models.Business;
using Bit.Core.Repositories;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Settings;
using Quartz; using Quartz;
namespace Bit.Api.Jobs; namespace Bit.Api.Jobs;
@ -7,17 +13,98 @@ namespace Bit.Api.Jobs;
public class ValidateOrganizationsJob : BaseJob public class ValidateOrganizationsJob : BaseJob
{ {
private readonly ILicensingService _licensingService; private readonly ILicensingService _licensingService;
private readonly IGlobalSettings _globalSettings;
private readonly IOrganizationRepository _organizationRepository;
private readonly IMailService _mailService;
public ValidateOrganizationsJob( public ValidateOrganizationsJob(
ILicensingService licensingService, ILicensingService licensingService,
IGlobalSettings globalSettings,
IOrganizationRepository organizationRepository,
IMailService mailService,
ILogger<ValidateOrganizationsJob> logger) ILogger<ValidateOrganizationsJob> logger)
: base(logger) : base(logger)
{ {
_licensingService = licensingService; _licensingService = licensingService;
_globalSettings = globalSettings;
_organizationRepository = organizationRepository;
_mailService = mailService;
} }
protected async override Task ExecuteJobAsync(IJobExecutionContext context) protected async override Task ExecuteJobAsync(IJobExecutionContext context)
{ {
await _licensingService.ValidateOrganizationsAsync(); await ValidateOrganizationsAsync();
}
private async Task ValidateOrganizationsAsync()
{
if (!_globalSettings.SelfHosted)
{
return;
}
var enabledOrgs = await _organizationRepository.GetManyByEnabledAsync();
_logger.LogInformation(Constants.BypassFiltersEventId, null,
"Validating licenses for {NumberOfOrganizations} organizations.", enabledOrgs.Count);
var exceptions = new List<Exception>();
foreach (var org in enabledOrgs)
{
try
{
var license = await _licensingService.ReadOrganizationLicenseAsync(org);
if (license == null)
{
await DisableOrganizationAsync(org, null, "No license file.");
continue;
}
var totalLicensedOrgs = enabledOrgs.Count(o => string.Equals(o.LicenseKey, license.LicenseKey));
if (totalLicensedOrgs > 1)
{
await DisableOrganizationAsync(org, license, "Multiple organizations.");
continue;
}
if (!license.VerifyData(org, _licensingService.GetClaimsPrincipalFromLicense(license), _globalSettings))
{
await DisableOrganizationAsync(org, license, "Invalid data.");
continue;
}
if (!_licensingService.VerifyLicense(license))
{
await DisableOrganizationAsync(org, license, "Invalid signature.");
continue;
}
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Count != 0)
{
throw new AggregateException("There were one or more exceptions while validating organizations.", exceptions);
}
}
private async Task DisableOrganizationAsync(Organization org, ILicense license, string reason)
{
_logger.LogInformation(Constants.BypassFiltersEventId, null,
"Organization {OrganizationId} ({OrganizationName}) has an invalid license and is being disabled. Reason: {Reason}",
org.Id,
org.DisplayName(),
reason);
org.Enabled = false;
org.ExpirationDate = license?.Expires ?? DateTime.UtcNow;
org.RevisionDate = DateTime.UtcNow;
await _organizationRepository.ReplaceAsync(org);
await _mailService.SendLicenseExpiredAsync([org.BillingEmail], org.DisplayName());
} }
} }

View File

@ -9,7 +9,6 @@ namespace Bit.Core.Services;
public interface ILicensingService public interface ILicensingService
{ {
Task ValidateOrganizationsAsync();
Task ValidateUsersAsync(); Task ValidateUsersAsync();
Task<bool> ValidateUserPremiumAsync(User user); Task<bool> ValidateUserPremiumAsync(User user);
bool VerifyLicense(ILicense license); bool VerifyLicense(ILicense license);

View File

@ -84,74 +84,6 @@ public class LicensingService : ILicensingService
} }
} }
public async Task ValidateOrganizationsAsync()
{
if (!_globalSettings.SelfHosted)
{
return;
}
var enabledOrgs = await _organizationRepository.GetManyByEnabledAsync();
_logger.LogInformation(Constants.BypassFiltersEventId, null,
"Validating licenses for {NumberOfOrganizations} organizations.", enabledOrgs.Count);
var exceptions = new List<Exception>();
foreach (var org in enabledOrgs)
{
try
{
var license = await ReadOrganizationLicenseAsync(org);
if (license == null)
{
await DisableOrganizationAsync(org, null, "No license file.");
continue;
}
var totalLicensedOrgs = enabledOrgs.Count(o => string.Equals(o.LicenseKey, license.LicenseKey));
if (totalLicensedOrgs > 1)
{
await DisableOrganizationAsync(org, license, "Multiple organizations.");
continue;
}
if (!license.VerifyData(org, GetClaimsPrincipalFromLicense(license), _globalSettings))
{
await DisableOrganizationAsync(org, license, "Invalid data.");
continue;
}
if (string.IsNullOrWhiteSpace(license.Token) && !license.VerifySignature(_certificate))
{
await DisableOrganizationAsync(org, license, "Invalid signature.");
continue;
}
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Any())
{
throw new AggregateException("There were one or more exceptions while validating organizations.", exceptions);
}
}
private async Task DisableOrganizationAsync(Organization org, ILicense license, string reason)
{
_logger.LogInformation(Constants.BypassFiltersEventId, null,
"Organization {0} ({1}) has an invalid license and is being disabled. Reason: {2}",
org.Id, org.DisplayName(), reason);
org.Enabled = false;
org.ExpirationDate = license?.Expires ?? DateTime.UtcNow;
org.RevisionDate = DateTime.UtcNow;
await _organizationRepository.ReplaceAsync(org);
await _mailService.SendLicenseExpiredAsync(new List<string> { org.BillingEmail }, org.DisplayName());
}
public async Task ValidateUsersAsync() public async Task ValidateUsersAsync()
{ {
if (!_globalSettings.SelfHosted) if (!_globalSettings.SelfHosted)