diff options
| -rw-r--r-- | docs/access.md | 1 | ||||
| -rw-r--r-- | src/access/rules.rs | 9 |
2 files changed, 9 insertions, 1 deletions
diff --git a/docs/access.md b/docs/access.md index 1ee9994..8443394 100644 --- a/docs/access.md +++ b/docs/access.md @@ -224,6 +224,7 @@ revocation since refuses nothing it allowed then, and every node judges alike. * A remake's decision by the coordinator its proposal names; the rest of a record by any member. * A user's tokens revoked by that user too (logging out). +* A member's forget record cancelled by that member too (forgotten while alive). * Everything else, protocol data or not, by a user the registry lets write there. * A node that isn't a member may only register itself; a banned node nothing (Banning a node, below). So a node registers before anything else it writes, through the API diff --git a/src/access/rules.rs b/src/access/rules.rs index 2aed4b8..96ee9d4 100644 --- a/src/access/rules.rs +++ b/src/access/rules.rs @@ -15,7 +15,8 @@ //! that member only (removing an entry also by a user who may write there); epochs //! and the swarm ID in a root only; a remake's decision by the coordinator its //! proposal names, the rest of a record by any member; a user's tokens revoked by that -//! user too (logging out); the rest by a user who may write there. +//! user too (logging out); a member's forget record by that member too (cancelling it, +//! alive); the rest by a user who may write there. //! * User data: by a user who may write there. //! * Under a strict policy (`access::policy`), the values their users sign //! (`access::envelope`) only as they signed them (`signed_values`). @@ -134,6 +135,8 @@ pub(crate) fn judge(doc: &Document, epoch: Epoch, change: &Change<'_>) -> Result (Some(meta::EPOCHS | meta::SWARM), _) => false, // Logging out: a user revokes its own tokens (`POST /auth/logout`). (Some(meta::LOGOUTS), Some(owner)) => change.user == Some(owner) || user_may(path), + // A node forgotten while alive cancels its own record (`swarm::peer::forget`). + (Some(meta::FORGOTTEN), Some(owner)) => owner == node || user_may(path), (Some(meta::REMAKES), Some(id)) => match path.get(3).map(String::as_str) { // Its coordinator's; or a record carried into a new epoch whole, by the // node that coordinated it (`remake::switch`): its proposal written with it. @@ -431,6 +434,10 @@ mod tests { let tokens = "_continuum/logouts/bob"; assert!(judged(&doc, "a", Some("bob"), &[tokens]).is_ok()); assert!(refused(judged(&doc, "a", Some("alice"), &[tokens]))); + // A forget record: cancelled by the node it names, not by another. + let forgotten = "_continuum/forgotten/a"; + assert!(judged(&doc, "a", None, &[forgotten]).is_ok()); + assert!(refused(judged(&doc, "b", None, &[forgotten]))); } /// A banned node's changes: refused, as the ban stood when they were made. |
