Skip to main content

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