Skip to content

Commit

Permalink
Merge pull request #12 from VictorGrycuk/dev/1.5.0
Browse files Browse the repository at this point in the history
[v1.5.0] Whole refactor of the project, new actions, new options, a few improvements
  • Loading branch information
VictorGrycuk authored Jan 22, 2022
2 parents bbf9859 + 5164f87 commit 01d6de3
Show file tree
Hide file tree
Showing 38 changed files with 1,045 additions and 351 deletions.
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ It uses the following configuration:

- **KeePass db path.** The absolute path to the KeePass file.
- **KeePass db password.** The main password of the KeePass file.
- **Entry Name.** The name of the entry that has the desired information.
- **Entry Name or UUID.** The name or UUID of the entry that has the desired information.
- **Field to retrieve.** The field whose content will be copied to the clipboard
- Password
- Username
- Notes
- URL
- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default).



Expand All @@ -42,9 +43,44 @@ It uses the following configuration:
- **Characters to Exclude.** Any character included in the text field will be excluded from the generated password.
- **Custom Pattern.** Allows to use a custom defined password generation pattern. Refer to the section *Generating Passwords that Follow Rules* of [KeePass Password Generator](https://keepass.info/help/base/pwgenerator.html) documentation.
- ***Note***: Using a custom pattern will override all the previous configuration.
- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default).

Check [KeePass Password Generator](https://keepass.info/help/base/pwgenerator.html) help site for more information.



#### Aware

Its function its identical to *Retrieve*, except it retrieves the stored field based on the current active window.

It only replaces the Entry Name option with a new one:

- **Process Mapping.** A `key=value` that maps a running process with a KeePass entry title/UUID.
- Examples:
- `steam.exe=Steam`
- `Discord.exe=2A8CC713A463524C928E1F613BA10DAC`
- Add one mapping per line.



#### MircoBabin's KeePassCommander

It allows direct communication with the KeePass application to retrieve a field of a stored entry to the clipboard. **Note**: It requires the **[KeePassCommander](https://github.com/MircoBabin/KeePassCommander)** plugin for KeePass.

It uses the following configuration:

- **CommandDLL path**. The absolute path to the `KeePassCommandDll.dll`.
- **Entry Name.** The name of the entry that has the desired information.
- **Note**: It does not support search by UUID.
- **Field to retrieve.** The field whose content will be copied to the clipboard
- Password
- Username
- Notes
- URL
- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default).



## My other Stream Deck plugins

- **[Color Picker](https://github.com/VictorGrycuk/streamdeck-color-picker)**
Expand Down
28 changes: 28 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionAware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BarRaider.SdTools;
using Newtonsoft.Json.Linq;
using streamdeck_keepass.Actions;
using StreamDeck_KeePass.Domain.Settings;

namespace StreamDeck_KeePass.Actions
{
[PluginActionId("com.victorgrycuk.keepass.aware")]
public class ActionAware : ActionBase
{
private readonly AwareSettings settings;

public ActionAware(SDConnection connection, InitialPayload payload) : base(connection, payload)
{
settings = ResolveSettings<AwareSettings>(payload, AwareSettings.CreateDefaultSettings());
CreatePlugin(settings);
}

public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found.");

public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
Tools.AutoPopulateSettings(settings, payload.Settings);
SaveSettings(JObject.FromObject(settings));
CreatePlugin(settings);
}
}
}
62 changes: 62 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using BarRaider.SdTools;
using Newtonsoft.Json.Linq;
using streamdeck_keepass.Domain;
using StreamDeck_KeePass.Domain.Settings;
using System.Threading.Tasks;

namespace streamdeck_keepass.Actions
{
abstract public class ActionBase : PluginBase
{
private KeePassPlugin plugin;

public ActionBase(SDConnection connection, InitialPayload payload) : base(connection, payload) { }

internal void CreatePlugin(GenerateSettings settings) => plugin = new KeePassPlugin(settings);

internal void CreatePlugin(RetrieveSettings settings) => plugin = new KeePassPlugin(settings);

internal void CreatePlugin(AwareSettings settings) => plugin = new KeePassPlugin(settings);

internal void CreatePlugin(CommanderSettings settings) => plugin = new KeePassPlugin(settings);

public override void Dispose() => Logger.Instance.LogMessage(TracingLevel.INFO, "Destructor called");

public void ExecuteAction(string logMessage)
{
try
{
var result = plugin.Invoke();

if (result == Result.WARNING)
{
Connection.ShowAlert().Wait();
Logger.Instance.LogMessage(TracingLevel.WARN, logMessage);
}
else
{
Connection.ShowOk().Wait();
}
}
catch (System.Exception ex)
{
Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message);
}
}

public override void KeyReleased(KeyPayload payload) { }

public override void OnTick() { }

public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { }

internal T ResolveSettings<T>(InitialPayload payload, object defaultConfig) where T : class
{
return payload.Settings == null || payload.Settings.Count == 0
? defaultConfig as T
: payload.Settings.ToObject<T>();
}

internal Task SaveSettings(JObject settings) => Connection.SetSettingsAsync(settings);
}
}
28 changes: 28 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionCommander.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BarRaider.SdTools;
using Newtonsoft.Json.Linq;
using streamdeck_keepass.Actions;
using StreamDeck_KeePass.Domain.Settings;

