Skip to content

Commit

Permalink
Hide expired entries in the popup menu (#82)
Browse files Browse the repository at this point in the history
* Add an expired entry to Test.kdbx
* Moved the filtering logic to a separate method
* Added a few unit tests
  • Loading branch information
robinvanpoppel committed Apr 5, 2020
1 parent f700c6e commit f6d1206
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 29 deletions.
46 changes: 46 additions & 0 deletions KeeTrayTOTP.Tests/ExpiryTests.cs
@@ -0,0 +1,46 @@
using KeePassLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace KeeTrayTOTP.Tests
{
[TestClass]
public class ExpiryTests
{
[TestMethod]
public void IsExpired_ShouldReturnTrue_WhenExpiresIsTrueAndExpiryTimeInThePast()
{
var pwEntry = new PwEntry(true, true)
{
Expires = true,
ExpiryTime = DateTime.MinValue
};

Assert.IsTrue(pwEntry.IsExpired());
}

[TestMethod]
public void IsExpired_ShouldReturnFalse_WhenExpiresIsTrueAndExpiryTimeInTheFuture()
{
var pwEntry = new PwEntry(true, true)
{
Expires = true,
ExpiryTime = DateTime.UtcNow.AddSeconds(2)
};

Assert.IsFalse(pwEntry.IsExpired());
}

[TestMethod]
public void IsExpired_ShouldReturnFalse_WhenExpiresIsFalseAndExpiryTimeInThePast()
{
var pwEntry = new PwEntry(true, true)
{
Expires = false,
ExpiryTime = DateTime.MinValue
};

Assert.IsFalse(pwEntry.IsExpired());
}
}
}
2 changes: 2 additions & 0 deletions KeeTrayTOTP/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("KeeTrayTOTP")]
[assembly: AssemblyDescription("Time based One Time Password Plugin to enable 2 step authentification by generating TOTPs from the KeePass tray icon. This plugin also provides a custom column to display and/or generate TOTP's. Auto-Type is also supported when the specified custom field is used in a keystroke sequence.")]
Expand All @@ -10,3 +11,4 @@
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.103.*")]
[assembly: AssemblyFileVersion("0.103.0.0")]
[assembly: InternalsVisibleTo("KeeTrayTOTP.Tests")]
Binary file modified KeeTrayTOTP/Test.kdbx
Binary file not shown.
13 changes: 12 additions & 1 deletion KeeTrayTOTP/TrayTOTP_Extensions.cs
@@ -1,4 +1,5 @@
using System;
using KeePassLib;
using System;

namespace KeeTrayTOTP
{
Expand Down Expand Up @@ -158,5 +159,15 @@ internal static bool ExtIsBase32(this string extension, out string invalidChars)
}
return invalidChars == null;
}

