1
0
mirror of https://github.com/Ylianst/MeshCentralRouter synced 2026-02-22 12:23:24 +00:00

Adding remember password option to login dialog (#121)

* remove CodeAnalysisRuleSet from Debug and Release configurations

* add VSCode task for building MeshCentralRouter

* refactor: use auto-properties for displayCrop and displayOrigin in KVMControl, suppress warnings for unused event in KVMResizeControl. Fixing build errors

* feat: add password encryption and decryption functionality with UI support for remembering passwords
This commit is contained in:
silversword411
2026-01-26 10:59:28 -05:00
committed by GitHub
parent fe14d3bfd5
commit 9ef8f38930
9 changed files with 149 additions and 14 deletions

18
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build MeshCentralRouter",
"type": "shell",
"command": "& '${env:ProgramFiles(x86)}\\Microsoft Visual Studio\\2022\\BuildTools\\MSBuild\\Current\\Bin\\MSBuild.exe' MeshCentralRouter.sln",
"isBackground": false,
"problemMatcher": [
"$msCompile"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -45,7 +45,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -55,7 +54,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup />
@@ -262,6 +260,7 @@
<Compile Include="src\MeshDiscovery.cs" />
<Compile Include="src\MeshMapper.cs" />
<Compile Include="src\NodeClass.cs" />
<Compile Include="MeshUtils.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">

View File

@@ -395,5 +395,36 @@ namespace MeshMiniRouterTool
public static StringBuilder GetStringBuilder() { lock (StringBuilderRecycleList) { return (StringBuilderRecycleList.Count == 0) ? new StringBuilder(16000) : StringBuilderRecycleList.Pop(); } }
public static void RecycleStringBuilder(StringBuilder obj) { lock (StringBuilderRecycleList) { obj.Length = 0; StringBuilderRecycleList.Push(obj); } }
// Password encryption/decryption using DPAPI (Data Protection API)
public static string EncryptPassword(string password)
{
if (string.IsNullOrEmpty(password)) return null;
try
{
byte[] data = Encoding.UTF8.GetBytes(password);
byte[] encrypted = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encrypted);
}
catch (Exception)
{
return null;
}
}
public static string DecryptPassword(string encryptedPassword)
{
if (string.IsNullOrEmpty(encryptedPassword)) return null;
try
{
byte[] data = Convert.FromBase64String(encryptedPassword);
byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(decrypted);
}
catch (Exception)
{
return null;
}
}
}
}

View File

