Add support for hidden passwords (#920)

* Add support for hidden passwords

* Hide TOTP, hide hidden fields.

* Change _cipher to Cipher.
This commit is contained in:
Oscar Hinton 2020-06-11 22:16:43 +02:00 committed by GitHub
parent e64fb39c32
commit 52ca84946b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 39 additions and 13 deletions

View file

@ -112,9 +112,11 @@
StyleClass="box-value" StyleClass="box-value"
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="{Binding PasswordFieldColSpan}"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}" IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
IsSpellCheckEnabled="False" IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False" /> IsTextPredictionEnabled="False"
IsEnabled="{Binding Cipher.ViewPassword}"/>
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="&#xf058;" Text="&#xf058;"
@ -123,7 +125,8 @@
Grid.Column="1" Grid.Column="1"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n CheckPassword}" /> AutomationProperties.Name="{u:I18n CheckPassword}"
IsVisible="{Binding Cipher.ViewPassword}" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}" Text="{Binding ShowPasswordIcon}"
@ -132,7 +135,8 @@
Grid.Column="2" Grid.Column="2"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}" /> AutomationProperties.Name="{u:I18n ToggleVisibility}"
IsVisible="{Binding Cipher.ViewPassword}" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="&#xf021;" Text="&#xf021;"
@ -141,7 +145,8 @@
Grid.Column="3" Grid.Column="3"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n GeneratePassword}" /> AutomationProperties.Name="{u:I18n GeneratePassword}"
IsVisible="{Binding Cipher.ViewPassword}" />
</Grid> </Grid>
<Grid StyleClass="box-row, box-row-input"> <Grid StyleClass="box-row, box-row-input">
@ -163,9 +168,12 @@
Text="{Binding Cipher.Login.Totp}" Text="{Binding Cipher.Login.Totp}"
IsSpellCheckEnabled="False" IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False" IsTextPredictionEnabled="False"
IsPassword="{Binding Cipher.ViewPassword, Converter={StaticResource inverseBool}}"
IsEnabled="{Binding Cipher.ViewPassword}"
StyleClass="box-value" StyleClass="box-value"
Grid.Row="1" Grid.Row="1"
Grid.Column="0" /> Grid.Column="0"
Grid.ColumnSpan="{Binding TotpColumnSpan}" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="&#xf030;" Text="&#xf030;"
@ -173,6 +181,7 @@
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Grid.RowSpan="2" Grid.RowSpan="2"
IsVisible="{Binding Cipher.ViewPassword}"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ScanQrTitle}" /> AutomationProperties.Name="{u:I18n ScanQrTitle}" />
</Grid> </Grid>
@ -562,6 +571,7 @@
Grid.Column="0" Grid.Column="0"
IsVisible="{Binding IsHiddenType}" IsVisible="{Binding IsHiddenType}"
IsPassword="{Binding ShowHiddenValue, Converter={StaticResource inverseBool}}" IsPassword="{Binding ShowHiddenValue, Converter={StaticResource inverseBool}}"
IsEnabled="{Binding ShowViewHidden}"
IsSpellCheckEnabled="False" IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"> IsTextPredictionEnabled="False">
<Entry.Keyboard> <Entry.Keyboard>
@ -582,7 +592,7 @@
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowHiddenValueIcon}" Text="{Binding ShowHiddenValueIcon}"
Command="{Binding ToggleHiddenValueCommand}" Command="{Binding ToggleHiddenValueCommand}"
IsVisible="{Binding IsHiddenType}" IsVisible="{Binding ShowViewHidden}"
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Grid.RowSpan="2" Grid.RowSpan="2"

View file

