Update credentials better looking

This commit is contained in:
Geoffroy BONNEVILLE
2020-04-30 15:32:42 +02:00
parent d2814c6c67
commit 1b981b00d5
8 changed files with 145 additions and 45 deletions

View File

@@ -331,6 +331,7 @@ namespace ModernKeePass.Infrastructure.KeePass
public void UpdateCredentials(Credentials credentials)
{
_pwDatabase.MasterKey = CreateCompositeKey(credentials);
_credentials = credentials;
}
public IEnumerable<EntryEntity> Search(string groupId, string text)

View File

@@ -85,10 +85,10 @@ namespace ModernKeePass
? exception.InnerException
: exception;
_hockey.TrackException(realException);
if (realException is SaveException)
{
unhandledExceptionEventArgs.Handled = true;
_hockey.TrackException(realException);
await _dialog.ShowMessage(realException.Message,
_resource.GetResourceValue("MessageDialogSaveErrorTitle"),
_resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"),
@@ -116,10 +116,6 @@ namespace ModernKeePass
}
});
}
else
{
await _dialog.ShowError(realException, realException.Message, "OK", () => {});
}
}
/// <summary>

View File

@@ -504,4 +504,13 @@
<data name="MoveButton.Content" xml:space="preserve">
<value>Move</value>
</data>
<data name="SetCredentialsControlMatchingPasswords.Text" xml:space="preserve">
<value>Passwords must match</value>
</data>
<data name="SetCredentialsControlMissingKeyFile.Text" xml:space="preserve">
<value>Key file can't be empty</value>
</data>
<data name="CompositeKeyConfirmPassword.PlaceholderText" xml:space="preserve">
<value>Confirm password</value>
</data>
</root>

View File

@@ -507,4 +507,13 @@
<data name="MoveButton.Content" xml:space="preserve">
<value>Déplacer</value>
</data>
<data name="SetCredentialsControlMatchingPasswords.Text" xml:space="preserve">
<value>Les mots de passe doivent être égaux</value>
</data>
<data name="SetCredentialsControlMissingKeyFile.Text" xml:space="preserve">
<value>Vous devez sélectionner un fichier de clé</value>
</data>
<data name="CompositeKeyConfirmPassword.PlaceholderText" xml:space="preserve">
<value>Confirmer le mot de passe</value>
</data>
</root>

View File

@@ -35,12 +35,14 @@
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</PasswordBox>
<CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding HasKeyFile, Mode=TwoWay}" />
<HyperlinkButton Grid.Row="1" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton"
Content="{Binding KeyFileText}"
IsEnabled="{Binding HasKeyFile}"
Click="KeyFileButton_Click" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
x:Uid="OpenDatabaseControlButton"
Visibility="{Binding IsOpening, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
@@ -49,7 +51,7 @@
<ProgressRing Grid.Column="0" Grid.Row="2" IsActive="{Binding IsOpening}" Visibility="{Binding IsOpening, Converter={StaticResource BooleanToVisibilityConverter}}" Foreground="{StaticResource MainColorBrush}" />
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="Auto" FontSize="14" FontWeight="Light"
Text="{Binding Status}"
Foreground="Red"
Foreground="{StaticResource ErrorBrush}"
Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
<VisualStateManager.VisualStateGroups>

View File

