Added a password rule engine
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
SelectedValueBinding="{ReflectionBinding Value}">
|
SelectedValueBinding="{ReflectionBinding Value}">
|
||||||
<ComboBox.Styles>
|
<ComboBox.Styles>
|
||||||
<Style Selector="ComboBox.Write">
|
<Style Selector="ComboBox.Write">
|
||||||
<Setter Property="MinWidth" Value="296" />
|
<Setter Property="MinWidth" Value="{Binding Width}" />
|
||||||
<Setter Property="IsVisible" Value="True" />
|
<Setter Property="IsVisible" Value="True" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="ComboBox.Read">
|
<Style Selector="ComboBox.Read">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<MaskedTextBox Mask="{Binding Pattern}" Text="{Binding Value}">
|
<MaskedTextBox Mask="{Binding Pattern}" Text="{Binding Value}">
|
||||||
<TextBox.Styles>
|
<TextBox.Styles>
|
||||||
<Style Selector="TextBox.Write">
|
<Style Selector="TextBox.Write">
|
||||||
<Setter Property="MinWidth" Value="296" />
|
<Setter Property="MinWidth" Value="{Binding Width}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="TextBox.Read">
|
<Style Selector="TextBox.Read">
|
||||||
<Setter Property="MinWidth" Value="0" />
|
<Setter Property="MinWidth" Value="0" />
|
||||||
|
|||||||
@@ -7,15 +7,58 @@
|
|||||||
Header="{Binding Key}">
|
Header="{Binding Key}">
|
||||||
<SettingsExpander.Footer>
|
<SettingsExpander.Footer>
|
||||||
<TextBox
|
<TextBox
|
||||||
MinWidth="264"
|
|
||||||
Classes="revealPasswordButton"
|
Classes="revealPasswordButton"
|
||||||
PasswordChar="●"
|
PasswordChar="●"
|
||||||
Text="{Binding Value}">
|
Text="{Binding Value}">
|
||||||
|
<TextBox.Styles>
|
||||||
|
<Style Selector="TextBox.Write">
|
||||||
|
<Setter Property="MinWidth" Value="{Binding Width}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="TextBox.Read">
|
||||||
|
<Setter Property="MinWidth" Value="0" />
|
||||||
|
<Setter Property="IsReadOnly" Value="True" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^:pointerover">
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Border#PART_BorderElement">
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:focus">
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Border#PART_BorderElement">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Styles>
|
||||||
<Interaction.Behaviors>
|
<Interaction.Behaviors>
|
||||||
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
|
||||||
<AddClassAction ClassName="Read" RemoveIfExists="True" />
|
<AddClassAction ClassName="Read" RemoveIfExists="True" />
|
||||||
|
<RemoveClassAction ClassName="Write" />
|
||||||
|
</DataTriggerBehavior>
|
||||||
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
|
||||||
|
<AddClassAction ClassName="Write" RemoveIfExists="True" />
|
||||||
|
<RemoveClassAction ClassName="Read" />
|
||||||
</DataTriggerBehavior>
|
</DataTriggerBehavior>
|
||||||
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
|
||||||
|
<AddClassAction ClassName="Write" RemoveIfExists="True" />
|
||||||
<RemoveClassAction ClassName="Read" />
|
<RemoveClassAction ClassName="Read" />
|
||||||
</DataTriggerBehavior>
|
</DataTriggerBehavior>
|
||||||
</Interaction.Behaviors>
|
</Interaction.Behaviors>
|
||||||
|
|||||||
@@ -6,6 +6,59 @@
|
|||||||
x:DataType="vm:TextEntryViewModel"
|
x:DataType="vm:TextEntryViewModel"
|
||||||
Header="{Binding Key}">
|
Header="{Binding Key}">
|
||||||
<SettingsExpander.Footer>
|
<SettingsExpander.Footer>
|
||||||
<DatePicker />
|
<TextBox Text="{Binding Value}">
|
||||||
|
<TextBox.Styles>
|
||||||
|
<Style Selector="TextBox.Write">
|
||||||
|
<Setter Property="MinWidth" Value="{Binding Width}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="TextBox.Read">
|
||||||
|
<Setter Property="MinWidth" Value="0" />
|
||||||
|
<Setter Property="IsReadOnly" Value="True" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^:pointerover">
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Border#PART_BorderElement">
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:focus">
|
||||||
|
<Setter Property="Foreground">
|
||||||
|
<Setter.Value>
|
||||||
|
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^ /template/ Border#PART_BorderElement">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Styles>
|
||||||
|
<Interaction.Behaviors>
|
||||||
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
|
||||||
|
<AddClassAction ClassName="Read" RemoveIfExists="True" />
|
||||||
|
<RemoveClassAction ClassName="Write" />
|
||||||
|
</DataTriggerBehavior>
|
||||||
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
|
||||||
|
<AddClassAction ClassName="Write" RemoveIfExists="True" />
|
||||||
|
<RemoveClassAction ClassName="Read" />
|
||||||
|
</DataTriggerBehavior>
|
||||||
|
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
|
||||||
|
<AddClassAction ClassName="Write" RemoveIfExists="True" />
|
||||||
|
<RemoveClassAction ClassName="Read" />
|
||||||
|
</DataTriggerBehavior>
|
||||||
|
</Interaction.Behaviors>
|
||||||
|
</TextBox>
|
||||||
</SettingsExpander.Footer>
|
</SettingsExpander.Footer>
|
||||||
</SettingsExpander>
|
</SettingsExpander>
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public partial class DigitRule :
|
||||||
|
IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password) =>
|
||||||
|
Regex().IsMatch(password) ? 2 : 0;
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\d")]
|
||||||
|
private static partial Regex Regex();
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public partial class DiversityBonusRule :
|
||||||
|
IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password)
|
||||||
|
{
|
||||||
|
bool hasUppercase = UppercaseRegex().IsMatch(password);
|
||||||
|
bool hasLowercase = LowercaseRegex().IsMatch(password);
|
||||||
|
bool hasDigit = DigitRegex().IsMatch(password);
|
||||||
|
bool hasSpecialChar = SpecialCharRegex().IsMatch(password);
|
||||||
|
|
||||||
|
return (hasUppercase && hasLowercase && hasDigit && hasSpecialChar) ? 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[A-Z]")]
|
||||||
|
private static partial Regex UppercaseRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[a-z]")]
|
||||||
|
private static partial Regex LowercaseRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\d")]
|
||||||
|
private static partial Regex DigitRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[^a-zA-Z0-9]")]
|
||||||
|
private static partial Regex SpecialCharRegex();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public interface IPasswordRule
|
||||||
|
{
|
||||||
|
int CalculateScore(string password);
|
||||||
|
}
|
||||||
@@ -719,6 +719,7 @@ public record ItemConfiguration
|
|||||||
{
|
{
|
||||||
Label = "Type",
|
Label = "Type",
|
||||||
Values = ["American Express", "Discover", "Maestro", "Mastercard", "Visa"],
|
Values = ["American Express", "Discover", "Maestro", "Mastercard", "Visa"],
|
||||||
|
Width = 120
|
||||||
},
|
},
|
||||||
new MaskedTextEntryConfiguration
|
new MaskedTextEntryConfiguration
|
||||||
{
|
{
|
||||||
@@ -731,18 +732,21 @@ public record ItemConfiguration
|
|||||||
Label = "Expiry Date",
|
Label = "Expiry Date",
|
||||||
Pattern = "00/00",
|
Pattern = "00/00",
|
||||||
Value = "__/__",
|
Value = "__/__",
|
||||||
|
Width = 120
|
||||||
},
|
},
|
||||||
new MaskedTextEntryConfiguration
|
new MaskedTextEntryConfiguration
|
||||||
{
|
{
|
||||||
Label = "Valid From",
|
Label = "Valid From",
|
||||||
Pattern = "00/00",
|
Pattern = "00/00",
|
||||||
Value = "__/__",
|
Value = "__/__",
|
||||||
|
Width = 120
|
||||||
},
|
},
|
||||||
new MaskedTextEntryConfiguration
|
new MaskedTextEntryConfiguration
|
||||||
{
|
{
|
||||||
Label = "Card verification code",
|
Label = "Card verification code",
|
||||||
Pattern = "000",
|
Pattern = "000",
|
||||||
Value = "___",
|
Value = "___",
|
||||||
|
Width = 120
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public class LengthRule :
|
||||||
|
IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password) =>
|
||||||
|
password.Length >= 8 ? 5 : 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public partial class LowercaseRule :
|
||||||
|
IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password) =>
|
||||||
|
Regex().IsMatch(password) ? 2 : 0;
|
||||||
|
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[a-z]")]
|
||||||
|
private static partial Regex Regex();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public partial class SpecialCharRule : IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password) =>
|
||||||
|
Regex().IsMatch(password) ? 2 : 0;
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[^a-zA-Z0-9]")]
|
||||||
|
private static partial Regex Regex();
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Bitvault;
|
||||||
|
|
||||||
|
public partial class UppercaseRule :
|
||||||
|
IPasswordRule
|
||||||
|
{
|
||||||
|
public int CalculateScore(string password) =>
|
||||||
|
Regex().IsMatch(password) ? 2 : 0;
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[A-Z]")]
|
||||||
|
private static partial Regex Regex();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user