Skip to content

Commit

Permalink
Fix duplicate folder creations during import (#4702)
Browse files Browse the repository at this point in the history
During import you are able to select an existing folder, or with
Bitwarden exports it can contain existing folders already. In either
case it didn't matter, we always created new folders.

Bitwarden uses the same UUID of the selected or existing folders if they
are already there.

This PR fixes this by using the same behaviour.

Fixes #4700
  • Loading branch information
BlackDex authored Jul 4, 2024
1 parent d42b264 commit bd91964
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
19 changes: 13 additions & 6 deletions src/api/core/ciphers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,24 +562,31 @@ async fn post_ciphers_import(
Cipher::validate_notes(&data.ciphers)?;

// Read and create the folders
let mut folders: Vec<_> = Vec::new();
let existing_folders: Vec<String> =
Folder::find_by_user(&headers.user.uuid, &mut conn).await.into_iter().map(|f| f.uuid).collect();
let mut folders: Vec<String> = Vec::with_capacity(data.folders.len());
for folder in data.folders.into_iter() {
let mut new_folder = Folder::new(headers.user.uuid.clone(), folder.name);
new_folder.save(&mut conn).await?;
let folder_uuid = if folder.id.is_some() && existing_folders.contains(folder.id.as_ref().unwrap()) {
folder.id.unwrap()
} else {
let mut new_folder = Folder::new(headers.user.uuid.clone(), folder.name);
new_folder.save(&mut conn).await?;
new_folder.uuid
};

folders.push(new_folder);
folders.push(folder_uuid);
}

// Read the relations between folders and ciphers
let mut relations_map = HashMap::new();
let mut relations_map = HashMap::with_capacity(data.folder_relationships.len());

for relation in data.folder_relationships {
relations_map.insert(relation.key, relation.value);
}

// Read and create the ciphers
for (index, mut cipher_data) in data.ciphers.into_iter().enumerate() {
let folder_uuid = relations_map.get(&index).map(|i| folders[*i].uuid.clone());
let folder_uuid = relations_map.get(&index).map(|i| folders[*i].clone());
cipher_data.folder_id = folder_uuid;

let mut cipher = Cipher::new(cipher_data.r#type, cipher_data.name.clone());
Expand Down
1 change: 1 addition & 0 deletions src/api/core/folders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ async fn get_folder(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResul
#[serde(rename_all = "camelCase")]
pub struct FolderData {
pub name: String,
pub id: Option<String>,
}

#[post("/folders", data = "<data>")]
Expand Down

0 comments on commit bd91964

Please sign in to comment.