Browse Source

Merge remote-tracking branch 'origin/branch-6.3'

tags/6.4-RC1
Simon Brandhof 7 years ago
parent
commit
dc75a91dcf

+ 6
- 0
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java View File

@@ -160,6 +160,12 @@ public class SearchAction implements ComponentsWsAction {
}

private List<ComponentDto> filterAuthorizedComponents(DbSession dbSession, List<ComponentDto> componentDtos) {
if (userSession.isRoot()) {
// the method AuthorizationDao#keepAuthorizedProjectIds() should be replaced by
// a call to UserSession, which would transparently support roots.
// Meanwhile root is explicitly handled.
return componentDtos;
}
Set<String> projectUuids = componentDtos.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet());
List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuids);
Map<String, Long> projectIdsByUuids = projects.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));

+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/issue/IssueStorage.java View File

@@ -100,10 +100,11 @@ public abstract class IssueStorage {
if (issue.isNew()) {
doInsert(session, now, issue);
insertChanges(issueChangeMapper, issue);
count++;
if (count > BatchSession.MAX_BATCH_SIZE) {
session.commit();
count = 0;
}
count++;
} else if (issue.isChanged()) {
toBeUpdated.add(issue);
}

+ 6
- 0
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java View File

@@ -137,6 +137,12 @@ public class SearchAction implements MeasuresWsAction {
}

private List<ComponentDto> getAuthorizedProjects(List<ComponentDto> projectDtos) {
if (userSession.isRoot()) {
// the method AuthorizationDao#keepAuthorizedProjectIds() should be replaced by
// a call to UserSession, which would transparently support roots.
// Meanwhile root is explicitly handled.
return projectDtos;
}
Map<String, Long> projectIdsByUuids = projectDtos.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
Set<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession,
projectDtos.stream().map(ComponentDto::getId).collect(toList()),

+ 19
- 2
server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java View File

@@ -96,10 +96,10 @@ public class PermissionIndexerDao {
/**
* Number of "{projectsCondition}" in SQL template
*/
private static final int NB_OF_CONDITION_PLACEHOLDERS = 3;
private static final int NB_OF_CONDITION_PLACEHOLDERS = 4;

private enum RowKind {
USER, GROUP, ANYONE
USER, GROUP, ANYONE, NONE
}

private static final String SQL_TEMPLATE = "SELECT " +
@@ -160,6 +160,21 @@ public class PermissionIndexerDao {
" AND projects.copy_component_uuid is NULL " +
" {projectsCondition} " +
" AND group_roles.group_id IS NULL " +
" UNION " +

// project is returned when no authorization
" SELECT '" + RowKind.NONE + "' as kind," +
" projects.uuid AS project, " +
" projects.authorization_updated_at AS updated_at, " +
" projects.qualifier AS qualifier, " +
" NULL AS user_id, " +
" NULL AS group_id " +
" FROM projects " +
" WHERE " +
" (projects.qualifier = 'TRK' or projects.qualifier = 'VW') " +
" AND projects.copy_component_uuid is NULL " +
" {projectsCondition} " +

" ) project_authorization";

List<Dto> selectAll(DbClient dbClient, DbSession session) {
@@ -221,6 +236,8 @@ public class PermissionIndexerDao {
dtosByProjectUuid.put(projectUuid, dto);
}
switch (rowKind) {
case NONE:
break;
case USER:
dto.addUserId(rs.getInt(3));
break;

+ 5
- 3
server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java View File

@@ -22,7 +22,6 @@ package org.sonar.server.project.ws;
import com.google.common.io.Resources;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -134,8 +133,11 @@ public class IndexAction implements ProjectsWsAction {
}

private List<ComponentDto> getAuthorizedComponents(DbSession dbSession, List<ComponentDto> components) {
if (components.isEmpty()) {
return Collections.emptyList();
if (userSession.isRoot() || components.isEmpty()) {
// the method AuthorizationDao#keepAuthorizedProjectIds() should be replaced by
// a call to UserSession, which would transparently support roots.
// Meanwhile root is explicitly handled.
return components;
}
Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet());
List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuids);

+ 6
- 0
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QgateProjectFinder.java View File

@@ -81,6 +81,12 @@ public class QgateProjectFinder {
}

private List<ProjectQgateAssociationDto> keepAuthorizedProjects(DbSession dbSession, List<ProjectQgateAssociationDto> projects) {
if (userSession.isRoot()) {
// the method AuthorizationDao#keepAuthorizedProjectIds() should be replaced by
// a call to UserSession, which would transparently support roots.
// Meanwhile root is explicitly handled.
return projects;
}
List<Long> projectIds = projects.stream().map(ProjectQgateAssociationDto::getId).collect(Collectors.toList());
Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession, projectIds, userSession.getUserId(), UserRole.USER);
return projects.stream().filter(project -> authorizedProjectIds.contains(project.getId())).collect(Collectors.toList());

+ 18
- 0
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java View File

@@ -186,6 +186,24 @@ public class SearchActionTest {
assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly(file1.getKey(), file2.getKey());
}

@Test
public void do_not_verify_permissions_if_user_is_root() throws IOException {
OrganizationDto org = db.organizations().insert();
ComponentDto project1 = newProjectDto(org);
ComponentDto file1 = newFileDto(project1);
ComponentDto project2 = newProjectDto(org);
ComponentDto file2 = newFileDto(project2);
db.components().insertComponents(project1, file1, project2, file2);

SearchWsRequest request = new SearchWsRequest().setQualifiers(singletonList(FILE)).setOrganization(org.getKey());

userSession.logIn().setNonRoot();
assertThat(call(request).getComponentsCount()).isZero();

userSession.logIn().setRoot();
assertThat(call(request).getComponentsList()).extracting(Component::getKey).containsOnly(file1.getKey(), file2.getKey());
}

@Test
public void fail_if_unknown_qualifier_provided() {
expectedException.expect(IllegalArgumentException.class);

+ 33
- 20
server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java View File

@@ -38,7 +38,6 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
@@ -79,13 +78,10 @@ public class SearchActionTest {
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);

ComponentDbTester componentDb = new ComponentDbTester(db);
DbClient dbClient = db.getDbClient();
DbSession dbSession = db.getSession();

UserDto user;

WsActionTester ws = new WsActionTester(new SearchAction(userSession, dbClient));
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
private UserDto user;
private WsActionTester ws = new WsActionTester(new SearchAction(userSession, dbClient));

@Before
public void setUp() throws Exception {
@@ -109,7 +105,7 @@ public class SearchActionTest {
@Test
public void return_measures() throws Exception {
ComponentDto project = newProjectDto(db.getDefaultOrganization());
SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project);
SnapshotDto projectSnapshot = db.components().insertProjectAndSnapshot(project);
setBrowsePermissionOnUser(project);
MetricDto coverage = insertCoverageMetric();
dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project, projectSnapshot).setValue(15.5d));
@@ -127,7 +123,7 @@ public class SearchActionTest {
@Test
public void return_measures_on_leak_period() throws Exception {
ComponentDto project = newProjectDto(db.organizations().insert());
SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project);
SnapshotDto projectSnapshot = db.components().insertProjectAndSnapshot(project);
setBrowsePermissionOnUser(project);
MetricDto coverage = insertCoverageMetric();
dbClient.measureDao().insert(dbSession,
@@ -154,11 +150,11 @@ public class SearchActionTest {
MetricDto complexity = insertComplexityMetric();
OrganizationDto organizationDto = db.organizations().insert();
ComponentDto project1 = newProjectDto(organizationDto).setName("C");
SnapshotDto projectSnapshot1 = componentDb.insertProjectAndSnapshot(project1);
SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
ComponentDto project2 = newProjectDto(organizationDto).setName("A");
SnapshotDto projectSnapshot2 = componentDb.insertProjectAndSnapshot(project2);
SnapshotDto projectSnapshot2 = db.components().insertProjectAndSnapshot(project2);
ComponentDto project3 = newProjectDto(organizationDto).setName("B");
SnapshotDto projectSnapshot3 = componentDb.insertProjectAndSnapshot(project3);
SnapshotDto projectSnapshot3 = db.components().insertProjectAndSnapshot(project3);
setBrowsePermissionOnUser(project1, project2, project3);
dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project1, projectSnapshot1).setValue(5.5d));
dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project2, projectSnapshot2).setValue(6.5d));
@@ -180,9 +176,9 @@ public class SearchActionTest {
public void only_returns_authorized_projects() {
MetricDto metricDto = insertComplexityMetric();
ComponentDto project1 = newProjectDto(db.getDefaultOrganization());
SnapshotDto projectSnapshot1 = componentDb.insertProjectAndSnapshot(project1);
SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
ComponentDto project2 = newProjectDto(db.getDefaultOrganization());
SnapshotDto projectSnapshot2 = componentDb.insertProjectAndSnapshot(project2);
SnapshotDto projectSnapshot2 = db.components().insertProjectAndSnapshot(project2);
dbClient.measureDao().insert(dbSession,
newMeasureDto(metricDto, project1, projectSnapshot1).setValue(15.5d),
newMeasureDto(metricDto, project2, projectSnapshot2).setValue(42.0d));
@@ -194,9 +190,26 @@ public class SearchActionTest {
assertThat(result.getMeasuresList()).extracting(Measure::getComponent).containsOnly(project1.key());
}

@Test
public void do_not_verify_permissions_if_user_is_root() {
MetricDto metricDto = insertComplexityMetric();
ComponentDto project1 = newProjectDto(db.getDefaultOrganization());
SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
dbClient.measureDao().insert(dbSession, newMeasureDto(metricDto, project1, projectSnapshot1).setValue(15.5d));
db.commit();

userSession.setNonRoot();
SearchWsResponse result = call(asList(project1.key()), singletonList("complexity"));
assertThat(result.getMeasuresCount()).isEqualTo(0);

userSession.setRoot();
result = call(asList(project1.key()), singletonList("complexity"));
assertThat(result.getMeasuresCount()).isEqualTo(1);
}

@Test
public void fail_if_no_metric() {
ComponentDto project = componentDb.insertProject();
ComponentDto project = db.components().insertProject();
setBrowsePermissionOnUser(project);

expectedException.expect(IllegalArgumentException.class);
@@ -207,7 +220,7 @@ public class SearchActionTest {

@Test
public void fail_if_empty_metric() {
ComponentDto project = componentDb.insertProject();
ComponentDto project = db.components().insertProject();
setBrowsePermissionOnUser(project);

expectedException.expect(IllegalArgumentException.class);
@@ -218,7 +231,7 @@ public class SearchActionTest {

@Test
public void fail_if_unknown_metric() {
ComponentDto project = componentDb.insertProject();
ComponentDto project = db.components().insertProject();
setBrowsePermissionOnUser(project);
insertComplexityMetric();

@@ -251,7 +264,7 @@ public class SearchActionTest {
@Test
public void fail_if_more_than_100_project_keys() {
List<String> keys = IntStream.rangeClosed(1, 101)
.mapToObj(i -> componentDb.insertProject())
.mapToObj(i -> db.components().insertProject())
.map(ComponentDto::key)
.collect(Collectors.toList());
insertComplexityMetric();
@@ -369,7 +382,7 @@ public class SearchActionTest {
ComponentDto project2 = newProjectDto(organizationDto).setKey("MY_PROJECT_2").setName("Project 2");
ComponentDto project3 = newProjectDto(organizationDto).setKey("MY_PROJECT_3").setName("Project 3");
projectKeys.addAll(asList(project1.key(), project2.key(), project3.key()));
componentDb.insertComponents(project1, project2, project3);
db.components().insertComponents(project1, project2, project3);
SnapshotDto projectSnapshot1 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project1)
.setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
.setPeriodMode("previous_version")

+ 17
- 20
server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java View File

@@ -95,21 +95,21 @@ public class PermissionIndexerDaoTest {

PermissionIndexerDao.Dto view1Authorization = getByProjectUuid(view1.uuid(), dtos);
assertThat(view1Authorization.getGroupIds()).containsOnly(group.getId());
assertThat(view1Authorization.isAllowAnyone()).isTrue();
assertThat(view1Authorization.isAllowAnyone()).isFalse();
assertThat(view1Authorization.getUserIds()).containsOnly(user1.getId());
assertThat(view1Authorization.getUpdatedAt()).isNotNull();
assertThat(view1Authorization.getQualifier()).isEqualTo(VIEW);

PermissionIndexerDao.Dto project2Authorization = getByProjectUuid(project2.uuid(), dtos);
assertThat(project2Authorization.getGroupIds()).isEmpty();
assertThat(project2Authorization.isAllowAnyone()).isTrue();
assertThat(project2Authorization.isAllowAnyone()).isFalse();
assertThat(project2Authorization.getUserIds()).containsOnly(user1.getId(), user2.getId());
assertThat(project2Authorization.getUpdatedAt()).isNotNull();
assertThat(project2Authorization.getQualifier()).isEqualTo(PROJECT);

PermissionIndexerDao.Dto view2Authorization = getByProjectUuid(view2.uuid(), dtos);
assertThat(view2Authorization.getGroupIds()).isEmpty();
assertThat(view2Authorization.isAllowAnyone()).isTrue();
assertThat(view2Authorization.isAllowAnyone()).isFalse();
assertThat(view2Authorization.getUserIds()).containsOnly(user1.getId(), user2.getId());
assertThat(view2Authorization.getUpdatedAt()).isNotNull();
assertThat(view2Authorization.getQualifier()).isEqualTo(VIEW);
@@ -133,21 +133,21 @@ public class PermissionIndexerDaoTest {

PermissionIndexerDao.Dto view1Authorization = dtos.get(view1.uuid());
assertThat(view1Authorization.getGroupIds()).containsOnly(group.getId());
assertThat(view1Authorization.isAllowAnyone()).isTrue();
assertThat(view1Authorization.isAllowAnyone()).isFalse();
assertThat(view1Authorization.getUserIds()).containsOnly(user1.getId());
assertThat(view1Authorization.getUpdatedAt()).isNotNull();
assertThat(view1Authorization.getQualifier()).isEqualTo(VIEW);

PermissionIndexerDao.Dto project2Authorization = dtos.get(project2.uuid());
assertThat(project2Authorization.getGroupIds()).isEmpty();
assertThat(project2Authorization.isAllowAnyone()).isTrue();
assertThat(project2Authorization.isAllowAnyone()).isFalse();
assertThat(project2Authorization.getUserIds()).containsOnly(user1.getId(), user2.getId());
assertThat(project2Authorization.getUpdatedAt()).isNotNull();
assertThat(project2Authorization.getQualifier()).isEqualTo(PROJECT);

PermissionIndexerDao.Dto view2Authorization = dtos.get(view2.uuid());
assertThat(view2Authorization.getGroupIds()).isEmpty();
assertThat(view2Authorization.isAllowAnyone()).isTrue();
assertThat(view2Authorization.isAllowAnyone()).isFalse();
assertThat(view2Authorization.getUserIds()).containsOnly(user1.getId(), user2.getId());
assertThat(view2Authorization.getUpdatedAt()).isNotNull();
assertThat(view2Authorization.getQualifier()).isEqualTo(VIEW);
@@ -176,16 +176,17 @@ public class PermissionIndexerDaoTest {
}

@Test
public void return_zero_rows_if_no_authorization() {
userDbTester.insertProjectPermissionOnUser(user1, USER, project2);
userDbTester.insertProjectPermissionOnGroup(group, USER, project2);
userDbTester.insertProjectPermissionOnUser(user1, USER, view2);
userDbTester.insertProjectPermissionOnGroup(group, USER, view2);

Collection<PermissionIndexerDao.Dto> dtos = underTest.selectAll(dbClient, dbSession);

// project1 and view1 don't have any permission
assertThat(dtos).extracting(PermissionIndexerDao.Dto::getProjectUuid).containsOnly(project2.uuid(), view2.uuid());
public void return_project_without_permission_if_no_authorization() {
List<PermissionIndexerDao.Dto> dtos = underTest.selectByUuids(dbClient, dbSession, asList(project1.uuid()));

// no permissions
assertThat(dtos).hasSize(1);
PermissionIndexerDao.Dto dto = dtos.get(0);
assertThat(dto.getGroupIds()).isEmpty();
assertThat(dto.getUserIds()).isEmpty();
assertThat(dto.isAllowAnyone()).isFalse();
assertThat(dto.getProjectUuid()).isEqualTo(project1.uuid());
assertThat(dto.getQualifier()).isEqualTo(project1.qualifier());
}

private static PermissionIndexerDao.Dto getByProjectUuid(String projectUuid, Collection<PermissionIndexerDao.Dto> dtos) {
@@ -214,9 +215,5 @@ public class PermissionIndexerDaoTest {
// Anyone group has user access on both projects
userDbTester.insertProjectPermissionOnAnyone(USER, project1);
userDbTester.insertProjectPermissionOnAnyone(ADMIN, project1);
userDbTester.insertProjectPermissionOnAnyone(USER, project2);
userDbTester.insertProjectPermissionOnAnyone(USER, view1);
userDbTester.insertProjectPermissionOnAnyone(ADMIN, view1);
userDbTester.insertProjectPermissionOnAnyone(USER, view2);
}
}

+ 22
- 1
server/sonar-server/src/test/java/org/sonar/server/project/ws/IndexActionTest.java View File

@@ -168,6 +168,28 @@ public class IndexActionTest {
verifyResult(result, "return_only_projects_authorized_for_user.json");
}

@Test
public void do_not_verify_permissions_if_user_is_root() throws Exception {
ComponentDto project = db.components().insertProject(p -> p.setKey("P1").setName("POne"));

String result = call(null, null, null);

userSession.setNonRoot();
assertThat(result).isEqualTo("[]");

userSession.setRoot();
result = call(null, null, null);
assertJson(result).isSimilarTo("[" +
" {" +
" \"id\":" + project.getId() + "," +
" \"k\":\"P1\"," +
" \"nm\":\"POne\"," +
" \"sc\":\"PRJ\"," +
" \"qu\":\"TRK\"" +
" }" +
"]");
}

@Test
public void test_example() {
insertProjectsAuthorizedForUser(
@@ -199,7 +221,6 @@ public class IndexActionTest {
private void insertProjectsAuthorizedForUser(ComponentDto... projects) {
db.components().insertComponents(projects);
setBrowsePermissionOnUser(projects);
db.commit();
}

private void setBrowsePermissionOnUser(ComponentDto... projects) {

+ 16
- 0
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java View File

@@ -37,6 +37,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.NotFoundException;
@@ -159,6 +160,21 @@ public class QgateProjectFinderTest {
verifyProjects(result, project1.getId());
}

@Test
public void do_not_verify_permissions_if_user_is_root() throws Exception {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto project = componentDbTester.insertProject(org);
ProjectQgateAssociationQuery query = builder()
.gateId(Long.toString(qGate.getId()))
.build();

userSession.logIn().setNonRoot();
verifyProjects(underTest.find(query));

userSession.logIn().setRoot();
verifyProjects(underTest.find(query), project.getId());
}

@Test
public void test_paging() throws Exception {
OrganizationDto org = dbTester.organizations().insert();

+ 9
- 13
travis.sh View File

@@ -52,22 +52,21 @@ function installMaven {
export M2_HOME=~/maven/apache-maven-3.3.9
export PATH=$M2_HOME/bin:$PATH
}

#
# Replaces the SNAPSHOT version by a version identifying the build.
# Replaces the version defined in sources, usually x.y-SNAPSHOT,
# by a version identifying the build.
# The build version is composed of 4 fields, including the semantic version and
# the build number provided by Travis.
#
# Exports the variables:
# Exported variables:
# - INITIAL_VERSION: version as defined in pom.xml
# - PROJECT_VERSION: build version. The name of this variable is important because
# it's used by QA when extracting version from Artifactory build info.
#
# The build version is composed of 4 fields, including the semantic version and
# the build number provided by Travis.
#
# Example
# Before: 6.3-SNAPSHOT
# After: 6.3.0.12345
#
# Exception: GA release like "6.3" is kept as-is.
# INITIAL_VERSION=6.3-SNAPSHOT
# PROJECT_VERSION=6.3.0.12345
#
function fixBuildVersion {
export INITIAL_VERSION=`maven_expression "project.version"`
@@ -88,10 +87,7 @@ function fixBuildVersion {
echo "Source Version: $INITIAL_VERSION"
echo "Build Version : $PROJECT_VERSION"

if [[ "$INITIAL_VERSION" == *"-"* ]]; then
# SNAPSHOT or RC
mvn org.codehaus.mojo:versions-maven-plugin:2.2:set -DnewVersion=$PROJECT_VERSION -DgenerateBackupPoms=false -B -e
fi
mvn org.codehaus.mojo:versions-maven-plugin:2.2:set -DnewVersion=$PROJECT_VERSION -DgenerateBackupPoms=false -B -e
}

#

Loading…
Cancel
Save