refactor(securestore): remove password-based authentication in favor of key-file only

Simplify SecureStore by removing MasterKeyEnvVar and password-based methods, leaving only key-file authentication for better security practices.
This commit is contained in:
Joseph Doherty
2026-01-23 00:17:19 -05:00
parent 9c4a184233
commit 1b7bb26def
22 changed files with 101 additions and 1421 deletions
@@ -12,7 +12,6 @@ public class NewStoreDialogViewModelTests
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = string.Empty;
sut.UseKeyFile = true;
sut.KeyFilePath = "/path/to/key.key";
// Act & Assert
@@ -20,12 +19,11 @@ public class NewStoreDialogViewModelTests
}
[Fact]
public void IsValid_WhenUseKeyFileButKeyFilePathEmpty_ReturnsFalse()
public void IsValid_WhenKeyFilePathEmpty_ReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = string.Empty;
// Act & Assert
@@ -33,87 +31,17 @@ public class NewStoreDialogViewModelTests
}
[Fact]
public void IsValid_WhenUsePasswordButPasswordEmpty_ReturnsFalse()
public void IsValid_WithValidConfiguration_ReturnsTrue()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = string.Empty;
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void IsValid_WhenPasswordsDoNotMatch_ReturnsFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = "password123";
sut.ConfirmPassword = "different456";
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void IsValid_WithValidKeyFileConfiguration_ReturnsTrue()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = "/path/to/key.key";
// Act & Assert
sut.IsValid.ShouldBeTrue();
}
[Fact]
public void IsValid_WithValidPasswordConfiguration_ReturnsTrue()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = "password123";
sut.ConfirmPassword = "password123";
// Act & Assert
sut.IsValid.ShouldBeTrue();
}
[Fact]
public void UseKeyFile_WhenSetToTrue_SetsUsePasswordToFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.UsePassword = true;
// Act
sut.UseKeyFile = true;
// Assert
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void UsePassword_WhenSetToTrue_SetsUseKeyFileToFalse()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.UseKeyFile = true;
// Act
sut.UsePassword = true;
// Assert
sut.UseKeyFile.ShouldBeFalse();
}
[Fact]
public void ValidationError_WhenStorePathEmpty_ReturnsAppropriateMessage()
{
@@ -131,47 +59,18 @@ public class NewStoreDialogViewModelTests
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = string.Empty;
// Act & Assert
sut.ValidationError.ShouldBe("Key file path is required.");
}
[Fact]
public void ValidationError_WhenPasswordEmpty_ReturnsAppropriateMessage()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = string.Empty;
// Act & Assert
sut.ValidationError.ShouldBe("Password is required.");
}
[Fact]
public void ValidationError_WhenPasswordsDoNotMatch_ReturnsAppropriateMessage()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = "password123";
sut.ConfirmPassword = "different456";
// Act & Assert
sut.ValidationError.ShouldBe("Passwords do not match.");
}
[Fact]
public void ValidationError_WhenValid_ReturnsNull()
{
// Arrange
var sut = new NewStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = "/path/to/key.key";
// Act & Assert
@@ -193,85 +92,17 @@ public class OpenStoreDialogViewModelTests
}
[Fact]
public void IsValid_WhenUseKeyFileButKeyFilePathEmpty_ReturnsFalse()
public void IsValid_WhenKeyFilePathEmpty_ReturnsFalse()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = string.Empty;
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void IsValid_WhenUsePasswordButPasswordEmpty_ReturnsFalse()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = string.Empty;
// Act & Assert
sut.IsValid.ShouldBeFalse();
}
[Fact]
public void IsValid_WithValidKeyFileConfiguration_ReturnsTrue()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UseKeyFile = true;
sut.KeyFilePath = "/path/to/key.key";
// Act & Assert
sut.IsValid.ShouldBeTrue();
}
[Fact]
public void IsValid_WithValidPasswordConfiguration_ReturnsTrue()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.StorePath = "/path/to/store.json";
sut.UsePassword = true;
sut.Password = "password123";
// Act & Assert
sut.IsValid.ShouldBeTrue();
}
[Fact]
public void UseKeyFile_WhenSetToTrue_SetsUsePasswordToFalse()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.UsePassword = true;
// Act
sut.UseKeyFile = true;
// Assert
sut.UsePassword.ShouldBeFalse();
}
[Fact]
public void UsePassword_WhenSetToTrue_SetsUseKeyFileToFalse()
{
// Arrange
var sut = new OpenStoreDialogViewModel();
sut.UseKeyFile = true;
// Act
sut.UsePassword = true;
// Assert
sut.UseKeyFile.ShouldBeFalse();
}
[Fact]
public void ValidationError_WhenStorePathEmpty_ReturnsAppropriateMessage()
{
@@ -303,7 +134,6 @@ public class OpenStoreDialogViewModelTests
{
var sut = new OpenStoreDialogViewModel();
sut.StorePath = tempFile;
sut.UseKeyFile = true;
sut.KeyFilePath = string.Empty;
// Act & Assert
@@ -324,7 +154,6 @@ public class OpenStoreDialogViewModelTests
{
var sut = new OpenStoreDialogViewModel();
sut.StorePath = tempFile;
sut.UseKeyFile = true;
sut.KeyFilePath = "/nonexistent/key.key";
// Act & Assert
@@ -335,27 +164,6 @@ public class OpenStoreDialogViewModelTests
File.Delete(tempFile);
}
}
[Fact]
public void ValidationError_WhenPasswordEmpty_ReturnsAppropriateMessage()
{
// Arrange - Create temp store file so we get past that validation
var tempFile = Path.GetTempFileName();
try
{
var sut = new OpenStoreDialogViewModel();
sut.StorePath = tempFile;
sut.UsePassword = true;
sut.Password = string.Empty;
// Act & Assert
sut.ValidationError.ShouldBe("Password is required.");
}
finally
{
File.Delete(tempFile);
}
}
}
public class SecretEditDialogViewModelTests