diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index f7bf5cd3..98623aa9 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -448,7 +448,11 @@ pub async fn update_cipher_from_data( cipher.user_uuid = Some(headers.user.uuid.clone()); } - if let Some(ref folder_id) = data.folder_id { + // Newer Bitwarden clients may send folderId as "" instead of null for "No folder". + // Normalize empty folder_id to None to avoid invalid folder lookup errors. + let folder_id = data.folder_id.filter(|f| !f.is_empty()); + + if let Some(ref folder_id) = folder_id { if Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, conn).await.is_none() { err!("Invalid folder", "Folder does not exist or belongs to another user"); } @@ -528,7 +532,7 @@ pub async fn update_cipher_from_data( cipher.reprompt = data.reprompt.filter(|r| *r == RepromptType::None as i32 || *r == RepromptType::Password as i32); cipher.save(conn).await?; - cipher.move_to_folder(data.folder_id, &headers.user.uuid, conn).await?; + cipher.move_to_folder(folder_id, &headers.user.uuid, conn).await?; cipher.set_favorite(data.favorite, &headers.user.uuid, conn).await?; if ut != UpdateType::None { @@ -722,14 +726,16 @@ async fn put_cipher_partial( err!("Cipher does not exist", "Cipher is not accessible for the current user") } - if let Some(ref folder_id) = data.folder_id { + let folder_id = data.folder_id.filter(|f| !f.is_empty()); + + if let Some(ref folder_id) = folder_id { if Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, &conn).await.is_none() { err!("Invalid folder", "Folder does not exist or belongs to another user"); } } // Move cipher - cipher.move_to_folder(data.folder_id.clone(), &headers.user.uuid, &conn).await?; + cipher.move_to_folder(folder_id, &headers.user.uuid, &conn).await?; // Update favorite cipher.set_favorite(Some(data.favorite), &headers.user.uuid, &conn).await?; @@ -1582,7 +1588,9 @@ async fn move_cipher_selected( let data = data.into_inner(); let user_id = &headers.user.uuid; - if let Some(ref folder_id) = data.folder_id { + let folder_id = data.folder_id.filter(|f| !f.is_empty()); + + if let Some(ref folder_id) = folder_id { if Folder::find_by_uuid_and_user(folder_id, user_id, &conn).await.is_none() { err!("Invalid folder", "Folder does not exist or belongs to another user"); } @@ -1596,7 +1604,7 @@ async fn move_cipher_selected( let accessible_ciphers = Cipher::find_by_user_and_ciphers(user_id, &data.ids, &conn).await; let accessible_ciphers_count = accessible_ciphers.len(); for cipher in accessible_ciphers { - cipher.move_to_folder(data.folder_id.clone(), user_id, &conn).await?; + cipher.move_to_folder(folder_id.clone(), user_id, &conn).await?; if cipher_count == 1 { single_cipher = Some(cipher); }