diff --git a/src/Core/Models/Domain/Card.cs b/src/Core/Models/Domain/Card.cs index c53f1ec04..baeddea69 100644 --- a/src/Core/Models/Domain/Card.cs +++ b/src/Core/Models/Domain/Card.cs @@ -36,7 +36,7 @@ namespace Bit.Core.Models.Domain return DecryptObjAsync(new CardView(this), this, _map, orgId); } - public CardData ToLoginUriData() + public CardData ToCardData() { var c = new CardData(); BuildDataModel(this, c, _map); diff --git a/src/Core/Models/Domain/Cipher.cs b/src/Core/Models/Domain/Cipher.cs index 3a84343d6..b40ad24cd 100644 --- a/src/Core/Models/Domain/Cipher.cs +++ b/src/Core/Models/Domain/Cipher.cs @@ -1,14 +1,186 @@ -using System; +using Bit.Core.Models.Data; +using Bit.Core.Models.View; +using System; using System.Collections.Generic; -using System.Text; +using System.Linq; +using System.Threading.Tasks; namespace Bit.Core.Models.Domain { public class Cipher : Domain { + public Cipher() { } + + public Cipher(CipherData obj, bool alreadyEncrypted = false, Dictionary localData = null) + { + BuildDomainModel(this, obj, new HashSet + { + "Id", + "UserId", + "OrganizationId", + "FolderId", + "Name", + "Notes" + }, alreadyEncrypted, new HashSet { "Id", "UserId", "OrganizationId", "FolderId" }); + + Type = obj.Type; + Favorite = obj.Favorite; + OrganizationUseTotp = obj.OrganizationUseTotp; + Edit = obj.Edit; + RevisionDate = obj.RevisionDate; + CollectionIds = obj.CollectionIds; + LocalData = localData; + + switch(Type) + { + case Enums.CipherType.Login: + Login = new Login(obj.Login, alreadyEncrypted); + break; + case Enums.CipherType.SecureNote: + SecureNote = new SecureNote(obj.SecureNote, alreadyEncrypted); + break; + case Enums.CipherType.Card: + Card = new Card(obj.Card, alreadyEncrypted); + break; + case Enums.CipherType.Identity: + Identity = new Identity(obj.Identity, alreadyEncrypted); + break; + default: + break; + } + + Attachments = obj.Attachments?.Select(a => new Attachment(a, alreadyEncrypted)).ToList(); + Fields = obj.Fields?.Select(f => new Field(f, alreadyEncrypted)).ToList(); + PasswordHistory = obj.PasswordHistory?.Select(ph => new PasswordHistory(ph, alreadyEncrypted)).ToList(); + } + public string Id { get; set; } public string OrganizationId { get; set; } + public string FolderId { get; set; } public CipherString Name { get; set; } + public CipherString Notes { get; set; } + public Enums.CipherType Type { get; set; } + public bool Favorite { get; set; } + public bool OrganizationUseTotp { get; set; } + public bool Edit { get; set; } + public DateTime RevisionDate { get; set; } + public Dictionary LocalData { get; set; } public Login Login { get; set; } + public Identity Identity { get; set; } + public Card Card { get; set; } + public SecureNote SecureNote { get; set; } + public List Attachments { get; set; } + public List Fields { get; set; } + public List PasswordHistory { get; set; } + public List CollectionIds { get; set; } + + public async Task DecryptAsync(string orgId) + { + var model = new CipherView(this); + await DecryptObjAsync(model, this, new HashSet + { + "Name", + "Notes" + }, orgId); + + switch(Type) + { + case Enums.CipherType.Login: + model.Login = await Login.DecryptAsync(orgId); + break; + case Enums.CipherType.SecureNote: + model.SecureNote = await SecureNote.DecryptAsync(orgId); + break; + case Enums.CipherType.Card: + model.Card = await Card.DecryptAsync(orgId); + break; + case Enums.CipherType.Identity: + model.Identity = await Identity.DecryptAsync(orgId); + break; + default: + break; + } + + if(Attachments?.Any() ?? false) + { + model.Attachments = new List(); + var tasks = new List(); + foreach(var attachment in Attachments) + { + var t = attachment.DecryptAsync(orgId) + .ContinueWith(async decAttachment => model.Attachments.Add(await decAttachment)); + tasks.Add(t); + } + await Task.WhenAll(tasks); + } + if(Fields?.Any() ?? false) + { + model.Fields = new List(); + var tasks = new List(); + foreach(var field in Fields) + { + var t = field.DecryptAsync(orgId) + .ContinueWith(async decField => model.Fields.Add(await decField)); + tasks.Add(t); + } + await Task.WhenAll(tasks); + } + if(PasswordHistory?.Any() ?? false) + { + model.PasswordHistory = new List(); + var tasks = new List(); + foreach(var ph in PasswordHistory) + { + var t = ph.DecryptAsync(orgId) + .ContinueWith(async decPh => model.PasswordHistory.Add(await decPh)); + tasks.Add(t); + } + await Task.WhenAll(tasks); + } + return model; + } + + public CipherData ToCipherData(string userId) + { + var c = new CipherData + { + Id = Id, + OrganizationId = OrganizationId, + FolderId = FolderId, + UserId = OrganizationId != null ? userId : null, + Edit = Edit, + OrganizationUseTotp = OrganizationUseTotp, + Favorite = Favorite, + RevisionDate = RevisionDate, + Type = Type, + CollectionIds = CollectionIds + }; + BuildDataModel(this, c, new HashSet + { + "Name", + "Notes" + }); + switch(c.Type) + { + case Enums.CipherType.Login: + c.Login = Login.ToLoginData(); + break; + case Enums.CipherType.SecureNote: + c.SecureNote = SecureNote.ToSecureNoteData(); + break; + case Enums.CipherType.Card: + c.Card = Card.ToCardData(); + break; + case Enums.CipherType.Identity: + c.Identity = Identity.ToIdentityData(); + break; + default: + break; + } + c.Fields = Fields?.Select(f => f.ToFieldData()).ToList(); + c.Attachments = Attachments?.Select(a => a.ToAttachmentData()).ToList(); + c.PasswordHistory = PasswordHistory?.Select(ph => ph.ToPasswordHistoryData()).ToList(); + return c; + } } } diff --git a/src/Core/Models/Domain/Field.cs b/src/Core/Models/Domain/Field.cs index 677055bc2..468241cd0 100644 --- a/src/Core/Models/Domain/Field.cs +++ b/src/Core/Models/Domain/Field.cs @@ -31,7 +31,7 @@ namespace Bit.Core.Models.Domain return DecryptObjAsync(new FieldView(this), this, _map, orgId); } - public FieldData ToLoginUriData() + public FieldData ToFieldData() { var f = new FieldData(); BuildDataModel(this, f, new HashSet diff --git a/src/Core/Models/Domain/Identity.cs b/src/Core/Models/Domain/Identity.cs index 3698d680c..c45bb64d8 100644 --- a/src/Core/Models/Domain/Identity.cs +++ b/src/Core/Models/Domain/Identity.cs @@ -60,7 +60,7 @@ namespace Bit.Core.Models.Domain return DecryptObjAsync(new IdentityView(this), this, _map, orgId); } - public IdentityData ToLoginUriData() + public IdentityData ToIdentityData() { var i = new IdentityData(); BuildDataModel(this, i, _map); diff --git a/src/Core/Models/Domain/Login.cs b/src/Core/Models/Domain/Login.cs index 266a58f5f..adb2314a4 100644 --- a/src/Core/Models/Domain/Login.cs +++ b/src/Core/Models/Domain/Login.cs @@ -48,7 +48,7 @@ namespace Bit.Core.Models.Domain return view; } - public LoginData ToLoginUriData() + public LoginData ToLoginData() { var l = new LoginData(); l.PasswordRevisionDate = PasswordRevisionDate; diff --git a/src/Core/Models/Domain/PasswordHistory.cs b/src/Core/Models/Domain/PasswordHistory.cs index 1f9ed732e..6ce9bc288 100644 --- a/src/Core/Models/Domain/PasswordHistory.cs +++ b/src/Core/Models/Domain/PasswordHistory.cs @@ -29,7 +29,7 @@ namespace Bit.Core.Models.Domain return DecryptObjAsync(new PasswordHistoryView(this), this, _map, orgId); } - public PasswordHistoryData ToLoginUriData() + public PasswordHistoryData ToPasswordHistoryData() { var ph = new PasswordHistoryData(); ph.LastUsedDate = LastUsedDate; diff --git a/src/Core/Models/Domain/SecureNote.cs b/src/Core/Models/Domain/SecureNote.cs index e45239db1..6d3afab4c 100644 --- a/src/Core/Models/Domain/SecureNote.cs +++ b/src/Core/Models/Domain/SecureNote.cs @@ -21,7 +21,7 @@ namespace Bit.Core.Models.Domain return Task.FromResult(new SecureNoteView(this)); } - public SecureNoteData ToLoginUriData() + public SecureNoteData ToSecureNoteData() { return new SecureNoteData { diff --git a/src/Core/Models/View/CipherView.cs b/src/Core/Models/View/CipherView.cs index 9a86df6ea..a43c291ec 100644 --- a/src/Core/Models/View/CipherView.cs +++ b/src/Core/Models/View/CipherView.cs @@ -1,13 +1,100 @@ -using System; +using Bit.Core.Enums; +using Bit.Core.Models.Domain; +using System; using System.Collections.Generic; -using System.Text; +using System.Linq; namespace Bit.Core.Models.View { public class CipherView : View { + public CipherView() { } + + public CipherView(Cipher c) + { + Id = c.Id; + OrganizationId = c.OrganizationId; + FolderId = c.FolderId; + Favorite = c.Favorite; + OrganizationUseTotp = c.OrganizationUseTotp; + Edit = c.Edit; + Type = c.Type; + LocalData = c.LocalData; + CollectionIds = c.CollectionIds; + RevisionDate = c.RevisionDate; + } + public string Id { get; set; } + public string OrganizationId { get; set; } + public string FolderId { get; set; } public string Name { get; set; } - public string Subtitle { get; set; } + public string Notes { get; set; } + public CipherType Type { get; set; } + public bool Favorite { get; set; } + public bool OrganizationUseTotp { get; set; } + public bool Edit { get; set; } + public Dictionary LocalData { get; set; } + public LoginView Login { get; set; } + public IdentityView Identity { get; set; } + public CardView Card { get; set; } + public SecureNoteView SecureNote { get; set; } + public List Attachments { get; set; } + public List Fields { get; set; } + public List PasswordHistory { get; set; } + public List CollectionIds { get; set; } + public DateTime RevisionDate { get; set; } + + + public string Subtitle + { + get + { + switch(Type) + { + case CipherType.Login: + return Login.SubTitle; + case CipherType.SecureNote: + return SecureNote.SubTitle; + case CipherType.Card: + // TODO + // return Card.SubTitle; + case CipherType.Identity: + // return Identity.SubTitle; + default: + break; + } + return null; + } + } + + public bool HasPasswordHistory => PasswordHistory?.Any() ?? false; + public bool HasAttachments => Attachments?.Any() ?? false; + public bool HasOldAttachments + { + get + { + if(HasAttachments) + { + return Attachments.Any(a => a.Key == null); + } + return false; + } + } + public bool HasFields => Fields?.Any() ?? false; + public DateTime? PasswordRevisionDisplayDate + { + get + { + if(Type != CipherType.Login || Login == null) + { + return null; + } + else if(string.IsNullOrWhiteSpace(Login.Password)) + { + return null; + } + return Login.PasswordRevisionDate; + } + } } }