@@ -4,7 +4,10 @@ use bitwarden_crypto::IdentifyKey;
4
4
use wasm_bindgen:: prelude:: * ;
5
5
6
6
use super :: EncryptionContext ;
7
- use crate :: { Cipher , CipherError , CipherListView , CipherView , DecryptError , EncryptError } ;
7
+ use crate :: {
8
+ cipher:: cipher:: DecryptCipherListResult , Cipher , CipherError , CipherListView , CipherView ,
9
+ DecryptError , EncryptError ,
10
+ } ;
8
11
9
12
#[ allow( missing_docs) ]
10
13
#[ cfg_attr( feature = "wasm" , wasm_bindgen) ]
@@ -57,6 +60,18 @@ impl CiphersClient {
57
60
Ok ( cipher_views)
58
61
}
59
62
63
+ /// Decrypt cipher list with failures
64
+ /// Returns both successfully decrypted ciphers and any that failed to decrypt
65
+ pub fn decrypt_list_with_failures ( & self , ciphers : Vec < Cipher > ) -> DecryptCipherListResult {
66
+ let key_store = self . client . internal . get_key_store ( ) ;
67
+ let ( successes, failures) = key_store. decrypt_list_with_failures ( & ciphers) ;
68
+
69
+ DecryptCipherListResult {
70
+ successes,
71
+ failures : failures. into_iter ( ) . cloned ( ) . collect ( ) ,
72
+ }
73
+ }
74
+
60
75
#[ allow( missing_docs) ]
61
76
pub fn decrypt_fido2_credentials (
62
77
& self ,
@@ -98,50 +113,6 @@ mod tests {
98
113
use super :: * ;
99
114
use crate :: { Attachment , CipherRepromptType , CipherType , Login , VaultClientExt } ;
100
115
101
- #[ tokio:: test]
102
- async fn test_decrypt_list ( ) {
103
- let client = Client :: init_test_account ( test_bitwarden_com_account ( ) ) . await ;
104
-
105
- let dec = client
106
- . vault ( )
107
- . ciphers ( )
108
- . decrypt_list ( vec ! [ Cipher {
109
- id: Some ( "a1569f46-0797-4d3f-b859-b181009e2e49" . parse( ) . unwrap( ) ) ,
110
- organization_id: Some ( "1bc9ac1e-f5aa-45f2-94bf-b181009709b8" . parse( ) . unwrap( ) ) ,
111
- folder_id: None ,
112
- collection_ids: vec![ "66c5ca57-0868-4c7e-902f-b181009709c0" . parse( ) . unwrap( ) ] ,
113
- key: None ,
114
- name: "2.RTdUGVWYl/OZHUMoy68CMg==|sCaT5qHx8i0rIvzVrtJKww==|jB8DsRws6bXBtXNfNXUmFJ0JLDlB6GON6Y87q0jgJ+0=" . parse( ) . unwrap( ) ,
115
- notes: None ,
116
- r#type: CipherType :: Login ,
117
- login: Some ( Login {
118
- username: Some ( "2.ouEYEk+SViUtqncesfe9Ag==|iXzEJq1zBeNdDbumFO1dUA==|RqMoo9soSwz/yB99g6YPqk8+ASWRcSdXsKjbwWzyy9U=" . parse( ) . unwrap( ) ) ,
119
- password: Some ( "2.6yXnOz31o20Z2kiYDnXueA==|rBxTb6NK9lkbfdhrArmacw==|ogZir8Z8nLgiqlaLjHH+8qweAtItS4P2iPv1TELo5a0=" . parse( ) . unwrap( ) ) ,
120
- password_revision_date: None , uris: None , totp: None , autofill_on_page_load: None , fido2_credentials: None } ) ,
121
- identity: None ,
122
- card: None ,
123
- secure_note: None ,
124
- ssh_key: None ,
125
- favorite: false ,
126
- reprompt: CipherRepromptType :: None ,
127
- organization_use_totp: true ,
128
- edit: true ,
129
- permissions: None ,
130
- view_password: true ,
131
- local_data: None ,
132
- attachments: None ,
133
- fields: None ,
134
- password_history: None ,
135
- creation_date: "2024-05-31T09:35:55.12Z" . parse( ) . unwrap( ) ,
136
- deleted_date: None ,
137
- revision_date: "2024-05-31T09:35:55.12Z" . parse( ) . unwrap( ) ,
138
- } ] )
139
-
140
- . unwrap ( ) ;
141
-
142
- assert_eq ! ( dec[ 0 ] . name, "Test item" ) ;
143
- }
144
-
145
116
fn test_cipher ( ) -> Cipher {
146
117
Cipher {
147
118
id : Some ( "358f2b2b-9326-4e5e-94a8-b18100bb0908" . parse ( ) . unwrap ( ) ) ,
@@ -203,6 +174,84 @@ mod tests {
203
174
}
204
175
}
205
176
177
+ #[ tokio:: test]
178
+ async fn test_decrypt_list ( ) {
179
+ let client = Client :: init_test_account ( test_bitwarden_com_account ( ) ) . await ;
180
+
181
+ let dec = client
182
+ . vault ( )
183
+ . ciphers ( )
184
+ . decrypt_list ( vec ! [ Cipher {
185
+ id: Some ( "a1569f46-0797-4d3f-b859-b181009e2e49" . parse( ) . unwrap( ) ) ,
186
+ organization_id: Some ( "1bc9ac1e-f5aa-45f2-94bf-b181009709b8" . parse( ) . unwrap( ) ) ,
187
+ folder_id: None ,
188
+ collection_ids: vec![ "66c5ca57-0868-4c7e-902f-b181009709c0" . parse( ) . unwrap( ) ] ,
189
+ key: None ,
190
+ name: "2.RTdUGVWYl/OZHUMoy68CMg==|sCaT5qHx8i0rIvzVrtJKww==|jB8DsRws6bXBtXNfNXUmFJ0JLDlB6GON6Y87q0jgJ+0=" . parse( ) . unwrap( ) ,
191
+ notes: None ,
192
+ r#type: CipherType :: Login ,
193
+ login: Some ( Login {
194
+ username: Some ( "2.ouEYEk+SViUtqncesfe9Ag==|iXzEJq1zBeNdDbumFO1dUA==|RqMoo9soSwz/yB99g6YPqk8+ASWRcSdXsKjbwWzyy9U=" . parse( ) . unwrap( ) ) ,
195
+ password: Some ( "2.6yXnOz31o20Z2kiYDnXueA==|rBxTb6NK9lkbfdhrArmacw==|ogZir8Z8nLgiqlaLjHH+8qweAtItS4P2iPv1TELo5a0=" . parse( ) . unwrap( ) ) ,
196
+ password_revision_date: None , uris: None , totp: None , autofill_on_page_load: None , fido2_credentials: None } ) ,
197
+ identity: None ,
198
+ card: None ,
199
+ secure_note: None ,
200
+ ssh_key: None ,
201
+ favorite: false ,
202
+ reprompt: CipherRepromptType :: None ,
203
+ organization_use_totp: true ,
204
+ edit: true ,
205
+ permissions: None ,
206
+ view_password: true ,
207
+ local_data: None ,
208
+ attachments: None ,
209
+ fields: None ,
210
+ password_history: None ,
211
+ creation_date: "2024-05-31T09:35:55.12Z" . parse( ) . unwrap( ) ,
212
+ deleted_date: None ,
213
+ revision_date: "2024-05-31T09:35:55.12Z" . parse( ) . unwrap( ) ,
214
+ } ] )
215
+
216
+ . unwrap ( ) ;
217
+
218
+ assert_eq ! ( dec[ 0 ] . name, "Test item" ) ;
219
+ }
220
+
221
+ #[ tokio:: test]
222
+ async fn test_decrypt_list_with_failures_all_success ( ) {
223
+ let client = Client :: init_test_account ( test_bitwarden_com_account ( ) ) . await ;
224
+
225
+ let valid_cipher = test_cipher ( ) ;
226
+
227
+ let result = client
228
+ . vault ( )
229
+ . ciphers ( )
230
+ . decrypt_list_with_failures ( vec ! [ valid_cipher] ) ;
231
+
232
+ assert_eq ! ( result. successes. len( ) , 1 ) ;
233
+ assert ! ( result. failures. is_empty( ) ) ;
234
+ assert_eq ! ( result. successes[ 0 ] . name, "234234" ) ;
235
+ }
236
+
237
+ #[ tokio:: test]
238
+ async fn test_decrypt_list_with_failures_mixed_results ( ) {
239
+ let client = Client :: init_test_account ( test_bitwarden_com_account ( ) ) . await ;
240
+ let valid_cipher = test_cipher ( ) ;
241
+ let mut invalid_cipher = test_cipher ( ) ;
242
+ // Set an invalid encryptedkey to cause decryption failure
243
+ invalid_cipher. key = Some ( "2.Gg8yCM4IIgykCZyq0O4+cA==|GJLBtfvSJTDJh/F7X4cJPkzI6ccnzJm5DYl3yxOW2iUn7DgkkmzoOe61sUhC5dgVdV0kFqsZPcQ0yehlN1DDsFIFtrb4x7LwzJNIkMgxNyg=|1rGkGJ8zcM5o5D0aIIwAyLsjMLrPsP3EWm3CctBO3Fw=" . parse ( ) . unwrap ( ) ) ;
244
+
245
+ let ciphers = vec ! [ valid_cipher, invalid_cipher. clone( ) ] ;
246
+
247
+ let result = client. vault ( ) . ciphers ( ) . decrypt_list_with_failures ( ciphers) ;
248
+
249
+ assert_eq ! ( result. successes. len( ) , 1 ) ;
250
+ assert_eq ! ( result. failures. len( ) , 1 ) ;
251
+
252
+ assert_eq ! ( result. successes[ 0 ] . name, "234234" ) ;
253
+ }
254
+
206
255
#[ tokio:: test]
207
256
async fn test_move_user_cipher_with_attachment_without_key_to_org_fails ( ) {
208
257
let client = Client :: init_test_account ( test_bitwarden_com_account ( ) ) . await ;
0 commit comments