1   /* Copyright 2004, 2005 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.acegisecurity.captcha;
16  
17  import junit.framework.TestCase;
18  
19  import org.acegisecurity.ConfigAttributeDefinition;
20  import org.acegisecurity.MockFilterChain;
21  import org.acegisecurity.SecurityConfig;
22  import org.acegisecurity.context.SecurityContextHolder;
23  import org.acegisecurity.intercept.web.FilterInvocation;
24  
25  import org.springframework.mock.web.MockHttpServletRequest;
26  import org.springframework.mock.web.MockHttpServletResponse;
27  
28  import java.io.IOException;
29  
30  import javax.servlet.ServletException;
31  
32  
33  /***
34   * Tests {@link org.acegisecurity.captcha.CaptchaChannelProcessorTemplate}
35   *
36   * @author marc antoine Garrigue
37   * @version $Id: CaptchaChannelProcessorTemplateTests.java,v 1.2 2005/11/17 00:56:08 benalex Exp $
38   */
39  public class CaptchaChannelProcessorTemplateTests extends TestCase {
40      //~ Methods ================================================================
41  
42      public void testContextRedirect() throws Exception {
43          CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
44          processor.setKeyword("X");
45  
46          ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
47          cad.addConfigAttribute(new SecurityConfig("Y"));
48  
49          CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
50          SecurityContextHolder.setContext(context);
51  
52          CaptchaEntryPoint epoint = new CaptchaEntryPoint();
53          epoint.setCaptchaFormUrl("/jcaptcha.do");
54          epoint.setIncludeOriginalRequest(false);
55  
56          processor.setEntryPoint(epoint);
57  
58          MockHttpServletRequest request = new MockHttpServletRequest();
59          request.setQueryString("info=true");
60          request.setServerName("localhost");
61          request.setContextPath("/demo");
62          request.setServletPath("/restricted");
63          request.setScheme("http");
64          request.setServerPort(8000);
65  
66          MockHttpServletResponse response = new MockHttpServletResponse();
67          MockFilterChain chain = new MockFilterChain();
68          FilterInvocation fi = new FilterInvocation(request, response, chain);
69  
70          processor.decide(fi, cad);
71          assertEquals(null, response.getRedirectedUrl());
72          processor.setKeyword("Y");
73          response = decideWithNewResponse(cad, processor, request);
74          assertEquals("http://localhost:8000/demo/jcaptcha.do",
75              response.getRedirectedUrl());
76          context.setHuman();
77          response = decideWithNewResponse(cad, processor, request);
78          assertEquals(null, response.getRedirectedUrl());
79      }
80  
81      public void testDecideRejectsNulls() throws Exception {
82          CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
83          processor.setEntryPoint(new CaptchaEntryPoint());
84          processor.setKeyword("X");
85          processor.afterPropertiesSet();
86  
87          try {
88              processor.decide(null, null);
89              fail("Should have thrown IllegalArgumentException");
90          } catch (IllegalArgumentException expected) {
91              assertTrue(true);
92          }
93      }
94  
95      public void testGettersSetters() {
96          CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
97          assertEquals(null, processor.getKeyword());
98          processor.setKeyword("X");
99          assertEquals("X", processor.getKeyword());
100 
101         assertEquals(0, processor.getThresold());
102         processor.setThresold(1);
103         assertEquals(1, processor.getThresold());
104 
105         assertTrue(processor.getEntryPoint() == null);
106         processor.setEntryPoint(new CaptchaEntryPoint());
107         assertTrue(processor.getEntryPoint() != null);
108     }
109 
110     public void testIncrementRequestCount() throws Exception {
111         CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
112         processor.setKeyword("X");
113 
114         ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
115         cad.addConfigAttribute(new SecurityConfig("X"));
116 
117         CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
118         SecurityContextHolder.setContext(context);
119 
120         CaptchaEntryPoint epoint = new CaptchaEntryPoint();
121         epoint.setCaptchaFormUrl("/jcaptcha.do");
122         processor.setEntryPoint(epoint);
123 
124         MockHttpServletRequest request = new MockHttpServletRequest();
125         request.setQueryString("info=true");
126         request.setServerName("localhost");
127         request.setContextPath("/demo");
128         request.setServletPath("/restricted");
129         request.setScheme("http");
130         request.setServerPort(8000);
131 
132         MockHttpServletResponse response = new MockHttpServletResponse();
133         MockFilterChain chain = new MockFilterChain();
134         FilterInvocation fi = new FilterInvocation(request, response, chain);
135 
136         processor.decide(fi, cad);
137         assertEquals(0, context.getHumanRestrictedResourcesRequestsCount());
138         context.setHuman();
139         decideWithNewResponse(cad, processor, request);
140         assertEquals(1, context.getHumanRestrictedResourcesRequestsCount());
141         decideWithNewResponse(cad, processor, request);
142         assertEquals(2, context.getHumanRestrictedResourcesRequestsCount());
143         processor.setKeyword("Y");
144         decideWithNewResponse(cad, processor, request);
145         assertEquals(2, context.getHumanRestrictedResourcesRequestsCount());
146         context = new CaptchaSecurityContextImpl();
147         decideWithNewResponse(cad, processor, request);
148         assertEquals(0, context.getHumanRestrictedResourcesRequestsCount());
149     }
150 
151     public void testMissingEntryPoint() throws Exception {
152         CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
153         processor.setEntryPoint(null);
154 
155         try {
156             processor.afterPropertiesSet();
157             fail("Should have thrown IllegalArgumentException");
158         } catch (IllegalArgumentException expected) {
159             assertEquals("entryPoint required", expected.getMessage());
160         }
161     }
162 
163     public void testMissingKeyword() throws Exception {
164         CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
165         processor.setKeyword(null);
166 
167         try {
168             processor.afterPropertiesSet();
169             fail("Should have thrown IllegalArgumentException");
170         } catch (IllegalArgumentException expected) {}
171 
172         processor.setKeyword("");
173 
174         try {
175             processor.afterPropertiesSet();
176             fail("Should have thrown IllegalArgumentException");
177         } catch (IllegalArgumentException expected) {}
178     }
179 
180     public void testSupports() {
181         CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
182         processor.setKeyword("X");
183         assertTrue(processor.supports(
184                 new SecurityConfig(processor.getKeyword())));
185 
186         assertTrue(processor.supports(new SecurityConfig("X")));
187 
188         assertFalse(processor.supports(null));
189 
190         assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
191     }
192 
193     private MockHttpServletResponse decideWithNewResponse(
194         ConfigAttributeDefinition cad,
195         CaptchaChannelProcessorTemplate processor,
196         MockHttpServletRequest request) throws IOException, ServletException {
197         MockHttpServletResponse response;
198         MockFilterChain chain;
199         FilterInvocation fi;
200         response = new MockHttpServletResponse();
201         chain = new MockFilterChain();
202         fi = new FilterInvocation(request, response, chain);
203         processor.decide(fi, cad);
204 
205         return response;
206     }
207 
208     //~ Inner Classes ==========================================================
209 
210     private class TestHumanityCaptchaChannelProcessor
211         extends CaptchaChannelProcessorTemplate {
212         boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
213             return context.isHuman();
214         }
215     }
216 }