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;
@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<File> logFile = ceLogging.getFile(ref);
+ LogFileRefComponentUuidTuple refAndComponentUuid = loadLogRef(taskUuid);
+ checkPermissions(refAndComponentUuid.componentUuid);
+ Optional<File> logFile = ceLogging.getFile(refAndComponentUuid.logFileRef);
if (logFile.isPresent()) {
writeFile(logFile.get(), wsResponse);
} else {
}
}
- 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<CeQueueDto> 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<CeActivityDto> 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));
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;
+ }
+ }
}
@Test
public void return_task_logs_if_available() throws IOException {
- userSession.setGlobalPermissions(UserRole.ADMIN);
+ globalAdministrator();
// task must exist in database
insert("TASK_1", null);
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();
@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.<File>absent());
@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();
@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);