diff --git a/src/Infrastructure.EntityFramework/Repositories/Queries/UserCipherDetailsQuery.cs b/src/Infrastructure.EntityFramework/Repositories/Queries/UserCipherDetailsQuery.cs index 25b8192ff7..faf84f4f97 100644 --- a/src/Infrastructure.EntityFramework/Repositories/Queries/UserCipherDetailsQuery.cs +++ b/src/Infrastructure.EntityFramework/Repositories/Queries/UserCipherDetailsQuery.cs @@ -50,7 +50,7 @@ public class UserCipherDetailsQuery : IQuery where ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null - select new { c, ou, o, cc, cu, gu, g, cg }.c; + select c; var query2 = from c in dbContext.Ciphers where c.UserId == _userId @@ -79,14 +79,23 @@ public class UserCipherDetailsQuery : IQuery private static Guid? GetFolderId(Guid? userId, Cipher cipher) { - if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders)) + try { - var folders = JsonSerializer.Deserialize>(cipher.Folders); - if (folders.TryGetValue(userId.Value, out var folder)) + if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders)) { - return folder; + var folders = JsonSerializer.Deserialize>(cipher.Folders); + if (folders.TryGetValue(userId.Value, out var folder)) + { + return folder; + } } + + return null; + } + catch + { + // Some Folders might be in an invalid format like: '{ "", "" }' + return null; } - return null; } } diff --git a/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs b/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs index af21005ff3..cf2b5085d2 100644 --- a/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs +++ b/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs @@ -1,4 +1,6 @@ -using AutoMapper; +using System.Text.Json; +using System.Text.Json.Nodes; +using AutoMapper; using Bit.Core.Enums; using Bit.Core.Utilities; using Bit.Core.Vault.Enums; @@ -13,8 +15,8 @@ using Bit.Infrastructure.EntityFramework.Vault.Repositories.Queries; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using NS = Newtonsoft.Json; +using NSL = Newtonsoft.Json.Linq; using User = Bit.Core.Entities.User; namespace Bit.Infrastructure.EntityFramework.Vault.Repositories; @@ -198,9 +200,9 @@ public class CipherRepository : Repository { var foldersJson = string.IsNullOrWhiteSpace(cipher.Folders) ? - new JObject() : - JObject.Parse(cipher.Folders); + new NSL.JObject() : + NSL.JObject.Parse(cipher.Folders); if (folderId.HasValue) { @@ -409,7 +411,7 @@ public class CipherRepository : Repository(cipher.UserId.Value.ToString(), true), + }); + cipher.Favorites = JsonSerializer.Serialize(jsonObject); } else { var favorites = CoreHelpers.LoadClassFromJsonData>(cipher.Favorites); favorites.Add(cipher.UserId.Value, true); - cipher.Favorites = JsonConvert.SerializeObject(favorites); + cipher.Favorites = JsonSerializer.Serialize(favorites); } } else @@ -447,32 +449,45 @@ public class CipherRepository : Repository>(cipher.Favorites); favorites.Remove(cipher.UserId.Value); - cipher.Favorites = JsonConvert.SerializeObject(favorites); + cipher.Favorites = JsonSerializer.Serialize(favorites); } } if (cipher.FolderId.HasValue) { if (cipher.Folders == null) { - cipher.Folders = $"{{{userIdKey}:\"{cipher.FolderId}\"}}"; + var jsonObject = new JsonObject(new[] + { + new KeyValuePair(cipher.UserId.Value.ToString(), cipher.FolderId), + }); + cipher.Folders = JsonSerializer.Serialize(jsonObject); } else { var folders = CoreHelpers.LoadClassFromJsonData>(cipher.Folders); folders.Add(cipher.UserId.Value, cipher.FolderId.Value); - cipher.Folders = JsonConvert.SerializeObject(folders); + cipher.Folders = JsonSerializer.Serialize(folders); } } else { if (cipher.Folders != null && cipher.Folders.Contains(cipher.UserId.Value.ToString())) { - var folders = CoreHelpers.LoadClassFromJsonData>(cipher.Favorites); + var folders = CoreHelpers.LoadClassFromJsonData>(cipher.Folders); folders.Remove(cipher.UserId.Value); - cipher.Favorites = JsonConvert.SerializeObject(folders); + cipher.Folders = JsonSerializer.Serialize(folders); } } - var mappedEntity = Mapper.Map((Core.Vault.Entities.Cipher)cipher); + + // Check if this cipher is a part of an organization, and if so do + // not save the UserId into the database. This must be done after we + // set the user specific data like Folders and Favorites because + // the UserId key is used for that + cipher.UserId = cipher.OrganizationId.HasValue ? + null : + cipher.UserId; + + var mappedEntity = Mapper.Map(cipher); dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity); if (cipher.OrganizationId.HasValue) @@ -701,10 +716,10 @@ public class CipherRepository : Repository() : - JsonConvert.DeserializeObject>(cipher.Attachments); - var metaData = JsonConvert.DeserializeObject(attachment.AttachmentData); + NS.JsonConvert.DeserializeObject>(cipher.Attachments); + var metaData = NS.JsonConvert.DeserializeObject(attachment.AttachmentData); attachments[attachment.AttachmentId] = metaData; - cipher.Attachments = JsonConvert.SerializeObject(attachments); + cipher.Attachments = NS.JsonConvert.SerializeObject(attachments); await dbContext.SaveChangesAsync(); if (attachment.OrganizationId.HasValue) @@ -744,7 +759,7 @@ public class CipherRepository : Repository string.Equals(jp.Name, user.Id.ToString(), StringComparison.OrdinalIgnoreCase)); + + Assert.NotEqual(default, userProperty); + Assert.Equal(folder.Id, userProperty.Value.GetGuid()); + } }