aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi-v2
diff options
context:
space:
mode:
authorPierre Guillot <pierre.guillot@sonarsource.com>2024-12-10 15:29:09 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:21 +0100
commitd639a965bce7acafb004906cd07a8f0b5f7af993 (patch)
tree647cd646abddb12dfeeef7e637aa33b4658f1049 /server/sonar-webserver-webapi-v2
parent451c1c2e4856ec3df87f86189fcdb25b31794027 (diff)
downloadsonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.tar.gz
sonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.zip
SONAR-22998 fetch active rules with a dedicated endpoint
Co-authored-by: Julien HENRY <julien.henry@sonarsource.com>
Diffstat (limited to 'server/sonar-webserver-webapi-v2')
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java1
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/ActiveRulesController.java47
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesController.java38
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandler.java27
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImpl.java47
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java20
-rw-r--r--server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesControllerTest.java107
-rw-r--r--server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImplTest.java71
8 files changed, 358 insertions, 0 deletions
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
index d77f2fda48a..1d053c5049f 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
@@ -51,6 +51,7 @@ public class WebApiEndpoints {
public static final String ANALYSIS_DOMAIN = "/analysis";
public static final String VERSION_ENDPOINT = ANALYSIS_DOMAIN + "/version";
public static final String JRE_ENDPOINT = ANALYSIS_DOMAIN + "/jres";
+ public static final String ACTIVE_RULES_ENDPOINT = ANALYSIS_DOMAIN + "/active_rules";
public static final String SCANNER_ENGINE_ENDPOINT = ANALYSIS_DOMAIN + "/engine";
private WebApiEndpoints() {
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/ActiveRulesController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/ActiveRulesController.java
new file mode 100644
index 00000000000..905420589a3
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/ActiveRulesController.java
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import java.util.List;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.sonar.server.v2.WebApiEndpoints.ACTIVE_RULES_ENDPOINT;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+@RequestMapping(value = ACTIVE_RULES_ENDPOINT, produces = APPLICATION_JSON_VALUE)
+@ResponseStatus(OK)
+@RestController
+public interface ActiveRulesController {
+
+ String PROJECT_KEY_PARAM_DESCRIPTION = "Project Key";
+
+ @GetMapping
+ @Operation(summary = "Get all active rules for a specific project", description = "Used by the scanner-engine to get all active rules for a given project.")
+ List<ActiveRuleRestReponse.ActiveRule> getActiveRules(@RequestParam(value = "projectKey") @Parameter(description = PROJECT_KEY_PARAM_DESCRIPTION) String projectKey);
+
+}
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesController.java
new file mode 100644
index 00000000000..9a51bd5972b
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesController.java
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.controller;
+
+import java.util.List;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+import org.sonar.server.v2.api.analysis.service.ActiveRulesHandler;
+
+public class DefaultActiveRulesController implements ActiveRulesController {
+
+ private final ActiveRulesHandler activeRulesHandler;
+
+ public DefaultActiveRulesController(ActiveRulesHandler activeRulesHandler) {
+ this.activeRulesHandler = activeRulesHandler;
+ }
+
+ @Override
+ public List<ActiveRuleRestReponse.ActiveRule> getActiveRules(String projectKey) {
+ return activeRulesHandler.getActiveRules(projectKey);
+ }
+}
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandler.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandler.java
new file mode 100644
index 00000000000..d14a66a6d7a
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandler.java
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.service;
+
+import java.util.List;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+
+public interface ActiveRulesHandler {
+ List<ActiveRuleRestReponse.ActiveRule> getActiveRules(String projectKey);
+}
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImpl.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImpl.java
new file mode 100644
index 00000000000..8b4562bc4f9
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImpl.java
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.service;
+
+import java.util.List;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+import org.sonar.server.rule.ActiveRuleService;
+
+public class ActiveRulesHandlerImpl implements ActiveRulesHandler {
+
+ private final DbClient dbClient;
+ private final ActiveRuleService activeRuleService;
+
+ public ActiveRulesHandlerImpl(DbClient dbClient, ActiveRuleService activeRuleService) {
+ this.dbClient = dbClient;
+ this.activeRuleService = activeRuleService;
+ }
+
+ @Override
+ public List<ActiveRuleRestReponse.ActiveRule> getActiveRules(String projectKey) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ return dbClient.projectDao().selectProjectByKey(dbSession, projectKey)
+ .map(projectDto -> activeRuleService.buildActiveRules(projectDto.getUuid()))
+ .orElse(activeRuleService.buildDefaultActiveRules());
+ }
+ }
+
+}
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java
index 20880ad7420..2ae1170b7af 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java
@@ -48,16 +48,21 @@ import org.sonar.server.platform.ServerFileSystem;
import org.sonar.server.platform.db.migration.DatabaseMigrationState;
import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import org.sonar.server.qualitygate.QualityGateConditionsValidator;
+import org.sonar.server.rule.ActiveRuleService;
import org.sonar.server.rule.RuleDescriptionFormatter;
import org.sonar.server.setting.SettingsChangeNotifier;
import org.sonar.server.user.SystemPasscode;
import org.sonar.server.user.UserSession;
+import org.sonar.server.v2.api.analysis.controller.ActiveRulesController;
+import org.sonar.server.v2.api.analysis.controller.DefaultActiveRulesController;
import org.sonar.server.v2.api.analysis.controller.DefaultJresController;
import org.sonar.server.v2.api.analysis.controller.DefaultScannerEngineController;
import org.sonar.server.v2.api.analysis.controller.DefaultVersionController;
import org.sonar.server.v2.api.analysis.controller.JresController;
import org.sonar.server.v2.api.analysis.controller.ScannerEngineController;
import org.sonar.server.v2.api.analysis.controller.VersionController;
+import org.sonar.server.v2.api.analysis.service.ActiveRulesHandler;
+import org.sonar.server.v2.api.analysis.service.ActiveRulesHandlerImpl;
import org.sonar.server.v2.api.analysis.service.JresHandler;
import org.sonar.server.v2.api.analysis.service.JresHandlerImpl;
import org.sonar.server.v2.api.analysis.service.ScannerEngineHandler;
@@ -227,4 +232,19 @@ public class PlatformLevel4WebConfig {
return new DefaultModeController(userSession, dbClient, configuration, settingsChangeNotifier, notificationManager, qualityGateConditionsValidator);
}
+ @Bean
+ public ActiveRuleService activeRuleService(DbClient dbClient, Languages languages) {
+ return new ActiveRuleService(dbClient, languages);
+ }
+
+ @Bean
+ public ActiveRulesHandler activeRulesHandler(DbClient dbClient, ActiveRuleService activeRuleService) {
+ return new ActiveRulesHandlerImpl(dbClient, activeRuleService);
+ }
+
+ @Bean
+ public ActiveRulesController activeRulesController(ActiveRulesHandler activeRulesHandler) {
+ return new DefaultActiveRulesController(activeRulesHandler);
+ }
+
}
diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesControllerTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesControllerTest.java
new file mode 100644
index 00000000000..c35ecfda28a
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultActiveRulesControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.controller;
+
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+import org.sonar.server.v2.api.analysis.service.ActiveRulesHandler;
+import org.springframework.test.web.servlet.MockMvc;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.v2.WebApiEndpoints.ACTIVE_RULES_ENDPOINT;
+import static org.sonar.server.v2.api.ControllerTester.getMockMvc;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+class DefaultActiveRulesControllerTest {
+
+ private final ActiveRulesHandler handler = mock(ActiveRulesHandler.class);
+
+ private final MockMvc mockMvc = getMockMvc(new DefaultActiveRulesController(handler));
+
+ @Test
+ void getActiveRules_shouldReturnActiveRulesAsJson() throws Exception {
+ var minimalAr = new ActiveRuleRestReponse.ActiveRule(
+ new ActiveRuleRestReponse.RuleKey("xoo", "rule1"),
+ "Rule 1",
+ "MAJOR",
+ "2024-12-09",
+ "2024-12-09",
+ null,
+ "java",
+ null,
+ "qProfileKey",
+ List.of(),
+ List.of(),
+ Map.of());
+ var maximalAr = new ActiveRuleRestReponse.ActiveRule(
+ new ActiveRuleRestReponse.RuleKey("xoo", "rule1"),
+ "Rule 1",
+ "MAJOR",
+ "2024-12-09",
+ "2024-12-09",
+ "someInternalKey",
+ "java",
+ "templateKey",
+ "qProfileKey",
+ List.of(new ActiveRuleRestReponse.RuleKey("old", "rule")),
+ List.of(new ActiveRuleRestReponse.Param("key", "value")),
+ Map.of(SoftwareQuality.MAINTAINABILITY, Severity.HIGH));
+ when(handler.getActiveRules("someKey")).thenReturn(List.of(minimalAr, maximalAr));
+
+ String expectedJson = """
+ [
+ {
+ "ruleKey":{"repository":"xoo","rule":"rule1"},
+ "name":"Rule 1",
+ "severity":"MAJOR",
+ "createdAt":"2024-12-09",
+ "updatedAt":"2024-12-09",
+ "language":"java",
+ "qProfileKey":"qProfileKey"
+ },
+ {
+ "ruleKey":{"repository":"xoo","rule":"rule1"},
+ "name":"Rule 1","severity":"MAJOR",
+ "createdAt":"2024-12-09",
+ "updatedAt":"2024-12-09",
+ "internalKey":"someInternalKey",
+ "language":"java",
+ "templateRuleKey":"templateKey",
+ "qProfileKey":"qProfileKey",
+ "deprecatedKeys":[{"repository":"old","rule":"rule"}],
+ "params":[{"key":"key","value":"value"}],
+ "impacts":{"MAINTAINABILITY":"HIGH"}}
+ ]
+ """;
+
+ mockMvc.perform(get(ACTIVE_RULES_ENDPOINT + "?projectKey=someKey"))
+ .andExpectAll(
+ status().isOk(),
+ content().json(expectedJson, true));
+ }
+
+}
diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImplTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImplTest.java
new file mode 100644
index 00000000000..26c8983195a
--- /dev/null
+++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/ActiveRulesHandlerImplTest.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.v2.api.analysis.service;
+
+import java.util.List;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.server.rule.ActiveRuleRestReponse;
+import org.sonar.server.rule.ActiveRuleService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ActiveRulesHandlerImplTest {
+
+ private final DbClient dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS);
+ private final DbSession dbSession = mock();
+ private final ActiveRuleService activeRuleService = mock(ActiveRuleService.class);
+
+ @BeforeEach
+ void setup() {
+ when(dbClient.openSession(false)).thenReturn(dbSession);
+ }
+
+ ActiveRulesHandlerImpl underTest = new ActiveRulesHandlerImpl(dbClient, activeRuleService);
+
+ @Test
+ void getActiveRules_returns_default_quality_profile_for_unknown_project() {
+ var defaultActiveRule1 = mock(ActiveRuleRestReponse.ActiveRule.class);
+ when(activeRuleService.buildDefaultActiveRules()).thenReturn(List.of(defaultActiveRule1));
+
+ List<ActiveRuleRestReponse.ActiveRule> result = underTest.getActiveRules("unknown-project");
+
+ assertThat(result).containsExactly(defaultActiveRule1);
+ }
+
+ @Test
+ void getActiveRules_returns_associated_quality_profile_for_known_project() {
+ when(dbClient.projectDao().selectProjectByKey(dbSession, "my-project")).thenReturn(Optional.of(new ProjectDto().setUuid("someProjectUuid")));
+ var activeRule1 = mock(ActiveRuleRestReponse.ActiveRule.class);
+ when(activeRuleService.buildActiveRules("someProjectUuid")).thenReturn(List.of(activeRule1));
+
+ List<ActiveRuleRestReponse.ActiveRule> result = underTest.getActiveRules("my-project");
+
+ assertThat(result).containsExactly(activeRule1);
+ }
+
+}