WIP Protect/Unprotect Additional Field on selection

This commit is contained in:
Geoffroy BONNEVILLE
2020-05-18 22:20:31 +02:00
parent 9126307b4c
commit b7f8853ef2
17 changed files with 227 additions and 75 deletions

View File

@@ -38,11 +38,12 @@ namespace ModernKeePass
private readonly IMediator _mediator;
private readonly ISettingsProxy _settings;
private readonly INavigationService _navigation;
private readonly IHockeyClient _hockey;
private readonly INotificationService _notification;
private readonly IFileProxy _file;
private readonly IMessenger _messenger;
private readonly ILogger _log;
private readonly IHockeyClient _hockey;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
@@ -63,6 +64,7 @@ namespace ModernKeePass
_settings = Services.GetService<ISettingsProxy>();
_navigation = Services.GetService<INavigationService>();
_notification = Services.GetService<INotificationService>();
_log = Services.GetService<ILogger>();
_hockey = Services.GetService<IHockeyClient>();
_file = Services.GetService<IFileProxy>();
_messenger = Services.GetService<IMessenger>();
@@ -93,8 +95,7 @@ namespace ModernKeePass
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_hockey.TrackException(e.Exception);
_hockey.Flush();
_log.LogError(e.Exception);
}
/// <summary>
@@ -209,8 +210,7 @@ namespace ModernKeePass
}
catch (Exception ex)
{
_hockey.TrackException(ex);
_hockey.Flush();
_log.LogError(ex);
}
finally
{

View File

@@ -4,8 +4,10 @@ using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common;
using ModernKeePass.Views;
using ModernKeePass.Log;
namespace ModernKeePass
{
@@ -37,6 +39,7 @@ namespace ModernKeePass
#endif
return HockeyClient.Current;
});
services.AddSingleton(typeof(ILogger), typeof(HockeyAppLog));
return services;
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ModernKeePass.Application.Common.Interfaces;
using Microsoft.HockeyApp;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.Log
{
public class HockeyAppLog : ILogger
{
private readonly IHockeyClient _hockey;
private readonly IFileProxy _file;
private readonly IDateTime _dateTime;
public HockeyAppLog(IHockeyClient hockey, IFileProxy file, IDateTime dateTime)
{
_hockey = hockey;
_file = file;
_dateTime = dateTime;
}
public async Task LogError(Exception exception)
{
_hockey.TrackException(exception);
_hockey.Flush();
var time = _dateTime.Now.ToLocalTime();
var data = new List<string>
{
$"{time} - {exception.Message}",
$"{time} - {exception.StackTrace}"
};
await _file.WriteToLogFile(data);
}
public void LogTrace(string message, Dictionary<string, string> values)
{
_hockey.TrackTrace(message, values);
_hockey.Flush();
}
}
}

View File

