]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10134 Add organization parameter in api/qualitygates/create_condition
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 5 Dec 2017 14:50:03 +0000 (15:50 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 14 Dec 2017 16:03:35 +0000 (17:03 +0100)
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/CreateConditionActionTest.java

index 4c109c56ba979665bae29f75b5b21b82e1902faf..3d90f2a5f298a58bfbb109df2df3e82fad1b532a 100644 (file)
@@ -52,6 +52,7 @@ public class QualityGateDao implements Dao {
     return mapper(session).selectById(id);
   }
 
+  @CheckForNull
   public QGateWithOrgDto selectByOrganizationAndUuid(DbSession dbSession, OrganizationDto organization, String qualityGateUuid) {
     return mapper(dbSession).selectByUuidAndOrganization(qualityGateUuid, organization.getUuid());
   }
@@ -61,6 +62,11 @@ public class QualityGateDao implements Dao {
     return mapper(session).selectByNameAndOrganization(name, organization.getUuid());
   }
 
+  @CheckForNull
+  public QGateWithOrgDto selectByOrganizationAndId(DbSession session, OrganizationDto organization, long id) {
+    return mapper(session).selectByIdAndOrganization(id, organization.getUuid());
+  }
+
   public void delete(QualityGateDto qGate, DbSession session) {
     mapper(session).delete(qGate.getId());
   }
index 4d2d37058a587b34784063fb956c0048c5419acf..a6fa14c48eee20224ef1141934ae84eade218db2 100644 (file)
@@ -38,6 +38,8 @@ public interface QualityGateMapper {
 
   QGateWithOrgDto selectByNameAndOrganization(@Param("name") String name, @Param("organizationUuid") String organizationUuid);
 
+  QGateWithOrgDto selectByIdAndOrganization(@Param("id") long id, @Param("organizationUuid") String organizationUuid);
+
   QualityGateDto selectBuiltIn();
 
   void delete(long id);
index ef19f754d5311b2d6cf9fd71b03e6c0da2ff923f..468ecab43e1a16c5b9eb7a6a3c5d36f9c02fb71c 100644 (file)
       qg.name = #{name, jdbcType=VARCHAR}
   </select>
 
+  <select id="selectByIdAndOrganization" parameterType="Map" resultType="org.sonar.db.qualitygate.QGateWithOrgDto">
+    SELECT
+    <include refid="qateWithOrgColumns"/>
+    FROM
+      quality_gates qg
+    INNER JOIN
+      org_quality_gates oqg ON oqg.quality_gate_uuid = qg.uuid AND oqg.organization_uuid = #{organizationUuid, jdbcType=VARCHAR}
+    WHERE
+      qg.id = #{id, jdbcType=BIGINT}
+  </select>
+
   <select id="selectById" parameterType="long" resultType="QualityGate">
     select
     <include refid="gateColumns"/>
index 0ff216bb7e6270a4f282f58dffc6572c3773d316..e3d73d3e8ac57c45fec001779838d79d79ce3c54 100644 (file)
@@ -132,6 +132,19 @@ public class QualityGateDaoTest {
     assertThat(underTest.selectByOrganizationAndName(dbSession, organization, "Unknown")).isNull();
   }
 
+  @Test
+  public void select_by_organization_and_id() {
+    OrganizationDto organization = db.organizations().insert();
+    QGateWithOrgDto qualityGate1 = db.qualityGates().insertQualityGate(organization);
+    QGateWithOrgDto qualityGate2 = db.qualityGates().insertQualityGate(organization);
+    OrganizationDto otherOrganization = db.organizations().insert();
+    QGateWithOrgDto qualityGate3 = db.qualityGates().insertQualityGate(otherOrganization);
+
+    assertThat(underTest.selectByOrganizationAndId(dbSession, organization, qualityGate1.getId()).getUuid()).isEqualTo(qualityGate1.getUuid());
+    assertThat(underTest.selectByOrganizationAndId(dbSession, otherOrganization, qualityGate3.getId()).getUuid()).isEqualTo(qualityGate3.getUuid());
+    assertThat(underTest.selectByOrganizationAndId(dbSession, organization, 123L)).isNull();
+  }
+
   @Test
   public void delete() {
     OrganizationDto organization = db.organizations().insert();
index 77ebc6d4b5233b79c89a1b7718fbe15df6d1d1a6..23cceab31868a74349b69803c1bf3e51aedac706 100644 (file)
@@ -23,7 +23,9 @@ import java.util.Optional;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.property.PropertyDto;
+import org.sonar.db.qualitygate.QGateWithOrgDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 
 import static com.google.common.base.Preconditions.checkState;
@@ -57,10 +59,18 @@ public class QualityGateFinder {
     }
   }
 
+  /**
+   * @deprecated Use {@link #getByOrganizationAndId(DbSession, OrganizationDto, long)}
+   */
+  @Deprecated
   public QualityGateDto getById(DbSession dbSession, long qualityGateId) {
     return checkFound(dbClient.qualityGateDao().selectById(dbSession, qualityGateId), "No quality gate has been found for id %s", qualityGateId);
   }
 
+  public QGateWithOrgDto getByOrganizationAndId(DbSession dbSession, OrganizationDto organization, long qualityGateId) {
+    return checkFound(dbClient.qualityGateDao().selectByOrganizationAndId(dbSession, organization, qualityGateId), "No quality gate has been found for id %s", qualityGateId);
+  }
+
   public Optional<QualityGateDto> getDefault(DbSession dbSession) {
     Optional<Long> defaultQualityGateId = getDefaultId(dbSession);
 
index 3264a945b935e61f9ce9928b9f34e49de78e95a4..66c19ac9d79e443f63100fd6a622c9265abe0dbc 100644 (file)
@@ -24,15 +24,15 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualitygate.QGateWithOrgDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
-import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
 import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonarqube.ws.Qualitygates.CreateConditionResponse;
 
 import static org.sonar.core.util.Protobuf.setNullable;
 import static org.sonar.server.qualitygate.ws.QualityGatesWs.addConditionParams;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_CREATE_CONDITION;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ERROR;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_ID;
@@ -40,6 +40,7 @@ import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_MET
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_OPERATOR;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PERIOD;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_WARNING;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
 public class CreateConditionAction implements QualityGatesWsAction {
 
@@ -72,6 +73,7 @@ public class CreateConditionAction implements QualityGatesWsAction {
       .setExampleValue("1");
 
     addConditionParams(createCondition);
+    wsSupport.createOrganizationParam(createCondition);
   }
 
   @Override
@@ -84,7 +86,8 @@ public class CreateConditionAction implements QualityGatesWsAction {
     Integer period = request.paramAsInt(PARAM_PERIOD);
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      QualityGateDto qualityGate = qualityGateFinder.getById(dbSession, gateId);
+      OrganizationDto organization = wsSupport.getOrganization(dbSession, request);
+      QGateWithOrgDto qualityGate = qualityGateFinder.getByOrganizationAndId(dbSession, organization, gateId);
       wsSupport.checkCanEdit(qualityGate);
       QualityGateConditionDto condition = qualityGateConditionsUpdater.createCondition(dbSession, qualityGate, metric, operator, warning, error, period);
       CreateConditionResponse.Builder createConditionResponse = CreateConditionResponse.newBuilder()
index ce367c78c821b06e041391dc9b3053e4efe5cf6a..e6df35ca9cce25632f72c50b144a485ca0f150f9 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualitygate.QGateWithOrgDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.organization.DefaultOrganizationProvider;
@@ -92,12 +93,22 @@ public class QualityGatesWsSupport {
     return checkFoundWithOptional(organizationDto, "No organization with key '%s'", organizationKey);
   }
 
+  /**
+   * @deprecated use {@link #checkCanEdit(QGateWithOrgDto)} instead
+   */
+  @Deprecated
   void checkCanEdit(QualityGateDto qualityGate) {
-    checkNotBuiltInt(qualityGate);
+    checkNotBuiltIn(qualityGate);
     userSession.checkPermission(ADMINISTER_QUALITY_GATES, defaultOrganizationProvider.get().getUuid());
   }
 
-  private static void checkNotBuiltInt(QualityGateDto qualityGate) {
+  void checkCanEdit(QGateWithOrgDto qualityGate) {
+    checkNotBuiltIn(qualityGate);
+    userSession.checkPermission(ADMINISTER_QUALITY_GATES, qualityGate.getOrganizationUuid());
+  }
+
+  private static void checkNotBuiltIn(QualityGateDto qualityGate) {
     checkArgument(!qualityGate.isBuiltIn(), "Operation forbidden for built-in Quality Gate '%s'", qualityGate.getName());
   }
+
 }
index ff4fa1d48d6e20d0211b1ca1abbf06b1dffbb1df..1f42e6d900be780fab1be1c206af4f3a18ae731a 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualitygate.QGateWithOrgDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -37,7 +38,6 @@ import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
 import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.Qualitygates.CreateConditionResponse;
 
@@ -50,6 +50,7 @@ import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ERR
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_ID;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_METRIC;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_OPERATOR;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ORGANIZATION;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PERIOD;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_WARNING;
 
@@ -74,56 +75,113 @@ public class CreateConditionActionTest {
 
   @Test
   public void create_warning_condition() throws Exception {
-    logInAsQualityGateAdmin();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    OrganizationDto organization = db.organizations().insert();
+    logInAsQualityGateAdmin(organization);
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
     MetricDto metric = insertMetric();
 
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", "90", null, null);
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_WARNING, "90")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute();
 
     assertCondition(qualityGate, metric, "LT", "90", null, null);
   }
 
   @Test
   public void create_error_condition() throws Exception {
-    logInAsQualityGateAdmin();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    OrganizationDto organization = db.organizations().insert();
+    logInAsQualityGateAdmin(organization);
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
     MetricDto metric = insertMetric();
 
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", null, "90", null);
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_ERROR, "90")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute();
 
     assertCondition(qualityGate, metric, "LT", null, "90", null);
   }
 
   @Test
   public void create_condition_over_leak_period() throws Exception {
-    logInAsQualityGateAdmin();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    OrganizationDto organization = db.organizations().insert();
+    logInAsQualityGateAdmin(organization);
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
     MetricDto metric = insertMetric();
 
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", null, "90", 1);
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_ERROR, "90")
+      .setParam(PARAM_PERIOD, "1")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute();
 
     assertCondition(qualityGate, metric, "LT", null, "90", 1);
   }
 
+  @Test
+  public void default_organization_is_used_when_no_organization_parameter() throws Exception {
+    logInAsQualityGateAdmin(db.getDefaultOrganization());
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
+    OrganizationDto otherOrganization = db.organizations().insert();
+    QGateWithOrgDto otherQualityGate = db.qualityGates().insertQualityGate(otherOrganization);
+
+    MetricDto metric = insertMetric();
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_WARNING, "90")
+      .execute();
+
+    assertCondition(qualityGate, metric, "LT", "90", null, null);
+  }
+
   @Test
   public void fail_to_update_built_in_quality_gate() {
-    logInAsQualityGateAdmin();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate(qg -> qg.setBuiltIn(true));
+    OrganizationDto organization = db.organizations().insert();
+    logInAsQualityGateAdmin(organization);
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization, qg -> qg.setBuiltIn(true));
     MetricDto metric = insertMetric();
 
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage(format("Operation forbidden for built-in Quality Gate '%s'", qualityGate.getName()));
 
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", null, "90", 1);
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_ERROR, "90")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute();
   }
 
   @Test
   public void test_response() throws Exception {
-    logInAsQualityGateAdmin();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    OrganizationDto organization = db.organizations().insert();
+    logInAsQualityGateAdmin(organization);
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
     MetricDto metric = insertMetric();
 
-    CreateConditionResponse response = executeRequest(qualityGate.getId(), metric.getKey(), "LT", "90", "45", 1);
+    CreateConditionResponse response = ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_ERROR, "45")
+      .setParam(PARAM_WARNING, "90")
+      .setParam(PARAM_PERIOD, "1")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .executeProtobuf(CreateConditionResponse.class);
 
     QualityGateConditionDto condition = new ArrayList<>(dbClient.gateConditionDao().selectForQualityGate(dbSession, qualityGate.getId())).get(0);
     assertThat(response.getId()).isEqualTo(condition.getId());
