diff --git a/mRemoteNGTests/Config/CredentialHarvesterTests.cs b/mRemoteNGTests/Config/CredentialHarvesterTests.cs index 1185843fe..a291ffc2b 100644 --- a/mRemoteNGTests/Config/CredentialHarvesterTests.cs +++ b/mRemoteNGTests/Config/CredentialHarvesterTests.cs @@ -36,7 +36,7 @@ namespace mRemoteNGTests.Config var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" }; var xdoc = CreateTestData(connection); var credentials = _credentialHarvester.Harvest(xdoc, _key); - Assert.That(credentials.Single().Username, Is.EqualTo(connection.Username)); + Assert.That(credentials.DistinctCredentialRecords.Single().Username, Is.EqualTo(connection.Username)); } [Test] @@ -45,7 +45,7 @@ namespace mRemoteNGTests.Config var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" }; var xdoc = CreateTestData(connection); var credentials = _credentialHarvester.Harvest(xdoc, _key); - Assert.That(credentials.Single().Domain, Is.EqualTo(connection.Domain)); + Assert.That(credentials.DistinctCredentialRecords.Single().Domain, Is.EqualTo(connection.Domain)); } [Test] @@ -54,7 +54,7 @@ namespace mRemoteNGTests.Config var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" }; var xdoc = CreateTestData(connection); var credentials = _credentialHarvester.Harvest(xdoc, _key); - Assert.That(credentials.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password)); + Assert.That(credentials.DistinctCredentialRecords.Single().Password.ConvertToUnsecureString(), Is.EqualTo(connection.Password)); } [Test] @@ -96,8 +96,7 @@ namespace mRemoteNGTests.Config var connection = new ConnectionInfo { Username = "myuser", Domain = "somedomain", Password = "mypass" }; var connectionGuid = Guid.Parse(connection.ConstantID); var xdoc = CreateTestData(connection); - _credentialHarvester.Harvest(xdoc, _key); - var map = _credentialHarvester.ConnectionToCredentialMap; + var map = _credentialHarvester.Harvest(xdoc, _key); Assert.That(map[connectionGuid].Username, Is.EqualTo(connection.Username)); } @@ -111,8 +110,7 @@ namespace mRemoteNGTests.Config var xdoc = CreateTestData(container); var con1Id = Guid.Parse(con1.ConstantID); var con2Id = Guid.Parse(con2.ConstantID); - _credentialHarvester.Harvest(xdoc, _key); - var map = _credentialHarvester.ConnectionToCredentialMap; + var map = _credentialHarvester.Harvest(xdoc, _key); Assert.That(map[con1Id], Is.EqualTo(map[con2Id])); } diff --git a/mRemoteV1/Config/ConnectionToCredentialMap.cs b/mRemoteV1/Config/ConnectionToCredentialMap.cs new file mode 100644 index 000000000..7f9cf6efc --- /dev/null +++ b/mRemoteV1/Config/ConnectionToCredentialMap.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using mRemoteNG.Credential; + +namespace mRemoteNG.Config +{ + public class ConnectionToCredentialMap : Dictionary + { + private readonly IEqualityComparer _credentialComparer = new CredentialDomainUserPasswordComparer(); + + public IEnumerable DistinctCredentialRecords => Values.Distinct(_credentialComparer); + } +} diff --git a/mRemoteV1/Config/CredentialHarvester.cs b/mRemoteV1/Config/CredentialHarvester.cs index 62be36fca..cb288b993 100644 --- a/mRemoteV1/Config/CredentialHarvester.cs +++ b/mRemoteV1/Config/CredentialHarvester.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Security; using System.Xml.Linq; +using mRemoteNG.Connection; using mRemoteNG.Credential; using mRemoteNG.Security; using mRemoteNG.Security.Factories; @@ -13,16 +14,21 @@ namespace mRemoteNG.Config { private readonly IEqualityComparer _credentialComparer = new CredentialDomainUserPasswordComparer(); - // maps a connectioninfo (by its id) to the credential object that was harvested - public Dictionary ConnectionToCredentialMap { get; } = new Dictionary(); - - public IEnumerable Harvest(XDocument xDocument, SecureString decryptionKey) + /// + /// Maps a (by its id) to the + /// object that was harvested + /// + /// + /// + /// + public ConnectionToCredentialMap Harvest(XDocument xDocument, SecureString decryptionKey) { if (xDocument == null) throw new ArgumentNullException(nameof(xDocument)); var cryptoProvider = new CryptoProviderFactoryFromXml(xDocument.Root).Build(); + var credentialMap = new ConnectionToCredentialMap(); foreach (var element in xDocument.Descendants("Node")) { if (!EntryHasSomeCredentialData(element)) continue; @@ -34,16 +40,16 @@ namespace mRemoteNG.Config //error } - if (ConnectionToCredentialMap.Values.Contains(newCredential, _credentialComparer)) + if (credentialMap.Values.Contains(newCredential, _credentialComparer)) { - var existingCredential = ConnectionToCredentialMap.Values.First(record => _credentialComparer.Equals(newCredential, record)); - ConnectionToCredentialMap.Add(connectionId, existingCredential); + var existingCredential = credentialMap.Values.First(record => _credentialComparer.Equals(newCredential, record)); + credentialMap.Add(connectionId, existingCredential); } else - ConnectionToCredentialMap.Add(connectionId, newCredential); + credentialMap.Add(connectionId, newCredential); } - return ConnectionToCredentialMap.Values.Distinct(_credentialComparer); + return credentialMap; } private ICredentialRecord BuildCredential(XElement element, ICryptographyProvider cryptographyProvider, SecureString decryptionKey) diff --git a/mRemoteV1/Config/Serializers/Versioning/XmlCredentialManagerUpgrader.cs b/mRemoteV1/Config/Serializers/Versioning/XmlCredentialManagerUpgrader.cs index 42e2f8f9a..cd7691b0d 100644 --- a/mRemoteV1/Config/Serializers/Versioning/XmlCredentialManagerUpgrader.cs +++ b/mRemoteV1/Config/Serializers/Versioning/XmlCredentialManagerUpgrader.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; -using System.Security; using System.Xml.Linq; using mRemoteNG.App; using mRemoteNG.Connection; using mRemoteNG.Credential; -using mRemoteNG.Credential.Repositories; using mRemoteNG.Security.Authentication; using mRemoteNG.Security.Factories; using mRemoteNG.Tools; @@ -14,34 +12,22 @@ using System.Linq; namespace mRemoteNG.Config.Serializers.Versioning { - public class XmlCredentialManagerUpgrader : IDeserializer + public class XmlCredentialManagerUpgrader { - private readonly CredentialService _credentialsService; - private readonly IDeserializer _decoratedDeserializer; - private readonly SecureString _newRepoPassword; + private readonly IDeserializer _deserializer; - public string CredentialFilePath { get; set; } - - public XmlCredentialManagerUpgrader( - CredentialService credentialsService, - string credentialFilePath, - IDeserializer decoratedDeserializer, - SecureString newRepoPassword) + public XmlCredentialManagerUpgrader(IDeserializer decoratedDeserializer) { - _credentialsService = credentialsService.ThrowIfNull(nameof(credentialsService)); - CredentialFilePath = credentialFilePath; - _newRepoPassword = newRepoPassword; - _decoratedDeserializer = decoratedDeserializer.ThrowIfNull(nameof(decoratedDeserializer)); + _deserializer = decoratedDeserializer.ThrowIfNull(nameof(decoratedDeserializer)); } - public ConnectionTreeModel Deserialize(string serializedData) + public ConnectionTreeModel Deserialize(string serializedData, ConnectionToCredentialMap upgradeMap) { var serializedDataAsXDoc = EnsureConnectionXmlElementsHaveIds(serializedData); - var upgradeMap = UpgradeUserFilesForCredentialManager(serializedDataAsXDoc); var serializedDataWithIds = $"{serializedDataAsXDoc.Declaration}{serializedDataAsXDoc}"; - var connectionTreeModel = _decoratedDeserializer.Deserialize(serializedDataWithIds); + var connectionTreeModel = _deserializer.Deserialize(serializedDataWithIds); if (upgradeMap != null) ApplyCredentialMapping(upgradeMap, connectionTreeModel.GetRecursiveChildList()); @@ -58,7 +44,7 @@ namespace mRemoteNG.Config.Serializers.Versioning return xdoc; } - public Dictionary UpgradeUserFilesForCredentialManager(XDocument xdoc) + public ConnectionToCredentialMap UpgradeUserFilesForCredentialManager(XDocument xdoc) { if (!CredentialManagerUpgradeNeeded(xdoc)) { @@ -76,13 +62,7 @@ namespace mRemoteNG.Config.Serializers.Versioning var credentialHarvester = new CredentialHarvester(); var harvestedCredentials = credentialHarvester.Harvest(xdoc, keyForOldConnectionFile); - var newCredentialRepository = BuildXmlCredentialRepo(_newRepoPassword); - - AddHarvestedCredentialsToRepo(harvestedCredentials, newCredentialRepository); - newCredentialRepository.SaveCredentials(_newRepoPassword); - - _credentialsService.AddRepository(newCredentialRepository); - return credentialHarvester.ConnectionToCredentialMap; + return harvestedCredentials; } /// @@ -100,33 +80,7 @@ namespace mRemoteNG.Config.Serializers.Versioning n.Attribute("Password") != null); } - private ICredentialRepository BuildXmlCredentialRepo(SecureString newCredRepoKey) - { - var repositoryConfig = new CredentialRepositoryConfig - { - Source = CredentialFilePath, - Title = "Converted Credentials", - TypeName = "Xml", - Key = newCredRepoKey - }; - - var xmlRepoFactory = _credentialsService.GetRepositoryFactoryForConfig(repositoryConfig); - - if (!xmlRepoFactory.Any()) - throw new CredentialRepositoryTypeNotSupportedException(repositoryConfig.TypeName); - - var newRepo = xmlRepoFactory.First().Build(repositoryConfig); - newRepo.LoadCredentials(newCredRepoKey); - return newRepo; - } - - private void AddHarvestedCredentialsToRepo(IEnumerable harvestedCredentials, ICredentialRepository repo) - { - foreach (var credential in harvestedCredentials) - repo.CredentialRecords.Add(credential); - } - - public void ApplyCredentialMapping(IDictionary map, IEnumerable connectionRecords) + private void ApplyCredentialMapping(IDictionary map, IEnumerable connectionRecords) { foreach (var connectionInfo in connectionRecords) { diff --git a/mRemoteV1/Connection/AbstractConnectionRecord.cs b/mRemoteV1/Connection/AbstractConnectionRecord.cs index 2d7719aaf..04d2b08c3 100644 --- a/mRemoteV1/Connection/AbstractConnectionRecord.cs +++ b/mRemoteV1/Connection/AbstractConnectionRecord.cs @@ -189,7 +189,7 @@ namespace mRemoteNG.Connection get { var credential = CredentialRecordId - .Select(guid => Runtime.CredentialService.RepositoryList.GetCredentialRecord(guid)) + .Select(guid => Runtime.CredentialService.GetCredentialRecord(guid)) .FirstOrDefault(); return credential ?? new PlaceholderCredentialRecord(CredentialRecordId); } diff --git a/mRemoteV1/UI/Controls/NewPasswordWithVerification.Designer.cs b/mRemoteV1/UI/Controls/NewPasswordWithVerification.Designer.cs index 58378b863..d79bf9ef5 100644 --- a/mRemoteV1/UI/Controls/NewPasswordWithVerification.Designer.cs +++ b/mRemoteV1/UI/Controls/NewPasswordWithVerification.Designer.cs @@ -28,32 +28,24 @@ /// private void InitializeComponent() { - this.labelFirstPasswordBox = new Controls.Base.NGLabel(); - this.labelSecondPasswordBox = new Controls.Base.NGLabel(); - this.labelPasswordsDontMatch = new Controls.Base.NGLabel(); this.imgError = new System.Windows.Forms.PictureBox(); + this.labelPasswordsDontMatch = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.labelSecondPasswordBox = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.labelFirstPasswordBox = new mRemoteNG.UI.Controls.Base.NGLabel(); this.secureTextBox2 = new mRemoteNG.UI.Controls.SecureTextBox(); this.secureTextBox1 = new mRemoteNG.UI.Controls.SecureTextBox(); ((System.ComponentModel.ISupportInitialize)(this.imgError)).BeginInit(); this.SuspendLayout(); // - // labelFirstPasswordBox + // imgError // - this.labelFirstPasswordBox.AutoSize = true; - this.labelFirstPasswordBox.Location = new System.Drawing.Point(-3, 0); - this.labelFirstPasswordBox.Name = "labelFirstPasswordBox"; - this.labelFirstPasswordBox.Size = new System.Drawing.Size(78, 13); - this.labelFirstPasswordBox.TabIndex = 2; - this.labelFirstPasswordBox.Text = "New Password"; - // - // labelSecondPasswordBox - // - this.labelSecondPasswordBox.AutoSize = true; - this.labelSecondPasswordBox.Location = new System.Drawing.Point(-3, 42); - this.labelSecondPasswordBox.Name = "labelSecondPasswordBox"; - this.labelSecondPasswordBox.Size = new System.Drawing.Size(79, 13); - this.labelSecondPasswordBox.TabIndex = 3; - this.labelSecondPasswordBox.Text = "VerifyPassword"; + this.imgError.Image = global::mRemoteNG.Resources.ErrorSmall; + this.imgError.Location = new System.Drawing.Point(3, 81); + this.imgError.Name = "imgError"; + this.imgError.Size = new System.Drawing.Size(16, 16); + this.imgError.TabIndex = 5; + this.imgError.TabStop = false; + this.imgError.Visible = false; // // labelPasswordsDontMatch // @@ -65,15 +57,23 @@ this.labelPasswordsDontMatch.Text = "Passwords do not match"; this.labelPasswordsDontMatch.Visible = false; // - // imgError + // labelSecondPasswordBox // - this.imgError.Image = global::mRemoteNG.Resources.ErrorSmall; - this.imgError.Location = new System.Drawing.Point(3, 81); - this.imgError.Name = "imgError"; - this.imgError.Size = new System.Drawing.Size(16, 16); - this.imgError.TabIndex = 5; - this.imgError.TabStop = false; - this.imgError.Visible = false; + this.labelSecondPasswordBox.AutoSize = true; + this.labelSecondPasswordBox.Location = new System.Drawing.Point(-3, 42); + this.labelSecondPasswordBox.Name = "labelSecondPasswordBox"; + this.labelSecondPasswordBox.Size = new System.Drawing.Size(79, 13); + this.labelSecondPasswordBox.TabIndex = 3; + this.labelSecondPasswordBox.Text = "VerifyPassword"; + // + // labelFirstPasswordBox + // + this.labelFirstPasswordBox.AutoSize = true; + this.labelFirstPasswordBox.Location = new System.Drawing.Point(-3, 0); + this.labelFirstPasswordBox.Name = "labelFirstPasswordBox"; + this.labelFirstPasswordBox.Size = new System.Drawing.Size(78, 13); + this.labelFirstPasswordBox.TabIndex = 2; + this.labelFirstPasswordBox.Text = "New Password"; // // secureTextBox2 // @@ -95,8 +95,9 @@ // // NewPasswordWithVerification // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.Transparent; this.Controls.Add(this.imgError); this.Controls.Add(this.labelPasswordsDontMatch); this.Controls.Add(this.labelSecondPasswordBox); diff --git a/mRemoteV1/UI/Controls/NewPasswordWithVerification.cs b/mRemoteV1/UI/Controls/NewPasswordWithVerification.cs index 92d036885..88382eeed 100644 --- a/mRemoteV1/UI/Controls/NewPasswordWithVerification.cs +++ b/mRemoteV1/UI/Controls/NewPasswordWithVerification.cs @@ -46,6 +46,9 @@ namespace mRemoteNG.UI.Controls public NewPasswordWithVerification() { InitializeComponent(); + var display = new DisplayProperties(); + secureTextBox1.Width = display.ScaleWidth(Width); + secureTextBox2.Width = display.ScaleWidth(Width); secureTextBox1.TextChanged += OnSecureTextBoxTextChanged; secureTextBox2.TextChanged += OnSecureTextBoxTextChanged; } diff --git a/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.Designer.cs b/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.Designer.cs index 4099e5c96..16e95556e 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.Designer.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.Designer.cs @@ -37,10 +37,19 @@ this.labelConfConsPathHeaderOnTab1 = new mRemoteNG.UI.Controls.Base.NGLabel(); this.buttonExit = new mRemoteNG.UI.Controls.Base.NGButton(); this.labelDescriptionOfUpgrade = new mRemoteNG.UI.Controls.Base.NGLabel(); - this.buttonPerformUpgrade = new mRemoteNG.UI.Controls.Base.NGButton(); + this.buttonBeginUpgrade = new mRemoteNG.UI.Controls.Base.NGButton(); this.buttonNewFile = new mRemoteNG.UI.Controls.Base.NGButton(); this.buttonOpenFile = new mRemoteNG.UI.Controls.Base.NGButton(); - this.tabPageUpgradeOptions = new System.Windows.Forms.TabPage(); + this.tabPageHarvestedCreds = new System.Windows.Forms.TabPage(); + this.olvFoundCredentials = new mRemoteNG.UI.Controls.Base.NGListView(); + this.colTitle = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); + this.colUsername = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); + this.colDomain = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); + this.colPassword = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); + this.lblCredsFound = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.btnCredsBack = new mRemoteNG.UI.Controls.Base.NGButton(); + this.btnCredsContinue = new mRemoteNG.UI.Controls.Base.NGButton(); + this.tabPageSaveRepo = new System.Windows.Forms.TabPage(); this.textBoxConfConPathTab2 = new mRemoteNG.UI.Controls.Base.NGTextBox(); this.buttonNewRepoPathBrowse = new mRemoteNG.UI.Controls.Base.NGButton(); this.labelWhereToSaveCredFile = new mRemoteNG.UI.Controls.Base.NGLabel(); @@ -49,10 +58,12 @@ this.labelSetPassword = new mRemoteNG.UI.Controls.Base.NGLabel(); this.newRepositoryPasswordEntry = new mRemoteNG.UI.Controls.NewPasswordWithVerification(); this.labelConfConsPathHeaderOnTab2 = new mRemoteNG.UI.Controls.Base.NGLabel(); - this.buttonBack = new mRemoteNG.UI.Controls.Base.NGButton(); + this.buttonSaveRepoBack = new mRemoteNG.UI.Controls.Base.NGButton(); this.tabControl.SuspendLayout(); this.tabPageWelcome.SuspendLayout(); - this.tabPageUpgradeOptions.SuspendLayout(); + this.tabPageHarvestedCreds.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.olvFoundCredentials)).BeginInit(); + this.tabPageSaveRepo.SuspendLayout(); this.SuspendLayout(); // // newCredRepoPathDialog @@ -68,7 +79,8 @@ // tabControl // this.tabControl.Controls.Add(this.tabPageWelcome); - this.tabControl.Controls.Add(this.tabPageUpgradeOptions); + this.tabControl.Controls.Add(this.tabPageHarvestedCreds); + this.tabControl.Controls.Add(this.tabPageSaveRepo); this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl.ItemSize = new System.Drawing.Size(60, 20); this.tabControl.Location = new System.Drawing.Point(0, 0); @@ -79,12 +91,12 @@ // // tabPageWelcome // - this.tabPageWelcome.BackColor = System.Drawing.SystemColors.Control; + this.tabPageWelcome.BackColor = System.Drawing.Color.Transparent; this.tabPageWelcome.Controls.Add(this.textBoxConfConPathTab1); this.tabPageWelcome.Controls.Add(this.labelConfConsPathHeaderOnTab1); this.tabPageWelcome.Controls.Add(this.buttonExit); this.tabPageWelcome.Controls.Add(this.labelDescriptionOfUpgrade); - this.tabPageWelcome.Controls.Add(this.buttonPerformUpgrade); + this.tabPageWelcome.Controls.Add(this.buttonBeginUpgrade); this.tabPageWelcome.Controls.Add(this.buttonNewFile); this.tabPageWelcome.Controls.Add(this.buttonOpenFile); this.tabPageWelcome.Location = new System.Drawing.Point(4, 24); @@ -136,17 +148,17 @@ this.labelDescriptionOfUpgrade.TabIndex = 0; this.labelDescriptionOfUpgrade.Text = resources.GetString("labelDescriptionOfUpgrade.Text"); // - // buttonPerformUpgrade + // buttonBeginUpgrade // - this.buttonPerformUpgrade._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; - this.buttonPerformUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonPerformUpgrade.Location = new System.Drawing.Point(190, 256); - this.buttonPerformUpgrade.Name = "buttonPerformUpgrade"; - this.buttonPerformUpgrade.Size = new System.Drawing.Size(212, 23); - this.buttonPerformUpgrade.TabIndex = 1; - this.buttonPerformUpgrade.Text = "Upgrade"; - this.buttonPerformUpgrade.UseVisualStyleBackColor = true; - this.buttonPerformUpgrade.Click += new System.EventHandler(this.buttonPerformUpgrade_Click); + this.buttonBeginUpgrade._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; + this.buttonBeginUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonBeginUpgrade.Location = new System.Drawing.Point(190, 256); + this.buttonBeginUpgrade.Name = "buttonBeginUpgrade"; + this.buttonBeginUpgrade.Size = new System.Drawing.Size(212, 23); + this.buttonBeginUpgrade.TabIndex = 1; + this.buttonBeginUpgrade.Text = "Upgrade"; + this.buttonBeginUpgrade.UseVisualStyleBackColor = true; + this.buttonBeginUpgrade.Click += new System.EventHandler(this.buttonBeginUpgrade_Click); // // buttonNewFile // @@ -173,24 +185,128 @@ this.buttonOpenFile.UseVisualStyleBackColor = true; this.buttonOpenFile.Click += new System.EventHandler(this.buttonOpenFile_Click); // - // tabPageUpgradeOptions + // tabPageHarvestedCreds // - this.tabPageUpgradeOptions.BackColor = System.Drawing.SystemColors.Control; - this.tabPageUpgradeOptions.Controls.Add(this.textBoxConfConPathTab2); - this.tabPageUpgradeOptions.Controls.Add(this.buttonNewRepoPathBrowse); - this.tabPageUpgradeOptions.Controls.Add(this.labelWhereToSaveCredFile); - this.tabPageUpgradeOptions.Controls.Add(this.textBoxCredRepoPath); - this.tabPageUpgradeOptions.Controls.Add(this.buttonExecuteUpgrade); - this.tabPageUpgradeOptions.Controls.Add(this.labelSetPassword); - this.tabPageUpgradeOptions.Controls.Add(this.newRepositoryPasswordEntry); - this.tabPageUpgradeOptions.Controls.Add(this.labelConfConsPathHeaderOnTab2); - this.tabPageUpgradeOptions.Controls.Add(this.buttonBack); - this.tabPageUpgradeOptions.Location = new System.Drawing.Point(4, 24); - this.tabPageUpgradeOptions.Name = "tabPageUpgradeOptions"; - this.tabPageUpgradeOptions.Padding = new System.Windows.Forms.Padding(3); - this.tabPageUpgradeOptions.Size = new System.Drawing.Size(609, 374); - this.tabPageUpgradeOptions.TabIndex = 1; - this.tabPageUpgradeOptions.Text = "upgradePage"; + this.tabPageHarvestedCreds.BackColor = System.Drawing.Color.Transparent; + this.tabPageHarvestedCreds.Controls.Add(this.olvFoundCredentials); + this.tabPageHarvestedCreds.Controls.Add(this.lblCredsFound); + this.tabPageHarvestedCreds.Controls.Add(this.btnCredsBack); + this.tabPageHarvestedCreds.Controls.Add(this.btnCredsContinue); + this.tabPageHarvestedCreds.Location = new System.Drawing.Point(4, 24); + this.tabPageHarvestedCreds.Name = "tabPageHarvestedCreds"; + this.tabPageHarvestedCreds.Padding = new System.Windows.Forms.Padding(3); + this.tabPageHarvestedCreds.Size = new System.Drawing.Size(609, 374); + this.tabPageHarvestedCreds.TabIndex = 2; + this.tabPageHarvestedCreds.Text = "harvestedCreds"; + // + // olvFoundCredentials + // + this.olvFoundCredentials.AllColumns.Add(this.colTitle); + this.olvFoundCredentials.AllColumns.Add(this.colUsername); + this.olvFoundCredentials.AllColumns.Add(this.colDomain); + this.olvFoundCredentials.AllColumns.Add(this.colPassword); + this.olvFoundCredentials.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.olvFoundCredentials.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.colTitle, + this.colUsername, + this.colDomain, + this.colPassword}); + this.olvFoundCredentials.Cursor = System.Windows.Forms.Cursors.Default; + this.olvFoundCredentials.DecorateLines = true; + this.olvFoundCredentials.HasCollapsibleGroups = false; + this.olvFoundCredentials.Location = new System.Drawing.Point(0, 31); + this.olvFoundCredentials.Name = "olvFoundCredentials"; + this.olvFoundCredentials.ShowFilterMenuOnRightClick = false; + this.olvFoundCredentials.Size = new System.Drawing.Size(609, 308); + this.olvFoundCredentials.SortGroupItemsByPrimaryColumn = false; + this.olvFoundCredentials.TabIndex = 4; + this.olvFoundCredentials.UseCompatibleStateImageBehavior = false; + this.olvFoundCredentials.UseNotifyPropertyChanged = true; + this.olvFoundCredentials.UseOverlays = false; + this.olvFoundCredentials.View = System.Windows.Forms.View.Details; + // + // colTitle + // + this.colTitle.AspectName = "Title"; + this.colTitle.Groupable = false; + this.colTitle.Hideable = false; + this.colTitle.Text = "Title"; + // + // colUsername + // + this.colUsername.AspectName = "Username"; + this.colUsername.Groupable = false; + this.colUsername.Hideable = false; + this.colUsername.Text = "Username"; + // + // colDomain + // + this.colDomain.AspectName = "Domain"; + this.colDomain.Groupable = false; + this.colDomain.Hideable = false; + this.colDomain.Text = "Domain"; + // + // colPassword + // + this.colPassword.AspectName = "Password"; + this.colPassword.FillsFreeSpace = true; + this.colPassword.Groupable = false; + this.colPassword.Hideable = false; + this.colPassword.Text = "Password"; + // + // lblCredsFound + // + this.lblCredsFound.AutoSize = true; + this.lblCredsFound.Location = new System.Drawing.Point(6, 3); + this.lblCredsFound.Name = "lblCredsFound"; + this.lblCredsFound.Size = new System.Drawing.Size(89, 13); + this.lblCredsFound.TabIndex = 3; + this.lblCredsFound.Text = "Credentials found"; + // + // btnCredsBack + // + this.btnCredsBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; + this.btnCredsBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCredsBack.Location = new System.Drawing.Point(445, 345); + this.btnCredsBack.Name = "btnCredsBack"; + this.btnCredsBack.Size = new System.Drawing.Size(75, 23); + this.btnCredsBack.TabIndex = 2; + this.btnCredsBack.Text = "Back"; + this.btnCredsBack.UseVisualStyleBackColor = true; + this.btnCredsBack.Click += new System.EventHandler(this.btnCredsBack_Click); + // + // btnCredsContinue + // + this.btnCredsContinue._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; + this.btnCredsContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCredsContinue.Location = new System.Drawing.Point(526, 345); + this.btnCredsContinue.Name = "btnCredsContinue"; + this.btnCredsContinue.Size = new System.Drawing.Size(75, 23); + this.btnCredsContinue.TabIndex = 1; + this.btnCredsContinue.Text = "Continue"; + this.btnCredsContinue.UseVisualStyleBackColor = true; + this.btnCredsContinue.Click += new System.EventHandler(this.btnCredsContinue_Click); + // + // tabPageSaveRepo + // + this.tabPageSaveRepo.BackColor = System.Drawing.Color.Transparent; + this.tabPageSaveRepo.Controls.Add(this.textBoxConfConPathTab2); + this.tabPageSaveRepo.Controls.Add(this.buttonNewRepoPathBrowse); + this.tabPageSaveRepo.Controls.Add(this.labelWhereToSaveCredFile); + this.tabPageSaveRepo.Controls.Add(this.textBoxCredRepoPath); + this.tabPageSaveRepo.Controls.Add(this.buttonExecuteUpgrade); + this.tabPageSaveRepo.Controls.Add(this.labelSetPassword); + this.tabPageSaveRepo.Controls.Add(this.newRepositoryPasswordEntry); + this.tabPageSaveRepo.Controls.Add(this.labelConfConsPathHeaderOnTab2); + this.tabPageSaveRepo.Controls.Add(this.buttonSaveRepoBack); + this.tabPageSaveRepo.Location = new System.Drawing.Point(4, 24); + this.tabPageSaveRepo.Name = "tabPageSaveRepo"; + this.tabPageSaveRepo.Padding = new System.Windows.Forms.Padding(3); + this.tabPageSaveRepo.Size = new System.Drawing.Size(609, 374); + this.tabPageSaveRepo.TabIndex = 1; + this.tabPageSaveRepo.Text = "saveRepoPage"; // // textBoxConfConPathTab2 // @@ -266,7 +382,7 @@ this.newRepositoryPasswordEntry.PasswordChar = '\0'; this.newRepositoryPasswordEntry.Size = new System.Drawing.Size(574, 100); this.newRepositoryPasswordEntry.TabIndex = 3; - this.newRepositoryPasswordEntry.UseSystemPasswordChar = false; + this.newRepositoryPasswordEntry.UseSystemPasswordChar = true; this.newRepositoryPasswordEntry.Verified += new System.EventHandler(this.newRepositoryPasswordEntry_Verified); this.newRepositoryPasswordEntry.NotVerified += new System.EventHandler(this.newRepositoryPasswordEntry_NotVerified); // @@ -279,17 +395,17 @@ this.labelConfConsPathHeaderOnTab2.TabIndex = 1; this.labelConfConsPathHeaderOnTab2.Text = "Connections file:"; // - // buttonBack + // buttonSaveRepoBack // - this.buttonBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; - this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonBack.Location = new System.Drawing.Point(445, 343); - this.buttonBack.Name = "buttonBack"; - this.buttonBack.Size = new System.Drawing.Size(75, 23); - this.buttonBack.TabIndex = 0; - this.buttonBack.Text = "Back"; - this.buttonBack.UseVisualStyleBackColor = true; - this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click); + this.buttonSaveRepoBack._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; + this.buttonSaveRepoBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonSaveRepoBack.Location = new System.Drawing.Point(445, 343); + this.buttonSaveRepoBack.Name = "buttonSaveRepoBack"; + this.buttonSaveRepoBack.Size = new System.Drawing.Size(75, 23); + this.buttonSaveRepoBack.TabIndex = 0; + this.buttonSaveRepoBack.Text = "Back"; + this.buttonSaveRepoBack.UseVisualStyleBackColor = true; + this.buttonSaveRepoBack.Click += new System.EventHandler(this.buttonSaveRepoBack_Click); // // CredentialManagerUpgradeForm // @@ -308,8 +424,11 @@ this.tabControl.ResumeLayout(false); this.tabPageWelcome.ResumeLayout(false); this.tabPageWelcome.PerformLayout(); - this.tabPageUpgradeOptions.ResumeLayout(false); - this.tabPageUpgradeOptions.PerformLayout(); + this.tabPageHarvestedCreds.ResumeLayout(false); + this.tabPageHarvestedCreds.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.olvFoundCredentials)).EndInit(); + this.tabPageSaveRepo.ResumeLayout(false); + this.tabPageSaveRepo.PerformLayout(); this.ResumeLayout(false); } @@ -317,14 +436,14 @@ #endregion private Controls.Base.NGLabel labelDescriptionOfUpgrade; - private Controls.Base.NGButton buttonPerformUpgrade; + private Controls.Base.NGButton buttonBeginUpgrade; private Controls.Base.NGButton buttonOpenFile; private Controls.Base.NGButton buttonNewFile; private Controls.Base.NGButton buttonExit; private mRemoteNG.UI.Controls.HeadlessTabControl tabControl; private System.Windows.Forms.TabPage tabPageWelcome; - private System.Windows.Forms.TabPage tabPageUpgradeOptions; - private Controls.Base.NGButton buttonBack; + private System.Windows.Forms.TabPage tabPageSaveRepo; + private Controls.Base.NGButton buttonSaveRepoBack; private Controls.Base.NGLabel labelConfConsPathHeaderOnTab2; private Controls.Base.NGButton buttonExecuteUpgrade; private Controls.Base.NGLabel labelSetPassword; @@ -337,5 +456,14 @@ private Controls.Base.NGTextBox textBoxConfConPathTab1; private Controls.Base.NGTextBox textBoxConfConPathTab2; private System.Windows.Forms.SaveFileDialog newConnectionsFileDialog; + private System.Windows.Forms.TabPage tabPageHarvestedCreds; + private Controls.Base.NGButton btnCredsBack; + private Controls.Base.NGButton btnCredsContinue; + private Controls.Base.NGLabel lblCredsFound; + private Controls.Base.NGListView olvFoundCredentials; + private BrightIdeasSoftware.OLVColumn colUsername; + private BrightIdeasSoftware.OLVColumn colDomain; + private BrightIdeasSoftware.OLVColumn colPassword; + private BrightIdeasSoftware.OLVColumn colTitle; } } \ No newline at end of file diff --git a/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.cs b/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.cs index f98aa8893..6d8dffa3c 100644 --- a/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.cs +++ b/mRemoteV1/UI/Forms/CredentialManagerUpgradeForm.cs @@ -1,12 +1,20 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Security; using System.Windows.Forms; using System.Xml.Linq; using mRemoteNG.App; +using mRemoteNG.Config; using mRemoteNG.Config.Connections; +using mRemoteNG.Config.DataProviders; using mRemoteNG.Config.Serializers; using mRemoteNG.Config.Serializers.Versioning; using mRemoteNG.Connection; using mRemoteNG.Credential; +using mRemoteNG.Credential.Repositories; +using mRemoteNG.Security; +using mRemoteNG.Themes; using mRemoteNG.Tree; namespace mRemoteNG.UI.Forms @@ -15,6 +23,10 @@ namespace mRemoteNG.UI.Forms { private string _connectionFilePath; private string _newCredentialRepoPath; + private XDocument _xdoc; + private XmlCredentialManagerUpgrader _upgradingDeserializer; + private ConnectionToCredentialMap _credentialMap; + private readonly ThemeManager _themeManager = ThemeManager.getInstance(); public IDeserializer ConnectionDeserializer { get; set; } public ConnectionsService ConnectionsService { get; set; } @@ -44,7 +56,10 @@ namespace mRemoteNG.UI.Forms { InitializeComponent(); ApplyLanguage(); + ApplyTheme(); UpdateUi(); + colPassword.AspectGetter = + rowObject => (rowObject as ICredentialRecord)?.Password.ConvertToUnsecureString(); } private const int CP_NOCLOSE_BUTTON = 0x200; @@ -60,20 +75,21 @@ namespace mRemoteNG.UI.Forms public ConnectionTreeModel Deserialize(string serializedData) { - var xdoc = XDocument.Parse(serializedData); - if (!XmlCredentialManagerUpgrader.CredentialManagerUpgradeNeeded(xdoc)) + _xdoc = XDocument.Parse(serializedData); + if (!XmlCredentialManagerUpgrader.CredentialManagerUpgradeNeeded(_xdoc)) return ConnectionDeserializer.Deserialize(serializedData); // close the splash screen during upgrade FrmSplashScreen.getInstance().Close(); + _upgradingDeserializer = new XmlCredentialManagerUpgrader(ConnectionDeserializer); var result = ShowDialog(); if (result != DialogResult.OK) return new ConnectionTreeModel(); var newRepoPassword = newRepositoryPasswordEntry.SecureString; - var upgradingDeserializer = new XmlCredentialManagerUpgrader(CredentialService, NewCredentialRepoPath, ConnectionDeserializer, newRepoPassword); - var connectionTreeModel = upgradingDeserializer.Deserialize(serializedData); + SaveCredentialsToNewRepository(_credentialMap.DistinctCredentialRecords, newRepoPassword, _newCredentialRepoPath); + var connectionTreeModel = _upgradingDeserializer.Deserialize(serializedData, _credentialMap); ConnectionsService.ConnectionsLoaded += ConnectionsServiceOnConnectionsLoaded; @@ -91,23 +107,39 @@ namespace mRemoteNG.UI.Forms private void ApplyLanguage() { - // tab 1 + // Welcome tab labelDescriptionOfUpgrade.Text = Language.strCredentialManagerUpgradeDescription; labelConfConsPathHeaderOnTab1.Text = $@"{Language.strConnectionFilePath}:"; - buttonPerformUpgrade.Text = Language.strUpgrade; + buttonBeginUpgrade.Text = Language.strUpgrade; buttonOpenFile.Text = Language.strOpenADifferentFile; buttonNewFile.Text = Language.strCreateAndOpenNewFile; buttonExit.Text = Language.strMenuExit; - // tab 2 + // HarvestedCreds tab + lblCredsFound.Text = "Credentials found"; + colTitle.Text = Language.strPropertyNameName; + colUsername.Text = Language.strPropertyNameUsername; + colDomain.Text = Language.strPropertyNameDomain; + colPassword.Text = Language.strPropertyNamePassword; + + // SaveRepo tab labelConfConsPathHeaderOnTab2.Text = $@"{Language.strConnectionFilePath}:"; labelWhereToSaveCredFile.Text = "Where should we save the new credential file?"; labelSetPassword.Text = "Set password for the credential repository"; buttonNewRepoPathBrowse.Text = Language.strButtonBrowse; - buttonBack.Text = Language.strBack; + buttonSaveRepoBack.Text = Language.strBack; buttonExecuteUpgrade.Text = Language.strUpgrade; } + private void ApplyTheme() + { + if (!_themeManager.ThemingActive) + return; + + BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); + ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); + } + private void UpdateUi() { textBoxConfConPathTab1.Text = ConnectionFilePath; @@ -115,17 +147,25 @@ namespace mRemoteNG.UI.Forms textBoxCredRepoPath.Text = NewCredentialRepoPath; } - private void buttonPerformUpgrade_Click(object sender, EventArgs e) + #region WelcomePage + private void buttonBeginUpgrade_Click(object sender, EventArgs e) { - tabControl.SelectedTab = tabPageUpgradeOptions; + tabControl.SelectedTab = tabPageHarvestedCreds; + + // harvest creds and update olv + _credentialMap = _upgradingDeserializer.UpgradeUserFilesForCredentialManager(_xdoc); + olvFoundCredentials.SetObjects(_credentialMap.DistinctCredentialRecords); + olvFoundCredentials.AutoResizeColumns(); } private void buttonOpenFile_Click(object sender, EventArgs e) { var loadConnectionsDialog = DialogFactory.BuildLoadConnectionsDialog(); var dialogResult = loadConnectionsDialog.ShowDialog(this); - if (dialogResult == DialogResult.OK) - ConnectionFilePath = loadConnectionsDialog.FileName; + if (dialogResult != DialogResult.OK) + return; + + ConnectionFilePath = loadConnectionsDialog.FileName; } private void buttonNewFile_Click(object sender, EventArgs e) @@ -140,7 +180,22 @@ namespace mRemoteNG.UI.Forms { Shutdown.Quit(); } + #endregion + #region HarvestedCredsPage + + private void btnCredsBack_Click(object sender, EventArgs e) + { + tabControl.SelectedTab = tabPageWelcome; + } + + private void btnCredsContinue_Click(object sender, EventArgs e) + { + tabControl.SelectedTab = tabPageSaveRepo; + } + #endregion + + #region SaveRepoPage private void buttonNewRepoPathBrowse_Click(object sender, EventArgs e) { var dialogResult = newCredRepoPathDialog.ShowDialog(this); @@ -148,20 +203,9 @@ namespace mRemoteNG.UI.Forms NewCredentialRepoPath = newCredRepoPathDialog.FileName; } - private void buttonBack_Click(object sender, EventArgs e) + private void buttonSaveRepoBack_Click(object sender, EventArgs e) { - tabControl.SelectedTab = tabPageWelcome; - } - - /// - /// Validate field entries to determine if we have enough information to perform the upgrade - /// - private void ValidateFields() - { - buttonExecuteUpgrade.Enabled = - newRepositoryPasswordEntry.PasswordsMatch && - newRepositoryPasswordEntry.SecureString.Length > 0 && - !string.IsNullOrWhiteSpace(textBoxCredRepoPath.Text); + tabControl.SelectedTab = tabPageHarvestedCreds; } private void textBoxCredRepoPath_TextChanged(object sender, EventArgs e) @@ -178,5 +222,55 @@ namespace mRemoteNG.UI.Forms { ValidateFields(); } + + /// + /// Validate field entries to determine if we have enough information to perform the upgrade + /// + private void ValidateFields() + { + buttonExecuteUpgrade.Enabled = + newRepositoryPasswordEntry.PasswordsMatch && + newRepositoryPasswordEntry.SecureString.Length > 0 && + !string.IsNullOrWhiteSpace(textBoxCredRepoPath.Text); + } + #endregion + + private void SaveCredentialsToNewRepository( + IEnumerable harvestedCredentials, + SecureString newRepoPassword, + string repoPath) + { + var newCredentialRepository = BuildXmlCredentialRepo(newRepoPassword, repoPath); + + AddHarvestedCredentialsToRepo(harvestedCredentials, newCredentialRepository); + + newCredentialRepository.SaveCredentials(newRepoPassword); + CredentialService.AddRepository(newCredentialRepository); + } + + private ICredentialRepository BuildXmlCredentialRepo(SecureString newCredRepoKey, string repoPath) + { + var repositoryConfig = new CredentialRepositoryConfig + { + Source = repoPath, + Title = "Converted Credentials", + TypeName = "Xml", + Key = newCredRepoKey + }; + + var xmlRepoFactory = CredentialService.GetRepositoryFactoryForConfig(repositoryConfig); + + if (!xmlRepoFactory.Any()) + throw new CredentialRepositoryTypeNotSupportedException(repositoryConfig.TypeName); + + var newRepo = xmlRepoFactory.First().Build(repositoryConfig, true); + return newRepo; + } + + private void AddHarvestedCredentialsToRepo(IEnumerable harvestedCredentials, ICredentialRepository repo) + { + foreach (var credential in harvestedCredentials) + repo.CredentialRecords.Add(credential); + } } } \ No newline at end of file diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj index 85f79a00a..2f9dce88e 100644 --- a/mRemoteV1/mRemoteV1.csproj +++ b/mRemoteV1/mRemoteV1.csproj @@ -151,6 +151,7 @@ +