internal static bool IsExpired(this PwEntry passwordEntry)
{
if (!passwordEntry.Expires)
{
return false;
}

return passwordEntry.ExpiryTime <= DateTime.UtcNow;
}
}
}
66 changes: 38 additions & 28 deletions KeeTrayTOTP/TrayTOTP_Plugin.cs
Expand Up @@ -430,34 +430,31 @@ private void OnNotifyMenuOpening(object sender, CancelEventArgs e)
if (PluginHost.MainWindow.ActiveDatabase.IsOpen)
{
var trimTrayText = PluginHost.CustomConfig.GetBool(KeeTrayTOTPExt.setname_bool_TrimTrayText, false);
foreach (PwEntry entry in PluginHost.MainWindow.ActiveDatabase.RootGroup.GetEntries(true))
foreach (PwEntry entry in GetVisibleAndValidPasswordEntries())
{
if (SettingsCheck(entry) && SeedCheck(entry))
{
var entryTitle = entry.Strings.ReadSafe(PwDefs.TitleField);
var entryTitle = entry.Strings.ReadSafe(PwDefs.TitleField);

var context = new SprContext(entry, PluginHost.MainWindow.ActiveDatabase, SprCompileFlags.All, false, false);
var entryUsername = SprEngine.Compile(entry.Strings.ReadSafe(PwDefs.UserNameField), context);
string trayTitle;
if ((trimTrayText && entryTitle.Length + entryUsername.Length > setstat_trim_text_length) || (string.IsNullOrEmpty(entryUsername)))
{
trayTitle = entryTitle.ExtWithSpaceAfter();
}
else
{
trayTitle = entryTitle.ExtWithSpaceAfter() + entryUsername.ExtWithParenthesis();
}
PluginHost.CustomConfig.GetBool(KeeTrayTOTPExt.setname_bool_TrimTrayText, false);
var context = new SprContext(entry, PluginHost.MainWindow.ActiveDatabase, SprCompileFlags.All, false, false);
var entryUsername = SprEngine.Compile(entry.Strings.ReadSafe(PwDefs.UserNameField), context);
string trayTitle;
if ((trimTrayText && entryTitle.Length + entryUsername.Length > setstat_trim_text_length) || (string.IsNullOrEmpty(entryUsername)))
{
trayTitle = entryTitle.ExtWithSpaceAfter();
}
else
{
trayTitle = entryTitle.ExtWithSpaceAfter() + entryUsername.ExtWithParenthesis();
}
PluginHost.CustomConfig.GetBool(KeeTrayTOTPExt.setname_bool_TrimTrayText, false);

var newMenu = new ToolStripMenuItem(trayTitle, Properties.Resources.TOTP_Key, OnNotifyMenuTOTPClick);
newMenu.Tag = entry;
if (!SettingsValidate(entry))
{
newMenu.Enabled = false;
newMenu.Image = Properties.Resources.TOTP_Error;
}
_niMenuList.Add(newMenu);
var newMenu = new ToolStripMenuItem(trayTitle, Properties.Resources.TOTP_Key, OnNotifyMenuTOTPClick);
newMenu.Tag = entry;
if (!SettingsValidate(entry))
{
newMenu.Enabled = false;
newMenu.Image = Properties.Resources.TOTP_Error;
}
_niMenuList.Add(newMenu);
}
if (_niMenuList.Count > 0)
{
Expand Down Expand Up @@ -502,6 +499,19 @@ private void OnNotifyMenuOpening(object sender, CancelEventArgs e)
}
}

/// <summary>
/// Get all the password entries in all groups and filter entries that are expired or have invalid TOTP settings.
/// </summary>
/// <returns></returns>
private IEnumerable<PwEntry> GetVisibleAndValidPasswordEntries()
{
var entries = PluginHost.MainWindow.ActiveDatabase.RootGroup.GetEntries(true);

return entries
.Where(entry => !entry.IsExpired())
.Where(entry => SettingsCheck(entry) && SeedCheck(entry));
}

/// <summary>
/// Creates the necessary menu items to switch to another database
/// </summary>
Expand All @@ -520,7 +530,7 @@ private void CreateMenuItemForOtherDatabases(IList<ToolStripMenuItem> items)
};
item.Click += SwitchToOtherDatabase;
items.Add(item);

PluginHost.MainWindow.TrayContextMenu.Items.Insert(i++, item);
}
}
Expand Down Expand Up @@ -704,7 +714,7 @@ internal bool SettingsValidate(PwEntry pe, out bool isUrlValid)
/// <returns>Error(s) while validating Interval or Length.</returns>
internal bool SettingsValidate(PwEntry pe, out bool isIntervalValid, out bool isLengthValid, out bool isUrlValid)
{
bool settingsValid = true;
bool settingsValid;
try
{
string[] settings = SettingsGet(pe);
Expand All @@ -730,8 +740,8 @@ private static bool UrlIsValid(string[] settings)
{
if (settings.Length < 3)
return false;
return settings[2].StartsWith("http://") || settings[2].StartsWith("https://");

return settings[2].StartsWith("http://") || settings[2].StartsWith("https://");
}

private bool LengthIsValid(string[] settings)
Expand Down

0 comments on commit f6d1206

Please sign in to comment.