@ -274,6 +274,8 @@ namespace Bit.App.Pages
public bool ShowAttachments => Cipher.HasAttachments; public bool ShowAttachments => Cipher.HasAttachments;
public string ShowPasswordIcon => ShowPassword ? "" : ""; public string ShowPasswordIcon => ShowPassword ? "" : "";
public string ShowCardCodeIcon => ShowCardCode ? "" : ""; public string ShowCardCodeIcon => ShowCardCode ? "" : "";
public int PasswordFieldColSpan => Cipher.ViewPassword ? 1 : 4;
public int TotpColumnSpan => Cipher.ViewPassword ? 1 : 2;
public void Init() public void Init()
{ {
@ -631,7 +633,8 @@ namespace Bit.App.Pages
Fields.Add(new AddEditPageFieldViewModel(Cipher, new FieldView Fields.Add(new AddEditPageFieldViewModel(Cipher, new FieldView
{ {
Type = type, Type = type,
Name = string.IsNullOrWhiteSpace(name) ? null : name Name = string.IsNullOrWhiteSpace(name) ? null : name,
NewField = true,
})); }));
} }
} }
@ -818,6 +821,7 @@ namespace Bit.App.Pages
public bool IsTextType => _field.Type == FieldType.Text; public bool IsTextType => _field.Type == FieldType.Text;
public bool IsBooleanType => _field.Type == FieldType.Boolean; public bool IsBooleanType => _field.Type == FieldType.Boolean;
public bool IsHiddenType => _field.Type == FieldType.Hidden; public bool IsHiddenType => _field.Type == FieldType.Hidden;
public bool ShowViewHidden => IsHiddenType && (_cipher.ViewPassword || _field.NewField);
public void ToggleHiddenValue() public void ToggleHiddenValue()
{ {

View file

@ -134,7 +134,8 @@
Grid.Column="1" Grid.Column="1"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n CheckPassword}" /> AutomationProperties.Name="{u:I18n CheckPassword}"
IsVisible="{Binding Cipher.ViewPassword}" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}" Text="{Binding ShowPasswordIcon}"
@ -143,7 +144,8 @@
Grid.Column="2" Grid.Column="2"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}" /> AutomationProperties.Name="{u:I18n ToggleVisibility}"
IsVisible="{Binding Cipher.ViewPassword}" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="&#xf0ea;" Text="&#xf0ea;"
@ -153,7 +155,8 @@
Grid.Column="3" Grid.Column="3"
Grid.RowSpan="2" Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True" AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n CopyPassword}" /> AutomationProperties.Name="{u:I18n CopyPassword}"
IsVisible="{Binding Cipher.ViewPassword}" />
</Grid> </Grid>
<BoxView StyleClass="box-row-separator" <BoxView StyleClass="box-row-separator"
IsVisible="{Binding Cipher.Login.Password, Converter={StaticResource stringHasValue}}" /> IsVisible="{Binding Cipher.Login.Password, Converter={StaticResource stringHasValue}}" />
@ -570,7 +573,7 @@
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowHiddenValueIcon}" Text="{Binding ShowHiddenValueIcon}"
Command="{Binding ToggleHiddenValueCommand}" Command="{Binding ToggleHiddenValueCommand}"
IsVisible="{Binding IsHiddenType}" IsVisible="{Binding ShowViewHidden}"
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Grid.RowSpan="2" Grid.RowSpan="2"

View file

