]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8950 filter rules search on qprofiles org, if not other specified
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Thu, 13 Apr 2017 12:36:44 +0000 (14:36 +0200)
committerDaniel Schwarz <bartfastiel@users.noreply.github.com>
Fri, 14 Apr 2017 06:57:18 +0000 (08:57 +0200)
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionMediumTest.java

index 381a6af12c4fb3e82cdb6e7325ba744fd6220d5a..c194b5d3979439980af86acc2b1885056996f4d0 100644 (file)
@@ -292,31 +292,34 @@ public class RuleIndex {
         QueryBuilders.termQuery(FIELD_RULE_TEMPLATE_KEY, template));
     }
 
-    // ActiveRule Filter (profile and inheritance)
-    BoolQueryBuilder childrenFilter = boolQuery();
-    addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey());
-    addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
-    addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities());
-    addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_ORGANIZATION_UUID, query.getOrganizationUuid());
-
-    // ChildQuery
-    QueryBuilder childQuery;
-    if (childrenFilter.hasClauses()) {
-      childQuery = childrenFilter;
-    } else {
-      childQuery = matchAllQuery();
-    }
-
     /* Implementation of activation query */
-    if (Boolean.TRUE.equals(query.getActivation())) {
-      filters.put("activation",
-        QueryBuilders.hasChildQuery(INDEX_TYPE_ACTIVE_RULE.getType(),
-          childQuery));
-    } else if (Boolean.FALSE.equals(query.getActivation())) {
-      filters.put("activation",
-        boolQuery().mustNot(
+    if (query.getActivation() != null) {
+
+      // ActiveRule Filter (profile and inheritance)
+      BoolQueryBuilder childrenFilter = boolQuery();
+      addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey());
+      addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
+      addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities());
+      addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_ORGANIZATION_UUID, query.getOrganizationUuid());
+
+      // ChildQuery
+      QueryBuilder childQuery;
+      if (childrenFilter.hasClauses()) {
+        childQuery = childrenFilter;
+      } else {
+        childQuery = matchAllQuery();
+      }
+
+      if (Boolean.TRUE.equals(query.getActivation())) {
+        filters.put("activation",
           QueryBuilders.hasChildQuery(INDEX_TYPE_ACTIVE_RULE.getType(),
-            childQuery)));
+            childQuery));
+      } else if (Boolean.FALSE.equals(query.getActivation())) {
+        filters.put("activation",
+          boolQuery().mustNot(
+            QueryBuilders.hasChildQuery(INDEX_TYPE_ACTIVE_RULE.getType(),
+              childQuery)));
+      }
     }
 
     return filters;
index d665853bc08da9702e7ec7fbcf0ed3d04eff1b5b..1d71266d0d4247198d02aa5da0f1686445f80641 100644 (file)
@@ -21,6 +21,8 @@ package org.sonar.server.rule.ws;
 
 import com.google.common.collect.ImmutableList;
 import java.util.Date;
+import java.util.List;
+import java.util.Optional;
 import javax.annotation.CheckForNull;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rules.RuleType;
@@ -29,8 +31,10 @@ import org.sonar.api.server.ws.Request;
 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.qualityprofile.QualityProfileDto;
 import org.sonar.server.rule.index.RuleQuery;
+import org.sonar.server.ws.WsUtils;
 
 import static org.sonar.server.util.EnumUtils.toEnums;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION;
