mirror of
https://github.com/bitwarden/server
synced 2025-12-24 20:23:21 +00:00
[PM-25947] Add folders and favorites when sharing a cipher (#6402)
* add folders and favorites when sharing a cipher * refactor folders and favorites assignment to consider existing folders/favorite assignments on a cipher * remove unneeded string manipulation * remove comment * add unit test for folder/favorite sharing * add migration for sharing a cipher to org and collect reprompt, favorite and folders * update date timestamp of migration
This commit is contained in:
@@ -760,7 +760,7 @@ public class CiphersController : Controller
|
||||
ValidateClientVersionForFido2CredentialSupport(cipher);
|
||||
|
||||
var original = cipher.Clone();
|
||||
await _cipherService.ShareAsync(original, model.Cipher.ToCipher(cipher), new Guid(model.Cipher.OrganizationId),
|
||||
await _cipherService.ShareAsync(original, model.Cipher.ToCipher(cipher, user.Id), new Guid(model.Cipher.OrganizationId),
|
||||
model.CollectionIds.Select(c => new Guid(c)), user.Id, model.Cipher.LastKnownRevisionDate);
|
||||
|
||||
var sharedCipher = await GetByIdAsync(id, user.Id);
|
||||
|
||||
@@ -84,7 +84,7 @@ public class CipherRequestModel
|
||||
return existingCipher;
|
||||
}
|
||||
|
||||
public Cipher ToCipher(Cipher existingCipher)
|
||||
public Cipher ToCipher(Cipher existingCipher, Guid? userId = null)
|
||||
{
|
||||
// If Data field is provided, use it directly
|
||||
if (!string.IsNullOrWhiteSpace(Data))
|
||||
@@ -124,9 +124,12 @@ public class CipherRequestModel
|
||||
}
|
||||
}
|
||||
|
||||
var userIdKey = userId.HasValue ? userId.ToString().ToUpperInvariant() : null;
|
||||
existingCipher.Reprompt = Reprompt;
|
||||
existingCipher.Key = Key;
|
||||
existingCipher.ArchivedDate = ArchivedDate;
|
||||
existingCipher.Folders = UpdateUserSpecificJsonField(existingCipher.Folders, userIdKey, FolderId);
|
||||
existingCipher.Favorites = UpdateUserSpecificJsonField(existingCipher.Favorites, userIdKey, Favorite);
|
||||
|
||||
var hasAttachments2 = (Attachments2?.Count ?? 0) > 0;
|
||||
var hasAttachments = (Attachments?.Count ?? 0) > 0;
|
||||
@@ -291,6 +294,37 @@ public class CipherRequestModel
|
||||
KeyFingerprint = SSHKey.KeyFingerprint,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a JSON string representing a dictionary by adding, updating, or removing a key-value pair
|
||||
/// based on the provided userIdKey and newValue.
|
||||
/// </summary>
|
||||
private static string UpdateUserSpecificJsonField(string existingJson, string userIdKey, object newValue)
|
||||
{
|
||||
if (userIdKey == null)
|
||||
{
|
||||
return existingJson;
|
||||
}
|
||||
|
||||
var jsonDict = string.IsNullOrWhiteSpace(existingJson)
|
||||
? new Dictionary<string, object>()
|
||||
: JsonSerializer.Deserialize<Dictionary<string, object>>(existingJson) ?? new Dictionary<string, object>();
|
||||
|
||||
var shouldRemove = newValue == null ||
|
||||
(newValue is string strValue && string.IsNullOrWhiteSpace(strValue)) ||
|
||||
(newValue is bool boolValue && !boolValue);
|
||||
|
||||
if (shouldRemove)
|
||||
{
|
||||
jsonDict.Remove(userIdKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonDict[userIdKey] = newValue is string str ? str.ToUpperInvariant() : newValue;
|
||||
}
|
||||
|
||||
return jsonDict.Count == 0 ? null : JsonSerializer.Serialize(jsonDict);
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherWithIdRequestModel : CipherRequestModel
|
||||
|
||||
@@ -704,6 +704,9 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
trackedCipher.RevisionDate = cipher.RevisionDate;
|
||||
trackedCipher.DeletedDate = cipher.DeletedDate;
|
||||
trackedCipher.Key = cipher.Key;
|
||||
trackedCipher.Folders = cipher.Folders;
|
||||
trackedCipher.Favorites = cipher.Favorites;
|
||||
trackedCipher.Reprompt = cipher.Reprompt;
|
||||
|
||||
await transaction.CommitAsync();
|
||||
|
||||
|
||||
@@ -38,8 +38,13 @@ BEGIN
|
||||
[Data] = @Data,
|
||||
[Attachments] = @Attachments,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate, [Key] = @Key, [ArchivedDate] = @ArchivedDate
|
||||
-- No need to update CreationDate, Favorites, Folders, or Type since that data will not change
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Key] = @Key,
|
||||
[ArchivedDate] = @ArchivedDate,
|
||||
[Folders] = @Folders,
|
||||
[Favorites] = @Favorites,
|
||||
[Reprompt] = @Reprompt
|
||||
-- No need to update CreationDate or Type since that data will not change
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
|
||||
Reference in New Issue
Block a user