From dbf7a69fd0746fff466bedb2288955b2d2f01607 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier - ROG Date: Fri, 16 Apr 2021 11:48:48 +0100 Subject: [PATCH] Screens for Config Editing --- DesktopEdge/App.xaml | 303 +++++- DesktopEdge/MainWindow.xaml.cs | 12 +- DesktopEdge/Views/Screens/MainMenu.xaml | 89 +- DesktopEdge/Views/Screens/MainMenu.xaml.cs | 1071 +++++++++++--------- 4 files changed, 962 insertions(+), 513 deletions(-) diff --git a/DesktopEdge/App.xaml b/DesktopEdge/App.xaml index bcd9158d..356176f8 100644 --- a/DesktopEdge/App.xaml +++ b/DesktopEdge/App.xaml @@ -1,7 +1,8 @@ - @@ -18,7 +19,7 @@ - + @@ -33,7 +34,7 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index c67c738d..0c1ddef9 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -156,6 +156,11 @@ namespace ZitiDesktopEdge { this.ShowMFA(identity, 1); } + /// + /// Show MFA for the identity and set the type of screen to show + /// + /// The Identity that is currently active + /// The type of screen to show - 1 Setup, 2 Authenticate, 3 Remove MFA, 4 Regenerate Codes private void ShowMFA(ZitiIdentity identity, int type) { MFASetup.Opacity = 0; MFASetup.Visibility = Visibility.Visible; @@ -503,6 +508,7 @@ namespace ZitiDesktopEdge { Application.Current.Properties.Add("Identities", new List()); MainMenu.OnAttachmentChange += AttachmentChanged; MainMenu.OnLogLevelChanged += LogLevelChanged; + MainMenu.OnShowBlurb += MainMenu_OnShowBlurb; IdentityMenu.OnError += IdentityMenu_OnError; try { @@ -524,7 +530,11 @@ namespace ZitiDesktopEdge { Placement(); } - private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) { + private void MainMenu_OnShowBlurb(string message) { + _ = ShowBlurbAsync(message, ""); + } + + private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) { var found = identities.Find(id => id.Fingerprint == e.Fingerprint); if (found == null) { logger.Warn($"{e.Action} service event for {e.Fingerprint} but the provided identity fingerprint was not found!"); diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index 0961caf4..b3c566a2 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -7,6 +7,7 @@ mc:Ignorable="d" x:Name="MainMenuArea" d:DesignHeight="400" d:DesignWidth="400" Margin="1,1,1,1"> + @@ -93,21 +94,7 @@ - - - - - - - - - + @@ -124,5 +111,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index d85a9b7a..58ddab5d 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -1,489 +1,586 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Diagnostics; -using System; -using System.Reflection; -using System.Net.Mail; -using System.IO; -using NLog; - -using ZitiDesktopEdge.Models; -using ZitiDesktopEdge.DataStructures; -using ZitiDesktopEdge.ServiceClient; -using System.Configuration; - -namespace ZitiDesktopEdge { - /// - /// Interaction logic for MainMenu.xaml - /// - public partial class MainMenu : UserControl { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public delegate void AttachementChanged(bool attached); - public event AttachementChanged OnAttachmentChange; - public delegate void LogLevelChanged(string level); - public event LogLevelChanged OnLogLevelChanged; - public delegate void Detched(MouseButtonEventArgs e); - public event Detched OnDetach; - public string menuState = "Main"; - public string licenseData = "it's open source."; - public string LogLevel = ""; - private string appVersion = null; - private bool allowReleaseSelect = false; - public double MainHeight = 500; - - private bool isBeta { - get { - return Application.Current.Properties["ReleaseStream"]?.ToString() == "beta"; - } - } - - internal MainWindow MainWindow { get; set; } - - public MainMenu() { - InitializeComponent(); - Application.Current.MainWindow.Title = "Ziti Desktop Edge"; - - try { - allowReleaseSelect = bool.Parse(ConfigurationManager.AppSettings.Get("ReleaseStreamSelect")); - } catch { - //if we can't parse the config - leave it as false... - allowReleaseSelect = false; //setting it here in case anyone changes the default above - } -#if DEBUG - Debug.WriteLine("OVERRIDING allowReleaseSelect to true!"); - allowReleaseSelect = true; -#endif - appVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - LicensesItems.Text = licenseData; - // don't check from the UI any more... CheckUpdates(); - } - - private void HideMenu(object sender, MouseButtonEventArgs e) { - menuState = "Menu"; - UpdateState(); - MainMenuArea.Visibility = Visibility.Collapsed; - } - private void Window_MouseDown(object sender, MouseButtonEventArgs e) { - if (e.ChangedButton == MouseButton.Left) { - OnDetach(e); - } - } - - private void CloseApp(object sender, MouseButtonEventArgs e) { - Application.Current.Shutdown(); - } - - private void ShowAbout(object sender, MouseButtonEventArgs e) { - menuState = "About"; - UpdateState(); - } - - private void ShowAdvanced(object sender, MouseButtonEventArgs e) { - menuState = "Advanced"; - UpdateState(); - } - private void ShowIdentities(object sender, MouseButtonEventArgs e) { - menuState = "Identities"; - UpdateState(); - } - private void ShowLicenses(object sender, MouseButtonEventArgs e) { - menuState = "Licenses"; - UpdateState(); - } - private void ShowConfig(object sender, MouseButtonEventArgs e) { - menuState = "Config"; - UpdateState(); - } - private void ShowLogs(object sender, MouseButtonEventArgs e) { - menuState = "Logs"; - UpdateState(); - } - private void ShowUILogs(object sender, MouseButtonEventArgs e) { - menuState = "UILogs"; - UpdateState(); - } - private void ShowReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { - logger.Warn("this is ShowReleaseStreamMenuAction at warn"); - logger.Info("this is ShowReleaseStreamMenuAction at info"); - logger.Debug("this is ShowReleaseStreamMenuAction at debug"); - logger.Trace("this is ShowReleaseStreamMenuAction at trace"); - menuState = "SetReleaseStream"; - UpdateState(); - } - - async private void SetReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { - CheckForUpdateStatus.Visibility = Visibility.Collapsed; - TriggerUpdateButton.Visibility = Visibility.Collapsed; - SubOptionItem opt = (SubOptionItem)sender; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - menuState = "SetReleaseStream"; - - bool releaseClicked = opt.Label.ToLower() == "stable"; - - if (releaseClicked) { - if (isBeta) { - //toggle to stable - var r = await monitorClient.SetReleaseStreamAsync("stable"); - checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); - } else { - logger.Debug("stable clicked but already on stable stream"); - } - } else { - if (!isBeta) { - //toggle to beta - var r = await monitorClient.SetReleaseStreamAsync("beta"); - checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); - } else { - logger.Debug("beta clicked but already on beta stream"); - } - } - Application.Current.Properties["ReleaseStream"] = opt.Label.ToLower(); - UpdateState(); - } - - private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { - if (r == null) { - MainWindow.ShowError(titleOnErr, msgOnErr); - } else { - logger.Info(r?.ToString()); - } - } - - private void SetLogLevel(object sender, MouseButtonEventArgs e) { - menuState = "LogLevel"; - UpdateState(); - } - - private void UpdateState() { - IdListScrollView.Height = this.ActualHeight-100.00; - IdListScrollView.Visibility = Visibility.Collapsed; - MainItems.Visibility = Visibility.Collapsed; - AboutItems.Visibility = Visibility.Collapsed; - MainItemsButton.Visibility = Visibility.Collapsed; - AboutItemsArea.Visibility = Visibility.Collapsed; - BackArrow.Visibility = Visibility.Collapsed; - AdvancedItems.Visibility = Visibility.Collapsed; - LicensesItems.Visibility = Visibility.Collapsed; - LogsItems.Visibility = Visibility.Collapsed; - ConfigItems.Visibility = Visibility.Collapsed; - LogLevelItems.Visibility = Visibility.Collapsed; - ReleaseStreamItems.Visibility = Visibility.Collapsed; - - if (menuState == "About") { - MenuTitle.Content = "About"; - AboutItemsArea.Visibility = Visibility.Visible; - AboutItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - - string version = ""; - try { - TunnelStatus s = (TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; - version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}"; - } catch (Exception e) { - logger.Warn(e, "Could not get service version/revision?"); - } - - // Interface Version - VersionInfo.Content = $"App: {appVersion} Service: {version}"; - - } else if (menuState == "Advanced") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - ShowReleaseStreamMenuItem.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; - } else if (menuState == "Licenses") { - MenuTitle.Content = "Third Party Licenses"; - LicensesItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "Logs") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - //string targetFile = NativeMethods.GetFinalPathName(MainWindow.ExpectedLogPathServices); - string targetFile = MainWindow.ExpectedLogPathServices; - - OpenLogFile("service", targetFile); - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "UILogs") { - MenuTitle.Content = "Advanced Settings"; - AdvancedItems.Visibility = Visibility.Visible; - OpenLogFile("UI", MainWindow.ExpectedLogPathUI); - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "LogLevel") { - ResetLevels(); - - MenuTitle.Content = "Set Log Level"; - LogLevelItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "SetReleaseStream") { - SetReleaseStream(); - - MenuTitle.Content = "Set Release Stream"; - ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; - BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "Config") { - MenuTitle.Content = "Tunnel Configuration"; - ConfigItems.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - - ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); - ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); - ConfigMtu.Value = Application.Current.Properties["mtu"]?.ToString(); - ConfigDns.Value = (bool)Application.Current.Properties["dnsenabled"] ? Application.Current.Properties["dns"]?.ToString() : "disabled"; - } else if (menuState == "Identities") { - MenuTitle.Content = "Identities"; - IdListScrollView.Visibility = Visibility.Visible; - BackArrow.Visibility = Visibility.Visible; - } else { - MenuTitle.Content = "Main Menu"; - MainItems.Visibility = Visibility.Visible; - MainItemsButton.Visibility = Visibility.Visible; - ReleaseStreamItems.Visibility = Visibility.Collapsed; - } - } - - private void OpenLogFile(string which, string logFile) { - var whichRoot = Path.Combine(MainWindow.ExpectedLogPathRoot, which); - try { - string target = Native.NativeMethods.GetFinalPathName(logFile); - if (File.Exists(target)) { - logger.Info("opening {0} logs at: {1}", which, target); - var p = Process.Start(new ProcessStartInfo(target) { UseShellExecute = true }); - if (p != null) { - logger.Info("showing {0} logs. file: {1}", which, target); - } else { - Process.Start(whichRoot); - } - return; - } else { - logger.Warn("could not show {0} logs. file not found: {1}", which, target); - } - } catch { - } - Process.Start(whichRoot); - } - - private void GoBack(object sender, MouseButtonEventArgs e) { - if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream") { - menuState = "Advanced"; - } else if (menuState == "Licenses") { - menuState = "About"; - } else { - menuState = "Menu"; - } - UpdateState(); - } - private void ShowPrivacy(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://netfoundry.io/privacy") { UseShellExecute = true }); - } - private void ShowTerms(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://netfoundry.io/terms") { UseShellExecute = true }); - } - - async private void ShowFeedback(object sender, MouseButtonEventArgs e) { - try { - MainWindow.ShowLoad("Collecting Information", "Please wait while we run some commands\nand collect some diagnostic information"); - var mailMessage = new MailMessage("help@openziti.org", "help@openziti.org"); - mailMessage.Subject = "Ziti Support"; - mailMessage.IsBodyHtml = false; - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - sb.Append("Logs collected at : " + DateTime.Now.ToString()); - sb.Append(". client version : " + appVersion); - - mailMessage.Body = sb.ToString(); - - string timestamp = DateTime.Now.ToFileTime().ToString(); - - var dataClient = (DataClient)Application.Current.Properties["ServiceClient"]; - await dataClient.zitiDump(); - - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - MonitorServiceStatusEvent resp = await monitorClient.CaptureLogsAsync(); - if (resp == null) { - logger.Error("no response from monitorClient?"); - MainWindow mw = (MainWindow)Application.Current.MainWindow; - mw?.ShowError("Error Collecting Feedback", "An error occurred while trying to gather feedback.\nIs the monitor service running?"); - return; - } - string pathToLogs = resp.Message; - logger.Info("Log files found at : {0}", resp.Message); - mailMessage.Attachments.Add(new Attachment(pathToLogs)); - - string emlFile = Path.Combine(Path.GetTempPath(), timestamp + "-ziti.eml"); - - using (var filestream = File.Open(emlFile, FileMode.Create)) { - var binaryWriter = new BinaryWriter(filestream); - binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine)); - var assembly = typeof(SmtpClient).Assembly; - var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); - var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null); - var mailWriter = mailWriterContructor.Invoke(new object[] { filestream }); - var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic); - sendMethod.Invoke(mailMessage, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null); - var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); - closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null); - } - var p = Process.Start(emlFile); - if (p != null) { - p.Exited += (object lambdaSender, EventArgs lambdaEventArgs) => { - logger.Info("Removing temp file: {0}", emlFile); - File.Delete(emlFile); - }; - p.EnableRaisingEvents = true; - } else { - logger.Debug("process was null. most likely the email file format was not known when the process tried to start"); - } - } catch (Exception ex) { - logger.Warn(ex, "An unexpected error has occurred when submitting feedback? {0}", ex.Message); - } - MainWindow.HideLoad(); - } - - private void ShowSupport(object sender, MouseButtonEventArgs e) { - Process.Start(new ProcessStartInfo("https://openziti.discourse.group/") { UseShellExecute = true }); - } - - private void DetachWindow(object sender, MouseButtonEventArgs e) { - Application.Current.MainWindow.ShowInTaskbar = true; - DetachButton.Visibility = Visibility.Collapsed; - AttachButton.Visibility = Visibility.Visible; - Arrow.Visibility = Visibility.Collapsed; - if (OnAttachmentChange != null) { - OnAttachmentChange(false); - } - MainMenuArea.Visibility = Visibility.Collapsed; - } - - public void Detach() { - Application.Current.MainWindow.ShowInTaskbar = true; - DetachButton.Visibility = Visibility.Collapsed; - AttachButton.Visibility = Visibility.Visible; - Arrow.Visibility = Visibility.Collapsed; - } - private void RetachWindow(object sender, MouseButtonEventArgs e) { - Application.Current.MainWindow.ShowInTaskbar = false; - DetachButton.Visibility = Visibility.Visible; - AttachButton.Visibility = Visibility.Collapsed; - Arrow.Visibility = Visibility.Visible; - if (OnAttachmentChange != null) { - OnAttachmentChange(true); - } - } - - private void ResetLevels() { - if (this.LogLevel == "") this.LogLevel = "error"; - LogVerbose.IsSelected = false; - LogDebug.IsSelected = false; - LogInfo.IsSelected = false; - LogError.IsSelected = false; - LogFatal.IsSelected = false; - LogWarn.IsSelected = false; - LogTrace.IsSelected = false; - if (this.LogLevel == "verbose") LogVerbose.IsSelected = true; - else if (this.LogLevel == "debug") LogDebug.IsSelected = true; - else if (this.LogLevel == "info") LogInfo.IsSelected = true; - else if (this.LogLevel == "error") LogError.IsSelected = true; - else if (this.LogLevel == "fatal") LogFatal.IsSelected = true; - else if (this.LogLevel == "warn") LogWarn.IsSelected = true; - else if (this.LogLevel == "trace") LogTrace.IsSelected = true; - } - - private void SetLevel(object sender, MouseButtonEventArgs e) { - SubOptionItem item = (SubOptionItem)sender; - this.LogLevel = item.Label.ToLower(); - if (OnLogLevelChanged != null) { - OnLogLevelChanged(this.LogLevel); - } - ResetLevels(); - } - - private void SetReleaseStream() { - this.ReleaseStreamItemBeta.IsSelected = isBeta; - this.ReleaseStreamItemStable.IsSelected = !isBeta; - } - - async private void CheckForUpdate_Click(object sender, RoutedEventArgs e) { - logger.Info("checking for update..."); - try { - CheckForUpdate.IsEnabled = false; - CheckForUpdateStatus.Content = "Checking for update..."; - CheckForUpdateStatus.Visibility = Visibility.Visible; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - var r = await monitorClient.DoUpdateCheck(); - checkResponse(r, "Error When Checking for Update", "An error occurred while trying check for update."); - CheckForUpdateStatus.Content = r.Message; - if (r.UpdateAvailable) { - TriggerUpdateButton.Visibility = Visibility.Visible; - } else { - TriggerUpdateButton.Visibility = Visibility.Collapsed; - } - } catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - CheckForUpdate.IsEnabled = true; - } - - async private void UpdateConfig_Click(object sender, RoutedEventArgs e) { - logger.Info("updating config..."); - DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; - try { - var newMaskVar = Int32.Parse(ConfigMaskNew.Text); - var addDnsNewVar = Convert.ToBoolean(AddDnsNew.Text); - - var r = await client.UpdateConfigAsync(ConfigIpNew.Text, newMaskVar, addDnsNewVar); - logger.Info("Got response from update config task : {0}", r); - } catch (DataStructures.ServiceException se) { - logger.Error(se, "service exception in update check: {0}", se.Message); +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Diagnostics; +using System; +using System.Reflection; +using System.Net.Mail; +using System.IO; +using NLog; +using System.Windows.Media.Animation; + +using ZitiDesktopEdge.Models; +using ZitiDesktopEdge.DataStructures; +using ZitiDesktopEdge.ServiceClient; +using System.Configuration; + +namespace ZitiDesktopEdge { + /// + /// Interaction logic for MainMenu.xaml + /// + public partial class MainMenu : UserControl { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + public delegate void AttachementChanged(bool attached); + public event AttachementChanged OnAttachmentChange; + public delegate void LogLevelChanged(string level); + public event LogLevelChanged OnLogLevelChanged; + public delegate void Detched(MouseButtonEventArgs e); + public event Detched OnDetach; + public delegate void ShowBlurb(string message); + public event ShowBlurb OnShowBlurb; + public string menuState = "Main"; + public string licenseData = "it's open source."; + public string LogLevel = ""; + private string appVersion = null; + private bool allowReleaseSelect = false; + public double MainHeight = 500; + + private bool isBeta { + get { + return Application.Current.Properties["ReleaseStream"]?.ToString() == "beta"; } - catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - } - - async private void TriggerUpdate_Click(object sender, RoutedEventArgs e) { - try { - CheckForUpdate.IsEnabled = false; - TriggerUpdateButton.IsEnabled = false; - CheckForUpdateStatus.Content = "Requesting automatic update..."; - var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; - var r = await monitorClient.TriggerUpdate(); - CheckForUpdateStatus.Content = "Automatic update requested..."; - checkResponse(r, "Error When Triggering Update", "An error occurred while trying to trigger the update."); - } catch (Exception ex) { - logger.Error(ex, "unexpected error in update check: {0}", ex.Message); - } - TriggerUpdateButton.IsEnabled = true; - CheckForUpdate.IsEnabled = true; - } - - public void SetupIdList(ZitiIdentity[] ids) { - IdListView.Children.Clear(); - for (int i=0; i { - VersionOlder.Content = msg; - VersionNewer.Content = ""; - VersionOlder.Visibility = Visibility.Visible; - VersionNewer.Visibility = Visibility.Collapsed; - }); - } - public void SetAppIsNewer(string msg) { - this.Dispatcher.Invoke(() => { - VersionNewer.Content = msg; - VersionOlder.Content = ""; - VersionNewer.Visibility = Visibility.Visible; - VersionOlder.Visibility = Visibility.Collapsed; - }); - } - } + } + + internal MainWindow MainWindow { get; set; } + + public MainMenu() { + InitializeComponent(); + Application.Current.MainWindow.Title = "Ziti Desktop Edge"; + + try { + allowReleaseSelect = bool.Parse(ConfigurationManager.AppSettings.Get("ReleaseStreamSelect")); + } catch { + //if we can't parse the config - leave it as false... + allowReleaseSelect = false; //setting it here in case anyone changes the default above + } +#if DEBUG + Debug.WriteLine("OVERRIDING allowReleaseSelect to true!"); + allowReleaseSelect = true; +#endif + appVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + LicensesItems.Text = licenseData; + // don't check from the UI any more... CheckUpdates(); + } + + private void HideMenu(object sender, MouseButtonEventArgs e) { + menuState = "Menu"; + UpdateState(); + MainMenuArea.Visibility = Visibility.Collapsed; + } + private void Window_MouseDown(object sender, MouseButtonEventArgs e) { + if (e.ChangedButton == MouseButton.Left) { + OnDetach(e); + } + } + + private void CloseApp(object sender, MouseButtonEventArgs e) { + Application.Current.Shutdown(); + } + + private void ShowAbout(object sender, MouseButtonEventArgs e) { + menuState = "About"; + UpdateState(); + } + + private void ShowAdvanced(object sender, MouseButtonEventArgs e) { + menuState = "Advanced"; + UpdateState(); + } + private void ShowIdentities(object sender, MouseButtonEventArgs e) { + menuState = "Identities"; + UpdateState(); + } + private void ShowLicenses(object sender, MouseButtonEventArgs e) { + menuState = "Licenses"; + UpdateState(); + } + private void ShowConfig(object sender, MouseButtonEventArgs e) { + menuState = "Config"; + UpdateState(); + } + private void ShowLogs(object sender, MouseButtonEventArgs e) { + menuState = "Logs"; + UpdateState(); + } + private void ShowUILogs(object sender, MouseButtonEventArgs e) { + menuState = "UILogs"; + UpdateState(); + } + private void ShowReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { + logger.Warn("this is ShowReleaseStreamMenuAction at warn"); + logger.Info("this is ShowReleaseStreamMenuAction at info"); + logger.Debug("this is ShowReleaseStreamMenuAction at debug"); + logger.Trace("this is ShowReleaseStreamMenuAction at trace"); + menuState = "SetReleaseStream"; + UpdateState(); + } + + async private void SetReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { + CheckForUpdateStatus.Visibility = Visibility.Collapsed; + TriggerUpdateButton.Visibility = Visibility.Collapsed; + SubOptionItem opt = (SubOptionItem)sender; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + menuState = "SetReleaseStream"; + + bool releaseClicked = opt.Label.ToLower() == "stable"; + + if (releaseClicked) { + if (isBeta) { + //toggle to stable + var r = await monitorClient.SetReleaseStreamAsync("stable"); + checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); + } else { + logger.Debug("stable clicked but already on stable stream"); + } + } else { + if (!isBeta) { + //toggle to beta + var r = await monitorClient.SetReleaseStreamAsync("beta"); + checkResponse(r, "Error When Setting Release Stream", "An error occurred while trying to set the release stream."); + } else { + logger.Debug("beta clicked but already on beta stream"); + } + } + Application.Current.Properties["ReleaseStream"] = opt.Label.ToLower(); + UpdateState(); + } + + private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { + if (r == null) { + MainWindow.ShowError(titleOnErr, msgOnErr); + } else { + logger.Info(r?.ToString()); + } + } + + private void SetLogLevel(object sender, MouseButtonEventArgs e) { + menuState = "LogLevel"; + UpdateState(); + } + + private void UpdateState() { + IdListScrollView.Height = this.ActualHeight-100.00; + IdListScrollView.Visibility = Visibility.Collapsed; + MainItems.Visibility = Visibility.Collapsed; + AboutItems.Visibility = Visibility.Collapsed; + MainItemsButton.Visibility = Visibility.Collapsed; + AboutItemsArea.Visibility = Visibility.Collapsed; + BackArrow.Visibility = Visibility.Collapsed; + AdvancedItems.Visibility = Visibility.Collapsed; + LicensesItems.Visibility = Visibility.Collapsed; + LogsItems.Visibility = Visibility.Collapsed; + ConfigItems.Visibility = Visibility.Collapsed; + LogLevelItems.Visibility = Visibility.Collapsed; + ReleaseStreamItems.Visibility = Visibility.Collapsed; + + if (menuState == "About") { + MenuTitle.Content = "About"; + AboutItemsArea.Visibility = Visibility.Visible; + AboutItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + + string version = ""; + try { + TunnelStatus s = (TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"]; + version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}"; + } catch (Exception e) { + logger.Warn(e, "Could not get service version/revision?"); + } + + // Interface Version + VersionInfo.Content = $"App: {appVersion} Service: {version}"; + + } else if (menuState == "Advanced") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + ShowReleaseStreamMenuItem.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; + } else if (menuState == "Licenses") { + MenuTitle.Content = "Third Party Licenses"; + LicensesItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "Logs") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + //string targetFile = NativeMethods.GetFinalPathName(MainWindow.ExpectedLogPathServices); + string targetFile = MainWindow.ExpectedLogPathServices; + + OpenLogFile("service", targetFile); + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "UILogs") { + MenuTitle.Content = "Advanced Settings"; + AdvancedItems.Visibility = Visibility.Visible; + OpenLogFile("UI", MainWindow.ExpectedLogPathUI); + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "LogLevel") { + ResetLevels(); + + MenuTitle.Content = "Set Log Level"; + LogLevelItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "SetReleaseStream") { + SetReleaseStream(); + + MenuTitle.Content = "Set Release Stream"; + ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; + BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "Config") { + MenuTitle.Content = "Tunnel Configuration"; + ConfigItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + + ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); + ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); + ConfigMtu.Value = Application.Current.Properties["mtu"]?.ToString(); + ConfigDns.Value = (bool)Application.Current.Properties["dnsenabled"] ? Application.Current.Properties["dns"]?.ToString() : "disabled"; + } else if (menuState == "Identities") { + MenuTitle.Content = "Identities"; + IdListScrollView.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; + } else { + MenuTitle.Content = "Main Menu"; + MainItems.Visibility = Visibility.Visible; + MainItemsButton.Visibility = Visibility.Visible; + ReleaseStreamItems.Visibility = Visibility.Collapsed; + } + } + + private void OpenLogFile(string which, string logFile) { + var whichRoot = Path.Combine(MainWindow.ExpectedLogPathRoot, which); + try { + string target = Native.NativeMethods.GetFinalPathName(logFile); + if (File.Exists(target)) { + logger.Info("opening {0} logs at: {1}", which, target); + var p = Process.Start(new ProcessStartInfo(target) { UseShellExecute = true }); + if (p != null) { + logger.Info("showing {0} logs. file: {1}", which, target); + } else { + Process.Start(whichRoot); + } + return; + } else { + logger.Warn("could not show {0} logs. file not found: {1}", which, target); + } + } catch { + } + Process.Start(whichRoot); + } + + private void GoBack(object sender, MouseButtonEventArgs e) { + if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream") { + menuState = "Advanced"; + } else if (menuState == "Licenses") { + menuState = "About"; + } else { + menuState = "Menu"; + } + UpdateState(); + } + private void ShowPrivacy(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://netfoundry.io/privacy") { UseShellExecute = true }); + } + private void ShowTerms(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://netfoundry.io/terms") { UseShellExecute = true }); + } + + async private void ShowFeedback(object sender, MouseButtonEventArgs e) { + try { + MainWindow.ShowLoad("Collecting Information", "Please wait while we run some commands\nand collect some diagnostic information"); + var mailMessage = new MailMessage("help@openziti.org", "help@openziti.org"); + mailMessage.Subject = "Ziti Support"; + mailMessage.IsBodyHtml = false; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append("Logs collected at : " + DateTime.Now.ToString()); + sb.Append(". client version : " + appVersion); + + mailMessage.Body = sb.ToString(); + + string timestamp = DateTime.Now.ToFileTime().ToString(); + + var dataClient = (DataClient)Application.Current.Properties["ServiceClient"]; + await dataClient.zitiDump(); + + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + MonitorServiceStatusEvent resp = await monitorClient.CaptureLogsAsync(); + if (resp == null) { + logger.Error("no response from monitorClient?"); + MainWindow mw = (MainWindow)Application.Current.MainWindow; + mw?.ShowError("Error Collecting Feedback", "An error occurred while trying to gather feedback.\nIs the monitor service running?"); + return; + } + string pathToLogs = resp.Message; + logger.Info("Log files found at : {0}", resp.Message); + mailMessage.Attachments.Add(new Attachment(pathToLogs)); + + string emlFile = Path.Combine(Path.GetTempPath(), timestamp + "-ziti.eml"); + + using (var filestream = File.Open(emlFile, FileMode.Create)) { + var binaryWriter = new BinaryWriter(filestream); + binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine)); + var assembly = typeof(SmtpClient).Assembly; + var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); + var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null); + var mailWriter = mailWriterContructor.Invoke(new object[] { filestream }); + var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic); + sendMethod.Invoke(mailMessage, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null); + var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); + closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null); + } + var p = Process.Start(emlFile); + if (p != null) { + p.Exited += (object lambdaSender, EventArgs lambdaEventArgs) => { + logger.Info("Removing temp file: {0}", emlFile); + File.Delete(emlFile); + }; + p.EnableRaisingEvents = true; + } else { + logger.Debug("process was null. most likely the email file format was not known when the process tried to start"); + } + } catch (Exception ex) { + logger.Warn(ex, "An unexpected error has occurred when submitting feedback? {0}", ex.Message); + } + MainWindow.HideLoad(); + } + + private void ShowSupport(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://openziti.discourse.group/") { UseShellExecute = true }); + } + + private void DetachWindow(object sender, MouseButtonEventArgs e) { + Application.Current.MainWindow.ShowInTaskbar = true; + DetachButton.Visibility = Visibility.Collapsed; + AttachButton.Visibility = Visibility.Visible; + Arrow.Visibility = Visibility.Collapsed; + if (OnAttachmentChange != null) { + OnAttachmentChange(false); + } + MainMenuArea.Visibility = Visibility.Collapsed; + } + + public void Detach() { + Application.Current.MainWindow.ShowInTaskbar = true; + DetachButton.Visibility = Visibility.Collapsed; + AttachButton.Visibility = Visibility.Visible; + Arrow.Visibility = Visibility.Collapsed; + } + private void RetachWindow(object sender, MouseButtonEventArgs e) { + Application.Current.MainWindow.ShowInTaskbar = false; + DetachButton.Visibility = Visibility.Visible; + AttachButton.Visibility = Visibility.Collapsed; + Arrow.Visibility = Visibility.Visible; + if (OnAttachmentChange != null) { + OnAttachmentChange(true); + } + } + + private void ResetLevels() { + if (this.LogLevel == "") this.LogLevel = "error"; + LogVerbose.IsSelected = false; + LogDebug.IsSelected = false; + LogInfo.IsSelected = false; + LogError.IsSelected = false; + LogFatal.IsSelected = false; + LogWarn.IsSelected = false; + LogTrace.IsSelected = false; + if (this.LogLevel == "verbose") LogVerbose.IsSelected = true; + else if (this.LogLevel == "debug") LogDebug.IsSelected = true; + else if (this.LogLevel == "info") LogInfo.IsSelected = true; + else if (this.LogLevel == "error") LogError.IsSelected = true; + else if (this.LogLevel == "fatal") LogFatal.IsSelected = true; + else if (this.LogLevel == "warn") LogWarn.IsSelected = true; + else if (this.LogLevel == "trace") LogTrace.IsSelected = true; + } + + private void SetLevel(object sender, MouseButtonEventArgs e) { + SubOptionItem item = (SubOptionItem)sender; + this.LogLevel = item.Label.ToLower(); + if (OnLogLevelChanged != null) { + OnLogLevelChanged(this.LogLevel); + } + ResetLevels(); + } + + private void SetReleaseStream() { + this.ReleaseStreamItemBeta.IsSelected = isBeta; + this.ReleaseStreamItemStable.IsSelected = !isBeta; + } + + async private void CheckForUpdate_Click(object sender, RoutedEventArgs e) { + logger.Info("checking for update..."); + try { + CheckForUpdate.IsEnabled = false; + CheckForUpdateStatus.Content = "Checking for update..."; + CheckForUpdateStatus.Visibility = Visibility.Visible; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + var r = await monitorClient.DoUpdateCheck(); + checkResponse(r, "Error When Checking for Update", "An error occurred while trying check for update."); + CheckForUpdateStatus.Content = r.Message; + if (r.UpdateAvailable) { + TriggerUpdateButton.Visibility = Visibility.Visible; + } else { + TriggerUpdateButton.Visibility = Visibility.Collapsed; + } + } catch (Exception ex) { + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + CheckForUpdate.IsEnabled = true; + } + + async public void TriggerUpdate_Click(object sender, RoutedEventArgs e) { + try { + CheckForUpdate.IsEnabled = false; + TriggerUpdateButton.IsEnabled = false; + CheckForUpdateStatus.Content = "Requesting automatic update..."; + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + var r = await monitorClient.TriggerUpdate(); + CheckForUpdateStatus.Content = "Automatic update requested..."; + checkResponse(r, "Error When Triggering Update", "An error occurred while trying to trigger the update."); + } catch (Exception ex) { + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + TriggerUpdateButton.IsEnabled = true; + CheckForUpdate.IsEnabled = true; + } + + public void SetupIdList(ZitiIdentity[] ids) { + IdListView.Children.Clear(); + for (int i=0; i { + VersionOlder.Content = msg; + VersionNewer.Content = ""; + VersionOlder.Visibility = Visibility.Visible; + VersionNewer.Visibility = Visibility.Collapsed; + }); + } + public void SetAppIsNewer(string msg) { + this.Dispatcher.Invoke(() => { + VersionNewer.Content = msg; + VersionOlder.Content = ""; + VersionNewer.Visibility = Visibility.Visible; + VersionOlder.Visibility = Visibility.Collapsed; + }); + } + + /// + /// Save the config information to the properties and queue for update. + /// + async private void UpdateConfig() { + logger.Info("updating config..."); + DataClient client = (DataClient)Application.Current.Properties["ServiceClient"]; + try { + ComboBoxItem item = (ComboBoxItem)ConfigMaskNew.SelectedValue; + var newMaskVar = Int32.Parse(item.Tag.ToString()); + var addDnsNewVar = Convert.ToBoolean(AddDnsNew.IsChecked); + + var r = await client.UpdateConfigAsync(ConfigIpNew.Text, newMaskVar, addDnsNewVar); + if (r.Code != 0) { + this.OnShowBlurb?.Invoke("Error: " + r.Error); + logger.Debug("ERROR: {0} : {1}", r.Message, r.Error); + } else { + this.OnShowBlurb?.Invoke("Config Save, Please Restart Ziti to Update"); + this.CloseEdit(); + } + logger.Info("Got response from update config task : {0}", r); + } catch (DataStructures.ServiceException se) { + this.OnShowBlurb?.Invoke("Error: " + se.Message); + logger.Error(se, "service exception in update check: {0}", se.Message); + } catch (Exception ex) { + this.OnShowBlurb?.Invoke("Error: " + ex.Message); + logger.Error(ex, "unexpected error in update check: {0}", ex.Message); + } + } + + /// + /// Show the Edit Modal and blur the background + /// + private void ShowEdit() { + ConfigIpNew.Text = ConfigIp.Value; + for (int i=0; i0) { + ConfigMaskNew.SelectedIndex = i; + break; + } + } + EditArea.Opacity = 0; + EditArea.Visibility = Visibility.Visible; + EditArea.Margin = new Thickness(0, 0, 0, 0); + EditArea.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(1, TimeSpan.FromSeconds(.3))); + EditArea.BeginAnimation(Grid.MarginProperty, new ThicknessAnimation(new Thickness(30, 30, 30, 30), TimeSpan.FromSeconds(.3))); + ShowModal(); + } + + /// + /// Hide the Edit Config + /// + private void CloseEdit() { + DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromSeconds(.3)); + ThicknessAnimation animateThick = new ThicknessAnimation(new Thickness(0, 0, 0, 0), TimeSpan.FromSeconds(.3)); + animation.Completed += CloseComplete; + EditArea.BeginAnimation(Grid.OpacityProperty, animation); + EditArea.BeginAnimation(Grid.MarginProperty, animateThick); + HideModal(); + } + + /// + /// Show the modal, aniimating opacity + /// + private void ShowModal() { + ModalBg.Visibility = Visibility.Visible; + ModalBg.Opacity = 0; + DoubleAnimation animation = new DoubleAnimation(.8, TimeSpan.FromSeconds(.3)); + ModalBg.BeginAnimation(Grid.OpacityProperty, animation); + } + + /// + /// Close the config window + /// + /// The close button + /// The event arguments + private void CloseComplete(object sender, EventArgs e) { + EditArea.Visibility = Visibility.Collapsed; + } + + /// + /// Hide the modal animating the opacity + /// + private void HideModal() { + DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromSeconds(.3)); + animation.Completed += ModalHideComplete; + ModalBg.BeginAnimation(Grid.OpacityProperty, animation); + } + + /// + /// When the animation completes, set the visibility to avoid UI object conflicts + /// + /// The animation + /// The event + private void ModalHideComplete(object sender, EventArgs e) { + ModalBg.Visibility = Visibility.Collapsed; + } + + /// + /// Close the config editor without saving + /// + /// The image button + /// The click event + private void CloseEditConfig(object sender, MouseButtonEventArgs e) { + CloseEdit(); + } + + private void SaveConfig() { + this.UpdateConfig(); + } + } } \ No newline at end of file