@@ -35,7 +35,6 @@ using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Extensions;
using ModernKeePass.Models;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
@@ -108,7 +107,7 @@ namespace ModernKeePass.ViewModels
}
public ObservableCollection<EntryVm> History { get; private set; }
public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; }
public ObservableCollection<FieldVm> AdditionalFields { get; private set; }
public ObservableCollection<Attachment> Attachments { get; private set; }
/// <summary>
@@ -124,14 +123,8 @@ namespace ModernKeePass.ViewModels
Set(() => SelectedItem, ref _selectedItem, value, true);
if (value != null)
{
AdditionalFields =
new ObservableCollection<EntryFieldVm>(
SelectedItem.AdditionalFields.Select(f =>
{
var field = new EntryFieldVm(_cryptography);
field.Initialize(f.Name, f.Value, f.IsProtected);
return field;
}));
AdditionalFields = new ObservableCollection<FieldVm>(SelectedItem.AdditionalFields);
Attachments = new ObservableCollection<Attachment>(SelectedItem.Attachments.Select(f => new Attachment
{
Name = f.Key,
@@ -164,6 +157,13 @@ namespace ModernKeePass.ViewModels
{
Set(() => AdditionalFieldSelectedIndex, ref _additionalFieldSelectedIndex, value);
DeleteAdditionalField.RaiseCanExecuteChanged();
if (value != -1)
{
var additionalField = AdditionalFields[value];
Set(nameof(AdditionalFieldName), ref _additionalFieldName, additionalField.Name);
Set(nameof(AdditionalFieldValue), ref _additionalFieldValue, additionalField.IsProtected ? _cryptography.UnProtect(additionalField.Value).GetAwaiter().GetResult() : additionalField.Value);
Set(nameof(AdditionalFieldIsProtected), ref _additionalFieldIsProtected, additionalField.IsProtected);
}
}
}
@@ -173,7 +173,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Title.Value = value;
SetFieldValue(nameof(Title), value, false).Wait();
SetFieldValue(nameof(Title), value, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -183,7 +183,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Username.Value = value;
SetFieldValue(nameof(UserName), value, false).Wait();
SetFieldValue(nameof(UserName), value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(UserName));
}
}
@@ -193,9 +193,10 @@ namespace ModernKeePass.ViewModels
get { return _cryptography.UnProtect(SelectedItem.Password.Value).GetAwaiter().GetResult(); }
set
{
var protectedPassword = _cryptography.Protect(value).GetAwaiter().GetResult();
// TODO: cleanup this
var protectedPassword = _cryptography.Protect(value).ConfigureAwait(false).GetAwaiter().GetResult();
SelectedItem.Password.Value = protectedPassword;
SetFieldValue(nameof(Password), protectedPassword, true).Wait();
SetFieldValue(nameof(Password), value, true).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Password));
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
}
@@ -207,7 +208,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Url.Value = value;
SetFieldValue(nameof(Url), value, false).Wait();
SetFieldValue(nameof(Url), value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Url));
}
}
@@ -218,7 +219,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Notes.Value = value;
SetFieldValue(nameof(Notes), value, false).Wait();
SetFieldValue(nameof(Notes), value, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -228,7 +229,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
SetFieldValue(nameof(Icon), SelectedItem.Icon, false).Wait();
SetFieldValue(nameof(Icon), SelectedItem.Icon, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -240,7 +241,7 @@ namespace ModernKeePass.ViewModels
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = value.Date;
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).Wait();
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -252,7 +253,7 @@ namespace ModernKeePass.ViewModels
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = SelectedItem.ExpirationDate.Date.Add(value);
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).Wait();
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -262,7 +263,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.HasExpirationDate = value;
SetFieldValue(nameof(HasExpirationDate), value, false).Wait();
SetFieldValue(nameof(HasExpirationDate), value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(HasExpirationDate));
}
}
@@ -273,7 +274,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.BackgroundColor = value.ToColor();
SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor, false).Wait();
SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -283,7 +284,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.ForegroundColor = value.ToColor();
SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor, false).Wait();
SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor, false).ConfigureAwait(false).GetAwaiter();
}
}
@@ -299,6 +300,41 @@ namespace ModernKeePass.ViewModels
set { Set(() => IsRevealPassword, ref _isRevealPassword, value); }
}
private string _additionalFieldName;
private string _additionalFieldValue;
private bool _additionalFieldIsProtected;
public string AdditionalFieldName
{
get { return _additionalFieldName; }
set
{
var newName = EntryFieldName.StandardFieldNames.Contains(value) ? $"{value}_1" : value;
UpdateFieldName(_additionalFieldName, newName, AdditionalFieldValue, AdditionalFieldIsProtected).ConfigureAwait(false).GetAwaiter();
}
}
public string AdditionalFieldValue
{
get
{
return _additionalFieldValue;
}
set
{
SetFieldValue(AdditionalFieldName, value, AdditionalFieldIsProtected).ConfigureAwait(false).GetAwaiter();
}
}
public bool AdditionalFieldIsProtected
{
get { return _additionalFieldIsProtected; }
set
{
SetFieldValue(AdditionalFieldName, AdditionalFieldValue, value).ConfigureAwait(false).GetAwaiter();
}
}
public RelayCommand SaveCommand { get; }
public RelayCommand GeneratePasswordCommand { get; }
public RelayCommand<string> MoveCommand { get; }
@@ -307,7 +343,7 @@ namespace ModernKeePass.ViewModels
public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand AddAdditionalField { get; set; }
public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; set; }
public RelayCommand<FieldVm> DeleteAdditionalField { get; set; }
public RelayCommand<Attachment> OpenAttachmentCommand { get; set; }
public RelayCommand AddAttachmentCommand { get; set; }
public RelayCommand<Attachment> DeleteAttachmentCommand { get; set; }
@@ -349,7 +385,7 @@ namespace ModernKeePass.ViewModels
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
DeleteAdditionalField = new RelayCommand<FieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry);
@@ -412,7 +448,8 @@ namespace ModernKeePass.ViewModels
private async Task SetFieldValue(string fieldName, object value, bool isProtected)
{
await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value, IsProtected = isProtected});
var protectedValue = isProtected ? await _cryptography.Protect(value?.ToString()) : value;
await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = protectedValue, IsProtected = isProtected});
UpdateDirtyStatus(true);
}
@@ -424,11 +461,11 @@ namespace ModernKeePass.ViewModels
private void AddField()
{
AdditionalFields.Add(new EntryFieldVm(_cryptography));
AdditionalFields.Add(new FieldVm());
AdditionalFieldSelectedIndex = AdditionalFields.Count - 1;
}
private async Task DeleteField(EntryFieldVm field)
private async Task DeleteField(FieldVm field)
{
AdditionalFields.Remove(field);
if (!string.IsNullOrEmpty(field.Name))

View File

@@ -321,7 +321,6 @@
<Flyout>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
<!--<actions:CloseFlyoutAction />-->
<core:CallMethodAction MethodName="Hide" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
@@ -506,12 +505,12 @@
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Name, Mode=TwoWay}" Width="350"
<TextBox Grid.Row="0" Text="{Binding Path=DataContext.AdditionalFieldName, ElementName=Page, Mode=TwoWay}" Width="350"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<TextBox Grid.Row="1" AcceptsReturn="True" Height="100" TextWrapping="Wrap" Width="350" Margin="0,5,0,0"
Text="{Binding Value, Mode=TwoWay}"
Text="{Binding Path=DataContext.AdditionalFieldValue, ElementName=Page, Mode=TwoWay}"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<ToggleSwitch Grid.Row="2" x:Uid="EntryEnableFieldProtection" HorizontalAlignment="Left" IsOn="{Binding IsProtected, Mode=TwoWay}" />
<ToggleSwitch Grid.Row="2" x:Uid="EntryEnableFieldProtection" HorizontalAlignment="Left" IsOn="{Binding Path=DataContext.AdditionalFieldIsProtected, ElementName=Page, Mode=TwoWay}" />
<Button Grid.Row="2" x:Uid="EntryDeleteAdditionalField" HorizontalAlignment="Right" Margin="0,15,0,0" Command="{Binding Path=DataContext.DeleteAdditionalField, ElementName=Page}" CommandParameter="{Binding}" />
</Grid>
</DataTemplate>

View File

@@ -7,8 +7,8 @@
mc:Ignorable="d">
<ComboBox x:Name="ComboBox"
ItemsSource="{Binding Colors, ElementName=UserControl}"
SelectionChanged="Selector_OnSelectionChanged"
Loaded="ComboBox_Loaded"
SelectedValue="{Binding SelectedColor, ElementName=UserControl, Mode=TwoWay}"
SelectedValuePath="ColorBrush"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}">
<ComboBox.ItemTemplate>
<DataTemplate>

View File

@@ -46,16 +46,5 @@ namespace ModernKeePass.Views.UserControls
});
}
}
private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
ComboBox.SelectedItem = Colors.Find(c => c.ColorBrush.Color.Equals(SelectedColor.Color));
}
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedItem = ComboBox.SelectedItem as Color? ?? new Color();
SelectedColor = selectedItem.ColorBrush;
}
}
}

View File

@@ -93,6 +93,7 @@
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="DependencyInjection.cs" />
<Compile Include="Log\HockeyAppLog.cs" />
<Compile Include="Models\NavigationItem.cs" />
<Compile Include="ViewModels\ViewModelLocator.cs" />
<Compile Include="Views\MainPageFrames\DonatePage.xaml.cs">