Card Security Code masked (bitwarden/desktop issue 78) (#328)

* Card Security Code masked in the same way as Passwords. (bitwarden/desktop issue 78)

By default shows Card Security Code masked in the same way as Passwords. (bitwarden/desktop issue 78)

* Creating property to store value of Masked Card Code Shown
This commit is contained in:
Neil Burrows 2018-06-18 14:00:45 +01:00 committed by Kyle Spearrin
parent 7cac07c185
commit 9523c7ab33
4 changed files with 51 additions and 6 deletions

View file

@ -23,6 +23,7 @@ namespace Bit.App.Models.Page
// Card // Card
private string _cardName, _cardNumber, _cardBrand, _cardExpMonth, _cardExpYear, _cardCode; private string _cardName, _cardNumber, _cardBrand, _cardExpMonth, _cardExpYear, _cardCode;
private bool _cardRevealCardCode;
// Identity // Identity
private string _idFirstName, _idLastName, _idMiddleName, _idCompany, _idEmail, _idPhone, _idUsername, private string _idFirstName, _idLastName, _idMiddleName, _idCompany, _idEmail, _idPhone, _idUsername,
@ -250,6 +251,22 @@ namespace Bit.App.Models.Page
} }
} }
public bool ShowCardCode => !string.IsNullOrWhiteSpace(CardCode); public bool ShowCardCode => !string.IsNullOrWhiteSpace(CardCode);
public bool RevealCardCode
{
get => _cardRevealCardCode;
set
{
_cardRevealCardCode = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(RevealCardCode)));
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedCardCode)));
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardCodeShowHideImage)));
}
}
public string MaskedCardCode => RevealCardCode ?
CardCode : CardCode == null ? null : new String('•', CardCode.Length);
public ImageSource CardCodeShowHideImage => RevealCardCode ?
ImageSource.FromFile("eye_slash.png") : ImageSource.FromFile("eye.png");
// Identity // Identity

View file

