diff options
author | Lukasz Jarocki <lukasz.jarocki@sonarsource.com> | 2021-04-09 15:00:09 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-04-15 20:03:44 +0000 |
commit | c54b7df81f34bd61265adb1e22fad6d53533367b (patch) | |
tree | 4d45022d887c1b76532b772368fe9e9aa5096bc1 /server/sonar-webserver-core | |
parent | 54be548dbeff18fc8c5ace739f80e99dda5c44eb (diff) | |
download | sonarqube-c54b7df81f34bd61265adb1e22fad6d53533367b.tar.gz sonarqube-c54b7df81f34bd61265adb1e22fad6d53533367b.zip |
SONAR-14662 Redirecting admin to the risk consent page
Diffstat (limited to 'server/sonar-webserver-core')
2 files changed, 269 insertions, 0 deletions
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/plugins/PluginsRiskConsentFilter.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/plugins/PluginsRiskConsentFilter.java new file mode 100644 index 00000000000..998c932f07a --- /dev/null +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/plugins/PluginsRiskConsentFilter.java @@ -0,0 +1,93 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.plugins; + +import com.google.common.collect.ImmutableSet; +import org.sonar.api.config.Configuration; +import org.sonar.api.web.ServletFilter; +import org.sonar.core.extension.PluginRiskConsent; +import org.sonar.server.user.ThreadLocalUserSession; + +import static org.sonar.api.web.ServletFilter.UrlPattern.Builder.staticResourcePatterns; +import static org.sonar.core.config.CorePropertyDefinitions.PLUGINS_RISK_CONSENT; +import static org.sonar.core.extension.PluginRiskConsent.NOT_ACCEPTED; +import static org.sonar.core.extension.PluginRiskConsent.REQUIRED; +import static org.sonar.server.authentication.AuthenticationRedirection.redirectTo; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +public class PluginsRiskConsentFilter extends ServletFilter { + + private static final String PLUGINS_RISK_CONSENT_PATH = "/admin/plugin_risk_consent"; //NOSONAR this path will be the same in every environment + + private static final Set<String> SKIPPED_URLS = ImmutableSet.of( + PLUGINS_RISK_CONSENT_PATH, + "/account/reset_password", + "/admin/change_admin_password", + "/batch/*", "/api/*"); + private final ThreadLocalUserSession userSession; + private final Configuration config; + + public PluginsRiskConsentFilter(Configuration config, ThreadLocalUserSession userSession) { + this.userSession = userSession; + this.config = config; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + //nothing to do + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + PluginRiskConsent riskConsent = PluginRiskConsent.valueOf(config.get(PLUGINS_RISK_CONSENT).orElse(NOT_ACCEPTED.name())); + + if (userSession.hasSession() && userSession.isLoggedIn() + && userSession.isSystemAdministrator() && riskConsent == REQUIRED) { + redirectTo(response, request.getContextPath() + PLUGINS_RISK_CONSENT_PATH); + } + + chain.doFilter(request, response); + } + + @Override + public UrlPattern doGetPattern() { + return UrlPattern.builder() + .includes("/*") + .excludes(staticResourcePatterns()) + .excludes(SKIPPED_URLS) + .build(); + } + + @Override + public void destroy() { + //nothing to do + } +} diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/plugins/PluginsRiskConsentFilterTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/plugins/PluginsRiskConsentFilterTest.java new file mode 100644 index 00000000000..523f65ce9fb --- /dev/null +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/plugins/PluginsRiskConsentFilterTest.java @@ -0,0 +1,176 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.plugins; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.sonar.api.config.Configuration; +import org.sonar.api.web.ServletFilter; +import org.sonar.core.extension.PluginRiskConsent; +import org.sonar.server.plugins.PluginsRiskConsentFilter; +import org.sonar.server.user.ThreadLocalUserSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.sonar.core.config.CorePropertyDefinitions.PLUGINS_RISK_CONSENT; +import javax.servlet.FilterChain; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +public class PluginsRiskConsentFilterTest { + + private Configuration configuration; + private ThreadLocalUserSession userSession; + + private ServletRequest servletRequest; + private HttpServletResponse servletResponse; + private FilterChain chain; + + @Before + public void before() { + configuration = mock(Configuration.class); + when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.REQUIRED.name())); + userSession = mock(ThreadLocalUserSession.class); + + servletRequest = mock(HttpServletRequest.class); + servletResponse = mock(HttpServletResponse.class); + chain = mock(FilterChain.class); + } + + @Test + public void doFilter_givenNoUserSession_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenNotLoggedIn_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(false); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenNotLoggedInAndRequired_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(false); + when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.REQUIRED.name())); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenNotLoggedInAndConsentAccepted_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(false); + when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.ACCEPTED.name())); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenLoggedInNotAdmin_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(true); + when(userSession.isSystemAdministrator()).thenReturn(false); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenLoggedInNotAdminAndRequiredConsent_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(true); + when(userSession.isSystemAdministrator()).thenReturn(false); + when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.REQUIRED.name())); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenLoggedInAdminAndConsentRequired_redirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(true); + when(userSession.isSystemAdministrator()).thenReturn(true); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(1)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doFilter_givenLoggedInAdminAndConsentNotRequired_dontRedirect() throws Exception { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + when(userSession.hasSession()).thenReturn(true); + when(userSession.isLoggedIn()).thenReturn(true); + when(userSession.isSystemAdministrator()).thenReturn(true); + when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.ACCEPTED.name())); + + consentFilter.doFilter(servletRequest, servletResponse, chain); + + verify(servletResponse, times(0)).sendRedirect(Mockito.anyString()); + } + + @Test + public void doGetPattern_excludesNotEmpty() { + PluginsRiskConsentFilter consentFilter = new PluginsRiskConsentFilter(configuration, userSession); + + ServletFilter.UrlPattern urlPattern = consentFilter.doGetPattern(); + + assertThat(urlPattern.getExclusions()).isNotEmpty(); + + } +} |