1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-17 16:53:26 +00:00

[Linked fields] Add Linked Field as a custom field type (#1563)

* Add linked fields support

* Fix style, don't show linked field if Secure Note

* Finish basic linked fields for Login

* Use Field.LinkedId to store linked field info

* Reset Linked Custom Fields if cipherType changes

* Refactor to use ItemView class

* Use enum for LinkedId

* Detect if no linkedFieldOptions
This commit is contained in:
Thomas Rittson
2021-11-09 07:34:16 +10:00
committed by GitHub
parent 3cb8adeeff
commit 90b62d61ae
20 changed files with 263 additions and 30 deletions

View File

@@ -1,9 +1,11 @@
using Bit.Core.Models.Domain;
using Bit.Core.Enums;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Bit.Core.Models.View
{
public class CardView : View
public class CardView : ItemView
{
private string _brand;
private string _number;
@@ -40,7 +42,7 @@ namespace Bit.Core.Models.View
}
}
public string SubTitle
public override string SubTitle
{
get
{
@@ -82,6 +84,19 @@ namespace Bit.Core.Models.View
}
}
public override List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions
{
get => new List<KeyValuePair<string, LinkedIdType>>()
{
new KeyValuePair<string, LinkedIdType>("CardholderName", LinkedIdType.Card_CardholderName),
new KeyValuePair<string, LinkedIdType>("ExpirationMonth", LinkedIdType.Card_ExpMonth),
new KeyValuePair<string, LinkedIdType>("ExpirationYear", LinkedIdType.Card_ExpYear),
new KeyValuePair<string, LinkedIdType>("SecurityCode", LinkedIdType.Card_Code),
new KeyValuePair<string, LinkedIdType>("Brand", LinkedIdType.Card_Brand),
new KeyValuePair<string, LinkedIdType>("Number", LinkedIdType.Card_Number),
};
}
private string FormatYear(string year)
{
return year.Length == 2 ? string.Concat("20", year) : year;

View File

@@ -50,20 +50,20 @@ namespace Bit.Core.Models.View
public DateTime? DeletedDate { get; set; }
public CipherRepromptType Reprompt { get; set; }
public string SubTitle
public ItemView Item
{
get
{
switch (Type)
{
case CipherType.Login:
return Login.SubTitle;
return Login;
case CipherType.SecureNote:
return SecureNote.SubTitle;
return SecureNote;
case CipherType.Card:
return Card.SubTitle;
return Card;
case CipherType.Identity:
return Identity.SubTitle;
return Identity;
default:
break;
}
@@ -71,6 +71,8 @@ namespace Bit.Core.Models.View
}
}
public List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions => Item.LinkedFieldOptions;
public string SubTitle => Item.SubTitle;
public bool Shared => OrganizationId != null;
public bool HasPasswordHistory => PasswordHistory?.Any() ?? false;
public bool HasAttachments => Attachments?.Any() ?? false;
@@ -102,5 +104,11 @@ namespace Bit.Core.Models.View
}
}
public bool IsDeleted => DeletedDate.HasValue;
public string LinkedFieldI18nKey(LinkedIdType id)
{
return LinkedFieldOptions.Find(lfo => lfo.Value == id).Key;
}
}
}

View File

@@ -10,6 +10,7 @@ namespace Bit.Core.Models.View
public FieldView(Field f)
{
Type = f.Type;
LinkedId = f.LinkedId;
}
public string Name { get; set; }
@@ -17,5 +18,6 @@ namespace Bit.Core.Models.View
public FieldType Type { get; set; }
public string MaskedValue => Value != null ? "••••••••" : null;
public bool NewField { get; set; }
public LinkedIdType? LinkedId { get; set; }
}
}

View File

