From: Teryk Bellahsene Date: Fri, 6 Oct 2017 11:55:00 +0000 (+0200) Subject: SONAR-9920 Quality gate administrators can do all qg related actions X-Git-Tag: 6.7-RC1~305 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=afac87bda0c0510d8c9315aa0c36dde8aa675419;p=sonarqube.git SONAR-9920 Quality gate administrators can do all qg related actions --- 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 b21c82cd664..0f940595faf 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 @@ -40,6 +40,7 @@ import org.sonar.db.qualitygate.QualityGateConditionDto; import org.sonar.db.qualitygate.QualityGateDao; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.user.UserSession; import org.sonar.server.util.Validation; @@ -61,14 +62,16 @@ public class QualityGates { private final MetricFinder metricFinder; private final PropertiesDao propertiesDao; private final UserSession userSession; + private final DefaultOrganizationProvider organizationProvider; - public QualityGates(DbClient dbClient, MetricFinder metricFinder, UserSession userSession) { + public QualityGates(DbClient dbClient, MetricFinder metricFinder, UserSession userSession, DefaultOrganizationProvider organizationProvider) { this.dbClient = dbClient; this.dao = dbClient.qualityGateDao(); this.conditionDao = dbClient.gateConditionDao(); this.metricFinder = metricFinder; this.propertiesDao = dbClient.propertiesDao(); this.userSession = userSession; + this.organizationProvider = organizationProvider; } public QualityGateDto get(Long qGateId) { @@ -80,7 +83,7 @@ public class QualityGates { } public QualityGateDto rename(long idToRename, String name) { - checkIsSystemAdministrator(); + checkIsQualityGateAdministrator(); try (DbSession dbSession = dbClient.openSession(false)) { QualityGateDto toRename = getNonNullQgate(idToRename); validateQualityGate(dbSession, idToRename, name); @@ -92,7 +95,7 @@ public class QualityGates { } public QualityGateDto copy(long sourceId, String destinationName) { - checkIsSystemAdministrator(); + checkIsQualityGateAdministrator(); getNonNullQgate(sourceId); try (DbSession dbSession = dbClient.openSession(false)) { validateQualityGate(dbSession, null, destinationName); @@ -116,7 +119,7 @@ public class QualityGates { } public void delete(long idToDelete) { - checkIsSystemAdministrator(); + checkIsQualityGateAdministrator(); QualityGateDto qGate = getNonNullQgate(idToDelete); try (DbSession session = dbClient.openSession(false)) { if (isDefault(qGate)) { @@ -129,7 +132,7 @@ public class QualityGates { } public void setDefault(DbSession dbSession, @Nullable Long idToUseAsDefault) { - checkIsSystemAdministrator(); + checkIsQualityGateAdministrator(); if (idToUseAsDefault == null) { propertiesDao.deleteGlobalProperty(SONAR_QUALITYGATE_PROPERTY, dbSession); } else { @@ -230,8 +233,8 @@ public class QualityGates { } } - private void checkIsSystemAdministrator() { - userSession.checkIsSystemAdministrator(); + private void checkIsQualityGateAdministrator() { + userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, organizationProvider.get().getUuid()); } private void checkProjectAdmin(ComponentDto project) { 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 16a67be383f..f8e9168dfe5 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 @@ -28,10 +28,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metric.ValueType; @@ -41,6 +39,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDao; import org.sonar.db.organization.OrganizationTesting; +import org.sonar.db.permission.OrganizationPermission; import org.sonar.db.property.PropertiesDao; import org.sonar.db.property.PropertyDto; import org.sonar.db.qualitygate.QualityGateConditionDao; @@ -49,6 +48,7 @@ import org.sonar.db.qualitygate.QualityGateDao; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.tester.UserSessionRule; import static org.assertj.core.api.Assertions.assertThat; @@ -61,18 +61,19 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -@RunWith(MockitoJUnitRunner.class) public class QualityGatesTest { private static final long QUALITY_GATE_ID = 42L; private static final String PROJECT_KEY = "SonarQube"; private static final String PROJECT_UUID = Uuids.UUID_EXAMPLE_01; + private static final String ORG_UUID = "ORG_UUID"; @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); + private TestDefaultOrganizationProvider organizationProvider = TestDefaultOrganizationProvider.fromUuid(ORG_UUID); private DbSession dbSession = mock(DbSession.class); private DbClient dbClient = mock(DbClient.class); private QualityGateDao dao = mock(QualityGateDao.class); @@ -83,7 +84,7 @@ public class QualityGatesTest { private QualityGates underTest; @Before - public void initialize() { + public void setUp() { when(dbClient.openSession(false)).thenReturn(dbSession); when(dbClient.qualityGateDao()).thenReturn(dao); when(dbClient.gateConditionDao()).thenReturn(conditionDao); @@ -93,9 +94,9 @@ public class QualityGatesTest { when(componentDao.selectOrFailById(eq(dbSession), anyLong())).thenReturn( newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), PROJECT_UUID).setId(1L).setDbKey(PROJECT_KEY)); - underTest = new QualityGates(dbClient, metricFinder, userSession); + underTest = new QualityGates(dbClient, metricFinder, userSession, organizationProvider); - userSession.logIn().setSystemAdministrator(); + userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, organizationProvider.get().getUuid()); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java index 49ae302197d..fa9639d1afe 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java @@ -39,6 +39,7 @@ import org.sonar.server.component.ComponentFinder; import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; @@ -61,7 +62,8 @@ public class DeselectActionTest { private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - private QualityGates qualityGates = new QualityGates(dbClient, mock(MetricFinder.class), userSession); + private TestDefaultOrganizationProvider organizationProvider = TestDefaultOrganizationProvider.from(db); + private QualityGates qualityGates = new QualityGates(dbClient, mock(MetricFinder.class), userSession, organizationProvider); private WsActionTester ws; private ComponentDto project; private QualityGateDto gate; diff --git a/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateTest.java b/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateTest.java index c9c13fc8814..75e6a897654 100644 --- a/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateTest.java +++ b/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateTest.java @@ -43,18 +43,25 @@ import org.sonar.wsclient.qualitygate.NewCondition; import org.sonar.wsclient.qualitygate.QualityGate; import org.sonar.wsclient.qualitygate.QualityGateClient; import org.sonarqube.tests.Category1Suite; +import org.sonarqube.tests.Session; import org.sonarqube.tests.Tester; import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.Organizations.Organization; import org.sonarqube.ws.WsCe; import org.sonarqube.ws.WsMeasures.Measure; import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; import org.sonarqube.ws.WsQualityGates; import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse; +import org.sonarqube.ws.WsUsers; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.PostRequest; import org.sonarqube.ws.client.WsResponse; +import org.sonarqube.ws.client.permission.AddUserWsRequest; +import org.sonarqube.ws.client.qualitygate.CreateConditionRequest; import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest; +import org.sonarqube.ws.client.qualitygate.QualityGatesService; import org.sonarqube.ws.client.qualitygate.SelectWsRequest; +import org.sonarqube.ws.client.qualitygate.UpdateConditionRequest; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; @@ -280,6 +287,26 @@ public class QualityGateTest { } } + @Test + public void administrate_quality_gate_with_gateadmin_permission() { + // user is quality gate admin of default organization + Organization organization = tester.organizations().getDefaultOrganization(); + WsUsers.CreateWsResponse.User user = tester.users().generateMember(organization); + tester.wsClient().permissions().addUser(new AddUserWsRequest().setLogin(user.getLogin()).setPermission("gateadmin").setOrganization(organization.getKey())); + Session qGateAdminTester = tester.as(user.getLogin()); + QualityGatesService qGateService = qGateAdminTester.qGates().service(); + // perform administration operations + WsQualityGates.CreateWsResponse qualityGate = qGateAdminTester.qGates().generate(); + WsQualityGates.CreateConditionWsResponse condition = qGateService.createCondition(CreateConditionRequest.builder() + .setQualityGateId(qualityGate.getId()).setMetricKey("coverage").setOperator("LT").setError("90").build()); + qGateService.updateCondition(UpdateConditionRequest.builder() + .setConditionId(condition.getId()).setMetricKey("coverage").setOperator("LT").setError("90").setWarning("80").build()); + qGateAdminTester.wsClient().wsConnector().call(new PostRequest("api/qualitygates/set_as_default").setParam("id", qualityGate.getId())); + qGateAdminTester.wsClient().wsConnector().call(new PostRequest("api/qualitygates/delete_condition").setParam("id", condition.getId())); + qGateAdminTester.wsClient().wsConnector().call(new PostRequest("api/qualitygates/unset_default").setParam("id", qualityGate.getId())); + qGateAdminTester.wsClient().wsConnector().call(new PostRequest("api/qualitygates/destroy").setParam("id", qualityGate.getId())); + } + private BuildResult executeAnalysis(String projectKey, String... keyValueProperties) { return orchestrator.executeBuild(SonarScanner.create( projectDir("qualitygate/xoo-sample"), concat(keyValueProperties, "sonar.projectKey", projectKey))); diff --git a/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateWithOrganizationsTest.java b/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateWithOrganizationsTest.java index 4af85f7a8ea..226096b2189 100644 --- a/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateWithOrganizationsTest.java +++ b/tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateWithOrganizationsTest.java @@ -27,7 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.sonarqube.tests.Category6Suite; import org.sonarqube.tests.Tester; -import org.sonarqube.ws.Organizations; +import org.sonarqube.ws.Organizations.Organization; import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; import org.sonarqube.ws.WsQualityGates.CreateWsResponse; import org.sonarqube.ws.WsUsers; @@ -49,7 +49,7 @@ public class QualityGateWithOrganizationsTest { @Test public void always_display_current_quality_gate_in_effect() throws Exception { - Organizations.Organization organization = tester.organizations().generate(); + Organization organization = tester.organizations().generate(); Project project = tester.projects().generate(organization); CreateWsResponse qualityGate = tester.qGates().generate(); tester.qGates().associateProject(qualityGate, project);