aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/access.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/access.rs')
-rw-r--r--src/api/access.rs42
1 files changed, 36 insertions, 6 deletions
diff --git a/src/api/access.rs b/src/api/access.rs
index 11daf83..6d26139 100644
--- a/src/api/access.rs
+++ b/src/api/access.rs
@@ -146,18 +146,34 @@ pub(crate) fn prune(
}
/// A shallow read of `path` (`store::read_shallow`), its `entries` only those `access`
-/// lets its user read at least partly.
+/// lets its user read at least partly. One it may read only partly is only a way
+/// through to what it may: a map, shown as no more than that (no size); anything else
+/// there (a scalar no capability covers, a list, as a deep read leaves it out) isn't
+/// shown at all.
pub(crate) fn prune_shallow(mut value: JsonValue, path: &[String], access: &Access) -> JsonValue {
if access.visible(path) == Visible::All {
return value;
}
if let Some(entries) = value.get_mut("entries").and_then(JsonValue::as_object_mut) {
let mut child = path.to_vec();
- entries.retain(|key, _| {
+ entries.retain(|key, entry| {
child.push(key.clone());
- let visible = access.visible(&child) != Visible::Nothing;
+ let visible = access.visible(&child);
child.pop();
- visible
+ match visible {
+ Visible::All => true,
+ Visible::Nothing => false,
+ Visible::Partly => {
+ let way = entry
+ .get("type")
+ .and_then(JsonValue::as_str)
+ .is_some_and(|kind| kind == "map");
+ if way {
+ *entry = serde_json::json!({ "type": "map" });
+ }
+ way
+ }
+ }
});
let size = entries.len();
value["size"] = size.into();
@@ -558,12 +574,26 @@ mod tests {
#[test]
fn a_shallow_read_lists_the_way() {
let read = json!({ "type": "map", "size": 3,
- "entries": { "a": {}, "b": {}, "_continuum": {} } });
+ "entries": { "a": { "type": "map", "size": 4 }, "b": {},
+ "_continuum": { "type": "map", "size": 9 } } });
let reader = caps(&[("a/x", &["read"])]);
assert_eq!(
prune_shallow(read.clone(), &[], &reader),
- json!({ "type": "map", "size": 1, "entries": { "a": {} } })
+ json!({ "type": "map", "size": 1, "entries": { "a": { "type": "map" } } })
);
assert_eq!(prune_shallow(read.clone(), &[], &Access::Everything), read);
+ // At a `*`: a scalar beside the way, which no capability covers, isn't shown;
+ // what the user may read is, whole.
+ let data = json!({ "type": "map", "size": 3, "entries": {
+ "count": { "type": "number", "size": 8, "value": 42 },
+ "x": { "type": "map", "size": 2 },
+ "public": { "type": "string", "size": 2, "value": "hi" } } });
+ let wildcard = caps(&[("data/*/public", &["read"]), ("data/public", &["read"])]);
+ assert_eq!(
+ prune_shallow(data, &path("data"), &wildcard),
+ json!({ "type": "map", "size": 2, "entries": {
+ "x": { "type": "map" },
+ "public": { "type": "string", "size": 2, "value": "hi" } } })
+ );
}
}