@ -215,6 +215,7 @@ namespace Bit.App.Pages
CardExpYearCell.InitEvents(); CardExpYearCell.InitEvents();
CardNameCell.InitEvents(); CardNameCell.InitEvents();
CardNumberCell.InitEvents(); CardNumberCell.InitEvents();
CardCodeCell.Button1.Clicked += CardCodeButton_Clicked;
break; break;
case CipherType.Identity: case CipherType.Identity:
IdTitleCell.InitEvents(); IdTitleCell.InitEvents();
@ -305,6 +306,7 @@ namespace Bit.App.Pages
CardExpYearCell.Dispose(); CardExpYearCell.Dispose();
CardNameCell.Dispose(); CardNameCell.Dispose();
CardNumberCell.Dispose(); CardNumberCell.Dispose();
CardCodeCell.Button1.Clicked -= CardCodeButton_Clicked;
break; break;
case CipherType.Identity: case CipherType.Identity:
IdTitleCell.Dispose(); IdTitleCell.Dispose();
@ -384,6 +386,13 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage)); await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage));
} }
private void CardCodeButton_Clicked(object sender, EventArgs e)
{
CardCodeCell.Entry.InvokeToggleIsPassword();
CardCodeCell.Button1.Image =
"eye" + (!CardCodeCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png";
}
private void AlertNoConnection() private void AlertNoConnection()
{ {
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage,
@ -451,8 +460,7 @@ namespace Bit.App.Pages
} }
else if(_type == CipherType.Card) else if(_type == CipherType.Card)
{ {
CardCodeCell = new FormEntryCell(AppResources.SecurityCode, Keyboard.Numeric, CardCodeCell = new FormEntryCell(AppResources.SecurityCode, Keyboard.Numeric, isPassword: true, nextElement: NotesCell.Editor, button1: "eye.png");
nextElement: NotesCell.Editor);
if(!string.IsNullOrWhiteSpace(_defaultCardCode)) if(!string.IsNullOrWhiteSpace(_defaultCardCode))
{ {
CardCodeCell.Entry.Text = _defaultCardCode; CardCodeCell.Entry.Text = _defaultCardCode;

View file

@ -219,7 +219,7 @@ namespace Bit.App.Pages
else if(Cipher.Type == CipherType.Card) else if(Cipher.Type == CipherType.Card)
{ {
CardCodeCell = new FormEntryCell(AppResources.SecurityCode, Keyboard.Numeric, CardCodeCell = new FormEntryCell(AppResources.SecurityCode, Keyboard.Numeric,
nextElement: NotesCell.Editor); isPassword: true, nextElement: NotesCell.Editor, button1: "eye.png");
CardCodeCell.Entry.Text = Cipher.Card.Code?.Decrypt(Cipher.OrganizationId); CardCodeCell.Entry.Text = Cipher.Card.Code?.Decrypt(Cipher.OrganizationId);
CardExpYearCell = new FormEntryCell(AppResources.ExpirationYear, Keyboard.Numeric, CardExpYearCell = new FormEntryCell(AppResources.ExpirationYear, Keyboard.Numeric,
@ -717,6 +717,10 @@ namespace Bit.App.Pages
CardExpYearCell?.InitEvents(); CardExpYearCell?.InitEvents();
CardNameCell?.InitEvents(); CardNameCell?.InitEvents();
CardNumberCell?.InitEvents(); CardNumberCell?.InitEvents();
if (CardCodeCell?.Button1 != null)
{
CardCodeCell.Button1.Clicked += CardCodeButton_Clicked;
}
break; break;
case CipherType.Identity: case CipherType.Identity:
IdTitleCell?.InitEvents(); IdTitleCell?.InitEvents();
@ -797,6 +801,10 @@ namespace Bit.App.Pages
CardExpYearCell?.Dispose(); CardExpYearCell?.Dispose();
CardNameCell?.Dispose(); CardNameCell?.Dispose();
CardNumberCell?.Dispose(); CardNumberCell?.Dispose();
if (CardCodeCell?.Button1 != null)
{
CardCodeCell.Button1.Clicked -= CardCodeButton_Clicked;
}
break; break;
case CipherType.Identity: case CipherType.Identity:
IdTitleCell?.Dispose(); IdTitleCell?.Dispose();
@ -871,6 +879,13 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage)); await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage));
} }
private void CardCodeButton_Clicked(object sender, EventArgs e)
{
CardCodeCell.Entry.InvokeToggleIsPassword();
CardCodeCell.Button1.Image =
"eye" + (!CardCodeCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png";
}
private async void AttachmentsCell_Tapped(object sender, EventArgs e) private async void AttachmentsCell_Tapped(object sender, EventArgs e)
{ {
var page = new ExtendedNavigationPage(new VaultAttachmentsPage(_cipherId)); var page = new ExtendedNavigationPage(new VaultAttachmentsPage(_cipherId));

View file

@ -168,9 +168,14 @@ namespace Bit.App.Pages
CardExpCell = new LabeledValueCell(AppResources.Expiration); CardExpCell = new LabeledValueCell(AppResources.Expiration);
CardExpCell.Value.SetBinding(Label.TextProperty, nameof(VaultViewCipherPageModel.CardExp)); CardExpCell.Value.SetBinding(Label.TextProperty, nameof(VaultViewCipherPageModel.CardExp));
CardCodeCell = new LabeledValueCell(AppResources.SecurityCode, button1Image: "clipboard.png"); CardCodeCell = new LabeledValueCell(AppResources.SecurityCode, button1Image: string.Empty, button2Image: "clipboard.png");
CardCodeCell.Button1.Command = new Command(() => Copy(Model.CardCode, AppResources.SecurityCode)); CardCodeCell.Value.SetBinding(Label.TextProperty,
CardCodeCell.Value.SetBinding(Label.TextProperty, nameof(VaultViewCipherPageModel.CardCode)); nameof(VaultViewCipherPageModel.MaskedCardCode));
CardCodeCell.Button1.SetBinding(Button.ImageProperty,
nameof(VaultViewCipherPageModel.CardCodeShowHideImage));
CardCodeCell.Button1.Command =
new Command(() => Model.RevealCardCode = !Model.RevealCardCode);
CardCodeCell.Button2.Command = new Command(() => Copy(Model.CardCode, AppResources.SecurityCode));
break; break;
case CipherType.Identity: case CipherType.Identity:
IdNameCell = new LabeledValueCell(AppResources.Name); IdNameCell = new LabeledValueCell(AppResources.Name);