1use crate::ServerError;
2use crate::ServerError::ClientError;
3use crate::billing::app_store_client::AppStoreClient;
4use crate::billing::google_play_client::GooglePlayClient;
5use crate::billing::stripe_client::StripeClient;
6use crate::defense::SERVER_BANDWIDTH_CAP;
7use crate::document_service::DocumentService;
8use crate::schema::ServerDb;
9
10use crate::{RequestContext, ServerState};
11use db_rs::Db;
12use lb_rs::model::api::{UpsertError, *};
13use lb_rs::model::clock::get_time;
14use lb_rs::model::errors::{LbErrKind, LbResult};
15use lb_rs::model::file_like::FileLike;
16use lb_rs::model::file_metadata::{Diff, Owner};
17use lb_rs::model::server_meta::{IntoServerMeta, ServerMeta};
18use lb_rs::model::server_tree::ServerTree;
19use lb_rs::model::tree_like::TreeLike;
20use std::collections::{HashMap, HashSet};
21use std::hash::Hash;
22use std::ops::DerefMut;
23use tracing::{debug, error, warn};
24
25impl<S, A, G, D> ServerState<S, A, G, D>
26where
27 S: StripeClient,
28 A: AppStoreClient,
29 G: GooglePlayClient,
30 D: DocumentService,
31{
32 pub async fn upsert_file_metadata_v2(
33 &self, context: RequestContext<UpsertRequestV2>,
34 ) -> Result<(), ServerError<UpsertError>> {
35 let req_owner = Owner(context.public_key);
36 let UpsertRequestV2 { updates } = context.request;
37
38 let mut prior_deleted = HashSet::new();
39 let mut current_deleted = HashSet::new();
40
41 let mut lock = self.index_db.lock().await;
42 let db = lock.deref_mut();
43 let tx = db.begin_transaction()?;
44
45 let mut tree = ServerTree::new(
47 req_owner,
48 &mut db.owned_files,
49 &mut db.shared_files,
50 &mut db.file_children,
51 &mut db.metas,
52 )?
53 .to_lazy();
54
55 for id in tree.ids() {
56 if tree.calculate_deleted(&id)? {
57 prior_deleted.insert(id);
58 }
59 }
60
61 let mut tree = tree.stage_diff_v2(updates.clone())?;
62 tree.validate(req_owner)?;
63
64 for id in tree.ids() {
65 if tree.calculate_deleted(&id)? {
66 current_deleted.insert(id);
67 }
68 }
69
70 drop(tree);
71
72 let mut affected_owners: HashSet<Owner> = HashSet::new();
74 for update in &updates {
75 affected_owners.insert(update.new.owner());
76 }
77
78 for &owner in &affected_owners {
81 let usage_cap = Self::get_cap(db, &owner.0).map_err(|err| internal!("{:?}", err))?;
82
83 let mut tree = ServerTree::new(
84 owner,
85 &mut db.owned_files,
86 &mut db.shared_files,
87 &mut db.file_children,
88 &mut db.metas,
89 )?
90 .to_lazy();
91
92 let old_usage = tree.calculate_usage(owner)?;
93 let mut tree = tree.stage_unvalidated(updates.clone());
94 let new_usage = tree.calculate_usage(owner)?;
95
96 debug!(?owner, ?old_usage, ?new_usage, ?usage_cap, "usage caps on upsert");
97
98 if new_usage > usage_cap && new_usage >= old_usage {
99 warn!(?owner, "user over cap");
100 return Err(ClientError(UpsertError::UsageIsOverDataCap));
101 }
102 }
103
104 let tree = ServerTree::new(
105 req_owner,
106 &mut db.owned_files,
107 &mut db.shared_files,
108 &mut db.file_children,
109 &mut db.metas,
110 )?
111 .to_lazy();
112
113 let tree = tree.stage_unvalidated(updates.clone());
114 let tree = tree.promote()?;
115
116 for id in tree.ids() {
117 if tree.find(&id)?.is_document()
118 && current_deleted.contains(&id)
119 && !prior_deleted.contains(&id)
120 {
121 let meta = tree.find(&id)?;
122 if let Some(hmac) = meta.file.timestamped_value.value.document_hmac().copied() {
123 db.scheduled_file_cleanups
124 .insert((*meta.id(), hmac), get_time().0)?;
125 }
126 }
127 }
128
129 let all_files: Vec<ServerMeta> = tree.all_files()?.into_iter().cloned().collect();
130 for meta in all_files {
131 let id = meta.id();
132 if current_deleted.contains(id) && !prior_deleted.contains(id) {
133 for user_access_info in meta.user_access_keys() {
134 db.shared_files
135 .remove(&Owner(user_access_info.encrypted_for), id)?;
136 }
137 }
138 }
139
140 db.last_seen.insert(req_owner, get_time().0 as u64)?;
141
142 tx.drop_safely()?;
143
144 Ok(())
145 }
146
147 pub async fn change_doc_v2(
148 &self, context: RequestContext<ChangeDocRequestV2>,
149 ) -> Result<(), ServerError<ChangeDocError>> {
150 use ChangeDocError::*;
151 let ChangeDocRequestV2 { diff, new_content } = context.request;
152
153 if diff.diff() != vec![Diff::Hmac] {
155 return Err(ClientError(DiffMalformed));
156 }
157
158 match diff.new.timestamped_value.value.doc_size() {
159 Some(size) => {
160 if *size != new_content.value.len() {
161 return Err(ClientError(NewSizeIncorrect));
162 }
163 }
164 None => {
165 if !new_content.value.is_empty() {
167 return Err(ClientError(NewSizeIncorrect));
168 }
169 }
170 }
171
172 let hmac_bytes = *diff.new.document_hmac().ok_or(ClientError(HmacMissing))?;
173 let hmac = base64::encode_config(hmac_bytes, base64::URL_SAFE);
174
175 let requester = Owner(context.public_key);
176 let id = *diff.id();
177 let new_meta = diff.new.clone().add_time(get_time().0 as u64);
178
179 let mut lock = self.index_db.lock().await;
181 let db = lock.deref_mut();
182 let og_meta = db
183 .metas
184 .get()
185 .get(&id)
186 .ok_or(ClientError(DocumentNotFound))?
187 .clone();
188 let tree_owner = og_meta.owner();
189
190 let usage_cap = Self::get_cap(db, &tree_owner.0).map_err(|err| internal!("{:?}", err))?;
191
192 let tree = ServerTree::new(
193 requester,
194 &mut db.owned_files,
195 &mut db.shared_files,
196 &mut db.file_children,
197 &mut db.metas,
198 )?
199 .to_lazy();
200
201 let current_meta = &tree
202 .maybe_find(&id)
203 .ok_or(ClientError(NotPermissioned))?
206 .file;
207
208 if let Some(old) = &diff.old {
209 if current_meta != old {
210 return Err(ClientError(OldVersionIncorrect));
211 }
212 }
213
214 let mut tree = tree.stage(vec![new_meta.clone()]);
215 tree.validate(requester)?;
216
217 let mut tree = ServerTree::new(
218 tree_owner,
219 &mut db.owned_files,
220 &mut db.shared_files,
221 &mut db.file_children,
222 &mut db.metas,
223 )?
224 .to_lazy();
225
226 let old_usage = tree.calculate_usage(tree_owner)?;
227 let mut tree = tree.stage(vec![new_meta.clone()]); let new_usage = tree.calculate_usage(tree_owner)?;
229 debug!(?old_usage, ?new_usage, ?usage_cap, "usage caps on change doc");
230
231 if new_usage > usage_cap && new_usage >= old_usage {
232 warn!("user over cap");
233 return Err(ClientError(UsageIsOverDataCap));
234 }
235
236 db.scheduled_file_cleanups.remove(&(id, hmac_bytes))?;
237 drop(lock);
238
239 self.document_service
240 .insert(&id, &hmac_bytes, &new_content)
241 .await?;
242 debug!(?id, ?hmac, "Inserted document contents");
243
244 let result = async {
245 let mut lock = self.index_db.lock().await;
246 let db = lock.deref_mut();
247 let tx = db.begin_transaction()?;
248
249 let mut tree = ServerTree::new(
250 requester,
251 &mut db.owned_files,
252 &mut db.shared_files,
253 &mut db.file_children,
254 &mut db.metas,
255 )?
256 .to_lazy();
257
258 if tree.calculate_deleted(&id)? {
259 return Err(ClientError(DocumentDeleted));
260 }
261
262 let current_meta = &tree
263 .maybe_find(&id)
264 .ok_or(ClientError(DocumentNotFound))?
265 .file;
266
267 if let Some(old) = &diff.old {
268 if current_meta != old {
269 return Err(ClientError(OldVersionIncorrect));
270 }
271 }
272
273 let old_usage = tree.calculate_usage(tree_owner)?;
274 let mut tree = tree.stage(vec![new_meta]);
275 let new_usage = tree.calculate_usage(tree_owner)?;
276 tree.validate(requester)?;
277 if new_usage > usage_cap && new_usage >= old_usage {
278 warn!("user over cap");
279 return Err(ClientError(UsageIsOverDataCap));
280 }
281 tree.promote()?;
282
283 if let Some(old_hmac) = diff.old.and_then(|old| old.document_hmac().copied()) {
284 db.scheduled_file_cleanups
285 .insert((id, old_hmac), get_time().0)?;
286 }
287
288 tx.drop_safely()?;
289 drop(lock);
290 Ok(())
291 };
292
293 let result = result.await;
294
295 if result.is_err() {
296 self.document_service.delete(&id, &hmac_bytes).await?;
298 debug!(?id, ?hmac, "Cleaned up new document contents after failed metadata update");
299 }
300
301 result?;
302
303 Ok(())
304 }
305
306 pub async fn get_document(
307 &self, context: RequestContext<GetDocRequest>,
308 ) -> Result<GetDocumentResponse, ServerError<GetDocumentError>> {
309 let request = &context.request;
310 let requester = Owner(context.public_key);
311 {
312 let mut lock = self.index_db.lock().await;
313 let db = lock.deref_mut();
314 let tx = db.begin_transaction()?;
315
316 let meta_exists = db.metas.get().get(&request.id).is_some();
317
318 let mut tree = ServerTree::new(
319 requester,
320 &mut db.owned_files,
321 &mut db.shared_files,
322 &mut db.file_children,
323 &mut db.metas,
324 )?
325 .to_lazy();
326
327 if tree.maybe_find(&request.id).is_none() {
328 return Err(if meta_exists {
329 ClientError(GetDocumentError::NotPermissioned)
330 } else {
331 ClientError(GetDocumentError::DocumentNotFound)
332 });
333 }
334
335 if tree.calculate_deleted(&request.id)? {
336 return Err(ClientError(GetDocumentError::DocumentNotFound));
337 }
338
339 tx.drop_safely()?;
340 };
341
342 let Some(content) = self
343 .document_service
344 .maybe_get(&request.id, &request.hmac)
345 .await?
346 else {
347 return Err(ClientError(GetDocumentError::DocumentNotFound));
348 };
349
350 let mut lock = self.index_db.lock().await;
351 let db = lock.deref_mut();
352 let tx = db.begin_transaction()?;
353
354 if self.config.features.bandwidth_controls {
355 let mut server_wide = db.server_egress.get().cloned().unwrap_or_default();
356 let mut account_bandwidth = db
357 .egress_by_owner
358 .get()
359 .get(&requester)
360 .cloned()
361 .unwrap_or_default();
362 let account_bandwidth_cap = db
363 .accounts
364 .get()
365 .get(&requester)
366 .map(|account| account.billing_info.bandwidth_cap())
367 .unwrap_or_default();
368
369 let doc_size = content.value.len();
370
371 if doc_size + server_wide.current_bandwidth() > SERVER_BANDWIDTH_CAP {
372 error!("Bandwidth caps are now being enforced");
373 if doc_size + account_bandwidth.current_bandwidth() > account_bandwidth_cap {
374 error!("User bandwidth cap exceeded");
375 return Err(ClientError(GetDocumentError::BandwidthExceeded));
376 }
377 }
378
379 server_wide.increase_by(doc_size);
380 account_bandwidth.increase_by(doc_size);
381
382 db.server_egress.insert(server_wide)?;
383 db.egress_by_owner.insert(requester, account_bandwidth)?;
384 }
385
386 tx.drop_safely()?;
387
388 Ok(GetDocumentResponse { content })
389 }
390
391 pub async fn get_file_ids(
392 &self, context: RequestContext<GetFileIdsRequest>,
393 ) -> Result<GetFileIdsResponse, ServerError<GetFileIdsError>> {
394 let owner = Owner(context.public_key);
395 let mut db = self.index_db.lock().await;
396 let db = db.deref_mut();
397
398 Ok(GetFileIdsResponse {
399 ids: ServerTree::new(
400 owner,
401 &mut db.owned_files,
402 &mut db.shared_files,
403 &mut db.file_children,
404 &mut db.metas,
405 )?
406 .ids()
407 .into_iter()
408 .collect(),
409 })
410 }
411
412 pub async fn get_updates_v2(
413 &self, context: RequestContext<GetUpdatesRequestV2>,
414 ) -> Result<GetUpdatesResponseV2, ServerError<GetUpdatesError>> {
415 let request = &context.request;
416 let owner = Owner(context.public_key);
417
418 let mut db = self.index_db.lock().await;
419 let db = db.deref_mut();
420 let mut tree = ServerTree::new(
421 owner,
422 &mut db.owned_files,
423 &mut db.shared_files,
424 &mut db.file_children,
425 &mut db.metas,
426 )?
427 .to_lazy();
428
429 let mut result_ids = HashSet::new();
430 for id in tree.ids() {
431 let file = tree.find(&id)?;
432 if file.version >= request.since_metadata_version {
433 result_ids.insert(id);
434 if file.owner() != owner
435 && file
436 .user_access_keys()
437 .iter()
438 .any(|k| !k.deleted && k.encrypted_for == context.public_key)
439 {
440 result_ids.insert(id);
441 result_ids.extend(tree.descendants(&id)?);
442 }
443 }
444 }
445
446 Ok(GetUpdatesResponseV2 {
447 as_of_metadata_version: get_time().0 as u64,
448 file_metadata: tree
449 .all_files()?
450 .into_iter()
451 .filter(|meta| result_ids.contains(meta.id()))
452 .map(|meta| meta.file.clone())
453 .collect(),
454 })
455 }
456
457 pub async fn admin_disappear_file(
458 &self, context: RequestContext<AdminDisappearFileRequest>,
459 ) -> Result<(), ServerError<AdminDisappearFileError>> {
460 let mut docs_to_delete = Vec::new();
461
462 {
463 let mut db = self.index_db.lock().await;
464 let db = db.deref_mut();
465 let tx = db.begin_transaction()?;
466
467 if !Self::is_admin::<AdminDisappearFileError>(
468 db,
469 &context.public_key,
470 &self.config.admin.admins,
471 )? {
472 return Err(ClientError(AdminDisappearFileError::NotPermissioned));
473 }
474
475 let owner = {
476 let meta = db
477 .metas
478 .get()
479 .get(&context.request.id)
480 .ok_or(ClientError(AdminDisappearFileError::FileNonexistent))?;
481 if meta.is_root() {
482 return Err(ClientError(AdminDisappearFileError::RootModificationInvalid));
483 }
484 meta.owner()
485 };
486 let mut tree = ServerTree::new(
487 owner,
488 &mut db.owned_files,
489 &mut db.shared_files,
490 &mut db.file_children,
491 &mut db.metas,
492 )?
493 .to_lazy();
494
495 let metas_to_delete = {
496 let mut metas_to_delete = tree.descendants(&context.request.id)?;
497 metas_to_delete.insert(context.request.id);
498 metas_to_delete
499 };
500 for id in metas_to_delete.clone() {
501 if !tree.calculate_deleted(&id)? {
502 let meta = tree.find(&id)?;
503 if meta.is_document() && meta.owner() == owner {
504 if let Some(hmac) = meta.document_hmac() {
505 docs_to_delete.push((*meta.id(), *hmac));
506 }
507 }
508 }
509 }
510
511 for id in metas_to_delete {
512 let meta = db
513 .metas
514 .remove(&id)?
515 .ok_or(ClientError(AdminDisappearFileError::FileNonexistent))?;
516
517 let owner = meta.owner();
519
520 if !db.owned_files.remove(&owner, &id)? {
521 error!(
522 ?id,
523 ?owner,
524 "attempted to disappear a file, owner or id not present in owned_files"
525 );
526 }
527
528 for user_access_key in meta.user_access_keys() {
530 let sharee = Owner(user_access_key.encrypted_for);
531 if !db.shared_files.remove(&sharee, &id)? {
532 error!(
533 ?id,
534 ?sharee,
535 "attempted to disappear a file, a sharee didn't have it shared"
536 );
537 }
538 }
539
540 let parent = *meta.parent();
542 if !db.file_children.remove(meta.parent(), &id)? {
543 error!(
544 ?id,
545 ?parent,
546 "attempted to disappear a file, the parent didn't have it as a child"
547 );
548 }
549 }
550
551 let username = db
552 .accounts
553 .get()
554 .get(&Owner(context.public_key))
555 .map(|account| account.username.clone())
556 .unwrap_or_else(|| "~unknown~".to_string());
557 warn!(?username, ?context.request.id, "Disappeared file");
558
559 tx.drop_safely()?;
560 }
561
562 for (id, version) in docs_to_delete {
563 self.document_service.delete(&id, &version).await?;
564 }
565
566 Ok(())
567 }
568
569 pub async fn admin_validate_account(
570 &self, context: RequestContext<AdminValidateAccountRequest>,
571 ) -> Result<AdminValidateAccount, ServerError<AdminValidateAccountError>> {
572 let request = &context.request;
573 let mut db = self.index_db.lock().await;
574 if !Self::is_admin::<AdminValidateAccountError>(
575 &db,
576 &context.public_key,
577 &self.config.admin.admins,
578 )? {
579 return Err(ClientError(AdminValidateAccountError::NotPermissioned));
580 }
581
582 let owner = *db
583 .usernames
584 .get()
585 .get(&request.username)
586 .ok_or(ClientError(AdminValidateAccountError::UserNotFound))?;
587
588 Ok(self.validate_account_helper(&mut db, owner)?)
589 }
590
591 pub fn validate_account_helper(
592 &self, db: &mut ServerDb, owner: Owner,
593 ) -> LbResult<AdminValidateAccount> {
594 let mut result = AdminValidateAccount::default();
595
596 let mut tree = ServerTree::new(
597 owner,
598 &mut db.owned_files,
599 &mut db.shared_files,
600 &mut db.file_children,
601 &mut db.metas,
602 )?
603 .to_lazy();
604
605 for id in tree.ids() {
606 if !tree.calculate_deleted(&id)? {
607 let file = tree.find(&id)?;
608 if file.is_document() && file.document_hmac().is_some() {
609 if file.file.timestamped_value.value.doc_size().is_none() {
610 result.documents_missing_size.push(id);
611 }
612
613 if !self
614 .document_service
615 .exists(&id, file.document_hmac().unwrap())
616 {
617 result.documents_missing_content.push(id);
618 }
619 }
620 }
621 }
622
623 let validation_res = tree.stage(None).validate(owner);
624 match validation_res {
625 Ok(_) => {}
626 Err(err) => match err.kind {
627 LbErrKind::Validation(validation) => {
628 result.tree_validation_failures.push(validation)
629 }
630 _ => {
631 error!(?owner, ?err, "Unexpected error while validating tree")
632 }
633 },
634 }
635
636 Ok(result)
637 }
638
639 pub async fn admin_validate_server(
640 &self, context: RequestContext<AdminValidateServerRequest>,
641 ) -> Result<AdminValidateServer, ServerError<AdminValidateServerError>> {
642 let mut db = self.index_db.lock().await;
643 let db = db.deref_mut();
644
645 if !Self::is_admin::<AdminValidateServerError>(
646 db,
647 &context.public_key,
648 &self.config.admin.admins,
649 )? {
650 return Err(ClientError(AdminValidateServerError::NotPermissioned));
651 }
652
653 let mut result: AdminValidateServer = Default::default();
654
655 let mut deleted_ids = HashSet::new();
656 for (id, meta) in db.metas.get().clone() {
657 let mut tree = ServerTree::new(
659 meta.owner(),
660 &mut db.owned_files,
661 &mut db.shared_files,
662 &mut db.file_children,
663 &mut db.metas,
664 )?
665 .to_lazy();
666 if tree.calculate_deleted(&id)? {
667 deleted_ids.insert(id);
668 }
669 }
670
671 for (owner, account) in db.accounts.get().clone() {
673 let validation = self.validate_account_helper(db, owner)?;
674 if !validation.is_empty() {
675 result
676 .users_with_validation_failures
677 .insert(account.username, validation);
678 }
679 }
680
681 for (username, owner) in db.usernames.get().clone() {
683 if let Some(account) = db.accounts.get().get(&owner) {
684 if username != account.username {
685 result
686 .usernames_mapped_to_wrong_accounts
687 .insert(username, account.username.clone());
688 }
689 } else {
690 result
691 .usernames_mapped_to_nonexistent_accounts
692 .insert(username, owner);
693 }
694 }
695 for (_, account) in db.accounts.get().clone() {
696 if db.usernames.get().get(&account.username).is_none() {
697 result
698 .usernames_unmapped_to_accounts
699 .insert(account.username.clone());
700 }
701 }
702
703 for (owner, ids) in db.owned_files.get().clone() {
705 for id in ids {
706 if let Some(meta) = db.metas.get().get(&id) {
707 if meta.owner() != owner {
708 insert(&mut result.owners_mapped_to_unowned_files, owner, id);
709 }
710 } else {
711 insert(&mut result.owners_mapped_to_nonexistent_files, owner, id);
712 }
713 }
714 }
715 for (id, meta) in db.metas.get().clone() {
716 if let Some(ids) = db.owned_files.get().get(&meta.owner()) {
717 if !ids.contains(&id) {
718 insert(&mut result.owners_unmapped_to_owned_files, meta.owner(), *meta.id());
719 }
720 } else {
721 result.owners_unmapped.insert(meta.owner());
722 }
723 }
724
725 for (sharee, ids) in db.shared_files.get().clone() {
727 for id in ids {
728 if let Some(meta) = db.metas.get().get(&id) {
729 if !meta.user_access_keys().iter().any(|k| {
730 !k.deleted && k.encrypted_for == sharee.0 && k.encrypted_by != sharee.0
731 }) {
732 insert(&mut result.sharees_mapped_to_unshared_files, sharee, id);
733 }
734 } else {
735 insert(&mut result.sharees_mapped_to_nonexistent_files, sharee, id);
736 }
737 if deleted_ids.contains(&id) {
738 insert(&mut result.sharees_mapped_for_deleted_files, sharee, id);
739 }
740 }
741 }
742 for (id, meta) in db.metas.get().clone() {
743 let mut deleted = false;
745 let mut ancestor = meta.clone();
746 loop {
747 if ancestor.explicitly_deleted() {
748 deleted = true;
749 break;
750 }
751 if ancestor.is_root() {
752 break;
753 }
754 match db.metas.get().get(ancestor.parent()) {
755 Some(parent) => ancestor = parent.clone(),
756 None => {
757 error!("missing parent for file {:?}", ancestor.parent());
758 deleted = true;
759 break;
760 }
761 }
762 }
763 if deleted {
764 continue;
765 }
766
767 for k in meta.user_access_keys() {
768 if k.deleted {
769 continue;
770 }
771 let sharee = Owner(k.encrypted_for);
772 if let Some(ids) = db.shared_files.get().get(&sharee) {
773 let self_share = k.encrypted_for == k.encrypted_by;
774 let indexed_share = ids.contains(&id);
775 if self_share && indexed_share {
776 insert(&mut result.sharees_mapped_for_owned_files, sharee, id);
777 } else if !self_share && !indexed_share {
778 insert(&mut result.sharees_unmapped_to_shared_files, sharee, id);
779 }
780 } else {
781 result.sharees_unmapped.insert(meta.owner());
782 }
783 }
784 }
785
786 for (parent_id, child_ids) in db.file_children.get().clone() {
788 for child_id in child_ids {
789 if let Some(meta) = db.metas.get().get(&child_id) {
790 if meta.parent() != &parent_id {
791 insert(
792 &mut result.files_mapped_as_parent_to_non_children,
793 parent_id,
794 child_id,
795 );
796 }
797 } else {
798 insert(
799 &mut result.files_mapped_as_parent_to_nonexistent_children,
800 parent_id,
801 child_id,
802 );
803 }
804 }
805 }
806 for (id, meta) in db.metas.get().clone() {
807 if let Some(child_ids) = db.file_children.get().get(meta.parent()) {
808 if meta.is_root() && child_ids.contains(&id) {
809 result.files_mapped_as_parent_to_self.insert(id);
810 } else if !meta.is_root() && !child_ids.contains(&id) {
811 insert(&mut result.files_unmapped_as_parent_to_children, *meta.parent(), id);
812 }
813 } else {
814 result.files_unmapped_as_parent.insert(*meta.parent());
815 }
816 }
817
818 for (id, meta) in db.metas.get().clone() {
820 if let Some(hmac) = meta.document_hmac() {
821 if !deleted_ids.contains(&id) && !self.document_service.exists(&id, hmac) {
822 result.files_with_hmacs_and_no_contents.insert(id);
823 }
824 }
825 }
826
827 Ok(result)
828 }
829
830 pub async fn admin_file_info(
831 &self, context: RequestContext<AdminFileInfoRequest>,
832 ) -> Result<AdminFileInfoResponse, ServerError<AdminFileInfoError>> {
833 let request = &context.request;
834 let mut db = self.index_db.lock().await;
835 let db = db.deref_mut();
836 if !Self::is_admin::<AdminFileInfoError>(
837 db,
838 &context.public_key,
839 &self.config.admin.admins,
840 )? {
841 return Err(ClientError(AdminFileInfoError::NotPermissioned));
842 }
843
844 let file = db
845 .metas
846 .get()
847 .get(&request.id)
848 .ok_or(ClientError(AdminFileInfoError::FileNonexistent))?
849 .clone();
850
851 let mut tree = ServerTree::new(
852 file.owner(),
853 &mut db.owned_files,
854 &mut db.shared_files,
855 &mut db.file_children,
856 &mut db.metas,
857 )?
858 .to_lazy();
859
860 let ancestors = tree
861 .ancestors(&request.id)?
862 .into_iter()
863 .filter_map(|id| tree.maybe_find(&id))
864 .cloned()
865 .collect();
866 let descendants = tree
867 .descendants(&request.id)?
868 .into_iter()
869 .filter_map(|id| tree.maybe_find(&id))
870 .cloned()
871 .collect();
872
873 Ok(AdminFileInfoResponse { file, ancestors, descendants })
874 }
875
876 pub async fn admin_rebuild_index(
877 &self, context: RequestContext<AdminRebuildIndexRequest>,
878 ) -> Result<(), ServerError<AdminRebuildIndexError>> {
879 let mut db = self.index_db.lock().await;
880
881 match context.request.index {
882 ServerIndex::OwnedFiles => {
883 db.owned_files.clear()?;
884 for owner in db.accounts.get().clone().keys() {
885 db.owned_files.create_key(*owner)?;
886 }
887 for (id, file) in db.metas.get().clone() {
888 db.owned_files.insert(file.owner(), id)?;
889 }
890 }
891 ServerIndex::SharedFiles => {
892 db.shared_files.clear()?;
893 for owner in db.accounts.get().clone().keys() {
894 db.shared_files.create_key(*owner)?;
895 }
896 for (id, file) in db.metas.get().clone() {
897 let mut deleted = false;
899 let mut ancestor = file.clone();
900 loop {
901 if ancestor.explicitly_deleted() {
902 deleted = true;
903 break;
904 }
905 if ancestor.is_root() {
906 break;
907 }
908 match db.metas.get().get(ancestor.parent()) {
909 Some(parent) => ancestor = parent.clone(),
910 None => {
911 error!("missing parent for file {:?}", ancestor.parent());
912 deleted = true;
913 break;
914 }
915 }
916 }
917
918 if !deleted {
919 for user_access_key in file.user_access_keys() {
920 if !user_access_key.deleted
921 && user_access_key.encrypted_for != user_access_key.encrypted_by
922 {
923 db.shared_files
924 .insert(Owner(user_access_key.encrypted_for), id)?;
925 }
926 }
927 }
928 }
929 }
930 ServerIndex::FileChildren => {
931 db.file_children.clear()?;
932 for id in db.metas.get().clone().keys() {
933 db.file_children.create_key(*id)?;
934 }
935 for (id, file) in db.metas.get().clone() {
936 db.file_children.insert(*file.parent(), id)?;
937 }
938 }
939 }
940 Ok(())
941 }
942}
943
944fn insert<K: Hash + Eq, V: Hash + Eq>(map: &mut HashMap<K, HashSet<V>>, k: K, v: V) {
945 map.entry(k).or_default().insert(v);
946}