1use crate::{Error, RemoteBridge, Result};
3use async_trait::async_trait;
4use secrecy::SecretString;
5use sha2::{Digest, Sha256};
6use sos_account::{
7 Account, AccountBuilder, AccountChange, AccountData, CipherComparison,
8 FolderChange, FolderCreate, FolderDelete, LocalAccount, SecretChange,
9 SecretDelete, SecretInsert, SecretMove,
10};
11use sos_backend::{BackendTarget, Folder, ServerOrigins};
12use sos_client_storage::{AccessOptions, NewFolderOptions};
13use sos_core::{
14 commit::{CommitHash, CommitState},
15 crypto::{AccessKey, Cipher, KeyDerivation},
16 device::{DevicePublicKey, TrustedDevice},
17 events::{
18 AccountEvent, DeviceEvent, EventLog, EventLogType, EventRecord,
19 ReadEvent, WriteEvent,
20 },
21 AccountId, AccountRef, AuthenticationError, FolderRef, Origin, Paths,
22 PublicIdentity, RemoteOrigins, SecretId, StorageError, UtcDateTime,
23 VaultCommit, VaultFlags, VaultId,
24};
25use sos_login::{
26 device::{DeviceManager, DeviceSigner},
27 DelegatedAccess,
28};
29use sos_protocol::{
30 is_offline, AccountSync, DiffRequest, RemoteResult, RemoteSync,
31 SyncClient, SyncOptions, SyncResult,
32};
33use sos_remote_sync::RemoteSyncHandler;
34use sos_sync::{CreateSet, StorageEventLogs, UpdateSet};
35use sos_vault::{
36 secret::{Secret, SecretMeta, SecretRow, SecretType},
37 Summary, Vault,
38};
39use std::{
40 collections::{HashMap, HashSet},
41 path::Path,
42 sync::Arc,
43};
44use tokio::sync::{Mutex, RwLock};
45
46#[cfg(feature = "clipboard")]
47use {
48 sos_account::{xclipboard::Clipboard, ClipboardCopyRequest},
49 sos_core::SecretPath,
50};
51
52#[cfg(feature = "search")]
53use sos_search::{
54 AccountStatistics, ArchiveFilter, Document, DocumentCount, DocumentView,
55 QueryFilter, SearchIndex,
56};
57
58use indexmap::IndexSet;
59
60#[cfg(feature = "contacts")]
61use sos_account::ContactImportProgress;
62
63#[cfg(feature = "migrate")]
64use sos_migrate::import::ImportTarget;
65
66#[cfg(feature = "listen")]
67use sos_protocol::network_client::WebSocketHandle;
68
69#[cfg(feature = "audit")]
70use {
71 sos_audit::{AuditData, AuditEvent},
72 sos_backend::audit::append_audit_events,
73 sos_core::events::EventKind,
74};
75
76use super::remote::Remotes;
84
85#[cfg(feature = "files")]
86use {
87 crate::account::file_transfers::{
88 FileTransferSettings, FileTransfers, FileTransfersHandle,
89 InflightTransfers,
90 },
91 sos_external_files::FileMutationEvent,
92 sos_protocol::{network_client::HttpClient, transfer::FileOperation},
93};
94
95#[derive(Debug, Default)]
97pub struct NetworkAccountOptions {
98 pub offline: bool,
100 #[cfg(feature = "files")]
102 pub file_transfer_settings: FileTransferSettings,
103}
104
105pub struct NetworkAccount {
107 account_id: AccountId,
109
110 paths: Arc<Paths>,
112
113 pub(super) account: Arc<Mutex<LocalAccount>>,
115
116 pub(super) remotes: Arc<RwLock<Remotes>>,
118
119 server_origins: Option<ServerOrigins>,
121
122 pub(super) sync_lock: Arc<Mutex<()>>,
125
126 #[cfg(feature = "listen")]
128 pub(super) listeners: Mutex<HashMap<Origin, WebSocketHandle>>,
129
130 connection_id: Option<String>,
136
137 #[cfg(feature = "files")]
139 file_transfers: Option<FileTransfers<HttpClient>>,
140
141 #[cfg(feature = "files")]
143 file_transfer_handle: Option<FileTransfersHandle>,
144
145 pub(crate) offline: bool,
147
148 #[allow(dead_code)]
150 options: NetworkAccountOptions,
151}
152
153impl NetworkAccount {
154 async fn login(&mut self, key: &AccessKey) -> Result<Vec<Summary>> {
155 let folders = {
156 let mut account = self.account.lock().await;
157 let folders = account.sign_in(key).await?;
158 self.paths = account.paths();
159 self.account_id = *account.account_id();
160 folders
161 };
162
163 if self.connection_id.is_none() {
166 self.connection_id = self.client_connection_id().await.ok();
167 }
168
169 let server_origins =
170 ServerOrigins::new(self.backend_target().await, &self.account_id);
171 let servers = server_origins.list_servers().await?;
172
173 if !servers.is_empty() {
175 let mut remotes: Remotes = Default::default();
176 for origin in servers {
177 let remote = self.remote_bridge(&origin).await?;
178 remotes.insert(origin, remote);
179 }
180 self.remotes = Arc::new(RwLock::new(remotes));
181 }
182
183 self.server_origins = Some(server_origins);
184 self.activate().await?;
185
186 Ok(folders)
187 }
188
189 pub async fn deactivate(&mut self) {
200 #[cfg(feature = "listen")]
201 {
202 tracing::debug!("net_sign_out::shutdown_websockets");
203 self.shutdown_websockets().await;
204 }
205
206 #[cfg(feature = "files")]
207 {
208 tracing::debug!("net_sign_out::stop_file_transfers");
209 self.stop_file_transfers().await;
210 }
211 }
212
213 pub async fn activate(&mut self) -> Result<()> {
216 #[cfg(feature = "files")]
217 {
218 let clients = {
219 let mut clients = Vec::new();
220 let remotes = self.remotes.read().await;
221 for (_, remote) in &*remotes {
222 clients.push(remote.client().clone());
223 }
224 clients
225 };
226
227 let file_transfers = FileTransfers::new(
228 clients,
229 self.options.file_transfer_settings.clone(),
230 );
231 self.file_transfers = Some(file_transfers);
232 self.start_file_transfers().await?;
233 }
234
235 Ok(())
236 }
237
238 pub fn set_connection_id(&mut self, value: Option<String>) {
240 self.connection_id = value;
241 }
242
243 pub fn connection_id(&self) -> Option<&str> {
245 self.connection_id.as_ref().map(|x| x.as_str())
246 }
247
248 async fn client_connection_id(&self) -> Result<String> {
256 Ok(if let Some(conn_id) = &self.connection_id {
257 conn_id.to_owned()
258 } else {
259 let mut hasher = Sha256::new();
260 let docs_dir = self.paths.documents_dir();
261 let docs_path = docs_dir.to_string_lossy().into_owned();
262
263 if !self.is_authenticated().await {
264 hasher.update(docs_path.as_bytes());
265 } else {
266 {
267 let device_signer = self.device_signer().await?;
268 let device_public_key = device_signer.public_key();
269
270 hasher.update(docs_path.as_bytes());
271 hasher.update(device_public_key.as_ref());
272 }
273 }
274
275 let result = hasher.finalize();
276 hex::encode(&result)
277 })
278 }
279
280 pub async fn add_server(
288 &mut self,
289 origin: Origin,
290 ) -> Result<Option<RemoteResult<Error>>> {
291 let remote = self.remote_bridge(&origin).await?;
292
293 #[cfg(feature = "files")]
294 {
295 if let Some(file_transfers) = self.file_transfers.as_mut() {
296 file_transfers.add_client(remote.client().clone()).await;
297 };
298
299 if let Some(handle) = &self.file_transfer_handle {
300 self.proxy_remote_file_queue(handle, &remote).await;
301 }
302 }
303
304 {
305 let mut remotes = self.remotes.write().await;
306 remotes.insert(origin.clone(), remote);
307 self.server_origins
308 .as_mut()
309 .unwrap()
310 .add_server(origin.clone())
311 .await?;
312 tracing::debug!(url = %origin.url(), "server::added");
313 }
314
315 let mut sync_result = None;
316 if !is_offline() {
317 let remotes = self.remotes.read().await;
318 if let Some(remote) = remotes.get(&origin) {
319 let options = SyncOptions {
320 origins: vec![origin.clone()],
321 ..Default::default()
322 };
323
324 let res = remote.sync_with_options(&options).await;
325 if let Some(sync_error) = res.result.as_ref().err() {
326 tracing::warn!(
327 sync_error = ?sync_error,
328 "server::initial_sync_failed");
329 }
330 sync_result = Some(res);
331 }
332 } else {
333 tracing::warn!(
334 "offline mode active, ignoring initial server sync"
335 );
336 }
337
338 Ok(sync_result)
339 }
340
341 pub async fn replace_server(
343 &mut self,
344 old_origin: &Origin,
345 new_origin: Origin,
346 ) -> Result<bool> {
347 let mut remotes = self.remotes.write().await;
350 if let Some(remote) = remotes.remove(&old_origin) {
351 remotes.insert(new_origin.clone(), remote);
352 self.server_origins
353 .as_mut()
354 .unwrap()
355 .replace_server(old_origin, new_origin)
356 .await?;
357 Ok(true)
358 } else {
359 Ok(false)
360 }
361 }
362
363 pub async fn remove_server(
365 &mut self,
366 origin: &Origin,
367 ) -> Result<Option<RemoteBridge>> {
368 let remote = {
369 let mut remotes = self.remotes.write().await;
370 let remote = remotes.remove(origin);
371 #[allow(unused_variables)]
372 if let Some(remote) = &remote {
373 #[cfg(feature = "files")]
374 if let Some(file_transfers) = self.file_transfers.as_mut() {
375 file_transfers.remove_client(remote.client()).await;
376 }
377 self.server_origins
378 .as_mut()
379 .unwrap()
380 .remove_server(origin)
381 .await?;
382 }
383 remote
384 };
385
386 tracing::debug!(url = %origin.url(), "server::removed");
387 Ok(remote)
388 }
389
390 async fn remote_bridge(&self, origin: &Origin) -> Result<RemoteBridge> {
392 let device = self.device_signer().await?;
393 let conn_id = if let Some(conn_id) = &self.connection_id {
394 conn_id.to_string()
395 } else {
396 self.client_connection_id().await?
397 };
398 let provider = RemoteBridge::new(
399 *self.account_id(),
400 Arc::clone(&self.account),
401 origin.clone(),
402 device.into(),
403 conn_id,
404 )?;
405 Ok(provider)
406 }
407
408 pub async fn servers(&self) -> HashSet<Origin> {
412 let remotes = self.remotes.read().await;
413 remotes.keys().cloned().collect()
414 }
415
416 pub async fn recover_remote_folder(
419 &mut self,
420 origin: &Origin,
421 folder_id: &VaultId,
422 ) -> Result<Summary> {
423 let folders = self.list_folders().await?;
424 if folders.iter().find(|f| f.id() == folder_id).is_some() {
425 return Err(Error::FolderExists(*folder_id));
426 }
427
428 self.recover_remote_folder_unchecked(origin, folder_id)
429 .await
430 }
431
432 async fn recover_remote_folder_unchecked(
436 &mut self,
437 origin: &Origin,
438 folder_id: &VaultId,
439 ) -> Result<Summary> {
440 let _ = self.sync_lock.lock().await;
441 let remote = self.remote_bridge(origin).await?;
442 let request = DiffRequest {
443 log_type: EventLogType::Folder(*folder_id),
444 from_hash: None,
445 };
446 let response = remote.client().diff(request).await?;
447 self.restore_folder(folder_id, response.patch).await
448 }
449
450 #[cfg(feature = "files")]
452 async fn start_file_transfers(&mut self) -> Result<()> {
453 if !self.is_authenticated().await {
454 return Err(AuthenticationError::NotAuthenticated.into());
455 }
456
457 if self.offline {
458 tracing::warn!("offline mode active, ignoring file transfers");
459 return Ok(());
460 }
461
462 self.stop_file_transfers().await;
464
465 let paths = self.paths();
466 if let Some(file_transfers) = &mut self.file_transfers {
467 tracing::debug!("file_transfers::start");
468
469 let handle = file_transfers.run(paths);
470
471 {
472 let remotes = self.remotes.read().await;
475 for (_, remote) in &*remotes {
476 self.proxy_remote_file_queue(&handle, remote).await;
477 }
478 }
479
480 self.file_transfer_handle = Some(handle);
481 }
482
483 Ok(())
484 }
485
486 #[cfg(feature = "files")]
487 async fn proxy_remote_file_queue(
488 &self,
489 handle: &FileTransfersHandle,
490 remote: &RemoteBridge,
491 ) {
492 let mut rx = remote.file_transfer_queue.subscribe();
493 let tx = handle.queue_tx.clone();
494 tokio::task::spawn(async move {
495 while let Ok(event) = rx.recv().await {
496 let res = tx.send(event).await;
497 if let Err(error) = res {
498 tracing::error!(error = ?error);
499 }
500 }
501 Ok::<_, Error>(())
502 });
503 }
504
505 #[cfg(feature = "files")]
507 async fn stop_file_transfers(&mut self) {
508 if let Some(handle) = self.file_transfer_handle.take() {
509 handle.shutdown().await;
510 }
511 }
512}
513
514impl From<&NetworkAccount> for AccountRef {
515 fn from(value: &NetworkAccount) -> Self {
516 Self::Id(*value.account_id())
517 }
518}
519
520impl NetworkAccount {
521 pub async fn new_unauthenticated(
526 account_id: AccountId,
527 target: BackendTarget,
528 options: NetworkAccountOptions,
529 ) -> Result<Self> {
530 let account =
531 LocalAccount::new_unauthenticated(account_id, target).await?;
532
533 Ok(Self {
534 account_id,
535 paths: account.paths(),
536 account: Arc::new(Mutex::new(account)),
537 remotes: Arc::new(RwLock::new(Default::default())),
538 server_origins: None,
539 sync_lock: Arc::new(Mutex::new(())),
540 #[cfg(feature = "listen")]
541 listeners: Mutex::new(Default::default()),
542 connection_id: None,
543 #[cfg(feature = "files")]
544 file_transfers: None,
545 #[cfg(feature = "files")]
546 file_transfer_handle: None,
547 offline: options.offline,
548 options,
549 })
550 }
551
552 pub async fn new_account(
559 account_name: String,
560 passphrase: SecretString,
561 target: BackendTarget,
562 options: NetworkAccountOptions,
563 ) -> Result<Self> {
564 Self::new_account_with_builder(
565 account_name,
566 passphrase,
567 target,
568 options,
569 |builder| {
570 builder
571 .save_passphrase(false)
572 .create_archive(false)
573 .create_authenticator(false)
574 .create_contacts(false)
575 .create_file_password(true)
576 },
577 )
578 .await
579 }
580
581 pub async fn new_account_with_builder(
585 account_name: String,
586 passphrase: SecretString,
587 target: BackendTarget,
588 options: NetworkAccountOptions,
589 builder: impl Fn(AccountBuilder) -> AccountBuilder + Send,
590 ) -> Result<Self> {
591 let account = LocalAccount::new_account_with_builder(
592 account_name,
593 passphrase.clone(),
594 target,
595 builder,
596 )
597 .await?;
598
599 let owner = Self {
600 account_id: *account.account_id(),
601 paths: account.paths(),
602 account: Arc::new(Mutex::new(account)),
603 remotes: Arc::new(RwLock::new(Default::default())),
604 server_origins: None,
605 sync_lock: Arc::new(Mutex::new(())),
606 #[cfg(feature = "listen")]
607 listeners: Mutex::new(Default::default()),
608 connection_id: None,
609 #[cfg(feature = "files")]
610 file_transfers: None,
611 #[cfg(feature = "files")]
612 file_transfer_handle: None,
613 offline: options.offline,
614 options,
615 };
616
617 Ok(owner)
618 }
619
620 #[cfg(feature = "files")]
622 pub fn inflight_transfers(&self) -> Result<Arc<InflightTransfers>> {
623 Ok(self
624 .file_transfers
625 .as_ref()
626 .map(|t| Arc::clone(&t.inflight))
627 .ok_or_else(|| AuthenticationError::NotAuthenticated)?)
628 }
629
630 #[cfg(feature = "files")]
632 async fn queue_file_mutation_events(
633 &self,
634 events: &[FileMutationEvent],
635 ) -> Result<()> {
636 if let Some(handle) = &self.file_transfer_handle {
637 let mut items = Vec::with_capacity(events.len());
638 for event in events {
639 let item: FileOperation = event.into();
640 items.push(item);
641 }
642
643 handle.send(items).await;
644 }
645
646 Ok(())
647 }
648}
649
650#[async_trait]
651impl Account for NetworkAccount {
652 type Error = Error;
653 type NetworkResult = SyncResult<Self::Error>;
654
655 fn account_id(&self) -> &AccountId {
656 &self.account_id
657 }
658
659 fn paths(&self) -> Arc<Paths> {
660 Arc::clone(&self.paths)
661 }
662
663 async fn backend_target(&self) -> BackendTarget {
664 let account = self.account.lock().await;
665 account.backend_target().await
666 }
667
668 async fn folder(&self, folder_id: &VaultId) -> Result<Folder> {
669 let account = self.account.lock().await;
670 Ok(account.folder(folder_id).await?)
671 }
672
673 async fn is_authenticated(&self) -> bool {
674 let account = self.account.lock().await;
675 account.is_authenticated().await
676 }
677
678 async fn import_account_events(
679 &mut self,
680 events: CreateSet,
681 ) -> Result<()> {
682 let mut inner = self.account.lock().await;
683 Ok(inner.import_account_events(events).await?)
684 }
685
686 async fn new_device_vault(
687 &mut self,
688 ) -> Result<(DeviceSigner, DeviceManager)> {
689 let mut account = self.account.lock().await;
690 Ok(account.new_device_vault().await?)
691 }
692
693 async fn device_signer(&self) -> Result<DeviceSigner> {
694 let account = self.account.lock().await;
695 Ok(account.device_signer().await?)
696 }
697
698 async fn device_public_key(&self) -> Result<DevicePublicKey> {
699 let account = self.account.lock().await;
700 Ok(account.device_public_key().await?)
701 }
702
703 async fn patch_devices_unchecked(
704 &mut self,
705 events: &[DeviceEvent],
706 ) -> Result<()> {
707 let mut account = self.account.lock().await;
708 Ok(account.patch_devices_unchecked(events).await?)
709 }
710
711 async fn revoke_device(
712 &mut self,
713 device_key: &DevicePublicKey,
714 ) -> Result<()> {
715 let current_device = self.current_device().await?;
716 if current_device.public_key() == device_key {
717 return Err(Error::RevokeDeviceSelf);
718 }
719
720 {
722 let mut account = self.account.lock().await;
723 account.revoke_device(device_key).await?;
724 }
725
726 #[cfg(feature = "audit")]
727 {
728 let audit_event = AuditEvent::new(
729 Default::default(),
730 EventKind::RevokeDevice,
731 *self.account_id(),
732 Some(AuditData::Device(*device_key)),
733 );
734 append_audit_events(&[audit_event]).await?;
735 }
736
737 if let Some(e) = self.sync().await.first_error() {
739 tracing::error!(error = ?e);
740 return Err(Error::RevokeDeviceSync(Box::new(e)));
741 }
742
743 Ok(())
744 }
745
746 async fn current_device(&self) -> Result<TrustedDevice> {
747 let account = self.account.lock().await;
748 Ok(account.current_device().await?)
749 }
750
751 async fn trusted_devices(&self) -> Result<IndexSet<TrustedDevice>> {
752 let account = self.account.lock().await;
753 Ok(account.trusted_devices().await?)
754 }
755
756 async fn public_identity(&self) -> Result<PublicIdentity> {
757 let account = self.account.lock().await;
758 Ok(account.public_identity().await?)
759 }
760
761 async fn account_name(&self) -> Result<String> {
762 let account = self.account.lock().await;
763 Ok(account.account_name().await?)
764 }
765
766 async fn folder_description(
767 &mut self,
768 folder_id: &VaultId,
769 ) -> Result<String> {
770 let mut account = self.account.lock().await;
771 Ok(account.folder_description(folder_id).await?)
772 }
773
774 async fn set_folder_description(
775 &mut self,
776 folder_id: &VaultId,
777 description: impl AsRef<str> + Send + Sync,
778 ) -> Result<FolderChange<Self::NetworkResult>> {
779 let _ = self.sync_lock.lock().await;
780 let result = {
781 let mut account = self.account.lock().await;
782 account
783 .set_folder_description(folder_id, description)
784 .await?
785 };
786
787 let result = FolderChange {
788 event: result.event,
789 commit_state: result.commit_state,
790 sync_result: self.sync().await,
791 };
792
793 Ok(result)
794 }
795
796 async fn login_folder_summary(&self) -> Result<Summary> {
797 let account = self.account.lock().await;
798 Ok(account.login_folder_summary().await?)
799 }
800
801 async fn reload_login_folder(&mut self) -> Result<()> {
802 let mut account = self.account.lock().await;
803 Ok(account.reload_login_folder().await?)
804 }
805
806 async fn change_cipher(
807 &mut self,
808 account_key: &AccessKey,
809 cipher: &Cipher,
810 kdf: Option<KeyDerivation>,
811 ) -> Result<CipherComparison> {
812 let conversion = {
813 let mut account = self.account.lock().await;
814 account.change_cipher(account_key, cipher, kdf).await?
816 };
817
818 let identity = if conversion.identity.is_some() {
819 let log = self.identity_log().await?;
820 let reader = log.read().await;
821 let diff = reader.diff_unchecked().await?;
822 Some(diff)
823 } else {
824 None
825 };
826
827 let mut folders = HashMap::new();
830
831 for folder in &conversion.folders {
832 if folder.flags().is_sync_disabled() {
833 continue;
834 }
835 let event_log = self.folder_log(folder.id()).await?;
836 let log_file = event_log.read().await;
837 let diff = log_file.diff_unchecked().await?;
838 folders.insert(*folder.id(), diff);
839 }
840
841 let sync_options: SyncOptions = Default::default();
843 let updates = UpdateSet {
844 identity,
845 folders,
846 ..Default::default()
847 };
848
849 let sync_result = self.force_update(updates, &sync_options).await;
850 if let Some(sync_error) = sync_result.first_error() {
851 return Err(Error::ForceUpdate(Box::new(sync_error)));
852 }
853
854 if let Some(sync_error) =
857 self.sync_with_options(&sync_options).await.first_error()
858 {
859 return Err(Error::ForceUpdate(Box::new(sync_error)));
860 }
861
862 Ok(conversion)
863 }
864
865 async fn change_account_password(
866 &mut self,
867 password: SecretString,
868 ) -> Result<()> {
869 {
870 let mut account = self.account.lock().await;
871 account.change_account_password(password).await?
872 }
873
874 let log = self.identity_log().await?;
875 let reader = log.read().await;
876 let identity = reader.diff_unchecked().await?;
877
878 let sync_options: SyncOptions = Default::default();
880 let updates = UpdateSet {
881 identity: Some(identity),
882 ..Default::default()
883 };
884
885 let sync_result = self.force_update(updates, &sync_options).await;
886 if let Some(sync_error) = sync_result.first_error() {
887 return Err(Error::ForceUpdate(Box::new(sync_error)));
888 }
889
890 if let Some(sync_error) =
893 self.sync_with_options(&sync_options).await.first_error()
894 {
895 return Err(Error::ForceUpdate(Box::new(sync_error)));
896 }
897
898 Ok(())
899 }
900
901 async fn sign_in(&mut self, key: &AccessKey) -> Result<Vec<Summary>> {
902 self.login(key).await
903 }
904
905 async fn verify(&self, key: &AccessKey) -> bool {
906 let account = self.account.lock().await;
907 account.verify(key).await
908 }
909
910 async fn open_folder(&self, folder_id: &VaultId) -> Result<()> {
911 let account = self.account.lock().await;
912 Ok(account.open_folder(folder_id).await?)
913 }
914
915 async fn current_folder(&self) -> Result<Option<Summary>> {
916 let account = self.account.lock().await;
917 Ok(account.current_folder().await?)
918 }
919
920 async fn history(
921 &self,
922 folder_id: &VaultId,
923 ) -> Result<Vec<(CommitHash, UtcDateTime, WriteEvent)>> {
924 let account = self.account.lock().await;
925 Ok(account.history(folder_id).await?)
926 }
927
928 async fn sign_out(&mut self) -> Result<()> {
929 self.deactivate().await;
930 self.remotes = Default::default();
931 self.server_origins = None;
932
933 #[cfg(feature = "files")]
934 {
935 self.file_transfers.take();
936 }
937
938 let mut account = self.account.lock().await;
939 Ok(account.sign_out().await?)
940 }
941
942 async fn rename_account(
943 &mut self,
944 account_name: String,
945 ) -> Result<AccountChange<Self::NetworkResult>> {
946 let _ = self.sync_lock.lock().await;
947 let result = {
948 let mut account = self.account.lock().await;
949 account.rename_account(account_name).await?
950 };
951
952 let result = AccountChange {
953 event: result.event,
954 sync_result: self.sync().await,
955 };
956
957 Ok(result)
958 }
959
960 async fn set_account_name(
961 &mut self,
962 account_name: String,
963 ) -> std::result::Result<(), Self::Error> {
964 let mut account = self.account.lock().await;
965 Ok(account.set_account_name(account_name).await?)
966 }
967
968 async fn delete_account(&mut self) -> Result<()> {
969 #[cfg(feature = "listen")]
971 self.shutdown_websockets().await;
972
973 #[cfg(feature = "files")]
975 self.stop_file_transfers().await;
976
977 {
978 let mut account = self.account.lock().await;
979 account.delete_account().await?;
981 }
982
983 Ok(())
984 }
985
986 async fn find<P>(&self, predicate: P) -> Option<Summary>
987 where
988 P: FnMut(&&Summary) -> bool + Send,
989 {
990 let account = self.account.lock().await;
991 account.find(predicate).await
992 }
993
994 async fn find_folder(&self, vault: &FolderRef) -> Option<Summary> {
995 let account = self.account.lock().await;
996 account.find_folder(vault).await
997 }
998
999 async fn load_folders(&mut self) -> Result<Vec<Summary>> {
1000 let mut account = self.account.lock().await;
1001 Ok(account.load_folders().await?)
1002 }
1003
1004 async fn list_folders(&self) -> Result<Vec<Summary>> {
1005 let account = self.account.lock().await;
1006 Ok(account.list_folders().await?)
1007 }
1008
1009 async fn list_secret_ids(
1010 &self,
1011 folder_id: &VaultId,
1012 ) -> Result<Vec<SecretId>> {
1013 let account = self.account.lock().await;
1014 Ok(account.list_secret_ids(folder_id).await?)
1015 }
1016
1017 async fn account_data(&self) -> Result<AccountData> {
1018 let account = self.account.lock().await;
1019 Ok(account.account_data().await?)
1020 }
1021
1022 async fn root_hash(&self, folder_id: &VaultId) -> Result<CommitHash> {
1023 let account = self.account.lock().await;
1024 Ok(account.root_hash(folder_id).await?)
1025 }
1026
1027 async fn identity_state(&self) -> Result<CommitState> {
1028 let account = self.account.lock().await;
1029 Ok(account.identity_state().await?)
1030 }
1031
1032 async fn commit_state(&self, folder_id: &VaultId) -> Result<CommitState> {
1033 let account = self.account.lock().await;
1034 Ok(account.commit_state(folder_id).await?)
1035 }
1036
1037 async fn compact_account(
1038 &mut self,
1039 ) -> Result<HashMap<Summary, AccountEvent>> {
1040 let result = {
1041 let mut account = self.account.lock().await;
1042 account.compact_account().await?
1043 };
1044
1045 let identity = {
1046 let log = self.identity_log().await?;
1047 let reader = log.read().await;
1048 reader.diff_unchecked().await?
1049 };
1050
1051 let mut folders = HashMap::new();
1054 let compact_folders = self.list_folders().await?;
1055
1056 for folder in &compact_folders {
1057 if folder.flags().is_sync_disabled() {
1058 continue;
1059 }
1060 let event_log = self.folder_log(folder.id()).await?;
1061 let log_file = event_log.read().await;
1062 let diff = log_file.diff_unchecked().await?;
1063 folders.insert(*folder.id(), diff);
1064 }
1065
1066 let sync_options: SyncOptions = Default::default();
1068 let updates = UpdateSet {
1069 identity: Some(identity),
1070 folders,
1071 ..Default::default()
1072 };
1073
1074 let sync_result = self.force_update(updates, &sync_options).await;
1075 if let Some(sync_error) = sync_result.first_error() {
1076 return Err(Error::ForceUpdate(Box::new(sync_error)));
1077 }
1078
1079 if let Some(sync_error) =
1082 self.sync_with_options(&sync_options).await.first_error()
1083 {
1084 return Err(Error::ForceUpdate(Box::new(sync_error)));
1085 }
1086
1087 Ok(result)
1088 }
1089
1090 async fn compact_folder(
1091 &mut self,
1092 folder_id: &VaultId,
1093 ) -> Result<AccountEvent> {
1094 let result = {
1095 let mut account = self.account.lock().await;
1096 account.compact_folder(folder_id).await?
1097 };
1098
1099 let mut folders = HashMap::new();
1102 let folder = self
1103 .find(|f| f.id() == folder_id)
1104 .await
1105 .ok_or_else(|| StorageError::FolderNotFound(*folder_id))?;
1106 if !folder.flags().is_sync_disabled() {
1107 let event_log = self.folder_log(folder_id).await?;
1108 let log_file = event_log.read().await;
1109 let diff = log_file.diff_unchecked().await?;
1110 folders.insert(*folder_id, diff);
1111 }
1112
1113 if !folders.is_empty() {
1114 let sync_options: SyncOptions = Default::default();
1116 let updates = UpdateSet {
1117 identity: None,
1118 folders,
1119 ..Default::default()
1120 };
1121
1122 let sync_result = self.force_update(updates, &sync_options).await;
1123 if let Some(sync_error) = sync_result.first_error() {
1124 return Err(Error::ForceUpdate(Box::new(sync_error)));
1125 }
1126
1127 if let Some(sync_error) =
1130 self.sync_with_options(&sync_options).await.first_error()
1131 {
1132 return Err(Error::ForceUpdate(Box::new(sync_error)));
1133 }
1134 }
1135
1136 Ok(result)
1137 }
1138
1139 async fn restore_folder(
1140 &mut self,
1141 folder_id: &VaultId,
1142 records: Vec<EventRecord>,
1143 ) -> Result<Summary> {
1144 let mut account = self.account.lock().await;
1145 Ok(account.restore_folder(folder_id, records).await?)
1146 }
1147
1148 async fn change_folder_password(
1149 &mut self,
1150 folder_id: &VaultId,
1151 new_key: AccessKey,
1152 ) -> Result<()> {
1153 {
1154 let mut account = self.account.lock().await;
1155 account.change_folder_password(folder_id, new_key).await?;
1156 }
1157
1158 let identity = {
1159 let log = self.identity_log().await?;
1160 let reader = log.read().await;
1161 reader.diff_unchecked().await?
1162 };
1163
1164 let mut folders = HashMap::new();
1167 let folder = self
1168 .find(|f| f.id() == folder_id)
1169 .await
1170 .ok_or_else(|| StorageError::FolderNotFound(*folder_id))?;
1171 if !folder.flags().is_sync_disabled() {
1172 let event_log = self.folder_log(folder_id).await?;
1173 let log_file = event_log.read().await;
1174 let diff = log_file.diff_unchecked().await?;
1175 folders.insert(*folder_id, diff);
1176 }
1177
1178 if !folders.is_empty() {
1179 let sync_options: SyncOptions = Default::default();
1181 let updates = UpdateSet {
1182 identity: Some(identity),
1183 folders,
1184 ..Default::default()
1185 };
1186
1187 let sync_result = self.force_update(updates, &sync_options).await;
1188 if let Some(sync_error) = sync_result.first_error() {
1189 return Err(Error::ForceUpdate(Box::new(sync_error)));
1190 }
1191
1192 if let Some(sync_error) =
1195 self.sync_with_options(&sync_options).await.first_error()
1196 {
1197 return Err(Error::ForceUpdate(Box::new(sync_error)));
1198 }
1199 }
1200
1201 Ok(())
1202 }
1203
1204 #[cfg(feature = "search")]
1205 async fn detached_view(
1206 &self,
1207 folder_id: &VaultId,
1208 commit: CommitHash,
1209 ) -> Result<sos_account::DetachedView> {
1210 let account = self.account.lock().await;
1211 Ok(account.detached_view(folder_id, commit).await?)
1212 }
1213
1214 #[cfg(feature = "search")]
1215 async fn initialize_search_index(
1216 &mut self,
1217 ) -> Result<(DocumentCount, Vec<Summary>)> {
1218 let mut account = self.account.lock().await;
1219 Ok(account.initialize_search_index().await?)
1220 }
1221
1222 #[cfg(feature = "search")]
1223 async fn statistics(&self) -> AccountStatistics {
1224 let account = self.account.lock().await;
1225 account.statistics().await
1226 }
1227
1228 #[cfg(feature = "search")]
1229 async fn search_index(&self) -> Result<Arc<RwLock<SearchIndex>>> {
1230 let account = self.account.lock().await;
1231 Ok(account.search_index().await?)
1232 }
1233
1234 #[cfg(feature = "search")]
1235 async fn query_view(
1236 &self,
1237 views: &[DocumentView],
1238 archive: Option<&ArchiveFilter>,
1239 ) -> Result<Vec<Document>> {
1240 let account = self.account.lock().await;
1241 Ok(account.query_view(views, archive).await?)
1242 }
1243
1244 #[cfg(feature = "search")]
1245 async fn query_map(
1246 &self,
1247 query: &str,
1248 filter: QueryFilter,
1249 ) -> Result<Vec<Document>> {
1250 let account = self.account.lock().await;
1251 Ok(account.query_map(query, filter).await?)
1252 }
1253
1254 #[cfg(feature = "search")]
1255 async fn document_count(&self) -> Result<DocumentCount> {
1256 let account = self.account.lock().await;
1257 Ok(account.document_count().await?)
1258 }
1259
1260 #[cfg(feature = "search")]
1261 async fn document_exists(
1262 &self,
1263 vault_id: &VaultId,
1264 label: &str,
1265 id: Option<&SecretId>,
1266 ) -> Result<bool> {
1267 let account = self.account.lock().await;
1268 Ok(account.document_exists(vault_id, label, id).await?)
1269 }
1270
1271 #[cfg(feature = "files")]
1272 async fn download_file(
1273 &self,
1274 vault_id: &VaultId,
1275 secret_id: &SecretId,
1276 file_name: &sos_core::ExternalFileName,
1277 ) -> Result<Vec<u8>> {
1278 let account = self.account.lock().await;
1279 Ok(account
1280 .download_file(vault_id, secret_id, file_name)
1281 .await?)
1282 }
1283
1284 async fn create_secret(
1285 &mut self,
1286 meta: SecretMeta,
1287 secret: Secret,
1288 options: AccessOptions,
1289 ) -> Result<SecretChange<Self::NetworkResult>> {
1290 let _ = self.sync_lock.lock().await;
1291
1292 let result = {
1293 let mut account = self.account.lock().await;
1294 account.create_secret(meta, secret, options).await?
1295 };
1296
1297 let result = SecretChange {
1298 id: result.id,
1299 event: result.event,
1300 commit_state: result.commit_state,
1301 folder: result.folder,
1302 sync_result: self.sync().await,
1303 #[cfg(feature = "files")]
1304 file_events: result.file_events,
1305 };
1306
1307 #[cfg(feature = "files")]
1308 self.queue_file_mutation_events(&result.file_events).await?;
1309
1310 Ok(result)
1311 }
1312
1313 async fn insert_secrets(
1314 &mut self,
1315 secrets: Vec<(SecretMeta, Secret)>,
1316 ) -> Result<SecretInsert<Self::NetworkResult>> {
1317 let _ = self.sync_lock.lock().await;
1318
1319 let result = {
1320 let mut account = self.account.lock().await;
1321 account.insert_secrets(secrets).await?
1322 };
1323
1324 #[cfg(feature = "files")]
1325 let mut file_events = Vec::new();
1326
1327 let result = SecretInsert {
1328 results: result
1329 .results
1330 .into_iter()
1331 .map(|#[allow(unused_mut)] mut result| {
1332 #[cfg(feature = "files")]
1333 file_events.append(&mut result.file_events);
1334 SecretChange {
1335 id: result.id,
1336 event: result.event,
1337 commit_state: result.commit_state,
1338 folder: result.folder,
1339 sync_result: Default::default(),
1340 #[cfg(feature = "files")]
1341 file_events: result.file_events,
1342 }
1343 })
1344 .collect(),
1345 sync_result: self.sync().await,
1346 };
1347
1348 #[cfg(feature = "files")]
1349 self.queue_file_mutation_events(&file_events).await?;
1350
1351 Ok(result)
1352 }
1353
1354 async fn update_secret(
1355 &mut self,
1356 secret_id: &SecretId,
1357 meta: SecretMeta,
1358 secret: Option<Secret>,
1359 options: AccessOptions,
1360 ) -> Result<SecretChange<Self::NetworkResult>> {
1361 let _ = self.sync_lock.lock().await;
1362
1363 let result = {
1364 let mut account = self.account.lock().await;
1365 account
1366 .update_secret(secret_id, meta, secret, options)
1367 .await?
1368 };
1369
1370 let result = SecretChange {
1371 id: result.id,
1372 event: result.event,
1373 commit_state: result.commit_state,
1374 folder: result.folder,
1375 sync_result: self.sync().await,
1376 #[cfg(feature = "files")]
1377 file_events: result.file_events,
1378 };
1379
1380 #[cfg(feature = "files")]
1381 self.queue_file_mutation_events(&result.file_events).await?;
1382
1383 Ok(result)
1384 }
1385
1386 async fn move_secret(
1387 &mut self,
1388 secret_id: &SecretId,
1389 from: &VaultId,
1390 to: &VaultId,
1391 options: AccessOptions,
1392 ) -> Result<SecretMove<Self::NetworkResult>> {
1393 let _ = self.sync_lock.lock().await;
1394
1395 let result = {
1396 let mut account = self.account.lock().await;
1397 account.move_secret(secret_id, from, to, options).await?
1398 };
1399
1400 let result = SecretMove {
1401 id: result.id,
1402 event: result.event,
1403 sync_result: self.sync().await,
1404 #[cfg(feature = "files")]
1405 file_events: result.file_events,
1406 };
1407
1408 #[cfg(feature = "files")]
1409 self.queue_file_mutation_events(&result.file_events).await?;
1410
1411 Ok(result)
1412 }
1413
1414 async fn read_secret(
1415 &self,
1416 secret_id: &SecretId,
1417 folder: Option<&VaultId>,
1418 ) -> Result<(SecretRow, ReadEvent)> {
1419 let account = self.account.lock().await;
1420 Ok(account.read_secret(secret_id, folder).await?)
1421 }
1422
1423 async fn raw_secret(
1424 &self,
1425 folder_id: &VaultId,
1426 secret_id: &SecretId,
1427 ) -> std::result::Result<Option<(VaultCommit, ReadEvent)>, Self::Error>
1428 {
1429 let account = self.account.lock().await;
1430 Ok(account.raw_secret(folder_id, secret_id).await?)
1431 }
1432
1433 async fn delete_secret(
1434 &mut self,
1435 secret_id: &SecretId,
1436 options: AccessOptions,
1437 ) -> Result<SecretDelete<Self::NetworkResult>> {
1438 let _ = self.sync_lock.lock().await;
1439
1440 let result = {
1441 let mut account = self.account.lock().await;
1442 account.delete_secret(secret_id, options).await?
1443 };
1444
1445 let result = SecretDelete {
1446 event: result.event,
1447 commit_state: result.commit_state,
1448 folder: result.folder,
1449 sync_result: self.sync().await,
1450 #[cfg(feature = "files")]
1451 file_events: result.file_events,
1452 };
1453
1454 #[cfg(feature = "files")]
1455 self.queue_file_mutation_events(&result.file_events).await?;
1456
1457 Ok(result)
1458 }
1459
1460 async fn archive(
1461 &mut self,
1462 folder_id: &VaultId,
1463 secret_id: &SecretId,
1464 options: AccessOptions,
1465 ) -> Result<SecretMove<Self::NetworkResult>> {
1466 let _ = self.sync_lock.lock().await;
1467 let result = {
1468 let mut account = self.account.lock().await;
1469 account.archive(folder_id, secret_id, options).await?
1470 };
1471
1472 let result = SecretMove {
1473 id: result.id,
1474 event: result.event,
1475 sync_result: self.sync().await,
1476 #[cfg(feature = "files")]
1477 file_events: result.file_events,
1478 };
1479
1480 #[cfg(feature = "files")]
1481 self.queue_file_mutation_events(&result.file_events).await?;
1482
1483 Ok(result)
1484 }
1485
1486 async fn unarchive(
1487 &mut self,
1488 secret_id: &SecretId,
1489 secret_kind: &SecretType,
1490 options: AccessOptions,
1491 ) -> Result<(SecretMove<Self::NetworkResult>, Summary)> {
1492 let _ = self.sync_lock.lock().await;
1493
1494 let (result, to) = {
1495 let mut account = self.account.lock().await;
1496 account.unarchive(secret_id, secret_kind, options).await?
1497 };
1498
1499 let result = SecretMove {
1500 id: result.id,
1501 event: result.event,
1502 sync_result: self.sync().await,
1503 #[cfg(feature = "files")]
1504 file_events: result.file_events,
1505 };
1506
1507 #[cfg(feature = "files")]
1508 self.queue_file_mutation_events(&result.file_events).await?;
1509
1510 Ok((result, to))
1511 }
1512
1513 #[cfg(feature = "files")]
1514 async fn update_file(
1515 &mut self,
1516 secret_id: &SecretId,
1517 meta: SecretMeta,
1518 path: impl AsRef<Path> + Send + Sync,
1519 options: AccessOptions,
1520 ) -> Result<SecretChange<Self::NetworkResult>> {
1521 let _ = self.sync_lock.lock().await;
1522
1523 let result = {
1524 let mut account = self.account.lock().await;
1525 let result =
1526 account.update_file(secret_id, meta, path, options).await?;
1527 result
1528 };
1529
1530 let result = SecretChange {
1531 id: result.id,
1532 event: result.event,
1533 commit_state: result.commit_state,
1534 folder: result.folder,
1535 sync_result: self.sync().await,
1536 #[cfg(feature = "files")]
1537 file_events: result.file_events,
1538 };
1539
1540 #[cfg(feature = "files")]
1541 self.queue_file_mutation_events(&result.file_events).await?;
1542
1543 Ok(result)
1544 }
1545
1546 async fn create_folder(
1547 &mut self,
1548 options: NewFolderOptions,
1549 ) -> Result<FolderCreate<Self::NetworkResult>> {
1550 let _ = self.sync_lock.lock().await;
1551 let result = {
1552 let mut account = self.account.lock().await;
1553 account.create_folder(options).await?
1554 };
1555
1556 let result = FolderCreate {
1557 folder: result.folder,
1558 event: result.event,
1559 commit_state: result.commit_state,
1560 sync_result: self.sync().await,
1561 };
1562
1563 Ok(result)
1564 }
1565
1566 async fn rename_folder(
1567 &mut self,
1568 folder_id: &VaultId,
1569 name: String,
1570 ) -> Result<FolderChange<Self::NetworkResult>> {
1571 let _ = self.sync_lock.lock().await;
1572 let result = {
1573 let mut account = self.account.lock().await;
1574 account.rename_folder(folder_id, name).await?
1575 };
1576
1577 let result = FolderChange {
1578 event: result.event,
1579 commit_state: result.commit_state,
1580 sync_result: self.sync().await,
1581 };
1582
1583 Ok(result)
1584 }
1585
1586 async fn update_folder_flags(
1587 &mut self,
1588 folder_id: &VaultId,
1589 flags: VaultFlags,
1590 ) -> Result<FolderChange<Self::NetworkResult>> {
1591 let _ = self.sync_lock.lock().await;
1592 let result = {
1593 let mut account = self.account.lock().await;
1594 account.update_folder_flags(folder_id, flags).await?
1595 };
1596
1597 let result = FolderChange {
1598 event: result.event,
1599 commit_state: result.commit_state,
1600 sync_result: self.sync().await,
1601 };
1602
1603 Ok(result)
1604 }
1605
1606 async fn import_folder(
1607 &mut self,
1608 path: impl AsRef<Path> + Send + Sync,
1609 key: AccessKey,
1610 overwrite: bool,
1611 ) -> Result<FolderCreate<Self::NetworkResult>> {
1612 let _ = self.sync_lock.lock().await;
1613
1614 let result = {
1615 let mut account = self.account.lock().await;
1616 account.import_folder(path.as_ref(), key, overwrite).await?
1617 };
1618
1619 let result = FolderCreate {
1620 folder: result.folder,
1621 event: result.event,
1622 commit_state: result.commit_state,
1623 sync_result: self.sync().await,
1624 };
1625
1626 Ok(result)
1627 }
1628
1629 async fn import_login_folder(
1630 &mut self,
1631 vault: Vault,
1632 ) -> Result<AccountEvent> {
1633 let mut account = self.account.lock().await;
1634 Ok(account.import_login_folder(vault).await?)
1635 }
1636
1637 async fn import_folder_buffer(
1638 &mut self,
1639 buffer: impl AsRef<[u8]> + Send + Sync,
1640 key: AccessKey,
1641 overwrite: bool,
1642 ) -> Result<FolderCreate<Self::NetworkResult>> {
1643 let _ = self.sync_lock.lock().await;
1644
1645 let result = {
1646 let mut account = self.account.lock().await;
1647 account.import_folder_buffer(buffer, key, overwrite).await?
1648 };
1649
1650 let result = FolderCreate {
1651 folder: result.folder,
1652 event: result.event,
1653 commit_state: result.commit_state,
1654 sync_result: self.sync().await,
1655 };
1656
1657 Ok(result)
1658 }
1659
1660 async fn export_folder(
1661 &mut self,
1662 path: impl AsRef<Path> + Send + Sync,
1663 folder_id: &VaultId,
1664 new_key: AccessKey,
1665 save_key: bool,
1666 ) -> Result<()> {
1667 let mut account = self.account.lock().await;
1668 Ok(account
1669 .export_folder(path, folder_id, new_key, save_key)
1670 .await?)
1671 }
1672
1673 async fn export_folder_buffer(
1674 &mut self,
1675 folder_id: &VaultId,
1676 new_key: AccessKey,
1677 save_key: bool,
1678 ) -> Result<Vec<u8>> {
1679 let mut account = self.account.lock().await;
1680 Ok(account
1681 .export_folder_buffer(folder_id, new_key, save_key)
1682 .await?)
1683 }
1684
1685 async fn delete_folder(
1686 &mut self,
1687 folder_id: &VaultId,
1688 ) -> Result<FolderDelete<Self::NetworkResult>> {
1689 let _ = self.sync_lock.lock().await;
1690 let result = {
1691 let mut account = self.account.lock().await;
1692 account.delete_folder(folder_id).await?
1693 };
1694
1695 let result = FolderDelete {
1696 events: result.events,
1697 commit_state: result.commit_state,
1698 sync_result: self.sync().await,
1699 };
1700
1701 Ok(result)
1702 }
1703
1704 async fn forget_folder(&mut self, folder_id: &VaultId) -> Result<bool> {
1705 let mut account = self.account.lock().await;
1706 Ok(account.forget_folder(folder_id).await?)
1707 }
1708
1709 #[cfg(feature = "contacts")]
1710 async fn load_avatar(
1711 &self,
1712 secret_id: &SecretId,
1713 folder: Option<&VaultId>,
1714 ) -> Result<Option<Vec<u8>>> {
1715 let account = self.account.lock().await;
1716 Ok(account.load_avatar(secret_id, folder).await?)
1717 }
1718
1719 #[cfg(feature = "contacts")]
1720 async fn export_contact(
1721 &self,
1722 path: impl AsRef<Path> + Send + Sync,
1723 secret_id: &SecretId,
1724 folder: Option<&VaultId>,
1725 ) -> Result<()> {
1726 let account = self.account.lock().await;
1727 Ok(account.export_contact(path, secret_id, folder).await?)
1728 }
1729
1730 #[cfg(feature = "contacts")]
1731 async fn export_all_contacts(
1732 &self,
1733 path: impl AsRef<Path> + Send + Sync,
1734 ) -> Result<()> {
1735 let account = self.account.lock().await;
1736 Ok(account.export_all_contacts(path).await?)
1737 }
1738
1739 #[cfg(feature = "contacts")]
1740 async fn import_contacts(
1741 &mut self,
1742 content: &str,
1743 progress: impl Fn(ContactImportProgress) + Send + Sync,
1744 ) -> Result<Vec<SecretId>> {
1745 let mut account = self.account.lock().await;
1746 Ok(account.import_contacts(content, progress).await?)
1747 }
1748
1749 #[cfg(feature = "migrate")]
1765 async fn export_unsafe_archive(
1766 &self,
1767 path: impl AsRef<Path> + Send + Sync,
1768 ) -> Result<()> {
1769 let account = self.account.lock().await;
1770 Ok(account.export_unsafe_archive(path).await?)
1771 }
1772
1773 #[cfg(feature = "migrate")]
1774 async fn import_file(
1775 &mut self,
1776 target: ImportTarget,
1777 ) -> Result<FolderCreate<Self::NetworkResult>> {
1778 let _ = self.sync_lock.lock().await;
1779
1780 let result = {
1781 let mut account = self.account.lock().await;
1782 account.import_file(target).await?
1783 };
1784
1785 let result = FolderCreate {
1786 folder: result.folder,
1787 event: result.event,
1788 commit_state: result.commit_state,
1789 sync_result: self.sync().await,
1790 };
1791
1792 Ok(result)
1793 }
1794
1795 #[cfg(feature = "archive")]
1796 async fn export_backup_archive(
1797 &self,
1798 path: impl AsRef<Path> + Send + Sync,
1799 ) -> Result<()> {
1800 let account = self.account.lock().await;
1801 Ok(account.export_backup_archive(path).await?)
1802 }
1803
1804 #[cfg(feature = "archive")]
1805 async fn import_backup_archive(
1806 path: impl AsRef<Path> + Send + Sync,
1807 target: &BackendTarget,
1808 ) -> Result<Vec<PublicIdentity>> {
1809 Ok(LocalAccount::import_backup_archive(path, target).await?)
1810 }
1811
1812 #[cfg(feature = "clipboard")]
1813 async fn copy_clipboard(
1814 &self,
1815 clipboard: &Clipboard,
1816 target: &SecretPath,
1817 request: &ClipboardCopyRequest,
1818 ) -> Result<bool> {
1819 let account = self.account.lock().await;
1820 Ok(account.copy_clipboard(clipboard, target, request).await?)
1821 }
1822}
1823
1824#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1825#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
1826impl DelegatedAccess for NetworkAccount {
1827 type Error = Error;
1828
1829 async fn find_folder_password(
1830 &self,
1831 folder_id: &VaultId,
1832 ) -> Result<Option<AccessKey>> {
1833 let account = self.account.lock().await;
1834 Ok(account.find_folder_password(folder_id).await?)
1835 }
1836
1837 async fn remove_folder_password(
1838 &mut self,
1839 folder_id: &VaultId,
1840 ) -> Result<()> {
1841 let mut account = self.account.lock().await;
1842 Ok(account.remove_folder_password(folder_id).await?)
1843 }
1844
1845 async fn save_folder_password(
1846 &mut self,
1847 folder_id: &VaultId,
1848 key: AccessKey,
1849 ) -> Result<()> {
1850 let mut account = self.account.lock().await;
1851 Ok(account.save_folder_password(folder_id, key).await?)
1852 }
1853}