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
36pub enum ServerStorage {
38 FileSystem(SyncImpl<ServerFileStorage>),
40 Database(SyncImpl<ServerDatabaseStorage>),
42}
43
44impl ServerStorage {
45 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 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 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 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 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 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}