Browse Source

SONAR-8635 Remove "assign_to_me" actions from issues

tags/6.7-RC1
Julien Lancelot 6 years ago
parent
commit
52182f4c03
17 changed files with 37 additions and 179 deletions
  1. 0
    66
      server/sonar-server/src/main/java/org/sonar/server/issue/ActionFinder.java
  2. 0
    2
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java
  3. 33
    5
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
  4. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/add_comment-example.json
  5. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/assign-example.json
  6. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/delete_comment-example.json
  7. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/do_transition-example.json
  8. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/edit_comment-example.json
  9. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_severity-example.json
  10. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_tags-example.json
  11. 0
    1
      server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_type-example.json
  12. 0
    88
      server/sonar-server/src/test/java/org/sonar/server/issue/ActionFinderTest.java
  13. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java
  14. 1
    3
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java
  15. 1
    3
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
  16. 1
    2
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionTest/load_additional_fields.json
  17. 0
    1
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionTest/load_additional_fields_with_issue_admin_permission.json

+ 0
- 66
server/sonar-server/src/main/java/org/sonar/server/issue/ActionFinder.java View File

@@ -1,66 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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.issue;

import java.util.Collections;
import java.util.List;
import org.sonar.db.issue.IssueDto;
import org.sonar.server.user.UserSession;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.server.issue.AssignAction.ASSIGN_KEY;
import static org.sonar.server.issue.CommentAction.COMMENT_KEY;
import static org.sonar.server.issue.SetSeverityAction.SET_SEVERITY_KEY;
import static org.sonar.server.issue.SetTypeAction.SET_TYPE_KEY;

public class ActionFinder {

private final UserSession userSession;

public ActionFinder(UserSession userSession) {
this.userSession = userSession;
}

public List<String> listAvailableActions(IssueDto issue) {
List<String> availableActions = newArrayList();
String login = userSession.getLogin();
if (login == null) {
return Collections.emptyList();
}
availableActions.add(COMMENT_KEY);
if (issue.getResolution() != null) {
return availableActions;
}
availableActions.add(ASSIGN_KEY);
availableActions.add("set_tags");
if (!login.equals(issue.getAssignee())) {
// This action will be removed by
availableActions.add("assign_to_me");
}
if (userSession.hasComponentUuidPermission(ISSUE_ADMIN, requireNonNull(issue.getProjectUuid()))) {
availableActions.add(SET_TYPE_KEY);
availableActions.add(SET_SEVERITY_KEY);
}
return availableActions;
}

}

+ 0
- 2
server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java View File

@@ -20,7 +20,6 @@
package org.sonar.server.issue.ws;

