diff options
author | Benjamin Campomenosi <109955405+benjamin-campomenosi-sonarsource@users.noreply.github.com> | 2022-10-13 15:29:43 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-10-13 20:03:18 +0000 |
commit | 3b01b425c30c5997b46a75076777af93765442ac (patch) | |
tree | b49d7638e4947a7d218f467350ecbf547d7a2273 | |
parent | 7004db190a00787bf7a890f4c76d6b76a1f3cab9 (diff) | |
download | sonarqube-3b01b425c30c5997b46a75076777af93765442ac.tar.gz sonarqube-3b01b425c30c5997b46a75076777af93765442ac.zip |
SONAR-16588 improve project authorization search
2 files changed, 82 insertions, 4 deletions
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java index a826f6fdda0..2d1ad370edf 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java @@ -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()) { diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java index 47a4197b6f0..855c3c5ae64 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java @@ -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); } |