]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14322 api/issues/search returns all issues if provided rule key doesn't exist
authorMichal Duda <michal.duda@sonarsource.com>
Tue, 30 Mar 2021 17:22:52 +0000 (19:22 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 1 Apr 2021 20:03:45 +0000 (20:03 +0000)
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java

index a948489caab5a0c4792c9d0893f1fbce001203f5..9f40942a5d67c33c3cf914d15c223517834d1a4b 100644 (file)
@@ -437,7 +437,7 @@ public class IssueIndex {
     filters.addFilter(
       FIELD_ISSUE_RULE_UUID, RULES.getFilterScope(), createTermsFilter(
         FIELD_ISSUE_RULE_UUID,
-        query.rules().stream().map(RuleDefinitionDto::getUuid).collect(toList())));
+        query.ruleUuids()));
     filters.addFilter(FIELD_ISSUE_STATUS, STATUSES.getFilterScope(), createTermsFilter(FIELD_ISSUE_STATUS, query.statuses()));
 
     // security category
@@ -669,7 +669,7 @@ public class IssueIndex {
     addFacetIfNeeded(options, aggregationHelper, esRequest, FILES, query.files().toArray());
     addFacetIfNeeded(options, aggregationHelper, esRequest, SCOPES, query.scopes().toArray());
     addFacetIfNeeded(options, aggregationHelper, esRequest, LANGUAGES, query.languages().toArray());
-    addFacetIfNeeded(options, aggregationHelper, esRequest, RULES, query.rules().stream().map(RuleDefinitionDto::getUuid).toArray());
+    addFacetIfNeeded(options, aggregationHelper, esRequest, RULES, query.ruleUuids().toArray());
     addFacetIfNeeded(options, aggregationHelper, esRequest, AUTHORS, query.authors().toArray());
     addFacetIfNeeded(options, aggregationHelper, esRequest, AUTHOR, query.authors().toArray());
     addFacetIfNeeded(options, aggregationHelper, esRequest, TAGS, query.tags().toArray());
index fd017efd005d3b278304efbc237f1be82f79c105..6c186591c91b14b6e4d22788b9d676c284e8896c 100644 (file)
@@ -74,6 +74,7 @@ public class IssueQuery {
   private final Collection<String> files;
   private final Collection<String> views;
   private final Collection<RuleDefinitionDto> rules;
+  private final Collection<String> ruleUuids;
   private final Collection<String> assignees;
   private final Collection<String> authors;
   private final Collection<String> scopes;
@@ -111,6 +112,7 @@ public class IssueQuery {
     this.files = defaultCollection(builder.files);
     this.views = defaultCollection(builder.views);
     this.rules = defaultCollection(builder.rules);
+    this.ruleUuids = defaultCollection(builder.ruleUuids);
     this.assignees = defaultCollection(builder.assigneeUuids);
     this.authors = defaultCollection(builder.authors);
     this.scopes = defaultCollection(builder.scopes);
@@ -184,6 +186,10 @@ public class IssueQuery {
     return rules;
   }
 
+  public Collection<String> ruleUuids() {
+    return ruleUuids;
+  }
+
   public Collection<String> assignees() {
     return assignees;
   }
@@ -308,6 +314,7 @@ public class IssueQuery {
     private Collection<String> files;
     private Collection<String> views;
     private Collection<RuleDefinitionDto> rules;
+    private Collection<String> ruleUuids;
     private Collection<String> assigneeUuids;
     private Collection<String> authors;
     private Collection<String> scopes;
@@ -396,6 +403,11 @@ public class IssueQuery {
       return this;
     }
 
+    public Builder ruleUuids(@Nullable Collection<String> ruleUuids) {
+      this.ruleUuids = ruleUuids;
+      return this;
+    }
+
     public Builder assigneeUuids(@Nullable Collection<String> l) {
       this.assigneeUuids = l;
       return this;
index bf61e71b6557a89ad0559881095493b68754e5e4..c238c58a6b5b86149055dca6e426bea4eca0bf48 100644 (file)
@@ -109,13 +109,22 @@ public class IssueQueryFactory {
   public IssueQuery create(SearchRequest request) {
     try (DbSession dbSession = dbClient.openSession(false)) {
       final ZoneId timeZone = parseTimeZone(request.getTimeZone()).orElse(clock.getZone());
+
+      Collection<RuleDefinitionDto> ruleDefinitionDtos = ruleKeysToRuleId(dbSession, request.getRules());
+      Collection<String> ruleUuids = ruleDefinitionDtos.stream().map(RuleDefinitionDto::getUuid).collect(Collectors.toSet());
+
+      if (request.getRules() != null && request.getRules().stream().collect(toSet()).size() != ruleDefinitionDtos.size()) {
+        ruleUuids.add("non-existing-uuid");
+      }
+
       IssueQuery.Builder builder = IssueQuery.builder()
         .issueKeys(request.getIssues())
         .severities(request.getSeverities())
         .statuses(request.getStatuses())
         .resolutions(request.getResolutions())
         .resolved(request.getResolved())
-        .rules(ruleKeysToRuleId(dbSession, request.getRules()))
+        .rules(ruleDefinitionDtos)
+        .ruleUuids(ruleUuids)
         .assigneeUuids(request.getAssigneeUuids())
         .authors(request.getAuthors())
         .scopes(request.getScopes())
@@ -367,7 +376,6 @@ public class IssueQueryFactory {
     return componentDtos;
   }
 
-  @CheckForNull
   private Collection<RuleDefinitionDto> ruleKeysToRuleId(DbSession dbSession, @Nullable Collection<String> rules) {
     if (rules != null) {
       return dbClient.ruleDao().selectDefinitionByKeys(dbSession, transform(rules, RuleKey::parse));
index e8e4f5fb17ae22e4efe029d32bd1ca1c8f8fc0ed..a95f32ed55e5da58a6becc8d76335d7d18cfd9b4 100644 (file)
@@ -569,8 +569,8 @@ public class IssueIndexFiltersTest {
 
     indexIssues(newDoc("I1", file).setRuleUuid(ruleDefinitionDto.getUuid()));
 
-    assertThatSearchReturnsOnly(IssueQuery.builder().rules(singletonList(ruleDefinitionDto)), "I1");
-    assertThatSearchReturnsEmpty(IssueQuery.builder().rules(singletonList(new RuleDefinitionDto().setUuid("uuid-abc"))));
+    assertThatSearchReturnsOnly(IssueQuery.builder().ruleUuids(singletonList(ruleDefinitionDto.getUuid())), "I1");
+    assertThatSearchReturnsEmpty(IssueQuery.builder().ruleUuids(singletonList("uuid-abc")));
   }
 
   @Test
index 89d77aed63c02ddab612dec64e559102e7eea447..d2057956dd83bc88a52efe75b5b80390359af455 100644 (file)
@@ -119,6 +119,7 @@ public class IssueQueryFactoryTest {
     assertThat(query.onComponentOnly()).isFalse();
     assertThat(query.assigned()).isTrue();
     assertThat(query.rules()).hasSize(2);
+    assertThat(query.ruleUuids()).hasSize(2);
     assertThat(query.directories()).containsOnly("aDirPath");
     assertThat(query.createdAfter().date()).isEqualTo(parseDateTime("2013-04-16T09:08:24+0200"));
     assertThat(query.createdAfter().inclusive()).isTrue();
@@ -127,6 +128,22 @@ public class IssueQueryFactoryTest {
     assertThat(query.asc()).isTrue();
   }
 
+  @Test
+  public void create_with_rule_key_that_does_not_exist_in_the_db() {
+    db.users().insertUser(u -> u.setLogin("joanna"));
+    ComponentDto project = db.components().insertPrivateProject();
+    db.components().insertComponent(newModuleDto(project));
+    db.components().insertComponent(newFileDto(project));
+    newRule(RuleKey.of("findbugs", "NullReference"));
+    SearchRequest request = new SearchRequest()
+      .setRules(asList("unknown:key1", "unknown:key2"));
+
+    IssueQuery query = underTest.create(request);
+
+    assertThat(query.rules()).isEmpty();
+    assertThat(query.ruleUuids()).containsExactly("non-existing-uuid");
+  }
+
   @Test
   public void leak_period_start_date_is_exclusive() {
     long leakPeriodStart = addDays(new Date(), -14).getTime();
index 6bb64d140a762699209591e5abe777f2c94a8bdc..303e14077f9332644dcb78a99de424ae3ec93571 100644 (file)
@@ -461,7 +461,7 @@ public class SearchAction implements IssuesWsAction {
     }
     addMandatoryValuesToFacet(facets, PARAM_ASSIGNEES, assignees);
     addMandatoryValuesToFacet(facets, FACET_ASSIGNED_TO_ME, singletonList(userSession.getUuid()));
-    addMandatoryValuesToFacet(facets, PARAM_RULES, query.rules().stream().map(RuleDefinitionDto::getUuid).collect(toList()));
+    addMandatoryValuesToFacet(facets, PARAM_RULES, query.ruleUuids());
     addMandatoryValuesToFacet(facets, PARAM_SCOPES, ISSUE_SCOPES);
     addMandatoryValuesToFacet(facets, PARAM_LANGUAGES, request.getLanguages());
     addMandatoryValuesToFacet(facets, PARAM_TAGS, request.getTags());
index 78d80d7fd670248532763fcc402e067a80826e85..d4f10af4b7239d97674c5d3d6a555048becba443 100644 (file)
@@ -397,6 +397,27 @@ public class SearchActionTest {
     execute.assertJson(this.getClass(), "result_for_rule_search.json");
   }
 
+  @Test
+  public void search_by_non_existing_rule_key() {
+    RuleDto rule = newIssueRule();
+    ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY").setLanguage("java"));
+    ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("java"));
+
+    db.issues().insertIssue(rule.getDefinition(), project, file);
+    session.commit();
+    indexIssues();
+
+    userSession.logIn("john")
+      .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
+    indexPermissions();
+
+    TestResponse execute = ws.newRequest()
+      .setParam(PARAM_RULES, "nonexisting:rulekey")
+      .setParam("additionalFields", "_all")
+      .execute();
+    execute.assertJson(this.getClass(), "no_issue.json");
+  }
+
   @Test
   public void issue_on_removed_file() {
     RuleDto rule = newIssueRule();