/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015 ForgeRock AS.
*/
package com.sun.identity.setup;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.testng.Assert.fail;
import java.io.File;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mockito.Mock;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.sun.identity.common.configuration.ConfigurationException;
import com.sun.identity.shared.Constants;
public class AMSetupFilterTest {
private AMSetupFilter setupFilter;
@Mock
private AMSetupManager setupManager;
private Injector injector;
@BeforeClass
public void setupClass() {
injector = mock(Injector.class);
SystemStartupInjectorHolder.initialise(injector);
}
@BeforeMethod
public void setup() {
initMocks(this);
given(injector.getInstance(AMSetupManager.class)).willReturn(setupManager);
setupFilter = new AMSetupFilter();
}
@AfterMethod
public void tearDown() {
System.clearProperty(Constants.CONFIG_STORE_DOWN_REDIRECT_URL);
}
@Test
public void initShouldSetEncryptionPasswordIfNotConfigured() throws Exception {
//Given
FilterConfig config = mock(FilterConfig.class);
ServletContext context = mock(ServletContext.class);
given(config.getServletContext()).willReturn(context);
systemIsNotConfigured();
//When
setupFilter.init(config);
//Then
verify(context).setAttribute(eq("am.enc.pwd"), anyString());
}
@Test
public void initShouldNotSetEncryptionPasswordIfConfigured() throws Exception {
//Given
FilterConfig config = mock(FilterConfig.class);
ServletContext context = mock(ServletContext.class);
given(config.getServletContext()).willReturn(context);
systemIsConfigured();
//When
setupFilter.init(config);
//Then
verifyZeroInteractions(context);
}
@Test
public void filterShouldAllowRequestsThroughIfConfigured() throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("REQUEST_URI");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsConfigured();
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(chain).doFilter(request, response);
}
@DataProvider
private Object[][] setupRequestUris() {
return new Object[][]{
{"/config/options.htm"},
{"/setup/setSetupProgress"},
{"/config/upgrade/upgrade.htm"},
{"/upgrade/setUpgradeProgress"},
};
}
@Test(dataProvider = "setupRequestUris")
public void filterShouldRedirectSetupRequestsIfConfigured(String requestUri) throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest(requestUri);
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsConfigured();
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(response).sendRedirect("SCHEME://SERVER_NAME:8080/CONTEXT_PATH");
verifyZeroInteractions(chain);
}
@Test
public void filterShouldRedirectRequestsIfUpgradeInProgressButConfigStoreIsDown() throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("REQUEST_URI");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsBeingUpgraded();
configStoreIsDown("CONFIG_STORE_DOWN_REDIRECT_URI");
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(response).sendRedirect("CONFIG_STORE_DOWN_REDIRECT_URI");
verifyZeroInteractions(chain);
}
@Test
public void filterShouldThrowConfigurationExceptionIfUpgradeInProgressAndConfigStoreIsDownButNoRedirectUriSet()
throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("REQUEST_URI");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsBeingUpgraded();
configStoreIsDown(null);
//When
try {
setupFilter.doFilter(request, response, chain);
fail("Expected ServletException with ConfigurationException is cause");
} catch (ServletException e) {
//Then
assertThat(e.getCause()).isInstanceOf(ConfigurationException.class);
verifyZeroInteractions(response, chain);
}
}
@Test
public void filterShouldAllowConfiguratorRequestsThroughIfNotConfigured() throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("/configurator");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsNotConfigured();
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(chain).doFilter(request, response);
}
@Test
public void filterShouldRedirectRequestsToSetupPageIfNotConfigured() throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("REQUEST_URI");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsNotConfigured();
withWritePermissionsOnBootstrapRootDirectory();
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(response).sendRedirect("SCHEME://SERVER_NAME:8080/CONTEXT_PATH/config/options.htm");
verifyZeroInteractions(chain);
}
@Test
public void filterShouldThrowExceptionIfNotConfiguredAndCannotWriteToUserHomeDirectory()
throws Exception {
//Given
initializeFilter();
HttpServletRequest request = mockRequest("REQUEST_URI");
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
systemIsNotConfigured();
noWritePermissionsOnBootstrapRootDirectory();
//When
try {
setupFilter.doFilter(request, response, chain);
fail("Expected ServletException with ConfigurationException as cause");
} catch (ServletException e) {
//Then
assertThat(e.getCause()).isInstanceOf(ConfigurationException.class);
verifyZeroInteractions(response, chain);
}
}
@DataProvider
private Object[][] allowedRequestsWhilstConfiguring() {
return new Object[][]{
{".ico"},
{".htm"},
{".css"},
{".js"},
{".jpg"},
{".gif"},
{".png"},
{".JPG"},
{"SMSObjectIF"},
{"setSetupProgress"},
{"setUpgradeProgress"},
{"/legal-notices/"},
};
}
@Test(dataProvider = "allowedRequestsWhilstConfiguring")
public void filterShouldAllowCertainRequestsThroughIfNotConfiguredAndInConfigurationMode(String suffix)
throws Exception {
//Previous request must have been redirected to setup page to set the pass-through flag
filterShouldRedirectRequestsToSetupPageIfNotConfigured();
//Given
HttpServletRequest request = mockRequest(suffix);
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain chain = mock(FilterChain.class);
//When
setupFilter.doFilter(request, response, chain);
//Then
verify(chain).doFilter(request, response);
}
@Test
public void filterShouldRedirectRequestsToSetupPageIfNotConfiguredAndInConfigurationMode() throws Exception {
//Given
//Previous request must have been redirected to setup page to set the pass-through flag
filterShouldRedirectRequestsToSetupPageIfNotConfigured();
//When/Then
filterShouldRedirectRequestsToSetupPageIfNotConfigured();
}
private void initializeFilter() throws ServletException {
FilterConfig config = mock(FilterConfig.class);
ServletContext context = mock(ServletContext.class);
given(config.getServletContext()).willReturn(context);
setupFilter.init(config);
}
private void systemIsNotConfigured() {
given(setupManager.isConfigured()).willReturn(false);
given(setupManager.isCurrentConfigurationValid()).willReturn(false);
}
private void systemIsConfigured() {
given(setupManager.isConfigured()).willReturn(true);
given(setupManager.isCurrentConfigurationValid()).willReturn(true);
}
private void systemIsBeingUpgraded() {
given(setupManager.isCurrentConfigurationValid()).willReturn(false);
}
private void configStoreIsDown(String redirectUri) {
if (redirectUri != null) {
System.setProperty(Constants.CONFIG_STORE_DOWN_REDIRECT_URL, redirectUri);
}
given(setupManager.getBootStrapFileLocation()).willReturn("BOOTSTRAP_FILE_LOCATION");
given(setupManager.isVersionNewer()).willReturn(false);
given(setupManager.isUpgradeCompleted()).willReturn(false);
}
private HttpServletRequest mockRequest(String suffix) {
HttpServletRequest request = mock(HttpServletRequest.class);
given(request.getScheme()).willReturn("SCHEME");
given(request.getServerName()).willReturn("SERVER_NAME");
given(request.getServerPort()).willReturn(8080);
given(request.getContextPath()).willReturn("/CONTEXT_PATH");
given(request.getRequestURI()).willReturn("REQUEST_URI" + suffix);
given(request.getServletPath()).willReturn("SERVLET_PATH" + suffix);
given(request.getPathInfo()).willReturn("PATH_INFO" + suffix);
return request;
}
private void withWritePermissionsOnBootstrapRootDirectory() {
File bootstrapRootDirectory = mock(File.class);
given(setupManager.getUserHomeDirectory()).willReturn(bootstrapRootDirectory);
given(bootstrapRootDirectory.canWrite()).willReturn(true);
}
private void noWritePermissionsOnBootstrapRootDirectory() {
File bootstrapRootDirectory = mock(File.class);
given(setupManager.getUserHomeDirectory()).willReturn(bootstrapRootDirectory);
given(bootstrapRootDirectory.canWrite()).willReturn(false);
}
}