bitwarden_vault/cipher/cipher_client/admin/
delete.rs1use bitwarden_api_api::models::CipherBulkDeleteRequestModel;
2use bitwarden_core::{ApiError, OrganizationId};
3use bitwarden_error::bitwarden_error;
4use thiserror::Error;
5#[cfg(feature = "wasm")]
6use wasm_bindgen::prelude::wasm_bindgen;
7
8use crate::{CipherId, cipher_client::admin::CipherAdminClient};
9
10#[allow(missing_docs)]
11#[bitwarden_error(flat)]
12#[derive(Debug, Error)]
13pub enum DeleteCipherAdminError {
15 #[error(transparent)]
18 Api(#[from] ApiError),
19}
20
21async fn delete_cipher(
22 cipher_id: CipherId,
23 api_client: &bitwarden_api_api::apis::ApiClient,
24) -> Result<(), ApiError> {
25 let api = api_client.ciphers_api();
26 api.delete_admin(cipher_id.into()).await?;
27 Ok(())
28}
29
30async fn delete_ciphers_many(
31 cipher_ids: Vec<CipherId>,
32 organization_id: OrganizationId,
33 api_client: &bitwarden_api_api::apis::ApiClient,
34) -> Result<(), ApiError> {
35 let api = api_client.ciphers_api();
36
37 api.delete_many_admin(Some(CipherBulkDeleteRequestModel {
38 ids: cipher_ids.iter().map(|id| id.to_string()).collect(),
39 organization_id: Some(organization_id.to_string()),
40 }))
41 .await?;
42
43 Ok(())
44}
45
46async fn soft_delete(
47 cipher_id: CipherId,
48 api_client: &bitwarden_api_api::apis::ApiClient,
49) -> Result<(), ApiError> {
50 let api = api_client.ciphers_api();
51 api.put_delete_admin(cipher_id.into()).await?;
52 Ok(())
53}
54
55async fn soft_delete_many(
56 cipher_ids: Vec<CipherId>,
57 organization_id: OrganizationId,
58 api_client: &bitwarden_api_api::apis::ApiClient,
59) -> Result<(), ApiError> {
60 let api = api_client.ciphers_api();
61
62 api.put_delete_many_admin(Some(CipherBulkDeleteRequestModel {
63 ids: cipher_ids.iter().map(|id| id.to_string()).collect(),
64 organization_id: Some(organization_id.to_string()),
65 }))
66 .await?;
67 Ok(())
68}
69
70#[cfg_attr(feature = "wasm", wasm_bindgen)]
71impl CipherAdminClient {
72 pub async fn delete(&self, cipher_id: CipherId) -> Result<(), DeleteCipherAdminError> {
75 Ok(delete_cipher(
76 cipher_id,
77 &self
78 .client
79 .internal
80 .get_api_configurations()
81 .await
82 .api_client,
83 )
84 .await?)
85 }
86
87 pub async fn soft_delete(&self, cipher_id: CipherId) -> Result<(), DeleteCipherAdminError> {
90 Ok(soft_delete(
91 cipher_id,
92 &self
93 .client
94 .internal
95 .get_api_configurations()
96 .await
97 .api_client,
98 )
99 .await?)
100 }
101
102 pub async fn delete_many(
105 &self,
106 cipher_ids: Vec<CipherId>,
107 organization_id: OrganizationId,
108 ) -> Result<(), DeleteCipherAdminError> {
109 Ok(delete_ciphers_many(
110 cipher_ids,
111 organization_id,
112 &self
113 .client
114 .internal
115 .get_api_configurations()
116 .await
117 .api_client,
118 )
119 .await?)
120 }
121
122 pub async fn soft_delete_many(
125 &self,
126 cipher_ids: Vec<CipherId>,
127 organization_id: OrganizationId,
128 ) -> Result<(), DeleteCipherAdminError> {
129 Ok(soft_delete_many(
130 cipher_ids,
131 organization_id,
132 &self
133 .client
134 .internal
135 .get_api_configurations()
136 .await
137 .api_client,
138 )
139 .await?)
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 const TEST_CIPHER_ID: &str = "5faa9684-c793-4a2d-8a12-b33900187097";
148 const TEST_CIPHER_ID_2: &str = "6faa9684-c793-4a2d-8a12-b33900187098";
149 const TEST_ORG_ID: &str = "1bc9ac1e-f5aa-45f2-94bf-b181009709b8";
150
151 #[tokio::test]
152 async fn test_delete_as_admin() {
153 delete_cipher(
154 TEST_CIPHER_ID.parse().unwrap(),
155 &bitwarden_api_api::apis::ApiClient::new_mocked(|mock| {
156 mock.ciphers_api.expect_delete_admin().returning(move |id| {
157 assert_eq!(&id.to_string(), TEST_CIPHER_ID);
158 Ok(())
159 });
160 }),
161 )
162 .await
163 .unwrap()
164 }
165
166 #[tokio::test]
167 async fn test_soft_delete_as_admin() {
168 soft_delete(
169 TEST_CIPHER_ID.parse().unwrap(),
170 &bitwarden_api_api::apis::ApiClient::new_mocked(|mock| {
171 mock.ciphers_api
172 .expect_put_delete_admin()
173 .returning(move |id| {
174 assert_eq!(&id.to_string(), TEST_CIPHER_ID);
175 Ok(())
176 });
177 }),
178 )
179 .await
180 .unwrap()
181 }
182
183 #[tokio::test]
184 async fn test_delete_many_as_admin() {
185 delete_ciphers_many(
186 vec![
187 TEST_CIPHER_ID.parse().unwrap(),
188 TEST_CIPHER_ID_2.parse().unwrap(),
189 ],
190 TEST_ORG_ID.parse().unwrap(),
191 &bitwarden_api_api::apis::ApiClient::new_mocked(|mock| {
192 mock.ciphers_api
193 .expect_delete_many_admin()
194 .returning(move |request| {
195 let CipherBulkDeleteRequestModel {
196 ids,
197 organization_id,
198 } = request.unwrap();
199
200 assert_eq!(
201 ids,
202 vec![TEST_CIPHER_ID.to_string(), TEST_CIPHER_ID_2.to_string(),],
203 );
204 assert_eq!(organization_id, Some(TEST_ORG_ID.to_string()));
205 Ok(())
206 });
207 }),
208 )
209 .await
210 .unwrap()
211 }
212
213 #[tokio::test]
214 async fn test_soft_delete_many_as_admin() {
215 soft_delete_many(
216 vec![
217 TEST_CIPHER_ID.parse().unwrap(),
218 TEST_CIPHER_ID_2.parse().unwrap(),
219 ],
220 TEST_ORG_ID.parse().unwrap(),
221 &bitwarden_api_api::apis::ApiClient::new_mocked(|mock| {
222 mock.ciphers_api
223 .expect_put_delete_many_admin()
224 .returning(move |request| {
225 let CipherBulkDeleteRequestModel {
226 ids,
227 organization_id,
228 } = request.unwrap();
229
230 assert_eq!(
231 ids,
232 vec![TEST_CIPHER_ID.to_string(), TEST_CIPHER_ID_2.to_string()],
233 );
234 assert_eq!(organization_id, Some(TEST_ORG_ID.to_string()));
235 Ok(())
236 });
237 }),
238 )
239 .await
240 .unwrap()
241 }
242}