1use std::{collections::HashMap, path::PathBuf, sync::Arc};
2
3use tokio::runtime::Runtime;
4use uuid::Uuid;
5
6use crate::{
7 model::{
8 account::{Account, Username},
9 api::{
10 AccountFilter, AccountIdentifier, AccountInfo, AdminFileInfoResponse,
11 AdminSetUserTierInfo, AdminValidateAccount, AdminValidateServer, ServerIndex,
12 StripeAccountTier, SubscriptionInfo,
13 },
14 core_config::Config,
15 crypto::DecryptedDocument,
16 errors::{LbResult, Warning},
17 file::{File, ShareMode},
18 file_metadata::{DocumentHmac, FileType},
19 path_ops::Filter,
20 },
21 service::{
22 activity::RankingWeights,
23 import_export::{ExportFileInfo, ImportStatus},
24 sync::{SyncProgress, SyncStatus},
25 usage::{UsageItemMetric, UsageMetrics},
26 },
27 subscribers::{
28 search::{SearchConfig, SearchResult},
29 status::Status,
30 },
31};
32
33#[derive(Clone)]
34pub struct Lb {
35 lb: crate::Lb,
36 rt: Arc<Runtime>,
37}
38
39impl Lb {
40 pub fn init(config: Config) -> LbResult<Self> {
41 let rt = Arc::new(Runtime::new().unwrap());
42 let lb = rt.block_on(crate::Lb::init(config))?;
43 Ok(Self { rt, lb })
44 }
45
46 pub fn create_account(
47 &self, username: &str, api_url: &str, welcome_doc: bool,
48 ) -> LbResult<Account> {
49 self.rt
50 .block_on(self.lb.create_account(username, api_url, welcome_doc))
51 }
52
53 pub fn import_account(&self, key: &str, api_url: Option<&str>) -> LbResult<Account> {
54 self.rt.block_on(self.lb.import_account(key, api_url))
55 }
56
57 pub fn export_account_private_key(&self) -> LbResult<String> {
58 self.lb.export_account_private_key_v1()
59 }
60
61 pub fn export_account_phrase(&self) -> LbResult<String> {
62 self.lb.export_account_phrase()
63 }
64
65 pub fn export_account_qr(&self) -> LbResult<Vec<u8>> {
66 self.lb.export_account_qr()
67 }
68
69 pub fn get_account(&self) -> LbResult<&Account> {
70 self.lb.get_account()
71 }
72
73 pub fn get_config(&self) -> Config {
74 self.lb.config.clone()
75 }
76
77 pub fn create_file(&self, name: &str, parent: &Uuid, file_type: FileType) -> LbResult<File> {
78 self.rt
79 .block_on(self.lb.create_file(name, parent, file_type))
80 }
81
82 pub fn safe_write(
83 &self, id: Uuid, old_hmac: Option<DocumentHmac>, content: Vec<u8>,
84 ) -> LbResult<DocumentHmac> {
85 self.rt.block_on(self.lb.safe_write(id, old_hmac, content))
86 }
87
88 pub fn write_document(&self, id: Uuid, content: &[u8]) -> LbResult<()> {
89 self.rt.block_on(self.lb.write_document(id, content))
90 }
91
92 pub fn get_root(&self) -> LbResult<File> {
93 self.rt.block_on(self.lb.root())
94 }
95
96 pub fn get_children(&self, id: &Uuid) -> LbResult<Vec<File>> {
97 self.rt.block_on(self.lb.get_children(id))
98 }
99
100 pub fn get_and_get_children_recursively(&self, id: &Uuid) -> LbResult<Vec<File>> {
101 self.rt
102 .block_on(self.lb.get_and_get_children_recursively(id))
103 }
104
105 pub fn get_file_by_id(&self, id: Uuid) -> LbResult<File> {
106 self.rt.block_on(self.lb.get_file_by_id(id))
107 }
108
109 pub fn delete_file(&self, id: &Uuid) -> LbResult<()> {
110 self.rt.block_on(self.lb.delete(id))
111 }
112
113 pub fn read_document(&self, id: Uuid, user_activity: bool) -> LbResult<DecryptedDocument> {
114 self.rt.block_on(self.lb.read_document(id, user_activity))
115 }
116
117 pub fn read_document_with_hmac(
118 &self, id: Uuid, user_activity: bool,
119 ) -> LbResult<(Option<DocumentHmac>, DecryptedDocument)> {
120 self.rt
121 .block_on(self.lb.read_document_with_hmac(id, user_activity))
122 }
123
124 pub fn list_metadatas(&self) -> LbResult<Vec<File>> {
125 self.rt.block_on(self.lb.list_metadatas())
126 }
127
128 pub fn rename_file(&self, id: &Uuid, new_name: &str) -> LbResult<()> {
129 self.rt.block_on(self.lb.rename_file(id, new_name))
130 }
131
132 pub fn move_file(&self, id: &Uuid, new_parent: &Uuid) -> LbResult<()> {
133 self.rt.block_on(self.lb.move_file(id, new_parent))
134 }
135
136 pub fn share_file(&self, id: Uuid, username: &str, mode: ShareMode) -> LbResult<()> {
137 self.rt.block_on(self.lb.share_file(id, username, mode))
138 }
139
140 pub fn get_pending_shares(&self) -> LbResult<Vec<File>> {
141 self.rt.block_on(self.lb.get_pending_shares())
142 }
143
144 pub fn delete_pending_share(&self, id: &Uuid) -> LbResult<()> {
145 self.rt.block_on(async { self.lb.reject_share(id).await })
146 }
147
148 pub fn create_link_at_path(&self, path_and_name: &str, target_id: Uuid) -> LbResult<File> {
149 self.rt
150 .block_on(self.lb.create_link_at_path(path_and_name, target_id))
151 }
152
153 pub fn create_at_path(&self, path_and_name: &str) -> LbResult<File> {
154 self.rt.block_on(self.lb.create_at_path(path_and_name))
155 }
156
157 pub fn get_by_path(&self, path: &str) -> LbResult<File> {
158 self.rt.block_on(self.lb.get_by_path(path))
159 }
160
161 pub fn get_path_by_id(&self, id: Uuid) -> LbResult<String> {
162 self.rt.block_on(self.lb.get_path_by_id(id))
163 }
164
165 pub fn list_paths(&self, filter: Option<Filter>) -> LbResult<Vec<String>> {
166 self.rt.block_on(self.lb.list_paths(filter))
167 }
168
169 pub fn get_local_changes(&self) -> LbResult<Vec<Uuid>> {
170 Ok(self.rt.block_on(self.lb.local_changes()))
171 }
172
173 pub fn calculate_work(&self) -> LbResult<SyncStatus> {
174 self.rt.block_on(self.lb.calculate_work())
175 }
176
177 pub fn sync(&self, f: Option<Box<dyn Fn(SyncProgress) + Send>>) -> LbResult<SyncStatus> {
178 self.rt.block_on(self.lb.sync(f))
179 }
180
181 pub fn get_last_synced(&self) -> LbResult<i64> {
182 self.rt.block_on(async {
183 let tx = self.lb.ro_tx().await;
184 let db = tx.db();
185 Ok(db.last_synced.get().copied().unwrap_or(0))
186 })
187 }
188
189 pub fn get_last_synced_human_string(&self) -> LbResult<String> {
190 self.rt.block_on(self.lb.get_last_synced_human())
191 }
192
193 pub fn get_timestamp_human_string(&self, timestamp: i64) -> String {
194 self.lb.get_timestamp_human_string(timestamp)
195 }
196
197 pub fn suggested_docs(&self, settings: RankingWeights) -> LbResult<Vec<Uuid>> {
198 self.rt.block_on(self.lb.suggested_docs(settings))
199 }
200
201 pub fn get_usage(&self) -> LbResult<UsageMetrics> {
203 self.rt.block_on(self.lb.get_usage())
204 }
205
206 pub fn get_uncompressed_usage_breakdown(&self) -> LbResult<HashMap<Uuid, usize>> {
207 self.rt.block_on(self.lb.get_uncompressed_usage_breakdown())
208 }
209
210 pub fn get_uncompressed_usage(&self) -> LbResult<UsageItemMetric> {
211 self.rt.block_on(self.lb.get_uncompressed_usage())
212 }
213
214 pub fn import_files<F: Fn(ImportStatus)>(
215 &self, sources: &[PathBuf], dest: Uuid, update_status: &F,
216 ) -> LbResult<()> {
217 self.rt
218 .block_on(self.lb.import_files(sources, dest, update_status))
219 }
220
221 pub fn export_files(
222 &self, id: Uuid, dest: PathBuf, edit: bool,
223 export_progress: &Option<Box<dyn Fn(ExportFileInfo)>>,
224 ) -> LbResult<()> {
225 self.rt
226 .block_on(self.lb.export_file(id, dest, edit, export_progress))
227 }
228
229 pub fn search_file_paths(&self, input: &str) -> LbResult<Vec<SearchResult>> {
230 self.rt
231 .block_on(async { self.lb.search(input, SearchConfig::Paths).await })
232 }
233
234 pub fn search(&self, input: &str, cfg: SearchConfig) -> LbResult<Vec<SearchResult>> {
235 self.rt.block_on(self.lb.search(input, cfg))
236 }
237
238 pub fn validate(&self) -> LbResult<Vec<Warning>> {
239 self.rt.block_on(self.lb.test_repo_integrity())
240 }
241
242 pub fn upgrade_account_stripe(&self, account_tier: StripeAccountTier) -> LbResult<()> {
243 self.rt
244 .block_on(self.lb.upgrade_account_stripe(account_tier))
245 }
246
247 pub fn upgrade_account_google_play(
248 &self, purchase_token: &str, account_id: &str,
249 ) -> LbResult<()> {
250 self.rt.block_on(
251 self.lb
252 .upgrade_account_google_play(purchase_token, account_id),
253 )
254 }
255
256 pub fn upgrade_account_app_store(
257 &self, original_transaction_id: String, app_account_token: String,
258 ) -> LbResult<()> {
259 self.rt.block_on(
260 self.lb
261 .upgrade_account_app_store(original_transaction_id, app_account_token),
262 )
263 }
264
265 pub fn cancel_subscription(&self) -> LbResult<()> {
266 self.rt.block_on(self.lb.cancel_subscription())
267 }
268
269 pub fn get_subscription_info(&self) -> LbResult<Option<SubscriptionInfo>> {
270 self.rt.block_on(self.lb.get_subscription_info())
271 }
272
273 pub fn delete_account(&self) -> LbResult<()> {
274 self.rt.block_on(self.lb.delete_account())
275 }
276
277 pub fn admin_disappear_account(&self, username: &str) -> LbResult<()> {
278 self.rt.block_on(self.lb.disappear_account(username))
279 }
280
281 pub fn admin_disappear_file(&self, id: Uuid) -> LbResult<()> {
282 self.rt.block_on(self.lb.disappear_file(id))
283 }
284
285 pub fn admin_list_users(&self, filter: Option<AccountFilter>) -> LbResult<Vec<Username>> {
286 self.rt.block_on(self.lb.list_users(filter))
287 }
288
289 pub fn admin_get_account_info(&self, identifier: AccountIdentifier) -> LbResult<AccountInfo> {
290 self.rt.block_on(self.lb.get_account_info(identifier))
291 }
292
293 pub fn admin_validate_account(&self, username: &str) -> LbResult<AdminValidateAccount> {
294 self.rt.block_on(self.lb.validate_account(username))
295 }
296
297 pub fn admin_validate_server(&self) -> LbResult<AdminValidateServer> {
298 self.rt.block_on(self.lb.validate_server())
299 }
300
301 pub fn admin_file_info(&self, id: Uuid) -> LbResult<AdminFileInfoResponse> {
302 self.rt.block_on(self.lb.file_info(id))
303 }
304
305 pub fn admin_rebuild_index(&self, index: ServerIndex) -> LbResult<()> {
306 self.rt.block_on(self.lb.rebuild_index(index))
307 }
308
309 pub fn admin_set_user_tier(&self, username: &str, info: AdminSetUserTierInfo) -> LbResult<()> {
310 self.rt.block_on(self.lb.set_user_tier(username, info))
311 }
312
313 pub fn status(&self) -> Status {
314 self.rt.block_on(self.lb.status())
315 }
316
317 pub fn debug_info(&self, os_info: String) -> String {
318 self.rt
319 .block_on(self.lb.debug_info(os_info))
320 .unwrap_or_else(|e| format!("failed to produce debug info: {:?}", e.to_string()))
321 }
322}