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