lockbook_shared/
server_ops.rs1use crate::clock::get_time;
2use crate::file_like::FileLike;
3use crate::file_metadata::FileDiff;
4use crate::lazy::{LazyStaged1, LazyTree};
5use crate::server_file::{IntoServerFile, ServerFile};
6
7use crate::server_tree::ServerTree;
8use crate::signed_file::SignedFile;
9use crate::tree_like::TreeLike;
10use crate::{SharedErrorKind, SharedResult};
11
12type LazyServerStaged1<'a> = LazyStaged1<ServerTree<'a>, Vec<ServerFile>>;
13
14impl<'a> LazyTree<ServerTree<'a>> {
15 pub fn stage_diff(
18 mut self, changes: Vec<FileDiff<SignedFile>>,
19 ) -> SharedResult<LazyServerStaged1<'a>> {
20 self.tree.ids.extend(changes.iter().map(|diff| *diff.id()));
21
22 for change in &changes {
24 if let Some(old) = &change.old {
25 if old.id() != change.new.id() {
26 return Err(SharedErrorKind::DiffMalformed.into());
27 }
28 }
29 }
30
31 for change in &changes {
33 match &change.old {
34 Some(old) => {
35 if old.timestamped_value.value.document_hmac
36 != change.new.timestamped_value.value.document_hmac
37 {
38 return Err(SharedErrorKind::HmacModificationInvalid.into());
39 }
40 }
41 None => {
42 if change.new.timestamped_value.value.document_hmac.is_some() {
43 return Err(SharedErrorKind::HmacModificationInvalid.into());
44 }
45 }
46 }
47 }
48
49 for change in &changes {
51 match &change.old {
52 Some(old) => {
53 let current = &self
54 .maybe_find(old.id())
55 .ok_or(SharedErrorKind::OldFileNotFound)?
56 .file;
57 if current != old {
58 return Err(SharedErrorKind::OldVersionIncorrect.into());
59 }
60 }
61 None => {
62 if self.maybe_find(change.new.id()).is_some() {
63 return Err(SharedErrorKind::OldVersionRequired.into());
64 }
65 }
66 }
67 }
68
69 let now = get_time().0 as u64;
70 let changes = changes
71 .into_iter()
72 .map(|change| change.new.add_time(now))
73 .collect();
74
75 Ok(self.stage(changes))
76 }
77}