From 8ec69dbae88e4b5d38315d0f4d1b8544ddceac3f Mon Sep 17 00:00:00 2001 From: DDMili <130993898+dejan-milisavljevic-sonarsource@users.noreply.github.com> Date: Fri, 31 May 2024 16:19:26 +0200 Subject: [PATCH] SONAR-22224 Add prioritizedRule to rules/search api --- .../qualityprofile/IndexedActiveRuleDto.java | 5 +++++ .../qualityprofile/index/ActiveRuleDoc.java | 9 +++++++++ .../index/ActiveRuleIndexer.java | 3 ++- .../org/sonar/server/rule/index/RuleIndex.java | 9 +++++++++ .../server/rule/index/RuleIndexDefinition.java | 4 +++- .../org/sonar/server/rule/index/RuleQuery.java | 10 ++++++++++ .../sonar/server/rule/ws/SearchActionIT.java | 2 +- .../sonar/server/rule/ws/RuleQueryFactory.java | 2 ++ .../sonar/server/rule/ws/RuleWsSupport.java | 10 ++++++++++ .../server/rule/ws/RulesWsParameters.java | 1 + .../org/sonar/server/rule/ws/SearchAction.java | 18 +++++++++++++++++- 11 files changed, 69 insertions(+), 4 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/IndexedActiveRuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/IndexedActiveRuleDto.java index 49a1f0e374e..585cc332186 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/IndexedActiveRuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/IndexedActiveRuleDto.java @@ -29,6 +29,7 @@ public class IndexedActiveRuleDto { private String repository; private String key; private String ruleProfileUuid; + private Boolean prioritizedRule; public IndexedActiveRuleDto() { // nothing to do here @@ -62,4 +63,8 @@ public class IndexedActiveRuleDto { public String getRuleProfileUuid() { return ruleProfileUuid; } + + public Boolean getPrioritizedRule() { + return prioritizedRule; + } } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleDoc.java index eedbf89adc6..f602bb21a5e 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleDoc.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleDoc.java @@ -21,6 +21,8 @@ package org.sonar.server.qualityprofile.index; import com.google.common.collect.Maps; import java.util.Map; +import java.util.Optional; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.server.es.BaseDoc; import org.sonar.server.qualityprofile.ActiveRuleInheritance; @@ -30,6 +32,7 @@ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_UUID; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_UUID; +import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_PRIORITIZED_RULE; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_UUID; import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE; @@ -87,6 +90,12 @@ public class ActiveRuleDoc extends BaseDoc { return this; } + ActiveRuleDoc setPrioritizedRule(@Nullable Boolean b) { + Boolean notNull = Optional.ofNullable(b).orElse(Boolean.FALSE); + setField(FIELD_PRIORITIZED_RULE, notNull); + return this; + } + ActiveRuleInheritance getInheritance() { String inheritance = getNullableField(FIELD_ACTIVE_RULE_INHERITANCE); if (inheritance == null || inheritance.isEmpty() || diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndexer.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndexer.java index 7b91c40c152..d21651b379e 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndexer.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndexer.java @@ -225,7 +225,8 @@ public class ActiveRuleIndexer implements ResilientIndexer { ActiveRuleDoc doc = new ActiveRuleDoc(dto.getUuid()) .setRuleUuid(dto.getRuleUuid()) .setRuleProfileUuid(dto.getRuleProfileUuid()) - .setSeverity(SeverityUtil.getSeverityFromOrdinal(dto.getSeverity())); + .setSeverity(SeverityUtil.getSeverityFromOrdinal(dto.getSeverity())) + .setPrioritizedRule(dto.getPrioritizedRule()); // all the fields must be present, even if value is null String inheritance = dto.getInheritance(); doc.setInheritance(inheritance == null ? ActiveRuleInheritance.NONE.name() : inheritance); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java index 4416dc50cd9..c3b6f438e97 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java @@ -96,6 +96,7 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_IMPA import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_UUID; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY; +import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_PRIORITIZED_RULE; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_CLEAN_CODE_ATTRIBUTE_CATEGORY; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_CREATED_AT; import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_CWE; @@ -443,6 +444,7 @@ public class RuleIndex { addTermFilter(activeRuleFilter, FIELD_ACTIVE_RULE_PROFILE_UUID, profile.getRulesProfileUuid()); addTermFilter(activeRuleFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance()); addTermFilter(activeRuleFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities()); + addTermFilter(activeRuleFilter, FIELD_PRIORITIZED_RULE, query.getPrioritizedRule()); // ChildQuery QueryBuilder childQuery; @@ -473,6 +475,13 @@ public class RuleIndex { return filter; } + private static BoolQueryBuilder addTermFilter(BoolQueryBuilder filter, String field, @Nullable Boolean value) { + if (value != null) { + filter.must(QueryBuilders.termQuery(field, value)); + } + return filter; + } + private static Map getFacets(RuleQuery query, SearchOptions options, QueryBuilder queryBuilder, Map filters) { Map aggregations = new HashMap<>(); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java index 6a27bb34c32..6da248e2eac 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java @@ -86,6 +86,7 @@ public class RuleIndexDefinition implements IndexDefinition { public static final String SUB_FIELD_SEVERITY = "severity"; public static final String FIELD_RULE_IMPACT_SOFTWARE_QUALITY = FIELD_RULE_IMPACTS + "." + SUB_FIELD_SOFTWARE_QUALITY; public static final String FIELD_RULE_IMPACT_SEVERITY = FIELD_RULE_IMPACTS + "." + SUB_FIELD_SEVERITY; + public static final String FIELD_PRIORITIZED_RULE = "activeRule_prioritizedRule"; private final Configuration config; private final boolean enableSource; @@ -166,6 +167,7 @@ public class RuleIndexDefinition implements IndexDefinition { .keywordFieldBuilder(FIELD_ACTIVE_RULE_UUID).disableNorms().build() .keywordFieldBuilder(FIELD_ACTIVE_RULE_PROFILE_UUID).disableNorms().build() .keywordFieldBuilder(FIELD_ACTIVE_RULE_INHERITANCE).disableNorms().build() - .keywordFieldBuilder(FIELD_ACTIVE_RULE_SEVERITY).disableNorms().build(); + .keywordFieldBuilder(FIELD_ACTIVE_RULE_SEVERITY).disableNorms().build() + .createBooleanField(FIELD_PRIORITIZED_RULE); } } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java index b3f4abb0aa4..7c46f846f6b 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java @@ -61,6 +61,7 @@ public class RuleQuery { private Collection impactSeverities; private Collection impactSoftwareQualities; private Collection cleanCodeAttributesCategories; + private Boolean prioritizedRule; @CheckForNull @@ -369,4 +370,13 @@ public class RuleQuery { return this; } + @Nullable + public Boolean getPrioritizedRule() { + return prioritizedRule; + } + + public RuleQuery setPrioritizedRule(@Nullable Boolean prioritizedRule) { + this.prioritizedRule = prioritizedRule; + return this; + } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java index cfd07ec4550..cb8219e5d2e 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java @@ -157,7 +157,7 @@ public class SearchActionIT { assertThat(def.since()).isEqualTo("4.4"); assertThat(def.isInternal()).isFalse(); assertThat(def.responseExampleAsString()).isNotEmpty(); - assertThat(def.params()).hasSize(31); + assertThat(def.params()).hasSize(32); WebService.Param compareToProfile = def.param("compareToProfile"); assertThat(compareToProfile.since()).isEqualTo("6.5"); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java index b29745af490..d6469fcb287 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java @@ -47,6 +47,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10_2021; +import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_REPOSITORIES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_RULE_KEY; @@ -73,6 +74,7 @@ public class RuleQueryFactory { public RuleQuery createRuleSearchQuery(DbSession dbSession, Request request) { RuleQuery query = createRuleQuery(dbSession, request); query.setIncludeExternal(request.mandatoryParamAsBoolean(PARAM_INCLUDE_EXTERNAL)); + query.setPrioritizedRule(request.paramAsBoolean(PARAM_PRIORITIZED_RULE)); return query; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java index e70999c5cdd..6667116ef4e 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java @@ -43,6 +43,7 @@ import org.sonar.server.security.SecurityStandards; import org.sonar.server.security.SecurityStandards.SQCategory; import org.sonar.server.user.UserSession; +import static java.lang.String.format; import static org.sonar.api.server.ws.WebService.Param.ASCENDING; import static org.sonar.api.server.ws.WebService.Param.SORT; import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY; @@ -63,6 +64,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10_2021; +import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_REPOSITORIES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_RULE_KEY; @@ -263,4 +265,12 @@ public class RuleWsSupport { .setSince("7.2"); } + static void definePrioritizedRuleParam(WebService.NewAction action) { + action + .createParam(PARAM_PRIORITIZED_RULE) + .setDescription(format("Filter on prioritized rules. Ignored if the parameter '%s' is not set.", PARAM_QPROFILE)) + .setBooleanPossibleValues() + .setSince("10.6"); + } + } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java index e09071764fb..afef0698918 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java @@ -51,6 +51,7 @@ public class RulesWsParameters { public static final String PARAM_IMPACT_SOFTWARE_QUALITIES = "impactSoftwareQualities"; public static final String PARAM_IMPACT_SEVERITIES = "impactSeverities"; public static final String PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES = "cleanCodeAttributeCategories"; + public static final String PARAM_PRIORITIZED_RULE = "prioritizedRule"; public static final String FIELD_REPO = "repo"; public static final String FIELD_NAME = "name"; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java index 7b150eeb9d5..174bafec6d6 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java @@ -33,6 +33,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.Severity; @@ -89,6 +90,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IMPACT_SOFTWARE_Q import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_OWASP_TOP_10_2021; +import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_REPOSITORIES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_SANS_TOP_25; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_SEVERITIES; @@ -139,6 +141,7 @@ public class SearchAction implements RulesWsAction { .addPagingParams(100, MAX_PAGE_SIZE) .setHandler(this) .setChangelog( + new Change("10.6", format("Parameter '%s has been added", PARAM_PRIORITIZED_RULE)), new Change("5.5", "The field 'effortToFixDescription' has been deprecated, use 'gapDescription' instead"), new Change("5.5", "The field 'debtRemFnCoeff' has been deprecated, use 'remFnGapMultiplier' instead"), new Change("5.5", "The field 'defaultDebtRemFnCoeff' has been deprecated, use 'defaultRemFnGapMultiplier' instead"), @@ -201,6 +204,7 @@ public class SearchAction implements RulesWsAction { // Rule-specific search parameters RuleWsSupport.defineGenericRuleSearchParameters(action); RuleWsSupport.defineIsExternalParam(action); + RuleWsSupport.definePrioritizedRuleParam(action); } @Override @@ -423,7 +427,8 @@ public class SearchAction implements RulesWsAction { .setOwaspTop10(request.paramAsStrings(PARAM_OWASP_TOP_10)) .setOwaspTop10For2021(request.paramAsStrings(PARAM_OWASP_TOP_10_2021)) .setSansTop25(request.paramAsStrings(PARAM_SANS_TOP_25)) - .setSonarsourceSecurity(request.paramAsStrings(PARAM_SONARSOURCE_SECURITY)); + .setSonarsourceSecurity(request.paramAsStrings(PARAM_SONARSOURCE_SECURITY)) + .setPrioritizedRule(request.paramAsBoolean(PARAM_PRIORITIZED_RULE)); } private static class SearchRequest { @@ -447,6 +452,7 @@ public class SearchAction implements RulesWsAction { private List impactSeverities; private List impactSoftwareQualities; private List cleanCodeAttributesCategories; + private Boolean prioritizedRule; private SearchRequest setActiveSeverities(List activeSeverities) { this.activeSeverities = activeSeverities; @@ -623,5 +629,15 @@ public class SearchAction implements RulesWsAction { this.cleanCodeAttributesCategories = cleanCodeAttributesCategories; return this; } + + @CheckForNull + public Boolean getPrioritizedRule() { + return prioritizedRule; + } + + public SearchRequest setPrioritizedRule(@Nullable Boolean prioritizedRule) { + this.prioritizedRule = prioritizedRule; + return this; + } } } -- 2.39.5