bitwarden_vault/cipher/cipher_client/
get.rs1use bitwarden_core::key_management::KeySlotIds;
2use bitwarden_crypto::{CryptoError, KeyStore};
3use bitwarden_error::bitwarden_error;
4use bitwarden_state::repository::{Repository, RepositoryError};
5use thiserror::Error;
6#[cfg(feature = "wasm")]
7use wasm_bindgen::prelude::wasm_bindgen;
8
9use super::CiphersClient;
10use crate::{
11 Cipher, CipherView, ItemNotFoundError,
12 cipher::cipher::{DecryptCipherListResult, DecryptCipherResult, StrictDecrypt},
13};
14
15#[allow(missing_docs)]
16#[bitwarden_error(flat)]
17#[derive(Debug, Error)]
18pub enum GetCipherError {
19 #[error(transparent)]
20 ItemNotFound(#[from] ItemNotFoundError),
21 #[error(transparent)]
22 Crypto(#[from] CryptoError),
23 #[error(transparent)]
24 Repository(#[from] RepositoryError),
25}
26
27async fn get_cipher(
28 store: &KeyStore<KeySlotIds>,
29 repository: &dyn Repository<Cipher>,
30 id: &str,
31 use_strict_decryption: bool,
32) -> Result<CipherView, GetCipherError> {
33 let id = id.parse().map_err(|_| ItemNotFoundError)?;
34 let cipher = repository.get(id).await?.ok_or(ItemNotFoundError)?;
35
36 if use_strict_decryption {
37 Ok(store.decrypt(&StrictDecrypt(cipher))?)
38 } else {
39 Ok(store.decrypt(&cipher)?)
40 }
41}
42
43async fn list_ciphers(
44 store: &KeyStore<KeySlotIds>,
45 repository: &dyn Repository<Cipher>,
46 use_strict_decryption: bool,
47) -> Result<DecryptCipherListResult, GetCipherError> {
48 let ciphers = repository.list().await?;
49 if use_strict_decryption {
50 let strict: Vec<StrictDecrypt<Cipher>> = ciphers.into_iter().map(StrictDecrypt).collect();
51 let (successes, failures) = store.decrypt_list_with_failures(&strict);
52 Ok(DecryptCipherListResult {
53 successes,
54 failures: failures.into_iter().map(|f| f.0.clone()).collect(),
55 })
56 } else {
57 let (successes, failures) = store.decrypt_list_with_failures(&ciphers);
58 Ok(DecryptCipherListResult {
59 successes,
60 failures: failures.into_iter().cloned().collect(),
61 })
62 }
63}
64
65async fn get_all_ciphers(
66 store: &KeyStore<KeySlotIds>,
67 repository: &dyn Repository<Cipher>,
68 use_strict_decryption: bool,
69) -> Result<DecryptCipherResult, GetCipherError> {
70 let ciphers = repository.list().await?;
71 if use_strict_decryption {
72 let strict: Vec<StrictDecrypt<Cipher>> = ciphers.into_iter().map(StrictDecrypt).collect();
73 let (successes, failures) = store.decrypt_list_with_failures(&strict);
74 Ok(DecryptCipherResult {
75 successes,
76 failures: failures.into_iter().map(|f| f.0.clone()).collect(),
77 })
78 } else {
79 let (successes, failures) = store.decrypt_list_with_failures(&ciphers);
80 Ok(DecryptCipherResult {
81 successes,
82 failures: failures.into_iter().cloned().collect(),
83 })
84 }
85}
86
87#[allow(deprecated)]
88#[cfg_attr(feature = "wasm", wasm_bindgen)]
89impl CiphersClient {
90 pub async fn list(&self) -> Result<DecryptCipherListResult, GetCipherError> {
94 let key_store = self.client.internal.get_key_store();
95 let repository = self.get_repository()?;
96
97 list_ciphers(
98 key_store,
99 repository.as_ref(),
100 self.is_strict_decrypt().await,
101 )
102 .await
103 }
104
105 pub async fn get_all(&self) -> Result<DecryptCipherResult, GetCipherError> {
109 let key_store = self.client.internal.get_key_store();
110 let repository = self.get_repository()?;
111
112 get_all_ciphers(
113 key_store,
114 repository.as_ref(),
115 self.is_strict_decrypt().await,
116 )
117 .await
118 }
119
120 pub async fn get(&self, cipher_id: &str) -> Result<CipherView, GetCipherError> {
122 let key_store = self.client.internal.get_key_store();
123 let repository = self.get_repository()?;
124
125 get_cipher(
126 key_store,
127 repository.as_ref(),
128 cipher_id,
129 self.is_strict_decrypt().await,
130 )
131 .await
132 }
133}