diff options
author | Matteo Mara <matteo.mara@sonarsource.com> | 2022-07-05 15:52:26 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-07-06 20:03:56 +0000 |
commit | 6354fe3096b07caf9eb017ab7b4e0565f6d303fc (patch) | |
tree | 593d31be7e2902f186e85d6d0a588288162a73fe | |
parent | 6a401f73236a70f702b64646d8bdec7c5a90e15d (diff) | |
download | sonarqube-6354fe3096b07caf9eb017ab7b4e0565f6d303fc.tar.gz sonarqube-6354fe3096b07caf9eb017ab7b4e0565f6d303fc.zip |
SONAR-16567 add an analysis warning when using a token expiring in less than 7 days.
10 files changed, 160 insertions, 21 deletions
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java index bb6f0e7773e..880fc46ccb5 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java @@ -19,22 +19,26 @@ */ package org.sonar.server.authentication; +import java.util.Optional; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.sonar.api.config.Configuration; import org.sonar.api.server.ServerSide; import org.sonar.api.web.ServletFilter.UrlPattern; +import org.sonar.db.user.UserTokenDto; import org.sonar.server.authentication.event.AuthenticationEvent; import org.sonar.server.authentication.event.AuthenticationEvent.Source; import org.sonar.server.authentication.event.AuthenticationException; import org.sonar.server.user.ThreadLocalUserSession; +import org.sonar.server.user.TokenUserSession; import org.sonar.server.user.UserSession; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; import static org.apache.commons.lang.StringUtils.defaultString; import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_DEFAULT_VALUE; import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY; +import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.api.web.ServletFilter.UrlPattern.Builder.staticResourcePatterns; import static org.sonar.server.authentication.AuthenticationError.handleAuthenticationError; @@ -48,6 +52,8 @@ public class UserSessionInitializer { */ private static final String ACCESS_LOG_LOGIN = "LOGIN"; + private static final String SQ_AUTHENTICATION_TOKEN_EXPIRATION = "sq-authentication-token-expiration"; + // SONAR-6546 these urls should be get from WebService private static final Set<String> SKIPPED_URLS = Set.of( "/batch/index", "/batch/file", @@ -76,6 +82,7 @@ public class UserSessionInitializer { .includes(URL_USING_PASSCODE) .build(); + private final Configuration config; private final ThreadLocalUserSession threadLocalSession; private final AuthenticationEvent authenticationEvent; @@ -128,9 +135,17 @@ public class UserSessionInitializer { .build(); } threadLocalSession.set(session); + checkTokenUserSession(response, session); request.setAttribute(ACCESS_LOG_LOGIN, defaultString(session.getLogin(), "-")); } + private static void checkTokenUserSession(HttpServletResponse response, UserSession session) { + if (session instanceof TokenUserSession) { + UserTokenDto userTokenDto = ((TokenUserSession) session).getUserToken(); + Optional.ofNullable(userTokenDto.getExpirationDate()).ifPresent(expirationDate -> response.addHeader(SQ_AUTHENTICATION_TOKEN_EXPIRATION, formatDateTime(expirationDate))); + } + } + public void removeUserSession() { threadLocalSession.unload(); } diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/TokenUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/TokenUserSession.java index 7f0b730aa7e..9c1e401e4cf 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/TokenUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/TokenUserSession.java @@ -73,4 +73,7 @@ public class TokenUserSession extends ServerUserSession { } } + public UserTokenDto getUserToken() { + return userToken; + } } diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java index dcaac1ea2ef..f577adaea42 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java @@ -19,6 +19,8 @@ */ package org.sonar.server.authentication; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -30,6 +32,8 @@ import org.sonar.api.config.internal.MapSettings; import org.sonar.api.server.authentication.BaseIdentityProvider; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; +import org.sonar.db.user.UserDto; +import org.sonar.db.user.UserTokenDto; import org.sonar.server.authentication.event.AuthenticationEvent; import org.sonar.server.authentication.event.AuthenticationEvent.Method; import org.sonar.server.authentication.event.AuthenticationEvent.Source; @@ -37,6 +41,7 @@ import org.sonar.server.authentication.event.AuthenticationException; import org.sonar.server.tester.AnonymousMockUserSession; import org.sonar.server.tester.MockUserSession; import org.sonar.server.user.ThreadLocalUserSession; +import org.sonar.server.user.TokenUserSession; import org.sonar.server.user.UserSession; import static org.assertj.core.api.Assertions.assertThat; @@ -47,6 +52,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.sonar.api.utils.DateUtils.formatDateTime; public class UserSessionInitializerTest { @@ -195,6 +201,20 @@ public class UserSessionInitializerTest { verify(response).sendRedirect("/sonarqube/sessions/unauthorized"); } + @Test + public void expiration_header_added_when_authenticating_with_an_expiring_token() { + long expirationTimestamp = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(); + UserDto userDto = new UserDto(); + UserTokenDto userTokenDto = new UserTokenDto().setExpirationDate(expirationTimestamp); + UserSession session = new TokenUserSession(DbTester.create().getDbClient(), userDto, userTokenDto); + + when(authenticator.authenticate(request, response)).thenReturn(session); + when(threadLocalSession.isLoggedIn()).thenReturn(true); + + assertThat(underTest.initUserSession(request, response)).isTrue(); + verify(response).addHeader("sq-authentication-token-expiration", formatDateTime(expirationTimestamp)); + } + private void assertPathIsIgnored(String path) { when(request.getRequestURI()).thenReturn(path); diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/TokenUserSessionTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/TokenUserSessionTest.java index 6ffe52c179c..0af1c638820 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/TokenUserSessionTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/TokenUserSessionTest.java @@ -42,6 +42,22 @@ public class TokenUserSessionTest { private final DbClient dbClient = db.getDbClient(); @Test + public void token_can_be_retrieved_from_the_session() { + ComponentDto project1 = db.components().insertPrivateProject(); + + UserDto user = db.users().insertUser(); + + db.users().insertProjectPermissionOnUser(user, SCAN, project1); + + TokenUserSession userSession = mockTokenUserSession(user); + + assertThat(userSession.getUserToken()).isNotNull(); + assertThat(userSession.getUserToken().getName()).isEqualTo("User Token"); + assertThat(userSession.getUserToken().getUserUuid()).isEqualTo("userUid"); + assertThat(userSession.getUserToken().getType()).isEqualTo("USER_TOKEN"); + } + + @Test public void test_hasProjectsPermission_for_UserToken() { ComponentDto project1 = db.components().insertPrivateProject(); ComponentDto project2 = db.components().insertPrivateProject(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java index 8dc5dc3a39f..0be294a4f99 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java @@ -23,11 +23,18 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.annotation.CheckForNull; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; +import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; @@ -41,21 +48,28 @@ import org.sonarqube.ws.client.WsResponse; import static java.lang.String.format; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_OK; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static org.sonar.api.utils.DateUtils.DATETIME_FORMAT; import static org.sonar.api.utils.Preconditions.checkState; public class DefaultScannerWsClient implements ScannerWsClient { private static final int MAX_ERROR_MSG_LEN = 128; + private static final String SQ_TOKEN_EXPIRATION_HEADER = "sq-authentication-token-expiration"; private static final Logger LOG = Loggers.get(DefaultScannerWsClient.class); + private final Set<String> warningMessages = new HashSet<>(); + private final WsClient target; private final boolean hasCredentials; private final GlobalAnalysisMode globalMode; + private final AnalysisWarnings analysisWarnings; - public DefaultScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode) { + public DefaultScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode, AnalysisWarnings analysisWarnings) { this.target = target; this.hasCredentials = hasCredentials; this.globalMode = globalMode; + this.analysisWarnings = analysisWarnings; } /** @@ -73,6 +87,7 @@ public class DefaultScannerWsClient implements ScannerWsClient { WsResponse response = target.wsConnector().call(request); profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl())); failIfUnauthorized(response); + checkAuthenticationWarnings(response); return response; } @@ -96,7 +111,6 @@ public class DefaultScannerWsClient implements ScannerWsClient { // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048 throw MessageException.of(format("Not authorized. Analyzing this project requires authentication. " + "Please provide a user token in %s or other credentials in %s and %s.", CoreProperties.LOGIN, CoreProperties.LOGIN, CoreProperties.PASSWORD)); - } if (code == HTTP_FORBIDDEN) { throw MessageException.of("You're not authorized to run analysis. Please contact the project administrator."); @@ -112,6 +126,33 @@ public class DefaultScannerWsClient implements ScannerWsClient { response.failIfNotSuccessful(); } + private void checkAuthenticationWarnings(WsResponse response) { + if (response.code() == HTTP_OK) { + response.header(SQ_TOKEN_EXPIRATION_HEADER).ifPresent(expirationDate -> { + if (isTokenExpiringInOneWeek(expirationDate)) { + addAnalysisWarning(expirationDate); + } + }); + } + } + + private static boolean isTokenExpiringInOneWeek(String expirationDate) { + ZonedDateTime localDateTime = ZonedDateTime.now(ZoneOffset.UTC); + ZonedDateTime headerDateTime = LocalDateTime.from(DateTimeFormatter.ofPattern(DATETIME_FORMAT) + .parse(expirationDate)).minusDays(7).atZone(ZoneOffset.UTC); + return localDateTime.isAfter(headerDateTime); + } + + private void addAnalysisWarning(String tokenExpirationDate) { + String warningMessage = "The token used for this analysis will expire on: " + tokenExpirationDate; + if (!warningMessages.contains(warningMessage)) { + warningMessages.add(warningMessage); + LOG.warn(warningMessage); + LOG.warn("Analysis executed with this token after the expiration date will fail."); + } + analysisWarnings.addUnique(warningMessage + "\nAnalysis executed with this token after the expiration date will fail."); + } + /** * Tries to form a short and relevant error message from the exception, to be displayed in the console. */ diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java index 8e86aa8b0b4..7a45f5cc35a 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java @@ -20,6 +20,7 @@ package org.sonar.scanner.bootstrap; import org.sonar.api.CoreProperties; +import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.System2; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonarqube.ws.client.HttpConnector; @@ -37,7 +38,7 @@ public class ScannerWsClientProvider { @Bean("DefaultScannerWsClient") public DefaultScannerWsClient provide(ScannerProperties scannerProps, EnvironmentInformation env, GlobalAnalysisMode globalMode, - System2 system) { + System2 system, AnalysisWarnings analysisWarnings) { String url = defaultIfBlank(scannerProps.property("sonar.host.url"), "http://localhost:9000"); HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder(); @@ -58,6 +59,6 @@ public class ScannerWsClientProvider { } return new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, - globalMode); + globalMode, analysisWarnings); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java index 752b6ef0891..3da98be8901 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java @@ -19,12 +19,16 @@ */ package org.sonar.scanner.bootstrap; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; +import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; @@ -39,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.api.utils.DateUtils.DATETIME_FORMAT; public class DefaultScannerWsClientTest { @@ -47,6 +52,8 @@ public class DefaultScannerWsClientTest { private final WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS); + private final AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class); + @Test public void log_and_profile_request_if_debug_level() { WsRequest request = newRequest(); @@ -54,7 +61,7 @@ public class DefaultScannerWsClientTest { when(wsClient.wsConnector().call(request)).thenReturn(response); logTester.setLevel(LoggerLevel.DEBUG); - DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))); + DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings); WsResponse result = underTest.call(request); @@ -92,10 +99,10 @@ public class DefaultScannerWsClientTest { when(wsClient.wsConnector().call(request)).thenReturn(response); assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, false, - new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request)) - .isInstanceOf(MessageException.class) - .hasMessage("Not authorized. Analyzing this project requires authentication. Please provide a user token in sonar.login or other " + - "credentials in sonar.login and sonar.password."); + new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings).call(request)) + .isInstanceOf(MessageException.class) + .hasMessage("Not authorized. Analyzing this project requires authentication. Please provide a user token in sonar.login or other " + + "credentials in sonar.login and sonar.password."); } @Test @@ -105,9 +112,9 @@ public class DefaultScannerWsClientTest { when(wsClient.wsConnector().call(request)).thenReturn(response); assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, /* credentials are configured */true, - new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request)) - .isInstanceOf(MessageException.class) - .hasMessage("Not authorized. Please check the properties sonar.login and sonar.password."); + new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings).call(request)) + .isInstanceOf(MessageException.class) + .hasMessage("Not authorized. Please check the properties sonar.login and sonar.password."); } @Test @@ -118,9 +125,33 @@ public class DefaultScannerWsClientTest { when(wsClient.wsConnector().call(request)).thenReturn(response); assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, true, - new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request)) - .isInstanceOf(MessageException.class) - .hasMessage("You're not authorized to run analysis. Please contact the project administrator."); + new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings).call(request)) + .isInstanceOf(MessageException.class) + .hasMessage("You're not authorized to run analysis. Please contact the project administrator."); + } + + @Test + public void warnings_are_added_when_expiration_approaches() { + WsRequest request = newRequest(); + String expirationDate = DateTimeFormatter + .ofPattern(DATETIME_FORMAT) + .format(LocalDateTime.now().atOffset(ZoneOffset.UTC).plusDays(5)); + WsResponse response = newResponse() + .setCode(200) + .setExpirationDate(expirationDate); + when(wsClient.wsConnector().call(request)).thenReturn(response); + + logTester.setLevel(LoggerLevel.DEBUG); + DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings); + underTest.call(request); + //the second call should not add the same warning twice + underTest.call(request); + + // check logs + List<String> warningLogs = logTester.logs(LoggerLevel.WARN); + assertThat(warningLogs).hasSize(2); + assertThat(warningLogs.get(0)).contains("The token used for this analysis will expire on: " + expirationDate); + assertThat(warningLogs.get(1)).contains("Analysis executed with this token after the expiration date will fail."); } @Test @@ -132,9 +163,9 @@ public class DefaultScannerWsClientTest { when(wsClient.wsConnector().call(request)).thenReturn(response); assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, true, - new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request)) - .isInstanceOf(MessageException.class) - .hasMessage("Boo! bad request! bad!"); + new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings).call(request)) + .isInstanceOf(MessageException.class) + .hasMessage("Boo! bad request! bad!"); } private MockWsResponse newResponse() { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java index d2b7cd4840d..233028242bd 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java @@ -48,6 +48,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin; import org.sonarqube.ws.client.HttpConnector; import org.sonarqube.ws.client.WsClientFactories; @@ -56,6 +57,7 @@ import static org.apache.commons.io.FileUtils.moveFile; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import static org.mockito.Mockito.mock; public class PluginFilesTest { @@ -64,6 +66,8 @@ public class PluginFilesTest { @Rule public MockWebServer server = new MockWebServer(); + private final AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class); + private File userHome; private PluginFiles underTest; @@ -72,7 +76,7 @@ public class PluginFilesTest { HttpConnector connector = HttpConnector.newBuilder().url(server.url("/").toString()).build(); GlobalAnalysisMode analysisMode = new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())); DefaultScannerWsClient wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connector), false, - analysisMode); + analysisMode, analysisWarnings); userHome = temp.newFolder(); MapSettings settings = new MapSettings(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java index e6e6d3ba627..c4db3d9258b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java @@ -40,7 +40,8 @@ public class ScannerWsClientProviderTest { ScannerProperties settings = new ScannerProperties(new HashMap<>()); DefaultScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), - mock(System2.class)); + mock(System2.class),warning -> { + }); assertThat(client).isNotNull(); assertThat(client.baseUrl()).isEqualTo("http://localhost:9000/"); @@ -61,7 +62,8 @@ public class ScannerWsClientProviderTest { ScannerProperties settings = new ScannerProperties(props); DefaultScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), - mock(System2.class)); + mock(System2.class),warning -> { + }); assertThat(client).isNotNull(); HttpConnector httpConnector = (HttpConnector) client.wsConnector(); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/MockWsResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/MockWsResponse.java index 70c889f0501..2e799b1806d 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/MockWsResponse.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/MockWsResponse.java @@ -35,6 +35,7 @@ import static java.util.Objects.requireNonNull; public class MockWsResponse extends BaseResponse { private static final String CONTENT_TYPE_HEADER = "Content-Type"; + private static final String SQ_TOKEN_EXPIRATION_HEADER = "sq-authentication-token-expiration"; private int code = HttpURLConnection.HTTP_OK; private String requestUrl; @@ -66,6 +67,11 @@ public class MockWsResponse extends BaseResponse { return this; } + public MockWsResponse setExpirationDate(String expirationDate) { + headers.put(SQ_TOKEN_EXPIRATION_HEADER, expirationDate); + return this; + } + public MockWsResponse setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; return this; |