1#[doc(no_inline)]
11use crate::prelude::*;
12
13use crate::{
14 InitAndRotationCheck::{NoRotationNeeded, RotationNeeded},
15 Result,
16};
17use std::{collections::HashMap, sync::Arc};
18
19#[cfg(feature = "beta")]
20use crate::search::{BlindIndexSearchInitialize, EncryptedBlindIndexSalt};
21use tokio::runtime::Runtime;
22
23#[derive(Clone, Debug)]
28pub struct BlockingDeviceContext {
29 pub device: DeviceContext,
30 pub(crate) rt: Arc<Runtime>,
31}
32
33impl From<DeviceAddResult> for BlockingDeviceContext {
34 fn from(value: DeviceAddResult) -> Self {
35 Self {
36 device: value.into(),
37 rt: Arc::new(create_runtime()),
38 }
39 }
40}
41
42impl BlockingDeviceContext {
43 pub fn new(device: DeviceContext) -> Self {
44 Self {
45 device,
46 rt: Arc::new(create_runtime()),
47 }
48 }
49 pub fn account_id(&self) -> &UserId {
51 &self.device.auth().account_id()
52 }
53 pub fn segment_id(&self) -> usize {
55 self.device.auth().segment_id()
56 }
57 pub fn signing_private_key(&self) -> &DeviceSigningKeyPair {
59 &self.device.auth().signing_private_key()
60 }
61 pub fn device_private_key(&self) -> &PrivateKey {
63 &self.device.device_private_key()
64 }
65}
66
67#[derive(Debug)]
71pub struct BlockingIronOxide {
72 pub(crate) ironoxide: IronOxide,
73 pub(crate) runtime: Arc<tokio::runtime::Runtime>,
74}
75
76impl BlockingIronOxide {
77 pub fn device(&self) -> &DeviceContext {
79 &self.ironoxide.device
80 }
81
82 pub fn clear_policy_cache(&self) -> usize {
84 self.ironoxide.clear_policy_cache()
85 }
86
87 #[cfg(feature = "beta")]
89 pub fn create_blind_index(&self, group_id: &GroupId) -> Result<EncryptedBlindIndexSalt> {
90 self.runtime
91 .block_on(self.ironoxide.create_blind_index(group_id))
92 }
93
94 pub fn rotate_all(
96 &self,
97 rotations: &PrivateKeyRotationCheckResult,
98 password: &str,
99 timeout: Option<std::time::Duration>,
100 ) -> Result<(
101 Option<UserUpdatePrivateKeyResult>,
102 Option<Vec<GroupUpdatePrivateKeyResult>>,
103 )> {
104 self.runtime
105 .block_on(self.ironoxide.rotate_all(rotations, password, timeout))
106 }
107
108 pub fn document_list(&self) -> Result<DocumentListResult> {
110 self.runtime.block_on(self.ironoxide.document_list())
111 }
112 pub fn document_get_metadata(&self, id: &DocumentId) -> Result<DocumentMetadataResult> {
114 self.runtime
115 .block_on(self.ironoxide.document_get_metadata(id))
116 }
117 pub fn document_get_id_from_bytes(&self, encrypted_document: &[u8]) -> Result<DocumentId> {
119 self.ironoxide
120 .document_get_id_from_bytes(encrypted_document)
121 }
122 pub fn document_encrypt(
124 &self,
125 document_data: Vec<u8>,
126 encrypt_opts: &DocumentEncryptOpts,
127 ) -> Result<DocumentEncryptResult> {
128 self.runtime
129 .block_on(self.ironoxide.document_encrypt(document_data, encrypt_opts))
130 }
131 pub fn document_update_bytes(
133 &self,
134 id: &DocumentId,
135 new_document_data: Vec<u8>,
136 ) -> Result<DocumentEncryptResult> {
137 self.runtime
138 .block_on(self.ironoxide.document_update_bytes(id, new_document_data))
139 }
140 pub fn document_decrypt(&self, encrypted_document: &[u8]) -> Result<DocumentDecryptResult> {
142 self.runtime
143 .block_on(self.ironoxide.document_decrypt(encrypted_document))
144 }
145 pub fn document_update_name(
147 &self,
148 id: &DocumentId,
149 name: Option<&DocumentName>,
150 ) -> Result<DocumentMetadataResult> {
151 self.runtime
152 .block_on(self.ironoxide.document_update_name(id, name))
153 }
154 pub fn document_grant_access(
156 &self,
157 id: &DocumentId,
158 grant_list: &Vec<UserOrGroup>,
159 ) -> Result<DocumentAccessResult> {
160 self.runtime
161 .block_on(self.ironoxide.document_grant_access(id, grant_list))
162 }
163 pub fn document_revoke_access(
165 &self,
166 id: &DocumentId,
167 revoke_list: &Vec<UserOrGroup>,
168 ) -> Result<DocumentAccessResult> {
169 self.runtime
170 .block_on(self.ironoxide.document_revoke_access(id, revoke_list))
171 }
172 pub fn document_encrypt_unmanaged(
174 &self,
175 data: Vec<u8>,
176 encrypt_opts: &DocumentEncryptOpts,
177 ) -> Result<DocumentEncryptUnmanagedResult> {
178 self.runtime.block_on(
179 self.ironoxide
180 .document_encrypt_unmanaged(data, encrypt_opts),
181 )
182 }
183 pub fn document_decrypt_unmanaged(
185 &self,
186 encrypted_data: &[u8],
187 encrypted_deks: &[u8],
188 ) -> Result<DocumentDecryptUnmanagedResult> {
189 self.runtime.block_on(
190 self.ironoxide
191 .document_decrypt_unmanaged(encrypted_data, encrypted_deks),
192 )
193 }
194 pub fn document_get_metadata_unmanaged(
196 &self,
197 encrypted_deks: &[u8],
198 ) -> Result<DocumentMetadataUnmanagedResult> {
199 self.ironoxide
200 .document_get_metadata_unmanaged(encrypted_deks)
201 }
202 pub fn document_get_id_from_bytes_unmanaged(
204 &self,
205 encrypted_document: &[u8],
206 ) -> Result<DocumentId> {
207 self.ironoxide
208 .document_get_id_from_bytes_unmanaged(encrypted_document)
209 }
210 pub fn document_get_id_from_edeks_unmanaged(&self, edeks: &[u8]) -> Result<DocumentId> {
212 self.ironoxide.document_get_id_from_edeks_unmanaged(edeks)
213 }
214 pub fn document_grant_access_unmanaged(
216 &self,
217 edeks: &[u8],
218 grant_list: &[UserOrGroup],
219 ) -> Result<DocumentAccessUnmanagedResult> {
220 self.runtime.block_on(
221 self.ironoxide
222 .document_grant_access_unmanaged(edeks, grant_list),
223 )
224 }
225 pub fn document_revoke_access_unmanaged(
227 &self,
228 edeks: &[u8],
229 revoke_list: &[UserOrGroup],
230 ) -> Result<DocumentAccessUnmanagedResult> {
231 self.ironoxide
232 .document_revoke_access_unmanaged(edeks, revoke_list)
233 }
234
235 pub fn document_file_encrypt(
237 &self,
238 source_path: &str,
239 destination_path: &str,
240 opts: &DocumentEncryptOpts,
241 ) -> Result<DocumentFileEncryptResult> {
242 self.runtime.block_on(self.ironoxide.document_file_encrypt(
243 source_path,
244 destination_path,
245 opts,
246 ))
247 }
248
249 pub fn document_file_decrypt(
251 &self,
252 source_path: &str,
253 destination_path: &str,
254 ) -> Result<DocumentFileDecryptResult> {
255 self.runtime.block_on(
256 self.ironoxide
257 .document_file_decrypt(source_path, destination_path),
258 )
259 }
260
261 pub fn document_file_encrypt_unmanaged(
263 &self,
264 source_path: &str,
265 destination_path: &str,
266 opts: &DocumentEncryptOpts,
267 ) -> Result<DocumentFileEncryptUnmanagedResult> {
268 self.runtime
269 .block_on(self.ironoxide.document_file_encrypt_unmanaged(
270 source_path,
271 destination_path,
272 opts,
273 ))
274 }
275
276 pub fn document_file_decrypt_unmanaged(
278 &self,
279 source_path: &str,
280 destination_path: &str,
281 encrypted_deks: &[u8],
282 ) -> Result<DocumentFileDecryptUnmanagedResult> {
283 self.runtime
284 .block_on(self.ironoxide.document_file_decrypt_unmanaged(
285 source_path,
286 destination_path,
287 encrypted_deks,
288 ))
289 }
290
291 pub fn export_public_key_cache(&self) -> Result<Vec<u8>> {
293 self.ironoxide.export_public_key_cache()
294 }
295 pub fn group_list(&self) -> Result<GroupListResult> {
297 self.runtime.block_on(self.ironoxide.group_list())
298 }
299 pub fn group_create(&self, opts: &GroupCreateOpts) -> Result<GroupCreateResult> {
301 self.runtime.block_on(self.ironoxide.group_create(opts))
302 }
303 pub fn group_get_metadata(&self, id: &GroupId) -> Result<GroupGetResult> {
305 self.runtime.block_on(self.ironoxide.group_get_metadata(id))
306 }
307 pub fn group_delete(&self, id: &GroupId) -> Result<GroupId> {
309 self.runtime.block_on(self.ironoxide.group_delete(id))
310 }
311 pub fn group_update_name(
313 &self,
314 id: &GroupId,
315 name: Option<&GroupName>,
316 ) -> Result<GroupMetaResult> {
317 self.runtime
318 .block_on(self.ironoxide.group_update_name(id, name))
319 }
320 pub fn group_add_members(
322 &self,
323 id: &GroupId,
324 grant_list: &[UserId],
325 ) -> Result<GroupAccessEditResult> {
326 self.runtime
327 .block_on(self.ironoxide.group_add_members(id, grant_list))
328 }
329 pub fn group_remove_members(
331 &self,
332 id: &GroupId,
333 revoke_list: &[UserId],
334 ) -> Result<GroupAccessEditResult> {
335 self.runtime
336 .block_on(self.ironoxide.group_remove_members(id, revoke_list))
337 }
338 pub fn group_add_admins(
340 &self,
341 id: &GroupId,
342 users: &[UserId],
343 ) -> Result<GroupAccessEditResult> {
344 self.runtime
345 .block_on(self.ironoxide.group_add_admins(id, users))
346 }
347 pub fn group_remove_admins(
349 &self,
350 id: &GroupId,
351 revoke_list: &[UserId],
352 ) -> Result<GroupAccessEditResult> {
353 self.runtime
354 .block_on(self.ironoxide.group_remove_admins(id, revoke_list))
355 }
356 pub fn group_rotate_private_key(&self, id: &GroupId) -> Result<GroupUpdatePrivateKeyResult> {
358 self.runtime
359 .block_on(self.ironoxide.group_rotate_private_key(id))
360 }
361 pub fn user_create(
363 jwt: &Jwt,
364 password: &str,
365 user_create_opts: &UserCreateOpts,
366 timeout: Option<std::time::Duration>,
367 ) -> Result<UserCreateResult> {
368 let rt = create_runtime();
369 rt.block_on(IronOxide::user_create(
370 jwt,
371 password,
372 user_create_opts,
373 timeout,
374 ))
375 }
376 pub fn user_list_devices(&self) -> Result<UserDeviceListResult> {
378 self.runtime.block_on(self.ironoxide.user_list_devices())
379 }
380 pub fn generate_new_device(
382 jwt: &Jwt,
383 password: &str,
384 device_create_options: &DeviceCreateOpts,
385 timeout: Option<std::time::Duration>,
386 ) -> Result<DeviceAddResult> {
387 let rt = create_runtime();
388 rt.block_on(IronOxide::generate_new_device(
389 jwt,
390 password,
391 device_create_options,
392 timeout,
393 ))
394 }
395 pub fn user_delete_device(&self, device_id: Option<&DeviceId>) -> Result<DeviceId> {
397 self.runtime
398 .block_on(self.ironoxide.user_delete_device(device_id))
399 }
400 pub fn user_verify(
402 jwt: &Jwt,
403 timeout: Option<std::time::Duration>,
404 ) -> Result<Option<UserResult>> {
405 let rt = create_runtime();
406 rt.block_on(IronOxide::user_verify(jwt, timeout))
407 }
408 pub fn user_get_public_key(&self, users: &[UserId]) -> Result<HashMap<UserId, PublicKey>> {
410 self.runtime
411 .block_on(self.ironoxide.user_get_public_key(users))
412 }
413 pub fn user_rotate_private_key(&self, password: &str) -> Result<UserUpdatePrivateKeyResult> {
415 self.runtime
416 .block_on(self.ironoxide.user_rotate_private_key(password))
417 }
418 pub fn user_change_password(
420 &self,
421 current_password: &str,
422 new_password: &str,
423 ) -> Result<UserUpdateResult> {
424 self.runtime.block_on(
425 self.ironoxide
426 .user_change_password(current_password, new_password),
427 )
428 }
429}
430
431fn create_runtime() -> tokio::runtime::Runtime {
433 tokio::runtime::Builder::new_current_thread()
434 .enable_all() .build()
436 .expect("tokio runtime failed to initialize")
437}
438
439pub fn initialize(
442 device_context: &BlockingDeviceContext,
443 config: &IronOxideConfig,
444) -> Result<BlockingIronOxide> {
445 let maybe_io = device_context
446 .rt
447 .block_on(crate::initialize(&device_context.device, config));
448 maybe_io.map(|io| BlockingIronOxide {
449 ironoxide: io,
450 runtime: device_context.rt.clone(),
451 })
452}
453
454pub fn initialize_with_public_keys(
459 device_context: &BlockingDeviceContext,
460 config: &IronOxideConfig,
461 public_key_cache: Vec<u8>,
462) -> Result<BlockingIronOxide> {
463 let maybe_io = device_context
464 .rt
465 .block_on(crate::initialize_with_public_keys(
466 &device_context.device,
467 config,
468 public_key_cache,
469 ));
470 maybe_io.map(|io| BlockingIronOxide {
471 ironoxide: io,
472 runtime: device_context.rt.clone(),
473 })
474}
475
476pub fn initialize_with_public_keys_and_check_rotation(
483 device_context: &BlockingDeviceContext,
484 config: &IronOxideConfig,
485 public_key_cache: Vec<u8>,
486) -> Result<InitAndRotationCheck<BlockingIronOxide>> {
487 let maybe_init =
488 device_context
489 .rt
490 .block_on(crate::initialize_with_public_keys_and_check_rotation(
491 &device_context.device,
492 config,
493 public_key_cache,
494 ));
495 maybe_init.map(|init| match init {
496 NoRotationNeeded(io) => NoRotationNeeded(BlockingIronOxide {
497 ironoxide: io,
498 runtime: device_context.rt.clone(),
499 }),
500 RotationNeeded(io, rot) => RotationNeeded(
501 BlockingIronOxide {
502 ironoxide: io,
503 runtime: device_context.rt.clone(),
504 },
505 rot,
506 ),
507 })
508}
509
510pub fn initialize_check_rotation(
514 device_context: &BlockingDeviceContext,
515 config: &IronOxideConfig,
516) -> Result<InitAndRotationCheck<BlockingIronOxide>> {
517 let maybe_init = device_context.rt.block_on(crate::initialize_check_rotation(
518 &device_context.device,
519 config,
520 ));
521 maybe_init.map(|init| match init {
522 NoRotationNeeded(io) => NoRotationNeeded(BlockingIronOxide {
523 ironoxide: io,
524 runtime: device_context.rt.clone(),
525 }),
526 RotationNeeded(io, rot) => RotationNeeded(
527 BlockingIronOxide {
528 ironoxide: io,
529 runtime: device_context.rt.clone(),
530 },
531 rot,
532 ),
533 })
534}