sos_backend/
lib.rs

1#![deny(missing_docs)]
2#![forbid(unsafe_code)]
3#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
4//! Backend database and file system storage.
5mod access_point;
6#[cfg(feature = "audit")]
7pub mod audit;
8pub mod compact;
9mod error;
10mod event_log;
11mod folder;
12mod helpers;
13#[cfg(feature = "preferences")]
14mod preferences;
15mod server_origins;
16#[cfg(feature = "system-messages")]
17mod system_messages;
18mod vault_writer;
19
20pub use access_point::BackendAccessPoint as AccessPoint;
21pub use error::{Error, StorageError};
22pub use event_log::{
23    BackendAccountEventLog as AccountEventLog,
24    BackendDeviceEventLog as DeviceEventLog, BackendEventLog,
25    BackendFolderEventLog as FolderEventLog,
26};
27pub use folder::Folder;
28pub use helpers::extract_vault;
29#[cfg(feature = "preferences")]
30pub use preferences::BackendPreferences as Preferences;
31pub use server_origins::ServerOrigins;
32pub use sos_database as database;
33pub use sos_filesystem::write_exclusive;
34use sos_vault::Summary;
35#[cfg(feature = "system-messages")]
36pub use system_messages::SystemMessages;
37pub use vault_writer::VaultWriter;
38
39#[cfg(feature = "files")]
40pub use event_log::BackendFileEventLog as FileEventLog;
41
42/// Result type for the library.
43pub(crate) type Result<T> = std::result::Result<T, Error>;
44
45use sos_core::{AccountId, PublicIdentity};
46use sos_database::entity::{
47    AccountEntity, AccountRecord, FolderEntity, FolderRecord,
48};
49
50/// Target backend.
51#[derive(Clone)]
52pub enum BackendTarget {
53    /// File system backend
54    FileSystem(sos_core::Paths),
55    /// Database backend.
56    Database(sos_database::async_sqlite::Client),
57}
58
59impl BackendTarget {
60    /// List accounts.
61    pub async fn list_accounts(&self) -> Result<Vec<PublicIdentity>> {
62        match self {
63            BackendTarget::FileSystem(paths) => {
64                Ok(sos_vault::list_accounts(Some(paths)).await?)
65            }
66            BackendTarget::Database(client) => {
67                let account_rows = client
68                    .conn_and_then(move |conn| {
69                        let account = AccountEntity::new(&conn);
70                        account.list_accounts()
71                    })
72                    .await?;
73                let mut accounts = Vec::new();
74                for row in account_rows {
75                    let record: AccountRecord = row.try_into()?;
76                    accounts.push(record.identity);
77                }
78                Ok(accounts)
79            }
80        }
81    }
82
83    /// List user folders for an account.
84    pub async fn list_folders(
85        &self,
86        account_id: &AccountId,
87    ) -> Result<Vec<Summary>> {
88        match self {
89            BackendTarget::FileSystem(paths) => {
90                let paths = paths.with_account_id(account_id);
91                Ok(sos_vault::list_local_folders(&paths)
92                    .await?
93                    .into_iter()
94                    .map(|(s, _)| s)
95                    .collect())
96            }
97            BackendTarget::Database(client) => {
98                let account_id = *account_id;
99                let folder_rows = client
100                    .conn_and_then(move |conn| {
101                        let account = AccountEntity::new(&conn);
102                        let folders = FolderEntity::new(&conn);
103                        let account_row = account.find_one(&account_id)?;
104                        folders.list_user_folders(account_row.row_id)
105                    })
106                    .await?;
107                let mut folders = Vec::new();
108                for row in folder_rows {
109                    let record = FolderRecord::from_row(row).await?;
110                    folders.push(record.summary);
111                }
112                Ok(folders)
113            }
114        }
115    }
116}