diff options
Diffstat (limited to 'src/access/rules.rs')
| -rw-r--r-- | src/access/rules.rs | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/src/access/rules.rs b/src/access/rules.rs index 96ee9d4..185996a 100644 --- a/src/access/rules.rs +++ b/src/access/rules.rs @@ -24,7 +24,8 @@ //! declared (`sealed_values`). //! //! In a swarm without a user registry (`access::registry`), whatever a user would need, -//! any member may. +//! any member may. A change written while the document had no policy (at its +//! dependencies) is judged by none: the rules hold from the policy on. use std::collections::BTreeSet; @@ -92,6 +93,12 @@ pub(crate) fn judge(doc: &Document, epoch: Epoch, change: &Change<'_>) -> Result }; } let at = At::new(doc, change.seen).ok_or(Refusal::Unready)?; + // Written while the document had no policy (or one this node doesn't know): judged + // as it was then, by none. History from before the policy stays as it is. + let policy = super::policy::of(&at); + if !policy.enforced() { + return Ok(()); + } let refuse = |why: String| Err(Refusal::Rule(why)); let Some(node) = change.committer else { return refuse("it names no node".to_owned()); @@ -161,7 +168,7 @@ pub(crate) fn judge(doc: &Document, epoch: Epoch, change: &Change<'_>) -> Result return refuse(format!("{} may not write {}", who(change), shown(path))); } } - if super::policy::of(&at).strict() { + if policy.strict() { signed_values(&at, change.ops).or_else(refuse)?; } let declared = super::sealed::declared(&at); @@ -332,6 +339,7 @@ mod tests { fn swarm(users: bool) -> Document { let mut doc = Document::new(); write(&mut doc, "_continuum/swarm", json!("s")); + write(&mut doc, "_continuum/access/policy", json!({"version": 1})); write(&mut doc, "_continuum/members/a", json!({"since": 1})); write(&mut doc, "_continuum/members/b", json!({"since": 1})); write( @@ -708,6 +716,31 @@ mod tests { assert!(judged(vec![op("notes/x", Action::PutString("plain".to_owned()))]).is_ok()); } + /// Written before the policy: judged by none, whatever it does; from the policy on, + /// by the rules. + #[test] + fn before_the_policy() { + let mut doc = Document::new(); + write(&mut doc, "_continuum/swarm", json!("s")); + write(&mut doc, "_continuum/members/a", json!({"since": 1})); + write( + &mut doc, + "_continuum/users/alice", + registry::entry("a", 1, &[]), + ); + assert!(judged(&doc, "stranger", Some("mallory"), &["notes/x"]).is_ok()); + write(&mut doc, "_continuum/access/policy", json!({"version": 1})); + assert!(refused(judged( + &doc, + "stranger", + Some("mallory"), + &["notes/x"] + ))); + // A policy this node doesn't know: judged by none either. + write(&mut doc, "_continuum/access/policy", json!({"version": 9})); + assert!(judged(&doc, "stranger", Some("mallory"), &["notes/x"]).is_ok()); + } + /// Roots: the first change of a swarm's first epoch, a later epoch's snapshot. #[test] fn roots() { |
