1use crate::Lb;
2use crate::model::access_info::UserAccessMode;
3use crate::model::errors::{LbErrKind, LbResult};
4use crate::model::file::File;
5use crate::model::file_metadata::{FileType, Owner};
6use crate::model::filename::MAX_FILENAME_LENGTH;
7use crate::model::symkey;
8use crate::model::tree_like::TreeLike;
9use crate::service::events::Actor;
10use std::iter;
11use uuid::Uuid;
12
13impl Lb {
14 #[instrument(level = "debug", skip(self), err(Debug))]
15 pub async fn create_file(
16 &self, name: &str, parent: &Uuid, file_type: FileType,
17 ) -> LbResult<File> {
18 let mut tx = self.begin_tx().await;
19 let db = tx.db();
20
21 if name.len() > MAX_FILENAME_LENGTH {
23 return Err(LbErrKind::FileNameTooLong.into());
24 }
25 let mut tree = (&db.base_metadata)
26 .to_staged(&mut db.local_metadata)
27 .to_lazy();
28
29 let id = tree.create(
30 Uuid::new_v4(),
31 symkey::generate_key(),
32 parent,
33 name,
34 file_type,
35 &self.keychain,
36 )?;
37
38 let ui_file = tree.decrypt(&self.keychain, &id, &db.pub_key_lookup)?;
39
40 tx.end();
41
42 self.events.meta_changed(Actor::User);
43 Ok(ui_file)
44 }
45
46 #[instrument(level = "debug", skip(self), err(Debug))]
47 pub async fn rename_file(&self, id: &Uuid, new_name: &str) -> LbResult<()> {
48 let mut tx = self.begin_tx().await;
49 let db = tx.db();
50
51 if new_name.len() > MAX_FILENAME_LENGTH {
52 return Err(LbErrKind::FileNameTooLong.into());
53 }
54 let mut tree = (&db.base_metadata)
55 .to_staged(&mut db.local_metadata)
56 .to_lazy();
57
58 let id = &tree.linked_by(id)?.unwrap_or(*id);
59
60 tree.rename(id, new_name, &self.keychain)?;
61
62 tx.end();
63
64 self.events.meta_changed(Actor::User);
65
66 Ok(())
67 }
68
69 #[instrument(level = "debug", skip(self), err(Debug))]
70 pub async fn move_file(&self, id: &Uuid, new_parent: &Uuid) -> LbResult<()> {
71 let mut tx = self.begin_tx().await;
72 let db = tx.db();
73
74 let mut tree = (&db.base_metadata)
75 .to_staged(&mut db.local_metadata)
76 .to_lazy();
77
78 let id = &tree.linked_by(id)?.unwrap_or(*id);
79
80 tree.move_file(id, new_parent, &self.keychain)?;
81 tx.end();
82
83 self.events.meta_changed(Actor::User);
84
85 Ok(())
86 }
87
88 #[instrument(level = "debug", skip(self), err(Debug))]
89 pub async fn delete(&self, id: &Uuid) -> LbResult<()> {
90 let mut tx = self.begin_tx().await;
91 let db = tx.db();
92
93 let mut tree = (&db.base_metadata)
94 .to_staged(&mut db.local_metadata)
95 .to_lazy();
96
97 let id = &tree.linked_by(id)?.unwrap_or(*id);
98
99 tree.delete(id, &self.keychain)?;
100
101 tx.end();
102
103 self.events.meta_changed(Actor::User);
104
105 Ok(())
106 }
107
108 #[instrument(level = "debug", skip(self), err(Debug))]
110 pub async fn root(&self) -> LbResult<File> {
111 let tx = self.ro_tx().await;
112 let db = tx.db();
113
114 let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
115
116 let root_id = db.root.get().ok_or(LbErrKind::RootNonexistent)?;
117
118 let root = tree.decrypt(&self.keychain, root_id, &db.pub_key_lookup)?;
119
120 Ok(root)
121 }
122
123 #[instrument(level = "debug", skip(self), err(Debug))]
124 pub async fn list_metadatas(&self) -> LbResult<Vec<File>> {
125 let tx = self.ro_tx().await;
126 let db = tx.db();
127
128 let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
129
130 let ids = tree.ids().into_iter();
131
132 tree.decrypt_all(&self.keychain, ids, &db.pub_key_lookup, true)
133 }
134
135 #[instrument(level = "debug", skip(self), err(Debug))]
136 pub async fn get_children(&self, id: &Uuid) -> LbResult<Vec<File>> {
137 let tx = self.ro_tx().await;
138 let db = tx.db();
139
140 let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
141
142 let ids = tree.children_using_links(id)?.into_iter();
143
144 tree.decrypt_all(&self.keychain, ids, &db.pub_key_lookup, true)
145 }
146
147 #[instrument(level = "debug", skip(self), err(Debug))]
148 pub async fn get_and_get_children_recursively(&self, id: &Uuid) -> LbResult<Vec<File>> {
149 let tx = self.ro_tx().await;
150 let db = tx.db();
151
152 let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
153
154 let descendants = tree.descendants_using_links(id)?;
155
156 tree.decrypt_all(
157 &self.keychain,
158 descendants.into_iter().chain(iter::once(*id)),
159 &db.pub_key_lookup,
160 true,
161 )
162 }
163
164 #[instrument(level = "debug", skip(self), err(Debug))]
165 pub async fn get_file_by_id(&self, id: Uuid) -> LbResult<File> {
166 let tx = self.ro_tx().await;
167 let db = tx.db();
168
169 let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
170
171 if tree.calculate_deleted(&id)? {
172 return Err(LbErrKind::FileNonexistent.into());
173 }
174 if tree.access_mode(Owner(self.keychain.get_pk()?), &id)? < Some(UserAccessMode::Read) {
175 return Err(LbErrKind::FileNonexistent.into());
176 }
177
178 let file = tree.decrypt(&self.keychain, &id, &db.pub_key_lookup)?;
179
180 Ok(file)
181 }
182
183 pub async fn local_changes(&self) -> Vec<Uuid> {
184 let tx = self.ro_tx().await;
185 let db = tx.db();
186 db.local_metadata.get().keys().copied().collect()
187 }
188}