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