mirror of
https://github.com/bitwarden/server
synced 2026-01-20 09:23:28 +00:00
[PM-27731] Updated organization licenses to save the correct values from the token (#6546)
* Updated organization licenses to save the correct values from the token * Added additional test cases around licenses * Added missing properties from Organization to UpdateOrganizationLicenseCommand.UpdateLicenseAsync() * Add tests to validate license property synchronization pipeline * `dotnet format`
This commit is contained in:
@@ -128,6 +128,7 @@ public class SelfHostedOrganizationDetails : Organization
|
||||
UseApi = UseApi,
|
||||
UseResetPassword = UseResetPassword,
|
||||
UseSecretsManager = UseSecretsManager,
|
||||
UsePasswordManager = UsePasswordManager,
|
||||
SelfHost = SelfHost,
|
||||
UsersGetPremium = UsersGetPremium,
|
||||
UseCustomPermissions = UseCustomPermissions,
|
||||
@@ -156,6 +157,8 @@ public class SelfHostedOrganizationDetails : Organization
|
||||
UseAdminSponsoredFamilies = UseAdminSponsoredFamilies,
|
||||
UseDisableSmAdsForUsers = UseDisableSmAdsForUsers,
|
||||
UsePhishingBlocker = UsePhishingBlocker,
|
||||
UseOrganizationDomains = UseOrganizationDomains,
|
||||
UseAutomaticUserConfirmation = UseAutomaticUserConfirmation,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Licenses;
|
||||
using Bit.Core.Billing.Licenses.Extensions;
|
||||
using Bit.Core.Billing.Organizations.Models;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations;
|
||||
using Bit.Core.Services;
|
||||
@@ -46,6 +48,57 @@ public class UpdateOrganizationLicenseCommand : IUpdateOrganizationLicenseComman
|
||||
}
|
||||
|
||||
var claimsPrincipal = _licensingService.GetClaimsPrincipalFromLicense(license);
|
||||
|
||||
// If the license has a Token (claims-based), extract all properties from claims BEFORE validation
|
||||
// This ensures that CanUseLicense validation has access to the correct values from claims
|
||||
// Otherwise, fall back to using the properties already on the license object (backward compatibility)
|
||||
if (claimsPrincipal != null)
|
||||
{
|
||||
license.Name = claimsPrincipal.GetValue<string>(OrganizationLicenseConstants.Name);
|
||||
license.BillingEmail = claimsPrincipal.GetValue<string>(OrganizationLicenseConstants.BillingEmail);
|
||||
license.BusinessName = claimsPrincipal.GetValue<string>(OrganizationLicenseConstants.BusinessName);
|
||||
license.PlanType = claimsPrincipal.GetValue<PlanType>(OrganizationLicenseConstants.PlanType);
|
||||
license.Seats = claimsPrincipal.GetValue<int?>(OrganizationLicenseConstants.Seats);
|
||||
license.MaxCollections = claimsPrincipal.GetValue<short?>(OrganizationLicenseConstants.MaxCollections);
|
||||
license.UsePolicies = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UsePolicies);
|
||||
license.UseSso = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseSso);
|
||||
license.UseKeyConnector = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseKeyConnector);
|
||||
license.UseScim = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseScim);
|
||||
license.UseGroups = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseGroups);
|
||||
license.UseDirectory = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseDirectory);
|
||||
license.UseEvents = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseEvents);
|
||||
license.UseTotp = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseTotp);
|
||||
license.Use2fa = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.Use2fa);
|
||||
license.UseApi = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseApi);
|
||||
license.UseResetPassword = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseResetPassword);
|
||||
license.Plan = claimsPrincipal.GetValue<string>(OrganizationLicenseConstants.Plan);
|
||||
license.SelfHost = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.SelfHost);
|
||||
license.UsersGetPremium = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UsersGetPremium);
|
||||
license.UseCustomPermissions = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseCustomPermissions);
|
||||
license.Enabled = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.Enabled);
|
||||
license.Expires = claimsPrincipal.GetValue<DateTime?>(OrganizationLicenseConstants.Expires);
|
||||
license.LicenseKey = claimsPrincipal.GetValue<string>(OrganizationLicenseConstants.LicenseKey);
|
||||
license.UsePasswordManager = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UsePasswordManager);
|
||||
license.UseSecretsManager = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseSecretsManager);
|
||||
license.SmSeats = claimsPrincipal.GetValue<int?>(OrganizationLicenseConstants.SmSeats);
|
||||
license.SmServiceAccounts = claimsPrincipal.GetValue<int?>(OrganizationLicenseConstants.SmServiceAccounts);
|
||||
license.UseRiskInsights = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseRiskInsights);
|
||||
license.UseOrganizationDomains = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseOrganizationDomains);
|
||||
license.UseAdminSponsoredFamilies = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseAdminSponsoredFamilies);
|
||||
license.UseAutomaticUserConfirmation = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseAutomaticUserConfirmation);
|
||||
license.UseDisableSmAdsForUsers = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UseDisableSmAdsForUsers);
|
||||
license.UsePhishingBlocker = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.UsePhishingBlocker);
|
||||
license.MaxStorageGb = claimsPrincipal.GetValue<short?>(OrganizationLicenseConstants.MaxStorageGb);
|
||||
license.InstallationId = claimsPrincipal.GetValue<Guid>(OrganizationLicenseConstants.InstallationId);
|
||||
license.LicenseType = claimsPrincipal.GetValue<LicenseType>(OrganizationLicenseConstants.LicenseType);
|
||||
license.Issued = claimsPrincipal.GetValue<DateTime>(OrganizationLicenseConstants.Issued);
|
||||
license.Refresh = claimsPrincipal.GetValue<DateTime?>(OrganizationLicenseConstants.Refresh);
|
||||
license.ExpirationWithoutGracePeriod = claimsPrincipal.GetValue<DateTime?>(OrganizationLicenseConstants.ExpirationWithoutGracePeriod);
|
||||
license.Trial = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.Trial);
|
||||
license.LimitCollectionCreationDeletion = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.LimitCollectionCreationDeletion);
|
||||
license.AllowAdminAccessToAllCollectionItems = claimsPrincipal.GetValue<bool>(OrganizationLicenseConstants.AllowAdminAccessToAllCollectionItems);
|
||||
}
|
||||
|
||||
var canUse = license.CanUse(_globalSettings, _licensingService, claimsPrincipal, out var exception) &&
|
||||
selfHostedOrganization.CanUseLicense(license, out exception);
|
||||
|
||||
@@ -54,12 +107,6 @@ public class UpdateOrganizationLicenseCommand : IUpdateOrganizationLicenseComman
|
||||
throw new BadRequestException(exception);
|
||||
}
|
||||
|
||||
var useAutomaticUserConfirmation = claimsPrincipal?
|
||||
.GetValue<bool>(OrganizationLicenseConstants.UseAutomaticUserConfirmation) ?? false;
|
||||
|
||||
selfHostedOrganization.UseAutomaticUserConfirmation = useAutomaticUserConfirmation;
|
||||
license.UseAutomaticUserConfirmation = useAutomaticUserConfirmation;
|
||||
|
||||
await WriteLicenseFileAsync(selfHostedOrganization, license);
|
||||
await UpdateOrganizationAsync(selfHostedOrganization, license);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Billing.Licenses;
|
||||
using Bit.Core.Billing.Licenses.Extensions;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Models.Business;
|
||||
using Bit.Core.Billing.Models.Sales;
|
||||
@@ -982,6 +984,16 @@ public class UserService : UserManager<User>, IUserService
|
||||
throw new BadRequestException(exceptionMessage);
|
||||
}
|
||||
|
||||
// If the license has a Token (claims-based), extract all properties from claims
|
||||
// Otherwise, fall back to using the properties already on the license object (backward compatibility)
|
||||
if (claimsPrincipal != null)
|
||||
{
|
||||
license.LicenseKey = claimsPrincipal.GetValue<string>(UserLicenseConstants.LicenseKey);
|
||||
license.Premium = claimsPrincipal.GetValue<bool>(UserLicenseConstants.Premium);
|
||||
license.MaxStorageGb = claimsPrincipal.GetValue<short?>(UserLicenseConstants.MaxStorageGb);
|
||||
license.Expires = claimsPrincipal.GetValue<DateTime?>(UserLicenseConstants.Expires);
|
||||
}
|
||||
|
||||
var dir = $"{_globalSettings.LicenseDirectory}/user";
|
||||
Directory.CreateDirectory(dir);
|
||||
using var fs = File.OpenWrite(Path.Combine(dir, $"{user.Id}.json"));
|
||||
|
||||
Reference in New Issue
Block a user