Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Licensing #4030

Merged
merged 7 commits into from Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/ServiceControl.Config/UI/License/LicenseComponentFactory.cs
Expand Up @@ -4,18 +4,18 @@
using System.Linq;
using ServiceControl.LicenseManagement;

class LicenseComponentFactory
static class LicenseComponentFactory
{
const string UpgradeProtectionLicenseText = "Please extend your upgrade protection so that we can continue to provide you with support and new versions of the Particular Service Platform.";
const string SubscriptionLicenseText = "Please extend your license to continue using the Particular Service Platform.";

CountInflector daysInflector = new CountInflector
static readonly CountInflector DaysInflector = new()
{
Singular = "{0} day",
Plural = "{0} days"
};

public IEnumerable<LicenseComponent> CreateComponents(LicenseDetails details)
public static IEnumerable<LicenseComponent> CreateComponents(LicenseDetails details)
{
yield return new LicenseComponent
{
Expand All @@ -38,7 +38,7 @@ public IEnumerable<LicenseComponent> CreateComponents(LicenseDetails details)
}
}

LicenseComponent SubscriptionExpiryComponent(LicenseDetails details)
static LicenseComponent SubscriptionExpiryComponent(LicenseDetails details)
{
if (details.WarnUserSubscriptionHasExpired || details.WarnUserTrialHasExpired)
{
Expand All @@ -54,7 +54,7 @@ LicenseComponent SubscriptionExpiryComponent(LicenseDetails details)

if (details.WarnUserSubscriptionIsExpiring || details.WarnUserTrialIsExpiring)
{
var daysRemain = daysInflector.Inflect(details.DaysUntilSubscriptionExpires ?? 0);
var daysRemain = DaysInflector.Inflect(details.DaysUntilSubscriptionExpires ?? 0);
return new LicenseComponent
{
Label = "Platform license expiry date:",
Expand All @@ -72,7 +72,7 @@ LicenseComponent SubscriptionExpiryComponent(LicenseDetails details)
};
}

LicenseComponent UpgradeProtectionExpiryComponent(LicenseDetails details)
static LicenseComponent UpgradeProtectionExpiryComponent(LicenseDetails details)
{
if (details.WarnUserUpgradeProtectionHasExpired)
{
Expand All @@ -88,7 +88,7 @@ LicenseComponent UpgradeProtectionExpiryComponent(LicenseDetails details)

if (details.WarnUserUpgradeProtectionIsExpiring)
{
var daysRemain = daysInflector.Inflect(details.DaysUntilUpgradeProtectionExpires ?? 0);
var daysRemain = DaysInflector.Inflect(details.DaysUntilUpgradeProtectionExpires ?? 0);
return new LicenseComponent
{
Label = "Upgrade protection expiry date:",
Expand Down
7 changes: 2 additions & 5 deletions src/ServiceControl.Config/UI/License/LicenseViewModel.cs
Expand Up @@ -13,10 +13,7 @@

class LicenseViewModel : RxScreen
{
public LicenseViewModel(IEventAggregator eventAggregator)
{
EventAggregator = eventAggregator;
}
public LicenseViewModel(IEventAggregator eventAggregator) => EventAggregator = eventAggregator;

public string ApplyLicenseError { get; set; }

Expand All @@ -42,7 +39,7 @@ void RefreshLicenseInfo()
{
license = LicenseManager.FindLicense();

Components = new LicenseComponentFactory().CreateComponents(license.Details).ToList();
Components = LicenseComponentFactory.CreateComponents(license.Details).ToList();

CanExtendTrial = license.Details.IsTrialLicense;

Expand Down
18 changes: 9 additions & 9 deletions src/ServiceControl.Config/UI/Shell/LicenseStatusManager.cs
Expand Up @@ -3,17 +3,17 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Caliburn.Micro;
using Commands;
using Events;
using Framework.Commands;
using Framework.Rx;
using License;
using ServiceControl.LicenseManagement;
using ICommand = System.Windows.Input.ICommand;

class LicenseStatusManager : RxScreen, IHandle<LicenseUpdated>, IHandle<FocusChanged>
{
public LicenseStatusManager(OpenViewModelCommand<LicenseViewModel> openLicense)
public LicenseStatusManager(AwaitableAbstractCommand<object> openLicense)
{
openLicense.OnCommandExecuting = () => ShowPopup = false;
OpenLicense = openLicense;
Expand All @@ -29,13 +29,13 @@ public bool ShowPopup
}

public string PopupHeading { get; set; }
public string PopupText { get; set; }
public string PopupText { get; private set; }

public ICommand OpenLicense { get; set; }

public bool IsWarning { get; set; }
public bool IsSerious { get; set; }
public bool HasFocus { get; set; }
public bool IsWarning { get; private set; }
public bool IsSerious { get; private set; }
public bool HasFocus { get; private set; }

public Task HandleAsync(FocusChanged message, CancellationToken cancellationToken)
{
Expand All @@ -53,9 +53,9 @@ void RefreshStatus(bool updatePopupDisplay)
{
var license = LicenseManager.FindLicense();

var components = new LicenseComponentFactory().CreateComponents(license.Details);
var components = LicenseComponentFactory.CreateComponents(license.Details);

var mostPressingComponent = components.OrderByDescending(d => d.Importance).FirstOrDefault();
var mostPressingComponent = components.MaxBy(d => d.Importance);

IsWarning = mostPressingComponent?.IsWarning ?? false;
IsSerious = mostPressingComponent?.IsSerious ?? false;
Expand Down
13 changes: 4 additions & 9 deletions src/ServiceControl.LicenseManagement/DetectedLicense.cs
Expand Up @@ -2,19 +2,14 @@
{
public class DetectedLicense
{
public DetectedLicense()
{
Details = new LicenseDetails();
}

public DetectedLicense(string licensePath, LicenseDetails details) : this()
public DetectedLicense(string licensePath, LicenseDetails details)
{
Location = licensePath;
Details = details;
}

public string Location { get; set; }
public LicenseDetails Details;
public bool IsEvaluationLicense { get; set; }
public string Location { get; }
public LicenseDetails Details { get; }
public bool IsEvaluationLicense { get; init; }
}
}
90 changes: 32 additions & 58 deletions src/ServiceControl.LicenseManagement/LicenseDetails.cs
Expand Up @@ -5,33 +5,36 @@

public class LicenseDetails
{
public DateTime? ExpirationDate { get; private set; }
public DateTime? UpgradeProtectionExpiration { get; private set; }
public DateTime? ExpirationDate { get; private init; }
public DateTime? UpgradeProtectionExpiration { get; private init; }

public bool IsTrialLicense { get; private set; }
public bool IsCommercialLicense { get; private set; }
public bool IsExtendedTrial { get; private set; }
public string LicenseType { get; private set; }
public string Edition { get; set; }
public string RegisteredTo { get; private set; }
public bool ValidForServiceControl { get; private set; }
public int? DaysUntilSubscriptionExpires { get; private set; }
public int? DaysUntilUpgradeProtectionExpires { get; private set; }
public bool WarnUserTrialIsExpiring { get; private set; }
public bool WarnUserTrialHasExpired { get; private set; }
public bool WarnUserSubscriptionIsExpiring { get; private set; }
public bool WarnUserSubscriptionHasExpired { get; private set; }
public bool WarnUserUpgradeProtectionIsExpiring { get; private set; }
public bool WarnUserUpgradeProtectionHasExpired { get; private set; }
public bool IsTrialLicense { get; private init; }
public bool IsCommercialLicense { get; private init; }
public bool IsExtendedTrial { get; private init; }
public string LicenseType { get; private init; }
public string Edition { get; private init; }
public string RegisteredTo { get; private init; }
public bool ValidForServiceControl { get; private init; }
public int? DaysUntilSubscriptionExpires { get; private init; }
public int? DaysUntilUpgradeProtectionExpires { get; private init; }
public bool WarnUserTrialIsExpiring { get; private init; }
public bool WarnUserTrialHasExpired { get; private init; }
public bool WarnUserSubscriptionIsExpiring { get; private init; }
public bool WarnUserSubscriptionHasExpired { get; private init; }
public bool WarnUserUpgradeProtectionIsExpiring { get; private init; }
public bool WarnUserUpgradeProtectionHasExpired { get; private init; }
public string Status { get; private init; }

internal static LicenseDetails FromLicense(License license)
{
LicenseStatus licenseStatus = license.GetLicenseStatus();

var details = new LicenseDetails
{
UpgradeProtectionExpiration = license.UpgradeProtectionExpiration,
//If expiration date is greater that 50 years treat is as no expiration date
ExpirationDate = license.ExpirationDate.HasValue
? (license.ExpirationDate.Value > DateTime.UtcNow.AddYears(50) ? null : license.ExpirationDate)
? license.ExpirationDate.Value > DateTime.UtcNow.AddYears(50) ? null : license.ExpirationDate
: license.ExpirationDate,
RegisteredTo = license.RegisteredTo,
IsCommercialLicense = license.IsCommercialLicense,
Expand All @@ -41,51 +44,22 @@ internal static LicenseDetails FromLicense(License license)
Edition = license.Edition,
ValidForServiceControl = license.ValidForApplication("ServiceControl"),
DaysUntilSubscriptionExpires = license.GetDaysUntilLicenseExpires(),
DaysUntilUpgradeProtectionExpires = license.GetDaysUntilUpgradeProtectionExpires()
DaysUntilUpgradeProtectionExpires = license.GetDaysUntilUpgradeProtectionExpires(),
WarnUserUpgradeProtectionHasExpired = licenseStatus is LicenseStatus.ValidWithExpiredUpgradeProtection or LicenseStatus.InvalidDueToExpiredUpgradeProtection,
WarnUserTrialIsExpiring = licenseStatus == LicenseStatus.ValidWithExpiringTrial,
WarnUserSubscriptionIsExpiring = licenseStatus == LicenseStatus.ValidWithExpiringSubscription,
WarnUserUpgradeProtectionIsExpiring = licenseStatus == LicenseStatus.ValidWithExpiringUpgradeProtection,
WarnUserTrialHasExpired = licenseStatus == LicenseStatus.InvalidDueToExpiredTrial,
WarnUserSubscriptionHasExpired = licenseStatus == LicenseStatus.InvalidDueToExpiredSubscription,
Status = licenseStatus.ToString()
};

switch (license.GetLicenseStatus())
{
case LicenseStatus.Valid:
break;
case LicenseStatus.ValidWithExpiredUpgradeProtection:
details.WarnUserUpgradeProtectionHasExpired = true;
break;
case LicenseStatus.ValidWithExpiringTrial:
details.WarnUserTrialIsExpiring = true;
break;
case LicenseStatus.ValidWithExpiringSubscription:
details.WarnUserSubscriptionIsExpiring = true;
break;
case LicenseStatus.ValidWithExpiringUpgradeProtection:
details.WarnUserUpgradeProtectionIsExpiring = true;
break;
case LicenseStatus.InvalidDueToExpiredTrial:
details.WarnUserTrialHasExpired = true;
break;
case LicenseStatus.InvalidDueToExpiredSubscription:
details.WarnUserSubscriptionHasExpired = true;
break;
case LicenseStatus.InvalidDueToExpiredUpgradeProtection:
details.WarnUserUpgradeProtectionHasExpired = true;
break;
default:
throw new ArgumentOutOfRangeException();
}


return details;
}

public bool HasLicenseExpired()
{
return ExpirationDate.HasValue && HasLicenseDateExpired(ExpirationDate.Value);
}
public bool HasLicenseExpired() => ExpirationDate.HasValue && HasLicenseDateExpired(ExpirationDate.Value);

public bool ReleaseNotCoveredByMaintenance(DateTime buildTimeStamp)
{
return buildTimeStamp > UpgradeProtectionExpiration;
}
public bool ReleaseNotCoveredByMaintenance(DateTime buildTimeStamp) =>
buildTimeStamp > UpgradeProtectionExpiration;

static bool HasLicenseDateExpired(DateTime licenseDate)
{
Expand Down
Expand Up @@ -18,6 +18,7 @@ namespace ServiceControl.Monitoring;
using NServiceBus.Features;
using NServiceBus.Transport;
using QueueLength;
using ServiceControl.Monitoring.Infrastructure.BackgroundTasks;
using Timings;
using Transports;

Expand All @@ -38,7 +39,6 @@ public static class HostApplicationBuilderExtensions

var services = hostBuilder.Services;
services.AddSingleton(settings);
services.AddSingleton<LicenseCheckFeatureStartup>();
services.AddSingleton<EndpointRegistry>();
services.AddSingleton<MessageTypeRegistry>();
services.AddSingleton<EndpointInstanceActivityTracker>();
Expand All @@ -61,11 +61,15 @@ public static class HostApplicationBuilderExtensions
// directly and to make things more complex of course the order of registration still matters ;)
services.AddSingleton(provider => new Lazy<IMessageDispatcher>(provider.GetRequiredService<IMessageDispatcher>));

services.AddLicenseCheck();

ConfigureEndpoint(endpointConfiguration, onCriticalError, transportCustomization, settings);
hostBuilder.UseNServiceBus(endpointConfiguration);

hostBuilder.AddAsyncTimer();
}

internal static void ConfigureEndpoint(EndpointConfiguration config, Func<ICriticalErrorContext, CancellationToken, Task> onCriticalError, ITransportCustomization transportCustomization, Settings settings)
static void ConfigureEndpoint(EndpointConfiguration config, Func<ICriticalErrorContext, CancellationToken, Task> onCriticalError, ITransportCustomization transportCustomization, Settings settings)
{
if (!string.IsNullOrWhiteSpace(settings.LicenseFileText))
{
Expand Down Expand Up @@ -107,8 +111,6 @@ internal static void ConfigureEndpoint(EndpointConfiguration config, Func<ICriti
config.AddDeserializer<TaggedLongValueWriterOccurrenceSerializerDefinition>();
config.Pipeline.Register(typeof(MessagePoolReleasingBehavior), "Releases pooled message.");
config.EnableFeature<QueueLength.QueueLength>();

config.EnableFeature<LicenseCheckFeature>();
}

static Func<QueueLengthStore, IProvideQueueLength> QueueLengthProviderBuilder(string connectionString,
Expand Down
35 changes: 24 additions & 11 deletions src/ServiceControl.Monitoring/Http/LicenseController.cs
@@ -1,38 +1,51 @@
namespace ServiceControl.Monitoring.Http
{
using Licensing;
using Microsoft.AspNetCore.Mvc;
using ServiceControl.Monitoring.Licensing;

[ApiController]
public class LicenseController(LicenseManager licenseManager) : ControllerBase
public class LicenseController(ActiveLicense activeLicense) : ControllerBase
{
[Route("license")]
[HttpGet]
public ActionResult<LicenseInfo> License()
public ActionResult<LicenseInfo> License(bool refresh)
{
licenseManager.Refresh();
if (refresh)
{
activeLicense.Refresh();
}

return new LicenseInfo
var licenseInfo = new LicenseInfo
{
TrialLicense = licenseManager.Details.IsTrialLicense,
Edition = licenseManager.Details.Edition ?? string.Empty,
RegisteredTo = licenseManager.Details.RegisteredTo ?? string.Empty,
UpgradeProtectionExpiration = licenseManager.Details.UpgradeProtectionExpiration?.ToString("O") ?? string.Empty,
ExpirationDate = licenseManager.Details.ExpirationDate?.ToString("O") ?? string.Empty,
Status = licenseManager.IsValid ? "valid" : "invalid"
TrialLicense = activeLicense.Details.IsTrialLicense,
Edition = activeLicense.Details.Edition ?? string.Empty,
RegisteredTo = activeLicense.Details.RegisteredTo ?? string.Empty,
UpgradeProtectionExpiration = activeLicense.Details.UpgradeProtectionExpiration?.ToString("O") ?? string.Empty,
ExpirationDate = activeLicense.Details.ExpirationDate?.ToString("O") ?? string.Empty,
Status = activeLicense.IsValid ? "valid" : "invalid"
};

return licenseInfo;
}

public class LicenseInfo
{
public bool TrialLicense { get; set; }

public string Edition { get; set; }

public string RegisteredTo { get; set; }

public string UpgradeProtectionExpiration { get; set; }

public string ExpirationDate { get; set; }

public string Status { get; set; }

public string LicenseType { get; set; }

public string InstanceName { get; set; }

public string LicenseStatus { get; set; }
}
}
Expand Down
@@ -0,0 +1,12 @@
namespace ServiceControl.Monitoring.Infrastructure.BackgroundTasks
{
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ServiceControl.Infrastructure.BackgroundTasks;

static class AsyncTimerHostBuilderExtensions
{
public static void AddAsyncTimer(this IHostApplicationBuilder hostBuilder) =>
hostBuilder.Services.AddSingleton<IAsyncTimer, AsyncTimer>();
}
}