From 9b0ff958302e5c2f73787ea9a456dd2b319579d5 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Tue, 19 Apr 2016 11:16:13 +0200 Subject: [PATCH] Background tasks logs are available for project admin --- .../org/sonar/server/ce/ws/LogsAction.java | 39 ++++++++++++++----- .../sonar/server/ce/ws/LogsActionTest.java | 33 +++++++++++++--- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/LogsAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/LogsAction.java index f89b3c7981d..aef36c51087 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/LogsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/LogsAction.java @@ -22,18 +22,21 @@ package org.sonar.server.ce.ws; import com.google.common.base.Optional; import java.io.File; import java.io.IOException; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; 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.api.web.UserRole; +import org.sonar.ce.log.CeLogging; +import org.sonar.ce.log.LogFileRef; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDto; -import org.sonar.ce.log.CeLogging; -import org.sonar.ce.log.LogFileRef; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UserSession; import org.sonarqube.ws.MediaTypes; @@ -74,11 +77,10 @@ public class LogsAction implements CeWsAction { @Override public void handle(Request wsRequest, Response wsResponse) throws Exception { - userSession.checkPermission(UserRole.ADMIN); - String taskUuid = wsRequest.mandatoryParam(PARAM_TASK_UUID); - LogFileRef ref = loadLogRef(taskUuid); - Optional logFile = ceLogging.getFile(ref); + LogFileRefComponentUuidTuple refAndComponentUuid = loadLogRef(taskUuid); + checkPermissions(refAndComponentUuid.componentUuid); + Optional logFile = ceLogging.getFile(refAndComponentUuid.logFileRef); if (logFile.isPresent()) { writeFile(logFile.get(), wsResponse); } else { @@ -86,16 +88,24 @@ public class LogsAction implements CeWsAction { } } - private LogFileRef loadLogRef(String taskUuid) { + private void checkPermissions(@Nullable String componentUuid) { + if (componentUuid == null) { + userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN); + } else { + userSession.checkComponentUuidPermission(UserRole.ADMIN, componentUuid); + } + } + + private LogFileRefComponentUuidTuple loadLogRef(String taskUuid) { DbSession dbSession = dbClient.openSession(false); try { Optional queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid); if (queueDto.isPresent()) { - return LogFileRef.from(queueDto.get()); + return new LogFileRefComponentUuidTuple(LogFileRef.from(queueDto.get()), queueDto.get().getComponentUuid()); } Optional activityDto = dbClient.ceActivityDao().selectByUuid(dbSession, taskUuid); if (activityDto.isPresent()) { - return LogFileRef.from(activityDto.get()); + return new LogFileRefComponentUuidTuple(LogFileRef.from(activityDto.get()), activityDto.get().getComponentUuid()); } throw new NotFoundException(format("Task %s not found", taskUuid)); @@ -113,4 +123,15 @@ public class LogsAction implements CeWsAction { throw new IllegalStateException("Fail to copy compute engine log file to HTTP response: " + file.getAbsolutePath(), e); } } + + private static class LogFileRefComponentUuidTuple { + private final LogFileRef logFileRef; + @CheckForNull + private final String componentUuid; + + private LogFileRefComponentUuidTuple(LogFileRef logFileRef, @Nullable String componentUuid) { + this.logFileRef = logFileRef; + this.componentUuid = componentUuid; + } + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/LogsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/LogsActionTest.java index ccdb4a9cd18..7a5277bb522 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/LogsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/LogsActionTest.java @@ -62,7 +62,7 @@ public class LogsActionTest { @Test public void return_task_logs_if_available() throws IOException { - userSession.setGlobalPermissions(UserRole.ADMIN); + globalAdministrator(); // task must exist in database insert("TASK_1", null); @@ -78,13 +78,31 @@ public class LogsActionTest { assertThat(response.getInput()).isEqualTo("{logs}"); } + @Test + public void return_task_logs_when_project_admin() throws Exception { + userSession.addProjectUuidPermissions(UserRole.ADMIN, "PROJECT_UUID"); + + // task must exist in database + insert("TASK_1", "PROJECT_UUID"); + File logFile = temp.newFile(); + FileUtils.write(logFile, "{logs}"); + when(ceLogging.getFile(new LogFileRef(CeTaskTypes.REPORT, "TASK_1", "PROJECT_UUID"))).thenReturn(Optional.of(logFile)); + + TestResponse response = tester.newRequest() + .setParam("taskId", "TASK_1") + .execute(); + + assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT); + assertThat(response.getInput()).isEqualTo("{logs}"); + } + /** * The parameter taskId is present but empty. It's considered as * a valid task which does not exist */ @Test(expected = NotFoundException.class) public void return_404_if_task_id_is_empty() { - userSession.setGlobalPermissions(UserRole.ADMIN); + globalAdministrator(); tester.newRequest() .setParam("taskId", "") .execute(); @@ -92,14 +110,14 @@ public class LogsActionTest { @Test(expected = IllegalArgumentException.class) public void bad_request_if_task_id_is_missing() { - userSession.setGlobalPermissions(UserRole.ADMIN); + globalAdministrator(); tester.newRequest() .execute(); } @Test(expected = NotFoundException.class) public void return_404_if_task_logs_are_not_available() { - userSession.setGlobalPermissions(UserRole.ADMIN); + globalAdministrator(); insert("TASK_1", null); when(ceLogging.getFile(new LogFileRef(CeTaskTypes.REPORT, "TASK_1", null))).thenReturn(Optional.absent()); @@ -110,7 +128,7 @@ public class LogsActionTest { @Test(expected = NotFoundException.class) public void return_404_if_task_does_not_exist() { - userSession.setGlobalPermissions(UserRole.ADMIN); + globalAdministrator(); tester.newRequest() .setParam("taskId", "TASK_1") .execute(); @@ -118,11 +136,16 @@ public class LogsActionTest { @Test(expected = ForbiddenException.class) public void require_admin_permission() { + insert("TASK_1", null); tester.newRequest() .setParam("taskId", "TASK_1") .execute(); } + private void globalAdministrator() { + userSession.setGlobalPermissions(UserRole.ADMIN); + } + private CeQueueDto insert(String taskUuid, @Nullable String componentUuid) { CeQueueDto queueDto = new CeQueueDto(); queueDto.setTaskType(CeTaskTypes.REPORT); -- 2.39.5