mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-07 11:03:15 +00:00
fix(collab): build no repair for a batch refused for lack of permission (#1980)
This commit is contained in:
1 parent
25d2a201a9
commit
6f780211dd
2 files changed
+28
-2
No files matched your search
@@ -413,10 +413,14 @@ impl Server {
|
||||
// client learned what happened to it from the catch-up.
|
||||
ClientMsg::Changes { batch_id, .. } if self.issued.get(&from).is_some_and(|p| batch_id <= p.last_batch) => Vec::new(),
|
||||
ClientMsg::Changes { base_seq, batch_id, changes } => {
|
||||
let mut denied = true;
|
||||
let result = match self.limited.get(&from) {
|
||||
Some(Access::View) => Err(Error::Invalid(VIEW_ONLY.into())),
|
||||
Some(Access::Comment) if !changes.iter().all(Change::is_comment) => Err(Error::Invalid(COMMENT_ONLY.into())),
|
||||
_ => self.accept(from, base_seq, &changes),
|
||||
_ => {
|
||||
denied = false;
|
||||
self.accept(from, base_seq, &changes)
|
||||
}
|
||||
};
|
||||
if let Some(p) = self.issued.get_mut(&from) {
|
||||
p.note(batch_id, result.is_err());
|
||||
@@ -430,7 +434,9 @@ impl Server {
|
||||
}
|
||||
Err(e) => {
|
||||
self.note(Journal::Refused { client: from, batch_id });
|
||||
let fixes = self.fixes(&changes).unwrap_or_default();
|
||||
// A refusal for lack of permission costs no repair: the client's confirmed copy
|
||||
// already is the server's state, so the fixes would only repeat it.
|
||||
let fixes = if denied { Vec::new() } else { self.fixes(&changes).unwrap_or_default() };
|
||||
vec![Outgoing::To(from, ServerMsg::Reject { batch_id, reason: reason(&e), fixes })]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,26 @@ fn deleted_nodes_can_come_back_but_ids_are_never_handed_out_twice() {
|
||||
assert_eq!(s.document(), gone.document());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_viewers_refused_deletion_gets_no_repair() {
|
||||
let (d, _, frame) = doc();
|
||||
let mut s = Server::new(d, "tok", Limits::default());
|
||||
let (id, out) = s.join_as(hello("tok"), crate::message::Access::View).unwrap();
|
||||
let Some(Outgoing::To(_, welcome)) = out.into_iter().next() else { panic!() };
|
||||
let mut v = Client::join(welcome).unwrap();
|
||||
let del = edit(&mut v, |d| d.remove(frame).unwrap());
|
||||
let (reason, fixes) = rejected(
|
||||
&mut s,
|
||||
id,
|
||||
match del {
|
||||
ClientMsg::Changes { changes, .. } => changes,
|
||||
_ => panic!(),
|
||||
},
|
||||
);
|
||||
assert_eq!(reason, crate::VIEW_ONLY);
|
||||
assert!(fixes.is_empty(), "{fixes:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixes_roll_a_rejected_client_back_to_the_server_state() {
|
||||
let (d, _, frame) = doc();
|
||||
|
||||
Reference in new issue
Block a user