From 09521d602ca56b85ab31be64b3e77ec04617dc38 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Thu, 19 Aug 2021 11:09:29 -0500 Subject: [PATCH] SONAR-15259 Fix generation of subview key --- .../org/sonar/db/portfolio/PortfolioDao.java | 22 ++++++++- .../org/sonar/db/portfolio/PortfolioDto.java | 4 ++ .../sonar/db/portfolio/PortfolioMapper.java | 10 +++- .../sonar/db/portfolio/PortfolioMapper.xml | 46 ++++++++++++++++-- .../sonar/db/portfolio/PortfolioDaoTest.java | 18 ++++++- .../sonar/db/component/ComponentDbTester.java | 47 +++++++++++++++---- .../tester/AbstractMockUserSession.java | 30 +++++++++++- .../sonar/server/tester/UserSessionRule.java | 6 +++ 8 files changed, 166 insertions(+), 17 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java index aaa87d1624d..d9c49ae2178 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java @@ -51,14 +51,16 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectAllRoots(); } + public List selectAll(DbSession dbSession) { + return mapper(dbSession).selectAll(); + } + public Optional selectByKey(DbSession dbSession, String key) { return Optional.ofNullable(mapper(dbSession).selectByKey(key)); - } public Optional selectByUuid(DbSession dbSession, String uuid) { return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); - } public void insert(DbSession dbSession, PortfolioDto portfolio) { @@ -85,6 +87,10 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectAllReferencesToPortfolios(); } + public List selectAllReferencesToApplications(DbSession dbSession) { + return mapper(dbSession).selectAllReferencesToApplications(); + } + public List selectTree(DbSession dbSession, String portfolioUuid) { return mapper(dbSession).selectTree(portfolioUuid); } @@ -105,6 +111,10 @@ public class PortfolioDao implements Dao { return mapper(dbSession).selectReferencersByKey(referenceKey); } + public List selectRootOfReferencers(DbSession dbSession, String referenceUuid) { + return mapper(dbSession).selectRootOfReferencers(referenceUuid); + } + public List getProjects(DbSession dbSession, String portfolioUuid) { return mapper(dbSession).selectProjects(portfolioUuid); } @@ -138,6 +148,14 @@ public class PortfolioDao implements Dao { mapper(dbSession).deleteProjects(portfolioUuid); } + public void deleteProject(DbSession dbSession, String portfolioUuid, String projectUuid) { + mapper(dbSession).deleteProject(portfolioUuid, projectUuid); + } + + public void deleteReferencesTo(DbSession dbSession, String referenceUuid) { + mapper(dbSession).deleteReferencesTo(referenceUuid); + } + public Map selectKeysByUuids(DbSession dbSession, Collection uuids) { return executeLargeInputs(uuids, uuids1 -> mapper(dbSession).selectByUuids(uuids1)).stream() .collect(Collectors.toMap(PortfolioDto::getUuid, PortfolioDto::getKey)); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java index 9a06cc38d65..6b6c790c9b8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDto.java @@ -60,6 +60,10 @@ public class PortfolioDto { return parentUuid; } + public boolean isRoot() { + return parentUuid == null; + } + public PortfolioDto setParentUuid(@Nullable String parentUuid) { this.parentUuid = parentUuid; return this; diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java index 720ecd99e76..f019dbaed05 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java @@ -35,8 +35,6 @@ public interface PortfolioMapper { void insert(PortfolioDto portfolio); - void deleteByUuids(String portfolioUuid); - void deleteByUuids(@Param("uuids") Set uuids); void deletePortfoliosByUuids(@Param("uuids") Set uuids); @@ -59,6 +57,8 @@ public interface PortfolioMapper { List selectAllReferencesToPortfolios(); + List selectAllReferencesToApplications(); + Set selectAllProjectsInHierarchy(String rootUuid); List selectByUuids(@Param("uuids") Collection uuids); @@ -67,7 +67,13 @@ public interface PortfolioMapper { List selectAllRoots(); + List selectAll(); + + List selectRootOfReferencers(String referenceUuid); + void deleteReferencesTo(String referenceUuid); void deleteProjects(String portfolioUuid); + + void deleteProject(@Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml index 663f69e003f..3e581205004 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml @@ -63,6 +63,12 @@ p.parent_uuid is null + + + + SELECT source.uuid as sourceUuid, - source.rootUuid as sourceRootUuid, - target.uuid as sourceUuid, - target.rootUuid as sourceRootUuid + source.root_uuid as sourceRootUuid, + target.uuid as targetUuid, + target.root_uuid as targetRootUuid FROM portfolio_references pr INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid INNER JOIN portfolios target ON pr.reference_uuid = target.uuid + + DELETE FROM portfolios WHERE uuid in #{uuid,jdbcType=VARCHAR} @@ -197,6 +223,13 @@ ) + delete from portfolio_references @@ -208,6 +241,13 @@ where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} + + delete from portfolio_projects + where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} + and + project_uuid = #{projectUuid,jdbcType=VARCHAR} + + INSERT INTO portfolio_projects ( uuid, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java index 17cffd59a4a..d921b1477de 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/portfolio/PortfolioDaoTest.java @@ -30,6 +30,7 @@ import org.sonar.db.DbTester; import org.sonar.db.project.ProjectDto; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; public class PortfolioDaoTest { private final System2 system2 = new AlwaysIncreasingSystem2(1L, 1); @@ -143,7 +144,22 @@ public class PortfolioDaoTest { assertThat(portfolioDao.selectReferencersByKey(db.getSession(), "app1")) .extracting("uuid").containsOnly("portfolio1", "portfolio2"); + } + + @Test + public void selectAllReferences() { + createPortfolio("portfolio1"); + createPortfolio("portfolio2"); + createPortfolio("portfolio3"); + ProjectDto app1 = db.components().insertPrivateApplicationDto(p -> p.setDbKey("app1")); + + portfolioDao.addReference(db.getSession(), "portfolio1", "portfolio2"); + portfolioDao.addReference(db.getSession(), "portfolio2", "portfolio3"); + portfolioDao.addReference(db.getSession(), "portfolio3", "app1"); + assertThat(portfolioDao.selectAllReferencesToPortfolios(db.getSession())) + .extracting(ReferenceDto::getSourceUuid, ReferenceDto::getTargetUuid) + .containsOnly(tuple("portfolio1", "portfolio2"), tuple("portfolio2", "portfolio3")); } @Test @@ -196,7 +212,7 @@ public class PortfolioDaoTest { portfolioDao.deleteProjects(db.getSession(), "portfolio1"); assertThat(portfolioDao.getProjects(db.getSession(), "portfolio1")).isEmpty(); assertThat(portfolioDao.getProjects(db.getSession(), "portfolio2")).extracting(ProjectDto::getUuid) - .containsExactlyInAnyOrder("project2"); + .containsExactlyInAnyOrder("project2"); } @Test diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java index 2f330626468..905d3297731 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java @@ -92,8 +92,7 @@ public class ComponentDbTester { } public final ComponentDto insertPrivateProject(Consumer dtoPopulator) { - return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), - dtoPopulator); + return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), dtoPopulator); } public final ComponentDto insertPrivateProject(Consumer componentDtoPopulator, Consumer projectDtoPopulator) { @@ -102,13 +101,11 @@ public class ComponentDbTester { } public final ComponentDto insertPublicProject(Consumer dtoPopulator) { - return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), - dtoPopulator); + return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), dtoPopulator); } public final ComponentDto insertPublicProject(Consumer componentDtoPopulator, Consumer projectDtoPopulator) { - return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), componentDtoPopulator, - projectDtoPopulator); + return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), componentDtoPopulator, projectDtoPopulator); } public ProjectDto insertPublicProjectDto() { @@ -135,8 +132,7 @@ public class ComponentDbTester { return getProjectDto(componentDto); } - public ProjectDto insertPrivateProjectDto(Consumer branchPopulator, Consumer componentDtoPopulator, - Consumer projectDtoPopulator) { + public ProjectDto insertPrivateProjectDto(Consumer branchPopulator, Consumer componentDtoPopulator, Consumer projectDtoPopulator) { ComponentDto componentDto = insertPrivateProjectWithCustomBranch(branchPopulator, componentDtoPopulator, projectDtoPopulator); return getProjectDto(componentDto); } @@ -178,6 +174,41 @@ public class ComponentDbTester { return insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(false), false, dtoPopulator, portfolioPopulator); } + public final PortfolioDto insertPublicPortfolioDto(Consumer dtoPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(false), false, dtoPopulator, defaults()); + return getPortfolioDto(component); + } + + public final PortfolioDto insertPrivatePortfolioDto(Consumer dtoPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(true), true, dtoPopulator, defaults()); + return getPortfolioDto(component); + } + + public final PortfolioDto insertPrivatePortfolioDto(Consumer dtoPopulator, Consumer portfolioPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(true), true, dtoPopulator,portfolioPopulator); + return getPortfolioDto(component); + } + + public final PortfolioDto insertPublicPortfolioDto(String uuid, Consumer dtoPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio(uuid).setPrivate(false), false, dtoPopulator, defaults()); + return getPortfolioDto(component); + } + + public final PortfolioDto insertPublicPortfolioDto(String uuid, Consumer dtoPopulator, Consumer portfolioPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio(uuid).setPrivate(false), false, dtoPopulator, portfolioPopulator); + return getPortfolioDto(component); + } + + public final PortfolioDto insertPublicPortfolioDto(Consumer dtoPopulator, Consumer portfolioPopulator) { + ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(false), false, dtoPopulator, portfolioPopulator); + return getPortfolioDto(component); + } + + public PortfolioDto getPortfolioDto(ComponentDto portfolio) { + return db.getDbClient().portfolioDao().selectByUuid(dbSession, portfolio.uuid()) + .orElseThrow(() -> new IllegalStateException("Portfolio has invalid configuration")); + } + public ComponentDto insertComponentAndPortfolio(ComponentDto componentDto, boolean isPrivate, Consumer componentPopulator, Consumer portfolioPopulator) { insertComponentImpl(componentDto, isPrivate, componentPopulator); diff --git a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java index 8125df70de1..b46b99ffe27 100644 --- a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java +++ b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java @@ -30,6 +30,7 @@ import java.util.Set; import org.sonar.api.web.UserRole; import org.sonar.db.component.ComponentDto; import org.sonar.db.permission.GlobalPermission; +import org.sonar.db.portfolio.PortfolioDto; import org.sonar.db.project.ProjectDto; import org.sonar.server.user.AbstractUserSession; @@ -92,6 +93,20 @@ public abstract class AbstractMockUserSession return clazz.cast(this); } + public T registerPortfolios(PortfolioDto... portfolios) { + Arrays.stream(portfolios) + .forEach(portfolio -> { + if (!portfolio.isPrivate()) { + this.projectUuidByPermission.put(UserRole.USER, portfolio.getUuid()); + this.projectUuidByPermission.put(UserRole.CODEVIEWER, portfolio.getUuid()); + this.projectPermissions.add(UserRole.USER); + this.projectPermissions.add(UserRole.CODEVIEWER); + } + this.projectUuidByComponentUuid.put(portfolio.getUuid(), portfolio.getUuid()); + }); + return clazz.cast(this); + } + public T addProjectPermission(String permission, ComponentDto... components) { Arrays.stream(components).forEach(component -> { checkArgument( @@ -114,7 +129,20 @@ public abstract class AbstractMockUserSession registerProjects(projects); this.projectPermissions.add(permission); Arrays.stream(projects) - .forEach(component -> this.projectUuidByPermission.put(permission, component.getUuid())); + .forEach(project -> this.projectUuidByPermission.put(permission, project.getUuid())); + return clazz.cast(this); + } + + public T addPortfolioPermission(String permission, PortfolioDto... portfolios) { + Arrays.stream(portfolios).forEach(component -> { + checkArgument( + component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission), + "public component %s can't be granted public permission %s", component.getUuid(), permission); + }); + registerPortfolios(portfolios); + this.projectPermissions.add(permission); + Arrays.stream(portfolios) + .forEach(portfolio -> this.projectUuidByPermission.put(permission, portfolio.getUuid())); return clazz.cast(this); } diff --git a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java index d85fa44e2c2..b0bdbce1cf2 100644 --- a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java +++ b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java @@ -30,6 +30,7 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.sonar.db.component.ComponentDto; import org.sonar.db.permission.GlobalPermission; +import org.sonar.db.portfolio.PortfolioDto; import org.sonar.db.project.ProjectDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; @@ -202,6 +203,11 @@ public class UserSessionRule implements TestRule, UserSession { return this; } + public UserSessionRule addPortfolioPermission(String portfolioPermission, PortfolioDto... portfolioDto) { + ensureAbstractMockUserSession().addPortfolioPermission(portfolioPermission, portfolioDto); + return this; + } + public UserSessionRule addPermission(GlobalPermission permission) { ensureAbstractMockUserSession().addPermission(permission); return this; -- 2.39.5