From 12c772b197fc7c3a02caf8a2aecdd952a68c2dd3 Mon Sep 17 00:00:00 2001 From: Stephen <11358399+nixuno@users.noreply.github.com> Date: Mon, 5 May 2025 15:44:04 -0400 Subject: [PATCH] Add bulk_collections endpoint --- src/api/core/ciphers.rs | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 6b883bab..0b6faae6 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -86,6 +86,7 @@ pub fn routes() -> Vec { post_collections_update, post_collections_admin, put_collections_admin, + bulk_collections ] } @@ -724,6 +725,19 @@ struct CollectionsAdminData { collection_ids: Vec, } +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct BulkCollectionsData { + #[serde(alias = "OrganizationId")] + organization_id: OrganizationId, + #[serde(alias = "CollectionIds")] + collection_ids: Vec, + #[serde(alias = "CipherIds")] + cipher_ids: Vec, + #[serde(alias = "RemoveCollections")] + remove_collections: bool, +} + #[put("/ciphers//collections_v2", data = "")] async fn put_collections2_update( cipher_id: CipherId, @@ -751,6 +765,57 @@ async fn post_collections2_update( }))) } +#[post("/ciphers/bulk_collections", data = "")] +async fn post_bulk_collections( + data: Json, + headers: Headers, + mut conn: DbConn, + nt: Notify<'_>, +) -> JsonResult { + let data: BulkCollectionsData = data.into_inner(); + + let Some(org) = Organization::find_by_uuid(&data.organization_id, &mut conn).await else { + err!("Organization doesn't exist") + }; + + if !org.is_admin(&headers.user.uuid, &mut conn).await { + err!("You don't have permission to add item to organization") + } + + let mut ciphers = Vec::with_capacity(data.cipher_ids.len()); + for cipher_id in data.cipher_ids { + let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else { + err!("Cipher doesn't exist") + }; + + if !cipher.is_write_accessible_to_user(&headers.user.uuid, &mut conn).await { + err!("Cipher is not write accessible") + } + + ciphers.push(cipher); + } + + for collection_id in data.collection_ids { + let Some(collection) = Collection::find_by_uuid_and_org(&collection_id, &data.organization_id, &mut conn).await else { + err!("Collection doesn't exist") + }; + + if collection.is_writable_by_user(&headers.user.uuid, &mut conn).await { + for cipher in &ciphers { + if data.remove_collections { + CollectionCipher::delete(&cipher.uuid, &collection.uuid, &mut conn).await?; + } else { + CollectionCipher::save(&cipher.uuid, &collection.uuid, &mut conn).await?; + } + } + } else { + err!("No rights to modify the collection") + } + } + + Ok(()) +} + #[put("/ciphers//collections", data = "")] async fn put_collections_update( cipher_id: CipherId,