]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8716 fix check of permissions in api/ce/task
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 6 Feb 2017 21:07:02 +0000 (22:07 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 7 Feb 2017 13:30:45 +0000 (14:30 +0100)
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java

index e70e24cd82d5e9b9ef193a983546e290e26a8a34..c394830ef3d37ed0be32f3dae63eb86ee8c0d49e 100644 (file)
@@ -37,13 +37,12 @@ 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.db.component.ComponentDto;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.WsCe;
 
 import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
-import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
-import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
 public class TaskAction implements CeWsAction {
@@ -91,17 +90,19 @@ public class TaskAction implements CeWsAction {
       WsCe.TaskResponse.Builder wsTaskResponse = WsCe.TaskResponse.newBuilder();
       Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid);
       if (queueDto.isPresent()) {
-        checkPermission(queueDto.get().getComponentUuid());
-        wsTaskResponse.setTask(wsTaskFormatter.formatQueue(dbSession, queueDto.get()));
+        Optional<ComponentDto> component = loadComponent(dbSession, queueDto.get().getComponentUuid());
+        checkPermission(component);
+        wsTaskResponse.setTask(wsTaskFormatter.formatQueue(dbSession, queueDto.get(), component));
       } else {
         Optional<CeActivityDto> activityDto = dbClient.ceActivityDao().selectByUuid(dbSession, taskUuid);
         if (activityDto.isPresent()) {
           CeActivityDto ceActivityDto = activityDto.get();
-          checkPermission(ceActivityDto.getComponentUuid());
+          Optional<ComponentDto> component = loadComponent(dbSession, ceActivityDto.getComponentUuid());
+          checkPermission(component);
           Set<AdditionalField> additionalFields = AdditionalField.getFromRequest(wsRequest);
           maskErrorStacktrace(ceActivityDto, additionalFields);
           wsTaskResponse.setTask(
-            wsTaskFormatter.formatActivity(dbSession, ceActivityDto, extractScannerContext(dbSession, ceActivityDto, additionalFields)));
+            wsTaskFormatter.formatActivity(dbSession, ceActivityDto, component, extractScannerContext(dbSession, ceActivityDto, additionalFields)));
         } else {
           throw new NotFoundException();
         }
@@ -110,11 +111,18 @@ public class TaskAction implements CeWsAction {
     }
   }
 
-  private void checkPermission(@Nullable String projectUuid) {
-    if (!userSession.hasPermission(SYSTEM_ADMIN)
-      && !userSession.hasPermission(SCAN_EXECUTION)
-      && (projectUuid == null || !userSession.hasComponentUuidPermission(SCAN_EXECUTION, projectUuid))) {
-      throw insufficientPrivilegesException();
+  private Optional<ComponentDto> loadComponent(DbSession dbSession, @Nullable String projectUuid) {
+    if (projectUuid == null) {
+      return Optional.absent();
+    }
+    return dbClient.componentDao().selectByUuid(dbSession, projectUuid);
+  }
+
+  private void checkPermission(Optional<ComponentDto> component) {
+    if (component.isPresent()) {
+      userSession.checkComponentPermission(SCAN_EXECUTION, component.get());
+    } else {
+      userSession.checkIsRoot();
     }
   }
 
index 9d832a82150e6d1f747288b8d5281ed0410ab724..514305752ec3bde3775429934dee9c1ab8feee46 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.ce.ws;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -41,7 +40,9 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonarqube.ws.WsCe;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Collections.emptyMap;
 import static org.sonar.api.utils.DateUtils.formatDateTime;
 import static org.sonar.core.util.Protobuf.setNullable;
 
@@ -68,6 +69,11 @@ public class TaskFormatter {
     return formatQueue(dto, ComponentDtoCache.forUuid(dbClient, dbSession, dto.getComponentUuid()));
   }
 
+  public WsCe.Task formatQueue(DbSession dbSession, CeQueueDto dto, Optional<ComponentDto> component) {
+    checkArgument(Objects.equals(dto.getComponentUuid(), component.transform(ComponentDto::uuid).orNull()));
+    return formatQueue(dto, ComponentDtoCache.forComponentDto(dbClient, dbSession, component));
+  }
+
   private WsCe.Task formatQueue(CeQueueDto dto, ComponentDtoCache componentDtoCache) {
     WsCe.Task.Builder builder = WsCe.Task.newBuilder();
     String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid());
@@ -89,11 +95,12 @@ public class TaskFormatter {
   }
 
   public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto dto) {
-    return formatActivity(dbSession, dto, null);
+    return formatActivity(dto, ComponentDtoCache.forUuid(dbClient, dbSession, dto.getComponentUuid()), null);
   }
 
-  public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto dto, @Nullable String scannerContext) {
-    return formatActivity(dto, ComponentDtoCache.forUuid(dbClient, dbSession, dto.getComponentUuid()), scannerContext);
+  public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto dto, Optional<ComponentDto> component,
+    @Nullable String scannerContext) {
+    return formatActivity(dto, ComponentDtoCache.forComponentDto(dbClient, dbSession, component), scannerContext);
   }
 
   public List<WsCe.Task> formatActivity(DbSession dbSession, List<CeActivityDto> dtos) {
@@ -179,8 +186,12 @@ public class TaskFormatter {
     }
 
     static ComponentDtoCache forUuid(DbClient dbClient, DbSession dbSession, String uuid) {
-      Optional<ComponentDto> componentDto = dbClient.componentDao().selectByUuid(dbSession, uuid);
-      Map<String, ComponentDto> componentsByUuid = componentDto.isPresent() ? ImmutableMap.of(uuid, componentDto.get()) : Collections.emptyMap();
+      Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, uuid);
+      return forComponentDto(dbClient, dbSession, component);
+    }
+
+    static ComponentDtoCache forComponentDto(DbClient dbClient, DbSession dbSession, Optional<ComponentDto> component) {
+      Map<String, ComponentDto> componentsByUuid = component.isPresent() ? ImmutableMap.of(component.get().uuid(), component.get()) : emptyMap();
       return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid));
     }
 
index 8ec673aff4cf05e7b520932a0a47b21e619cc763..a401e60ba421bc57d9cefb11d0a192497fa6d5dd 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.ce.ws;
 
+import com.google.common.base.Optional;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Date;
@@ -176,7 +177,7 @@ public class TaskFormatterTest {
     CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED);
 
     String expected = "scanner context baby!";
-    WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto, expected);
+    WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto, Optional.absent(), expected);
 
     assertThat(wsTask.hasScannerContext()).isTrue();
     assertThat(wsTask.getScannerContext()).isEqualTo(expected);