@@ -51,14 +51,16 @@ public class PortfolioDao implements Dao { | |||
return mapper(dbSession).selectAllRoots(); | |||
} | |||
public List<PortfolioDto> selectAll(DbSession dbSession) { | |||
return mapper(dbSession).selectAll(); | |||
} | |||
public Optional<PortfolioDto> selectByKey(DbSession dbSession, String key) { | |||
return Optional.ofNullable(mapper(dbSession).selectByKey(key)); | |||
} | |||
public Optional<PortfolioDto> 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<ReferenceDto> selectAllReferencesToApplications(DbSession dbSession) { | |||
return mapper(dbSession).selectAllReferencesToApplications(); | |||
} | |||
public List<PortfolioDto> 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<PortfolioDto> selectRootOfReferencers(DbSession dbSession, String referenceUuid) { | |||
return mapper(dbSession).selectRootOfReferencers(referenceUuid); | |||
} | |||
public List<ProjectDto> 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<String, String> selectKeysByUuids(DbSession dbSession, Collection<String> uuids) { | |||
return executeLargeInputs(uuids, uuids1 -> mapper(dbSession).selectByUuids(uuids1)).stream() | |||
.collect(Collectors.toMap(PortfolioDto::getUuid, PortfolioDto::getKey)); |
@@ -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; |
@@ -35,8 +35,6 @@ public interface PortfolioMapper { | |||
void insert(PortfolioDto portfolio); | |||
void deleteByUuids(String portfolioUuid); | |||
void deleteByUuids(@Param("uuids") Set<String> uuids); | |||
void deletePortfoliosByUuids(@Param("uuids") Set<String> uuids); | |||
@@ -59,6 +57,8 @@ public interface PortfolioMapper { | |||
List<ReferenceDto> selectAllReferencesToPortfolios(); | |||
List<ReferenceDto> selectAllReferencesToApplications(); | |||
Set<PortfolioProjectDto> selectAllProjectsInHierarchy(String rootUuid); | |||
List<PortfolioDto> selectByUuids(@Param("uuids") Collection<String> uuids); | |||
@@ -67,7 +67,13 @@ public interface PortfolioMapper { | |||
List<PortfolioDto> selectAllRoots(); | |||
List<PortfolioDto> selectAll(); | |||
List<PortfolioDto> selectRootOfReferencers(String referenceUuid); | |||
void deleteReferencesTo(String referenceUuid); | |||
void deleteProjects(String portfolioUuid); | |||
void deleteProject(@Param("portfolioUuid") String portfolioUuid, @Param("projectUuid") String projectUuid); | |||
} |
@@ -63,6 +63,12 @@ | |||
p.parent_uuid is null | |||
</select> | |||
<select id="selectAll" resultType="Portfolio"> | |||
SELECT | |||
<include refid="portfolioColumns"/> | |||
FROM portfolios p | |||
</select> | |||
<select id="selectProjects" resultType="Project"> | |||
SELECT | |||
<include refid="projectColumns"/> | |||
@@ -94,6 +100,15 @@ | |||
p.portfolio_uuid=#{portfolioUuid,jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectRootOfReferencers" resultType="Portfolio"> | |||
SELECT distinct <include refid="portfolioColumns"/> | |||
FROM portfolios c | |||
INNER JOIN portfolio_references pr on pr.portfolio_uuid = c.uuid | |||
INNER JOIN portfolios p on p.uuid = c.root_uuid | |||
where | |||
pr.reference_uuid=#{referenceUuid,jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectTree" parameterType="String" resultType="Portfolio"> | |||
SELECT <include refid="portfolioColumns"/> | |||
FROM portfolios p | |||
@@ -157,14 +172,25 @@ | |||
<select id="selectAllReferencesToPortfolios" resultType="org.sonar.db.portfolio.ReferenceDto"> | |||
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 | |||
</select> | |||
<select id="selectAllReferencesToApplications" resultType="org.sonar.db.portfolio.ReferenceDto"> | |||
SELECT | |||
source.uuid as sourceUuid, | |||
source.root_uuid as sourceRootUuid, | |||
target.uuid as targetUuid, | |||
target.uuid as targetRootUuid | |||
FROM portfolio_references pr | |||
INNER JOIN portfolios source ON pr.portfolio_uuid = source.uuid | |||
INNER JOIN projects target ON pr.reference_uuid = target.uuid where target.qualifier = 'APP' | |||
</select> | |||
<delete id="deletePortfoliosByUuids" parameterType="String"> | |||
DELETE FROM portfolios WHERE uuid in | |||
<foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid,jdbcType=VARCHAR}</foreach> | |||
@@ -197,6 +223,13 @@ | |||
) | |||
</insert> | |||
<select id="selectReferencesTo" parameterType="String"> | |||
SELECT | |||
<include refid="portfolioColumns"/> | |||
FROM portfolios p | |||
INNER JOIN portfolio_references pr ON p.uuid = pr.portfolio_uuid | |||
where pr.reference_uuid = #{referenceUuid,jdbcType=VARCHAR} | |||
</select> | |||
<delete id="deleteReferencesTo" parameterType="String"> | |||
delete from portfolio_references | |||
@@ -208,6 +241,13 @@ | |||
where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} | |||
</delete> | |||
<delete id="deleteProject" parameterType="map"> | |||
delete from portfolio_projects | |||
where portfolio_uuid = #{portfolioUuid,jdbcType=VARCHAR} | |||
and | |||
project_uuid = #{projectUuid,jdbcType=VARCHAR} | |||
</delete> | |||
<insert id="insertProject" parameterType="PortfolioProject"> | |||
INSERT INTO portfolio_projects ( | |||
uuid, |
@@ -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 |
@@ -92,8 +92,7 @@ public class ComponentDbTester { | |||
} | |||
public final ComponentDto insertPrivateProject(Consumer<ComponentDto> dtoPopulator) { | |||
return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), | |||
dtoPopulator); | |||
return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), dtoPopulator); | |||
} | |||
public final ComponentDto insertPrivateProject(Consumer<ComponentDto> componentDtoPopulator, Consumer<ProjectDto> projectDtoPopulator) { | |||
@@ -102,13 +101,11 @@ public class ComponentDbTester { | |||
} | |||
public final ComponentDto insertPublicProject(Consumer<ComponentDto> dtoPopulator) { | |||
return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), | |||
dtoPopulator); | |||
return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), dtoPopulator); | |||
} | |||
public final ComponentDto insertPublicProject(Consumer<ComponentDto> componentDtoPopulator, Consumer<ProjectDto> 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<BranchDto> branchPopulator, Consumer<ComponentDto> componentDtoPopulator, | |||
Consumer<ProjectDto> projectDtoPopulator) { | |||
public ProjectDto insertPrivateProjectDto(Consumer<BranchDto> branchPopulator, Consumer<ComponentDto> componentDtoPopulator, Consumer<ProjectDto> 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<ComponentDto> dtoPopulator) { | |||
ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(false), false, dtoPopulator, defaults()); | |||
return getPortfolioDto(component); | |||
} | |||
public final PortfolioDto insertPrivatePortfolioDto(Consumer<ComponentDto> dtoPopulator) { | |||
ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(true), true, dtoPopulator, defaults()); | |||
return getPortfolioDto(component); | |||
} | |||
public final PortfolioDto insertPrivatePortfolioDto(Consumer<ComponentDto> dtoPopulator, Consumer<PortfolioDto> portfolioPopulator) { | |||
ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio().setPrivate(true), true, dtoPopulator,portfolioPopulator); | |||
return getPortfolioDto(component); | |||
} | |||
public final PortfolioDto insertPublicPortfolioDto(String uuid, Consumer<ComponentDto> dtoPopulator) { | |||
ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio(uuid).setPrivate(false), false, dtoPopulator, defaults()); | |||
return getPortfolioDto(component); | |||
} | |||
public final PortfolioDto insertPublicPortfolioDto(String uuid, Consumer<ComponentDto> dtoPopulator, Consumer<PortfolioDto> portfolioPopulator) { | |||
ComponentDto component = insertComponentAndPortfolio(ComponentTesting.newPortfolio(uuid).setPrivate(false), false, dtoPopulator, portfolioPopulator); | |||
return getPortfolioDto(component); | |||
} | |||
public final PortfolioDto insertPublicPortfolioDto(Consumer<ComponentDto> dtoPopulator, Consumer<PortfolioDto> 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<ComponentDto> componentPopulator, | |||
Consumer<PortfolioDto> portfolioPopulator) { | |||
insertComponentImpl(componentDto, isPrivate, componentPopulator); |
@@ -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<T extends 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<T extends 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); | |||
} | |||
@@ -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; |