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">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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