Skip to content

Commit

Permalink
Add password picker
Browse files Browse the repository at this point in the history
  • Loading branch information
cezarypiatek committed Jul 20, 2022
1 parent e0e273d commit a31e2a5
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 25 deletions.
19 changes: 15 additions & 4 deletions src/ScriptRunner/ScriptRunner.GUI/ParamsPanelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,11 @@ private static IControlRecord CreateControlRecord(ScriptParam p, string? value)
}
};
case PromptType.Password:
return new TextControl
return new PasswordControl
{
Control = new TextBox
Control = new PasswordBox()
{
PasswordChar = '*',
Text = value
Password = value
},
MaskingRequired = true
};
Expand Down Expand Up @@ -283,6 +282,18 @@ public string GetFormattedValue()
public string Name { get; set; }
public bool MaskingRequired { get; set; }
}
public class PasswordControl : IControlRecord
{
public IControl Control { get; set; }

public string GetFormattedValue()
{
return ((PasswordBox)Control).Password;
}

public string Name { get; set; }
public bool MaskingRequired { get; set; }
}
public class FileContent : IControlRecord
{
public IControl Control { get; set; }
Expand Down
52 changes: 31 additions & 21 deletions src/ScriptRunner/ScriptRunner.GUI/ViewModels/VaultViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using ReactiveUI;
using ScriptRunner.GUI.Settings;

namespace ScriptRunner.GUI.ViewModels
{
public static class VaultProvider
{
public static IReadOnlyList<VaultEntry> ReadFromVault()
{
var vaultPath = AppSettingsService.GetSettingsPathFor("Vault.dat");
if (File.Exists(vaultPath))
{
File.Decrypt(vaultPath);
var content = File.ReadAllText(vaultPath);
File.Encrypt(vaultPath);
var data = JsonSerializer.Deserialize<List<VaultEntry>>(content);
return data ?? new List<VaultEntry>();
}
return Array.Empty<VaultEntry>();
}

public static void UpdateVault(List<VaultEntry> date)
{
var vaultPath = AppSettingsService.GetSettingsPathFor("Vault.dat");
File.WriteAllText(vaultPath, JsonSerializer.Serialize(date), Encoding.UTF8);
File.Encrypt(vaultPath);
}
}

public class VaultViewModel : ViewModelBase
{
public ObservableCollection<VaultEntry> Entries
Expand All @@ -22,23 +49,7 @@ public ObservableCollection<VaultEntry> Entries

public VaultViewModel()
{
var vaultPath = AppSettingsService.GetSettingsPathFor("Vault.dat");
if (File.Exists(vaultPath))
{
File.Decrypt(vaultPath);
var content = File.ReadAllText(vaultPath);
File.Encrypt(vaultPath);
var data = JsonSerializer.Deserialize<List<VaultEntry>>(content);
Entries = new ObservableCollection<VaultEntry>(data?? new List<VaultEntry>());
}
else
{
Entries = new ObservableCollection<VaultEntry>()
{

};
}

Entries = new ObservableCollection<VaultEntry>(VaultProvider.ReadFromVault());
}

public void AddNewVaultEntry()
Expand All @@ -49,10 +60,9 @@ public void AddNewVaultEntry()
public void SaveVault()
{
var date = Entries.ToList();
var vaultPath = AppSettingsService.GetSettingsPathFor("Vault.dat");
File.WriteAllText(vaultPath, JsonSerializer.Serialize(date), Encoding.UTF8);
File.Encrypt(vaultPath);
VaultProvider.UpdateVault(date);
}

}

public class VaultEntry
Expand Down
16 changes: 16 additions & 0 deletions src/ScriptRunner/ScriptRunner.GUI/Views/PasswordBox.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ScriptRunner.GUI.Views.PasswordBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" PasswordChar="*" x:Name="PasswordTextBox"></TextBox>
<Button avalonia:Attached.Icon="fas fa-lock" Margin="5,0" ToolTip.Tip="Pick password from vault" Grid.Column="1" Width="50" Click="PickFromVault" VerticalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Button>
</Grid>
</UserControl>
57 changes: 57 additions & 0 deletions src/ScriptRunner/ScriptRunner.GUI/Views/PasswordBox.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using Avalonia.VisualTree;

namespace ScriptRunner.GUI.Views
{
public partial class PasswordBox : UserControl
{
public PasswordBox()
{
InitializeComponent();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}

private async void PickFromVault(object? sender, RoutedEventArgs e)
{
var pickerDialog = new VaultPicker();
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var sourceWindow = (sender as IControl)?.GetVisualRoot() as Window ?? desktop.MainWindow;
var selectedPassword = await pickerDialog.ShowDialog<string?>(sourceWindow);
if (selectedPassword != null)
{
Dispatcher.UIThread.Post(() =>
{
Password = selectedPassword;
});

}
}
}

public static readonly DirectProperty<PasswordBox, string?> PasswordProperty = AvaloniaProperty.RegisterDirect<PasswordBox, string?>
(
name: nameof(Password),
getter: picker => picker.FindControl<TextBox>("PasswordTextBox").Text,
setter: (picker, s) => picker.FindControl<TextBox>("PasswordTextBox").Text = s
);


public string? Password
{
get => GetValue(PasswordProperty);
set => SetValue(PasswordProperty, value);
}
}
}
20 changes: 20 additions & 0 deletions src/ScriptRunner/ScriptRunner.GUI/Views/VaultPicker.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Width="400"
SizeToContent="WidthAndHeight"
x:Class="ScriptRunner.GUI.Views.VaultPicker"
WindowStartupLocation="CenterOwner"
Title="Pick secret">
<StackPanel Margin="40">
<ComboBox Name="SecretsCombo" Items="{Binding}" HorizontalAlignment="Center" Margin="10,0,0,20" Width="250">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontFamily="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button HorizontalAlignment="Center" Click="Accept">Use selected secret</Button>
</StackPanel>
</Window>
28 changes: 28 additions & 0 deletions src/ScriptRunner/ScriptRunner.GUI/Views/VaultPicker.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using ScriptRunner.GUI.ViewModels;

namespace ScriptRunner.GUI.Views
{
public partial class VaultPicker : Window
{
public VaultPicker()
{

DataContext = VaultProvider.ReadFromVault();
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}



private void Accept(object? sender, RoutedEventArgs e)
{
Close((SecretsCombo.SelectedItem as VaultEntry)?.Secret);
}
}
}

0 comments on commit a31e2a5

Please sign in to comment.