From: Pierre Guillot Date: Mon, 31 Jul 2023 07:07:28 +0000 (+0200) Subject: SONAR-19372 validate transitions X-Git-Tag: 10.2.0.77647~261 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=958b8cc8f68974ff0294bba2ee0b7a71af14bf1a;p=sonarqube.git SONAR-19372 validate transitions --- diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsActionIT.java index b7913311c6a..8dee07a4aa7 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsActionIT.java @@ -71,18 +71,18 @@ public class AnticipatedTransitionsActionIT { assertThat(definition.key()).isEqualTo("anticipated_transitions"); assertThat(definition.description()).isEqualTo(""" Receive a list of anticipated transitions that can be applied to not yet discovered issues on a specific project.
- Requires the following permission: 'Administer' on the specified project.

+ Requires the following permission: 'Administer Issues' on the specified project.
+ Only falsepositive and wontfix transitions are supported.
Upon successful execution, the HTTP status code returned is 202 (Accepted).

Request example: -

-      [
+      
[
         {
           "ruleKey": "squid:S0001",
           "issueMessage": "issueMessage1",
           "filePath": "filePath1",
           "line": 1,
           "lineHash": "lineHash1",
-          "transition": "transition1",
+          "transition": "falsepositive",
           "comment": "comment1"
         },
         {
@@ -91,10 +91,10 @@ public class AnticipatedTransitionsActionIT {
           "filePath": "filePath2",
           "line": 2,
           "lineHash": "lineHash2",
-          "transition": "transition2",
+          "transition": "wontfix",
           "comment": "comment2"
         }
-      ]""");
+      ]
"""); assertThat(definition.isPost()).isTrue(); assertThat(definition.isInternal()).isTrue(); assertThat(definition.params()).extracting(WebService.Param::key, WebService.Param::isRequired, WebService.Param::description, WebService.Param::since).containsExactlyInAnyOrder( @@ -166,7 +166,7 @@ public class AnticipatedTransitionsActionIT { "filePath": "filePath3", "line": 3, "lineHash": "lineHash3", - "transition": "transition3", + "transition": "wontfix", "comment": "comment3" } ]"""; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java index 2687b7b16bc..eb02da3726a 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java @@ -22,19 +22,34 @@ package org.sonar.server.issue.ws.anticipatedtransition; import com.google.gson.Gson; import java.util.Arrays; import java.util.List; +import java.util.Set; import org.sonar.api.rule.RuleKey; import org.sonar.core.issue.AnticipatedTransition; public class AnticipatedTransitionParser { private static final Gson GSON = new Gson(); + private static final String WONTFIX = "wontfix"; + private static final String FALSEPOSITIVE = "falsepositive"; + private static final Set ALLOWED_TRANSITIONS = Set.of(WONTFIX, FALSEPOSITIVE); + private static final String TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE = "Transition '%s' not supported. Only 'wontfix' and 'falsepositive' are supported."; public List parse(String requestBody, String userUuid, String projectKey) { + List anticipatedTransitions; try { - List anticipatedTransitions = Arrays.asList(GSON.fromJson(requestBody, GsonAnticipatedTransition[].class)); - return mapBodyToAnticipatedTransitions(anticipatedTransitions, userUuid, projectKey); + anticipatedTransitions = Arrays.asList(GSON.fromJson(requestBody, GsonAnticipatedTransition[].class)); } catch (Exception e) { throw new IllegalStateException("Unable to parse anticipated transitions from request body.", e); } + validateAnticipatedTransitions(anticipatedTransitions); + return mapBodyToAnticipatedTransitions(anticipatedTransitions, userUuid, projectKey); + } + + private static void validateAnticipatedTransitions(List anticipatedTransitions) { + for (GsonAnticipatedTransition anticipatedTransition : anticipatedTransitions) { + if (!ALLOWED_TRANSITIONS.contains(anticipatedTransition.transition())) { + throw new IllegalArgumentException(String.format(TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE, anticipatedTransition.transition())); + } + } } private static List mapBodyToAnticipatedTransitions(List anticipatedTransitions, String userUuid, String projectKey) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsAction.java index ca89b13a46c..287f0abd740 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionsAction.java @@ -45,18 +45,18 @@ public class AnticipatedTransitionsAction implements IssuesWsAction { public void define(WebService.NewController controller) { WebService.NewAction action = controller.createAction(IssuesWsParameters.ACTION_ANTICIPATED_TRANSITIONS).setDescription(""" Receive a list of anticipated transitions that can be applied to not yet discovered issues on a specific project.
- Requires the following permission: 'Administer' on the specified project.

+ Requires the following permission: 'Administer Issues' on the specified project.
+ Only falsepositive and wontfix transitions are supported.
Upon successful execution, the HTTP status code returned is 202 (Accepted).

Request example: -

-      [
+      
[
         {
           "ruleKey": "squid:S0001",
           "issueMessage": "issueMessage1",
           "filePath": "filePath1",
           "line": 1,
           "lineHash": "lineHash1",
-          "transition": "transition1",
+          "transition": "falsepositive",
           "comment": "comment1"
         },
         {
@@ -65,10 +65,10 @@ public class AnticipatedTransitionsAction implements IssuesWsAction {
           "filePath": "filePath2",
           "line": 2,
           "lineHash": "lineHash2",
-          "transition": "transition2",
+          "transition": "wontfix",
           "comment": "comment2"
         }
-      ]""")
+      ]
""") .setSince("10.2") .setHandler(this) .setInternal(true) diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParserTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParserTest.java index 6d648b582fe..02b3e5042df 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParserTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParserTest.java @@ -74,6 +74,29 @@ public class AnticipatedTransitionParserTest { .hasMessage("Unable to parse anticipated transitions from request body."); } + @Test + public void givenRequestBodyWithInvalidTransition_whenParse_thenExceptionIsThrown() throws IOException { + // given + String requestBodyWithInvalidTransition = """ + [ + { + "ruleKey": "squid:S0001", + "issueMessage": "issueMessage1", + "filePath": "filePath1", + "line": 1, + "lineHash": "lineHash1", + "transition": "invalid-transition", + "comment": "comment1" + }, + ] + """; + + // when + Assertions.assertThatThrownBy(() -> underTest.parse(requestBodyWithInvalidTransition, USER_UUID, PROJECT_KEY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Transition 'invalid-transition' not supported. Only 'wontfix' and 'falsepositive' are supported."); + } + // Handwritten Anticipated Transitions that are expected from the request-with-transitions.json file private List transitionsExpectedFromTestFile() { return List.of( @@ -86,7 +109,7 @@ public class AnticipatedTransitionParserTest { "filePath1", 1, "lineHash1", - "transition1", + "wontfix", "comment1"), new AnticipatedTransition( PROJECT_KEY, @@ -97,7 +120,7 @@ public class AnticipatedTransitionParserTest { "filePath2", 2, "lineHash2", - "transition2", + "falsepositive", "comment2")); } @@ -105,4 +128,4 @@ public class AnticipatedTransitionParserTest { return Files.readString(Path.of(getClass().getResource(fileName).getPath())); } -} \ No newline at end of file +} diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/issue/ws/anticipatedtransition/request-with-transitions.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/issue/ws/anticipatedtransition/request-with-transitions.json index c9697230b86..0a822ac5b77 100644 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/issue/ws/anticipatedtransition/request-with-transitions.json +++ b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/issue/ws/anticipatedtransition/request-with-transitions.json @@ -5,7 +5,7 @@ "filePath": "filePath1", "line": 1, "lineHash": "lineHash1", - "transition": "transition1", + "transition": "wontfix", "comment": "comment1" }, { @@ -14,7 +14,7 @@ "filePath": "filePath2", "line": 2, "lineHash": "lineHash2", - "transition": "transition2", + "transition": "falsepositive", "comment": "comment2" } ] \ No newline at end of file