aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZipeng WU <zipeng.wu@sonarsource.com>2023-05-08 10:09:52 +0200
committersonartech <sonartech@sonarsource.com>2023-05-09 20:10:37 +0000
commit2c5ee5384d9f3e7bccee6260112f3cbd20d0f9ae (patch)
treeccddf48d508826cf3615d3d2f32c1532ad184328
parent9e906a6151503e38c17a30529407be8f820aa158 (diff)
downloadsonarqube-2c5ee5384d9f3e7bccee6260112f3cbd20d0f9ae.tar.gz
sonarqube-2c5ee5384d9f3e7bccee6260112f3cbd20d0f9ae.zip
SONAR-19103 Open documentation links safely in new tabs
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ListActionIT.java18
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/NewCodeTestServer.java67
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/SetActionIT.java14
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ShowActionIT.java17
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/UnsetActionIT.java15
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ListAction.java15
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupport.java42
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWs.java9
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/SetAction.java14
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ShowAction.java16
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/UnsetAction.java14
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/DeleteAction.java4
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupportTest.java40
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWsTest.java7
-rw-r--r--server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java16
-rw-r--r--server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsUtilsTest.java6
-rw-r--r--sonar-core/src/main/java/org/sonar/core/documentation/DefaultDocumentationLinkGenerator.java6
-rw-r--r--sonar-core/src/test/java/org/sonar/core/documentation/DefaultDocumentationLinkGeneratorTest.java11
18 files changed, 119 insertions, 212 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ListActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ListActionIT.java
index 89d17bf76b2..040bf225dcd 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ListActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ListActionIT.java
@@ -40,13 +40,14 @@
import java.time.Instant;
import java.util.Optional;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
@@ -70,6 +71,9 @@ import org.sonarqube.ws.NewCodePeriods.ShowWSResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
@@ -84,12 +88,18 @@ import static org.sonar.db.component.SnapshotTesting.newAnalysis;
private ComponentFinder componentFinder = TestComponentFinder.from(db);
private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
private NewCodePeriodDbTester tester = new NewCodePeriodDbTester(db);
- private Server server = new NewCodeTestServer("9.9.0.65466");
- private ListAction underTest = new ListAction(dbClient, userSession, componentFinder, dao, server);
- private WsActionTester ws = new WsActionTester(underTest);
+ private DocumentationLinkGenerator documentationLinkGenerator = mock(DocumentationLinkGenerator.class);
+ private WsActionTester ws;
+
+ @Before
+ public void setup(){
+ when(documentationLinkGenerator.getDocumentationLink(any())).thenReturn("https://docs.sonarqube.org/9.9/project-administration/defining-new-code/");
+ ws = new WsActionTester(new ListAction(dbClient, userSession, componentFinder, dao, documentationLinkGenerator));
+ }
@Test
public void test_definition() {
+
WebService.Action definition = ws.getDef();
assertThat(definition.description()).contains("https://docs.sonarqube.org/9.9/project-administration/defining-new-code/");
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/NewCodeTestServer.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/NewCodeTestServer.java
deleted file mode 100644
index 789098ae862..00000000000
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/NewCodeTestServer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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.newcodeperiod.ws;
-
-import java.util.Date;
-import org.sonar.api.platform.Server;
-
-class NewCodeTestServer extends Server {
-
- private final String version;
-
- NewCodeTestServer(String version) {
- this.version = version;
- }
-
- @Override
- public String getId() {
- return null;
- }
-
- @Override
- public String getPermanentServerId() {
- return null;
- }
-
- @Override
- public String getVersion() {
- return version;
- }
-
- @Override
- public Date getStartedAt() {
- return null;
- }
-
- @Override
- public String getContextPath() {
- return null;
- }
-
- @Override
- public String getPublicRootUrl() {
- return null;
- }
-
- @Override
- public boolean isSecured() {
- return false;
- }
-}
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/SetActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/SetActionIT.java
index 59cb2e96d01..20baefcfb20 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/SetActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/SetActionIT.java
@@ -24,13 +24,14 @@ import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.Optional;
import javax.annotation.Nullable;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.core.util.UuidFactoryFast;
@@ -53,6 +54,7 @@ import org.sonar.server.ws.WsActionTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
@@ -70,10 +72,14 @@ public class SetActionIT {
private ComponentFinder componentFinder = TestComponentFinder.from(db);
private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
- private Server server = new NewCodeTestServer("9.9.0.65466");
- private SetAction underTest = new SetAction(dbClient, userSession, componentFinder, editionProvider, dao, server);
- private WsActionTester ws = new WsActionTester(underTest);
+ private DocumentationLinkGenerator documentationLinkGenerator = mock(DocumentationLinkGenerator.class);
+ private WsActionTester ws;
+ @Before
+ public void setup(){
+ when(documentationLinkGenerator.getDocumentationLink(any())).thenReturn("https://docs.sonarqube.org/9.9/project-administration/defining-new-code/");
+ ws = new WsActionTester(new SetAction(dbClient, userSession, componentFinder, editionProvider, dao, documentationLinkGenerator));
+ }
@Test
public void test_definition() {
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ShowActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ShowActionIT.java
index e5608c63afb..930e9fde621 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ShowActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/ShowActionIT.java
@@ -19,12 +19,13 @@
*/
package org.sonar.server.newcodeperiod.ws;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
@@ -44,6 +45,9 @@ import org.sonarqube.ws.NewCodePeriods.ShowWSResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ShowActionIT {
@Rule
@@ -56,9 +60,14 @@ public class ShowActionIT {
private ComponentFinder componentFinder = TestComponentFinder.from(db);
private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
private NewCodePeriodDbTester tester = new NewCodePeriodDbTester(db);
- private Server server = new NewCodeTestServer("10.1-SNAPSHOT");
- private ShowAction underTest = new ShowAction(dbClient, userSession, componentFinder, dao, server);
- private WsActionTester ws = new WsActionTester(underTest);
+ private DocumentationLinkGenerator documentationLinkGenerator = mock(DocumentationLinkGenerator.class);
+ private WsActionTester ws;
+
+ @Before
+ public void setup(){
+ when(documentationLinkGenerator.getDocumentationLink(any())).thenReturn("https://docs.sonarqube.org/latest/project-administration/defining-new-code/");
+ ws = new WsActionTester(new ShowAction(dbClient, userSession, componentFinder, dao, documentationLinkGenerator));
+ }
@Test
public void test_definition() {
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/UnsetActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/UnsetActionIT.java
index 6dee555fbff..c6e73d9de37 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/UnsetActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/newcodeperiod/ws/UnsetActionIT.java
@@ -21,12 +21,13 @@ package org.sonar.server.newcodeperiod.ws;
import java.util.Optional;
import javax.annotation.Nullable;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.core.util.UuidFactoryFast;
@@ -47,6 +48,7 @@ import org.sonar.server.ws.WsActionTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -62,9 +64,14 @@ public class UnsetActionIT {
private ComponentFinder componentFinder = TestComponentFinder.from(db);
private NewCodePeriodDao dao = new NewCodePeriodDao(System2.INSTANCE, UuidFactoryFast.getInstance());
private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
- private Server server = new NewCodeTestServer("9.9.0.65466");
- private UnsetAction underTest = new UnsetAction(dbClient, userSession, componentFinder, editionProvider, dao, server);
- private WsActionTester ws = new WsActionTester(underTest);
+ private DocumentationLinkGenerator documentationLinkGenerator = mock(DocumentationLinkGenerator.class);
+ private WsActionTester ws;
+
+ @Before
+ public void setup(){
+ when(documentationLinkGenerator.getDocumentationLink(any())).thenReturn("https://docs.sonarqube.org/9.9/project-administration/defining-new-code/");
+ ws = new WsActionTester(new UnsetAction(dbClient, userSession, componentFinder, editionProvider, dao, documentationLinkGenerator));
+ }
@Test
public void test_definition() {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ListAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ListAction.java
index 001dace3c75..293cf23c422 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ListAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ListAction.java
@@ -26,12 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
@@ -47,7 +47,7 @@ import org.sonarqube.ws.NewCodePeriods;
import org.sonarqube.ws.NewCodePeriods.ListWSResponse;
import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.server.newcodeperiod.ws.NewCodeActionSupport.getDocumentationUrl;
+import static org.sonar.server.ws.WsUtils.createHtmlExternalLink;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.NewCodePeriods.ShowWSResponse.newBuilder;
@@ -58,21 +58,22 @@ public class ListAction implements NewCodePeriodsWsAction {
private final UserSession userSession;
private final ComponentFinder componentFinder;
private final NewCodePeriodDao newCodePeriodDao;
- private final Server server;
+ private final String newCodeDefinitionDocumentationUrl;
- public ListAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao, Server server) {
+ public ListAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao,
+ DocumentationLinkGenerator documentationLinkGenerator) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
this.newCodePeriodDao = newCodePeriodDao;
- this.server = server;
+ this.newCodeDefinitionDocumentationUrl = documentationLinkGenerator.getDocumentationLink("/project-administration/defining-new-code/");
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("list")
- .setDescription("Lists the <a href=\"" + getDocumentationUrl(server.getVersion(), "project-administration/defining-new-code/") +
- "\">new code definition</a> for all branches in a project.<br>" +
+ .setDescription("Lists the " + createHtmlExternalLink(newCodeDefinitionDocumentationUrl, "new code definition") +
+ " for all branches in a project.<br>" +
"Requires the permission to browse the project")
.setSince("8.0")
.setResponseExample(getClass().getResource("list-example.json"))
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupport.java
deleted file mode 100644
index ee4592d1a9a..00000000000
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupport.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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.newcodeperiod.ws;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
-
-class NewCodeActionSupport {
-
- private static final Pattern pattern = Pattern.compile("^(\\d{1,3}\\.\\d{1,3}).*$");
-
- private NewCodeActionSupport() {
- throw new UnsupportedOperationException("This class cannot be instantiated.");
- }
-
- protected static String getDocumentationUrl(@Nonnull String version, @Nonnull String docPath) {
- Matcher matcher = pattern.matcher(version);
- boolean isSnapshot = version.contains("-SNAPSHOT");
- boolean isPreviousVersion = matcher.matches() && matcher.groupCount() == 1 && !isSnapshot;
- String docVersion = isPreviousVersion ? matcher.group(1) : "latest";
- return String.format("https://docs.sonarqube.org/%s/%s", docVersion, docPath);
- }
-
-}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWs.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWs.java
index 5a90630b4a8..d4ef9bcb279 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWs.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWs.java
@@ -20,19 +20,24 @@
package org.sonar.server.newcodeperiod.ws;
import org.sonar.api.server.ws.WebService;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
+
+import static org.sonar.server.ws.WsUtils.createHtmlExternalLink;
public class NewCodePeriodsWs implements WebService {
private final NewCodePeriodsWsAction[] actions;
+ private final DocumentationLinkGenerator documentationLinkGenerator;
- public NewCodePeriodsWs(NewCodePeriodsWsAction... actions) {
+ public NewCodePeriodsWs(DocumentationLinkGenerator documentationLinkGenerator, NewCodePeriodsWsAction... actions) {
this.actions = actions;
+ this.documentationLinkGenerator = documentationLinkGenerator;
}
@Override
public void define(Context context) {
NewController controller = context.createController("api/new_code_periods")
- .setDescription("Manage new code definitions.")
+ .setDescription("Manage "+ createHtmlExternalLink(documentationLinkGenerator.getDocumentationLink("/project-administration/defining-new-code/"), "new code definition") +".")
.setSince("8.0");
for (NewCodePeriodsWsAction action : actions) {
action.define(controller);
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/SetAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/SetAction.java
index 79683db81cf..317b09c3ffc 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/SetAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/SetAction.java
@@ -24,11 +24,11 @@ import java.util.EnumSet;
import java.util.Locale;
import java.util.Set;
import javax.annotation.Nullable;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.DbClient;
@@ -50,7 +50,7 @@ import static org.sonar.db.newcodeperiod.NewCodePeriodType.NUMBER_OF_DAYS;
import static org.sonar.db.newcodeperiod.NewCodePeriodType.PREVIOUS_VERSION;
import static org.sonar.db.newcodeperiod.NewCodePeriodType.REFERENCE_BRANCH;
import static org.sonar.db.newcodeperiod.NewCodePeriodType.SPECIFIC_ANALYSIS;
-import static org.sonar.server.newcodeperiod.ws.NewCodeActionSupport.getDocumentationUrl;
+import static org.sonar.server.ws.WsUtils.createHtmlExternalLink;
public class SetAction implements NewCodePeriodsWsAction {
private static final String PARAM_BRANCH = "branch";
@@ -71,24 +71,24 @@ public class SetAction implements NewCodePeriodsWsAction {
private final ComponentFinder componentFinder;
private final PlatformEditionProvider editionProvider;
private final NewCodePeriodDao newCodePeriodDao;
- private final Server server;
+ private final String newCodeDefinitionDocumentationUrl;
public SetAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, PlatformEditionProvider editionProvider,
- NewCodePeriodDao newCodePeriodDao, Server server) {
+ NewCodePeriodDao newCodePeriodDao, DocumentationLinkGenerator documentationLinkGenerator) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
this.editionProvider = editionProvider;
this.newCodePeriodDao = newCodePeriodDao;
- this.server = server;
+ this.newCodeDefinitionDocumentationUrl = documentationLinkGenerator.getDocumentationLink("/project-administration/defining-new-code/");
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("set")
.setPost(true)
- .setDescription("Updates the <a href=\"" + getDocumentationUrl(server.getVersion(), "project-administration/defining-new-code/") +
- "\">new code definition</a> on different levels:<br>" +
+ .setDescription("Updates the " + createHtmlExternalLink(newCodeDefinitionDocumentationUrl, "new code definition") +
+ " on different levels:<br>" +
BEGIN_LIST +
BEGIN_ITEM_LIST + "Not providing a project key and a branch key will update the default value at global level. " +
"Existing projects or branches having a specific new code definition will not be impacted" + END_ITEM_LIST +
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ShowAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ShowAction.java
index dd5111679ae..b47d88c9528 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ShowAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/ShowAction.java
@@ -21,11 +21,11 @@ package org.sonar.server.newcodeperiod.ws;
import java.util.Optional;
import javax.annotation.Nullable;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
@@ -40,8 +40,8 @@ import org.sonarqube.ws.NewCodePeriods;
import static java.lang.String.format;
import static org.sonar.db.permission.GlobalPermission.SCAN;
-import static org.sonar.server.newcodeperiod.ws.NewCodeActionSupport.getDocumentationUrl;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
+import static org.sonar.server.ws.WsUtils.createHtmlExternalLink;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.NewCodePeriods.ShowWSResponse;
@@ -53,22 +53,22 @@ public class ShowAction implements NewCodePeriodsWsAction {
private final UserSession userSession;
private final ComponentFinder componentFinder;
private final NewCodePeriodDao newCodePeriodDao;
- private final Server server;
+ private final String newCodeDefinitionDocumentationUrl;
- public ShowAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao, Server server) {
+ public ShowAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, NewCodePeriodDao newCodePeriodDao,
+ DocumentationLinkGenerator documentationLinkGenerator) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
this.newCodePeriodDao = newCodePeriodDao;
- this.server = server;
+ this.newCodeDefinitionDocumentationUrl = documentationLinkGenerator.getDocumentationLink("/project-administration/defining-new-code/");
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("show")
- .setDescription("Shows the <a href=\"" + getDocumentationUrl(server.getVersion(), "project-administration/defining-new-code/") +
- "\">new code definition</a>.<br> "
- + "If the component requested doesn't exist or if no new code definition is set for it, a value is inherited from the project or from the global setting." +
+ .setDescription("Shows the " + createHtmlExternalLink(newCodeDefinitionDocumentationUrl, "new code definition") + ".<br> " +
+ "If the component requested doesn't exist or if no new code definition is set for it, a value is inherited from the project or from the global setting." +
"Requires one of the following permissions if a component is specified: " +
"<ul>" +
"<li>'Administer' rights on the specified component</li>" +
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/UnsetAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/UnsetAction.java
index dd290bb50f8..0b313178a37 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/UnsetAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/newcodeperiod/ws/UnsetAction.java
@@ -19,11 +19,11 @@
*/
package org.sonar.server.newcodeperiod.ws;
-import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.DbClient;
@@ -36,7 +36,7 @@ import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UserSession;
import static java.lang.String.format;
-import static org.sonar.server.newcodeperiod.ws.NewCodeActionSupport.getDocumentationUrl;
+import static org.sonar.server.ws.WsUtils.createHtmlExternalLink;
public class UnsetAction implements NewCodePeriodsWsAction {
private static final String PARAM_BRANCH = "branch";
@@ -47,24 +47,24 @@ public class UnsetAction implements NewCodePeriodsWsAction {
private final ComponentFinder componentFinder;
private final PlatformEditionProvider editionProvider;
private final NewCodePeriodDao newCodePeriodDao;
- private final Server server;
+ private final String newCodeDefinitionDocumentationUrl;
public UnsetAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder,
- PlatformEditionProvider editionProvider, NewCodePeriodDao newCodePeriodDao, Server server) {
+ PlatformEditionProvider editionProvider, NewCodePeriodDao newCodePeriodDao, DocumentationLinkGenerator documentationLinkGenerator) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
this.editionProvider = editionProvider;
this.newCodePeriodDao = newCodePeriodDao;
- this.server = server;
+ this.newCodeDefinitionDocumentationUrl = documentationLinkGenerator.getDocumentationLink("/project-administration/defining-new-code/");
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("unset")
.setPost(true)
- .setDescription("Unsets the <a href=\"" + getDocumentationUrl(server.getVersion(), "project-administration/defining-new-code/") +
- "\">new code definition</a> for a branch, project or global.<br>" +
+ .setDescription("Unsets the " + createHtmlExternalLink(newCodeDefinitionDocumentationUrl, "new code definition") +
+ " for a branch, project or global.<br>" +
"Requires one of the following permissions: " +
"<ul>" +
"<li>'Administer System' to change the global setting</li>" +
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/DeleteAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/DeleteAction.java
index 212d19cb7dc..187ac7408e9 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/DeleteAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/DeleteAction.java
@@ -29,12 +29,12 @@ import org.sonar.db.project.ProjectDto;
import org.sonar.db.webhook.WebhookDto;
import org.sonar.server.user.UserSession;
+import static java.lang.String.format;
import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.DELETE_ACTION;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.WsUtils.checkStateWithOptional;
public class DeleteAction implements WebhooksWsAction {
@@ -78,7 +78,7 @@ public class DeleteAction implements WebhooksWsAction {
String projectUuid = webhookDto.getProjectUuid();
if (projectUuid != null) {
Optional<ProjectDto> optionalDto = dbClient.projectDao().selectByUuid(dbSession, projectUuid);
- ProjectDto projectDto = checkStateWithOptional(optionalDto, "the requested project '%s' was not found", projectUuid);
+ ProjectDto projectDto = optionalDto.orElseThrow(() -> new IllegalStateException(format("the requested project '%s' was not found", projectUuid)));
webhookSupport.checkPermission(projectDto);
deleteWebhook(dbSession, webhookDto);
} else {
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupportTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupportTest.java
deleted file mode 100644
index 552008e872c..00000000000
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodeActionSupportTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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.newcodeperiod.ws;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.newcodeperiod.ws.NewCodeActionSupport.getDocumentationUrl;
-
-public class NewCodeActionSupportTest {
- private static final String LATEST = "https://docs.sonarqube.org/latest/project-administration/defining-new-code/";
-
- @Test
- public void check_documentation_url_generation() {
- assertThat(getDocumentationUrl("10.1-SNAPSHOT", "project-administration/defining-new-code/")).isEqualTo(LATEST);
- assertThat(getDocumentationUrl("10.1.0.654666-SNAPSHOT", "project-administration/defining-new-code/")).isEqualTo(LATEST);
- assertThat(getDocumentationUrl("X.X.10.WHATEVER", "project-administration/defining-new-code/")).isEqualTo(LATEST);
- assertThat(getDocumentationUrl("9.9.0.65466", "another/path/")).isEqualTo("https://docs.sonarqube.org/9.9/another/path/");
- assertThat(getDocumentationUrl("9.8.0", "yet/another/path/")).isEqualTo("https://docs.sonarqube.org/9.8/yet/another/path/");
- assertThat(getDocumentationUrl("100.999.0", "yet/another/path/")).isEqualTo("https://docs.sonarqube.org/100.999/yet/another/path/");
- }
-
-}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWsTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWsTest.java
index 7c96703c725..9dffbbf9831 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWsTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/newcodeperiod/ws/NewCodePeriodsWsTest.java
@@ -23,14 +23,19 @@ import org.junit.Test;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
+import org.sonar.core.documentation.DocumentationLinkGenerator;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
public class NewCodePeriodsWsTest {
private String actionKey = randomAlphanumeric(10);
+ private DocumentationLinkGenerator documentationLinkGenerator = mock(DocumentationLinkGenerator.class);
+
+
private NewCodePeriodsWs underTest = new NewCodePeriodsWs(
- new NewCodePeriodsWsAction() {
+ documentationLinkGenerator, new NewCodePeriodsWsAction() {
@Override
public void define(WebService.NewController context) {
context.createAction(actionKey).setHandler(this);
diff --git a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java
index ed7fbb04004..dcc3f80c6c4 100644
--- a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java
+++ b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java
@@ -33,13 +33,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.sonarqube.ws.MediaTypes.JSON;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;
-public class WsUtils {
+public interface WsUtils {
- private WsUtils() {
- // only statics
- }
-
- public static void writeProtobuf(Message msg, Request request, Response response) {
+ static void writeProtobuf(Message msg, Request request, Response response) {
OutputStream output = response.stream().output();
try {
if (request.getMediaType().equals(PROTOBUF)) {
@@ -58,11 +54,7 @@ public class WsUtils {
}
}
- public static <T> T checkStateWithOptional(java.util.Optional<T> value, String message, Object... messageArguments) {
- if (!value.isPresent()) {
- throw new IllegalStateException(format(message, messageArguments));
- }
-
- return value.get();
+ static String createHtmlExternalLink(String url, String text) {
+ return String.format("<a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">%s</a>", url, text);
}
}
diff --git a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsUtilsTest.java b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsUtilsTest.java
index ebc320c6259..5981e9cb53f 100644
--- a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsUtilsTest.java
+++ b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsUtilsTest.java
@@ -84,6 +84,12 @@ public class WsUtilsTest {
}
@Test
+ public void create_safe_external_link_tag() {
+ assertThat(WsUtils.createHtmlExternalLink("http://google.com", "Google"))
+ .isEqualTo("<a href=\"http://google.com\" target=\"_blank\" rel=\"noopener noreferrer\">Google</a>");
+ }
+
+ @Test
public void checkRequest_ko() {
assertThatThrownBy(() -> BadRequestException.checkRequest(false, "Missing param: %s", "foo"))
.isInstanceOf(BadRequestException.class)
diff --git a/sonar-core/src/main/java/org/sonar/core/documentation/DefaultDocumentationLinkGenerator.java b/sonar-core/src/main/java/org/sonar/core/documentation/DefaultDocumentationLinkGenerator.java
index 6b447820b0d..dbfa0740328 100644
--- a/sonar-core/src/main/java/org/sonar/core/documentation/DefaultDocumentationLinkGenerator.java
+++ b/sonar-core/src/main/java/org/sonar/core/documentation/DefaultDocumentationLinkGenerator.java
@@ -41,7 +41,11 @@ public class DefaultDocumentationLinkGenerator implements DocumentationLinkGener
if (!url.endsWith("/")) {
url += "/";
}
- url += version.major() + "." + version.minor();
+ if (version.qualifier().equals("SNAPSHOT")) {
+ url += "latest";
+ } else {
+ url += version.major() + "." + version.minor();
+ }
return url;
}
diff --git a/sonar-core/src/test/java/org/sonar/core/documentation/DefaultDocumentationLinkGeneratorTest.java b/sonar-core/src/test/java/org/sonar/core/documentation/DefaultDocumentationLinkGeneratorTest.java
index 5d6cc77e5c2..5c20ea45ab4 100644
--- a/sonar-core/src/test/java/org/sonar/core/documentation/DefaultDocumentationLinkGeneratorTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/documentation/DefaultDocumentationLinkGeneratorTest.java
@@ -49,6 +49,7 @@ public class DefaultDocumentationLinkGeneratorTest {
public void setUp() {
when(sonarQubeVersion.get().major()).thenReturn(100);
when(sonarQubeVersion.get().minor()).thenReturn(1000);
+ when(sonarQubeVersion.get().qualifier()).thenReturn("");
when(configuration.get(DOCUMENTATION_BASE_URL)).thenReturn(Optional.empty());
documentationLinkGenerator = new DefaultDocumentationLinkGenerator(sonarQubeVersion, configuration);
}
@@ -61,6 +62,16 @@ public class DefaultDocumentationLinkGeneratorTest {
}
@Test
+ public void getDocumentationLink_whenSnapshot_returnLatest() {
+ when(sonarQubeVersion.get().qualifier()).thenReturn("SNAPSHOT");
+ documentationLinkGenerator = new DefaultDocumentationLinkGenerator(sonarQubeVersion, configuration);
+
+ String generatedLink = documentationLinkGenerator.getDocumentationLink(TEST_SUFFIX);
+
+ assertThat(generatedLink).isEqualTo(DOCUMENTATION_PUBLIC_URL + "latest/documentation/analyzing-source-code/scm-integration/");
+ }
+
+ @Test
public void getDocumentationLink_whenSuffixNotProvided_returnsBaseUrl() {
String generatedLink = documentationLinkGenerator.getDocumentationLink(null);