feat(configmanager): integrate SecureStore for credential management
Add SecureStore integration to ConfigManager for secure handling of connection strings and sensitive configuration values. Includes store/secret management UI, encrypted .store file support, and comprehensive test coverage.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using JdeScoping.ConfigManager.Constants;
|
||||
using JdeScoping.ConfigManager.ViewModels.Dialogs;
|
||||
using MsBox.Avalonia;
|
||||
using MsBox.Avalonia.Enums;
|
||||
|
||||
namespace JdeScoping.ConfigManager.Views.Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// Dialog for unlocking an existing secure store.
|
||||
/// </summary>
|
||||
public partial class UnlockStoreDialog : Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the view model for this dialog.
|
||||
/// </summary>
|
||||
public UnlockStoreDialogViewModel ViewModel => (UnlockStoreDialogViewModel)DataContext!;
|
||||
|
||||
/// <summary>
|
||||
/// Design-time constructor. Required for XAML previewer.
|
||||
/// </summary>
|
||||
public UnlockStoreDialog() : this(string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnlockStoreDialog"/> class.
|
||||
/// </summary>
|
||||
/// <param name="storePath">The path to the store file to unlock.</param>
|
||||
public UnlockStoreDialog(string storePath)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new UnlockStoreDialogViewModel(storePath);
|
||||
Loaded += UnlockStoreDialog_Loaded;
|
||||
}
|
||||
|
||||
private void UnlockStoreDialog_Loaded(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.OnShowOpenFileDialog += ShowOpenFileDialogAsync;
|
||||
}
|
||||
|
||||
private async Task<string?> ShowOpenFileDialogAsync(string title, string fileTypeName, string pattern)
|
||||
{
|
||||
var files = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = title,
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = new[]
|
||||
{
|
||||
new FilePickerFileType(fileTypeName) { Patterns = new[] { pattern } },
|
||||
new FilePickerFileType(SecureStoreFileExtensions.AllFilesTypeName) { Patterns = new[] { SecureStoreFileExtensions.AllFilesPattern } }
|
||||
}
|
||||
});
|
||||
|
||||
return files.Count > 0 ? files[0].Path.LocalPath : null;
|
||||
}
|
||||
|
||||
private async void UnlockButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!ViewModel.IsValid)
|
||||
{
|
||||
var box = MessageBoxManager.GetMessageBoxStandard(
|
||||
SecureStoreStrings.ValidationErrorTitle,
|
||||
ViewModel.ValidationError ?? SecureStoreStrings.DefaultValidationError,
|
||||
ButtonEnum.Ok,
|
||||
MsBox.Avalonia.Enums.Icon.Warning);
|
||||
await box.ShowWindowDialogAsync(this);
|
||||
return;
|
||||
}
|
||||
|
||||
Close(true);
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
Close(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user