| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.sling.auth.form.impl; |
| |
| import static org.easymock.EasyMock.cmpEq; |
| import static org.easymock.EasyMock.createMock; |
| import static org.easymock.EasyMock.expect; |
| import static org.easymock.EasyMock.expectLastCall; |
| import static org.easymock.EasyMock.replay; |
| import static org.easymock.EasyMock.verify; |
| import static org.junit.Assert.assertEquals; |
| |
| import java.io.File; |
| import java.lang.reflect.Method; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.apache.sling.api.auth.Authenticator; |
| import org.apache.sling.auth.core.spi.AuthenticationInfo; |
| import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler; |
| import org.hamcrest.Description; |
| import org.hamcrest.text.StringStartsWith; |
| import org.jmock.Expectations; |
| import org.jmock.Mockery; |
| import org.jmock.api.Action; |
| import org.jmock.api.Invocation; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.osgi.framework.BundleContext; |
| import org.powermock.api.easymock.PowerMock; |
| import org.powermock.api.support.membermodification.MemberMatcher; |
| import org.powermock.core.classloader.annotations.PrepareForTest; |
| import org.powermock.modules.junit4.PowerMockRunner; |
| |
| @RunWith(PowerMockRunner.class) |
| @PrepareForTest(FormAuthenticationHandler.class) |
| public class FormAuthenticationHandlerTest { |
| |
| @Test public void test_getTokenFile() { |
| final File root = new File("bundle999").getAbsoluteFile(); |
| final SlingHomeAction slingHome = new SlingHomeAction(); |
| slingHome.setSlingHome(new File("sling").getAbsolutePath()); |
| |
| Mockery context = new Mockery(); |
| final BundleContext bundleContext = context.mock(BundleContext.class); |
| |
| context.checking(new Expectations() { |
| { |
| // mock access to sling.home framework property |
| allowing(bundleContext).getProperty("sling.home"); |
| will(slingHome); |
| |
| // mock no data file support with file names starting with sl |
| allowing(bundleContext).getDataFile( |
| with(new StringStartsWith("sl"))); |
| will(returnValue(null)); |
| |
| // mock data file support for any other name |
| allowing(bundleContext).getDataFile(with(any(String.class))); |
| will(new RVA(root)); |
| } |
| }); |
| |
| final FormAuthenticationHandler handler = new FormAuthenticationHandler(); |
| |
| // test files relative to bundle context |
| File relFile0 = handler.getTokenFile("", bundleContext); |
| assertEquals(root, relFile0); |
| |
| String relName1 = "rel/path"; |
| File relFile1 = handler.getTokenFile(relName1, bundleContext); |
| assertEquals(new File(root, relName1), relFile1); |
| |
| // test file relative to sling.home if no data file support |
| String relName2 = "sl/rel_to_sling.home"; |
| File relFile2 = handler.getTokenFile(relName2, bundleContext); |
| assertEquals(new File(slingHome.getSlingHome(), relName2), relFile2); |
| |
| // test file relative to current working directory |
| String relName3 = "sl/test"; |
| slingHome.setSlingHome(null); |
| File relFile3 = handler.getTokenFile(relName3, bundleContext); |
| assertEquals(new File(relName3).getAbsoluteFile(), relFile3); |
| |
| // test absolute file return |
| File absFile = new File("test").getAbsoluteFile(); |
| File absFile0 = handler.getTokenFile(absFile.getPath(), bundleContext); |
| assertEquals(absFile, absFile0); |
| } |
| |
| @Test public void test_getUserid() { |
| final FormAuthenticationHandler handler = new FormAuthenticationHandler(); |
| assertEquals(null, handler.getUserId(null)); |
| assertEquals(null, handler.getUserId("")); |
| assertEquals(null, handler.getUserId("field0")); |
| assertEquals(null, handler.getUserId("field0@field1")); |
| assertEquals("field3", handler.getUserId("field0@field1@field3")); |
| assertEquals("field3@field4", handler.getUserId("field0@field1@field3@field4")); |
| } |
| |
| /** |
| * Test for SLING-3443 Parameter based redirection should only handle relative paths |
| * @throws Exception PowerMock.expectPrivate throws Exception and UrlEncoder.encode |
| * throws UnsupportedEncodingException |
| * @since 1.0.6 |
| */ |
| @Test public void testRedirectionAfterLogin() throws Exception { |
| // Create mocks |
| final HttpServletRequest request = createMock(HttpServletRequest.class); |
| final HttpServletResponse response = createMock(HttpServletResponse.class); |
| final AuthenticationInfo authenticationInfo = createMock(AuthenticationInfo.class); |
| |
| // Use PowerMock to mock private method |
| final String methodName = "refreshAuthData"; |
| final FormAuthenticationHandler authenticationHandler = PowerMock.createPartialMock(FormAuthenticationHandler.class, |
| methodName); |
| final Method[] methods = MemberMatcher.methods(FormAuthenticationHandler.class, methodName); |
| PowerMock.expectPrivate(authenticationHandler, methods[0], request, response, authenticationInfo); |
| |
| // Mock the static method since we are just unit testing the authentication succeeded flow |
| PowerMock.mockStatic(DefaultAuthenticationFeedbackHandler.class); |
| expect(DefaultAuthenticationFeedbackHandler.handleRedirect(request, response)).andReturn(false); |
| |
| // Mocks the Authenticator.LOGIN_RESOURCE attribute |
| final String url = "http://www.blah.com"; |
| expect(request.getAttribute(Authenticator.LOGIN_RESOURCE)).andReturn(url); |
| |
| // Mocks the HttpServletRequest and HttpServletResponse object |
| expect(request.getMethod()).andReturn("POST"); |
| expect(request.getRequestURI()).andReturn("http://blah/blah/j_security_check"); |
| String contextPath = "/blah"; |
| expect(request.getContextPath()).andReturn(contextPath).anyTimes(); |
| expect(response.isCommitted()).andReturn(false); |
| |
| // Mocking method with void return type |
| response.resetBuffer(); |
| expectLastCall().once(); |
| |
| // The request should be redirected to the context root rather than the |
| // passing the parameter directly |
| response.sendRedirect(cmpEq(contextPath)); |
| |
| // Replay the mocks |
| replay(request); |
| replay(response); |
| replay(authenticationInfo); |
| replay(authenticationHandler); |
| |
| // Test the method |
| authenticationHandler.authenticationSucceeded(request, response, authenticationInfo); |
| |
| // Verify mocks |
| verify(request, response, authenticationInfo, authenticationHandler); |
| } |
| |
| /** |
| * The <code>RVA</code> action returns a file relative to some root file as |
| * requested by the first parameter of the invocation, expecting the first |
| * parameter to be a string. |
| */ |
| private static class RVA implements Action { |
| |
| private final File root; |
| |
| RVA(final File root) { |
| this.root = root; |
| } |
| |
| public Object invoke(Invocation invocation) throws Throwable { |
| String data = (String) invocation.getParameter(0); |
| if (data.startsWith("/")) { |
| data = data.substring(1); |
| } |
| return new File(root, data); |
| } |
| |
| public void describeTo(Description description) { |
| description.appendText("returns new File(root, arg0)"); |
| } |
| } |
| |
| /** |
| * The <code>SlingHomeAction</code> action returns the current value of the |
| * <code>slingHome</code> field on all invocations |
| */ |
| private static class SlingHomeAction implements Action { |
| private String slingHome; |
| |
| public void setSlingHome(String slingHome) { |
| this.slingHome = slingHome; |
| } |
| |
| public String getSlingHome() { |
| return slingHome; |
| } |
| |
| public Object invoke(Invocation invocation) throws Throwable { |
| return slingHome; |
| } |
| |
| public void describeTo(Description description) { |
| description.appendText("returns " + slingHome); |
| } |
| } |
| } |