]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9920 Quality gate administrators can do all qg related actions
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 6 Oct 2017 11:55:00 +0000 (13:55 +0200)
committerTeryk Bellahsene <teryk@users.noreply.github.com>
Wed, 11 Oct 2017 16:04:40 +0000 (18:04 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java
tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateTest.java
tests/src/test/java/org/sonarqube/tests/qualityGate/QualityGateWithOrganizationsTest.java

index b21c82cd664e5ded5ce490222c9220d45dca7db2..0f940595fafaab590e0a387bfc620d21a6ed7f49 100644 (file)
@@ -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) {
index 16a67be383f9b48e30422360534b8a262f0eb015..f8e9168dfe5ef0f4e68830a3abc17ad8ec22f89a 100644 (file)
@@ -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
index 49ae302197d54c4588e40a5945c26547789198ac..fa9639d1afe6a40975ad705e81e51ca10e080422 100644 (file)
@@ -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;
index c9c13fc88148c177979630beb2439a04f9db61be..75e6a8976545c6dc1209ba6b8ec643796a857e5c 100644 (file)
@@ -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)));
index 4af85f7a8ea039cfaa0bb6a5f33559f12588cbd2..226096b21897617f0c706e6b7efcc6586e4fc980 100644 (file)
@@ -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);