@@ -11,9 +11,13 @@
<UserControl.Resources>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToSolidColorBrushConverter"/>
<converters:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid x:Name="Grid" DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}">
<Grid.Resources>
<SolidColorBrush x:Key="ErrorBrush" Color="Red" />
<SolidColorBrush x:Key="ValidBrush" Color="Green" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
@@ -21,29 +25,45 @@
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" />
<PasswordBox Grid.Row="0" Grid.Column="1" x:Uid="CompositeKeyPassword" Password="{Binding Password, Mode=TwoWay}" Height="30" IsPasswordRevealButtonEnabled="True" BorderBrush="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}">
<PasswordBox Grid.Row="0" Grid.Column="1" Height="30"
x:Uid="CompositeKeyPassword"
x:Name="PasswordBox"
Password="{Binding Password, Mode=TwoWay}"
IsPasswordRevealButtonEnabled="True" >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="GotFocus">
<core:ChangePropertyAction TargetObject="{Binding}" PropertyName="HasPassword" Value="True" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</PasswordBox>
<PasswordBox Grid.Row="1" Grid.Column="1" x:Uid="CompositeKeyPassword" Password="{Binding ConfirmPassword, Mode=TwoWay}" Height="30" IsPasswordRevealButtonEnabled="True" BorderBrush="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" />
<PasswordBox Grid.Row="1" Grid.Column="1" Height="30"
x:Uid="CompositeKeyConfirmPassword"
x:Name="ConfirmPasswordBox"
Password="{Binding ConfirmPassword, Mode=TwoWay}"
IsPasswordRevealButtonEnabled="True" />
<ProgressBar Grid.Row="1" Grid.Column="1"
Maximum="128" VerticalAlignment="Bottom"
Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}"
Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToSolidColorBrushConverter}}"/>
<CheckBox Grid.Row="2" Grid.Column="0" IsChecked="{Binding HasKeyFile, Mode=TwoWay}" />
<HyperlinkButton Grid.Row="2" Grid.Column="1" Margin="-15,0,0,0"
<TextBlock Grid.Row="2" Grid.Column="1"
FontSize="14" FontWeight="Light"
x:Uid="SetCredentialsControlMatchingPasswords"
Foreground="{StaticResource ErrorBrush}"
Visibility="{Binding IsPasswordValid, Converter={StaticResource InverseBooleanToVisibilityConverter}}" />
<CheckBox Grid.Row="3" Grid.Column="0" IsChecked="{Binding HasKeyFile, Mode=TwoWay}" />
<HyperlinkButton Grid.Row="3" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton"
Content="{Binding KeyFileText}"
IsEnabled="{Binding HasKeyFile}"
Click="KeyFileButton_Click" />
<HyperlinkButton Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right"
<HyperlinkButton Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right"
IsEnabled="{Binding HasKeyFile}"
Click="CreateKeyFileButton_Click">
<SymbolIcon Symbol="Add">
@@ -52,12 +72,82 @@
</ToolTipService.ToolTip>
</SymbolIcon>
</HyperlinkButton>
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3"
<TextBlock Grid.Row="4" Grid.Column="1" FontSize="14" FontWeight="Light"
x:Uid="SetCredentialsControlMissingKeyFile"
Foreground="{StaticResource ErrorBrush}"
Visibility="{Binding IsKeyFileValid, Converter={StaticResource InverseBooleanToVisibilityConverter}}" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="5"
Command="{Binding GenerateCredentialsCommand}"
Content="{Binding ButtonLabel, ElementName=UserControl}" />
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4" Height="Auto" FontSize="14" FontWeight="Light"
Text="{Binding Status}"
Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}"
Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CredentialStatus">
<VisualState x:Name="PasswordError">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ErrorBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ConfirmPasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ErrorBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PasswordValid">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ValidBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ConfirmPasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ValidBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="KeyFileError">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HyperlinkButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ErrorBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="KeyFileValid">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HyperlinkButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ValidBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Initial">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ConfirmPasswordBox" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HyperlinkButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource HyperlinkForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsPasswordValid}" Value="False">
<core:GoToStateAction StateName="PasswordError"/>
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsPasswordValid}" Value="True">
<core:GoToStateAction StateName="PasswordValid"/>
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsKeyFileValid}" Value="False">
<core:GoToStateAction StateName="KeyFileError"/>
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsKeyFileValid}" Value="True">
<core:GoToStateAction StateName="KeyFileValid"/>
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsValid}" Value="True">
<core:GoToStateAction StateName="Initial"/>
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Grid>
</UserControl>

View File

@@ -2,6 +2,6 @@
{
public class SaveErrorMessage
{
public string Message { get; set; }
}
}

View File

@@ -19,6 +19,7 @@ namespace ModernKeePass.ViewModels
set
{
Set(() => HasPassword, ref _hasPassword, value);
RaisePropertyChanged(nameof(IsPasswordValid));
RaisePropertyChanged(nameof(IsValid));
GenerateCredentialsCommand.RaiseCanExecuteChanged();
}
@@ -30,23 +31,19 @@ namespace ModernKeePass.ViewModels
set
{
Set(() => HasKeyFile, ref _hasKeyFile, value);
RaisePropertyChanged(nameof(IsKeyFileValid));
RaisePropertyChanged(nameof(IsValid));
GenerateCredentialsCommand.RaiseCanExecuteChanged();
}
}
public string Status
{
get { return _status; }
set { Set(() => Status, ref _status, value); }
}
public string Password
{
get { return _password; }
set
{
_password = value;
RaisePropertyChanged(nameof(IsPasswordValid));
RaisePropertyChanged(nameof(IsValid));
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
GenerateCredentialsCommand.RaiseCanExecuteChanged();
@@ -58,6 +55,7 @@ namespace ModernKeePass.ViewModels
set
{
_confirmPassword = value;
RaisePropertyChanged(nameof(IsPasswordValid));
RaisePropertyChanged(nameof(IsValid));
GenerateCredentialsCommand.RaiseCanExecuteChanged();
}
@@ -69,6 +67,7 @@ namespace ModernKeePass.ViewModels
set
{
_keyFilePath = value;
RaisePropertyChanged(nameof(IsKeyFileValid));
RaisePropertyChanged(nameof(IsValid));
GenerateCredentialsCommand.RaiseCanExecuteChanged();
}
@@ -80,26 +79,20 @@ namespace ModernKeePass.ViewModels
set { Set(() => KeyFileText, ref _keyFileText, value); }
}
public string OpenButtonLabel
{
get { return _openButtonLabel; }
set { Set(() => OpenButtonLabel, ref _openButtonLabel, value); }
}
public double PasswordComplexityIndicator => _credentials.EstimatePasswordComplexity(Password);
public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath);
public bool IsPasswordValid => HasPassword && Password == ConfirmPassword || !HasPassword;
public bool IsKeyFileValid => HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) || !HasKeyFile;
public bool IsValid => (IsPasswordValid || IsKeyFileValid) && (HasPassword || HasKeyFile);
public RelayCommand GenerateCredentialsCommand{ get; }
private bool _hasPassword;
private bool _hasKeyFile;
private string _password = string.Empty;
private string _confirmPassword;
private string _status;
private string _confirmPassword = string.Empty;
private string _keyFilePath;
private string _keyFileText;
private string _openButtonLabel;
public SetCredentialsVm(IMediator mediator, ICredentialsProxy credentials, IResourceProxy resource)
{