@@ -1,8 +1,10 @@
using Bit.Core.Models.Domain;
using Bit.Core.Enums;
using System.Collections.Generic;
namespace Bit.Core.Models.View
{
public class IdentityView : View
public class IdentityView : ItemView
{
private string _firstName;
private string _lastName;
@@ -47,7 +49,7 @@ namespace Bit.Core.Models.View
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
public string SubTitle
public override string SubTitle
{
get
{
@@ -141,5 +143,31 @@ namespace Bit.Core.Models.View
return string.Format("{0}, {1}, {2}", city, state, postalCode);
}
}
public override List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions
{
get => new List<KeyValuePair<string, LinkedIdType>>()
{
new KeyValuePair<string, LinkedIdType>("Title", LinkedIdType.Identity_Title),
new KeyValuePair<string, LinkedIdType>("MiddleName", LinkedIdType.Identity_MiddleName),
new KeyValuePair<string, LinkedIdType>("Address1", LinkedIdType.Identity_Address1),
new KeyValuePair<string, LinkedIdType>("Address2", LinkedIdType.Identity_Address2),
new KeyValuePair<string, LinkedIdType>("Address3", LinkedIdType.Identity_Address3),
new KeyValuePair<string, LinkedIdType>("CityTown", LinkedIdType.Identity_City),
new KeyValuePair<string, LinkedIdType>("StateProvince", LinkedIdType.Identity_State),
new KeyValuePair<string, LinkedIdType>("ZipPostalCode", LinkedIdType.Identity_PostalCode),
new KeyValuePair<string, LinkedIdType>("Country", LinkedIdType.Identity_Country),
new KeyValuePair<string, LinkedIdType>("Company", LinkedIdType.Identity_Company),
new KeyValuePair<string, LinkedIdType>("Email", LinkedIdType.Identity_Email),
new KeyValuePair<string, LinkedIdType>("Phone", LinkedIdType.Identity_Phone),
new KeyValuePair<string, LinkedIdType>("SSN", LinkedIdType.Identity_Ssn),
new KeyValuePair<string, LinkedIdType>("Username", LinkedIdType.Identity_Username),
new KeyValuePair<string, LinkedIdType>("PassportNumber", LinkedIdType.Identity_PassportNumber),
new KeyValuePair<string, LinkedIdType>("LicenseNumber", LinkedIdType.Identity_LicenseNumber),
new KeyValuePair<string, LinkedIdType>("FirstName", LinkedIdType.Identity_FirstName),
new KeyValuePair<string, LinkedIdType>("LastName", LinkedIdType.Identity_LastName),
new KeyValuePair<string, LinkedIdType>("FullName", LinkedIdType.Identity_FullName),
};
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Bit.Core.Enums;
namespace Bit.Core.Models.View
{
public abstract class ItemView : View
{
public ItemView() { }
public abstract string SubTitle { get; }
public abstract List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions { get; }
}
}

View File

@@ -1,11 +1,12 @@
using Bit.Core.Models.Domain;
using Bit.Core.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Core.Models.View
{
public class LoginView : View
public class LoginView : ItemView
{
public LoginView() { }
@@ -21,9 +22,18 @@ namespace Bit.Core.Models.View
public List<LoginUriView> Uris { get; set; }
public string Uri => HasUris ? Uris[0].Uri : null;
public string MaskedPassword => Password != null ? "••••••••" : null;
public string SubTitle => Username;
public override string SubTitle => Username;
public bool CanLaunch => HasUris && Uris.Any(u => u.CanLaunch);
public string LaunchUri => HasUris ? Uris.FirstOrDefault(u => u.CanLaunch)?.LaunchUri : null;
public bool HasUris => (Uris?.Count ?? 0) > 0;
public override List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions
{
get => new List<KeyValuePair<string, LinkedIdType>>()
{
new KeyValuePair<string, LinkedIdType>("Username", LinkedIdType.Login_Username),
new KeyValuePair<string, LinkedIdType>("Password", LinkedIdType.Login_Password),
};
}
}
}

View File

@@ -1,9 +1,10 @@
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using System.Collections.Generic;
namespace Bit.Core.Models.View
{
public class SecureNoteView : View
public class SecureNoteView : ItemView
{
public SecureNoteView() { }
@@ -13,6 +14,7 @@ namespace Bit.Core.Models.View
}
public SecureNoteType Type { get; set; }
public string SubTitle => null;
public override string SubTitle => null;
public override List<KeyValuePair<string, LinkedIdType>> LinkedFieldOptions => null;
}
}