@ -684,8 +684,9 @@ namespace Bit.App.Pages
public bool IsTextType => _field.Type == Core.Enums.FieldType.Text; public bool IsTextType => _field.Type == Core.Enums.FieldType.Text;
public bool IsBooleanType => _field.Type == Core.Enums.FieldType.Boolean; public bool IsBooleanType => _field.Type == Core.Enums.FieldType.Boolean;
public bool IsHiddenType => _field.Type == Core.Enums.FieldType.Hidden; public bool IsHiddenType => _field.Type == Core.Enums.FieldType.Hidden;
public bool ShowViewHidden => IsHiddenType && _cipher.ViewPassword;
public bool ShowCopyButton => _field.Type != Core.Enums.FieldType.Boolean && public bool ShowCopyButton => _field.Type != Core.Enums.FieldType.Boolean &&
!string.IsNullOrWhiteSpace(_field.Value); !string.IsNullOrWhiteSpace(_field.Value) && !(IsHiddenType && !_cipher.ViewPassword);
public void ToggleHiddenValue() public void ToggleHiddenValue()
{ {

View file

@ -30,7 +30,7 @@ namespace Bit.App.Utilities
{ {
options.Add(AppResources.CopyUsername); options.Add(AppResources.CopyUsername);
} }
if (!string.IsNullOrWhiteSpace(cipher.Login.Password)) if (!string.IsNullOrWhiteSpace(cipher.Login.Password) && cipher.ViewPassword)
{ {
options.Add(AppResources.CopyPassword); options.Add(AppResources.CopyPassword);
} }

View file

@ -16,6 +16,7 @@ namespace Bit.Core.Models.Data
FolderId = response.FolderId; FolderId = response.FolderId;
UserId = userId; UserId = userId;
Edit = response.Edit; Edit = response.Edit;
ViewPassword = response.ViewPassword;
OrganizationUseTotp = response.OrganizationUseTotp; OrganizationUseTotp = response.OrganizationUseTotp;
Favorite = response.Favorite; Favorite = response.Favorite;
RevisionDate = response.RevisionDate; RevisionDate = response.RevisionDate;
@ -53,6 +54,7 @@ namespace Bit.Core.Models.Data
public string FolderId { get; set; } public string FolderId { get; set; }
public string UserId { get; set; } public string UserId { get; set; }
public bool Edit { get; set; } public bool Edit { get; set; }
public bool ViewPassword { get; set; }
public bool OrganizationUseTotp { get; set; } public bool OrganizationUseTotp { get; set; }
public bool Favorite { get; set; } public bool Favorite { get; set; }
public DateTime RevisionDate { get; set; } public DateTime RevisionDate { get; set; }

View file

@ -26,6 +26,7 @@ namespace Bit.Core.Models.Domain
Favorite = obj.Favorite; Favorite = obj.Favorite;
OrganizationUseTotp = obj.OrganizationUseTotp; OrganizationUseTotp = obj.OrganizationUseTotp;
Edit = obj.Edit; Edit = obj.Edit;
ViewPassword = obj.ViewPassword;
RevisionDate = obj.RevisionDate; RevisionDate = obj.RevisionDate;
CollectionIds = obj.CollectionIds != null ? new HashSet<string>(obj.CollectionIds) : null; CollectionIds = obj.CollectionIds != null ? new HashSet<string>(obj.CollectionIds) : null;
LocalData = localData; LocalData = localData;
@ -63,6 +64,7 @@ namespace Bit.Core.Models.Domain
public bool Favorite { get; set; } public bool Favorite { get; set; }
public bool OrganizationUseTotp { get; set; } public bool OrganizationUseTotp { get; set; }
public bool Edit { get; set; } public bool Edit { get; set; }
public bool ViewPassword { get; set; }
public DateTime RevisionDate { get; set; } public DateTime RevisionDate { get; set; }
public Dictionary<string, object> LocalData { get; set; } public Dictionary<string, object> LocalData { get; set; }
public Login Login { get; set; } public Login Login { get; set; }

View file

@ -19,6 +19,7 @@ namespace Bit.Core.Models.Response
public SecureNoteApi SecureNote { get; set; } public SecureNoteApi SecureNote { get; set; }
public bool Favorite { get; set; } public bool Favorite { get; set; }
public bool Edit { get; set; } public bool Edit { get; set; }
public bool ViewPassword { get; set; } = true; // Fallback for old server versions
public bool OrganizationUseTotp { get; set; } public bool OrganizationUseTotp { get; set; }
public DateTime RevisionDate { get; set; } public DateTime RevisionDate { get; set; }
public List<AttachmentResponse> Attachments { get; set; } public List<AttachmentResponse> Attachments { get; set; }

View file

@ -18,6 +18,7 @@ namespace Bit.Core.Models.View
Favorite = c.Favorite; Favorite = c.Favorite;
OrganizationUseTotp = c.OrganizationUseTotp; OrganizationUseTotp = c.OrganizationUseTotp;
Edit = c.Edit; Edit = c.Edit;
ViewPassword = c.ViewPassword;
Type = c.Type; Type = c.Type;
LocalData = c.LocalData; LocalData = c.LocalData;
CollectionIds = c.CollectionIds; CollectionIds = c.CollectionIds;
@ -34,6 +35,7 @@ namespace Bit.Core.Models.View
public bool Favorite { get; set; } public bool Favorite { get; set; }
public bool OrganizationUseTotp { get; set; } public bool OrganizationUseTotp { get; set; }
public bool Edit { get; set; } public bool Edit { get; set; }
public bool ViewPassword { get; set; }
public Dictionary<string, object> LocalData { get; set; } public Dictionary<string, object> LocalData { get; set; }
public LoginView Login { get; set; } public LoginView Login { get; set; }
public IdentityView Identity { get; set; } public IdentityView Identity { get; set; }

View file

@ -16,5 +16,6 @@ namespace Bit.Core.Models.View
public string Value { get; set; } public string Value { get; set; }
public FieldType Type { get; set; } public FieldType Type { get; set; }
public string MaskedValue => Value != null ? "••••••••" : null; public string MaskedValue => Value != null ? "••••••••" : null;
public bool NewField { get; set; }
} }
} }