@@ -136,29 +194,21 @@ public class CreateConditionActionTest {
 
   @Test
   public void throw_ForbiddenException_if_not_gate_administrator() throws Exception {
-    userSession.logIn();
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
-    MetricDto metric = insertMetric();
-
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage("Insufficient privileges");
-
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", "90", null, null);
-  }
-
-  @Test
-  public void throw_ForbiddenException_if_not_gate_administrator_of_default_organization() throws Exception {
-    // as long as organizations don't support Quality gates, the global permission
-    // is defined on the default organization
-    OrganizationDto org = db.organizations().insert();
-    userSession.logIn().addPermission(ADMINISTER_QUALITY_GATES, org);
-    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    OrganizationDto organization = db.organizations().insert();
+    QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
     MetricDto metric = insertMetric();
+    userSession.logIn();
 
     expectedException.expect(ForbiddenException.class);
     expectedException.expectMessage("Insufficient privileges");
 
-    executeRequest(qualityGate.getId(), metric.getKey(), "LT", "90", null, null);
+    ws.newRequest()
+      .setParam(PARAM_GATE_ID, qualityGate.getId().toString())
+      .setParam(PARAM_METRIC, metric.getKey())
+      .setParam(PARAM_OPERATOR, "LT")
+      .setParam(PARAM_ERROR, "90")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute();
   }
 
   @Test
@@ -168,7 +218,16 @@ public class CreateConditionActionTest {
     assertThat(action.isInternal()).isFalse();
     assertThat(action.isPost()).isTrue();
     assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(6);
+    assertThat(action.params())
+      .extracting(WebService.Param::key, WebService.Param::isRequired)
+      .containsExactlyInAnyOrder(
+        tuple("gateId", true),
+        tuple("metric", true),
+        tuple("period", false),
+        tuple("op", false),
+        tuple("warning", false),
+        tuple("error", false),
+        tuple("organization", false));
   }
 
   private void assertCondition(QualityGateDto qualityGate, MetricDto metric, String operator, @Nullable String warning, @Nullable String error, @Nullable Integer period) {
@@ -178,26 +237,8 @@ public class CreateConditionActionTest {
       .containsExactlyInAnyOrder(tuple(qualityGate.getId(), metric.getId().longValue(), operator, warning, error, period));
   }
 
-  private CreateConditionResponse executeRequest(long qualityProfileId, String metricKey, String operator, @Nullable String warning, @Nullable String error,
-    @Nullable Integer period) {
-    TestRequest request = ws.newRequest()
-      .setParam(PARAM_GATE_ID, Long.toString(qualityProfileId))
-      .setParam(PARAM_METRIC, metricKey)
-      .setParam(PARAM_OPERATOR, operator);
-    if (warning != null) {
-      request.setParam(PARAM_WARNING, warning);
-    }
-    if (error != null) {
-      request.setParam(PARAM_ERROR, error);
-    }
-    if (period != null) {
-      request.setParam(PARAM_PERIOD, Integer.toString(period));
-    }
-    return request.executeProtobuf(CreateConditionResponse.class);
-  }
-
-  private void logInAsQualityGateAdmin() {
-    userSession.logIn().addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization());
+  private void logInAsQualityGateAdmin(OrganizationDto organization) {
+    userSession.logIn().addPermission(ADMINISTER_QUALITY_GATES, organization);
   }
 
   private MetricDto insertMetric() {