@@ -65,28 +69,40 @@ public class RuleQueryFactory {
    * When a profile key is set, the language of the profile is automatically set in the query
    */
   public RuleQuery createRuleQuery(DbSession dbSession, Request request) {
-    RuleQuery ruleQuery = createRuleQuery(dbSession, new RuleQuery(), request);
-
-    String qProfileKey = ruleQuery.getQProfileKey();
-    if (qProfileKey != null) {
-      QualityProfileDto qProfile = getProfileByKey(dbSession, qProfileKey);
-      if (qProfile != null) {
-        ruleQuery.setLanguages(ImmutableList.of(qProfile.getLanguage()));
-      }
-    }
-    return ruleQuery;
-  }
-
-  private RuleQuery createRuleQuery(DbSession dbSession, RuleQuery query, Request request) {
+    RuleQuery query = new RuleQuery();
     query.setQueryText(request.param(WebService.Param.TEXT_QUERY));
     query.setSeverities(request.paramAsStrings(PARAM_SEVERITIES));
     query.setRepositories(request.paramAsStrings(PARAM_REPOSITORIES));
     Date availableSince = request.paramAsDate(PARAM_AVAILABLE_SINCE);
     query.setAvailableSince(availableSince != null ? availableSince.getTime() : null);
     query.setStatuses(toEnums(request.paramAsStrings(PARAM_STATUSES), RuleStatus.class));
-    query.setLanguages(request.paramAsStrings(PARAM_LANGUAGES));
-    query.setActivation(request.paramAsBoolean(PARAM_ACTIVATION));
-    query.setQProfileKey(request.param(PARAM_QPROFILE));
+    Boolean activation = request.paramAsBoolean(PARAM_ACTIVATION);
+    query.setActivation(activation);
+
+    String qualityProfileKey = request.param(PARAM_QPROFILE);
+    String organizationKey = request.param(PARAM_ORGANIZATION);
+    String organizationUuid;
+    List<String> languages;
+    if (qualityProfileKey == null) {
+      organizationUuid = wsSupport.getOrganizationByKey(dbSession, organizationKey).getUuid();
+      languages = request.paramAsStrings(PARAM_LANGUAGES);
+    } else {
+      QualityProfileDto qualityProfileOptional = dbClient.qualityProfileDao().selectByKey(dbSession, qualityProfileKey);
+      QualityProfileDto qualityProfile = WsUtils.checkFound(qualityProfileOptional, "The specified qualityProfile '%s' does not exist", qualityProfileKey);
+      query.setQProfileKey(qualityProfileKey);
+      languages = ImmutableList.of(qualityProfile.getLanguage());
+      organizationUuid = qualityProfile.getOrganizationUuid();
+      if (organizationKey != null) {
+        Optional<OrganizationDto> organizationOptional = dbClient.organizationDao().selectByKey(dbSession, organizationKey);
+        OrganizationDto organization = WsUtils.checkFoundWithOptional(organizationOptional, "No organization with key '%s'", organizationKey);
+        if (!organizationUuid.equals(organization.getUuid())) {
+          throw new IllegalArgumentException(String.format("The specified qualityProfile '%s' is not part of the specified organization '%s'", qualityProfileKey, organizationKey));
+        }
+      }
+    }
+    query.setOrganizationUuid(organizationUuid);
+    query.setLanguages(languages);
+
     query.setTags(request.paramAsStrings(PARAM_TAGS));
     query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
     query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
@@ -94,7 +110,6 @@ public class RuleQueryFactory {
     query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
     query.setTypes(toEnums(request.paramAsStrings(PARAM_TYPES), RuleType.class));
     query.setKey(request.param(PARAM_RULE_KEY));
-    query.setOrganizationUuid(wsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION)).getUuid());
 
     String sortParam = request.param(WebService.Param.SORT);
     if (sortParam != null) {
index 29c4ff46d4d49cfa1c583d1c9c327f7fe38de1b2..f69004eb2ada92af76adf9187c62aed3c04a6759 100644 (file)
  */
 package org.sonar.server.rule.ws;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
@@ -29,7 +31,6 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationTesting;
 import org.sonar.db.qualityprofile.QualityProfileDto;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.rule.index.RuleQuery;
@@ -57,6 +58,7 @@ import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SIN
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ORGANIZATION;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
 import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
@@ -70,6 +72,8 @@ public class RuleQueryFactoryTest {
 
   @Rule
   public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
 
   DbClient dbClient = dbTester.getDbClient();
 
@@ -78,7 +82,12 @@ public class RuleQueryFactoryTest {
   RuleQueryFactory underTest = new RuleQueryFactory(dbClient, new RuleWsSupport(dbClient, null, TestDefaultOrganizationProvider.from(dbTester)));
 
   FakeAction fakeAction = new FakeAction(underTest);
-  OrganizationDto organization = OrganizationTesting.newOrganizationDto();
+  OrganizationDto organization;
+
+  @Before
+  public void before() {
+    organization = dbTester.organizations().insert();
+  }
 
   @Test
   public void create_empty_query() throws Exception {
@@ -108,6 +117,8 @@ public class RuleQueryFactoryTest {
 
   @Test
   public void create_query() throws Exception {
+    QualityProfileDto qualityProfile = dbTester.qualityProfiles().insert(organization);
+
     RuleQuery result = execute(
       PARAM_RULE_KEY, "ruleKey",
 
@@ -118,7 +129,8 @@ public class RuleQueryFactoryTest {
       PARAM_IS_TEMPLATE, "true",
       PARAM_LANGUAGES, "java,js",
       TEXT_QUERY, "S001",
-      PARAM_QPROFILE, "sonar-way",
+      PARAM_QPROFILE, qualityProfile.getKey(),
+      PARAM_ORGANIZATION, organization.getKey(),
       PARAM_REPOSITORIES, "pmd,checkstyle",
       PARAM_SEVERITIES, "MINOR,CRITICAL",
       PARAM_STATUSES, "DEPRECATED,READY",
@@ -137,9 +149,10 @@ public class RuleQueryFactoryTest {
     assertThat(result.getAvailableSinceLong()).isNotNull();
     assertThat(result.getInheritance()).containsOnly(INHERITED, OVERRIDES);
     assertThat(result.isTemplate()).isTrue();
-    assertThat(result.getLanguages()).containsOnly("java", "js");
+    assertThat(result.getLanguages()).containsOnly(qualityProfile.getLanguage());
     assertThat(result.getQueryText()).isEqualTo("S001");
-    assertThat(result.getQProfileKey()).isEqualTo("sonar-way");
+    assertThat(result.getQProfileKey()).isEqualTo(qualityProfile.getKey());
+    assertThat(result.getOrganizationUuid()).isEqualTo(organization.getUuid());
     assertThat(result.getRepositories()).containsOnly("pmd", "checkstyle");
     assertThat(result.getRuleKey()).isNull();
     assertThat(result.getSeverities()).containsOnly(MINOR, CRITICAL);
@@ -151,6 +164,27 @@ public class RuleQueryFactoryTest {
     assertThat(result.getSortField()).isEqualTo("updatedAt");
   }
 
+  @Test
+  public void use_quality_profiles_language_if_available() throws Exception {
+    QualityProfileDto qualityProfile = dbTester.qualityProfiles().insert(organization);
+    String qualityProfileKey = qualityProfile.getKey();
+
+    RuleQuery result = execute(
+      PARAM_LANGUAGES, "specifiedLanguage",
+      PARAM_ACTIVATION, "true",
+      PARAM_QPROFILE, qualityProfileKey);
+
+    assertThat(result.getLanguages()).containsExactly(qualityProfile.getLanguage());
+  }
+
+  @Test
+  public void use_specified_languages_if_no_quality_profile_available() throws Exception {
+    RuleQuery result = execute(
+      PARAM_LANGUAGES, "specifiedLanguage");
+
+    assertThat(result.getLanguages()).containsExactly("specifiedLanguage");
+  }
+
   @Test
   public void create_query_add_language_from_profile() throws Exception {
     String profileKey = "sonar-way";
@@ -168,6 +202,39 @@ public class RuleQueryFactoryTest {
     assertThat(result.getLanguages()).containsOnly("xoo");
   }
 
+  @Test
+  public void filter_on_quality_profiles_organization_if_searching_for_actives_with_no_organization_specified() throws Exception {
+    String profileKey = "sonar-way";
+    dbClient.qualityProfileDao().insert(dbSession, QualityProfileDto.createFor(profileKey)
+      .setOrganizationUuid(organization.getUuid())
+      .setName("Sonar Way")
+      .setLanguage("xoo"));
+    dbSession.commit();
+
+    RuleQuery result = execute(
+      PARAM_ACTIVATION, "true",
+      PARAM_QPROFILE, profileKey);
+
+    assertThat(result.getOrganizationUuid()).isEqualTo(organization.getUuid());
+  }
+
+  @Test
+  public void fail_if_organization_and_quality_profile_are_contradictory() throws Exception {
+    OrganizationDto organization1 = dbTester.organizations().insert();
+    OrganizationDto organization2 = dbTester.organizations().insert();
+
+    QualityProfileDto qualityProfile = dbTester.qualityProfiles().insert(organization1);
+
+    String qualityProfileKey = qualityProfile.getKey();
+    String organization2Key = organization2.getKey();
+
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("The specified qualityProfile '" + qualityProfileKey + "' is not part of the specified organization '" + organization2Key + "'");
+
+    RuleQuery result = execute(PARAM_QPROFILE, qualityProfileKey,
+      PARAM_ORGANIZATION, organization2Key);
+  }
+
   private RuleQuery execute(String... paramsKeyAndValue) {
     WsActionTester ws = new WsActionTester(fakeAction);
     TestRequest request = ws.newRequest();
index 582c732a964f122805dd50d04d7cd2f454a95dad..c3fe4c9ab4bc0df729e4ed023470ca35a46744ba 100644 (file)
@@ -26,6 +26,7 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
@@ -46,6 +47,7 @@ import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleParamDto;
 import org.sonar.db.rule.RuleTesting;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.organization.DefaultOrganization;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.qualityprofile.QProfileTesting;
@@ -72,6 +74,8 @@ public class SearchActionMediumTest {
   public static ServerTester tester = new ServerTester().withEsIndexes().addXoo();
   @Rule
   public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
 
   private static final String API_ENDPOINT = "api/rules";
   private static final String API_SEARCH_METHOD = "search";
@@ -394,12 +398,15 @@ public class SearchActionMediumTest {
     WsTester.Result result = request.execute();
     result.assertJson(this.getClass(), "search_profile_active_rules.json");
 
-    tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD)
+    WsTester.TestRequest request2 = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD)
       .setParam(PARAM_ACTIVATION, "true")
       .setParam(PARAM_QPROFILE, "unknown_profile")
-      .setParam(WebService.Param.FIELDS, "actives")
-      .execute()
-      .assertJson(this.getClass(), "search_no_rules.json");
+      .setParam(WebService.Param.FIELDS, "actives");
+
+    thrown.expect(NotFoundException.class);
+    thrown.expectMessage("The specified qualityProfile 'unknown_profile' does not exist");
+
+    request2.execute();
   }
 
   @Test