diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-11-16 15:51:13 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-11-17 07:36:51 +0100 |
commit | b612813d06583cb5021469afb6a06c15ecdc3662 (patch) | |
tree | a521ed1c5d728180f509fd41fc9822f8a7df9b9e /server/sonar-server | |
parent | 75bae1e0539dd6504c898814621262f1739d08d4 (diff) | |
download | sonarqube-b612813d06583cb5021469afb6a06c15ecdc3662.tar.gz sonarqube-b612813d06583cb5021469afb6a06c15ecdc3662.zip |
SONAR-8383 add param "process" to api/system/logs
Diffstat (limited to 'server/sonar-server')
-rw-r--r-- | server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java | 33 | ||||
-rw-r--r-- | server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java | 92 |
2 files changed, 111 insertions, 14 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java index 545144d697c..141f0d84938 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java @@ -20,16 +20,23 @@ package org.sonar.server.platform.ws; import java.io.File; +import java.net.HttpURLConnection; import org.apache.commons.io.FileUtils; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; +import org.sonar.core.util.stream.Collectors; +import org.sonar.process.ProcessId; import org.sonar.server.platform.ServerLogging; import org.sonar.server.user.UserSession; import org.sonarqube.ws.MediaTypes; +import static java.util.Arrays.stream; + public class LogsAction implements SystemWsAction { + private static final String PROCESS_PROPERTY = "process"; + private final UserSession userSession; private final ServerLogging serverLogging; @@ -40,21 +47,39 @@ public class LogsAction implements SystemWsAction { @Override public void define(WebService.NewController controller) { - controller.createAction("logs") + WebService.NewAction action = controller.createAction("logs") .setDescription("Get system logs in plain-text format. Requires system administration permission.") .setResponseExample(getClass().getResource("logs-example.log")) .setSince("5.2") .setHandler(this); + + action + .createParam(PROCESS_PROPERTY) + .setPossibleValues(stream(ProcessId.values()) + .map(ProcessId::getKey) + .sorted() + .collect(Collectors.toList(ProcessId.values().length))) + .setDefaultValue(ProcessId.APP.getKey()) + .setSince("6.2") + .setDescription("Process to get logs from"); } @Override public void handle(Request wsRequest, Response wsResponse) throws Exception { userSession.checkIsRoot(); - wsResponse.stream().setMediaType(MediaTypes.TXT); - File file = serverLogging.getCurrentLogFile(); - if (file.exists()) { + String processKey = wsRequest.mandatoryParam(PROCESS_PROPERTY); + ProcessId processId = ProcessId.fromKey(processKey); + + File logsDir = serverLogging.getLogsDir(); + File file = new File(logsDir, processId.getLogFilenamePrefix() + ".log"); + // filenames are defined in the enum LogProcess. Still to prevent any vulnerability, + // path is double-checked to prevent returning any file present on the file system. + if (file.exists() && file.getParentFile().equals(logsDir)) { + wsResponse.stream().setMediaType(MediaTypes.TXT); FileUtils.copyFile(file, wsResponse.stream().output()); + } else { + wsResponse.stream().setStatus(HttpURLConnection.HTTP_NOT_FOUND); } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java index feac4ff14fd..a894e880bfa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java @@ -21,6 +21,7 @@ package org.sonar.server.platform.ws; import java.io.File; import java.io.IOException; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.junit.Rule; import org.junit.Test; @@ -51,6 +52,13 @@ public class LogsActionTest { private WsActionTester actionTester = new WsActionTester(underTest); @Test + public void values_of_process_parameter_are_names_of_processes() { + Set<String> values = actionTester.getDef().param("process").possibleValues(); + // values are lower-case and alphabetically ordered + assertThat(values).containsExactly("app", "ce", "es", "web"); + } + + @Test public void request_fails_with_ForbiddenException_when_user_is_not_logged_in() { expectedException.expect(ForbiddenException.class); @@ -67,29 +75,93 @@ public class LogsActionTest { } @Test - public void get_logs() throws IOException { + public void get_app_logs_by_default() throws IOException { makeAuthenticatedUserRoot(); - File file = temp.newFile(); - FileUtils.write(file, "{logs}"); - when(serverLogging.getCurrentLogFile()).thenReturn(file); + createAllLogsFiles(); TestResponse response = actionTester.newRequest().execute(); assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); - assertThat(response.getInput()).isEqualTo("{logs}"); + assertThat(response.getInput()).isEqualTo("{app}"); } @Test - public void get_empty_logs_if_file_does_not_exist() throws IOException { + public void return_404_not_found_if_file_does_not_exist() throws IOException { makeAuthenticatedUserRoot(); - File file = temp.newFile(); - file.delete(); - when(serverLogging.getCurrentLogFile()).thenReturn(file); + createLogsDir(); TestResponse response = actionTester.newRequest().execute(); + assertThat(response.getStatus()).isEqualTo(404); + } + + @Test + public void get_ce_logs() throws IOException { + makeAuthenticatedUserRoot(); + + createAllLogsFiles(); + + TestResponse response = actionTester.newRequest() + .setParam("process", "ce") + .execute(); + assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); + assertThat(response.getInput()).isEqualTo("{ce}"); + } + + @Test + public void get_es_logs() throws IOException { + makeAuthenticatedUserRoot(); + + createAllLogsFiles(); + + TestResponse response = actionTester.newRequest() + .setParam("process", "es") + .execute(); + assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); + assertThat(response.getInput()).isEqualTo("{es}"); + } + + @Test + public void get_web_logs() throws IOException { + makeAuthenticatedUserRoot(); + + createAllLogsFiles(); + + TestResponse response = actionTester.newRequest() + .setParam("process", "web") + .execute(); assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); - assertThat(response.getInput()).isEqualTo(""); + assertThat(response.getInput()).isEqualTo("{web}"); + } + + @Test + public void do_not_return_rotated_files() throws IOException { + makeAuthenticatedUserRoot(); + + File dir = createLogsDir(); + FileUtils.write(new File(dir, "sonar.1.log"), "{old}"); + FileUtils.write(new File(dir, "sonar.log"), "{recent}"); + + TestResponse response = actionTester.newRequest() + .setParam("process", "app") + .execute(); + assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); + assertThat(response.getInput()).isEqualTo("{recent}"); + } + + private File createAllLogsFiles() throws IOException { + File dir = createLogsDir(); + FileUtils.write(new File(dir, "sonar.log"), "{app}"); + FileUtils.write(new File(dir, "ce.log"), "{ce}"); + FileUtils.write(new File(dir, "es.log"), "{es}"); + FileUtils.write(new File(dir, "web.log"), "{web}"); + return dir; + } + + private File createLogsDir() throws IOException { + File dir = temp.newFolder(); + when(serverLogging.getLogsDir()).thenReturn(dir); + return dir; } private void makeAuthenticatedUserRoot() { |