aboutsummaryrefslogtreecommitdiffstats
path: root/src/access/envelope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/access/envelope.rs')
-rw-r--r--src/access/envelope.rs45
1 files changed, 39 insertions, 6 deletions
diff --git a/src/access/envelope.rs b/src/access/envelope.rs
index 7244a3b..1804b98 100644
--- a/src/access/envelope.rs
+++ b/src/access/envelope.rs
@@ -72,15 +72,39 @@ pub(crate) fn signed_paths(doc: &impl ReadDoc) -> Vec<Vec<String>> {
/// its `*` segments as `path` has them.
pub(crate) fn signed_path(signed: &[Vec<String>], path: &[String]) -> Option<Vec<String>> {
signed.iter().find_map(|pattern| {
- (path.len() >= pattern.len()
- && pattern
- .iter()
- .zip(path)
- .all(|(segment, key)| segment == "*" || segment == key))
- .then(|| path[..pattern.len()].to_vec())
+ (path.len() >= pattern.len() && agree(pattern, path))
+ .then(|| path[..pattern.len()].to_vec())
})
}
+/// Whether `path` is where a user-signed value goes, of `signed` (`signed_paths`).
+pub(crate) fn is_signed(signed: &[Vec<String>], path: &[String]) -> bool {
+ signed
+ .iter()
+ .any(|pattern| pattern.len() == path.len() && agree(pattern, path))
+}
+
+/// Whether a user-signed value of `signed` may be below `path` (`signed_paths`).
+pub(crate) fn above_signed(signed: &[Vec<String>], path: &[String]) -> bool {
+ signed
+ .iter()
+ .any(|pattern| pattern.len() > path.len() && agree(pattern, path))
+}
+
+/// Whether a write at `path` reaches a user-signed value of `signed` (`signed_paths`):
+/// at one, within one, or above one.
+pub(crate) fn reaches_signed(signed: &[Vec<String>], path: &[String]) -> bool {
+ signed.iter().any(|pattern| agree(pattern, path))
+}
+
+/// Whether `pattern` and `path` agree as far as both go (`*`: any key).
+fn agree(pattern: &[String], path: &[String]) -> bool {
+ pattern
+ .iter()
+ .zip(path)
+ .all(|(segment, key)| segment == "*" || segment == key)
+}
+
/// A signed value's payload.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct Payload {
@@ -280,5 +304,14 @@ mod tests {
signed_path(&signed, &path("_continuum/access/policy")),
Some(path("_continuum/access/policy"))
);
+ assert!(is_signed(&signed, &path("_continuum/users/alice")));
+ assert!(!is_signed(&signed, &path("_continuum/users/alice/caps")));
+ assert!(above_signed(&signed, &path("_continuum/users")));
+ assert!(above_signed(&signed, &path("a")));
+ assert!(!above_signed(&signed, &path("a/b")));
+ assert!(reaches_signed(&signed, &path("a")));
+ assert!(reaches_signed(&signed, &path("a/b/c")));
+ assert!(!reaches_signed(&signed, &path("a/c")));
+ assert!(!reaches_signed(&signed, &path("_continuum/members/x")));
}
}