mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-24 16:38:22 +01:00
save password history changes
This commit is contained in:
parent
4d08ce90cc
commit
a9a33ad71e
@ -13,7 +13,7 @@ namespace Bit.App.Models.Api
|
||||
Uris = cipher.Login.Uris?.Select(u => new LoginUriType(u));
|
||||
Username = cipher.Login.Username?.EncryptedString;
|
||||
Password = cipher.Login.Password?.EncryptedString;
|
||||
|
||||
PasswordRevisionDate = cipher.Login.PasswordRevisionDate;
|
||||
Totp = cipher.Login.Totp?.EncryptedString;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,11 @@ namespace Bit.App.Models.Api
|
||||
Fields = cipher.Fields.Select(f => new FieldType(f));
|
||||
}
|
||||
|
||||
if(cipher.PasswordHistory != null)
|
||||
{
|
||||
PasswordHistory = cipher.PasswordHistory.Select(h => new PasswordHistoryRequest(h));
|
||||
}
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
@ -46,7 +51,7 @@ namespace Bit.App.Models.Api
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public IEnumerable<FieldType> Fields { get; set; }
|
||||
public IEnumerable<PasswordHistoryResponse> PasswordHistory { get; set; }
|
||||
public IEnumerable<PasswordHistoryRequest> PasswordHistory { get; set; }
|
||||
|
||||
public LoginType Login { get; set; }
|
||||
public CardType Card { get; set; }
|
||||
|
@ -2,6 +2,12 @@
|
||||
{
|
||||
public class PasswordHistoryRequest
|
||||
{
|
||||
public PasswordHistoryRequest(PasswordHistory ph)
|
||||
{
|
||||
Password = ph.Password?.EncryptedString;
|
||||
LastUsedDate = ph.LastUsedDate;
|
||||
}
|
||||
|
||||
public string Password { get; set; }
|
||||
public System.DateTime LastUsedDate { get; set; }
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ namespace Bit.App.Pages
|
||||
private readonly IDeviceInfoService _deviceInfo;
|
||||
private readonly IGoogleAnalyticsService _googleAnalyticsService;
|
||||
private DateTime? _lastAction;
|
||||
private string _originalLoginPassword = null;
|
||||
private List<Tuple<string, string>> _originalHiddenFields = new List<Tuple<string, string>>();
|
||||
|
||||
public VaultEditCipherPage(string cipherId)
|
||||
{
|
||||
@ -169,7 +171,7 @@ namespace Bit.App.Pages
|
||||
// Types
|
||||
if(Cipher.Type == CipherType.Login)
|
||||
{
|
||||
LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey,
|
||||
LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey,
|
||||
button1: _deviceInfo.HasCamera ? "camera.png" : null);
|
||||
LoginTotpCell.Entry.Text = Cipher.Login?.Totp?.Decrypt(Cipher.OrganizationId);
|
||||
LoginTotpCell.Entry.DisableAutocapitalize = true;
|
||||
@ -179,7 +181,8 @@ namespace Bit.App.Pages
|
||||
|
||||
LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true,
|
||||
nextElement: LoginTotpCell.Entry, button1: "eye.png", button2: "refresh_alt.png");
|
||||
LoginPasswordCell.Entry.Text = Cipher.Login?.Password?.Decrypt(Cipher.OrganizationId);
|
||||
LoginPasswordCell.Entry.Text = _originalLoginPassword =
|
||||
Cipher.Login?.Password?.Decrypt(Cipher.OrganizationId);
|
||||
LoginPasswordCell.Entry.DisableAutocapitalize = true;
|
||||
LoginPasswordCell.Entry.Autocorrect = false;
|
||||
LoginPasswordCell.Entry.FontFamily =
|
||||
@ -211,7 +214,7 @@ namespace Bit.App.Pages
|
||||
foreach(var uri in Cipher.Login.Uris)
|
||||
{
|
||||
var value = uri.Uri?.Decrypt(Cipher.OrganizationId);
|
||||
UrisSection.Insert(UrisSection.Count - 1,
|
||||
UrisSection.Insert(UrisSection.Count - 1,
|
||||
Helpers.MakeUriCell(value, uri.Match, UrisSection, this));
|
||||
}
|
||||
}
|
||||
@ -415,6 +418,11 @@ namespace Bit.App.Pages
|
||||
{
|
||||
FieldsSection.Add(cell);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(label) && !string.IsNullOrWhiteSpace(value) &&
|
||||
field.Type == FieldType.Hidden)
|
||||
{
|
||||
_originalHiddenFields.Add(new Tuple<string, string>(label, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
AddFieldCell = new ExtendedTextCell
|
||||
@ -491,7 +499,8 @@ namespace Bit.App.Pages
|
||||
Cipher.Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null :
|
||||
NotesCell.Editor.Text.Encrypt(Cipher.OrganizationId);
|
||||
Cipher.Favorite = FavoriteCell.On;
|
||||
|
||||
|
||||
var passwordHistory = Cipher.PasswordHistory?.ToList() ?? new List<PasswordHistory>();
|
||||
switch(Cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
@ -505,6 +514,18 @@ namespace Bit.App.Pages
|
||||
LoginTotpCell.Entry.Text.Encrypt(Cipher.OrganizationId),
|
||||
};
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(_originalLoginPassword) &&
|
||||
LoginPasswordCell.Entry.Text != _originalLoginPassword)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
passwordHistory.Insert(0, new PasswordHistory
|
||||
{
|
||||
LastUsedDate = now,
|
||||
Password = _originalLoginPassword.Encrypt(Cipher.OrganizationId),
|
||||
});
|
||||
Cipher.Login.PasswordRevisionDate = now;
|
||||
}
|
||||
|
||||
Helpers.ProcessUrisSectionForSave(UrisSection, Cipher);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
@ -639,7 +660,18 @@ namespace Bit.App.Pages
|
||||
Cipher.FolderId = null;
|
||||
}
|
||||
|
||||
Helpers.ProcessFieldsSectionForSave(FieldsSection, Cipher);
|
||||
var hiddenFields = Helpers.ProcessFieldsSectionForSave(FieldsSection, Cipher);
|
||||
var changedFields = _originalHiddenFields.Where(of =>
|
||||
hiddenFields.Any(f => f.Item1 == of.Item1 && f.Item2 != of.Item2));
|
||||
foreach(var cf in changedFields)
|
||||
{
|
||||
passwordHistory.Insert(0, new PasswordHistory
|
||||
{
|
||||
LastUsedDate = DateTime.UtcNow,
|
||||
Password = (cf.Item1 + ": " + cf.Item2).Encrypt(Cipher.OrganizationId),
|
||||
});
|
||||
}
|
||||
Cipher.PasswordHistory = (passwordHistory?.Count ?? 0) > 0 ? passwordHistory : null;
|
||||
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||
var saveTask = await _cipherService.SaveAsync(Cipher);
|
||||
@ -714,7 +746,7 @@ namespace Bit.App.Pages
|
||||
CardExpYearCell?.InitEvents();
|
||||
CardNameCell?.InitEvents();
|
||||
CardNumberCell?.InitEvents();
|
||||
if (CardCodeCell?.Button1 != null)
|
||||
if(CardCodeCell?.Button1 != null)
|
||||
{
|
||||
CardCodeCell.Button1.Clicked += CardCodeButton_Clicked;
|
||||
}
|
||||
@ -798,7 +830,7 @@ namespace Bit.App.Pages
|
||||
CardExpYearCell?.Dispose();
|
||||
CardNameCell?.Dispose();
|
||||
CardNumberCell?.Dispose();
|
||||
if (CardCodeCell?.Button1 != null)
|
||||
if(CardCodeCell?.Button1 != null)
|
||||
{
|
||||
CardCodeCell.Button1.Clicked -= CardCodeButton_Clicked;
|
||||
}
|
||||
@ -826,7 +858,7 @@ namespace Bit.App.Pages
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Helpers.DisposeSectionEvents(FieldsSection);
|
||||
Helpers.DisposeSectionEvents(UrisSection);
|
||||
}
|
||||
|
@ -331,8 +331,9 @@ namespace Bit.App.Utilities
|
||||
return cell;
|
||||
}
|
||||
|
||||
public static void ProcessFieldsSectionForSave(TableSection fieldsSection, Cipher cipher)
|
||||
public static List<Tuple<string, string>> ProcessFieldsSectionForSave(TableSection fieldsSection, Cipher cipher)
|
||||
{
|
||||
var hiddenFieldValues = new List<Tuple<string, string>>();
|
||||
if(fieldsSection != null && fieldsSection.Count > 0)
|
||||
{
|
||||
var fields = new List<Field>();
|
||||
@ -348,6 +349,12 @@ namespace Bit.App.Utilities
|
||||
entryCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||
Type = entryCell.Entry.IsPassword ? FieldType.Hidden : FieldType.Text
|
||||
});
|
||||
|
||||
if(entryCell.Entry.IsPassword && !string.IsNullOrWhiteSpace(entryCell.Label.Text))
|
||||
{
|
||||
hiddenFieldValues.Add(new Tuple<string, string>(entryCell.Label.Text,
|
||||
entryCell.Entry.Text));
|
||||
}
|
||||
}
|
||||
else if(cell is FormSwitchCell switchCell)
|
||||
{
|
||||
@ -368,6 +375,7 @@ namespace Bit.App.Utilities
|
||||
{
|
||||
cipher.Fields = null;
|
||||
}
|
||||
return hiddenFieldValues;
|
||||
}
|
||||
|
||||
public static FormEntryCell MakeUriCell(string value, UriMatchType? match, TableSection urisSection, Page page)
|
||||
|
Loading…
Reference in New Issue
Block a user