bitwarden_vault/cipher/attachment_client/
renew.rs1use 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::{AttachmentsClient, CipherId};
8
9#[allow(missing_docs)]
10#[bitwarden_error(flat)]
11#[derive(Debug, Error)]
12pub enum CipherRenewFileUploadUrlError {
13 #[error(transparent)]
14 Api(#[from] ApiError),
15 #[error(transparent)]
16 MissingField(#[from] MissingFieldError),
17}
18
19impl<T> From<bitwarden_api_api::apis::Error<T>> for CipherRenewFileUploadUrlError {
20 fn from(value: bitwarden_api_api::apis::Error<T>) -> Self {
21 Self::Api(value.into())
22 }
23}
24
25#[cfg_attr(feature = "wasm", wasm_bindgen)]
26impl AttachmentsClient {
27 pub async fn renew_file_upload_url(
30 &self,
31 cipher_id: CipherId,
32 attachment_id: String,
33 ) -> Result<String, CipherRenewFileUploadUrlError> {
34 let response = self
35 .api_configurations
36 .api_client
37 .ciphers_api()
38 .renew_file_upload_url(cipher_id.into(), &attachment_id)
39 .await?;
40
41 response.url.ok_or_else(|| MissingFieldError("url").into())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use std::sync::Arc;
48
49 use bitwarden_api_api::{apis::ApiClient, models::AttachmentUploadDataResponseModel};
50 use bitwarden_core::{client::ApiConfigurations, key_management::KeySlotIds};
51 use bitwarden_crypto::KeyStore;
52 use reqwest::StatusCode;
53
54 use super::*;
55
56 const TEST_CIPHER_ID: &str = "5faa9684-c793-4a2d-8a12-b33900187097";
57 const TEST_ATTACHMENT_ID: &str = "uf7bkexzag04d3cw04jsbqqkbpbwhxs0";
58 const TEST_RENEW_URL: &str = "http://localhost:4000/attachments/test/renewed";
59
60 fn client_with_api(api_client: ApiClient) -> AttachmentsClient {
61 AttachmentsClient {
62 key_store: KeyStore::<KeySlotIds>::default(),
63 api_configurations: Arc::new(ApiConfigurations::from_api_client(api_client)),
64 repository: None,
65 http_client: reqwest::Client::new(),
66 }
67 }
68
69 #[tokio::test]
70 async fn returns_url_from_api_response() {
71 let api_client = ApiClient::new_mocked(|mock| {
72 mock.ciphers_api
73 .expect_renew_file_upload_url()
74 .returning(|id, attachment_id| {
75 assert_eq!(&id.to_string(), TEST_CIPHER_ID);
76 assert_eq!(attachment_id, TEST_ATTACHMENT_ID);
77 Ok(AttachmentUploadDataResponseModel {
78 url: Some(TEST_RENEW_URL.to_string()),
79 ..Default::default()
80 })
81 });
82 });
83
84 let client = client_with_api(api_client);
85 let cipher_id: CipherId = TEST_CIPHER_ID.parse().unwrap();
86 let url = client
87 .renew_file_upload_url(cipher_id, TEST_ATTACHMENT_ID.to_string())
88 .await
89 .unwrap();
90
91 assert_eq!(url, TEST_RENEW_URL);
92 }
93
94 #[tokio::test]
95 async fn returns_missing_field_when_response_has_no_url() {
96 let api_client = ApiClient::new_mocked(|mock| {
97 mock.ciphers_api
98 .expect_renew_file_upload_url()
99 .returning(|_id, _attachment_id| {
100 Ok(AttachmentUploadDataResponseModel {
101 url: None,
102 ..Default::default()
103 })
104 });
105 });
106
107 let client = client_with_api(api_client);
108 let cipher_id: CipherId = TEST_CIPHER_ID.parse().unwrap();
109 let err = client
110 .renew_file_upload_url(cipher_id, TEST_ATTACHMENT_ID.to_string())
111 .await
112 .unwrap_err();
113
114 assert!(matches!(
115 err,
116 CipherRenewFileUploadUrlError::MissingField(_)
117 ));
118 }
119
120 #[tokio::test]
121 async fn propagates_api_errors() {
122 let api_client = ApiClient::new_mocked(|mock| {
123 mock.ciphers_api
124 .expect_renew_file_upload_url()
125 .returning(|_id, _attachment_id| {
126 Err(bitwarden_api_api::apis::Error::Response(
127 bitwarden_api_api::apis::ResponseContent {
128 status: StatusCode::INTERNAL_SERVER_ERROR,
129 message: "boom".to_string(),
130 },
131 ))
132 });
133 });
134
135 let client = client_with_api(api_client);
136 let cipher_id: CipherId = TEST_CIPHER_ID.parse().unwrap();
137 let err = client
138 .renew_file_upload_url(cipher_id, TEST_ATTACHMENT_ID.to_string())
139 .await
140 .unwrap_err();
141
142 assert!(matches!(err, CipherRenewFileUploadUrlError::Api(_)));
143 }
144}