aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCody Simms <141657208+cody-simms-sonarsource@users.noreply.github.com>2024-12-18 09:58:49 -0600
committersonartech <sonartech@sonarsource.com>2024-12-18 20:03:11 +0000
commitab3125728559f0d37ae3210610335c210dac02ba (patch)
tree9e10fdb801ba57c5f931fef505722dc5201fba4f
parentec0d8ad9cdb8097ddee68ceada41abd0b2632032 (diff)
downloadsonarqube-ab3125728559f0d37ae3210610335c210dac02ba.tar.gz
sonarqube-ab3125728559f0d37ae3210610335c210dac02ba.zip
SONAR-23936 Query all portfolio projects at once rather than recursively
Co-authored-by: Duarte Meneses <duarte.meneses@sonarsource.com>
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java34
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java10
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml25
-rw-r--r--server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java67
4 files changed, 62 insertions, 74 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
index 437961a5470..59dcb3ede0c 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
@@ -61,7 +61,8 @@ public class ComponentDao implements Dao {
}
public ComponentDto selectOrFailByUuid(DbSession session, String uuid) {
- return selectByUuid(session, uuid).orElseThrow(() -> new RowNotFoundException(String.format("Component with uuid '%s' not found", uuid)));
+ return selectByUuid(session, uuid).orElseThrow(() -> new RowNotFoundException(String.format("Component with uuid '%s' not found",
+ uuid)));
}
public List<ComponentDto> selectByUuids(DbSession session, Collection<String> uuids) {
@@ -99,18 +100,24 @@ public class ComponentDao implements Dao {
*/
/**
- * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
- * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
- * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getComponentIds() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
*/
public List<ComponentDto> selectByQuery(DbSession dbSession, ComponentQuery query, Pagination pagination) {
return selectByQueryImpl(dbSession, query, pagination);
}
/**
- * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
- * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
- * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getComponentIds() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
+ * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than
+ * {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values
*/
public int countByQuery(DbSession session, ComponentQuery query) {
return countByQueryImpl(session, query);
@@ -158,7 +165,8 @@ public class ComponentDao implements Dao {
/**
* If no branch or pull request is provided, returns components in the main branch
*/
- public List<ComponentDto> selectByKeys(DbSession session, Collection<String> keys, @Nullable String branch, @Nullable String pullRequest) {
+ public List<ComponentDto> selectByKeys(DbSession session, Collection<String> keys, @Nullable String branch,
+ @Nullable String pullRequest) {
checkState(branch == null || pullRequest == null, "Can't set both branch and pull request");
return executeLargeInputs(keys, subKeys -> mapper(session).selectByKeysAndBranchOrPr(subKeys, branch, pullRequest));
}
@@ -250,8 +258,10 @@ public class ComponentDao implements Dao {
* Returns components with open issues from P/Rs that use a certain branch as reference (reference branch).
* Excludes components from the current branch.
*/
- public List<KeyWithUuidDto> selectComponentsFromPullRequestsTargetingCurrentBranchThatHaveOpenIssues(DbSession dbSession, String referenceBranchUuid, String currentBranchUuid) {
- return mapper(dbSession).selectComponentsFromPullRequestsTargetingCurrentBranchThatHaveOpenIssues(referenceBranchUuid, currentBranchUuid);
+ public List<KeyWithUuidDto> selectComponentsFromPullRequestsTargetingCurrentBranchThatHaveOpenIssues(DbSession dbSession,
+ String referenceBranchUuid, String currentBranchUuid) {
+ return mapper(dbSession).selectComponentsFromPullRequestsTargetingCurrentBranchThatHaveOpenIssues(referenceBranchUuid,
+ currentBranchUuid);
}
/**
@@ -329,7 +339,8 @@ public class ComponentDao implements Dao {
mapper(session).setPrivateForBranchUuid(branchUuid, isPrivate);
}
- public void setPrivateForBranchUuid(DbSession session, String branchUuid, boolean isPrivate, String qualifier, String componentKey, String componentName) {
+ public void setPrivateForBranchUuid(DbSession session, String branchUuid, boolean isPrivate, String qualifier, String componentKey,
+ String componentName) {
ComponentNewValue componentNewValue = new ComponentNewValue(branchUuid, componentName, componentKey, isPrivate, qualifier);
//TODO we should log change to the visibility in EntityDao, not ComponentDao
auditPersister.updateComponentVisibility(session, componentNewValue);
@@ -351,5 +362,4 @@ public class ComponentDao implements Dao {
checkThatNotTooManyConditions(query.getComponentKeys(), "Too many component keys in query");
checkThatNotTooManyConditions(query.getComponentUuids(), "Too many component UUIDs in query");
}
-
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java
index 7b61364c650..7d26dc3d09f 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java
@@ -33,7 +33,8 @@ public interface ComponentMapper {
List<ComponentDto> selectByKeyCaseInsensitive(@Param("key") String key);
@CheckForNull
- ComponentDto selectByKeyAndBranchOrPr(@Param("key") String key, @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest);
+ ComponentDto selectByKeyAndBranchOrPr(@Param("key") String key, @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest"
+ ) String pullRequest);
@CheckForNull
ComponentDto selectByUuid(@Param("uuid") String uuid);
@@ -58,7 +59,8 @@ public interface ComponentMapper {
int countByQuery(@Param("query") ComponentQuery query);
- List<ComponentDto> selectDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuid") String baseUuid, @Param("baseUuidPath") String baseUuidPath);
+ List<ComponentDto> selectDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuid") String baseUuid, @Param("baseUuidPath"
+ ) String baseUuidPath);
List<ComponentDto> selectChildren(@Param("branchUuid") String branchUuid, @Param("uuidPaths") Set<String> uuidPaths);
@@ -111,5 +113,7 @@ public interface ComponentMapper {
List<KeyWithUuidDto> selectComponentsFromBranchesThatHaveOpenIssues(@Param("branchUuids") List<String> branchUuids);
- short checkIfAnyOfComponentsWithQualifiers(@Param("componentKeys") Collection<String> componentKeys, @Param("qualifiers") Set<String> qualifiers);
+ short checkIfAnyOfComponentsWithQualifiers(@Param("componentKeys") Collection<String> componentKeys,
+ @Param("qualifiers") Set<String> qualifiers);
+
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml
index d0be1f8bcfa..0d340aa7046 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml
@@ -162,9 +162,10 @@
and gr.group_uuid = gu.group_uuid
)
)
- and <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=" or ">
- gr.entity_uuid=#{element, jdbcType=VARCHAR}
- </foreach>
+ and gr.entity_uuid in
+ <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=",">
+ #{element, jdbcType=VARCHAR}
+ </foreach>
union
@@ -177,8 +178,9 @@
where
ur.role=#{role, jdbcType=VARCHAR}
and ur.user_uuid=#{userUuid, jdbcType=INTEGER}
- and <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=" or ">
- entity.uuid=#{element, jdbcType=VARCHAR}
+ and entity.uuid in
+ <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=",">
+ #{element, jdbcType=VARCHAR}
</foreach>
union
@@ -191,9 +193,9 @@
entity.uuid
from
(<include refid="org.sonar.db.entity.EntityMapper.selectAll"/>) entity
- where
- <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=" or ">
- entity.uuid=#{element ,jdbcType=VARCHAR}
+ where entity.uuid in
+ <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=",">
+ #{element ,jdbcType=VARCHAR}
</foreach>
and entity.isPrivate = ${_false}
and #{role, jdbcType=VARCHAR} in ('user','codeviewer')
@@ -207,9 +209,10 @@
where
gr.role=#{role, jdbcType=VARCHAR}
and gr.group_uuid is null
- and <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=" or ">
- gr.entity_uuid=#{element, jdbcType=VARCHAR}
- </foreach>
+ and gr.entity_uuid in
+ <foreach collection="entityUuids" open="(" close=")" item="element" index="index" separator=",">
+ #{element, jdbcType=VARCHAR}
+ </foreach>
union
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 d4c20ff8bc9..4f973599cc7 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
@@ -32,12 +32,12 @@ import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.sonar.db.component.ComponentQualifiers;
-import org.sonar.db.component.ComponentScopes;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentQualifiers;
+import org.sonar.db.component.ComponentScopes;
import org.sonar.db.component.ComponentTreeQuery;
import org.sonar.db.component.ComponentTreeQuery.Strategy;
import org.sonar.db.entity.EntityDto;
@@ -49,9 +49,9 @@ import static java.util.Collections.singleton;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toSet;
+import static org.sonar.api.web.UserRole.PUBLIC_PERMISSIONS;
import static org.sonar.db.component.ComponentQualifiers.SUBVIEW;
import static org.sonar.db.component.ComponentQualifiers.VIEW;
-import static org.sonar.api.web.UserRole.PUBLIC_PERMISSIONS;
/**
* Implementation of {@link UserSession} used in web server
@@ -178,9 +178,8 @@ public class ServerUserSession extends AbstractUserSession {
@Override
protected boolean hasPortfolioChildProjectsPermission(String permission, String portfolioUuid) {
- Set<ComponentDto> portfolioHierarchyComponents = resolvePortfolioHierarchyComponents(portfolioUuid);
- Set<String> branchUuids = findBranchUuids(portfolioHierarchyComponents);
- Set<String> projectUuids = findProjectUuids(branchUuids);
+ // portfolioUuid might be the UUID of a sub portfolio
+ Set<String> projectUuids = findProjectUuids(portfolioUuid);
Set<String> projectsWithPermission = keepEntitiesUuidsByPermission(permission, projectUuids);
return projectsWithPermission.containsAll(projectUuids);
@@ -204,16 +203,21 @@ public class ServerUserSession extends AbstractUserSession {
}
}
- private static Set<String> findBranchUuids(Set<ComponentDto> portfolioHierarchyComponents) {
- return portfolioHierarchyComponents.stream()
- .map(ComponentDto::getCopyComponentUuid)
- .collect(toSet());
- }
-
- private Set<String> findProjectUuids(Set<String> branchesComponentsUuid) {
+ private Set<String> findProjectUuids(String portfolioUuid) {
try (DbSession dbSession = dbClient.openSession(false)) {
- List<ComponentDto> componentDtos = dbClient.componentDao().selectByUuids(dbSession, branchesComponentsUuid);
- return getProjectUuids(dbSession, componentDtos);
+ List<ComponentDto> portfolioLeaves = dbClient.componentDao().selectDescendants(dbSession, ComponentTreeQuery.builder()
+ .setBaseUuid(portfolioUuid)
+ .setQualifiers(List.of(ComponentQualifiers.PROJECT))
+ .setStrategy(Strategy.LEAVES).build());
+
+ Set<String> projectBranchUuids = portfolioLeaves.stream()
+ .map(ComponentDto::getCopyComponentUuid)
+ .filter(Objects::nonNull)
+ .collect(toSet());
+
+ return dbClient.branchDao().selectByUuids(dbSession, projectBranchUuids).stream()
+ .map(BranchDto::getProjectUuid)
+ .collect(toSet());
}
}
@@ -297,39 +301,6 @@ public class ServerUserSession extends AbstractUserSession {
}
}
- private List<ComponentDto> getDirectChildComponents(String portfolioUuid) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- return dbClient.componentDao().selectDescendants(dbSession, ComponentTreeQuery.builder()
- .setBaseUuid(portfolioUuid)
- .setQualifiers(Arrays.asList(ComponentQualifiers.PROJECT, ComponentQualifiers.SUBVIEW))
- .setStrategy(Strategy.CHILDREN).build());
- }
- }
-
- private Set<ComponentDto> resolvePortfolioHierarchyComponents(String parentComponentUuid) {
- Set<ComponentDto> portfolioHierarchyProjects = new HashSet<>();
- resolvePortfolioHierarchyComponents(parentComponentUuid, portfolioHierarchyProjects);
- return portfolioHierarchyProjects;
- }
-
- private void resolvePortfolioHierarchyComponents(String parentComponentUuid, Set<ComponentDto> hierarchyChildComponents) {
- List<ComponentDto> childComponents = getDirectChildComponents(parentComponentUuid);
-
- if (childComponents.isEmpty()) {
- return;
- }
-
- childComponents.forEach(c -> {
- if (c.getCopyComponentUuid() != null) {
- hierarchyChildComponents.add(c);
- }
-
- if (ComponentQualifiers.SUBVIEW.equals(c.qualifier())) {
- resolvePortfolioHierarchyComponents(c.uuid(), hierarchyChildComponents);
- }
- });
- }
-
private Set<GlobalPermission> loadGlobalPermissions() {
Set<String> permissionKeys;
try (DbSession dbSession = dbClient.openSession(false)) {