]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16588 improve project authorization search
authorBenjamin Campomenosi <109955405+benjamin-campomenosi-sonarsource@users.noreply.github.com>
Thu, 13 Oct 2022 13:29:43 +0000 (15:29 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 13 Oct 2022 20:03:18 +0000 (20:03 +0000)
server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java

index a826f6fdda083b8d5fd9a4a3249731ff94a90264..2d1ad370edfd9fd6c1cf0b923e8a5675a2a142f2 100644 (file)
@@ -41,12 +41,14 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTreeQuery;
 import org.sonar.db.component.ComponentTreeQuery.Strategy;
 import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
 
 import static java.util.Collections.singleton;
 import static java.util.Optional.of;
 import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
 import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
 import static org.sonar.api.web.UserRole.PUBLIC_PERMISSIONS;
@@ -147,7 +149,7 @@ public class ServerUserSession extends AbstractUserSession {
     }
     try (DbSession dbSession = dbClient.openSession(false)) {
       Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
-      if (!component.isPresent()) {
+      if (component.isEmpty()) {
         return Optional.empty();
       }
       // if component is part of a branch, then permissions must be
@@ -180,10 +182,27 @@ public class ServerUserSession extends AbstractUserSession {
       .allMatch(uuid -> hasPermission(permission, uuid));
   }
 
+  @Override
+  public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) {
+    Set<String> projectsUuids = projects.stream().map(ProjectDto::getUuid).collect(Collectors.toSet());
+    Set<String> authorizedProjectsUuids = keepProjectsUuidsByPermission(permission, projectsUuids);
+
+    return projects.stream()
+      .filter(project -> authorizedProjectsUuids.contains(project.getUuid()))
+      .collect(toList());
+  }
+
+  private Set<String> keepProjectsUuidsByPermission(String permission, Collection<String> projectsUuids) {
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      String userUuid = userDto == null ? null : userDto.getUuid();
+      return dbClient.authorizationDao().keepAuthorizedProjectUuids(dbSession, projectsUuids, userUuid, permission);
+    }
+  }
+
   private static Set<String> findBranchUuids(Set<ComponentDto> portfolioHierarchyComponents) {
     return portfolioHierarchyComponents.stream()
       .map(ComponentDto::getCopyComponentUuid)
-      .collect(Collectors.toSet());
+      .collect(toSet());
   }
 
   private Set<String> findProjectUuids(Set<String> branchesComponents) {
@@ -209,7 +228,7 @@ public class ServerUserSession extends AbstractUserSession {
   private Set<String> loadProjectPermissions(String projectUuid) {
     try (DbSession dbSession = dbClient.openSession(false)) {
       Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, projectUuid);
-      if (!component.isPresent()) {
+      if (component.isEmpty()) {
         return Collections.emptySet();
       }
       if (component.get().isPrivate()) {
index 47a4197b6f0d2f6cba4fd4d002d82dd833914157..855c3c5ae6496ce5b719f888f4a9702d1a13ad05 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.user;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import javax.annotation.Nullable;
 import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
 import org.junit.Rule;
@@ -29,6 +30,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -44,7 +46,6 @@ import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonar.db.component.ComponentTesting.newChildComponent;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
 import static org.sonar.db.component.ComponentTesting.newProjectCopy;
 import static org.sonar.db.component.ComponentTesting.newSubPortfolio;
 import static org.sonar.db.permission.GlobalPermission.ADMINISTER;
@@ -789,6 +790,64 @@ public class ServerUserSessionTest {
     assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", fileInBranch)).isTrue();
   }
 
+  @Test
+  public void keepAuthorizedProjects_shouldAcceptsPublicProjects_whenCalledWithPublicPermissionAndNoUser(){
+    ComponentDto publicProject  = db.components().insertPublicProject();
+    ComponentDto privateProject = db.components().insertPrivateProject();
+
+    Set<ProjectDto> projectDto = Set.of(getProjectDto(publicProject), getProjectDto(privateProject));
+    List<ProjectDto> projectDtos = newUserSession(null).keepAuthorizedProjects(USER, projectDto);
+
+    assertThat(projectDtos).containsExactly(db.components().getProjectDto(publicProject));
+  }
+
+  @Test
+  public void keepAuthorizedProjects_shouldAcceptsPublicProjects_whenCalledWithPublicPermissionAndAnUser(){
+    UserDto userDto = db.users().insertUser();
+    ComponentDto publicProject  = db.components().insertPublicProject();
+    ComponentDto privateProject = db.components().insertPrivateProject();
+
+    Set<ProjectDto> projectDto = Set.of(getProjectDto(publicProject), getProjectDto(privateProject));
+    List<ProjectDto> projectDtos = newUserSession(userDto).keepAuthorizedProjects(USER, projectDto);
+
+    assertThat(projectDtos).containsExactly(db.components().getProjectDto(publicProject));
+  }
+
+  @Test
+  public void keepAuthorizedProjects_shouldAcceptsOnlyPrivateProject_whenCalledWithGoodPermissionAndAnUser(){
+    String permission = "aNewPermission";
+    UserDto userDto = db.users().insertUser();
+    ComponentDto publicProject  = db.components().insertPublicProject();
+    ComponentDto privateProject = db.components().insertPrivateProject();
+    db.users().insertProjectPermissionOnUser(userDto, permission,privateProject);
+    ComponentDto privateProjectWithoutPermission = db.components().insertPrivateProject();
+
+    Set<ProjectDto> projectDto = Set.of(getProjectDto(publicProject), getProjectDto(privateProject), getProjectDto(privateProjectWithoutPermission));
+    List<ProjectDto> projectDtos = newUserSession(userDto).keepAuthorizedProjects(permission, projectDto);
+
+    assertThat(projectDtos).containsExactly(db.components().getProjectDto(privateProject));
+  }
+
+  @Test
+  public void keepAuthorizedProjects_shouldRejectPrivateAndPublicProject_whenCalledWithWrongPermissionAndNoUser(){
+    String permission = "aNewPermission";
+    UserDto userDto = db.users().insertUser();
+    ComponentDto publicProject  = db.components().insertPublicProject();
+    ComponentDto privateProject = db.components().insertPrivateProject();
+    db.users().insertProjectPermissionOnUser(userDto, permission,privateProject);
+    ComponentDto privateProjectWithoutPermission = db.components().insertPrivateProject();
+
+    Set<ProjectDto> projectDto = Set.of(getProjectDto(publicProject), getProjectDto(privateProject), getProjectDto(privateProjectWithoutPermission));
+    List<ProjectDto> projectDtos = newUserSession(null).keepAuthorizedProjects(permission, projectDto);
+
+    assertThat(projectDtos).isEmpty();
+  }
+
+  private ProjectDto getProjectDto(ComponentDto publicProject) {
+    return db.components().getProjectDto(publicProject);
+  }
+
+
   private ServerUserSession newUserSession(@Nullable UserDto userDto) {
     return new ServerUserSession(dbClient, userDto);
   }