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