This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5627-cookie-authorization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit cea95636907c0fa852731a93f3f0dc5ec5fdd3ab
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat May 9 19:15:49 2026 +0200

    WW-5627 cover CookieInterceptor authorization matrix in 
CookieInterceptorAnnotationTest
---
 .../CookieInterceptorAnnotationTest.java           | 127 +++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git 
a/core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorAnnotationTest.java
 
b/core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorAnnotationTest.java
index dc965a029..4d794ecbf 100644
--- 
a/core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorAnnotationTest.java
+++ 
b/core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorAnnotationTest.java
@@ -21,6 +21,7 @@ package org.apache.struts2.interceptor;
 import jakarta.servlet.http.Cookie;
 import org.apache.struts2.ActionContext;
 import org.apache.struts2.ActionSupport;
+import org.apache.struts2.ModelDriven;
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsInternalTestCase;
 import org.apache.struts2.action.Action;
@@ -28,8 +29,12 @@ import 
org.apache.struts2.interceptor.parameter.ParameterAuthorizer;
 import org.apache.struts2.interceptor.parameter.StrutsParameter;
 import org.apache.struts2.interceptor.parameter.StrutsParameterAuthorizer;
 import org.apache.struts2.mock.MockActionInvocation;
+import org.apache.struts2.util.ValueStack;
 import org.springframework.mock.web.MockHttpServletRequest;
 
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
 public class CookieInterceptorAnnotationTest extends StrutsInternalTestCase {
 
     private CookieInterceptor interceptor;
@@ -58,6 +63,101 @@ public class CookieInterceptorAnnotationTest extends 
StrutsInternalTestCase {
         
assertNull(ActionContext.getContext().getValueStack().findValue("unannotated"));
     }
 
+    public void testRequireAnnotations_annotatedSetter_isInjected() throws 
Exception {
+        configureRequireAnnotations(true, false);
+        AnnotatedAction action = new AnnotatedAction();
+        invokeWithCookies(action, new Cookie("annotated", "v"));
+
+        assertEquals("v", action.getAnnotated());
+        assertEquals("v", 
ActionContext.getContext().getValueStack().findValue("annotated"));
+    }
+
+    public void testRequireAnnotations_annotatedNestedPath_isInjected() throws 
Exception {
+        configureRequireAnnotations(true, false);
+        AnnotatedAction action = new AnnotatedAction();
+        action.setNested(new NestedBean());
+        invokeWithCookies(action, new Cookie("nested.field", "v"));
+
+        assertEquals("v", action.getNested().getField());
+    }
+
+    public void testRequireAnnotations_unannotatedNestedPath_isSkipped() 
throws Exception {
+        configureRequireAnnotations(true, false);
+        AnnotatedAction action = new AnnotatedAction();
+        action.setUnannotatedNested(new NestedBean());
+        invokeWithCookies(action, new Cookie("unannotatedNested.field", "v"));
+
+        assertNull(action.getUnannotatedNested().getField());
+    }
+
+    public void testRequireAnnotations_transitionMode_exemptsDepthZero() 
throws Exception {
+        configureRequireAnnotations(true, true);
+        AnnotatedAction action = new AnnotatedAction();
+        invokeWithCookies(action, new Cookie("unannotated", "v"));
+
+        assertEquals("v", action.getUnannotated());
+    }
+
+    public void testDefaultConfig_unannotatedSetter_stillInjected() throws 
Exception {
+        configureRequireAnnotations(false, false);
+        AnnotatedAction action = new AnnotatedAction();
+        invokeWithCookies(action, new Cookie("unannotated", "v"));
+
+        assertEquals("v", action.getUnannotated());
+    }
+
+    public void testRequireAnnotations_modelDriven_exemptsModel() throws 
Exception {
+        configureRequireAnnotations(true, false);
+        ModelDrivenAction action = new ModelDrivenAction();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setCookies(new Cookie("name", "v"));
+        ServletActionContext.setRequest(request);
+        // ModelDriven contract: the model is pushed on top of the action.
+        ActionContext.getContext().getValueStack().push(action);
+        ActionContext.getContext().getValueStack().push(action.getModel());
+
+        MockActionInvocation invocation = new MockActionInvocation();
+        invocation.setAction(action);
+        invocation.setInvocationContext(ActionContext.getContext());
+        invocation.setResultCode(Action.SUCCESS);
+
+        interceptor.intercept(invocation);
+
+        assertEquals("v", action.getModel().getName());
+    }
+
+    public void 
testSubclassOverridingDeprecatedHook_stillSeesAuthorizationGate() throws 
Exception {
+        configureRequireAnnotations(true, false);
+        AtomicInteger calls = new AtomicInteger();
+        @SuppressWarnings("deprecation")
+        CookieInterceptor subclass = new CookieInterceptor() {
+            @Override
+            protected void populateCookieValueIntoStack(String name, String 
value, Map<String, String> map, ValueStack stack) {
+                calls.incrementAndGet();
+                super.populateCookieValueIntoStack(name, value, map, stack);
+            }
+        };
+        container.inject(subclass);
+        subclass.setCookiesName("*");
+
+        AnnotatedAction action = new AnnotatedAction();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        req.setCookies(new Cookie("annotated", "ok"), new 
Cookie("unannotated", "blocked"));
+        ServletActionContext.setRequest(req);
+        ActionContext.getContext().getValueStack().push(action);
+
+        MockActionInvocation invocation = new MockActionInvocation();
+        invocation.setAction(action);
+        invocation.setInvocationContext(ActionContext.getContext());
+        invocation.setResultCode(Action.SUCCESS);
+        subclass.intercept(invocation);
+
+        assertEquals("ok", action.getAnnotated());
+        assertNull(action.getUnannotated());
+        assertEquals("4-arg hook should be invoked exactly once (only for the 
authorized cookie)", 1, calls.get());
+    }
+
     private void configureRequireAnnotations(boolean require, boolean 
transitionMode) {
         StrutsParameterAuthorizer authorizer = (StrutsParameterAuthorizer) 
container.getInstance(ParameterAuthorizer.class);
         authorizer.setRequireAnnotations(Boolean.toString(require));
@@ -81,6 +181,8 @@ public class CookieInterceptorAnnotationTest extends 
StrutsInternalTestCase {
     public static class AnnotatedAction extends ActionSupport {
         private String annotated;
         private String unannotated;
+        private NestedBean nested;
+        private NestedBean unannotatedNested;
 
         @StrutsParameter
         public void setAnnotated(String v) { this.annotated = v; }
@@ -88,5 +190,30 @@ public class CookieInterceptorAnnotationTest extends 
StrutsInternalTestCase {
 
         public void setUnannotated(String v) { this.unannotated = v; }
         public String getUnannotated() { return unannotated; }
+
+        @StrutsParameter(depth = 1)
+        public NestedBean getNested() { return nested; }
+        public void setNested(NestedBean nested) { this.nested = nested; }
+
+        public NestedBean getUnannotatedNested() { return unannotatedNested; }
+        public void setUnannotatedNested(NestedBean v) { 
this.unannotatedNested = v; }
+    }
+
+    public static class NestedBean {
+        private String field;
+        public String getField() { return field; }
+        public void setField(String f) { this.field = f; }
+    }
+
+    public static class ModelDrivenAction extends ActionSupport implements 
ModelDriven<Model> {
+        private final Model model = new Model();
+        @Override
+        public Model getModel() { return model; }
+    }
+
+    public static class Model {
+        private String name;
+        public String getName() { return name; }
+        public void setName(String n) { this.name = n; }
     }
 }

Reply via email to