diff --git a/src/Core/Billing/Licenses/Extensions/LicenseExtensions.cs b/src/Core/Billing/Licenses/Extensions/LicenseExtensions.cs index 184d8dad23..fd0ac23e4d 100644 --- a/src/Core/Billing/Licenses/Extensions/LicenseExtensions.cs +++ b/src/Core/Billing/Licenses/Extensions/LicenseExtensions.cs @@ -1,7 +1,11 @@ -using System.Security.Claims; +using System.Reflection; +using System.Security.Claims; +using System.Text; using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Enums; +using Bit.Core.Billing.Licenses.Attributes; using Bit.Core.Models.Business; +using Bit.Core.Utilities; namespace Bit.Core.Billing.Licenses.Extensions; @@ -76,6 +80,34 @@ public static class LicenseExtensions return expirationDate; } + public static byte[] GetDataBytesWithAttributes(this ILicense license, bool forHash = false) + { + var props = license.GetType() + .GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Where(p => + { + var versionAttr = p.GetCustomAttribute(); + if (versionAttr is null || versionAttr.Version > license.Version) + { + return false; + } + + var ignoreAttr = p.GetCustomAttribute(); + if (ignoreAttr is null) + { + return true; + } + + return forHash && ignoreAttr.IncludeInHash; + }) + .OrderBy(p => p.Name) + .Select(p => $"{p.Name}:{CoreHelpers.FormatLicenseSignatureValue(p.GetValue(license, null))}") + .Aggregate((c, n) => $"{c}|{n}"); + + var data = $"license:{license.LicenseType.ToString().ToLowerInvariant()}|{props}"; + return Encoding.UTF8.GetBytes(data); + } + public static T GetValue(this ClaimsPrincipal principal, string claimType) { var claim = principal.FindFirst(claimType); diff --git a/src/Core/Models/Business/BaseLicense.cs b/src/Core/Models/Business/BaseLicense.cs index 25bb05a6b4..08894654e2 100644 --- a/src/Core/Models/Business/BaseLicense.cs +++ b/src/Core/Models/Business/BaseLicense.cs @@ -43,7 +43,7 @@ public abstract class BaseLicense : ILicense public string Signature { get; set; } [LicenseIgnore] - public LicenseType? LicenseType { get; set; } + public LicenseType LicenseType { get; set; } [LicenseIgnore] public string Token { get; set; } diff --git a/src/Core/Models/Business/ILicense.cs b/src/Core/Models/Business/ILicense.cs index b0e295bdd9..d3b72601ec 100644 --- a/src/Core/Models/Business/ILicense.cs +++ b/src/Core/Models/Business/ILicense.cs @@ -1,9 +1,11 @@ using System.Security.Cryptography.X509Certificates; +using Bit.Core.Enums; namespace Bit.Core.Models.Business; public interface ILicense { + LicenseType LicenseType { get; set; } string LicenseKey { get; set; } int Version { get; set; } DateTime Issued { get; set; } diff --git a/src/Core/Models/Business/OrganizationLicense.cs b/src/Core/Models/Business/OrganizationLicense.cs index 9fc2ac5969..89e9912490 100644 --- a/src/Core/Models/Business/OrganizationLicense.cs +++ b/src/Core/Models/Business/OrganizationLicense.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Security.Claims; +using System.Security.Claims; using System.Text; using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Enums; @@ -258,30 +257,7 @@ public class OrganizationLicense : BaseLicense throw new NotSupportedException($"Version {Version} is not supported."); } - var props = GetType() - .GetProperties(BindingFlags.Public | BindingFlags.Instance) - .Where(p => - { - var versionAttr = p.GetCustomAttribute(); - if (versionAttr is null || versionAttr.Version > Version) - { - return false; - } - - var ignoreAttr = p.GetCustomAttribute(); - if (ignoreAttr is null) - { - return true; - } - - return forHash && ignoreAttr.IncludeInHash; - }) - .OrderBy(p => p.Name) - .Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}") - .Aggregate((c, n) => $"{c}|{n}"); - - var data = $"license:organization|{props}"; - return Encoding.UTF8.GetBytes(data); + return this.GetDataBytesWithAttributes(forHash); } public bool CanUse( @@ -397,7 +373,7 @@ public class OrganizationLicense : BaseLicense errorMessages.AppendLine("The license does not allow for on-premise hosting of organizations."); } - if (LicenseType != null && LicenseType != Enums.LicenseType.Organization) + if (LicenseType != LicenseType.Organization) { errorMessages.AppendLine("Premium licenses cannot be applied to an organization. " + "Upload this license from your personal account settings page."); diff --git a/src/Core/Models/Business/UserLicense.cs b/src/Core/Models/Business/UserLicense.cs index 0cf2f050ef..3528835836 100644 --- a/src/Core/Models/Business/UserLicense.cs +++ b/src/Core/Models/Business/UserLicense.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Security.Claims; +using System.Security.Claims; using System.Text; using Bit.Core.Billing.Licenses.Attributes; using Bit.Core.Billing.Licenses.Extensions; @@ -71,30 +70,7 @@ public class UserLicense : BaseLicense throw new NotSupportedException($"Version {Version} is not supported."); } - var props = GetType() - .GetProperties(BindingFlags.Public | BindingFlags.Instance) - .Where(p => - { - var versionAttr = p.GetCustomAttribute(); - if (versionAttr is null || versionAttr.Version > Version) - { - return false; - } - - var ignoreAttr = p.GetCustomAttribute(); - if (ignoreAttr is null) - { - return true; - } - - return forHash && ignoreAttr.IncludeInHash; - }) - .OrderBy(p => p.Name) - .Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}") - .Aggregate((c, n) => $"{c}|{n}"); - - var data = $"license:user|{props}"; - return Encoding.UTF8.GetBytes(data); + return this.GetDataBytesWithAttributes(forHash); } public bool CanUse(User user, ClaimsPrincipal claimsPrincipal, out string exception)