aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDejan Milisavljevic <dejan.milisavljevic@sonarsource.com>2024-12-11 15:25:51 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:23 +0100
commit742bdb16f309b8f7573d07af279e9aed8311aed4 (patch)
treeacb740856386602ac70c12cbcd64cdd5a96b1aeb /server
parent01db3ec4c38768361506abc43dac0d379314276b (diff)
downloadsonarqube-742bdb16f309b8f7573d07af279e9aed8311aed4.tar.gz
sonarqube-742bdb16f309b8f7573d07af279e9aed8311aed4.zip
SONAR-23688 Add facet and filter on active_impactSeverities
Co-authored-by: OrlovAlexander <alexander.orlov@sonarsource.com>
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server-common/src/it/java/org/sonar/server/rule/index/RuleIndexIT.java179
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java74
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java1
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java11
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java3
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/DeactivateRulesActionIT.java3
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java7
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java1
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java23
11 files changed, 254 insertions, 52 deletions
diff --git a/server/sonar-server-common/src/it/java/org/sonar/server/rule/index/RuleIndexIT.java b/server/sonar-server-common/src/it/java/org/sonar/server/rule/index/RuleIndexIT.java
index 17865560586..17ab8191225 100644
--- a/server/sonar-server-common/src/it/java/org/sonar/server/rule/index/RuleIndexIT.java
+++ b/server/sonar-server-common/src/it/java/org/sonar/server/rule/index/RuleIndexIT.java
@@ -66,9 +66,12 @@ import static org.assertj.core.api.Assertions.entry;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.sonar.api.issue.impact.Severity.HIGH;
+import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
+import static org.sonar.api.issue.impact.SoftwareQuality.RELIABILITY;
+import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
import static org.sonar.api.rule.Severity.BLOCKER;
import static org.sonar.api.rule.Severity.CRITICAL;
-import static org.sonar.api.rule.Severity.INFO;
import static org.sonar.api.rule.Severity.MAJOR;
import static org.sonar.api.rule.Severity.MINOR;
import static org.sonar.api.rules.RuleType.BUG;
@@ -468,10 +471,10 @@ class RuleIndexIT {
void search_by_security_cwe_return_correct_data_based_on_mode(boolean mqrMode) {
doReturn(Optional.of(mqrMode)).when(config).getBoolean(MULTI_QUALITY_MODE_ENABLED);
RuleDto rule1 = createRule(setSecurityStandards(of("cwe:543", "cwe:123", "owaspTop10:a1")),
- r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
RuleDto rule2 = createRule(setSecurityStandards(of("cwe:543", "owaspTop10:a1")), r -> r.setType(SECURITY_HOTSPOT));
createRule(setSecurityStandards(of("owaspTop10:a1")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
index();
RuleQuery query = new RuleQuery().setCwe(of("543"));
@@ -484,10 +487,10 @@ class RuleIndexIT {
void search_by_security_owaspTop10_2017_return_correct_data_based_on_mode(boolean mqrMode) {
doReturn(Optional.of(mqrMode)).when(config).getBoolean(MULTI_QUALITY_MODE_ENABLED);
RuleDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10:a10", "cwe:543")),
- r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
RuleDto rule2 = createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:543")), r -> r.setType(SECURITY_HOTSPOT));
createRule(setSecurityStandards(of("cwe:543")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
index();
RuleQuery query = new RuleQuery().setOwaspTop10(of("a5", "a10"));
@@ -500,10 +503,10 @@ class RuleIndexIT {
void search_by_security_owaspTop10_2021_return_correct_data_based_on_mode(boolean mqrMode) {
doReturn(Optional.of(mqrMode)).when(config).getBoolean(MULTI_QUALITY_MODE_ENABLED);
RuleDto rule1 = createRule(setSecurityStandards(of("owaspTop10-2021:a1", "owaspTop10-2021:a10", "cwe:543")),
- r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
RuleDto rule2 = createRule(setSecurityStandards(of("owaspTop10-2021:a10", "cwe:543")), r -> r.setType(SECURITY_HOTSPOT));
createRule(setSecurityStandards(of("cwe:543")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
index();
RuleQuery query = new RuleQuery().setOwaspTop10For2021(of("a5", "a10"));
@@ -516,10 +519,10 @@ class RuleIndexIT {
void search_by_security_sansTop25_return_correct_data_based_on_mode(boolean mqrMode) {
doReturn(Optional.of(mqrMode)).when(config).getBoolean(MULTI_QUALITY_MODE_ENABLED);
RuleDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10:a10", "cwe:89")),
- r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
RuleDto rule2 = createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:829")), r -> r.setType(SECURITY_HOTSPOT));
createRule(setSecurityStandards(of("cwe:306")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
index();
RuleQuery query = new RuleQuery().setSansTop25(of(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE));
@@ -532,9 +535,9 @@ class RuleIndexIT {
void search_by_security_sonarsource_return_correct_data_based_on_mode(boolean mqrMode) {
doReturn(Optional.of(mqrMode)).when(config).getBoolean(MULTI_QUALITY_MODE_ENABLED);
RuleDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10-2021:a10", "cwe:89")),
- r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(VULNERABILITY).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:829")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
RuleDto rule3 = createRule(setSecurityStandards(of("cwe:601")), r -> r.setType(SECURITY_HOTSPOT));
index();
@@ -551,7 +554,7 @@ class RuleIndexIT {
//Should not be counted in Standard mode because it is not a Vulnerability type
RuleDto rule2 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10-2021:a10", "cwe:89")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.SECURITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SECURITY, Severity.HIGH))));
//Hotspots should be counted in both modes
RuleDto rule3 = createRule(setSecurityStandards(of("cwe:601")), r -> r.setType(SECURITY_HOTSPOT));
@@ -582,7 +585,7 @@ class RuleIndexIT {
// Should be ignore because it is not a hotspot, and not a vulnerability (in Standard mode) and not having Security impact (in MQR mode)
createRule(setSecurityStandards(of("cwe:787")),
- r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH))));
+ r -> r.setType(CODE_SMELL).replaceAllDefaultImpacts(List.of(new ImpactDto(MAINTAINABILITY, Severity.HIGH))));
index();
RuleQuery query = new RuleQuery();
@@ -633,10 +636,10 @@ class RuleIndexIT {
@Test
void search_by_any_of_severities() {
createRule(setSeverity(BLOCKER));
- RuleDto info = createRule(setSeverity(INFO));
+ RuleDto info = createRule(setSeverity(org.sonar.api.rule.Severity.INFO));
index();
- RuleQuery query = new RuleQuery().setSeverities(asList(INFO, MINOR));
+ RuleQuery query = new RuleQuery().setSeverities(asList(org.sonar.api.rule.Severity.INFO, MINOR));
SearchIdResult<String> results = underTest.search(query, new SearchOptions());
assertThat(results.getUuids()).containsOnly(info.getUuid());
@@ -774,7 +777,7 @@ class RuleIndexIT {
void search_by_activation_and_severity() {
RuleDto major = createRule(setSeverity(MAJOR));
RuleDto minor = createRule(setSeverity(MINOR));
- createRule(setSeverity(INFO));
+ createRule(setSeverity(org.sonar.api.rule.Severity.INFO));
QProfileDto profile1 = createJavaProfile();
QProfileDto profile2 = createJavaProfile();
db.qualityProfiles().activateRule(profile1, major, ar -> ar.setSeverity(BLOCKER));
@@ -804,6 +807,100 @@ class RuleIndexIT {
verifyNoFacet(query, RuleIndex.FACET_ACTIVE_SEVERITIES);
}
+ @Test
+ void search_by_activation_returns_impact_severity_facet() {
+ RuleDto rule1 = createRule();
+ RuleDto rule2 = createRule(setSeverity(MINOR));
+ RuleDto rule3 = createRule();
+ RuleDto rule4 = createRule();
+ QProfileDto profile1 = createJavaProfile();
+ QProfileDto profile2 = createJavaProfile();
+ db.qualityProfiles().activateRule(profile1, rule1, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.INFO)));
+ db.qualityProfiles().activateRule(profile1, rule2, ar -> ar.setImpacts(Map.of(SECURITY, Severity.LOW, MAINTAINABILITY, Severity.INFO,
+ RELIABILITY, HIGH)));
+ db.qualityProfiles().activateRule(profile1, rule3, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.BLOCKER, RELIABILITY, Severity.BLOCKER)));
+ db.qualityProfiles().activateRule(profile1, rule4, ar -> ar.setImpacts(Map.of(SECURITY, Severity.MEDIUM, RELIABILITY,
+ Severity.MEDIUM)));
+
+ // Ignored because on profile2 which is not part of the query
+ db.qualityProfiles().activateRule(profile2, rule1, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.INFO)));
+ index();
+
+ RuleQuery query = newRuleQuery().setActivation(true).setQProfile(profile1);
+
+ SearchIdResult result = underTest.search(query,
+ new SearchOptions().addFacets(singletonList("active_impactSeverities")));
+
+ assertThat(result.getFacets().getAll()).hasSize(1);
+ assertThat(result.getFacets().getAll().get("active_impactSeverities"))
+ .containsOnly(
+ entry("BLOCKER", 2L),
+ entry("HIGH", 1L),
+ entry("MEDIUM", 1L),
+ entry("LOW", 1L),
+ entry("INFO", 2L)
+ );
+ }
+
+ @Test
+ void search_by_activation_and_impact_severity_returns_impact_severity_facet() {
+ RuleDto rule1 = createRule(setImpacts(List.of(new ImpactDto(SECURITY, Severity.MEDIUM))));
+ RuleDto rule2 = createRule(setImpacts(List.of(new ImpactDto(SECURITY, Severity.BLOCKER))));
+ RuleDto rule3 = createRule();
+ RuleDto rule4 = createRule();
+ QProfileDto profile1 = createJavaProfile();
+ QProfileDto profile2 = createJavaProfile();
+ db.qualityProfiles().activateRule(profile1, rule1, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.INFO)).setSeverity("INFO"));
+ db.qualityProfiles().activateRule(profile1, rule2, ar -> ar.setImpacts(Map.of(SECURITY, Severity.LOW, MAINTAINABILITY, Severity.INFO,
+ RELIABILITY, HIGH)).setSeverity("INFO"));
+ db.qualityProfiles().activateRule(profile1, rule3, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.BLOCKER, RELIABILITY, Severity.BLOCKER)).setSeverity("MAJOR"));
+ db.qualityProfiles().activateRule(profile1, rule4, ar -> ar.setImpacts(Map.of(SECURITY, Severity.MEDIUM, RELIABILITY,
+ Severity.MEDIUM)).setSeverity("MAJOR"));
+
+ // Should be ignored because it is on profile2 which is not part of the query
+ db.qualityProfiles().activateRule(profile2, rule1, ar -> ar.setImpacts(Map.of(SECURITY, Severity.BLOCKER, MAINTAINABILITY,
+ Severity.INFO)));
+ index();
+
+ RuleQuery query =
+ newRuleQuery().setActivation(true).setQProfile(profile1).setActiveImpactSeverities(List.of("BLOCKER"));
+
+ SearchIdResult result1 = underTest.search(query, new SearchOptions().addFacets(singletonList("active_impactSeverities")));
+
+ // Filtering on active Impact Severity should have no effect on the Active Severity Facets
+ assertThat(result1.getFacets().getAll()).hasSize(1);
+ assertThat(result1.getFacets().getAll().get("active_impactSeverities"))
+ .containsOnly(
+ entry("BLOCKER", 2L),
+ entry("HIGH", 1L),
+ entry("MEDIUM", 1L),
+ entry("LOW", 1L),
+ entry("INFO", 2L)
+ );
+ assertThat(result1.getUuids()).containsExactlyInAnyOrder(rule1.getUuid(), rule3.getUuid());
+
+ query = query.setActiveSeverities(List.of("MAJOR"));
+
+ SearchIdResult result2 = underTest.search(query, new SearchOptions().addFacets(singletonList("active_impactSeverities")));
+
+ // Filters other than "active impact severity" should affect the counts
+ assertThat(result2.getFacets().getAll()).hasSize(1);
+ assertThat(result2.getFacets().getAll().get("active_impactSeverities"))
+ .containsOnly(
+ entry("BLOCKER", 1L),
+ entry("HIGH", 0L),
+ entry("MEDIUM", 1L),
+ entry("LOW", 0L),
+ entry("INFO", 0L)
+ );
+ assertThat(result2.getUuids()).containsExactlyInAnyOrder(rule3.getUuid());
+ }
+
private void verifyFacet(RuleQuery query, String facet, Map.Entry<String, Long>... expectedBuckets) {
SearchIdResult<String> result = underTest.search(query, new SearchOptions().addFacets(facet));
assertThat(result.getFacets().get(facet))
@@ -870,24 +967,24 @@ class RuleIndexIT {
@Test
void search_by_software_quality() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
RuleDto phpRule = createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
index();
RuleQuery query = new RuleQuery();
- SearchIdResult result1 = underTest.search(query.setImpactSoftwareQualities(List.of(SoftwareQuality.MAINTAINABILITY.name())),
+ SearchIdResult result1 = underTest.search(query.setImpactSoftwareQualities(List.of(MAINTAINABILITY.name())),
new SearchOptions());
assertThat(result1.getUuids()).isEmpty();
query = new RuleQuery();
- SearchIdResult result2 = underTest.search(query.setImpactSoftwareQualities(List.of(SoftwareQuality.SECURITY.name())),
+ SearchIdResult result2 = underTest.search(query.setImpactSoftwareQualities(List.of(SECURITY.name())),
new SearchOptions());
assertThat(result2.getUuids()).containsOnly(phpRule.getUuid());
}
@Test
void search_by_severity() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.BLOCKER);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.BLOCKER);
RuleDto phpRule = createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
index();
@@ -934,8 +1031,8 @@ class RuleIndexIT {
@Test
void search_should_support_software_quality_facet() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2)));
index();
@@ -954,8 +1051,8 @@ class RuleIndexIT {
@Test
void search_should_support_software_quality_facet_with_filtering() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2)));
index();
@@ -975,11 +1072,11 @@ class RuleIndexIT {
@Test
void search_whenFilteringOnSeverityAndSoftwareQuality_shouldReturnFacet() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(Severity.LOW);
ImpactDto impactDto4 = new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(Severity.BLOCKER);
- ImpactDto impactDto5 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.BLOCKER);
+ ImpactDto impactDto5 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.BLOCKER);
ImpactDto impactDto6 = new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(Severity.INFO);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2)));
@@ -992,7 +1089,7 @@ class RuleIndexIT {
RuleQuery query = new RuleQuery();
SearchIdResult result = underTest.search(
- query.setImpactSeverities(of(Severity.LOW.name())).setImpactSoftwareQualities(List.of(SoftwareQuality.MAINTAINABILITY.name())),
+ query.setImpactSeverities(of(Severity.LOW.name())).setImpactSoftwareQualities(List.of(MAINTAINABILITY.name())),
new SearchOptions().addFacets(List.of("impactSoftwareQualities", "impactSeverities")));
assertThat(result.getFacets().getAll()).hasSize(2);
@@ -1013,8 +1110,8 @@ class RuleIndexIT {
@Test
void search_should_support_severity_facet() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(Severity.BLOCKER);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2, impactDto3)));
@@ -1036,11 +1133,11 @@ class RuleIndexIT {
@Test
void search_should_support_severity_facet_with_filters() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
- ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.INFO);
- ImpactDto impactDto4 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.INFO);
- ImpactDto impactDto5 = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.BLOCKER);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.INFO);
+ ImpactDto impactDto4 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.INFO);
+ ImpactDto impactDto5 = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.BLOCKER);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2, impactDto3)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto4, impactDto5)));
@@ -1063,16 +1160,16 @@ class RuleIndexIT {
@Test
void search_should_support_software_quality_and_severity_facets_with_filtering() {
- ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(Severity.HIGH);
- ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.LOW);
- ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(SoftwareQuality.MAINTAINABILITY).setSeverity(Severity.BLOCKER);
+ ImpactDto impactDto = new ImpactDto().setSoftwareQuality(SECURITY).setSeverity(Severity.HIGH);
+ ImpactDto impactDto2 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.LOW);
+ ImpactDto impactDto3 = new ImpactDto().setSoftwareQuality(MAINTAINABILITY).setSeverity(Severity.BLOCKER);
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto2)));
createRule(setRepositoryKey("php"), setImpacts(List.of(impactDto3)));
index();
RuleQuery query = new RuleQuery().setImpactSeverities(of("LOW"))
- .setImpactSoftwareQualities(of(SoftwareQuality.MAINTAINABILITY.name()));
+ .setImpactSoftwareQualities(of(MAINTAINABILITY.name()));
SearchOptions searchOptions = new SearchOptions().addFacets(List.of("impactSeverities", "impactSoftwareQualities"));
SearchIdResult result2 = underTest.search(query, searchOptions);
@@ -1085,8 +1182,8 @@ class RuleIndexIT {
entry("INFO", 0L),
entry("BLOCKER", 1L));
assertThat(result2.getFacets().getAll().get("impactSoftwareQualities")).containsOnly(
- entry(SoftwareQuality.SECURITY.name(), 0L),
- entry(SoftwareQuality.MAINTAINABILITY.name(), 1L),
+ entry(SECURITY.name(), 0L),
+ entry(MAINTAINABILITY.name(), 1L),
entry(SoftwareQuality.RELIABILITY.name(), 0L));
}
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 872fe7a69a9..29cea09e555 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,8 @@ import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SEARCH_GR
import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SEARCH_WORDS_ANALYZER;
import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SORTABLE_ANALYZER;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_IMPACTS;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_IMPACTS;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_IMPACT_SEVERITY;
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;
@@ -157,6 +159,7 @@ public class RuleIndex {
public static final String FACET_CLEAN_CODE_ATTRIBUTE_CATEGORY = "cleanCodeAttributeCategories";
public static final String FACET_IMPACT_SOFTWARE_QUALITY = "impactSoftwareQualities";
public static final String FACET_IMPACT_SEVERITY = "impactSeverities";
+ public static final String FACET_ACTIVE_IMPACT_SEVERITY = "active_impactSeverities";
private static final BoolQueryBuilder SECURITY_IMPACT_AND_HOTSPOT_FILTER =
boolQuery()
@@ -461,6 +464,7 @@ public class RuleIndex {
addTermFilter(activeRuleFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
addTermFilter(activeRuleFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities());
addTermFilter(activeRuleFilter, FIELD_PRIORITIZED_RULE, query.getPrioritizedRule());
+ addActiveImpactSeverityFilter(activeRuleFilter, query.getActiveImpactSeverities());
// ChildQuery
QueryBuilder childQuery;
@@ -472,6 +476,18 @@ public class RuleIndex {
return childQuery;
}
+ private static BoolQueryBuilder addActiveImpactSeverityFilter(BoolQueryBuilder filter, @Nullable Collection<String> values) {
+ if (isNotEmpty(values)) {
+ BoolQueryBuilder valuesFilter = boolQuery();
+ valuesFilter.must(nestedQuery(FIELD_ACTIVE_RULE_IMPACTS,
+ termsQuery(FIELD_ACTIVE_RULE_IMPACT_SEVERITY, values),
+ ScoreMode.Avg));
+
+ filter.must(valuesFilter);
+ }
+ return filter;
+ }
+
private static BoolQueryBuilder addTermFilter(BoolQueryBuilder filter, String field, @Nullable Collection<String> values) {
if (isNotEmpty(values)) {
BoolQueryBuilder valuesFilter = boolQuery();
@@ -551,6 +567,7 @@ public class RuleIndex {
addImpactSoftwareQualityFacetIfNeeded(options, query, aggregations, stickyFacetBuilder);
addImpactSeverityFacetIfNeeded(options, query, aggregations, stickyFacetBuilder);
+ addActiveRuleImpactSeverityFacetIfNeeded(options, query, aggregations, stickyFacetBuilder);
addDefaultSecurityFacets(query, options, aggregations, stickyFacetBuilder);
}
@@ -594,10 +611,7 @@ public class RuleIndex {
Function<String, BoolQueryBuilder> mainQuery = severity -> boolQuery()
.filter(QueryBuilders.termQuery(FIELD_RULE_IMPACT_SEVERITY, severity));
- FiltersAggregator.KeyedFilter[] keyedFilters = Arrays.stream(org.sonar.api.issue.impact.Severity.values())
- .map(severity -> new FiltersAggregator.KeyedFilter(severity.name(),
- buildSeverityFacetFilter(query, mainQuery, severity.name())))
- .toArray(FiltersAggregator.KeyedFilter[]::new);
+ FiltersAggregator.KeyedFilter[] keyedFilters = getKeyedFilters(query, mainQuery);
NestedAggregationBuilder nestedAggregationBuilder = AggregationBuilders.nested("nested_" + FACET_IMPACT_SEVERITY, FIELD_RULE_IMPACTS)
.subAggregation(filters(FACET_IMPACT_SEVERITY, keyedFilters).subAggregation(reverseNested("reverse_nested_" + FIELD_RULE_IMPACT_SEVERITY)));
@@ -608,6 +622,57 @@ public class RuleIndex {
aggregations.put(FACET_IMPACT_SEVERITY, aggregationBuilder);
}
+ private static void addActiveRuleImpactSeverityFacetIfNeeded(SearchOptions options, RuleQuery query,
+ Map<String, AggregationBuilder> aggregations, StickyFacetBuilder stickyFacetBuilder) {
+ QProfileDto profile = query.getQProfile();
+ if (!options.getFacets().contains(FACET_ACTIVE_IMPACT_SEVERITY) || profile == null) {
+ return;
+ }
+
+ // We are building a children aggregation on active rules
+ // so the rule filter has to be used as parent filter for active rules
+ // from which we remove filters that concern active rules ("activation")
+ HasParentQueryBuilder ruleFilter = JoinQueryBuilders.hasParentQuery(
+ TYPE_RULE.getType(),
+ stickyFacetBuilder.getStickyFacetFilter("activation"),
+ false);
+
+ // Rebuilding the active rule filter without impact severities
+ BoolQueryBuilder childrenFilter = boolQuery();
+ addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_UUID, profile.getRulesProfileUuid());
+ addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities());
+ RuleIndex.addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
+ QueryBuilder activeRuleFilter = childrenFilter.must(ruleFilter);
+
+ Function<String, BoolQueryBuilder> mainQuery = severity -> boolQuery()
+ .filter(QueryBuilders.termQuery(FIELD_ACTIVE_RULE_IMPACT_SEVERITY, severity));
+
+ FiltersAggregator.KeyedFilter[] keyedFilters = getKeyedFilters(query, mainQuery);
+
+ NestedAggregationBuilder nestedAggregationBuilder = AggregationBuilders.nested("nested_" + FACET_ACTIVE_IMPACT_SEVERITY,
+ FIELD_ACTIVE_RULE_IMPACTS)
+ .subAggregation(filters(FACET_ACTIVE_IMPACT_SEVERITY, keyedFilters)
+ .subAggregation(reverseNested("reverse_nested_" + FIELD_ACTIVE_RULE_IMPACT_SEVERITY))
+ );
+
+ AggregationBuilder activeSeverities = JoinAggregationBuilders.children(FACET_ACTIVE_IMPACT_SEVERITY + "_children",
+ TYPE_ACTIVE_RULE.getName())
+ .subAggregation(
+ AggregationBuilders.filter(FACET_ACTIVE_IMPACT_SEVERITY + "_filter", activeRuleFilter)
+ .subAggregation(nestedAggregationBuilder)
+ );
+
+ aggregations.put(FACET_ACTIVE_IMPACT_SEVERITY,
+ AggregationBuilders.global(FACET_ACTIVE_IMPACT_SEVERITY).subAggregation(activeSeverities));
+ }
+
+ private static FiltersAggregator.KeyedFilter[] getKeyedFilters(RuleQuery query, Function<String, BoolQueryBuilder> mainQuery) {
+ return Arrays.stream(org.sonar.api.issue.impact.Severity.values())
+ .map(severity -> new FiltersAggregator.KeyedFilter(severity.name(),
+ buildSeverityFacetFilter(query, mainQuery, severity.name())))
+ .toArray(FiltersAggregator.KeyedFilter[]::new);
+ }
+
private static BoolQueryBuilder buildSeverityFacetFilter(RuleQuery query, Function<String, BoolQueryBuilder> mainQuery, String value) {
BoolQueryBuilder boolQueryBuilder = mainQuery.apply(value);
if (isNotEmpty(query.getImpactSoftwareQualities())) {
@@ -698,6 +763,7 @@ public class RuleIndex {
// Rebuilding the active rule filter without severities
BoolQueryBuilder childrenFilter = boolQuery();
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_UUID, profile.getRulesProfileUuid());
+ addActiveImpactSeverityFilter(childrenFilter, query.getActiveImpactSeverities());
RuleIndex.addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
QueryBuilder activeRuleFilter = childrenFilter.must(ruleFilter);
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 7304e98016e..63c637948c3 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
@@ -81,7 +81,6 @@ public class RuleIndexDefinition implements IndexDefinition {
public static final String FIELD_ACTIVE_RULE_SEVERITY = "activeRule_severity";
public static final String FIELD_PRIORITIZED_RULE = "activeRule_prioritizedRule";
public static final String FIELD_ACTIVE_RULE_IMPACTS = "activeRule_impacts";
- public static final String FIELD_ACTIVE_RULE_IMPACT_SOFTWARE_QUALITY = FIELD_ACTIVE_RULE_IMPACTS + "." + SUB_FIELD_SOFTWARE_QUALITY;
public static final String FIELD_ACTIVE_RULE_IMPACT_SEVERITY = FIELD_ACTIVE_RULE_IMPACTS + "." + SUB_FIELD_SEVERITY;
public static final Set<String> SORT_FIELDS = Set.of(
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 7c46f846f6b..a1c7f178a29 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
@@ -60,6 +60,7 @@ public class RuleQuery {
private Collection<String> sonarsourceSecurity;
private Collection<String> impactSeverities;
private Collection<String> impactSoftwareQualities;
+ private Collection<String> activeImpactSeverities;
private Collection<String> cleanCodeAttributesCategories;
private Boolean prioritizedRule;
@@ -205,6 +206,16 @@ public class RuleQuery {
}
@CheckForNull
+ public Collection<String> getActiveImpactSeverities() {
+ return activeImpactSeverities;
+ }
+
+ public RuleQuery setActiveImpactSeverities(@Nullable Collection<String> activeImpactSeverities) {
+ this.activeImpactSeverities = activeImpactSeverities;
+ return this;
+ }
+
+ @CheckForNull
public Boolean isTemplate() {
return isTemplate;
}
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java
index 900de2cf852..4cbf8dd889d 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java
@@ -97,7 +97,8 @@ class ActivateRulesActionIT {
"sonarsourceSecurity",
"cleanCodeAttributeCategories",
"impactSoftwareQualities",
- "impactSeverities");
+ "impactSeverities",
+ "active_impactSeverities");
}
@Test
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/DeactivateRulesActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/DeactivateRulesActionIT.java
index 9f863094cae..bf8ed8454e0 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/DeactivateRulesActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/DeactivateRulesActionIT.java
@@ -94,7 +94,8 @@ public class DeactivateRulesActionIT {
"sonarsourceSecurity",
"cleanCodeAttributeCategories",
"impactSoftwareQualities",
- "impactSeverities");
+ "impactSeverities",
+ "active_impactSeverities");
}
@Test
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 b62ea7e17b7..216f77cfcf8 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
@@ -159,7 +159,7 @@ class SearchActionIT {
assertThat(def.since()).isEqualTo("4.4");
assertThat(def.isInternal()).isFalse();
assertThat(def.responseExampleAsString()).isNotEmpty();
- assertThat(def.params()).hasSize(32);
+ assertThat(def.params()).hasSize(33);
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 d6469fcb287..6faa393c465 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
@@ -34,6 +34,7 @@ import org.sonar.server.rule.index.RuleQuery;
import static org.sonar.server.exceptions.NotFoundException.checkFound;
import static org.sonar.server.rule.ws.EnumUtils.toEnums;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_IMPACT_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES;
@@ -112,6 +113,7 @@ public class RuleQueryFactory {
query.setCleanCodeAttributesCategories(request.paramAsStrings(PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES));
query.setImpactSeverities(request.paramAsStrings(PARAM_IMPACT_SEVERITIES));
query.setImpactSoftwareQualities(request.paramAsStrings(PARAM_IMPACT_SOFTWARE_QUALITIES));
+ query.setActiveImpactSeverities(request.paramAsStrings(PARAM_ACTIVE_IMPACT_SEVERITIES));
String sortParam = request.param(WebService.Param.SORT);
if (sortParam != null) {
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 cde40bc0dc7..de38b488ab4 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
@@ -51,6 +51,7 @@ import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_IMPACT_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES;
@@ -190,6 +191,12 @@ public class RuleWsSupport {
.setExampleValue(org.sonar.api.issue.impact.Severity.HIGH + "," + org.sonar.api.issue.impact.Severity.MEDIUM)
.setPossibleValues(org.sonar.api.issue.impact.Severity.values());
+ action.createParam(PARAM_ACTIVE_IMPACT_SEVERITIES)
+ .setSince("2025.1")
+ .setDescription("Comma-separated list of Activation Software Quality Severities, i.e the impact severity of rules in Quality profiles.")
+ .setExampleValue(org.sonar.api.issue.impact.Severity.HIGH + "," + org.sonar.api.issue.impact.Severity.MEDIUM)
+ .setPossibleValues(org.sonar.api.issue.impact.Severity.values());
+
action.createParam(PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES)
.setSince("10.2")
.setDescription("Comma-separated list of Clean Code Attribute Categories")
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 afef0698918..85f468ba652 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
@@ -50,6 +50,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_ACTIVE_IMPACT_SEVERITIES = "active_impactSeverities";
public static final String PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES = "cleanCodeAttributeCategories";
public static final String PARAM_PRIORITIZED_RULE = "prioritizedRule";
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 1562c3ad6f5..e3fdcd222e0 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
@@ -68,6 +68,7 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonar.server.es.SearchOptions.MAX_PAGE_SIZE;
import static org.sonar.server.rule.index.RuleIndex.ALL_STATUSES_EXCEPT_REMOVED;
+import static org.sonar.server.rule.index.RuleIndex.FACET_ACTIVE_IMPACT_SEVERITY;
import static org.sonar.server.rule.index.RuleIndex.FACET_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.index.RuleIndex.FACET_CLEAN_CODE_ATTRIBUTE_CATEGORY;
import static org.sonar.server.rule.index.RuleIndex.FACET_CWE;
@@ -85,6 +86,7 @@ import static org.sonar.server.rule.index.RuleIndex.FACET_STATUSES;
import static org.sonar.server.rule.index.RuleIndex.FACET_TAGS;
import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES;
import static org.sonar.server.rule.ws.RulesWsParameters.OPTIONAL_FIELDS;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_IMPACT_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_CWE;
@@ -123,7 +125,8 @@ public class SearchAction implements RulesWsAction {
FACET_SONARSOURCE_SECURITY,
FACET_CLEAN_CODE_ATTRIBUTE_CATEGORY,
FACET_IMPACT_SEVERITY,
- FACET_IMPACT_SOFTWARE_QUALITY
+ FACET_IMPACT_SOFTWARE_QUALITY,
+ FACET_ACTIVE_IMPACT_SEVERITY
};
private final RuleQueryFactory ruleQueryFactory;
@@ -194,7 +197,8 @@ public class SearchAction implements RulesWsAction {
new Change("10.8", format("The parameters '%s','%s and '%s' are not deprecated anymore.", PARAM_SEVERITIES, PARAM_TYPES, PARAM_ACTIVE_SEVERITIES)),
new Change("10.8", "The values 'severity' and 'types' for the 'facets' parameter are not deprecated anymore."),
new Change("10.8", "The fields 'type' and 'severity' in the response are not deprecated anymore."),
- new Change("10.8", "The value 'severity' for the 'f' parameter is not deprecated anymore."));
+ new Change("10.8", "The value 'severity' for the 'f' parameter is not deprecated anymore."),
+ new Change("2025.2", format("The facet '%s' has been added.", FACET_ACTIVE_IMPACT_SEVERITY)));
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
@@ -365,6 +369,7 @@ public class SearchAction implements RulesWsAction {
facetValuesByFacetKey.put(FACET_CLEAN_CODE_ATTRIBUTE_CATEGORY, request.getCleanCodeAttributesCategories());
facetValuesByFacetKey.put(FACET_IMPACT_SOFTWARE_QUALITY, request.getImpactSoftwareQualities());
facetValuesByFacetKey.put(FACET_IMPACT_SEVERITY, request.getImpactSeverities());
+ facetValuesByFacetKey.put(FACET_ACTIVE_IMPACT_SEVERITY, request.getActiveImpactSeverities());
for (String facetName : context.getFacets()) {
facet.clear().setProperty(facetName);
@@ -439,7 +444,8 @@ public class SearchAction implements RulesWsAction {
.setOwaspTop10For2021(request.paramAsStrings(PARAM_OWASP_TOP_10_2021))
.setSansTop25(request.paramAsStrings(PARAM_SANS_TOP_25))
.setSonarsourceSecurity(request.paramAsStrings(PARAM_SONARSOURCE_SECURITY))
- .setPrioritizedRule(request.paramAsBoolean(PARAM_PRIORITIZED_RULE));
+ .setPrioritizedRule(request.paramAsBoolean(PARAM_PRIORITIZED_RULE))
+ .setActiveImpactSeverities(request.paramAsStrings(PARAM_ACTIVE_IMPACT_SEVERITIES));
}
private static class SearchRequest {
@@ -463,6 +469,7 @@ public class SearchAction implements RulesWsAction {
private List<String> impactSeverities;
private List<String> impactSoftwareQualities;
private List<String> cleanCodeAttributesCategories;
+ private List<String> activeImpactSeverities;
private Boolean prioritizedRule;
private SearchRequest setActiveSeverities(List<String> activeSeverities) {
@@ -650,5 +657,15 @@ public class SearchAction implements RulesWsAction {
this.prioritizedRule = prioritizedRule;
return this;
}
+
+ public SearchRequest setActiveImpactSeverities(@Nullable List<String> activeImpactSeverities) {
+ this.activeImpactSeverities = activeImpactSeverities;
+ return this;
+ }
+
+ @CheckForNull
+ public List<String> getActiveImpactSeverities() {
+ return activeImpactSeverities;
+ }
}
}