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 {
--- /dev/null
+/*
+ * 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);
+ }
+}
private static void defineRailsActions(NewController controller) {
defineChangelogAction(controller);
- defineAssignAction(controller);
defineAddCommentAction(controller);
defineDeleteCommentAction(controller);
defineEditCommentAction(controller);
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")
--- /dev/null
+/*
+ * 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);
+ }
+}
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;
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,
--- /dev/null
+/*
+ * 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));
+ }
+}
+/*
+ * 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;
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