mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-27 12:26:31 +01:00
add password history and updated dates
This commit is contained in:
parent
13b9e01604
commit
01d9ccc110
@ -13,12 +13,14 @@ namespace Bit.App.Models.Api
|
||||
Uris = cipher.Login.Uris?.Select(u => new LoginUriType(u));
|
||||
Username = cipher.Login.Username?.EncryptedString;
|
||||
Password = cipher.Login.Password?.EncryptedString;
|
||||
|
||||
Totp = cipher.Login.Totp?.EncryptedString;
|
||||
}
|
||||
|
||||
public IEnumerable<LoginUriType> Uris { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public System.DateTime? PasswordRevisionDate { get; set; }
|
||||
public string Totp { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,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 LoginType Login { get; set; }
|
||||
public CardType Card { get; set; }
|
||||
|
8
src/App/Models/Api/Request/PasswordHistoryRequest.cs
Normal file
8
src/App/Models/Api/Request/PasswordHistoryRequest.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class PasswordHistoryRequest
|
||||
{
|
||||
public string Password { get; set; }
|
||||
public System.DateTime LastUsedDate { get; set; }
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ namespace Bit.App.Models.Api
|
||||
public SecureNoteType SecureNote { get; set; }
|
||||
public IEnumerable<FieldType> Fields { get; set; }
|
||||
public IEnumerable<AttachmentResponse> Attachments { get; set; }
|
||||
public IEnumerable<PasswordHistoryResponse> PasswordHistory { get; set; }
|
||||
public IEnumerable<string> CollectionIds { get; set; }
|
||||
public DateTime RevisionDate { get; set; }
|
||||
}
|
||||
|
8
src/App/Models/Api/Response/PasswordHistoryResponse.cs
Normal file
8
src/App/Models/Api/Response/PasswordHistoryResponse.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class PasswordHistoryResponse
|
||||
{
|
||||
public string Password { get; set; }
|
||||
public System.DateTime LastUsedDate { get; set; }
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ namespace Bit.App.Models
|
||||
Edit = data.Edit;
|
||||
OrganizationUseTotp = data.OrganizationUseTotp;
|
||||
Attachments = attachments?.Select(a => new Attachment(a));
|
||||
RevisionDate = data.RevisionDateTime;
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
@ -52,6 +53,17 @@ namespace Bit.App.Models
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(data.PasswordHistory))
|
||||
{
|
||||
try
|
||||
{
|
||||
var phModels = JsonConvert.DeserializeObject<IEnumerable<PasswordHistoryDataModel>>(
|
||||
data.PasswordHistory);
|
||||
PasswordHistory = phModels?.Select(f => new PasswordHistory(f));
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
@ -62,14 +74,19 @@ namespace Bit.App.Models
|
||||
public CipherString Name { get; set; }
|
||||
public CipherString Notes { get; set; }
|
||||
public IEnumerable<Field> Fields { get; set; }
|
||||
public IEnumerable<PasswordHistory> PasswordHistory { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public bool Edit { get; set; }
|
||||
public bool OrganizationUseTotp { get; set; }
|
||||
public IEnumerable<Attachment> Attachments { get; set; }
|
||||
public System.DateTime RevisionDate { get; set; }
|
||||
|
||||
public Login Login { get; set; }
|
||||
public Identity Identity { get; set; }
|
||||
public Card Card { get; set; }
|
||||
public SecureNote SecureNote { get; set; }
|
||||
|
||||
public System.DateTime? PasswordRevisionDisplayDate =>
|
||||
Login?.Password == null ? (System.DateTime?)null : Login.PasswordRevisionDate ?? RevisionDate;
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,16 @@ namespace Bit.App.Models.Data
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
|
||||
if(cipher.PasswordHistory != null && cipher.PasswordHistory.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordHistory = JsonConvert.SerializeObject(
|
||||
cipher.PasswordHistory.Select(h => new PasswordHistoryDataModel(h)));
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
@ -75,6 +85,7 @@ namespace Bit.App.Models.Data
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Fields { get; set; }
|
||||
public string PasswordHistory { get; set; }
|
||||
public string Login { get; set; }
|
||||
public string Card { get; set; }
|
||||
public string Identity { get; set; }
|
||||
|
@ -13,10 +13,12 @@ namespace Bit.App.Models.Data
|
||||
Name = cipher.Name;
|
||||
Notes = cipher.Notes;
|
||||
Fields = cipher.Fields?.Select(f => new FieldDataModel(f));
|
||||
PasswordHistory = cipher.PasswordHistory?.Select(h => new PasswordHistoryDataModel(h));
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public IEnumerable<FieldDataModel> Fields { get; set; }
|
||||
public IEnumerable<PasswordHistoryDataModel> PasswordHistory { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace Bit.App.Models.Data
|
||||
Uris = response.Login.Uris?.Where(u => u != null).Select(u => new LoginUriDataModel(u));
|
||||
Username = response.Login.Username;
|
||||
Password = response.Login.Password;
|
||||
PasswordRevisionDate = response.Login.PasswordRevisionDate;
|
||||
Totp = response.Login.Totp;
|
||||
}
|
||||
|
||||
@ -33,6 +34,7 @@ namespace Bit.App.Models.Data
|
||||
public IEnumerable<LoginUriDataModel> Uris { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public DateTime? PasswordRevisionDate { get; set; }
|
||||
public string Totp { get; set; }
|
||||
}
|
||||
}
|
||||
|
18
src/App/Models/Data/CipherData/PasswordHistoryDataModel.cs
Normal file
18
src/App/Models/Data/CipherData/PasswordHistoryDataModel.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Models.Data
|
||||
{
|
||||
public class PasswordHistoryDataModel
|
||||
{
|
||||
public PasswordHistoryDataModel() { }
|
||||
|
||||
public PasswordHistoryDataModel(PasswordHistoryResponse h)
|
||||
{
|
||||
Password = h.Password;
|
||||
LastUsedDate = h.LastUsedDate;
|
||||
}
|
||||
|
||||
public string Password { get; set; }
|
||||
public System.DateTime LastUsedDate { get; set; }
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ namespace Bit.App.Models
|
||||
|
||||
Username = deserializedData.Username != null ? new CipherString(deserializedData.Username) : null;
|
||||
Password = deserializedData.Password != null ? new CipherString(deserializedData.Password) : null;
|
||||
PasswordRevisionDate = deserializedData.PasswordRevisionDate;
|
||||
Totp = deserializedData.Totp != null ? new CipherString(deserializedData.Totp) : null;
|
||||
Uris = deserializedData.Uris?.Select(u => new LoginUri(u));
|
||||
}
|
||||
@ -35,6 +36,7 @@ namespace Bit.App.Models
|
||||
public IEnumerable<LoginUri> Uris { get; set; }
|
||||
public CipherString Username { get; set; }
|
||||
public CipherString Password { get; set; }
|
||||
public DateTime? PasswordRevisionDate { get; set; }
|
||||
public CipherString Totp { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace Bit.App.Models.Page
|
||||
{
|
||||
private const string MaskedPasswordString = "••••••••";
|
||||
|
||||
private string _name, _notes;
|
||||
private string _name, _notes, _reivisonDate, _passwordReivisonDate;
|
||||
private List<Attachment> _attachments;
|
||||
private List<Field> _fields;
|
||||
private List<LoginUri> _loginUris;
|
||||
@ -44,6 +44,28 @@ namespace Bit.App.Models.Page
|
||||
}
|
||||
}
|
||||
|
||||
public string RevisionDate
|
||||
{
|
||||
get => _reivisonDate;
|
||||
set
|
||||
{
|
||||
_reivisonDate = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(RevisionDate)));
|
||||
}
|
||||
}
|
||||
|
||||
public string PasswordRevisionDate
|
||||
{
|
||||
get => _passwordReivisonDate;
|
||||
set
|
||||
{
|
||||
_passwordReivisonDate = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(PasswordRevisionDate)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowPasswordRevisionDate)));
|
||||
}
|
||||
}
|
||||
public bool ShowPasswordRevisionDate => !string.IsNullOrWhiteSpace(PasswordRevisionDate);
|
||||
|
||||
public string Notes
|
||||
{
|
||||
get => _notes;
|
||||
@ -523,6 +545,20 @@ namespace Bit.App.Models.Page
|
||||
{
|
||||
Name = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||
Notes = cipher.Notes?.Decrypt(cipher.OrganizationId);
|
||||
var revisionDate = DateTime.SpecifyKind(cipher.RevisionDate, DateTimeKind.Utc).ToLocalTime();
|
||||
RevisionDate = revisionDate.ToShortDateString() + " " + revisionDate.ToShortTimeString();
|
||||
|
||||
if(cipher.PasswordRevisionDisplayDate.HasValue)
|
||||
{
|
||||
var passwordRevisionDate = DateTime.SpecifyKind(
|
||||
cipher.PasswordRevisionDisplayDate.Value, DateTimeKind.Utc).ToLocalTime();
|
||||
PasswordRevisionDate = passwordRevisionDate.ToShortDateString() + " " +
|
||||
passwordRevisionDate.ToShortTimeString();
|
||||
}
|
||||
else
|
||||
{
|
||||
PasswordRevisionDate = null;
|
||||
}
|
||||
|
||||
if(cipher.Attachments != null)
|
||||
{
|
||||
@ -693,7 +729,7 @@ namespace Bit.App.Models.Page
|
||||
}
|
||||
}
|
||||
public string Label => IsWebsite ? AppResources.Website : AppResources.URI;
|
||||
public bool IsWebsite => Value == null ? false :
|
||||
public bool IsWebsite => Value == null ? false :
|
||||
Value.StartsWith("http://") || Value.StartsWith("https://");
|
||||
public bool IsApp => Value == null ? false : Value.StartsWith(Constants.AndroidAppProtocol);
|
||||
}
|
||||
|
18
src/App/Models/PasswordHistory.cs
Normal file
18
src/App/Models/PasswordHistory.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class PasswordHistory
|
||||
{
|
||||
public PasswordHistory() { }
|
||||
|
||||
public PasswordHistory(PasswordHistoryDataModel model)
|
||||
{
|
||||
Password = model.Password != null ? new CipherString(model.Password) : null;
|
||||
LastUsedDate = model.LastUsedDate;
|
||||
}
|
||||
|
||||
public CipherString Password { get; set; }
|
||||
public System.DateTime LastUsedDate { get; set; }
|
||||
}
|
||||
}
|
@ -43,6 +43,7 @@ namespace Bit.App.Pages
|
||||
private TableSection NotesSection { get; set; }
|
||||
private TableSection AttachmentsSection { get; set; }
|
||||
private TableSection FieldsSection { get; set; }
|
||||
public TableSection OtherSection { get; set; }
|
||||
public LabeledValueCell NotesCell { get; set; }
|
||||
private EditCipherToolBarItem EditItem { get; set; }
|
||||
public List<LabeledValueCell> FieldsCells { get; set; }
|
||||
@ -51,6 +52,7 @@ namespace Bit.App.Pages
|
||||
// Login
|
||||
public LabeledValueCell LoginUsernameCell { get; set; }
|
||||
public LabeledValueCell LoginPasswordCell { get; set; }
|
||||
public LabeledValueCell LoginPasswordRevisionDateCell { get; set; }
|
||||
public LabeledValueCell LoginTotpCodeCell { get; set; }
|
||||
|
||||
// Card
|
||||
@ -111,6 +113,10 @@ namespace Bit.App.Pages
|
||||
NotesCell.Value.SetBinding(Label.TextProperty, nameof(VaultViewCipherPageModel.Notes));
|
||||
NotesCell.Value.LineBreakMode = LineBreakMode.WordWrap;
|
||||
|
||||
var revisionDateCell = new LabeledValueCell(AppResources.DateUpdated);
|
||||
revisionDateCell.Value.SetBinding(Label.TextProperty, nameof(VaultViewCipherPageModel.RevisionDate));
|
||||
revisionDateCell.Value.LineBreakMode = LineBreakMode.WordWrap;
|
||||
|
||||
switch(_type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
@ -152,6 +158,12 @@ namespace Bit.App.Pages
|
||||
nameof(VaultViewCipherPageModel.LoginTotpColor));
|
||||
LoginTotpCodeCell.Value.FontFamily =
|
||||
Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier");
|
||||
|
||||
// Password Revision Date
|
||||
LoginPasswordRevisionDateCell = new LabeledValueCell(AppResources.DatePasswordUpdated);
|
||||
LoginPasswordRevisionDateCell.Value.SetBinding(Label.TextProperty,
|
||||
nameof(VaultViewCipherPageModel.PasswordRevisionDate));
|
||||
LoginPasswordRevisionDateCell.Value.LineBreakMode = LineBreakMode.WordWrap;
|
||||
break;
|
||||
case CipherType.Card:
|
||||
CardNameCell = new LabeledValueCell(AppResources.CardholderName);
|
||||
@ -235,6 +247,11 @@ namespace Bit.App.Pages
|
||||
NotesCell
|
||||
};
|
||||
|
||||
OtherSection = new TableSection(AppResources.Other)
|
||||
{
|
||||
revisionDateCell
|
||||
};
|
||||
|
||||
Table = new ExtendedTableView
|
||||
{
|
||||
Intent = TableIntent.Settings,
|
||||
@ -363,10 +380,26 @@ namespace Bit.App.Pages
|
||||
Table.Root.Add(AttachmentsSection);
|
||||
}
|
||||
|
||||
// Other
|
||||
if(Table.Root.Contains(OtherSection))
|
||||
{
|
||||
Table.Root.Remove(OtherSection);
|
||||
}
|
||||
Table.Root.Add(OtherSection);
|
||||
|
||||
// Various types
|
||||
switch(cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
if(OtherSection.Contains(LoginPasswordRevisionDateCell))
|
||||
{
|
||||
OtherSection.Remove(LoginPasswordRevisionDateCell);
|
||||
}
|
||||
if(Model.ShowPasswordRevisionDate)
|
||||
{
|
||||
OtherSection.Add(LoginPasswordRevisionDateCell);
|
||||
}
|
||||
|
||||
AddSectionCell(LoginUsernameCell, Model.ShowLoginUsername);
|
||||
AddSectionCell(LoginPasswordCell, Model.ShowLoginPassword);
|
||||
|
||||
|
18
src/App/Resources/AppResources.Designer.cs
generated
18
src/App/Resources/AppResources.Designer.cs
generated
@ -942,6 +942,24 @@ namespace Bit.App.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Password Updated.
|
||||
/// </summary>
|
||||
public static string DatePasswordUpdated {
|
||||
get {
|
||||
return ResourceManager.GetString("DatePasswordUpdated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Updated.
|
||||
/// </summary>
|
||||
public static string DateUpdated {
|
||||
get {
|
||||
return ResourceManager.GetString("DateUpdated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to December.
|
||||
/// </summary>
|
||||
|
@ -887,7 +887,7 @@
|
||||
</data>
|
||||
<data name="YubiKeyTitle" xml:space="preserve">
|
||||
<value>YubiKey Security Key</value>
|
||||
<comment>"YubiKey NEO" is the product name and should not be translated.</comment>
|
||||
<comment>"YubiKey" is the product name and should not be translated.</comment>
|
||||
</data>
|
||||
<data name="AddNewAttachment" xml:space="preserve">
|
||||
<value>Add New Attachment</value>
|
||||
@ -1305,4 +1305,12 @@
|
||||
<data name="BitwardenAutofillAccessibilityServiceDescription2" xml:space="preserve">
|
||||
<value>The accessibility service may be helpful to use when apps do not support the standard auto-fill service.</value>
|
||||
</data>
|
||||
<data name="DatePasswordUpdated" xml:space="preserve">
|
||||
<value>Password Updated</value>
|
||||
<comment>ex. Date this password was updated</comment>
|
||||
</data>
|
||||
<data name="DateUpdated" xml:space="preserve">
|
||||
<value>Updated</value>
|
||||
<comment>ex. Date this item was updated</comment>
|
||||
</data>
|
||||
</root>
|
Loading…
Reference in New Issue
Block a user