namespace StreamDeck_KeePass.Actions
{
[PluginActionId("com.victorgrycuk.keepass.commander")]
public class ActionCommander : ActionBase
{
private readonly CommanderSettings settings;

public ActionCommander(SDConnection connection, InitialPayload payload) : base(connection, payload)
{
settings = ResolveSettings<CommanderSettings>(payload, CommanderSettings.CreateDefaultSettings());
CreatePlugin(settings);
}

public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found.");

public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
Tools.AutoPopulateSettings(settings, payload.Settings);
SaveSettings(JObject.FromObject(settings));
CreatePlugin(settings);
}
}
}
28 changes: 28 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionGenerate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BarRaider.SdTools;
using Newtonsoft.Json.Linq;
using streamdeck_keepass.Actions;
using StreamDeck_KeePass.Domain.Settings;

namespace StreamDeck_KeePass.Actions
{
[PluginActionId("com.victorgrycuk.keepass.generate")]
public class ActionGenerate : ActionBase
{
private readonly GenerateSettings settings;

public ActionGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload)
{
settings = ResolveSettings<GenerateSettings>(payload, GenerateSettings.CreateDefaultSettings());
CreatePlugin(settings);
}

public override void KeyPressed(KeyPayload payload) => ExecuteAction("No password was generated with the given configuration.");

public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
Tools.AutoPopulateSettings(settings, payload.Settings);
SaveSettings(JObject.FromObject(settings));
CreatePlugin(settings);
}
}
}
28 changes: 28 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionRetrieve.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BarRaider.SdTools;
using Newtonsoft.Json.Linq;
using streamdeck_keepass.Actions;
using StreamDeck_KeePass.Domain.Settings;

namespace StreamDeck_KeePass.Actions
{
[PluginActionId("com.victorgrycuk.keepass.retrieve")]
public class ActionRetrieve : ActionBase
{
private readonly RetrieveSettings settings;

public ActionRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload)
{
settings = ResolveSettings<RetrieveSettings>(payload, RetrieveSettings.CreateDefaultSettings());
CreatePlugin(settings);
}

public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found.");

public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
Tools.AutoPopulateSettings(settings, payload.Settings);
SaveSettings(JObject.FromObject(settings));
CreatePlugin(settings);
}
}
}
20 changes: 0 additions & 20 deletions StreamDeck-KeePass/StreamDeck-KeePass/ClipboardHelper.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace streamdeck_keepass.Domain
{
internal interface IKeePassAction
{
string Invoke();
}
}
76 changes: 76 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassAware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using streamdeck_keepass.Services;
using StreamDeck_KeePass.Domain.Settings;
using System.Collections.Generic;
using System.Linq;

namespace streamdeck_keepass.Domain
{
internal class KeePassAware : IKeePassAction
{
private readonly AwareSettings settings;

public KeePassAware(object objectSettings) => settings = objectSettings as AwareSettings;

public string Invoke()
{
var db = OpenDB(settings);
var mapping = GetMapping(settings.ProcessMapping);
if (!mapping.TryGetValue(ProcessHelper.GetActiveProcessFileName(), out string entryId)) return string.Empty;
var foundEntry = GetKeePassEntry(db, entryId);

if (foundEntry == null)
{
return string.Empty;
}

db.Close();

switch (settings.Field)
{
case "Password":
return foundEntry.Password;
case "Username":
return foundEntry.Username;
case "Notes":
return foundEntry.Notes;
case "URL":
return foundEntry.URL;
default:
return string.Empty;
}
}

static private PwDatabase OpenDB(AwareSettings settings)
{
var conn = new IOConnectionInfo { Path = settings.DBPath };
var compKey = new CompositeKey();
compKey.AddUserKey(new KcpPassword(settings.Password));

if (!string.IsNullOrEmpty(settings.KeyFilePath))
{
compKey.AddUserKey(new KcpKeyFile(settings.KeyFilePath));
}

var db = new PwDatabase();
db.Open(conn, compKey, null);

return db;
}

private Dictionary<string, string> GetMapping(string entries)
{
var dictionary = new Dictionary<string, string>();
var lines = entries.Split('\n').ToList();
lines.ForEach(l => dictionary.Add(l.Split('=')[0], l.Split('=')[1]));

return dictionary;
}

static private KeePassEntry GetKeePassEntry(PwDatabase db, string matchingValue) => (from entry in db.RootGroup.GetEntries(true)
where entry.Strings.ReadSafe("Title") == matchingValue || entry.Uuid.ToHexString() == matchingValue
select new KeePassEntry(entry)).FirstOrDefault();
}
}
38 changes: 38 additions & 0 deletions StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassCommander.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using StreamDeck_KeePass.Domain.Settings;

namespace streamdeck_keepass.Domain
{
internal class KeePassCommander : IKeePassAction
{
private readonly CommanderSettings settings;

public KeePassCommander(object objectSettings)
{
settings = objectSettings as CommanderSettings;

if (!KeePassCommand.KeePassEntry.IsInitialized())
KeePassCommand.KeePassEntry.Initialize(settings.CommandDLLPath);
}

public string Invoke()
{
var entry = KeePassCommand.KeePassEntry.getfirst(settings.EntryTitle);

if (entry == null) return string.Empty;

switch (settings.Field)
{
case "Password":
return entry.Password;
case "Username":
return entry.Username;
case "Notes":
return entry.Notes;
case "URL":
return entry.Url;
default:
return string.Empty;
}
}
}
}
Loading

0 comments on commit 01d6de3

Please sign in to comment.