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