diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-08-04 14:28:41 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-08-04 14:33:19 +0200 |
commit | 324e7ea6fb166942a519dfac10647eae5af803cd (patch) | |
tree | c132452ed535e403b3c17b85f875ea836d85a805 /server/sonar-server | |
parent | 2124979c80e18d7c5c098bfe97e91671d75ec290 (diff) | |
download | sonarqube-324e7ea6fb166942a519dfac10647eae5af803cd.tar.gz sonarqube-324e7ea6fb166942a519dfac10647eae5af803cd.zip |
SONAR-5402 Fix issue on provisionned projects
Diffstat (limited to 'server/sonar-server')
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(); + } +} |