import org.sonar.core.platform.Module;
import org.sonar.server.issue.ActionFinder;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.IssueFinder;
import org.sonar.server.issue.IssueQueryFactory;
@@ -37,7 +36,6 @@ public class IssueWsModule extends Module {
@Override
protected void configureModule() {
add(
ActionFinder.class,
IssueUpdater.class,
IssueFinder.class,
TransitionService.class,

+ 33
- 5
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java View File

@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -40,7 +41,6 @@ import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.es.Facets;
import org.sonar.server.issue.ActionFinder;
import org.sonar.server.issue.TransitionService;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.client.issue.IssuesWsParameters;
@@ -51,7 +51,12 @@ import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.difference;
import static java.util.Collections.emptyList;
import static java.util.stream.Stream.concat;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.core.util.stream.MoreCollectors.toList;
import static org.sonar.server.issue.AssignAction.ASSIGN_KEY;
import static org.sonar.server.issue.CommentAction.COMMENT_KEY;
import static org.sonar.server.issue.SetSeverityAction.SET_SEVERITY_KEY;
import static org.sonar.server.issue.SetTypeAction.SET_TYPE_KEY;
import static org.sonar.server.issue.ws.SearchAdditionalField.ACTIONS;
import static org.sonar.server.issue.ws.SearchAdditionalField.COMMENTS;
import static org.sonar.server.issue.ws.SearchAdditionalField.RULES;
@@ -65,13 +70,11 @@ public class SearchResponseLoader {

private final UserSession userSession;
private final DbClient dbClient;
private final ActionFinder actionService;
private final TransitionService transitionService;

public SearchResponseLoader(UserSession userSession, DbClient dbClient, ActionFinder actionService, TransitionService transitionService) {
public SearchResponseLoader(UserSession userSession, DbClient dbClient, TransitionService transitionService) {
this.userSession = userSession;
this.dbClient = dbClient;
this.actionService = actionService;
this.transitionService = transitionService;
}

@@ -241,10 +244,16 @@ public class SearchResponseLoader {

private void loadActionsAndTransitions(Collector collector, SearchResponseData result) {
if (collector.contains(ACTIONS) || collector.contains(TRANSITIONS)) {
Map<String, ComponentDto> componentsByProjectUuid =
result.getComponents()
.stream()
.filter(ComponentDto::isRootProject)
.collect(MoreCollectors.uniqueIndex(ComponentDto::projectUuid));
for (IssueDto dto : result.getIssues()) {
// so that IssueDto can be used.
if (collector.contains(ACTIONS)) {
result.addActions(dto.getKey(), actionService.listAvailableActions(dto));
ComponentDto project = componentsByProjectUuid.get(dto.getProjectUuid());
result.addActions(dto.getKey(), listAvailableActions(dto, project));
}
if (collector.contains(TRANSITIONS)) {
// TODO workflow and action engines must not depend on org.sonar.api.issue.Issue but on a generic interface
@@ -255,6 +264,25 @@ public class SearchResponseLoader {
}
}

private List<String> listAvailableActions(IssueDto issue, ComponentDto project) {
List<String> availableActions = newArrayList();
String login = userSession.getLogin();
if (login == null) {
return Collections.emptyList();
}
availableActions.add(COMMENT_KEY);
if (issue.getResolution() != null) {
return availableActions;
}
availableActions.add(ASSIGN_KEY);
availableActions.add("set_tags");
if (userSession.hasComponentPermission(ISSUE_ADMIN, project)) {
availableActions.add(SET_TYPE_KEY);
availableActions.add(SET_SEVERITY_KEY);
}
return availableActions;
}

private static void completeTotalEffortFromFacet(@Nullable Facets facets, SearchResponseData result) {
if (facets != null) {
Map<String, Long> effortFacet = facets.get(IssuesWsParameters.FACET_MODE_EFFORT);

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/add_comment-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/assign-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/delete_comment-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/do_transition-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/edit_comment-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_severity-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_tags-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 1
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/set_type-example.json View File

@@ -33,7 +33,6 @@
"assign",
"set_tags",
"set_type",
"assign_to_me",
"set_severity"
],
"comments": [

+ 0
- 88
server/sonar-server/src/test/java/org/sonar/server/issue/ActionFinderTest.java View File

@@ -1,88 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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.issue;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.organization.OrganizationTesting;
import org.sonar.server.tester.UserSessionRule;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.issue.IssueTesting.newDto;
import static org.sonar.db.rule.RuleTesting.newXooX1;

public class ActionFinderTest {

static final String PROJECT_KEY = "PROJECT_KEY";
static final String PROJECT_UUID = "PROJECT_UUID";

static final String ISSUE_KEY = "ISSUE_KEY";

@Rule
public ExpectedException thrown = ExpectedException.none();

@Rule
public UserSessionRule userSession = UserSessionRule.standalone().logIn("arthur");

private ComponentDto project = newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), PROJECT_UUID).setDbKey(PROJECT_KEY);
private IssueDto issue = newDto(newXooX1().setId(10), newFileDto(project, null), project).setKee(ISSUE_KEY);

private ActionFinder underTest = new ActionFinder(userSession);

@Test
public void return_provided_actions_without_set_severity_and_set_tpye_when_not_issue_admin() {
assertThat(underTest.listAvailableActions(issue)).containsOnly("comment", "assign", "set_tags", "assign_to_me");
}

@Test
public void return_provided_actions_with_set_severity_and_set_type_when_issue_admin() {
userSession.addProjectPermission(ISSUE_ADMIN, ComponentTesting.newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), PROJECT_UUID));
assertThat(underTest.listAvailableActions(issue)).containsOnly("comment", "assign", "set_tags", "set_type", "assign_to_me", "set_severity");
}

@Test
public void return_no_actions_when_not_logged() {
userSession.anonymous();
assertThat(underTest.listAvailableActions(issue)).isEmpty();
}

@Test
public void doest_not_return_assign_to_me_action_when_issue_already_assigned_to_user() {

userSession.logIn("julien");
IssueDto issue = newDto(newXooX1().setId(10), newFileDto(project, null), project).setKee(ISSUE_KEY).setAssignee("julien");
assertThat(underTest.listAvailableActions(issue)).doesNotContain("assign_to_me");
}

@Test
public void return_only_comment_action_when_issue_has_a_resolution() {
IssueDto issue = newDto(newXooX1().setId(10), newFileDto(project, null), project).setKee(ISSUE_KEY).setResolution(RESOLUTION_FIXED);
assertThat(underTest.listAvailableActions(issue)).containsOnly("comment");
}

}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java View File

@@ -30,7 +30,7 @@ public class IssueWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new IssueWsModule().configure(container);
assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 31);
assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 30);
}
}


+ 1
- 3
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java View File

@@ -40,7 +40,6 @@ import org.sonar.db.issue.IssueDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.es.EsTester;
import org.sonar.server.issue.ActionFinder;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.IssueQueryFactory;
import org.sonar.server.issue.TransitionService;
@@ -97,8 +96,7 @@ public class SearchActionComponentsTest {
private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new ActionFinder(userSession),
new TransitionService(userSession, issueWorkflow));
private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
private Languages languages = new Languages();
private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), new WsResponseCommonFormat(languages), languages, new AvatarResolverImpl());
private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer);

+ 1
- 3
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java View File

@@ -50,7 +50,6 @@ import org.sonar.db.user.UserDto;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.es.StartupIndexer;
import org.sonar.server.issue.ActionFinder;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueQueryFactory;
@@ -99,8 +98,7 @@ public class SearchActionTest {
private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSessionRule);
private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSessionRule, dbClient, new ActionFinder(userSessionRule),
new TransitionService(userSessionRule, issueWorkflow));
private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSessionRule, dbClient, new TransitionService(userSessionRule, issueWorkflow));
private Languages languages = new Languages();
private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), new WsResponseCommonFormat(languages), languages, new AvatarResolverImpl());
private WsActionTester ws = new WsActionTester(new SearchAction(userSessionRule, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat));

+ 1
- 2
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionTest/load_additional_fields.json View File

@@ -7,8 +7,7 @@
"actions": [
"comment",
"assign",
"set_tags",
"assign_to_me"
"set_tags"
],
"transitions": [
"confirm",

+ 0
- 1
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionTest/load_additional_fields_with_issue_admin_permission.json View File

@@ -8,7 +8,6 @@
"comment",
"assign",
"set_tags",
"assign_to_me",
"set_type",
"set_severity"
],

Loading…
Cancel
Save