You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IssueAssignTest.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2017 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package it.organization;
  21. import com.sonar.orchestrator.Orchestrator;
  22. import it.Category6Suite;
  23. import java.util.List;
  24. import java.util.stream.Collectors;
  25. import org.junit.After;
  26. import org.junit.Before;
  27. import org.junit.BeforeClass;
  28. import org.junit.ClassRule;
  29. import org.junit.Rule;
  30. import org.junit.Test;
  31. import org.junit.rules.ExpectedException;
  32. import org.sonarqube.ws.Issues;
  33. import org.sonarqube.ws.Issues.Issue;
  34. import org.sonarqube.ws.client.HttpException;
  35. import org.sonarqube.ws.client.WsClient;
  36. import org.sonarqube.ws.client.issue.AssignRequest;
  37. import org.sonarqube.ws.client.issue.BulkChangeRequest;
  38. import org.sonarqube.ws.client.issue.SearchWsRequest;
  39. import org.sonarqube.ws.client.organization.CreateWsRequest;
  40. import org.sonarqube.ws.client.project.CreateRequest;
  41. import org.sonarqube.ws.client.qualityprofile.AddProjectRequest;
  42. import pageobjects.Navigation;
  43. import pageobjects.issues.IssuesPage;
  44. import util.issue.IssueRule;
  45. import util.user.UserRule;
  46. import static it.Category6Suite.enableOrganizationsSupport;
  47. import static java.lang.String.format;
  48. import static java.util.Collections.singletonList;
  49. import static org.assertj.core.api.Assertions.assertThat;
  50. import static util.ItUtils.deleteOrganizationsIfExists;
  51. import static util.ItUtils.newAdminWsClient;
  52. import static util.ItUtils.newOrganizationKey;
  53. import static util.ItUtils.restoreProfile;
  54. import static util.ItUtils.runProjectAnalysis;
  55. import static util.ItUtils.setServerProperty;
  56. public class IssueAssignTest {
  57. private final static String ORGANIZATION_KEY = newOrganizationKey();
  58. private final static String OTHER_ORGANIZATION_KEY = newOrganizationKey();
  59. private final static String SAMPLE_PROJECT_KEY = "sample";
  60. private static final String ASSIGNEE_LOGIN = "bob";
  61. private static final String OTHER_LOGIN = "neo";
  62. @Rule
  63. public ExpectedException expectedException = ExpectedException.none();
  64. @Rule
  65. public Navigation nav = Navigation.get(orchestrator);
  66. @ClassRule
  67. public static Orchestrator orchestrator = Category6Suite.ORCHESTRATOR;
  68. @ClassRule
  69. public static UserRule userRule = UserRule.from(orchestrator);
  70. @ClassRule
  71. public static IssueRule issueRule = IssueRule.from(orchestrator);
  72. private WsClient adminClient = newAdminWsClient(orchestrator);
  73. @BeforeClass
  74. public static void enableOrganizations() throws Exception {
  75. enableOrganizationsSupport();
  76. }
  77. @Before
  78. public void setUp() throws Exception {
  79. userRule.deactivateUsers(ASSIGNEE_LOGIN, OTHER_LOGIN);
  80. createOrganization(ORGANIZATION_KEY);
  81. restoreProfile(orchestrator, getClass().getResource("/organization/IssueAssignTest/one-issue-per-file-profile.xml"), ORGANIZATION_KEY);
  82. }
  83. @After
  84. public void tearDown() throws Exception {
  85. userRule.deactivateUsers(ASSIGNEE_LOGIN, OTHER_LOGIN);
  86. deleteOrganizationsIfExists(orchestrator, ORGANIZATION_KEY, OTHER_ORGANIZATION_KEY);
  87. }
  88. @Test
  89. public void auto_assign_issues_to_user_if_default_assignee_is_member_of_project_organization() throws Exception {
  90. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  91. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  92. provisionProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  93. setServerProperty(orchestrator, "sample", "sonar.issues.defaultAssigneeLogin", ASSIGNEE_LOGIN);
  94. analyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  95. assertThat(issueRule.getRandomIssue().getAssignee()).isEqualTo(ASSIGNEE_LOGIN);
  96. }
  97. @Test
  98. public void does_not_auto_assign_issues_to_user_if_default_assignee_is_not_member_of_project_organization() throws Exception {
  99. createOrganization(OTHER_ORGANIZATION_KEY);
  100. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  101. adminClient.organizations().addMember(OTHER_ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  102. provisionProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  103. setServerProperty(orchestrator, "sample", "sonar.issues.defaultAssigneeLogin", ASSIGNEE_LOGIN);
  104. analyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  105. assertThat(issueRule.getRandomIssue().hasAssignee()).isFalse();
  106. }
  107. @Test
  108. public void assign_issue_to_user_being_member_of_same_organization_as_project_issue_organization() throws Exception {
  109. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  110. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  111. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  112. Issue issue = issueRule.getRandomIssue();
  113. adminClient.issues().assign(new AssignRequest(issue.getKey(), ASSIGNEE_LOGIN));
  114. assertThat(issueRule.getByKey(issue.getKey()).getAssignee()).isEqualTo(ASSIGNEE_LOGIN);
  115. }
  116. @Test
  117. public void fail_to_assign_issue_to_user_not_being_member_of_same_organization_as_project_issue_organization() throws Exception {
  118. createOrganization(OTHER_ORGANIZATION_KEY);
  119. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  120. adminClient.organizations().addMember(OTHER_ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  121. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  122. Issue issue = issueRule.getRandomIssue();
  123. expectedException.expect(HttpException.class);
  124. expectedException.expectMessage(format("User 'bob' is not member of organization '%s'", ORGANIZATION_KEY));
  125. adminClient.issues().assign(new AssignRequest(issue.getKey(), ASSIGNEE_LOGIN));
  126. }
  127. @Test
  128. public void bulk_assign_issues_to_user_being_only_member_of_same_organization_as_project_issue_organization() throws Exception {
  129. createOrganization(OTHER_ORGANIZATION_KEY);
  130. restoreProfile(orchestrator, getClass().getResource("/organization/IssueAssignTest/one-issue-per-file-profile.xml"), OTHER_ORGANIZATION_KEY);
  131. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  132. // User is only member of "organization-key", not of "other-organization-key"
  133. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  134. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  135. provisionAndAnalyseProject("sample2", OTHER_ORGANIZATION_KEY);
  136. List<String> issues = issueRule.search(new org.sonarqube.ws.client.issue.SearchWsRequest()).getIssuesList().stream().map(Issue::getKey).collect(Collectors.toList());
  137. Issues.BulkChangeWsResponse response = adminClient.issues().bulkChange(BulkChangeRequest.builder().setIssues(issues).setAssign(ASSIGNEE_LOGIN).build());
  138. assertThat(response.getIgnored()).isGreaterThan(0);
  139. assertThat(issueRule.search(new SearchWsRequest().setProjectKeys(singletonList("sample"))).getIssuesList()).extracting(Issue::getAssignee).containsOnly(ASSIGNEE_LOGIN);
  140. assertThat(issueRule.search(new SearchWsRequest().setProjectKeys(singletonList("sample2"))).getIssuesList()).extracting(Issue::hasAssignee).containsOnly(false);
  141. }
  142. @Test
  143. public void single_assign_search_show_only_members_in_global_issues() {
  144. createOrganization(OTHER_ORGANIZATION_KEY);
  145. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  146. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  147. userRule.createUser(OTHER_LOGIN, "pwd");
  148. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  149. IssuesPage page = nav.logIn().asAdmin().openIssues();
  150. page.getFirstIssue()
  151. .shouldAllowAssign()
  152. .assigneeSearchResultCount(OTHER_LOGIN, 0)
  153. .assigneeSearchResultCount(ASSIGNEE_LOGIN, 1);
  154. }
  155. @Test
  156. public void bulk_assign_search_only_members_of_organization_in_project_issues() {
  157. createOrganization(OTHER_ORGANIZATION_KEY);
  158. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  159. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  160. userRule.createUser(OTHER_LOGIN, "pwd");
  161. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  162. IssuesPage page = nav.logIn().asAdmin().openComponentIssues(SAMPLE_PROJECT_KEY);
  163. page
  164. .bulkChangeOpen()
  165. .bulkChangeAssigneeSearchCount(ASSIGNEE_LOGIN, 1)
  166. .bulkChangeAssigneeSearchCount(OTHER_LOGIN, 0);
  167. }
  168. @Test
  169. public void bulk_assign_search_all_users_in_global_issues() {
  170. createOrganization(OTHER_ORGANIZATION_KEY);
  171. userRule.createUser(ASSIGNEE_LOGIN, ASSIGNEE_LOGIN);
  172. adminClient.organizations().addMember(ORGANIZATION_KEY, ASSIGNEE_LOGIN);
  173. userRule.createUser(OTHER_LOGIN, "pwd");
  174. provisionAndAnalyseProject(SAMPLE_PROJECT_KEY, ORGANIZATION_KEY);
  175. IssuesPage page = nav.logIn().asAdmin().openIssues();
  176. page
  177. .bulkChangeOpen()
  178. .bulkChangeAssigneeSearchCount(ASSIGNEE_LOGIN, 1)
  179. .bulkChangeAssigneeSearchCount(OTHER_LOGIN, 1);
  180. }
  181. private void createOrganization(String organizationKey) {
  182. adminClient.organizations().create(new CreateWsRequest.Builder().setKey(organizationKey).setName(organizationKey).build()).getOrganization();
  183. }
  184. private void provisionAndAnalyseProject(String projectKey, String organization) {
  185. provisionProject(projectKey, organization);
  186. analyseProject(projectKey, organization);
  187. }
  188. private void provisionProject(String projectKey, String organization) {
  189. adminClient.projects().create(
  190. CreateRequest.builder()
  191. .setKey(projectKey)
  192. .setName(projectKey)
  193. .setOrganization(organization)
  194. .build());
  195. }
  196. private void analyseProject(String projectKey, String organization) {
  197. addQualityProfileToProject(organization, projectKey);
  198. runProjectAnalysis(orchestrator, "issue/xoo-with-scm",
  199. "sonar.projectKey", projectKey,
  200. "sonar.organization", organization,
  201. "sonar.login", "admin",
  202. "sonar.password", "admin",
  203. "sonar.scm.disabled", "false",
  204. "sonar.scm.provider", "xoo");
  205. }
  206. private void addQualityProfileToProject(String organization, String projectKey) {
  207. adminClient.qualityProfiles().addProject(
  208. AddProjectRequest.builder()
  209. .setProjectKey(projectKey)
  210. .setOrganization(organization)
  211. .setLanguage("xoo")
  212. .setProfileName("one-issue-per-file-profile")
  213. .build());
  214. }
  215. }