Skip to main content

bitwarden_uniffi/vault/
ciphers.rs

1use bitwarden_collections::collection::CollectionId;
2use bitwarden_core::OrganizationId;
3use bitwarden_vault::{
4    Cipher, CipherCreateRequest, CipherEditRequest, CipherId, CipherListView,
5    CipherPartialEditRequest, CipherView, DecryptCipherListResult, DecryptCipherResult,
6    EncryptionContext, FolderId,
7};
8
9use crate::Result;
10
11#[allow(missing_docs)]
12#[derive(uniffi::Object)]
13pub struct CiphersClient(pub(crate) bitwarden_vault::CiphersClient);
14
15#[uniffi::export(async_runtime = "tokio")]
16impl CiphersClient {
17    /// Encrypt cipher
18    pub async fn encrypt(&self, cipher_view: CipherView) -> Result<EncryptionContext> {
19        Ok(self.0.encrypt(cipher_view).await?)
20    }
21
22    /// Decrypt cipher
23    pub async fn decrypt(&self, cipher: Cipher) -> Result<CipherView> {
24        Ok(self.0.decrypt(cipher).await?)
25    }
26
27    /// Decrypt cipher list
28    pub async fn decrypt_list(&self, ciphers: Vec<Cipher>) -> Result<Vec<CipherListView>> {
29        Ok(self.0.decrypt_list(ciphers).await?)
30    }
31
32    /// Encrypt a list of cipher views. Fails if any cipher fails to encrypt.
33    pub async fn encrypt_list(
34        &self,
35        cipher_views: Vec<CipherView>,
36    ) -> Result<Vec<EncryptionContext>> {
37        Ok(self.0.encrypt_list(cipher_views).await?)
38    }
39
40    /// Decrypt cipher list with failures
41    /// Returns both successfully decrypted ciphers and any that failed to decrypt
42    // Note that this function still needs to return a Result, as the parameter conversion can still
43    // fail
44    pub async fn decrypt_list_with_failures(
45        &self,
46        ciphers: Vec<Cipher>,
47    ) -> Result<DecryptCipherListResult> {
48        Ok(self.0.decrypt_list_with_failures(ciphers).await)
49    }
50
51    /// Move a cipher to an organization, reencrypting the cipher key if necessary
52    pub fn move_to_organization(
53        &self,
54        cipher: CipherView,
55        organization_id: OrganizationId,
56    ) -> Result<CipherView> {
57        Ok(self.0.move_to_organization(cipher, organization_id)?)
58    }
59
60    /// Prepare ciphers for bulk share to an organization
61    pub async fn prepare_ciphers_for_bulk_share(
62        &self,
63        ciphers: Vec<CipherView>,
64        organization_id: OrganizationId,
65        collection_ids: Vec<CollectionId>,
66    ) -> Result<Vec<EncryptionContext>> {
67        Ok(self
68            .0
69            .prepare_ciphers_for_bulk_share(ciphers, organization_id, collection_ids)
70            .await?)
71    }
72
73    /// Decrypt full cipher list
74    /// Returns both successfully fully decrypted ciphers and any that failed to decrypt
75    // Note that this function still needs to return a Result, as the parameter conversion can still
76    // fail
77    pub async fn decrypt_list_full_with_failures(
78        &self,
79        ciphers: Vec<Cipher>,
80    ) -> Result<DecryptCipherResult> {
81        Ok(self.0.decrypt_list_full_with_failures(ciphers).await)
82    }
83
84    /// Create a new cipher and save it to the server and local state
85    pub async fn create(&self, request: CipherCreateRequest) -> Result<CipherView> {
86        Ok(self.0.create(request).await?)
87    }
88
89    /// Edit an existing cipher and save it to the server and local state
90    pub async fn edit(&self, request: CipherEditRequest) -> Result<CipherView> {
91        Ok(self.0.edit(request).await?)
92    }
93
94    /// Edit a PAM-gated cipher whose secrets were revealed under an active lease.
95    ///
96    /// Pass the full view obtained from the lease-authorised read as `original_cipher_view`. The
97    /// returned view is partial, since the server withholds secrets from a gated write-return.
98    pub async fn edit_gated(
99        &self,
100        request: CipherEditRequest,
101        original_cipher_view: CipherView,
102    ) -> Result<CipherView> {
103        Ok(self.0.edit_gated(request, original_cipher_view).await?)
104    }
105
106    /// Update only the folder and favorite status of a cipher, for users without edit permission
107    pub async fn edit_partial(&self, request: CipherPartialEditRequest) -> Result<CipherView> {
108        Ok(self.0.edit_partial(request).await?)
109    }
110
111    /// Update the collections a cipher belongs to
112    pub async fn update_collection(
113        &self,
114        cipher_id: CipherId,
115        collection_ids: Vec<CollectionId>,
116    ) -> Result<CipherView> {
117        Ok(self.0.update_collection(cipher_id, collection_ids).await?)
118    }
119
120    /// Get a cipher from local state and decrypt it
121    pub async fn get(&self, cipher_id: CipherId) -> Result<CipherView> {
122        Ok(self.0.get(cipher_id).await?)
123    }
124
125    /// Get all ciphers from local state and decrypt them to list views, returning both successes
126    /// and failures
127    pub async fn list(&self) -> Result<DecryptCipherListResult> {
128        Ok(self.0.list().await?)
129    }
130
131    /// Get all ciphers from local state and fully decrypt them, returning both successes and
132    /// failures
133    pub async fn get_all(&self) -> Result<DecryptCipherResult> {
134        Ok(self.0.get_all().await?)
135    }
136
137    /// Permanently delete a cipher from the server and local state
138    pub async fn delete(&self, cipher_id: CipherId) -> Result<()> {
139        Ok(self.0.delete(cipher_id).await?)
140    }
141
142    /// Permanently delete multiple ciphers from the server and local state
143    pub async fn delete_many(
144        &self,
145        cipher_ids: Vec<CipherId>,
146        organization_id: Option<OrganizationId>,
147    ) -> Result<()> {
148        Ok(self.0.delete_many(cipher_ids, organization_id).await?)
149    }
150
151    /// Move a cipher to the trash
152    pub async fn soft_delete(&self, cipher_id: CipherId) -> Result<()> {
153        Ok(self.0.soft_delete(cipher_id).await?)
154    }
155
156    /// Move multiple ciphers to the trash
157    pub async fn soft_delete_many(
158        &self,
159        cipher_ids: Vec<CipherId>,
160        organization_id: Option<OrganizationId>,
161    ) -> Result<()> {
162        Ok(self.0.soft_delete_many(cipher_ids, organization_id).await?)
163    }
164
165    /// Restore a cipher from the trash
166    pub async fn restore(&self, cipher_id: CipherId) -> Result<CipherView> {
167        Ok(self.0.restore(cipher_id).await?)
168    }
169
170    /// Restore multiple ciphers from the trash
171    pub async fn restore_many(&self, cipher_ids: Vec<CipherId>) -> Result<DecryptCipherListResult> {
172        Ok(self.0.restore_many(cipher_ids).await?)
173    }
174
175    /// Share a cipher with an organization, re-encrypting it with the organization key
176    pub async fn share_cipher(
177        &self,
178        cipher_view: CipherView,
179        organization_id: OrganizationId,
180        collection_ids: Vec<CollectionId>,
181        original_cipher_view: Option<CipherView>,
182    ) -> Result<CipherView> {
183        Ok(self
184            .0
185            .share_cipher(
186                cipher_view,
187                organization_id,
188                collection_ids,
189                original_cipher_view,
190            )
191            .await?)
192    }
193
194    /// Share multiple ciphers with an organization, re-encrypting them with the organization key
195    pub async fn share_ciphers_bulk(
196        &self,
197        cipher_views: Vec<CipherView>,
198        organization_id: OrganizationId,
199        collection_ids: Vec<CollectionId>,
200    ) -> Result<Vec<CipherView>> {
201        Ok(self
202            .0
203            .share_ciphers_bulk(cipher_views, organization_id, collection_ids)
204            .await?)
205    }
206
207    /// Move multiple ciphers to a folder, or out of any folder when `folder_id` is `None`
208    pub async fn move_many(
209        &self,
210        cipher_ids: Vec<CipherId>,
211        folder_id: Option<FolderId>,
212    ) -> Result<()> {
213        Ok(self.0.move_many(cipher_ids, folder_id).await?)
214    }
215
216    /// Add or remove collections for multiple organization ciphers
217    pub async fn bulk_update_collections(
218        &self,
219        organization_id: OrganizationId,
220        cipher_ids: Vec<CipherId>,
221        collection_ids: Vec<CollectionId>,
222        remove_collections: bool,
223    ) -> Result<()> {
224        Ok(self
225            .0
226            .bulk_update_collections(
227                organization_id,
228                cipher_ids,
229                collection_ids,
230                remove_collections,
231            )
232            .await?)
233    }
234}