using H.Pipes; using InABox.Core; using InABox.DynamicGrid; using InABox.Wpf.Editors; using InABox.WPF; using PRSServices; using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Timers; using System.Windows; using InABox.Clients; using InABox.Rpc; using PRSServer; using Comal.Classes; using InABox.Wpf; using Microsoft.Win32; using PRS.Shared; namespace PRSLicensing; public class LicenseEditData : BaseObject { [EditorSequence(1)] public CustomerLink Customer { get; set; } [EditorSequence(2)] public DateTime ExpiryDate { get; set; } [EditorSequence(3)] public bool IsDynamic { get; set; } } /// /// Interaction logic for MainWindow.xaml /// public partial class Console : Window, INotifyPropertyChanged { private LicensingConfiguration Settings { get; set; } private Timer timer; public event PropertyChangedEventHandler? PropertyChanged; private bool _isRunning = false; public bool IsRunning { get => _isRunning; set { _isRunning = value; OnPropertyChanged(); } } private bool _isInstalled = false; public bool IsInstalled { get => _isInstalled; set { _isInstalled = value; OnPropertyChanged(); } } private bool _hasDbServer = false; public bool HasDbServer { get => _hasDbServer; set { _hasDbServer = value; OnPropertyChanged(); } } private PipeClient? _client; private Timer? RefreshTimer; public Console() { InitializeComponent(); LoadSettings(); Progress.DisplayImage = PRSLicensing.Resources.splash_small.AsBitmapImage(); timer = new Timer(2000); timer.Elapsed += Timer_Elapsed; timer.AutoReset = true; timer.Start(); } private string GetUpdateLocation() => "https://prsdigital.com.au/updates/prs"; private string GetLatestVersion(string location) => Update.GetRemoteFile($"{location}/PreRelease/version.txt").Content; private string GetReleaseNotes(string location)=> Update.GetRemoteFile($"{location}/Release Notes.txt").Content; private void Window_Loaded(object sender, RoutedEventArgs e) { Title = Title = $"PRS Licensing (Release {CoreUtils.GetVersion()})"; var isUpdateAvailable = Update.CheckForUpdates( GetUpdateLocation, GetLatestVersion, GetReleaseNotes, null, null, false, ""); RefreshStatus(); Progress.ShowModal("Registering Classes", progress => { var tasks = new Task[] { Task.Run(() => CoreUtils.RegisterClasses()), Task.Run(() => ComalUtils.RegisterClasses()), Task.Run(() => DynamicGridUtils.RegisterClasses()), }; Task.WaitAll(tasks.ToArray()); }); } private void Timer_Elapsed(object? sender, ElapsedEventArgs e) { RefreshStatus(); } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); _client?.DisposeAsync().AsTask().Wait(); _client = null; RefreshTimer?.Stop(); } private void RefreshStatus() { IsRunning = PRSServiceInstaller.IsRunning(Settings.GetServiceName()); IsInstalled = PRSServiceInstaller.IsInstalled(Settings.GetServiceName()); HasDbServer = !String.IsNullOrWhiteSpace(GetProperties().Server); if(_client is null) { if (IsRunning) { CreateClient(); } } else if(_client.PipeName != GetPipeName()) { _client.DisposeAsync().AsTask().Wait(); _client = null; CreateClient(); } } private bool _creatingClient = false; private void CreateClient() { if (_creatingClient) return; _creatingClient = true; var client = new PipeClient(GetPipeName(), "."); client.MessageReceived += (o, args) => { Dispatcher.BeginInvoke(() => { ConsoleControl.LoadLogEntry(args.Message ?? ""); }); }; client.Connected += (o, args) => { Dispatcher.BeginInvoke(() => { ConsoleControl.Enabled = true; }); }; client.Disconnected += (o, args) => { Dispatcher.BeginInvoke(() => { ConsoleControl.Enabled = false; }); if (RefreshTimer == null) { RefreshTimer = new Timer(1000); RefreshTimer.Elapsed += RefreshTimer_Elapsed; } RefreshTimer.Start(); }; client.ExceptionOccurred += (o, args) => { }; if (!client.IsConnecting) { client.ConnectAsync(); } _client = client; _creatingClient = false; } private void RefreshTimer_Elapsed(object? sender, ElapsedEventArgs e) { if (_client is null) return; if (!_client.IsConnected) { if (!_client.IsConnecting) { _client.ConnectAsync(); } } else { RefreshTimer?.Stop(); } } private string GetPipeName() { return Settings.GetServiceName(); } private void LoadSettings() { Settings = PRSLicensingService.GetConfiguration().Load(); ServiceName.Content = Settings.ServiceName; } private void SaveSettings() { PRSLicensingService.GetConfiguration().Save(Settings); } private void Install() { var username = GetProperties().Username; string? password = null; if (!string.IsNullOrWhiteSpace(username)) { var passwordEditor = new PasswordDialog(string.Format("Enter password for {0}", username)); if(passwordEditor.ShowDialog() == true) { password = passwordEditor.Password; } else { password = null; } } else { username = null; } PRSServiceInstaller.InstallService( Settings.GetServiceName(), "PRS Licensing Service", Settings.ServiceName, username, password); } private void InstallButton_Click(object sender, RoutedEventArgs e) { if (PRSServiceInstaller.IsInstalled(Settings.GetServiceName())) { Progress.ShowModal("Uninstalling Service", (progress) => { PRSServiceInstaller.UninstallService(Settings.GetServiceName()); }); } else { Progress.ShowModal("Installing Service", (progress) => { Install(); }); } RefreshStatus(); } private void StartButton_Click(object sender, RoutedEventArgs e) { if (PRSServiceInstaller.IsRunning(Settings.GetServiceName())) { Progress.ShowModal("Stopping Service", (progress) => { PRSServiceInstaller.StopService(Settings.GetServiceName()); }); } else { Progress.ShowModal("Starting Service", (progress) => { PRSServiceInstaller.StartService(Settings.GetServiceName()); }); } RefreshStatus(); } private LicensingEngineProperties GetProperties() { var properties = Serialization.Deserialize(Settings.Properties) ?? new LicensingEngineProperties(); properties.Name = Settings.ServiceName; var tokens = CoreUtils.TypeList(x =>x.IsSubclassOf(typeof(LicenseToken))) .OrderBy(x => x.EntityName().Split('.').Last()) .ToArray(); foreach (var token in tokens) { if (!properties.Mappings.Any(x => String.Equals(x.License, token.EntityName()))) properties.Mappings.Add(new LicenseProductMapping() { License = token.EntityName() }); } return properties; } private bool CheckConnection() { var properties = GetProperties(); if (!String.IsNullOrWhiteSpace(properties.Server)) { ClientFactory.SetClientType( typeof(RpcClient<>), Platform.LicensingEngine, CoreUtils.GetVersion(), new RpcClientPipeTransport(DatabaseServerProperties.GetPipeName(properties.Server, true)) ); if (Client.Ping()) { ClientFactory.SetBypass(); return true; } } return false; } private void EditButton_Click(object sender, RoutedEventArgs e) { var grid = new DynamicItemsListGrid(); grid.OnEditorLoaded += (editor, items) => { var control = editor.FindEditor(nameof(LicensingEngineProperties.Mappings)) as ButtonEditorControl; if (control != null) { control.OnClick += (o, args) => { DynamicItemsListGrid mappinggrid = new DynamicItemsListGrid(); mappinggrid.Items = items.First().Mappings; DynamicGridUtils.CreateGridWindow("License Mappings", mappinggrid).ShowDialog(); }; } }; Settings.CommitChanges(); var properties = GetProperties(); CheckConnection(); if(grid.EditItems(new LicensingEngineProperties[] { properties })) { Settings.Properties = Serialization.Serialize(properties); Settings.ServiceName = properties.Name; if (Settings.IsChanged()) { if(Settings.HasOriginalValue(x => x.ServiceName) || properties.HasOriginalValue(x => x.Username)) { var oldService = LicensingConfiguration.GetServiceName(Settings.GetOriginalValue(x => x.ServiceName)); if (PRSServiceInstaller.IsInstalled(oldService)) { Progress.ShowModal("Modifying Service", (progress) => { PRSServiceInstaller.UninstallService(oldService); Install(); }); } } SaveSettings(); ServiceName.Content = Settings.ServiceName; RefreshStatus(); } } } protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void GenerateButton_Click(object sender, RoutedEventArgs e) { if (!CheckConnection()) { MessageWindow.ShowMessage("Unable to connect to Server", "Error"); return; } var ofd = new OpenFileDialog() { FileName = "license.request", Filter = "Request Files (*.request)|*.request" }; if (ofd.ShowDialog() == true && System.IO.File.Exists(ofd.FileName)) { var text = System.IO.File.ReadAllText(ofd.FileName); if (LicenseUtils.TryDecryptLicenseRequest(text, out var request, out var _)) { var data = new LicenseEditData(); data.Customer.ID = request.CustomerID; data.IsDynamic = request.IsDynamic; var grid = new DynamicItemsListGrid(); grid.OnValidate += (o, items, errors) => { if (items.Any(x => x.Customer.ID == Guid.Empty)) errors.Add("Customer may not be blank!"); if (items.Any(x => x.ExpiryDate <= DateTime.Today)) errors.Add("Expiry must be in the future!"); }; if (grid.EditItems(new LicenseEditData[] { data })) { var license = new LicenseData() { CustomerID = data.Customer.ID, Expiry = data.ExpiryDate, RenewalAvailable = data.ExpiryDate.AddMonths(-1), LastRenewal = DateTime.Today, Addresses = request.Addresses, IsDynamic = data.IsDynamic }; SaveFileDialog sfd = new SaveFileDialog() { FileName = "license.key" }; if (sfd.ShowDialog() == true) File.WriteAllText(sfd.FileName, LicenseUtils.EncryptLicense(license)); } } else MessageWindow.ShowMessage("Invalid Request File","Error"); } } }