Skip to main content

bitwarden_vault/cipher/attachment_client/admin/
delete.rs

1use bitwarden_core::{ApiError, MissingFieldError};
2use bitwarden_error::bitwarden_error;
3use thiserror::Error;
4#[cfg(feature = "wasm")]
5use wasm_bindgen::prelude::wasm_bindgen;
6
7use crate::{
8    AttachmentAdminClient, Cipher, CipherId, VaultParseError, cipher::cipher::PartialCipher,
9};
10
11#[allow(missing_docs)]
12#[bitwarden_error(flat)]
13#[derive(Debug, Error)]
14pub enum DeleteAttachmentAdminError {
15    #[error(transparent)]
16    Api(#[from] ApiError),
17    #[error(transparent)]
18    MissingField(#[from] MissingFieldError),
19    #[error(transparent)]
20    VaultParse(#[from] VaultParseError),
21}
22
23impl<T> From<bitwarden_api_api::apis::Error<T>> for DeleteAttachmentAdminError {
24    fn from(value: bitwarden_api_api::apis::Error<T>) -> Self {
25        Self::Api(value.into())
26    }
27}
28
29#[cfg_attr(feature = "wasm", wasm_bindgen)]
30impl AttachmentAdminClient {
31    /// Deletes an attachment from a cipher using the admin endpoint.
32    /// Affects server data only, does not modify local state.
33    pub async fn delete_attachment(
34        &self,
35        cipher_id: CipherId,
36        attachment_id: String,
37    ) -> Result<Cipher, DeleteAttachmentAdminError> {
38        let response = self
39            .api_configurations
40            .api_client
41            .ciphers_api()
42            .delete_attachment_admin(cipher_id.into(), &attachment_id)
43            .await?;
44
45        let cipher_response = response
46            .cipher
47            .map(|c| *c)
48            .ok_or(MissingFieldError("cipher"))?;
49        Ok(cipher_response.merge_with_cipher(None)?)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use std::sync::Arc;
56
57    use bitwarden_api_api::{
58        apis::ApiClient,
59        models::{CipherMiniResponseModel, DeleteAttachmentResponseModel},
60    };
61    use bitwarden_core::client::ApiConfigurations;
62
63    use super::*;
64
65    const TEST_CIPHER_ID: &str = "5faa9684-c793-4a2d-8a12-b33900187097";
66    const TEST_ATTACHMENT_ID: &str = "uf7bkexzag04d3cw04jsbqqkbpbwhxs0";
67
68    fn client_with_api(api_client: ApiClient) -> AttachmentAdminClient {
69        AttachmentAdminClient {
70            api_configurations: Arc::new(ApiConfigurations::from_api_client(api_client)),
71        }
72    }
73
74    #[tokio::test]
75    async fn test_delete_attachment_as_admin() {
76        let api_client = ApiClient::new_mocked(|mock| {
77            mock.ciphers_api.expect_delete_attachment_admin().returning(
78                move |id, attachment_id| {
79                    assert_eq!(&id.to_string(), TEST_CIPHER_ID);
80                    assert_eq!(attachment_id, TEST_ATTACHMENT_ID);
81                    Ok(DeleteAttachmentResponseModel {
82                        object: None,
83                        cipher: Some(Box::new(CipherMiniResponseModel {
84                            id: Some(TEST_CIPHER_ID.try_into().unwrap()),
85                            name: Some("2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=".to_string()),
86                            r#type: Some(bitwarden_api_api::models::CipherType::Login),
87                            creation_date: Some("2024-05-31T11:20:58.4566667Z".to_string()),
88                            revision_date: Some("2024-05-31T11:20:58.4566667Z".to_string()),
89                            attachments: None,
90                            ..Default::default()
91                        })),
92                    })
93                },
94            );
95        });
96
97        let client = client_with_api(api_client);
98        let result = client
99            .delete_attachment(
100                TEST_CIPHER_ID.parse().unwrap(),
101                TEST_ATTACHMENT_ID.to_string(),
102            )
103            .await
104            .unwrap();
105
106        assert!(result.attachments.is_none());
107    }
108}