WW-4858 test(json): cover nested-leaf accepted-name and include patterns (#1783)

Add two tests to JSONInterceptorTest exercising the nested-object path for
the name/value filtering added in WW-4858:

- testAcceptedNamePatternRejectsNestedKey: accepted name patterns are raw
  full-match regexes with no hierarchy expansion, so the intermediate node
  ("bean") must itself match an accepted pattern or the whole subtree is
  dropped before the leaf is visited.
- testIncludePropertiesAppliedToNestedInputWhenEnabled: include patterns do
  expand across the hierarchy, so "bean.stringField" also matches the
  intermediate "bean" and the nested leaf populates while the excluded
  sibling "bean.intField" is dropped.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Lukasz Lenart
2026-07-14 13:31:06 +02:00
committed by GitHub
parent b70ecc8e15
commit 40fcae3101
@@ -770,6 +770,31 @@ public class JSONInterceptorTest extends StrutsTestCase {
assertEquals(0, action.getBean().getIntField());
}
public void testAcceptedNamePatternRejectsNestedKey() throws Exception {
this.request.setContent("{\"bean\": {\"stringField\": \"keep\", \"intField\": 42}}".getBytes());
this.request.addHeader("Content-Type", "application/json");
JSONInterceptor interceptor = createInterceptor();
org.apache.struts2.security.DefaultAcceptedPatternsChecker accepted =
new org.apache.struts2.security.DefaultAcceptedPatternsChecker();
// Accept the intermediate node "bean" and the nested leaf "bean.stringField", but not
// "bean.intField". The intermediate node must itself match an accepted pattern, otherwise
// the whole subtree is dropped before the leaf is ever visited (accepted name patterns are
// raw full-match regexes with no hierarchy expansion, unlike include patterns).
accepted.setAcceptedPatterns("bean(\\.stringField)?");
interceptor.setAcceptedPatterns(accepted);
TestAction action = new TestAction();
this.invocation.setAction(action);
this.invocation.getStack().push(action);
interceptor.intercept(this.invocation);
assertNotNull(action.getBean());
assertEquals("keep", action.getBean().getStringField());
assertEquals(0, action.getBean().getIntField());
}
public void testExcludedValuePatternRejectsListElement() throws Exception {
this.request.setContent("{\"list\": [\"good\", \"badvalue\"]}".getBytes());
this.request.addHeader("Content-Type", "application/json");
@@ -905,6 +930,28 @@ public class JSONInterceptorTest extends StrutsTestCase {
assertEquals("b", action.getBar());
}
public void testIncludePropertiesAppliedToNestedInputWhenEnabled() throws Exception {
this.request.setContent("{\"bean\": {\"stringField\": \"keep\", \"intField\": 42}}".getBytes());
this.request.addHeader("Content-Type", "application/json");
JSONInterceptor interceptor = createInterceptor();
interceptor.setApplyPropertyFiltersToInput(true);
// Include patterns expand across the hierarchy: "bean.stringField" compiles patterns for
// both the intermediate node "bean" and the leaf "bean.stringField", so the nested leaf
// populates while the excluded sibling "bean.intField" is dropped.
interceptor.setIncludeProperties("bean\\.stringField");
TestAction action = new TestAction();
this.invocation.setAction(action);
this.invocation.getStack().push(action);
interceptor.intercept(this.invocation);
assertNotNull(action.getBean());
assertEquals("keep", action.getBean().getStringField());
assertEquals(0, action.getBean().getIntField());
}
@Override
protected void setUp() throws Exception {
super.setUp();