aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacek <jacek.poreda@sonarsource.com>2020-02-12 16:34:45 +0100
committerSonarTech <sonartech@sonarsource.com>2020-02-21 20:46:18 +0100
commitf198157719a6b5fd841a93c8e34728ddcb4d4759 (patch)
tree589af35bd3756d2c5ac24988adbed119303a9f7f
parent3ac2de9977c7f59ecdd8da13d5e8a5f797097f7d (diff)
downloadsonarqube-f198157719a6b5fd841a93c8e34728ddcb4d4759.tar.gz
sonarqube-f198157719a6b5fd841a93c8e34728ddcb4d4759.zip
SONAR-12922 add delete hotspot comment WS
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/DeleteCommentAction.java94
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotWsSupport.java5
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotsWsModule.java1
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/DeleteCommentActionTest.java183
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/HotspotsWsModuleTest.java2
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/DeleteCommentRequest.java47
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/HotspotsService.java15
7 files changed, 346 insertions, 1 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/DeleteCommentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/DeleteCommentAction.java
new file mode 100644
index 00000000000..4d74a212c09
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/DeleteCommentAction.java
@@ -0,0 +1,94 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.hotspot.ws;
+
+import java.util.Objects;
+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.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.issue.IssueChangeDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+
+public class DeleteCommentAction implements HotspotsWsAction {
+ private static final String PARAM_COMMENT = "comment";
+
+ private final UserSession userSession;
+ private final DbClient dbClient;
+ private final HotspotWsSupport hotspotWsSupport;
+
+ public DeleteCommentAction(DbClient dbClient, HotspotWsSupport hotspotWsSupport, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.hotspotWsSupport = hotspotWsSupport;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller
+ .createAction("delete_comment")
+ .setHandler(this)
+ .setPost(true)
+ .setDescription("Delete comment from Security Hotpot.<br/>" +
+ "Requires authentication and the following permission: 'Browse' on the project of the specified Security Hotspot.")
+ .setSince("8.2")
+ .setInternal(true);
+
+ action.createParam(PARAM_COMMENT)
+ .setDescription("Comment key.")
+ .setRequired(true)
+ .setExampleValue(UUID_EXAMPLE_01);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ hotspotWsSupport.checkLoggedIn();
+
+ String commentKey = request.mandatoryParam(PARAM_COMMENT);
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ IssueChangeDto hotspotComment = getHotspotComment(commentKey, dbSession);
+ validate(dbSession, hotspotComment);
+ deleteComment(dbSession, hotspotComment.getKey());
+ response.noContent();
+ }
+ }
+
+ private IssueChangeDto getHotspotComment(String commentKey, DbSession dbSession) {
+ return dbClient.issueChangeDao().selectCommentByKey(dbSession, commentKey)
+ .orElseThrow(() -> new NotFoundException(format("Comment with key '%s' does not exist", commentKey)));
+ }
+
+ private void validate(DbSession dbSession, IssueChangeDto issueChangeDto) {
+ hotspotWsSupport.loadAndCheckProject(dbSession, issueChangeDto.getIssueKey());
+ checkArgument(Objects.equals(issueChangeDto.getUserUuid(), userSession.getUuid()), "You can only delete your own comments");
+ }
+
+ private void deleteComment(DbSession dbSession, String commentKey) {
+ dbClient.issueChangeDao().delete(dbSession, commentKey);
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotWsSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotWsSupport.java
index 31c1f5ed430..29a280a2e64 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotWsSupport.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotWsSupport.java
@@ -50,6 +50,11 @@ public class HotspotWsSupport {
return userSession.checkLoggedIn().getUuid();
}
+ ComponentDto loadAndCheckProject(DbSession dbSession, String hotspotKey) {
+ IssueDto hotspot = loadHotspot(dbSession, hotspotKey);
+ return loadAndCheckProject(dbSession, hotspot, UserRole.USER);
+ }
+
IssueDto loadHotspot(DbSession dbSession, String hotspotKey) {
return dbClient.issueDao().selectByKey(dbSession, hotspotKey)
.filter(t -> t.getType() == RuleType.SECURITY_HOTSPOT.getDbConstant())
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotsWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotsWsModule.java
index 73c05653e5f..1979b02e076 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotsWsModule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/HotspotsWsModule.java
@@ -32,6 +32,7 @@ public class HotspotsWsModule extends Module {
ShowAction.class,
ChangeStatusAction.class,
AddCommentAction.class,
+ DeleteCommentAction.class,
HotspotsWs.class);
}
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/DeleteCommentActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/DeleteCommentActionTest.java
new file mode 100644
index 00000000000..f2937d5347d
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/DeleteCommentActionTest.java
@@ -0,0 +1,183 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.hotspot.ws;
+
+import java.util.Optional;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.issue.IssueChangeDto;
+import org.sonar.db.issue.IssueDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+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.mockito.Mockito.mock;
+
+public class DeleteCommentActionTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+ private DbClient dbClient = dbTester.getDbClient();
+ private System2 system2 = mock(System2.class);
+ private HotspotWsSupport hotspotWsSupport = new HotspotWsSupport(dbClient, userSessionRule, system2);
+
+ private DeleteCommentAction underTest = new DeleteCommentAction(dbClient, hotspotWsSupport, userSessionRule);
+ private WsActionTester actionTester = new WsActionTester(underTest);
+
+ @Test
+ public void verify_ws_def() {
+ assertThat(actionTester.getDef().isInternal()).isTrue();
+ assertThat(actionTester.getDef().isPost()).isTrue();
+
+ Param commentKeyParam = actionTester.getDef().param("comment");
+ assertThat(commentKeyParam).isNotNull();
+ assertThat(commentKeyParam.isRequired()).isTrue();
+ }
+
+ @Test
+ public void delete_comment_from_hotspot_private_project() {
+ UserDto userDeletingOwnComment = dbTester.users().insertUser();
+
+ ComponentDto project = dbTester.components().insertPrivateProject();
+
+ IssueDto hotspot = dbTester.issues().insertHotspot(h -> h.setProject(project));
+ IssueChangeDto comment = dbTester.issues().insertComment(hotspot, userDeletingOwnComment, "Some comment");
+
+ userSessionRule.logIn(userDeletingOwnComment);
+ userSessionRule.addProjectPermission(UserRole.USER, project);
+
+ TestRequest request = newRequest(comment.getKey());
+
+ TestResponse response = request.execute();
+ assertThat(response.getStatus()).isEqualTo(204);
+ assertThat(getHotspotCommentByKey(comment.getKey()))
+ .isEmpty();
+ }
+
+ @Test
+ public void delete_comment_from_hotspot_public_project() {
+ UserDto userAddingComment = dbTester.users().insertUser();
+
+ ComponentDto project = dbTester.components().insertPublicProject();
+
+ IssueDto hotspot = dbTester.issues().insertHotspot(h -> h.setProject(project));
+ IssueChangeDto comment = dbTester.issues().insertComment(hotspot, userAddingComment, "Some comment");
+
+ assertThat(getHotspotCommentByKey(comment.getKey()))
+ .isNotEmpty();
+
+ userSessionRule.logIn(userAddingComment);
+ userSessionRule.registerComponents(project);
+
+ TestRequest request = newRequest(comment.getKey());
+
+ TestResponse response = request.execute();
+ assertThat(response.getStatus()).isEqualTo(204);
+ assertThat(getHotspotCommentByKey(comment.getKey()))
+ .isEmpty();
+ }
+
+ @Test
+ public void fails_with_UnauthorizedException_if_user_is_anonymous() {
+ userSessionRule.anonymous();
+
+ TestRequest request = actionTester.newRequest();
+
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(UnauthorizedException.class)
+ .hasMessage("Authentication is required");
+ }
+
+ @Test
+ public void fails_if_comment_with_provided_key_does_not_exist() {
+ userSessionRule.logIn();
+
+ TestRequest request = newRequest("not-existing-comment-key");
+
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage("Comment with key 'not-existing-comment-key' does not exist");
+ }
+
+ @Test
+ public void fails_if_trying_to_delete_comment_of_another_user_in_private_project() {
+ UserDto userTryingToDelete = dbTester.users().insertUser();
+ UserDto userWithHotspotComment = dbTester.users().insertUser();
+
+ ComponentDto project = dbTester.components().insertPrivateProject();
+
+ IssueDto hotspot = dbTester.issues().insertHotspot(h -> h.setProject(project));
+ IssueChangeDto comment = dbTester.issues().insertComment(hotspot, userWithHotspotComment, "Some comment");
+
+ userSessionRule.logIn(userTryingToDelete);
+ userSessionRule.addProjectPermission(UserRole.USER, project);
+
+ TestRequest request = newRequest(comment.getKey());
+
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("You can only delete your own comments");
+ }
+
+ @Test
+ public void fails_if_trying_to_delete_comment_of_another_user_in_public_project() {
+ UserDto userTryingToDelete = dbTester.users().insertUser();
+ UserDto userWithHotspotComment = dbTester.users().insertUser();
+
+ ComponentDto project = dbTester.components().insertPublicProject();
+
+ IssueDto hotspot = dbTester.issues().insertHotspot(h -> h.setProject(project));
+ IssueChangeDto comment = dbTester.issues().insertComment(hotspot, userWithHotspotComment, "Some comment");
+
+ userSessionRule.logIn(userTryingToDelete)
+ .registerComponents(project);
+
+ TestRequest request = newRequest(comment.getKey());
+
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("You can only delete your own comments");
+ }
+
+ private TestRequest newRequest(String commentKey) {
+ return actionTester.newRequest()
+ .setParam("comment", commentKey);
+ }
+
+ private Optional<IssueChangeDto> getHotspotCommentByKey(String commentKey) {
+ return dbClient.issueChangeDao().selectCommentByKey(dbTester.getSession(), commentKey);
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/HotspotsWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/HotspotsWsModuleTest.java
index f0618b66128..099aecbd6a2 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/HotspotsWsModuleTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/HotspotsWsModuleTest.java
@@ -30,7 +30,7 @@ public class HotspotsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new HotspotsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 8);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 9);
}
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/DeleteCommentRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/DeleteCommentRequest.java
new file mode 100644
index 00000000000..a3426bd6b7f
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/DeleteCommentRequest.java
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.sonarqube.ws.client.hotspots;
+
+import javax.annotation.Generated;
+
+/**
+ * This is part of the internal API.
+ * This is a POST request.
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/hotspots/delete_comment">Further information about this action online (including a response example)</a>
+ * @since 8.2
+ */
+@Generated("sonar-ws-generator")
+public class DeleteCommentRequest {
+
+ private String comment;
+
+ /**
+ * This is a mandatory parameter.
+ * Example value: "AU-Tpxb--iU5OvuD2FLy"
+ */
+ public DeleteCommentRequest setComment(String comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/HotspotsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/HotspotsService.java
index be4ec96dc3e..4b37ba48a43 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/HotspotsService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/hotspots/HotspotsService.java
@@ -89,6 +89,21 @@ public class HotspotsService extends BaseService {
/**
*
* This is part of the internal API.
+ * This is a POST request.
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/hotspots/delete_comment">Further information about this action online (including a response example)</a>
+ * @since 8.2
+ */
+ public void deleteComment(DeleteCommentRequest request) {
+ call(
+ new PostRequest(path("delete_comment"))
+ .setParam("comment", request.getComment())
+ .setMediaType(MediaTypes.JSON)
+ ).content();
+ }
+
+ /**
+ *
+ * This is part of the internal API.
* This is a GET request.
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/hotspots/search">Further information about this action online (including a response example)</a>
* @since 8.1