From 23eb9cc44be0271ca1505cf2b8118ae76cb69cfe Mon Sep 17 00:00:00 2001 From: David Sparer Date: Thu, 27 Dec 2018 19:27:14 -0600 Subject: [PATCH] added option to auto close the cred unlocker form when all repos are unlocked --- .../CompositeRepositoryUnlockerTests.cs | 3 +- .../CompositeRepositoryUnlocker.cs | 15 ++-- mRemoteV1/Properties/Settings.Designer.cs | 58 +++++++-------- mRemoteV1/Properties/Settings.settings | 6 ++ ...siteCredentialRepoUnlockerForm.Designer.cs | 71 ++++++++++++------- .../CompositeCredentialRepoUnlockerForm.cs | 23 ++++-- mRemoteV1/app.config | 7 ++ 7 files changed, 117 insertions(+), 66 deletions(-) diff --git a/mRemoteNGTests/Credential/CompositeRepositoryUnlockerTests.cs b/mRemoteNGTests/Credential/CompositeRepositoryUnlockerTests.cs index 773d2f4a2..fd1a9c5fe 100644 --- a/mRemoteNGTests/Credential/CompositeRepositoryUnlockerTests.cs +++ b/mRemoteNGTests/Credential/CompositeRepositoryUnlockerTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Security; using mRemoteNG.Credential; using mRemoteNG.Credential.Repositories; @@ -36,7 +37,7 @@ namespace mRemoteNGTests.Credential { var key = new SecureString(); _repositoryUnlocker.Unlock(key); - _repositoryUnlocker.SelectedRepository.Received(1).LoadCredentials(key); + _repositoryUnlocker.SelectedRepository.First().Received(1).LoadCredentials(key); } [Test] diff --git a/mRemoteV1/Credential/Repositories/CompositeRepositoryUnlocker.cs b/mRemoteV1/Credential/Repositories/CompositeRepositoryUnlocker.cs index 79dd9572e..5246522a7 100644 --- a/mRemoteV1/Credential/Repositories/CompositeRepositoryUnlocker.cs +++ b/mRemoteV1/Credential/Repositories/CompositeRepositoryUnlocker.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Security; +using mRemoteNG.Tools; namespace mRemoteNG.Credential.Repositories { @@ -10,7 +11,7 @@ namespace mRemoteNG.Credential.Repositories private readonly List _repositories = new List(); public IEnumerable Repositories => _repositories; - public ICredentialRepository SelectedRepository { get; set; } + public Optional SelectedRepository { get; set; } = Optional.Empty; public CompositeRepositoryUnlocker(IEnumerable repositories) { @@ -23,7 +24,8 @@ namespace mRemoteNG.Credential.Repositories public void Unlock(SecureString key) { - SelectedRepository.LoadCredentials(key); + if (SelectedRepository.Any()) + SelectedRepository.First().LoadCredentials(key); } public void SelectNextLockedRepository() @@ -31,10 +33,10 @@ namespace mRemoteNG.Credential.Repositories SelectedRepository = GetNextLockedRepo(); } - private ICredentialRepository GetNextLockedRepo() + private Optional GetNextLockedRepo() { var newOrder = OrderListForNextLockedRepo(); - return newOrder.Any() ? newOrder.First() : null; + return new Optional(newOrder.FirstOrDefault()); } private IList OrderListForNextLockedRepo() @@ -67,7 +69,10 @@ namespace mRemoteNG.Credential.Repositories private int GetNewListStartIndex() { - var currentItemIndex = _repositories.IndexOf(SelectedRepository); + if (!SelectedRepository.Any()) + return 0; + + var currentItemIndex = _repositories.IndexOf(SelectedRepository.First()); return currentItemIndex + 1; } } diff --git a/mRemoteV1/Properties/Settings.Designer.cs b/mRemoteV1/Properties/Settings.Designer.cs index 508f874b0..0616014d5 100644 --- a/mRemoteV1/Properties/Settings.Designer.cs +++ b/mRemoteV1/Properties/Settings.Designer.cs @@ -12,11 +12,7 @@ namespace mRemoteNG { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")] - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -2642,37 +2638,19 @@ namespace mRemoteNG { this["SaveConnectionsAfterEveryEdit"] = value; } } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool UseFilterSearch - { - get - { + public bool UseFilterSearch { + get { return ((bool)(this["UseFilterSearch"])); } - set - { + set { this["UseFilterSearch"] = value; } } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool PlaceSearchBarAboveConnectionTree - { - get - { - return ((bool)(this["PlaceSearchBarAboveConnectionTree"])); - } - set - { - this["PlaceSearchBarAboveConnectionTree"] = value; - } - } - + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] @@ -2768,5 +2746,29 @@ namespace mRemoteNG { this["StartUpPanelName"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool CloseCredentialUnlockerDialogAfterLastUnlock { + get { + return ((bool)(this["CloseCredentialUnlockerDialogAfterLastUnlock"])); + } + set { + this["CloseCredentialUnlockerDialogAfterLastUnlock"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool PlaceSearchBarAboveConnectionTree { + get { + return ((bool)(this["PlaceSearchBarAboveConnectionTree"])); + } + set { + this["PlaceSearchBarAboveConnectionTree"] = value; + } + } } } diff --git a/mRemoteV1/Properties/Settings.settings b/mRemoteV1/Properties/Settings.settings index 7ee752fe1..292f43c39 100644 --- a/mRemoteV1/Properties/Settings.settings +++ b/mRemoteV1/Properties/Settings.settings @@ -683,5 +683,11 @@ General + + True + + + False + \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.Designer.cs b/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.Designer.cs index 24e30c077..9fa039859 100644 --- a/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.Designer.cs +++ b/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.Designer.cs @@ -29,26 +29,27 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CompositeCredentialRepoUnlockerForm)); - this.objectListViewRepos = new Controls.Base.NGListView(); + this.objectListViewRepos = new mRemoteNG.UI.Controls.Base.NGListView(); this.olvColumnName = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); this.olvColumnStatusIcon = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); - this.labelUnlocking = new Controls.Base.NGLabel(); - this.labelPassword = new Controls.Base.NGLabel(); - this.buttonUnlock = new Controls.Base.NGButton(); - this.buttonClose = new Controls.Base.NGButton(); - this.labelRepoTitle = new Controls.Base.NGLabel(); - this.textBoxType = new Controls.Base.NGTextBox(); - this.textBoxTitle = new Controls.Base.NGTextBox(); - this.labelRepoType = new Controls.Base.NGLabel(); - this.textBoxSource = new Controls.Base.NGTextBox(); - this.labelRepoSource = new Controls.Base.NGLabel(); - this.textBoxId = new Controls.Base.NGTextBox(); - this.labelId = new Controls.Base.NGLabel(); - this.labelPasswordError = new Controls.Base.NGLabel(); + this.labelUnlocking = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.labelPassword = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.buttonUnlock = new mRemoteNG.UI.Controls.Base.NGButton(); + this.buttonClose = new mRemoteNG.UI.Controls.Base.NGButton(); + this.labelRepoTitle = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.textBoxType = new mRemoteNG.UI.Controls.Base.NGTextBox(); + this.textBoxTitle = new mRemoteNG.UI.Controls.Base.NGTextBox(); + this.labelRepoType = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.textBoxSource = new mRemoteNG.UI.Controls.Base.NGTextBox(); + this.labelRepoSource = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.textBoxId = new mRemoteNG.UI.Controls.Base.NGTextBox(); + this.labelId = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.labelPasswordError = new mRemoteNG.UI.Controls.Base.NGLabel(); this.imgPasswordError = new System.Windows.Forms.PictureBox(); this.imgUnlocked = new System.Windows.Forms.PictureBox(); - this.labelUnlocked = new Controls.Base.NGLabel(); + this.labelUnlocked = new mRemoteNG.UI.Controls.Base.NGLabel(); this.secureTextBoxPassword = new mRemoteNG.UI.Controls.SecureTextBox(); + this.chkCloseAfterLastUnlock = new mRemoteNG.UI.Controls.Base.NGCheckBox(); ((System.ComponentModel.ISupportInitialize)(this.objectListViewRepos)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.imgPasswordError)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.imgUnlocked)).BeginInit(); @@ -63,6 +64,7 @@ this.olvColumnName, this.olvColumnStatusIcon}); this.objectListViewRepos.Cursor = System.Windows.Forms.Cursors.Default; + this.objectListViewRepos.DecorateLines = true; this.objectListViewRepos.Dock = System.Windows.Forms.DockStyle.Left; this.objectListViewRepos.EmptyListMsg = "No Credential Repositories Found"; this.objectListViewRepos.HasCollapsibleGroups = false; @@ -73,7 +75,7 @@ this.objectListViewRepos.Name = "objectListViewRepos"; this.objectListViewRepos.SelectAllOnControlA = false; this.objectListViewRepos.ShowGroups = false; - this.objectListViewRepos.Size = new System.Drawing.Size(175, 272); + this.objectListViewRepos.Size = new System.Drawing.Size(175, 283); this.objectListViewRepos.TabIndex = 3; this.objectListViewRepos.UseCompatibleStateImageBehavior = false; this.objectListViewRepos.UseOverlays = false; @@ -112,7 +114,7 @@ // this.labelPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelPassword.AutoSize = true; - this.labelPassword.Location = new System.Drawing.Point(190, 174); + this.labelPassword.Location = new System.Drawing.Point(195, 173); this.labelPassword.Name = "labelPassword"; this.labelPassword.Size = new System.Drawing.Size(53, 13); this.labelPassword.TabIndex = 2; @@ -120,8 +122,9 @@ // // buttonUnlock // + this.buttonUnlock._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; this.buttonUnlock.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonUnlock.Location = new System.Drawing.Point(386, 237); + this.buttonUnlock.Location = new System.Drawing.Point(387, 234); this.buttonUnlock.Name = "buttonUnlock"; this.buttonUnlock.Size = new System.Drawing.Size(75, 23); this.buttonUnlock.TabIndex = 1; @@ -131,9 +134,10 @@ // // buttonClose // + this.buttonClose._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonClose.Location = new System.Drawing.Point(467, 237); + this.buttonClose.Location = new System.Drawing.Point(468, 234); this.buttonClose.Name = "buttonClose"; this.buttonClose.Size = new System.Drawing.Size(75, 23); this.buttonClose.TabIndex = 2; @@ -190,7 +194,7 @@ this.textBoxSource.Multiline = true; this.textBoxSource.Name = "textBoxSource"; this.textBoxSource.ReadOnly = true; - this.textBoxSource.Size = new System.Drawing.Size(306, 46); + this.textBoxSource.Size = new System.Drawing.Size(306, 40); this.textBoxSource.TabIndex = 11; this.textBoxSource.TabStop = false; // @@ -230,7 +234,7 @@ this.labelPasswordError.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.labelPasswordError.ForeColor = System.Drawing.Color.DarkRed; this.labelPasswordError.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.labelPasswordError.Location = new System.Drawing.Point(191, 213); + this.labelPasswordError.Location = new System.Drawing.Point(196, 212); this.labelPasswordError.Name = "labelPasswordError"; this.labelPasswordError.Size = new System.Drawing.Size(115, 13); this.labelPasswordError.TabIndex = 14; @@ -241,7 +245,7 @@ // this.imgPasswordError.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.imgPasswordError.Image = global::mRemoteNG.Resources.exclamation; - this.imgPasswordError.Location = new System.Drawing.Point(176, 192); + this.imgPasswordError.Location = new System.Drawing.Point(181, 191); this.imgPasswordError.Name = "imgPasswordError"; this.imgPasswordError.Size = new System.Drawing.Size(16, 16); this.imgPasswordError.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -253,7 +257,7 @@ // this.imgUnlocked.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.imgUnlocked.Image = global::mRemoteNG.Resources.tick; - this.imgUnlocked.Location = new System.Drawing.Point(188, 241); + this.imgUnlocked.Location = new System.Drawing.Point(189, 238); this.imgUnlocked.Name = "imgUnlocked"; this.imgUnlocked.Size = new System.Drawing.Size(16, 16); this.imgUnlocked.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -265,7 +269,7 @@ // this.labelUnlocked.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelUnlocked.AutoSize = true; - this.labelUnlocked.Location = new System.Drawing.Point(204, 242); + this.labelUnlocked.Location = new System.Drawing.Point(205, 239); this.labelUnlocked.Name = "labelUnlocked"; this.labelUnlocked.Size = new System.Drawing.Size(174, 13); this.labelUnlocked.TabIndex = 17; @@ -276,19 +280,33 @@ // this.secureTextBoxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.secureTextBoxPassword.Location = new System.Drawing.Point(193, 190); + this.secureTextBoxPassword.Location = new System.Drawing.Point(198, 189); this.secureTextBoxPassword.Name = "secureTextBoxPassword"; this.secureTextBoxPassword.Size = new System.Drawing.Size(348, 20); this.secureTextBoxPassword.TabIndex = 0; this.secureTextBoxPassword.UseSystemPasswordChar = true; // + // chkCloseAfterLastUnlock + // + this.chkCloseAfterLastUnlock._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER; + this.chkCloseAfterLastUnlock.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.chkCloseAfterLastUnlock.AutoSize = true; + this.chkCloseAfterLastUnlock.Location = new System.Drawing.Point(189, 263); + this.chkCloseAfterLastUnlock.Name = "chkCloseAfterLastUnlock"; + this.chkCloseAfterLastUnlock.Size = new System.Drawing.Size(332, 17); + this.chkCloseAfterLastUnlock.TabIndex = 18; + this.chkCloseAfterLastUnlock.Text = "Automatically close this dialog after the last repository is unlocked"; + this.chkCloseAfterLastUnlock.UseVisualStyleBackColor = true; + this.chkCloseAfterLastUnlock.CheckedChanged += new System.EventHandler(this.chkCloseAfterLastUnlock_CheckedChanged); + // // CompositeCredentialRepoUnlockerForm // this.AcceptButton = this.buttonUnlock; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.buttonClose; - this.ClientSize = new System.Drawing.Size(554, 272); + this.ClientSize = new System.Drawing.Size(554, 283); + this.Controls.Add(this.chkCloseAfterLastUnlock); this.Controls.Add(this.labelUnlocked); this.Controls.Add(this.imgUnlocked); this.Controls.Add(this.imgPasswordError); @@ -345,5 +363,6 @@ private System.Windows.Forms.PictureBox imgPasswordError; private System.Windows.Forms.PictureBox imgUnlocked; private Controls.Base.NGLabel labelUnlocked; + private Controls.Base.NGCheckBox chkCloseAfterLastUnlock; } } \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.cs b/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.cs index 68da119a0..29ecc2747 100644 --- a/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.cs +++ b/mRemoteV1/UI/Forms/CompositeCredentialRepoUnlockerForm.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Windows.Forms; using mRemoteNG.Credential; using mRemoteNG.Credential.Repositories; +using mRemoteNG.Tools; namespace mRemoteNG.UI.Forms { @@ -13,14 +14,12 @@ namespace mRemoteNG.UI.Forms public CompositeCredentialRepoUnlockerForm(CompositeRepositoryUnlocker repositoryUnlocker) { - if (repositoryUnlocker == null) - throw new ArgumentNullException(nameof(repositoryUnlocker)); - - _repositoryUnlocker = repositoryUnlocker; + _repositoryUnlocker = repositoryUnlocker.ThrowIfNull(nameof(repositoryUnlocker)); InitializeComponent(); SetupListView(); ApplyLanguage(); ApplyTheme(); + chkCloseAfterLastUnlock.Checked = Settings.Default.CloseCredentialUnlockerDialogAfterLastUnlock; Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme; } @@ -37,6 +36,11 @@ namespace mRemoteNG.UI.Forms { _repositoryUnlocker.Unlock(secureTextBoxPassword.SecString); SelectNextLockedRepo(); + + if (Settings.Default.CloseCredentialUnlockerDialogAfterLastUnlock && _repositoryUnlocker.Repositories.All(r => r.IsLoaded)) + { + Close(); + } } catch (Exception exception) { @@ -57,14 +61,14 @@ namespace mRemoteNG.UI.Forms private void SelectNextLockedRepo() { _repositoryUnlocker.SelectNextLockedRepository(); - objectListViewRepos.SelectedObject = _repositoryUnlocker.SelectedRepository; + objectListViewRepos.SelectedObject = _repositoryUnlocker.SelectedRepository.FirstOrDefault(); } private void objectListViewRepos_SelectionChanged(object sender, EventArgs e) { objectListViewRepos.RefreshObjects(_repositoryUnlocker.Repositories.ToList()); var selectedRepo = objectListViewRepos.SelectedObject as ICredentialRepository; - _repositoryUnlocker.SelectedRepository = selectedRepo; + _repositoryUnlocker.SelectedRepository = new Optional(selectedRepo); ShowRepoDetails(selectedRepo); ShowPasswordError(false); UnlockRequired(!selectedRepo?.IsLoaded ?? false); @@ -93,6 +97,12 @@ namespace mRemoteNG.UI.Forms secureTextBoxPassword.BackColor = shouldErrorBeActive ? Color.MistyRose : SystemColors.Window; } + private void chkCloseAfterLastUnlock_CheckedChanged(object sender, EventArgs e) + { + Settings.Default.CloseCredentialUnlockerDialogAfterLastUnlock = chkCloseAfterLastUnlock.Checked; + Settings.Default.Save(); + } + #region Setup private void SetupListView() { @@ -144,6 +154,7 @@ namespace mRemoteNG.UI.Forms labelUnlocked.Text = Language.RepositoryIsUnlocked; buttonUnlock.Text = Language.Unlock; buttonClose.Text = Language.strButtonClose; + chkCloseAfterLastUnlock.Text = "Automatically close this dialog after the last repository is unlocked"; } #endregion } diff --git a/mRemoteV1/app.config b/mRemoteV1/app.config index bf6ccc794..eab490ec1 100644 --- a/mRemoteV1/app.config +++ b/mRemoteV1/app.config @@ -708,6 +708,13 @@ General + + True + + + False +