@@ -31,6 +31,6 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.8.*")]
[assembly: AssemblyVersion("1.9.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -61,8 +61,8 @@ namespace MeshCentralRouter
private long killNextKeyPress = 0;
private bool controlLoaded = false;
public Rectangle[] displayInfo = null;
public Rectangle displayCrop = Rectangle.Empty;
public Point displayOrigin = Point.Empty;
public Rectangle displayCrop { get; set; } = Rectangle.Empty;
public Point displayOrigin { get; set; } = Point.Empty;
//System level functions to be used for hook and unhook keyboard input
@@ -949,7 +949,8 @@ namespace MeshCentralRouter
return false;
}
// Structure contain information about low-level keyboard input event
// Structure contain information about low-level keyboard input event
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value (filled by Windows via P/Invoke)
private struct KBDLLHOOKSTRUCT
{
public Keys key;
@@ -958,6 +959,7 @@ namespace MeshCentralRouter
public int time;
public IntPtr extra;
}
#pragma warning restore CS0649
public void cropDisplay(Point o, Rectangle r)
{

View File

@@ -29,7 +29,9 @@ namespace MeshCentralRouter
[Category("Action")]
[Description("Fires when the connection state changes.")]
#pragma warning disable CS0067 // Event is declared but never invoked in this class
public event EventHandler StateChanged;
#pragma warning restore CS0067
[Category("Action")]
[Description("Fires when the display list is received.")]

View File

@@ -42,6 +42,7 @@
this.label27 = new System.Windows.Forms.Label();
this.label26 = new System.Windows.Forms.Label();
this.passwordTextBox = new System.Windows.Forms.TextBox();
this.rememberPasswordCheckBox = new System.Windows.Forms.CheckBox();
this.serverNameComboBox = new System.Windows.Forms.ComboBox();
this.userNameTextBox = new System.Windows.Forms.TextBox();
this.licenseLinkLabel = new System.Windows.Forms.LinkLabel();
@@ -213,6 +214,7 @@
this.panel1.Controls.Add(this.label27);
this.panel1.Controls.Add(this.label26);
this.panel1.Controls.Add(this.passwordTextBox);
this.panel1.Controls.Add(this.rememberPasswordCheckBox);
this.panel1.Controls.Add(this.serverNameComboBox);
this.panel1.Controls.Add(this.userNameTextBox);
this.panel1.Controls.Add(this.licenseLinkLabel);
@@ -266,6 +268,12 @@
this.passwordTextBox.TextChanged += new System.EventHandler(this.updatePanel1);
this.passwordTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.passwordTextBox_KeyPress);
//
// rememberPasswordCheckBox
//
resources.ApplyResources(this.rememberPasswordCheckBox, "rememberPasswordCheckBox");
this.rememberPasswordCheckBox.Name = "rememberPasswordCheckBox";
this.rememberPasswordCheckBox.UseVisualStyleBackColor = true;
//
// serverNameComboBox
//
resources.ApplyResources(this.serverNameComboBox, "serverNameComboBox");
@@ -1094,6 +1102,7 @@
private System.Windows.Forms.ComboBox serverNameComboBox;
private System.Windows.Forms.TextBox userNameTextBox;
private System.Windows.Forms.TextBox passwordTextBox;
private System.Windows.Forms.CheckBox rememberPasswordCheckBox;
private System.Windows.Forms.Label label28;
private System.Windows.Forms.Label label27;
private System.Windows.Forms.Label label26;

View File

@@ -31,6 +31,7 @@ using System.Drawing;
using System.Text;
using System.Web;
using System.Threading.Tasks;
using MeshMiniRouterTool;
namespace MeshCentralRouter
{
@@ -253,6 +254,33 @@ namespace MeshCentralRouter
userNameTextBox.Text = Settings.GetRegValue("UserName", "");
notifyIcon.Visible = Settings.GetRegValue("NotifyIcon", false);
// Load saved password if available and not expired (30 days)
string savedPassword = Settings.GetRegValue("SavedPassword", "");
string savedPasswordDate = Settings.GetRegValue("SavedPasswordDate", "");
if (!string.IsNullOrEmpty(savedPassword) && !string.IsNullOrEmpty(savedPasswordDate))
{
try
{
DateTime savedDate = DateTime.Parse(savedPasswordDate);
if ((DateTime.Now - savedDate).TotalDays <= 30)
{
string decryptedPassword = MeshUtils.DecryptPassword(savedPassword);
if (decryptedPassword != null)
{
passwordTextBox.Text = decryptedPassword;
rememberPasswordCheckBox.Checked = true;
}
}
else
{
// Password expired, clear it
Settings.SetRegValue("SavedPassword", "");
Settings.SetRegValue("SavedPasswordDate", "");
}
}
catch (Exception) { }
}
title = this.Text;
initialHeight = this.Height;
@@ -1158,6 +1186,22 @@ namespace MeshCentralRouter
{
Settings.SetRegValue("ServerName", serverNameComboBox.Text);
Settings.SetRegValue("UserName", userNameTextBox.Text);
// Save or clear password based on remember checkbox
if (rememberPasswordCheckBox.Checked)
{
string encryptedPassword = MeshUtils.EncryptPassword(passwordTextBox.Text);
if (encryptedPassword != null)
{
Settings.SetRegValue("SavedPassword", encryptedPassword);
Settings.SetRegValue("SavedPasswordDate", DateTime.Now.ToString("o"));
}
}
else
{
Settings.SetRegValue("SavedPassword", "");
Settings.SetRegValue("SavedPasswordDate", "");
}
}
if (meshcentral.username != null)
{

View File

@@ -348,6 +348,36 @@
<data name="&gt;&gt;passwordTextBox.ZOrder" xml:space="preserve">
<value>6</value>
</data>
<data name="rememberPasswordCheckBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left</value>
</data>
<data name="rememberPasswordCheckBox.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="rememberPasswordCheckBox.Location" type="System.Drawing.Point, System.Drawing">
<value>241, 218</value>
</data>
<data name="rememberPasswordCheckBox.Size" type="System.Drawing.Size, System.Drawing">
<value>200, 17</value>
</data>
<data name="rememberPasswordCheckBox.TabIndex" type="System.Int32, mscorlib">
<value>107</value>
</data>
<data name="rememberPasswordCheckBox.Text" xml:space="preserve">
<value>Remember password for 30 days</value>
</data>
<data name="&gt;&gt;rememberPasswordCheckBox.Name" xml:space="preserve">
<value>rememberPasswordCheckBox</value>
</data>
<data name="&gt;&gt;rememberPasswordCheckBox.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;rememberPasswordCheckBox.Parent" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;rememberPasswordCheckBox.ZOrder" xml:space="preserve">
<value>7</value>
</data>
<data name="serverNameComboBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
</data>
@@ -373,7 +403,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;serverNameComboBox.ZOrder" xml:space="preserve">
<value>7</value>
<value>8</value>
</data>
<data name="userNameTextBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
@@ -397,7 +427,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;userNameTextBox.ZOrder" xml:space="preserve">
<value>8</value>
<value>9</value>
</data>
<data name="licenseLinkLabel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
@@ -430,7 +460,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;licenseLinkLabel.ZOrder" xml:space="preserve">
<value>9</value>
<value>10</value>
</data>
<data name="versionLabel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left</value>
@@ -463,7 +493,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;versionLabel.ZOrder" xml:space="preserve">
<value>10</value>
<value>11</value>
</data>
<data name="nextButton1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
@@ -493,7 +523,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;nextButton1.ZOrder" xml:space="preserve">
<value>11</value>
<value>12</value>
</data>
<data name="pictureBox3.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left, Right</value>
@@ -523,7 +553,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;pictureBox3.ZOrder" xml:space="preserve">
<value>12</value>
<value>13</value>
</data>
<data name="label1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
@@ -553,7 +583,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>13</value>
<value>14</value>
</data>
<data name="pictureBox2.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
@@ -583,7 +613,7 @@
<value>panel1</value>
</data>
<data name="&gt;&gt;pictureBox2.ZOrder" xml:space="preserve">
<value>14</value>
<value>15</value>
</data>
<data name="panel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>