refactor(securestore): store entire connection strings in SecureStore

Eliminates placeholder substitution (${KEY}) in favor of storing complete
connection strings as single encrypted values. SecureStore now auto-creates
entries for all connection strings defined in appsettings. ConfigManager
editor reads/writes values directly to SecureStore.
This commit is contained in:
Joseph Doherty
2026-01-23 14:44:04 -05:00
parent ba54a87be5
commit bfc1c8064a
16 changed files with 462 additions and 279 deletions
@@ -294,4 +294,139 @@ public class SecureStoreManagerTests : IDisposable
// Act & Assert
Should.Throw<InvalidOperationException>(() => _sut.GetSecret("key"));
}
[Fact]
public void EnsureAllRequiredEntries_AddsMissingKeys()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
_sut.SetSecret("existingKey", "existingValue");
_sut.Save();
// Act
var addedKeys = _sut.EnsureAllRequiredEntries(
new[] { "existingKey", "newKey1" },
new[] { "LotFinder", "JDE" });
// Assert
addedKeys.Count.ShouldBe(3);
addedKeys.ShouldContain("newKey1");
addedKeys.ShouldContain("LotFinder");
addedKeys.ShouldContain("JDE");
addedKeys.ShouldNotContain("existingKey");
// Verify all keys exist
_sut.GetKeys().ShouldContain("existingKey");
_sut.GetKeys().ShouldContain("newKey1");
_sut.GetKeys().ShouldContain("LotFinder");
_sut.GetKeys().ShouldContain("JDE");
}
[Fact]
public void EnsureAllRequiredEntries_CreatesEmptyValues()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
// Act
_sut.EnsureAllRequiredEntries(
new[] { "newKey" },
Array.Empty<string>());
// Assert
_sut.GetSecret("newKey").ShouldBe(string.Empty);
}
[Fact]
public void EnsureAllRequiredEntries_DoesNotOverwriteExistingValues()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
_sut.SetSecret("existingKey", "originalValue");
_sut.Save();
// Act
var addedKeys = _sut.EnsureAllRequiredEntries(
new[] { "existingKey" },
Array.Empty<string>());
// Assert
addedKeys.ShouldBeEmpty(); // Key already existed
_sut.GetSecret("existingKey").ShouldBe("originalValue"); // Value preserved
}
[Fact]
public void EnsureAllRequiredEntries_AutoSavesWhenKeysAdded()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
// Act
_sut.EnsureAllRequiredEntries(
new[] { "newKey" },
Array.Empty<string>());
// Assert - should auto-save (HasUnsavedChanges should be false after calling EnsureAllRequiredEntries)
_sut.HasUnsavedChanges.ShouldBeFalse();
// Verify persistence
_sut.CloseStore();
_sut.OpenStore(storePath, keyPath);
_sut.GetKeys().ShouldContain("newKey");
}
[Fact]
public void EnsureAllRequiredEntries_ReturnsEmptyList_WhenNoMissingKeys()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
_sut.SetSecret("key1", "value1");
_sut.SetSecret("key2", "value2");
_sut.Save();
// Act
var addedKeys = _sut.EnsureAllRequiredEntries(
new[] { "key1" },
new[] { "key2" });
// Assert
addedKeys.ShouldBeEmpty();
}
[Fact]
public void EnsureAllRequiredEntries_WhenNoStoreOpen_ThrowsInvalidOperationException()
{
// Act & Assert
Should.Throw<InvalidOperationException>(() => _sut.EnsureAllRequiredEntries(
new[] { "key" },
Array.Empty<string>()));
}
[Fact]
public void EnsureAllRequiredEntries_HandlesDuplicatesAcrossLists()
{
// Arrange
var storePath = Path.Combine(_testDirectory, "test.json");
var keyPath = Path.Combine(_testDirectory, "test.key");
_sut.CreateStore(storePath, keyPath);
// Act - same key in both lists should not cause issues
var addedKeys = _sut.EnsureAllRequiredEntries(
new[] { "sharedKey" },
new[] { "sharedKey" });
// Assert - should only add once
addedKeys.Count.ShouldBe(1);
addedKeys.ShouldContain("sharedKey");
}
}