lb_rs/service/
file.rs

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        // todo this is checked later and probably can be removed
21        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    // todo: keychain?
108    #[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}