]> source.dussan.org Git - sonarqube.git/commitdiff
WS api/issues/assign in Java+Protobuf
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Sun, 2 Aug 2015 21:26:59 +0000 (23:26 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 5 Aug 2015 17:32:11 +0000 (19:32 +0200)
server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/AssignAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/OperationResponseWriter.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/AssignActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ws/WsUtilsTest.java
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb

index 2690882d7626c658cedf099dd0c28aaf2f843d1f..ecb4e0a02a3fcd97d96353f3145edd8a54c33166 100644 (file)
@@ -192,16 +192,6 @@ public class InternalRubyIssueService {
     return result;
   }
 
-  public Result<Issue> assign(String issueKey, @Nullable String assignee) {
-    Result<Issue> result = Result.of();
-    try {
-      result.set(issueService.assign(issueKey, StringUtils.defaultIfBlank(assignee, null)));
-    } catch (Exception e) {
-      result.addError(e.getMessage());
-    }
-    return result;
-  }
-
   public Result<Issue> setSeverity(String issueKey, String severity) {
     Result<Issue> result = Result.of();
     try {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AssignAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AssignAction.java
new file mode 100644 (file)
index 0000000..cdcf024
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.issue.ws;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.user.UserSession;
+
+public class AssignAction implements IssuesWsAction {
+
+  public static final String ASSIGN_ACTION = "assign";
+
+  private final UserSession userSession;
+  private final IssueService issueService;
+  private final OperationResponseWriter responseWriter;
+
+  public AssignAction(UserSession userSession, IssueService issueService, OperationResponseWriter responseWriter) {
+    this.userSession = userSession;
+    this.issueService = issueService;
+    this.responseWriter = responseWriter;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction(ASSIGN_ACTION)
+      .setDescription("Assign/Unassign an issue. Requires authentication and Browse permission on project")
+      .setSince("3.6")
+      .setHandler(this)
+      .setPost(true);
+    // TODO add example of response
+
+    action.createParam("issue")
+      .setDescription("Key of the issue")
+      .setRequired(true)
+      .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
+    action.createParam("assignee")
+      // TODO document absent value for unassign, or _me for assigning to me
+      .setDescription("Login of the assignee")
+      .setExampleValue("admin");
+    action.createParam("me")
+      .setDescription("(deprecated) Assign the issue to the logged-in user. Replaced by the parameter assignee=_me")
+      .setBooleanPossibleValues();
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+
+    String assignee = request.param("assignee");
+    if ("_me".equals(assignee) || BooleanUtils.isTrue(request.paramAsBoolean("me"))) {
+      // Permission is currently checked by IssueService. We still
+      // check that user is authenticated in order to get his login.
+      userSession.checkLoggedIn();
+      assignee = userSession.getLogin();
+    }
+    String key = request.mandatoryParam("issue");
+    issueService.assign(key, assignee);
+
+    responseWriter.write(key, request, response);
+  }
+}
index 9089029b21ae954aca0d96b413013d90a67fca53..3232d0725da156926a2422660a38903996f1698f 100644 (file)
@@ -62,7 +62,6 @@ public class IssuesWs implements WebService {
 
   private static void defineRailsActions(NewController controller) {
     defineChangelogAction(controller);
-    defineAssignAction(controller);
     defineAddCommentAction(controller);
     defineDeleteCommentAction(controller);
     defineEditCommentAction(controller);
@@ -89,23 +88,6 @@ public class IssuesWs implements WebService {
     RailsHandler.addFormatParam(action);
   }
 
-  private static void defineAssignAction(NewController controller) {
-    WebService.NewAction action = controller.createAction(ASSIGN_ACTION)
-      .setDescription("Assign/Unassign an issue. Requires authentication and Browse permission on project")
-      .setSince("3.6")
-      .setHandler(RailsHandler.INSTANCE)
-      .setPost(true);
-
-    action.createParam("issue")
-      .setDescription("Key of the issue")
-      .setRequired(true)
-      .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
-    action.createParam("assignee")
-      .setDescription("Login of the assignee")
-      .setExampleValue("admin");
-    RailsHandler.addFormatParam(action);
-  }
-
   private static void defineAddCommentAction(NewController controller) {
     WebService.NewAction action = controller.createAction(ADD_COMMENT_ACTION)
       .setDescription("Add a comment. Requires authentication and Browse permission on project")
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/OperationResponseWriter.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/OperationResponseWriter.java
new file mode 100644 (file)
index 0000000..13d3bbe
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.issue.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.ws.WsUtils;
+import org.sonarqube.ws.Issues;
+
+import static java.util.Collections.singletonList;
+import static org.sonar.server.issue.ws.SearchAdditionalField.ALL_ADDITIONAL_FIELDS;
+
+public class OperationResponseWriter {
+
+  private final SearchResponseLoader loader;
+  private final SearchResponseFormat format;
+
+  public OperationResponseWriter(SearchResponseLoader loader, SearchResponseFormat format) {
+    this.loader = loader;
+    this.format = format;
+  }
+
+  public void write(String issueKey, Request request, Response response) throws Exception {
+    SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(
+      ALL_ADDITIONAL_FIELDS, singletonList(issueKey));
+    SearchResponseData data = loader.load(collector, null);
+
+    Issues.Search responseBody = this.format.format(ALL_ADDITIONAL_FIELDS, data, null, null);
+
+    WsUtils.writeProtobuf(responseBody, request, response);
+  }
+}
index b4e68e63bb3dd17d54ced84f87972deb85885fa8..2ac4baecc072466e86f7b2432e0e3a645023d0f1 100644 (file)
@@ -158,6 +158,7 @@ import org.sonar.server.issue.ws.IssueActionsWriter;
 import org.sonar.server.issue.ws.IssueComponentHelper;
 import org.sonar.server.issue.ws.IssueJsonWriter;
 import org.sonar.server.issue.ws.IssuesWs;
+import org.sonar.server.issue.ws.OperationResponseWriter;
 import org.sonar.server.issue.ws.SearchResponseFormat;
 import org.sonar.server.issue.ws.SearchResponseLoader;
 import org.sonar.server.issue.ws.SetTagsAction;
@@ -608,6 +609,8 @@ public class PlatformLevel4 extends PlatformLevel {
       WsResponseCommonFormat.class,
       SearchResponseLoader.class,
       SearchResponseFormat.class,
+      OperationResponseWriter.class,
+      org.sonar.server.issue.ws.AssignAction.class,
       org.sonar.server.issue.ws.ShowAction.class,
       org.sonar.server.issue.ws.SearchAction.class,
       org.sonar.server.issue.ws.Search2Action.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/AssignActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/AssignActionTest.java
new file mode 100644 (file)
index 0000000..d61c898
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.issue.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class AssignActionTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  IssueService issueService = mock(IssueService.class);
+  OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
+  AssignAction underTest = new AssignAction(userSession, issueService, responseWriter);
+  WsActionTester tester = new WsActionTester(underTest);
+
+  @Test
+  public void assign_to_me() throws Exception {
+    userSession.login("perceval");
+
+    tester.newRequest()
+      .setParam("issue", "ABC")
+      .setParam("assignee", "_me")
+      .execute();
+
+    verify(issueService).assign("ABC", "perceval");
+    verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+  }
+
+  @Test
+  public void assign_to_me_with_deprecated_param() throws Exception {
+    userSession.login("perceval");
+
+    tester.newRequest()
+      .setParam("issue", "ABC")
+      .setParam("me", "true")
+      .execute();
+
+    verify(issueService).assign("ABC", "perceval");
+    verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+  }
+
+  @Test
+  public void assign_to_someone() throws Exception {
+    userSession.login("perceval");
+
+    tester.newRequest()
+      .setParam("issue", "ABC")
+      .setParam("assignee", "arthur")
+      .execute();
+
+    verify(issueService).assign("ABC", "arthur");
+    verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+  }
+
+  @Test
+  public void must_be_authenticated_to_assign_to_me() throws Exception {
+    expectedException.expect(UnauthorizedException.class);
+
+    tester.newRequest()
+      .setParam("issue", "ABC")
+      .setParam("assignee", "_me")
+      .execute();
+  }
+
+  @Test
+  public void unassign() throws Exception {
+    userSession.login("perceval");
+
+    tester.newRequest()
+      .setParam("issue", "ABC")
+      .execute();
+
+    verify(issueService).assign("ABC", null);
+    verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+  }
+}
index 0edfbecb6fda2c9de70ad5778be6f728adc27a66..a0227286f393567d042a0ea20cd5f9df2210eeb7 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.ws;
 
 import org.junit.Test;
index 020b251147449429dd00d2e0312be87a0b633a6f..9d06746a051c7f98ffae36e54b557db81a2e4b5a 100644 (file)
@@ -145,24 +145,6 @@ class Api::IssuesController < Api::ApiController
     end
   end
 
-  #
-  # Assign an existing issue to a user or un-assign.
-  #
-  # POST /api/issues/assign?issue=<key>&assignee=<optional assignee>&me=<true or false>
-  # A nil or blank assignee removes the assignee.
-  #
-  # -- Example
-  # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/assign?issue=4a2881e7-825e-4140-a154-01f420c43d11&assignee=emmerik'
-  #
-  def assign
-    verify_post_request
-    require_parameters :issue
-
-    assignee = (params[:me]=='true' ? current_user.login : params[:assignee])
-    result = Internal.issues.assign(params[:issue], assignee)
-    render_result_issue(result)
-  end
-
 
   #
   # Change the severity of an existing issue