sos_server_storage/
storage.rs

1use crate::{
2    database::ServerDatabaseStorage, filesystem::ServerFileStorage, Error,
3    Result, ServerAccountStorage,
4};
5use async_trait::async_trait;
6use indexmap::IndexSet;
7use sos_backend::{
8    AccountEventLog, BackendTarget, DeviceEventLog, FolderEventLog,
9};
10use sos_core::{
11    commit::{CommitState, Comparison},
12    device::{DevicePublicKey, TrustedDevice},
13    events::{
14        patch::{AccountDiff, CheckedPatch, DeviceDiff, FolderDiff},
15        EventLog, WriteEvent,
16    },
17    AccountId, Paths, VaultFlags, VaultId,
18};
19use sos_database::{async_sqlite::Client, entity::AccountEntity};
20use sos_sync::{
21    CreateSet, ForceMerge, Merge, MergeOutcome, StorageEventLogs, SyncStatus,
22    SyncStorage,
23};
24use sos_vault::{Summary, Vault};
25use std::{
26    collections::{HashMap, HashSet},
27    sync::Arc,
28};
29use tokio::sync::RwLock;
30
31#[cfg(feature = "files")]
32use {sos_backend::FileEventLog, sos_core::events::patch::FileDiff};
33
34use crate::sync::SyncImpl;
35
36/// Server storage backed by filesystem or database.
37pub enum ServerStorage {
38    /// Filesystem storage.
39    FileSystem(SyncImpl<ServerFileStorage>),
40    /// Database storage.
41    Database(SyncImpl<ServerDatabaseStorage>),
42}
43
44impl ServerStorage {
45    /// Create new server storage.
46    pub async fn new(
47        paths: &Paths,
48        account_id: &AccountId,
49        target: BackendTarget,
50    ) -> Result<Self> {
51        debug_assert!(paths.is_server());
52
53        match target {
54            BackendTarget::FileSystem(paths) => {
55                Self::new_fs(paths, account_id).await
56            }
57            BackendTarget::Database(client) => {
58                Self::new_db(paths, account_id, client).await
59            }
60        }
61    }
62
63    /// Create new file system storage.
64    async fn new_fs(paths: Paths, account_id: &AccountId) -> Result<Self> {
65        let paths = paths.with_account_id(account_id);
66
67        let mut event_log =
68            FolderEventLog::new_fs_folder(paths.identity_events()).await?;
69        event_log.load_tree().await?;
70
71        Ok(Self::FileSystem(SyncImpl::new(
72            ServerFileStorage::new(
73                paths,
74                *account_id,
75                Arc::new(RwLock::new(event_log)),
76            )
77            .await?,
78        )))
79    }
80
81    /// Create an account in server storage.
82    pub async fn create_account(
83        paths: &Paths,
84        account_id: &AccountId,
85        target: BackendTarget,
86        account_data: &CreateSet,
87    ) -> Result<Self> {
88        debug_assert!(paths.is_server());
89
90        match target {
91            BackendTarget::FileSystem(paths) => {
92                Self::create_fs_account(&paths, account_id, account_data)
93                    .await
94            }
95            BackendTarget::Database(client) => {
96                Self::create_db_account(
97                    paths,
98                    account_id,
99                    client,
100                    account_data,
101                )
102                .await
103            }
104        }
105    }
106
107    /// Create a new file system account.
108    async fn create_fs_account(
109        paths: &Paths,
110        account_id: &AccountId,
111        account_data: &CreateSet,
112    ) -> Result<Self> {
113        let paths = paths.with_account_id(account_id);
114        paths.ensure().await?;
115
116        let identity_log = ServerFileStorage::initialize_account(
117            &paths,
118            &account_data.identity,
119        )
120        .await?;
121
122        let mut storage = ServerFileStorage::new(
123            paths,
124            *account_id,
125            Arc::new(RwLock::new(identity_log)),
126        )
127        .await?;
128        storage.import_account(&account_data).await?;
129
130        Ok(Self::FileSystem(SyncImpl::new(storage)))
131    }
132
133    /// Create new database storage.
134    async fn new_db(
135        paths: &Paths,
136        account_id: &AccountId,
137        client: Client,
138    ) -> Result<Self> {
139        let paths = paths.with_account_id(account_id);
140
141        let (_, login_folder) =
142            AccountEntity::find_account_with_login(&client, account_id)
143                .await?;
144
145        let mut event_log = FolderEventLog::new_db_folder(
146            client.clone(),
147            *account_id,
148            *login_folder.summary.id(),
149        )
150        .await?;
151        event_log.load_tree().await?;
152
153        Ok(Self::Database(SyncImpl::new(
154            ServerDatabaseStorage::new(
155                client,
156                *account_id,
157                Arc::new(RwLock::new(event_log)),
158                paths,
159            )
160            .await?,
161        )))
162    }
163
164    /// Create a new database account.
165    async fn create_db_account(
166        paths: &Paths,
167        account_id: &AccountId,
168        mut client: Client,
169        account_data: &CreateSet,
170    ) -> Result<Self> {
171        let paths = paths.with_account_id(account_id);
172
173        let identity_log = ServerDatabaseStorage::initialize_account(
174            &mut client,
175            account_id,
176            &account_data.identity,
177        )
178        .await?;
179
180        let mut storage = ServerDatabaseStorage::new(
181            client,
182            *account_id,
183            Arc::new(RwLock::new(identity_log)),
184            paths,
185        )
186        .await?;
187        storage.import_account(&account_data).await?;
188
189        Ok(Self::Database(SyncImpl::new(storage)))
190    }
191}
192
193#[async_trait]
194impl ServerAccountStorage for ServerStorage {
195    fn account_id(&self) -> &AccountId {
196        match self {
197            ServerStorage::FileSystem(fs) => fs.account_id(),
198            ServerStorage::Database(db) => db.account_id(),
199        }
200    }
201
202    fn list_device_keys(&self) -> HashSet<&DevicePublicKey> {
203        match self {
204            ServerStorage::FileSystem(fs) => fs.list_device_keys(),
205            ServerStorage::Database(db) => db.list_device_keys(),
206        }
207    }
208
209    fn paths(&self) -> Arc<Paths> {
210        match self {
211            ServerStorage::FileSystem(fs) => fs.paths(),
212            ServerStorage::Database(db) => db.paths(),
213        }
214    }
215
216    fn folders(&self) -> &HashMap<VaultId, Arc<RwLock<FolderEventLog>>> {
217        match self {
218            ServerStorage::FileSystem(fs) => fs.folders(),
219            ServerStorage::Database(db) => db.folders(),
220        }
221    }
222
223    fn folders_mut(
224        &mut self,
225    ) -> &mut HashMap<VaultId, Arc<RwLock<FolderEventLog>>> {
226        match self {
227            ServerStorage::FileSystem(fs) => fs.folders_mut(),
228            ServerStorage::Database(db) => db.folders_mut(),
229        }
230    }
231
232    fn set_devices(&mut self, devices: IndexSet<TrustedDevice>) {
233        match self {
234            ServerStorage::FileSystem(fs) => fs.set_devices(devices),
235            ServerStorage::Database(db) => db.set_devices(devices),
236        }
237    }
238
239    async fn rename_account(&self, name: &str) -> Result<()> {
240        match self {
241            ServerStorage::FileSystem(fs) => fs.rename_account(name).await,
242            ServerStorage::Database(db) => db.rename_account(name).await,
243        }
244    }
245
246    async fn write_vault(&self, vault: &Vault) -> Result<()> {
247        match self {
248            ServerStorage::FileSystem(fs) => fs.write_vault(vault).await,
249            ServerStorage::Database(db) => db.write_vault(vault).await,
250        }
251    }
252
253    async fn replace_folder(
254        &self,
255        folder_id: &VaultId,
256        diff: &FolderDiff,
257    ) -> Result<(FolderEventLog, Vault)> {
258        match self {
259            ServerStorage::FileSystem(fs) => {
260                fs.replace_folder(folder_id, diff).await
261            }
262            ServerStorage::Database(db) => {
263                db.replace_folder(folder_id, diff).await
264            }
265        }
266    }
267
268    async fn set_folder_flags(
269        &self,
270        folder_id: &VaultId,
271        flags: VaultFlags,
272    ) -> Result<()> {
273        match self {
274            ServerStorage::FileSystem(fs) => {
275                fs.set_folder_flags(folder_id, flags).await
276            }
277            ServerStorage::Database(db) => {
278                db.set_folder_flags(folder_id, flags).await
279            }
280        }
281    }
282
283    async fn import_account(
284        &mut self,
285        account_data: &CreateSet,
286    ) -> Result<()> {
287        match self {
288            ServerStorage::FileSystem(fs) => {
289                fs.import_account(account_data).await
290            }
291            ServerStorage::Database(db) => {
292                db.import_account(account_data).await
293            }
294        }
295    }
296
297    async fn load_folders(&mut self) -> Result<Vec<Summary>> {
298        match self {
299            ServerStorage::FileSystem(fs) => fs.load_folders().await,
300            ServerStorage::Database(db) => db.load_folders().await,
301        }
302    }
303
304    async fn import_folder(
305        &mut self,
306        id: &VaultId,
307        buffer: &[u8],
308    ) -> Result<()> {
309        match self {
310            ServerStorage::FileSystem(fs) => {
311                fs.import_folder(id, buffer).await
312            }
313            ServerStorage::Database(db) => db.import_folder(id, buffer).await,
314        }
315    }
316
317    async fn rename_folder(
318        &mut self,
319        id: &VaultId,
320        name: &str,
321    ) -> Result<()> {
322        match self {
323            ServerStorage::FileSystem(fs) => fs.rename_folder(id, name).await,
324            ServerStorage::Database(db) => db.rename_folder(id, name).await,
325        }
326    }
327
328    async fn delete_folder(&mut self, id: &VaultId) -> Result<()> {
329        match self {
330            ServerStorage::FileSystem(fs) => fs.delete_folder(id).await,
331            ServerStorage::Database(db) => db.delete_folder(id).await,
332        }
333    }
334
335    async fn delete_account(&mut self) -> Result<()> {
336        match self {
337            ServerStorage::FileSystem(fs) => fs.delete_account().await,
338            ServerStorage::Database(db) => db.delete_account().await,
339        }
340    }
341}
342
343#[async_trait]
344impl Merge for ServerStorage {
345    async fn merge_identity(
346        &mut self,
347        diff: FolderDiff,
348        outcome: &mut MergeOutcome,
349    ) -> Result<CheckedPatch> {
350        match self {
351            ServerStorage::FileSystem(fs) => {
352                fs.merge_identity(diff, outcome).await
353            }
354            ServerStorage::Database(db) => {
355                db.merge_identity(diff, outcome).await
356            }
357        }
358    }
359
360    async fn compare_identity(
361        &self,
362        state: &CommitState,
363    ) -> Result<Comparison> {
364        match self {
365            ServerStorage::FileSystem(fs) => fs.compare_identity(state).await,
366            ServerStorage::Database(db) => db.compare_identity(state).await,
367        }
368    }
369
370    async fn merge_account(
371        &mut self,
372        diff: AccountDiff,
373        outcome: &mut MergeOutcome,
374    ) -> Result<(CheckedPatch, HashSet<VaultId>)> {
375        match self {
376            ServerStorage::FileSystem(fs) => {
377                fs.merge_account(diff, outcome).await
378            }
379            ServerStorage::Database(db) => {
380                db.merge_account(diff, outcome).await
381            }
382        }
383    }
384
385    async fn compare_account(
386        &self,
387        state: &CommitState,
388    ) -> Result<Comparison> {
389        match self {
390            ServerStorage::FileSystem(fs) => fs.compare_account(state).await,
391            ServerStorage::Database(db) => db.compare_account(state).await,
392        }
393    }
394
395    async fn merge_device(
396        &mut self,
397        diff: DeviceDiff,
398        outcome: &mut MergeOutcome,
399    ) -> Result<CheckedPatch> {
400        match self {
401            ServerStorage::FileSystem(fs) => {
402                fs.merge_device(diff, outcome).await
403            }
404            ServerStorage::Database(db) => {
405                db.merge_device(diff, outcome).await
406            }
407        }
408    }
409
410    async fn compare_device(
411        &self,
412        state: &CommitState,
413    ) -> Result<Comparison> {
414        match self {
415            ServerStorage::FileSystem(fs) => fs.compare_device(state).await,
416            ServerStorage::Database(db) => db.compare_device(state).await,
417        }
418    }
419
420    #[cfg(feature = "files")]
421    async fn merge_files(
422        &mut self,
423        diff: FileDiff,
424        outcome: &mut MergeOutcome,
425    ) -> Result<CheckedPatch> {
426        match self {
427            ServerStorage::FileSystem(fs) => {
428                fs.merge_files(diff, outcome).await
429            }
430            ServerStorage::Database(db) => {
431                db.merge_files(diff, outcome).await
432            }
433        }
434    }
435
436    #[cfg(feature = "files")]
437    async fn compare_files(&self, state: &CommitState) -> Result<Comparison> {
438        match self {
439            ServerStorage::FileSystem(fs) => fs.compare_files(state).await,
440            ServerStorage::Database(db) => db.compare_files(state).await,
441        }
442    }
443
444    async fn merge_folder(
445        &mut self,
446        folder_id: &VaultId,
447        diff: FolderDiff,
448        outcome: &mut MergeOutcome,
449    ) -> Result<(CheckedPatch, Vec<WriteEvent>)> {
450        match self {
451            ServerStorage::FileSystem(fs) => {
452                fs.merge_folder(folder_id, diff, outcome).await
453            }
454            ServerStorage::Database(db) => {
455                db.merge_folder(folder_id, diff, outcome).await
456            }
457        }
458    }
459
460    async fn compare_folder(
461        &self,
462        folder_id: &VaultId,
463        state: &CommitState,
464    ) -> Result<Comparison> {
465        match self {
466            ServerStorage::FileSystem(fs) => {
467                fs.compare_folder(folder_id, state).await
468            }
469            ServerStorage::Database(db) => {
470                db.compare_folder(folder_id, state).await
471            }
472        }
473    }
474}
475
476#[async_trait]
477impl ForceMerge for ServerStorage {
478    async fn force_merge_identity(
479        &mut self,
480        diff: FolderDiff,
481        outcome: &mut MergeOutcome,
482    ) -> Result<()> {
483        match self {
484            ServerStorage::FileSystem(fs) => {
485                fs.force_merge_identity(diff, outcome).await
486            }
487            ServerStorage::Database(db) => {
488                db.force_merge_identity(diff, outcome).await
489            }
490        }
491    }
492
493    async fn force_merge_account(
494        &mut self,
495        diff: AccountDiff,
496        outcome: &mut MergeOutcome,
497    ) -> Result<()> {
498        match self {
499            ServerStorage::FileSystem(fs) => {
500                fs.force_merge_account(diff, outcome).await
501            }
502            ServerStorage::Database(db) => {
503                db.force_merge_account(diff, outcome).await
504            }
505        }
506    }
507
508    async fn force_merge_device(
509        &mut self,
510        diff: DeviceDiff,
511        outcome: &mut MergeOutcome,
512    ) -> Result<()> {
513        match self {
514            ServerStorage::FileSystem(fs) => {
515                fs.force_merge_device(diff, outcome).await
516            }
517            ServerStorage::Database(db) => {
518                db.force_merge_device(diff, outcome).await
519            }
520        }
521    }
522
523    #[cfg(feature = "files")]
524    async fn force_merge_files(
525        &mut self,
526        diff: FileDiff,
527        outcome: &mut MergeOutcome,
528    ) -> Result<()> {
529        match self {
530            ServerStorage::FileSystem(fs) => {
531                fs.force_merge_files(diff, outcome).await
532            }
533            ServerStorage::Database(db) => {
534                db.force_merge_files(diff, outcome).await
535            }
536        }
537    }
538
539    async fn force_merge_folder(
540        &mut self,
541        folder_id: &VaultId,
542        diff: FolderDiff,
543        outcome: &mut MergeOutcome,
544    ) -> Result<()> {
545        match self {
546            ServerStorage::FileSystem(fs) => {
547                fs.force_merge_folder(folder_id, diff, outcome).await
548            }
549            ServerStorage::Database(db) => {
550                db.force_merge_folder(folder_id, diff, outcome).await
551            }
552        }
553    }
554}
555
556#[async_trait]
557impl StorageEventLogs for ServerStorage {
558    type Error = Error;
559
560    async fn identity_log(&self) -> Result<Arc<RwLock<FolderEventLog>>> {
561        match self {
562            ServerStorage::FileSystem(fs) => fs.identity_log().await,
563            ServerStorage::Database(db) => db.identity_log().await,
564        }
565    }
566
567    async fn account_log(&self) -> Result<Arc<RwLock<AccountEventLog>>> {
568        match self {
569            ServerStorage::FileSystem(fs) => fs.account_log().await,
570            ServerStorage::Database(db) => db.account_log().await,
571        }
572    }
573
574    async fn device_log(&self) -> Result<Arc<RwLock<DeviceEventLog>>> {
575        match self {
576            ServerStorage::FileSystem(fs) => fs.device_log().await,
577            ServerStorage::Database(db) => db.device_log().await,
578        }
579    }
580
581    #[cfg(feature = "files")]
582    async fn file_log(&self) -> Result<Arc<RwLock<FileEventLog>>> {
583        match self {
584            ServerStorage::FileSystem(fs) => fs.file_log().await,
585            ServerStorage::Database(db) => db.file_log().await,
586        }
587    }
588
589    async fn folder_details(&self) -> Result<IndexSet<Summary>> {
590        match self {
591            ServerStorage::FileSystem(fs) => fs.folder_details().await,
592            ServerStorage::Database(db) => db.folder_details().await,
593        }
594    }
595
596    async fn folder_log(
597        &self,
598        id: &VaultId,
599    ) -> Result<Arc<RwLock<FolderEventLog>>> {
600        match self {
601            ServerStorage::FileSystem(fs) => fs.folder_log(id).await,
602            ServerStorage::Database(db) => db.folder_log(id).await,
603        }
604    }
605}
606
607#[async_trait]
608impl SyncStorage for ServerStorage {
609    fn is_client_storage(&self) -> bool {
610        false
611    }
612
613    async fn sync_status(&self) -> Result<SyncStatus> {
614        match self {
615            ServerStorage::FileSystem(fs) => fs.sync_status().await,
616            ServerStorage::Database(db) => db.sync_status().await,
617        }
618    }
619}