lockbook_shared/
server_tree.rs

1use crate::file_like::FileLike;
2use crate::file_metadata::Owner;
3use crate::server_file::ServerFile;
4use crate::tree_like::{TreeLike, TreeLikeMut};
5use crate::SharedResult;
6use db_rs::{LookupSet, LookupTable};
7use std::collections::HashSet;
8use std::iter::FromIterator;
9use tracing::*;
10use uuid::Uuid;
11
12pub struct ServerTree<'a> {
13    pub ids: HashSet<Uuid>,
14    pub owned_files: &'a mut LookupSet<Owner, Uuid>,
15    pub shared_files: &'a mut LookupSet<Owner, Uuid>,
16    pub file_children: &'a mut LookupSet<Uuid, Uuid>,
17    pub files: &'a mut LookupTable<Uuid, ServerFile>,
18}
19
20impl<'a> ServerTree<'a> {
21    pub fn new(
22        owner: Owner, owned_files: &'a mut LookupSet<Owner, Uuid>,
23        shared_files: &'a mut LookupSet<Owner, Uuid>, file_children: &'a mut LookupSet<Uuid, Uuid>,
24        files: &'a mut LookupTable<Uuid, ServerFile>,
25    ) -> SharedResult<Self> {
26        let (owned_ids, shared_ids) =
27            match (owned_files.get().get(&owner), shared_files.get().get(&owner)) {
28                (Some(owned_ids), Some(shared_ids)) => (owned_ids.clone(), shared_ids.clone()),
29                _ => {
30                    error!("Tree created for user without owned and shared files {:?}", owner);
31                    (HashSet::new(), HashSet::new())
32                }
33            };
34
35        let mut ids = HashSet::new();
36        ids.extend(owned_ids);
37        ids.extend(shared_ids.clone());
38
39        let mut to_get_descendants = Vec::from_iter(shared_ids);
40        while let Some(id) = to_get_descendants.pop() {
41            let children = file_children.get().get(&id).cloned().unwrap_or_default();
42            ids.extend(children.clone());
43            to_get_descendants.extend(children);
44        }
45
46        Ok(Self { ids, owned_files, shared_files, file_children, files })
47    }
48}
49
50impl TreeLike for ServerTree<'_> {
51    type F = ServerFile;
52
53    fn ids(&self) -> HashSet<&Uuid> {
54        self.ids.iter().collect()
55    }
56
57    fn maybe_find(&self, id: &Uuid) -> Option<&Self::F> {
58        if self.ids.contains(id) {
59            self.files.maybe_find(id)
60        } else {
61            None
62        }
63    }
64}
65
66impl TreeLikeMut for ServerTree<'_> {
67    fn insert(&mut self, f: Self::F) -> SharedResult<Option<Self::F>> {
68        let id = *f.id();
69        let owner = f.owner();
70        let maybe_prior = LookupTable::insert(self.files, id, f.clone())?;
71
72        // maintain index: owned_files
73        if maybe_prior.as_ref().map(|f| f.owner()) != Some(f.owner()) {
74            if let Some(ref prior) = maybe_prior {
75                self.owned_files.remove(&prior.owner(), &id)?;
76            }
77            self.owned_files.insert(owner, id)?;
78        }
79
80        // maintain index: shared_files
81        let prior_sharees = if let Some(ref prior) = maybe_prior {
82            prior
83                .user_access_keys()
84                .iter()
85                .filter(|k| !k.deleted)
86                .map(|k| Owner(k.encrypted_for))
87                .collect()
88        } else {
89            HashSet::new()
90        };
91        let sharees = f
92            .user_access_keys()
93            .iter()
94            .filter(|k| !k.deleted)
95            .map(|k| Owner(k.encrypted_for))
96            .collect::<HashSet<_>>();
97        for removed_sharee in prior_sharees.difference(&sharees) {
98            self.shared_files.remove(removed_sharee, &id)?;
99        }
100        for new_sharee in sharees.difference(&prior_sharees) {
101            self.shared_files.insert(*new_sharee, id)?;
102        }
103
104        // maintain index: file_children
105        if self.file_children.get().get(&id).is_none() {
106            self.file_children.create_key(id)?;
107        }
108        if self.file_children.get().get(f.parent()).is_none() {
109            self.file_children.create_key(*f.parent())?;
110        }
111        if maybe_prior.as_ref().map(|f| *f.parent()) != Some(*f.parent()) {
112            if let Some(ref prior) = maybe_prior {
113                self.file_children.remove(prior.parent(), &id)?;
114            }
115
116            self.file_children.insert(*f.parent(), id)?;
117        }
118
119        Ok(maybe_prior)
120    }
121
122    fn remove(&mut self, _id: Uuid) -> SharedResult<Option<Self::F>> {
123        error!("remove metadata called in server!");
124        Ok(None)
125    }
126
127    fn clear(&mut self) -> SharedResult<()> {
128        error!("clear called in server!");
129        Ok(())
130    }
131}