vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 92236394e6e55e1078bb044651a4c2b08b6c3f42
parent 85bc5514f871256f8e67a51c274bcec10182c8b4
Author: Daniel GarcĂ­a <dani1861994@hotmail.com>
Date:   Fri,  4 May 2018 19:02:19 +0200

Delete folder mappings when deleting folders and make sure that we can't change a ciphers owner when created

Diffstat:
Msrc/api/core/ciphers.rs | 53+++++++++++++++++++++++++----------------------------
Msrc/api/core/folders.rs | 6+++---
Msrc/db/models/cipher.rs | 9+++++----
Msrc/db/models/folder.rs | 6++++++
4 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs @@ -107,17 +107,28 @@ fn post_ciphers_admin(data: Json<CipherData>, headers: Headers, conn: DbConn) -> fn post_ciphers(data: Json<CipherData>, headers: Headers, conn: DbConn) -> JsonResult { let data: CipherData = data.into_inner(); - let user_uuid = headers.user.uuid.clone(); - let favorite = data.favorite.unwrap_or(false); - let mut cipher = Cipher::new(Some(user_uuid), None, data.type_, data.name.clone(), favorite); - - update_cipher_from_data(&mut cipher, data, &headers, &conn)?; - cipher.save(&conn); + let mut cipher = Cipher::new(data.type_, data.name.clone()); + update_cipher_from_data(&mut cipher, data, &headers, true, &conn)?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn))) } -fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Headers, conn: &DbConn) -> EmptyResult { +fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Headers, is_new: bool, conn: &DbConn) -> EmptyResult { + if is_new { + if let Some(org_id) = data.organizationId { + match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { + None => err!("You don't have permission to add item to organization"), + Some(org_user) => if org_user.access_all || org_user.type_ < UserOrgType::User as i32 { + cipher.organization_uuid = Some(org_id); + } else { + err!("You don't have permission to add cipher directly to organization") + } + } + } else { + cipher.user_uuid = Some(headers.user.uuid.clone()); + } + } + if let Some(ref folder_id) = data.folderId { match Folder::find_by_uuid(folder_id, conn) { Some(folder) => { @@ -129,17 +140,6 @@ fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Head } } - if let Some(org_id) = data.organizationId { - match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { - None => err!("You don't have permission to add item to organization"), - Some(org_user) => if org_user.access_all || org_user.type_ < UserOrgType::User as i32 { - cipher.organization_uuid = Some(org_id); - } else { - err!("You don't have permission to add cipher directly to organization") - } - } - } - let uppercase_fields = data.fields.map(|f| { let mut value = json!({}); // Copy every field object and change the names to the correct case @@ -177,11 +177,14 @@ fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Head if cipher.move_to_folder(data.folderId, &headers.user.uuid, &conn).is_err() { err!("Error saving the folder information") } + + cipher.favorite = data.favorite.unwrap_or(false); cipher.name = data.name; cipher.notes = data.notes; cipher.fields = uppercase_fields.map(|f| f.to_string()); cipher.data = values.to_string(); + cipher.save(&conn); Ok(()) } @@ -247,14 +250,11 @@ fn post_ciphers_import(data: Json<ImportData>, headers: Headers, conn: DbConn) - let folder_uuid = relations_map.get(&index) .map(|i| folders[*i as usize].uuid.clone()); - let user_uuid = headers.user.uuid.clone(); - let favorite = cipher_data.favorite.unwrap_or(false); - let mut cipher = Cipher::new(Some(user_uuid), None, cipher_data.type_, cipher_data.name.clone(), favorite); - - if update_cipher_from_data(&mut cipher, cipher_data, &headers, &conn).is_err() { err!("Error creating cipher") } + let mut cipher = Cipher::new(cipher_data.type_, cipher_data.name.clone()); + update_cipher_from_data(&mut cipher, cipher_data, &headers, true, &conn)?; cipher.move_to_folder(folder_uuid, &headers.user.uuid.clone(), &conn).ok(); - cipher.save(&conn); + index += 1; } @@ -279,10 +279,7 @@ fn put_cipher(uuid: String, data: Json<CipherData>, headers: Headers, conn: DbCo err!("Cipher is not write accessible") } - cipher.favorite = data.favorite.unwrap_or(false); - - update_cipher_from_data(&mut cipher, data, &headers, &conn)?; - cipher.save(&conn); + update_cipher_from_data(&mut cipher, data, &headers, false, &conn)?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn))) } diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs @@ -89,10 +89,10 @@ fn delete_folder(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { err!("Folder belongs to another user") } - if !Cipher::find_by_folder(&folder.uuid, &conn).is_empty() { - err!("Folder is not empty") - } + // Delete FolderCipher mappings + for fc in FolderCipher::find_by_folder(&uuid, &conn) { fc.delete(&conn).expect("Error deleting mapping"); } + // Delete the actual folder entry folder.delete(&conn); Ok(()) diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs @@ -36,7 +36,7 @@ pub struct Cipher { /// Local methods impl Cipher { - pub fn new(user_uuid: Option<String>, organization_uuid: Option<String>, type_: i32, name: String, favorite: bool) -> Self { + pub fn new(type_: i32, name: String) -> Self { let now = Utc::now().naive_utc(); Self { @@ -44,11 +44,11 @@ impl Cipher { created_at: now, updated_at: now, - user_uuid, - organization_uuid, + user_uuid: None, + organization_uuid: None, type_, - favorite, + favorite: false, name, notes: None, @@ -98,6 +98,7 @@ impl Cipher { "OrganizationId": self.organization_uuid, "Attachments": attachments_json, "OrganizationUseTotp": false, + "CollectionIds": [], "Name": self.name, "Notes": self.notes, diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs @@ -123,4 +123,10 @@ impl FolderCipher { .filter(folders_ciphers::cipher_uuid.eq(cipher_uuid)) .first::<Self>(&**conn).ok() } + + pub fn find_by_folder(folder_uuid: &str, conn: &DbConn) -> Vec<Self> { + folders_ciphers::table + .filter(folders_ciphers::folder_uuid.eq(folder_uuid)) + .load::<Self>(&**conn).expect("Error loading folders") + } }