diff --git a/support/inspect/src/defer.rs b/support/inspect/src/defer.rs index 5928bdc9e9..bcf0aeec1a 100644 --- a/support/inspect/src/defer.rs +++ b/support/inspect/src/defer.rs @@ -69,6 +69,7 @@ impl Request<'_> { node: send, sensitivity: self.params.root.sensitivity, number_format: self.params.number_format, + parent_sensitivity: self.params.parent_sensitivity, })) } } @@ -100,6 +101,7 @@ struct DeferredInner { depth: usize, node: mesh::OneshotSender, sensitivity: SensitivityLevel, + parent_sensitivity: SensitivityLevel, number_format: NumberFormat, } @@ -156,6 +158,7 @@ impl Deferred { path_start: 0, depth: self.0.depth, number_format: self.0.number_format, + parent_sensitivity: self.0.parent_sensitivity, } } diff --git a/support/inspect/src/initiate.rs b/support/inspect/src/initiate.rs index 37a44cd02e..f3d5481571 100644 --- a/support/inspect/src/initiate.rs +++ b/support/inspect/src/initiate.rs @@ -426,6 +426,7 @@ impl<'a> InspectionBuilder<'a> { path_start: 0, depth: depth_with_root, number_format: NumberFormat::default(), + parent_sensitivity: SensitivityLevel::Unspecified, }; (params, path_node_count(root.full_path)) } diff --git a/support/inspect/src/lib.rs b/support/inspect/src/lib.rs index 2cc5fc4987..86b78d7c0b 100644 --- a/support/inspect/src/lib.rs +++ b/support/inspect/src/lib.rs @@ -497,6 +497,7 @@ struct RequestParams<'a> { path_start: usize, depth: usize, number_format: NumberFormat, + parent_sensitivity: SensitivityLevel, } impl<'a> RequestParams<'a> { @@ -580,9 +581,9 @@ enum Action<'a> { } impl<'a> Action<'a> { - // Determine which action to take for the field with `name`, given the + // Determine which action to take for the child field `child`, given the // remaining `path` and the remaining `depth`. - fn eval(child: Child<'a>, params: &RequestParams<'_>, path: &str) -> Self { + fn eval(child: &Child<'a>, params: &RequestParams<'_>, path: &str) -> Self { if params.depth == 0 { // Don't return any subfields if the depth is exhausted, since depth // exhausted will be reported for the current node. @@ -815,7 +816,7 @@ impl Response<'_> { fn child_request(&mut self, child: Child<'_>) -> Option> { let children = &mut **self.children.as_mut()?; - let action = Action::eval(child, &self.params, self.path_without_slashes); + let action = Action::eval(&child, &self.params, self.path_without_slashes); match action { Action::Process { name, @@ -833,7 +834,9 @@ impl Response<'_> { RequestParams { path_start: new_path_start, depth: new_depth, - ..self.params + root: self.params.root, + number_format: self.params.number_format, + parent_sensitivity: child.sensitivity, } .request(&mut entry.node), ) @@ -1018,6 +1021,13 @@ assert_eq!( let entry = children.last_mut().unwrap(); Some(self.params.request(&mut entry.node)) } + + /// Gets the sensitivity level of the parent node of this request. This is + /// useful for wrappers around fields that wish to inherit the sensitivity + /// level of their parent node. + pub fn parent_sensitivity(&self) -> SensitivityLevel { + self.params.parent_sensitivity + } } impl<'a> RequestParams<'a> { @@ -1856,7 +1866,7 @@ where fn inspect(&self, req: Request<'_>) { let mut resp = req.respond(); for (name, value) in self.0.clone() { - resp.field(&name.to_string(), value); + resp.sensitivity_field(&name.to_string(), resp.parent_sensitivity(), value); } } } @@ -3269,6 +3279,72 @@ mod tests { ); } + #[test] + fn test_inherit_sensitivity() { + fn inspect_sync( + path: &str, + sensitivity: Option, + obj: impl Inspect, + ) -> Node { + let mut result = InspectionBuilder::new(path) + .sensitivity(sensitivity) + .inspect(&obj); + result.resolve().now_or_never(); + result.results() + } + + #[derive(Inspect)] + struct Indexed { + #[inspect(safe, iter_by_index)] + a: Vec, + } + + #[derive(Inspect)] + struct Baz { + #[inspect(safe)] + a: u32, + #[inspect(safe)] + b: Qux, + } + + #[derive(Inspect)] + struct Qux { + #[inspect(sensitive)] + a: u32, + b: u32, + } + + let obj = Indexed { + a: vec![ + Baz { + a: 0, + b: Qux { a: 0, b: 0 }, + }, + Baz { + a: 0, + b: Qux { a: 0, b: 0 }, + }, + ], + }; + + expected_node( + inspect_sync("", Some(SensitivityLevel::Safe), &obj), + expect!([r#" + { + a: { + 0: { + a: 0, + b: {}, + }, + 1: { + a: 0, + b: {}, + }, + }, + }|{"a":{"0":{"a":0,"b":{}},"1":{"a":0,"b":{}}}}"#]), + ); + } + /// Test that you can update via AtomicMut. #[test] fn test_atomic_mut() {