added option to auto close the cred unlocker form when all repos are unlocked

This commit is contained in:
David Sparer
2018-12-27 19:27:14 -06:00
parent f1797282d9
commit 23eb9cc44b
7 changed files with 117 additions and 66 deletions

View File

@@ -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]

View File

@@ -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<ICredentialRepository> _repositories = new List<ICredentialRepository>();
public IEnumerable<ICredentialRepository> Repositories => _repositories;
public ICredentialRepository SelectedRepository { get; set; }
public Optional<ICredentialRepository> SelectedRepository { get; set; } = Optional<ICredentialRepository>.Empty;
public CompositeRepositoryUnlocker(IEnumerable<ICredentialRepository> 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<ICredentialRepository> GetNextLockedRepo()
{
var newOrder = OrderListForNextLockedRepo();
return newOrder.Any() ? newOrder.First() : null;
return new Optional<ICredentialRepository>(newOrder.FirstOrDefault());
}
private IList<ICredentialRepository> 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;
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -683,5 +683,11 @@
<Setting Name="StartUpPanelName" Type="System.String" Scope="User">
<Value Profile="(Default)">General</Value>
</Setting>
<Setting Name="CloseCredentialUnlockerDialogAfterLastUnlock" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="PlaceSearchBarAboveConnectionTree" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -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;
}
}

View File

@@ -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<ICredentialRepository>(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
}

View File

@@ -708,6 +708,13 @@
<setting name="StartUpPanelName" serializeAs="String">
<value>General</value>
</setting>
<setting name="CloseCredentialUnlockerDialogAfterLastUnlock"
serializeAs="String">
<value>True</value>
</setting>
<setting name="PlaceSearchBarAboveConnectionTree" serializeAs="String">
<value>False</value>
</setting>
</mRemoteNG.Settings>
</userSettings>
<applicationSettings>