diff --git a/.github/workflows/installer.build.yml b/.github/workflows/installer.build.yml index be197ad1b..8f49de1d1 100644 --- a/.github/workflows/installer.build.yml +++ b/.github/workflows/installer.build.yml @@ -83,10 +83,15 @@ jobs: ziti_ci_gpg_key_id: ${{ secrets.ZITI_CI_GPG_KEY_ID }} run: powershell -File .\Installer\build.ps1 - name: Upload installer onto job - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ZitiDesktopEdgeClient-${{ env.VERSION }} path: "Installer/Output/Ziti Desktop Edge Client-*" + - name: Upload update json to job + uses: actions/upload-artifact@v2 + with: + name: ZitiDesktopEdgeClient-${{ env.VERSION }} + path: ${{ env.VERSION }}.json - name: Git Status run: git status - name: git diff diff --git a/.gitignore b/.gitignore index 5b54d4eb1..8fb4c2bd1 100644 --- a/.gitignore +++ b/.gitignore @@ -280,5 +280,7 @@ ziti-edge-tunnel/*.dll ziti-edge-tunnel/*.exe ziti-edge-tunnel/*.zip OPENZITI_P12.b64 -Installer/wintun.zip Installer/zet.zip +release-streams/local/* +release-streams/local.json +release-streams/dev.json diff --git a/DesktopEdge/App.xaml.cs b/DesktopEdge/App.xaml.cs index e3da396b7..2d65ffa5b 100644 --- a/DesktopEdge/App.xaml.cs +++ b/DesktopEdge/App.xaml.cs @@ -34,7 +34,6 @@ protected override void OnStartup(StartupEventArgs e) { bool createdNew; - _mutex = new Mutex(true, appName, out createdNew); if (!createdNew) { @@ -59,8 +58,8 @@ protected override void OnStartup(StartupEventArgs e) { #pragma warning disable 4014 //This async method lacks 'await' StartServer(); #pragma warning restore 4014 //This async method lacks 'await' - } - } + } + } async public Task StartServer() { logger.Debug("Starting IPC server to listen for other instances of the app"); diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index 163f2bbe7..a791f0043 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -46,13 +46,14 @@ public partial class MainWindow : Window { private int _right = 75; private int _left = 75; private int _top = 30; - public bool IsUpdateAvailable = false; + private int defaultHeight = 490; public int NotificationsShownCount = 0; private double _maxHeight = 800d; public string CurrentIcon = "white"; private string[] suffixes = { "Bps", "kBps", "mBps", "gBps", "tBps", "pBps" }; private string _blurbUrl = ""; + private DateTime NextNotificationTime; private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1); static System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); @@ -76,7 +77,6 @@ static MainWindow() { ExpectedLogPathRoot = Path.Combine(ExecutionDirectory, "logs"); ExpectedLogPathUI = Path.Combine(ExpectedLogPathRoot, "UI", $"{ThisAssemblyName}.log"); ExpectedLogPathServices = Path.Combine(ExpectedLogPathRoot, "service", $"ziti-tunneler.log"); - } async private void IdentityMenu_OnMessage(string message) { @@ -183,14 +183,14 @@ private void ServiceClient_OnMfaEvent(object sender, MfaEvent mfa) { } } else if (mfa.Action == "mfa_auth_status") { var found = identities.Find(id => id.Identifier == mfa.Identifier); - for (int i=0; iThe Ziti Identity to Authenticate async public void ShowMFARecoveryCodes(ZitiIdentity identity) { if (identity.IsMFAEnabled) { - if (identity.IsAuthenticated&& identity.RecoveryCodes!=null) { + if (identity.IsAuthenticated && identity.RecoveryCodes != null) { MFASetup.Opacity = 0; MFASetup.Visibility = Visibility.Visible; MFASetup.Margin = new Thickness(0, 0, 0, 0); @@ -329,7 +329,7 @@ private void DoClose(bool isComplete) { HideModal(); if (isComplete) { if (MFASetup.Type == 1) { - for (int i=0; i { Application.Current.Shutdown(); @@ -796,13 +800,15 @@ private void MonitorClient_OnServiceStatusEvent(object sender, MonitorServiceSta try { if (evt.Message?.ToLower() == "upgrading") { logger.Info("The monitor has indicated an upgrade is in progress. Shutting down the UI"); + App.Current.Exit -= Current_Exit; + logger.Info("Removed Current_Exit handler"); notifyIcon.Visible = false; notifyIcon.Icon.Dispose(); notifyIcon.Dispose(); Application.Current.Shutdown(); + return; } state.AutomaticUpdatesEnabledFromString(evt.AutomaticUpgradeDisabled); - MainMenu.ShowUpdateAvailable(); logger.Debug("MonitorClient_OnServiceStatusEvent: {0}", evt.Status); Application.Current.Properties["ReleaseStream"] = evt.ReleaseStream; @@ -846,32 +852,44 @@ private void MonitorClient_OnServiceStatusEvent(object sender, MonitorServiceSta private void MonitorClient_OnInstallationNotificationEvent(object sender, InstallationNotificationEvent evt) { this.Dispatcher.Invoke(() => { logger.Debug("MonitorClient_OnInstallationNotificationEvent: {0}", evt.Message); - - if ("installationupdate".Equals(evt.Message?.ToLower()) || "Configuration Changed" == evt.Message) { - logger.Debug("Installation Update is available - {0}", evt.ZDEVersion); - IsUpdateAvailable = true; - var remaining = evt.InstallTime - DateTime.Now; - - state.AutomaticUpdatesEnabledFromString(evt.AutomaticUpgradeDisabled); - state.PendingUpdate.Version = evt.ZDEVersion; - state.PendingUpdate.InstallTime = evt.InstallTime; - MainMenu.ShowUpdateAvailable(); - AlertCanvas.Visibility = Visibility.Visible; - - if (isToastEnabled()) { - if (!state.AutomaticUpdatesDisabled) { - if (remaining.TotalSeconds < 60) { - //this is an immediate update - show a different message - ShowToast("Ziti Desktop Edge will initiate auto installation in the next minute!"); + switch (evt.Message?.ToLower()) { + case "installationupdate": + logger.Debug("Installation Update is available - {0}", evt.ZDEVersion); + var remaining = evt.InstallTime - DateTime.Now; + + state.AutomaticUpdatesEnabledFromString(evt.AutomaticUpgradeDisabled); + state.AutomaticUpdateURL = evt.AutomaticUpgradeURL; + state.PendingUpdate.Version = evt.ZDEVersion; + state.PendingUpdate.InstallTime = evt.InstallTime; + state.UpdateAvailable = true; + MainMenu.ShowUpdateAvailable(); + AlertCanvas.Visibility = Visibility.Visible; + + if (isToastEnabled()) { + if (!state.AutomaticUpdatesDisabled) { + if (remaining.TotalSeconds < 60) { + //this is an immediate update - show a different message + ShowToast("Ziti Desktop Edge will initiate auto installation in the next minute!"); + } else { + if (DateTime.Now > NextNotificationTime) { + ShowToast($"Update {evt.ZDEVersion} is available for Ziti Desktop Edge and will be automatically installed by " + evt.InstallTime); + NextNotificationTime = DateTime.Now + evt.NotificationDuration; + } else { + logger.Debug("Skipping notification. Time until next notification {} seconds which is at {}", (int)((NextNotificationTime - DateTime.Now).TotalSeconds), NextNotificationTime); + } + } } else { - ShowToast($"Update {evt.ZDEVersion} is available for Ziti Desktop Edge and will be automatically installed by " + evt.InstallTime); + ShowToast("New version available", $"Version {evt.ZDEVersion} is available for Ziti Desktop Edge"); } - } else { - ShowToast($"Version {evt.ZDEVersion} is available for Ziti Desktop Edge"); + SetNotifyIcon(""); + // display a tag in UI and a button for the update software } - SetNotifyIcon(""); - // display a tag in UI and a button for the update software - } + break; + case "configuration changed": + break; + default: + logger.Debug("unexpected event type?"); + break; } }); } @@ -887,13 +905,22 @@ private bool isToastEnabled() { return result; } + private void ShowToast(string header, string message) { + try { + logger.Info("showing toast: {} {}", header, message); + new ToastContentBuilder() + .AddText(header) + .AddText(message) + .SetBackgroundActivation() + .Show(); + NotificationsShownCount++; + } catch { + logger.Warn("couldn't show toast: {} {}", header, message); + } + } + private void ShowToast(string message) { - new ToastContentBuilder() - .AddText("Important Notice") - .AddText(message) - .SetBackgroundActivation() - .Show(); - NotificationsShownCount++; + ShowToast("Important Notice", message); } async private Task WaitForServiceToStop(DateTime until) { @@ -956,19 +983,6 @@ async private void StartZitiService(object sender, RoutedEventArgs e) { private void ShowServiceNotStarted() { TunnelConnected(false); LoadIdentities(true); - /* - this.Dispatcher.Invoke(() => { - semaphoreSlim.Wait(); //make sure the event is only added to the button once - CloseErrorButton.Click -= CloseError; - if (!startZitiButtonVisible) { - CloseErrorButton.Content = "Start Service"; - startZitiButtonVisible = true; - CloseErrorButton.Click += StartZitiService; - } - semaphoreSlim.Release(); - SetCantDisplay("Service Not Started", "Do you want to start the data service now?", Visibility.Visible); - }); - */ } private void MonitorClient_OnClientConnected(object sender, object e) { @@ -1037,14 +1051,14 @@ private void ServiceClient_OnIdentityEvent(object sender, IdentityEvent e) { LoadIdentities(true); } else { // means we likely are getting an update for some reason. compare the identities and use the latest info - if (zid.Name!=null && zid.Name.Length>0) found.Name = zid.Name; + if (zid.Name != null && zid.Name.Length > 0) found.Name = zid.Name; if (zid.ControllerUrl != null && zid.ControllerUrl.Length > 0) found.ControllerUrl = zid.ControllerUrl; if (zid.ContollerVersion != null && zid.ContollerVersion.Length > 0) found.ContollerVersion = zid.ContollerVersion; found.IsEnabled = zid.IsEnabled; found.IsMFAEnabled = e.Id.MfaEnabled; found.IsAuthenticated = !e.Id.MfaNeeded; found.IsConnected = true; - for (int i=0; i (i.Name != null) ? i.Name.ToLower() : i.Name).ToArray(); MainMenu.SetupIdList(ids); if (ids.Length > 0 && serviceClient.Connected) { - double height = 490 + (ids.Length * 60); + double height = defaultHeight + (ids.Length * 60); if (height > _maxHeight) height = _maxHeight; this.Height = height; IdentityMenu.SetHeight(this.Height - 160); @@ -1353,12 +1367,12 @@ private void LoadIdentities(Boolean repaint) { idItem.OnStatusChanged += Id_OnStatusChanged; idItem.Identity = id; idItem.IdentityChanged += IdItem_IdentityChanged; - + if (repaint) idItem.RefreshUI(); IdList.Children.Add(idItem); - if (IdentityMenu.Visibility==Visibility.Visible) { + if (IdentityMenu.Visibility == Visibility.Visible) { if (id.Identifier == IdentityMenu.Identity.Identifier) IdentityMenu.Identity = id; } } @@ -1366,7 +1380,7 @@ private void LoadIdentities(Boolean repaint) { IdList.BeginAnimation(FrameworkElement.HeightProperty, animation); IdListScroller.Visibility = Visibility.Visible; } else { - this.Height = 490; + this.Height = defaultHeight; MainMenu.IdentitiesButton.Visibility = Visibility.Collapsed; IdListScroller.Visibility = Visibility.Collapsed; } @@ -1379,11 +1393,11 @@ private void LoadIdentities(Boolean repaint) { } private void IdItem_IdentityChanged(ZitiIdentity identity) { - for (int i=0; i /// The message to show /// The url or action name to execute - public async Task ShowBlurbAsync(string message, string url, string level="error") { + public async Task ShowBlurbAsync(string message, string url, string level = "error") { RedBlurb.Visibility = Visibility.Collapsed; InfoBlurb.Visibility = Visibility.Collapsed; - if (level=="error") { + if (level == "error") { RedBlurb.Visibility = Visibility.Visible; } else { InfoBlurb.Visibility = Visibility.Visible; @@ -1725,9 +1739,9 @@ private void HideComplete(object sender, EventArgs e) { /// The object that was clicked /// The click event private void BlurbAction(object sender, MouseButtonEventArgs e) { - if (_blurbUrl.Length>0) { + if (_blurbUrl.Length > 0) { // So this simply execute a url but you could do like if (_blurbUrl=="DoSomethingNifty") CallNifyFunction(); - if (_blurbUrl== this.RECOVER) { + if (_blurbUrl == this.RECOVER) { this.ShowMFA(IdentityMenu.Identity, 4); } else { Process.Start(new ProcessStartInfo(_blurbUrl) { UseShellExecute = true }); @@ -1791,4 +1805,4 @@ public bool CanExecute(object parameter) { public event EventHandler CanExecuteChanged; #pragma warning restore CS0067 //The event 'ActionCommand.CanExecuteChanged' is never used } -} +} \ No newline at end of file diff --git a/DesktopEdge/Models/ViewState.cs b/DesktopEdge/Models/ViewState.cs index 1a18a72af..d5311a83d 100644 --- a/DesktopEdge/Models/ViewState.cs +++ b/DesktopEdge/Models/ViewState.cs @@ -6,45 +6,46 @@ using System.Threading.Tasks; using System.Windows; -namespace Ziti.Desktop.Edge.Models -{ - public class ZDEWViewState - { +namespace Ziti.Desktop.Edge.Models { + public class ZDEWViewState { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private bool automaticUpdatesDisabled = false; - public bool AutomaticUpdatesDisabled - { - get - { + private string updateUrl = "not set yet"; + public bool AutomaticUpdatesDisabled { + get { return automaticUpdatesDisabled; } - set - { + set { automaticUpdatesDisabled = value; } } + public string AutomaticUpdateURL { + get { + return updateUrl; + } + set { + updateUrl = value; + } + } + public bool UpdateAvailable { get; set; } public UpdateInfo PendingUpdate { get; set; } = new UpdateInfo(); - internal void AutomaticUpdatesEnabledFromString(string automaticUpgradeDisabled) - { + internal void AutomaticUpdatesEnabledFromString(string automaticUpgradeDisabled) { bool disabled = bool.TrueString.ToLower() == automaticUpgradeDisabled?.ToLower().Trim(); this.AutomaticUpdatesDisabled = disabled; } } - public class UpdateInfo - { + public class UpdateInfo { public DateTime InstallTime { get; set; } = DateTime.MinValue; public string Version { get; set; } = "0.0.0.0"; - public double TimeLeft - { - get - { + public double TimeLeft { + get { double timeLeft = (InstallTime - DateTime.Now).TotalSeconds; return timeLeft; } } } -} +} \ No newline at end of file diff --git a/DesktopEdge/Views/Controls/StyledButton.xaml.cs b/DesktopEdge/Views/Controls/StyledButton.xaml.cs index c6f44b23b..ff2d35e92 100644 --- a/DesktopEdge/Views/Controls/StyledButton.xaml.cs +++ b/DesktopEdge/Views/Controls/StyledButton.xaml.cs @@ -20,7 +20,7 @@ namespace ZitiDesktopEdge { /// public partial class StyledButton : UserControl { - public delegate void ClickAction(); + public delegate void ClickAction(object sender, MouseButtonEventArgs e); public event ClickAction OnClick; private string _label = ""; private string bgColor = "#0069FF"; @@ -82,7 +82,7 @@ private void Down(object sender, MouseButtonEventArgs e) { /// /// private void DoClick(object sender, MouseButtonEventArgs e) { - this.OnClick?.Invoke(); + this.OnClick?.Invoke(sender, e); } } } diff --git a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs index cc600b8de..21263d001 100644 --- a/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs +++ b/DesktopEdge/Views/Screens/IdentityDetails.xaml.cs @@ -312,7 +312,7 @@ public void SetHeight(double height) { MainDetailScroll.Height = height; } - private void ForgetIdentity() { + private void ForgetIdentity(object sender, MouseButtonEventArgs e) { if (this.Visibility==Visibility.Visible&&ConfirmView.Visibility==Visibility.Collapsed) { ConfirmView.Visibility = Visibility.Visible; } diff --git a/DesktopEdge/Views/Screens/MFAScreen.xaml.cs b/DesktopEdge/Views/Screens/MFAScreen.xaml.cs index ec3a029b0..dd3ac89b9 100644 --- a/DesktopEdge/Views/Screens/MFAScreen.xaml.cs +++ b/DesktopEdge/Views/Screens/MFAScreen.xaml.cs @@ -198,7 +198,7 @@ async private void GenerateMFACodes(object sender, MouseButtonEventArgs e) { Logger.Error("DATA: {0}", gencodes.Data); } - private void SaveCodes() { + private void SaveCodes(object sender, MouseButtonEventArgs e) { string fileText = string.Join("\n", _codes); string name = Regex.Replace(this._identity.Name, "[^a-zA-Z0-9]", String.Empty); @@ -212,7 +212,7 @@ private void SaveCodes() { } } - async private void DoSetupAuthenticate() { + async private void DoSetupAuthenticate(object sender, MouseButtonEventArgs e) { string code = SetupCode.Text; DataClient serviceClient = serviceClient = (DataClient)Application.Current.Properties["ServiceClient"]; @@ -233,7 +233,7 @@ async private void DoSetupAuthenticate() { /// 3 = Remove MFA /// 4 = Generate New MFA Codes /// - async private void DoAuthenticate() { + async private void DoAuthenticate(object sender, MouseButtonEventArgs e) { if (!this._executing) { this._executing = true; @@ -315,13 +315,13 @@ private void ShowSecret(object sender, MouseButtonEventArgs e) { private void HandleKey(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { - DoSetupAuthenticate(); + DoSetupAuthenticate(sender, null); } } private void AuthCode_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { - DoAuthenticate(); + DoAuthenticate(sender, null); } } } diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index c87503acc..2e4e7ff89 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -19,6 +19,9 @@ + + 8 + @@ -46,7 +49,7 @@ - + + + + + + + + + + + + + - + - + + + + + + + + +