bitwarden_vault/cipher/attachment_client/
mod.rs1use std::{path::Path, sync::Arc};
2
3use bitwarden_core::{FromClient, client::ApiConfigurations, key_management::KeySlotIds};
4use bitwarden_crypto::{EncString, KeyStore};
5use bitwarden_error::bitwarden_error;
6use bitwarden_state::repository::Repository;
7use thiserror::Error;
8#[cfg(feature = "wasm")]
9use wasm_bindgen::prelude::*;
10
11use crate::{
12 Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView,
13 Cipher, DecryptError, EncryptError,
14};
15
16mod admin;
17mod create;
18mod delete;
19mod download_url;
20mod renew;
21mod upgrade;
22
23pub use admin::{
24 AttachmentAdminClient, CipherAdminGetAttachmentDownloadUrlError, DeleteAttachmentAdminError,
25};
26pub use create::{
27 AttachmentFileUploadType, CipherCreateAttachmentError, CreateAttachmentRequest,
28 CreatedAttachment,
29};
30pub use delete::CipherDeleteAttachmentError;
31pub use download_url::CipherGetAttachmentDownloadUrlError;
32pub use renew::CipherRenewFileUploadUrlError;
33pub use upgrade::CipherUpgradeAttachmentError;
34
35#[allow(missing_docs)]
37#[bitwarden_error(flat)]
38#[derive(Debug, Error)]
39pub enum EncryptFileError {
40 #[error(transparent)]
41 Encrypt(#[from] EncryptError),
42 #[error(transparent)]
43 Io(#[from] std::io::Error),
44}
45
46#[allow(missing_docs)]
48#[bitwarden_error(flat)]
49#[derive(Debug, Error)]
50pub enum DecryptFileError {
51 #[error(transparent)]
52 Decrypt(#[from] DecryptError),
53 #[error(transparent)]
54 Io(#[from] std::io::Error),
55}
56
57#[cfg_attr(feature = "wasm", wasm_bindgen)]
59#[derive(FromClient)]
60pub struct AttachmentsClient {
61 pub(crate) key_store: KeyStore<KeySlotIds>,
62 pub(crate) api_configurations: Arc<ApiConfigurations>,
63 pub(crate) repository: Option<Arc<dyn Repository<Cipher>>>,
64 pub(crate) http_client: reqwest::Client,
65}
66
67#[cfg_attr(feature = "wasm", wasm_bindgen)]
68impl AttachmentsClient {
69 pub fn admin(&self) -> AttachmentAdminClient {
72 AttachmentAdminClient {
73 api_configurations: self.api_configurations.clone(),
74 }
75 }
76
77 #[allow(missing_docs)]
78 pub fn decrypt_buffer(
79 &self,
80 cipher: Cipher,
81 attachment: AttachmentView,
82 encrypted_buffer: &[u8],
83 ) -> Result<Vec<u8>, DecryptError> {
84 Ok(self.key_store.decrypt(&AttachmentFile {
85 cipher,
86 attachment,
87 contents: EncString::from_buffer(encrypted_buffer)?,
88 })?)
89 }
90}
91
92impl AttachmentsClient {
93 #[allow(missing_docs)]
94 pub fn encrypt_buffer(
95 &self,
96 cipher: Cipher,
97 attachment: AttachmentView,
98 buffer: &[u8],
99 ) -> Result<AttachmentEncryptResult, EncryptError> {
100 Ok(self.key_store.encrypt(AttachmentFileView {
101 cipher,
102 attachment,
103 contents: buffer,
104 })?)
105 }
106
107 #[allow(missing_docs)]
108 pub fn encrypt_file(
109 &self,
110 cipher: Cipher,
111 attachment: AttachmentView,
112 decrypted_file_path: &Path,
113 encrypted_file_path: &Path,
114 ) -> Result<Attachment, EncryptFileError> {
115 let data = std::fs::read(decrypted_file_path)?;
116 let AttachmentEncryptResult {
117 attachment,
118 contents,
119 } = self.encrypt_buffer(cipher, attachment, &data)?;
120 std::fs::write(encrypted_file_path, contents)?;
121 Ok(attachment)
122 }
123
124 #[allow(missing_docs)]
125 pub fn decrypt_file(
126 &self,
127 cipher: Cipher,
128 attachment: AttachmentView,
129 encrypted_file_path: &Path,
130 decrypted_file_path: &Path,
131 ) -> Result<(), DecryptFileError> {
132 let data = std::fs::read(encrypted_file_path)?;
133 let decrypted = self.decrypt_buffer(cipher, attachment, &data)?;
134 std::fs::write(decrypted_file_path, decrypted)?;
135 Ok(())
136 }
137}