summaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-08-04 14:28:41 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-08-04 14:33:19 +0200
commit324e7ea6fb166942a519dfac10647eae5af803cd (patch)
treec132452ed535e403b3c17b85f875ea836d85a805 /server/sonar-server
parent2124979c80e18d7c5c098bfe97e91671d75ec290 (diff)
downloadsonarqube-324e7ea6fb166942a519dfac10647eae5af803cd.tar.gz
sonarqube-324e7ea6fb166942a519dfac10647eae5af803cd.zip
SONAR-5402 Fix issue on provisionned projects
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsJsonWriter.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java37
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java42
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsJsonWriterTest.java12
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java53
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileProjectOperationsMediumTest.java159
9 files changed, 299 insertions, 55 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java
index 657287999b7..5b6ff6d7ec8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java
@@ -21,6 +21,7 @@ package org.sonar.server.component.persistence;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.System2;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.db.ComponentMapper;
import org.sonar.core.persistence.DaoComponent;
@@ -43,6 +44,15 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String>
}
public ComponentDto getById(Long id, DbSession session) {
+ ComponentDto componentDto = getNullableById(id, session);
+ if (componentDto == null) {
+ throw new NotFoundException(String.format("Project with id '%s' not found", id));
+ }
+ return componentDto;
+ }
+
+ @CheckForNull
+ public ComponentDto getNullableById(Long id, DbSession session) {
return mapper(session).selectById(id);
}
@@ -67,7 +77,21 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String>
return mapper(session).findModulesByProject(projectKey);
}
+ @CheckForNull
+ public AuthorizedComponentDto getNullableAuthorizedComponentById(Long id, DbSession session) {
+ return mapper(session).selectAuthorizedComponentById(id);
+ }
+
+ public AuthorizedComponentDto getAuthorizedComponentById(Long id, DbSession session) {
+ AuthorizedComponentDto componentDto = getNullableAuthorizedComponentById(id, session);
+ if (componentDto == null) {
+ throw new NotFoundException(String.format("Project with id '%s' not found", id));
+ }
+ return componentDto;
+ }
+
@Override
+ @CheckForNull
protected ComponentDto doGetNullableByKey(DbSession session, String key) {
return mapper(session).selectByKey(key);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsJsonWriter.java b/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsJsonWriter.java
index ccc2afb7032..2c6addbbfb4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsJsonWriter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsJsonWriter.java
@@ -125,7 +125,7 @@ public class DuplicationsJsonWriter implements ServerComponent {
private ComponentDto getProject(@Nullable Long projectId, Map<Long, ComponentDto> projectsById, DbSession session) {
ComponentDto project = projectsById.get(projectId);
if (project == null && projectId != null) {
- project = componentDao.getById(projectId, session);
+ project = componentDao.getNullableById(projectId, session);
if (project != null) {
projectsById.put(project.getId(), project);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
index e627be18a6c..8ce814ba46c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
@@ -29,6 +29,8 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metric.ValueType;
import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
@@ -207,12 +209,10 @@ public class QualityGates {
}
public void associateProject(Long qGateId, Long projectId) {
- checkPermission(UserSession.get());
-
DbSession session = myBatis.openSession(false);
try {
getNonNullQgate(qGateId);
- checkNonNullProject(projectId, session);
+ checkPermission(UserSession.get(), projectId, session);
propertiesDao.setProperty(new PropertyDto().setKey(SONAR_QUALITYGATE_PROPERTY).setResourceId(projectId).setValue(qGateId.toString()));
} finally {
MyBatis.closeQuietly(session);
@@ -220,12 +220,10 @@ public class QualityGates {
}
public void dissociateProject(Long qGateId, Long projectId) {
- checkPermission(UserSession.get());
-
DbSession session = myBatis.openSession(false);
try {
getNonNullQgate(qGateId);
- checkNonNullProject(projectId, session);
+ checkPermission(UserSession.get(), projectId, session);
propertiesDao.deleteProjectProperty(SONAR_QUALITYGATE_PROPERTY, projectId);
} finally {
MyBatis.closeQuietly(session);
@@ -338,12 +336,6 @@ public class QualityGates {
return condition;
}
- private void checkNonNullProject(long projectId, DbSession session) {
- if (!componentDao.existsById(projectId, session)) {
- throw new NotFoundException("There is no project with id=" + projectId);
- }
- }
-
private void validateQualityGate(@Nullable Long updatingQgateId, @Nullable String name) {
Errors errors = new Errors();
if (Strings.isNullOrEmpty(name)) {
@@ -366,4 +358,11 @@ public class QualityGates {
private void checkPermission(UserSession userSession) {
userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
}
+
+ private void checkPermission(UserSession userSession, Long projectId, DbSession session) {
+ AuthorizedComponentDto project = componentDao.getAuthorizedComponentById(projectId, session);
+ if (!userSession.hasGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN) && !userSession.hasProjectPermission(UserRole.ADMIN, project.key())) {
+ throw new ForbiddenException("Insufficient privileges");
+ }
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java
index 429b192a336..2d5724b9383 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java
@@ -21,17 +21,21 @@
package org.sonar.server.qualityprofile;
import org.sonar.api.ServerComponent;
-import org.sonar.api.component.Component;
-import org.sonar.core.component.ComponentDto;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.properties.PropertyDto;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.user.UserSession;
+/**
+ * Should be refactored in order to use project key. Mabye should it be move to {@link QProfileFactory}
+ * Permission checks should also be done in the upper service.
+ */
public class QProfileProjectOperations implements ServerComponent {
private final DbClient db;
@@ -41,7 +45,6 @@ public class QProfileProjectOperations implements ServerComponent {
}
public void addProject(int profileId, long projectId, UserSession userSession) {
- checkPermission(userSession);
DbSession session = db.openSession(false);
try {
addProject(profileId, projectId, userSession, session);
@@ -52,8 +55,8 @@ public class QProfileProjectOperations implements ServerComponent {
}
void addProject(int profileId, long projectId, UserSession userSession, DbSession session) {
- checkPermission(userSession);
- ComponentDto project = (ComponentDto) findProjectNotNull(projectId, session);
+ AuthorizedComponentDto project = db.componentDao().getAuthorizedComponentById(projectId, session);
+ checkPermission(userSession, project.key());
QualityProfileDto qualityProfile = findNotNull(profileId, session);
db.propertiesDao().setProperty(new PropertyDto().setKey(
@@ -62,10 +65,10 @@ public class QProfileProjectOperations implements ServerComponent {
}
public void removeProject(int profileId, long projectId, UserSession userSession) {
- checkPermission(userSession);
DbSession session = db.openSession(false);
try {
- ComponentDto project = (ComponentDto) findProjectNotNull(projectId, session);
+ AuthorizedComponentDto project = db.componentDao().getAuthorizedComponentById(projectId, session);
+ checkPermission(userSession, project.key());
QualityProfileDto qualityProfile = findNotNull(profileId, session);
db.propertiesDao().deleteProjectProperty(QProfileProjectLookup.PROFILE_PROPERTY_PREFIX + qualityProfile.getLanguage(), project.getId(), session);
@@ -76,10 +79,10 @@ public class QProfileProjectOperations implements ServerComponent {
}
public void removeProject(String language, long projectId, UserSession userSession) {
- checkPermission(userSession);
DbSession session = db.openSession(false);
try {
- ComponentDto project = (ComponentDto) findProjectNotNull(projectId, session);
+ AuthorizedComponentDto project = db.componentDao().getAuthorizedComponentById(projectId, session);
+ checkPermission(userSession, project.key());
db.propertiesDao().deleteProjectProperty(QProfileProjectLookup.PROFILE_PROPERTY_PREFIX + language, project.getId(), session);
session.commit();
@@ -106,16 +109,14 @@ public class QProfileProjectOperations implements ServerComponent {
return qualityProfile;
}
- private Component findProjectNotNull(long projectId, DbSession session) {
- Component component = db.resourceDao().findById(projectId, session);
- if (component == null) {
- throw new NotFoundException("This project does not exist");
- }
- return component;
- }
-
private void checkPermission(UserSession userSession) {
userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
}
+ private void checkPermission(UserSession userSession, String projectKey) {
+ if (!userSession.hasGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN) && !userSession.hasProjectPermission(UserRole.ADMIN, projectKey)) {
+ throw new ForbiddenException("Insufficient privileges");
+ }
+ }
+
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
index 2fb0b470d19..fde5a90ed2f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
@@ -193,8 +193,6 @@ public class QProfileService implements ServerComponent {
/**
* Used in /api/profiles and in /profiles/export
- * @param language
- * @return
*/
@CheckForNull
public QualityProfileDto getDefault(String language) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java
index 190127ecca3..4ff1d97a556 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java
@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
@@ -97,7 +98,21 @@ public class ComponentDaoTest extends AbstractDaoTestCase {
setupData("shared");
assertThat(dao.getById(4L, session)).isNotNull();
- assertThat(dao.getById(111L, session)).isNull();
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void fail_to_get_by_id_when_project_not_found() {
+ setupData("shared");
+
+ dao.getById(111L, session);
+ }
+
+ @Test
+ public void get_nullable_by_id() {
+ setupData("shared");
+
+ assertThat(dao.getNullableById(4L, session)).isNotNull();
+ assertThat(dao.getNullableById(111L, session)).isNull();
}
@Test
@@ -153,6 +168,31 @@ public class ComponentDaoTest extends AbstractDaoTestCase {
}
@Test
+ public void get_nullable_authorized_component_by_id() {
+ setupData("shared");
+
+ AuthorizedComponentDto result = dao.getNullableAuthorizedComponentById(4L, session);
+ assertThat(result).isNotNull();
+ assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+
+ assertThat(dao.getNullableAuthorizedComponentById(111L, session)).isNull();
+ }
+
+ @Test
+ public void get_authorized_component_by_id() {
+ setupData("shared");
+
+ assertThat(dao.getAuthorizedComponentById(4L, session)).isNotNull();
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void fail_to_get_authorized_component_by_id_when_project_not_found() {
+ setupData("shared");
+
+ dao.getAuthorizedComponentById(111L, session);
+ }
+
+ @Test
public void insert() {
when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime());
setupData("empty");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsJsonWriterTest.java b/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsJsonWriterTest.java
index 6a26a071871..226f7d4ecec 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsJsonWriterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsJsonWriterTest.java
@@ -66,8 +66,8 @@ public class DuplicationsJsonWriterTest {
when(componentDao.getNullableByKey(session, key1)).thenReturn(file1);
when(componentDao.getNullableByKey(session, key2)).thenReturn(file2);
- when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
- when(componentDao.getById(5L, session)).thenReturn(new ComponentDto().setId(5L).setKey("org.codehaus.sonar:sonar-ws-client").setLongName("SonarQube :: Web Service Client"));
+ when(componentDao.getNullableById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
+ when(componentDao.getNullableById(5L, session)).thenReturn(new ComponentDto().setId(5L).setKey("org.codehaus.sonar:sonar-ws-client").setLongName("SonarQube :: Web Service Client"));
List<DuplicationsParser.Block> blocks = newArrayList();
blocks.add(new DuplicationsParser.Block(newArrayList(
@@ -112,8 +112,8 @@ public class DuplicationsJsonWriterTest {
verify(componentDao, times(2)).getNullableByKey(eq(session), anyString());
// Verify call to dao is cached when searching for project / sub project
- verify(componentDao, times(1)).getById(eq(1L), eq(session));
- verify(componentDao, times(1)).getById(eq(5L), eq(session));
+ verify(componentDao, times(1)).getNullableById(eq(1L), eq(session));
+ verify(componentDao, times(1)).getNullableById(eq(5L), eq(session));
}
@Test
@@ -125,7 +125,7 @@ public class DuplicationsJsonWriterTest {
when(componentDao.getNullableByKey(session, key1)).thenReturn(file1);
when(componentDao.getNullableByKey(session, key2)).thenReturn(file2);
- when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
+ when(componentDao.getNullableById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
List<DuplicationsParser.Block> blocks = newArrayList();
blocks.add(new DuplicationsParser.Block(newArrayList(
@@ -171,7 +171,7 @@ public class DuplicationsJsonWriterTest {
ComponentDto file1 = new ComponentDto().setId(10L).setQualifier("FIL").setKey(key1).setLongName("PropertyDeleteQuery").setProjectId(1L);
when(componentDao.getNullableByKey(session, key1)).thenReturn(file1);
- when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
+ when(componentDao.getNullableById(1L, session)).thenReturn(new ComponentDto().setId(1L).setKey("org.codehaus.sonar:sonar").setLongName("SonarQube"));
List<DuplicationsParser.Block> blocks = newArrayList();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
index bc0f6d85dc0..99d5b8319e0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
@@ -34,6 +34,8 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metric.ValueType;
import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
@@ -60,10 +62,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class QualityGatesTest {
@@ -91,15 +90,20 @@ public class QualityGatesTest {
QualityGates qGates;
- UserSession authorizedUserSession = MockUserSession.create().setLogin("gaudol").setName("Olivier").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
- UserSession unauthenticatedUserSession = MockUserSession.create();
+ static final String PROJECT_KEY = "SonarQube";
+
+ UserSession authorizedProfileAdminUserSession = MockUserSession.create().setLogin("gaudol").setName("Olivier").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ UserSession authorizedProjectAdminUserSession = MockUserSession.create().setLogin("gaudol").setName("Olivier").addProjectPermissions(UserRole.ADMIN, PROJECT_KEY);
UserSession unauthorizedUserSession = MockUserSession.create().setLogin("polop").setName("Polop");
+ UserSession unauthenticatedUserSession = MockUserSession.create();
@Before
public void initialize() {
+ when(componentDao.getAuthorizedComponentById(anyLong(), eq(session))).thenReturn(new AuthorizedComponentDto().setId(1L).setKey(PROJECT_KEY));
+
when(myBatis.openSession(false)).thenReturn(session);
qGates = new QualityGates(dao, conditionDao, metricFinder, propertiesDao, componentDao, myBatis);
- UserSessionTestUtils.setUserSession(authorizedUserSession);
+ UserSessionTestUtils.setUserSession(authorizedProfileAdminUserSession);
}
@Test
@@ -214,7 +218,7 @@ public class QualityGatesTest {
public void should_select_default_qgate() throws Exception {
long defaultId = 42L;
String defaultName = "Default Name";
- when(dao.selectById(defaultId)).thenReturn(new QualityGateDto().setId(defaultId).setName(defaultName ));
+ when(dao.selectById(defaultId)).thenReturn(new QualityGateDto().setId(defaultId).setName(defaultName));
qGates.setDefault(defaultId);
verify(dao).selectById(defaultId);
ArgumentCaptor<PropertyDto> propertyCaptor = ArgumentCaptor.forClass(PropertyDto.class);
@@ -460,7 +464,7 @@ public class QualityGatesTest {
QualityGateConditionDto cond1 = new QualityGateConditionDto().setMetricId(metric1Id);
QualityGateConditionDto cond2 = new QualityGateConditionDto().setMetricId(metric2Id);
Collection<QualityGateConditionDto> conditions = ImmutableList.of(cond1, cond2);
- when(conditionDao.selectForQualityGate(qGateId)).thenReturn(conditions );
+ when(conditionDao.selectForQualityGate(qGateId)).thenReturn(conditions);
Metric metric1 = mock(Metric.class);
when(metric1.getKey()).thenReturn(metric1Key);
when(metricFinder.findById((int) metric1Id)).thenReturn(metric1);
@@ -482,7 +486,7 @@ public class QualityGatesTest {
QualityGateConditionDto cond1 = new QualityGateConditionDto().setMetricId(metric1Id);
QualityGateConditionDto cond2 = new QualityGateConditionDto().setMetricId(metric2Id);
Collection<QualityGateConditionDto> conditions = ImmutableList.of(cond1, cond2);
- when(conditionDao.selectForQualityGate(qGateId)).thenReturn(conditions );
+ when(conditionDao.selectForQualityGate(qGateId)).thenReturn(conditions);
Metric metric1 = mock(Metric.class);
when(metric1.getKey()).thenReturn(metric1Key);
when(metricFinder.findById((int) metric1Id)).thenReturn(metric1);
@@ -509,7 +513,6 @@ public class QualityGatesTest {
Long qGateId = 42L;
Long projectId = 24L;
when(dao.selectById(qGateId)).thenReturn(new QualityGateDto().setId(qGateId));
- when(componentDao.existsById(projectId, session)).thenReturn(true);
qGates.associateProject(qGateId, projectId);
verify(dao).selectById(qGateId);
ArgumentCaptor<PropertyDto> propertyCaptor = ArgumentCaptor.forClass(PropertyDto.class);
@@ -520,12 +523,21 @@ public class QualityGatesTest {
assertThat(property.getValue()).isEqualTo("42");
}
- @Test(expected = NotFoundException.class)
- public void should_fail_associate_project_on_not_existing_project() {
+ @Test
+ public void associate_project_with_project_admin_permission() {
+ UserSessionTestUtils.setUserSession(authorizedProjectAdminUserSession);
+
Long qGateId = 42L;
Long projectId = 24L;
when(dao.selectById(qGateId)).thenReturn(new QualityGateDto().setId(qGateId));
- qGates.associateProject(qGateId , projectId);
+ qGates.associateProject(qGateId, projectId);
+ verify(dao).selectById(qGateId);
+ ArgumentCaptor<PropertyDto> propertyCaptor = ArgumentCaptor.forClass(PropertyDto.class);
+ verify(propertiesDao).setProperty(propertyCaptor.capture());
+ PropertyDto property = propertyCaptor.getValue();
+ assertThat(property.getKey()).isEqualTo("sonar.qualitygate");
+ assertThat(property.getResourceId()).isEqualTo(projectId);
+ assertThat(property.getValue()).isEqualTo("42");
}
@Test
@@ -533,7 +545,18 @@ public class QualityGatesTest {
Long qGateId = 42L;
Long projectId = 24L;
when(dao.selectById(qGateId)).thenReturn(new QualityGateDto().setId(qGateId));
- when(componentDao.existsById(projectId, session)).thenReturn(true);
+ qGates.dissociateProject(qGateId, projectId);
+ verify(dao).selectById(qGateId);
+ verify(propertiesDao).deleteProjectProperty("sonar.qualitygate", projectId);
+ }
+
+ @Test
+ public void dissociate_project_with_project_admin_permission() {
+ UserSessionTestUtils.setUserSession(authorizedProjectAdminUserSession);
+
+ Long qGateId = 42L;
+ Long projectId = 24L;
+ when(dao.selectById(qGateId)).thenReturn(new QualityGateDto().setId(qGateId));
qGates.dissociateProject(qGateId, projectId);
verify(dao).selectById(qGateId);
verify(propertiesDao).deleteProjectProperty("sonar.qualitygate", projectId);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileProjectOperationsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileProjectOperationsMediumTest.java
new file mode 100644
index 00000000000..36e8b53bcde
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileProjectOperationsMediumTest.java
@@ -0,0 +1,159 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.qualityprofile;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.UserSession;
+
+import java.util.Date;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class QProfileProjectOperationsMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ DbClient db;
+ DbSession dbSession;
+ IndexClient index;
+ QProfileFactory factory;
+ QProfileProjectOperations projectOperations;
+
+ ComponentDto project;
+ QualityProfileDto profile;
+ static final String PROJECT_KEY = "SonarQube";
+
+ UserSession authorizedProfileAdminUserSession = MockUserSession.create().setLogin("john").setName("John").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ UserSession authorizedProjectAdminUserSession = MockUserSession.create().setLogin("john").setName("John").addProjectPermissions(UserRole.ADMIN, PROJECT_KEY);
+
+ @Before
+ public void before() {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ dbSession = db.openSession(false);
+ index = tester.get(IndexClient.class);
+ factory = tester.get(QProfileFactory.class);
+ projectOperations = tester.get(QProfileProjectOperations.class);
+
+ project = new ComponentDto()
+ .setKey(PROJECT_KEY)
+ .setName("SonarQube")
+ .setLongName("SonarQube")
+ .setQualifier("TRK")
+ .setScope("PRJ")
+ .setEnabled(true);
+ db.componentDao().insert(dbSession, project);
+
+ profile = QProfileTesting.newXooP1();
+ db.qualityProfileDao().insert(dbSession, profile);
+
+ dbSession.commit();
+ }
+
+ @After
+ public void after() throws Exception {
+ dbSession.close();
+ }
+
+ @Test
+ public void add_project() throws Exception {
+ projectOperations.addProject(profile.getId(), project.getId(), authorizedProfileAdminUserSession);
+
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNotNull();
+ }
+
+ @Test
+ public void add_project_with_only_project_admin_permission() throws Exception {
+ projectOperations.addProject(profile.getId(), project.getId(), authorizedProjectAdminUserSession);
+
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNotNull();
+ }
+
+ @Test
+ public void remove_project_from_project_id() throws Exception {
+ projectOperations.addProject(profile.getId(), project.getId(), authorizedProfileAdminUserSession);
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNotNull();
+
+ projectOperations.removeProject(profile.getId(), project.getId(), authorizedProfileAdminUserSession);
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNull();
+ }
+
+ @Test
+ public void remove_project_from_language() throws Exception {
+ projectOperations.addProject(profile.getId(), project.getId(), authorizedProfileAdminUserSession);
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNotNull();
+
+ projectOperations.removeProject(profile.getLanguage(), project.getId(), authorizedProfileAdminUserSession);
+ assertThat(factory.getByProjectAndLanguage(PROJECT_KEY, profile.getLanguage())).isNull();
+ }
+
+ @Test
+ public void remove_all_projects() throws Exception {
+ ComponentDto project1 = new ComponentDto()
+ .setKey("project1")
+ .setName("project1")
+ .setLongName("project1")
+ .setQualifier("TRK")
+ .setScope("PRJ")
+ .setEnabled(true);
+ ComponentDto project2 = new ComponentDto()
+ .setKey("project2")
+ .setName("project2")
+ .setLongName("project2")
+ .setQualifier("TRK")
+ .setScope("PRJ")
+ .setEnabled(true);
+ db.componentDao().insert(dbSession, project1);
+ db.componentDao().insert(dbSession, project2);
+
+ // Create a user having user permission on the two projects and the global quality profile admin permission
+ UserDto user = new UserDto().setLogin("john").setName("John").setEmail("jo@hn.com").setCreatedAt(new Date()).setUpdatedAt(new Date());
+ db.userDao().insert(dbSession, user);
+ tester.get(PermissionFacade.class).insertUserPermission(project1.getId(), user.getId(), UserRole.USER, dbSession);
+ tester.get(PermissionFacade.class).insertUserPermission(project2.getId(), user.getId(), UserRole.USER, dbSession);
+ UserSession userSession = MockUserSession.set().setUserId(user.getId().intValue()).setLogin("john").setName("John")
+ .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ dbSession.commit();
+
+ projectOperations.addProject(profile.getId(), project1.getId(), userSession);
+ projectOperations.addProject(profile.getId(), project2.getId(), userSession);
+ assertThat(tester.get(QProfileProjectLookup.class).projects(profile.getId())).hasSize(2);
+
+ projectOperations.removeAllProjects(profile.getId(), userSession);
+ assertThat(tester.get(QProfileProjectLookup.class).projects(profile.getId())).isEmpty();
+ }
+}