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.

SearchActionTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 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 org.sonar.server.user.ws;
  21. import java.util.stream.IntStream;
  22. import org.junit.Rule;
  23. import org.junit.Test;
  24. import org.sonar.api.server.ws.WebService;
  25. import org.sonar.api.server.ws.WebService.Param;
  26. import org.sonar.api.utils.System2;
  27. import org.sonar.db.DbTester;
  28. import org.sonar.db.user.GroupDto;
  29. import org.sonar.db.user.UserDto;
  30. import org.sonar.server.es.EsTester;
  31. import org.sonar.server.issue.ws.AvatarResolverImpl;
  32. import org.sonar.server.tester.UserSessionRule;
  33. import org.sonar.server.user.index.UserIndex;
  34. import org.sonar.server.user.index.UserIndexer;
  35. import org.sonar.server.ws.WsActionTester;
  36. import org.sonarqube.ws.Common.Paging;
  37. import org.sonarqube.ws.Users.SearchWsResponse;
  38. import org.sonarqube.ws.Users.SearchWsResponse.User;
  39. import static java.util.Arrays.asList;
  40. import static java.util.Collections.emptyList;
  41. import static java.util.Collections.singletonList;
  42. import static org.assertj.core.api.Assertions.assertThat;
  43. import static org.assertj.core.api.Assertions.tuple;
  44. import static org.sonar.api.utils.DateUtils.formatDateTime;
  45. import static org.sonar.test.JsonAssert.assertJson;
  46. public class SearchActionTest {
  47. @Rule
  48. public EsTester es = EsTester.create();
  49. @Rule
  50. public UserSessionRule userSession = UserSessionRule.standalone();
  51. @Rule
  52. public DbTester db = DbTester.create();
  53. private UserIndex index = new UserIndex(es.client(), System2.INSTANCE);
  54. private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
  55. private WsActionTester ws = new WsActionTester(new SearchAction(userSession, index, db.getDbClient(), new AvatarResolverImpl()));
  56. @Test
  57. public void search_for_all_users() {
  58. UserDto user1 = db.users().insertUser();
  59. UserDto user2 = db.users().insertUser();
  60. userIndexer.indexOnStartup(null);
  61. userSession.logIn();
  62. SearchWsResponse response = ws.newRequest()
  63. .executeProtobuf(SearchWsResponse.class);
  64. assertThat(response.getUsersList())
  65. .extracting(User::getLogin, User::getName)
  66. .containsExactlyInAnyOrder(
  67. tuple(user1.getLogin(), user1.getName()),
  68. tuple(user2.getLogin(), user2.getName()));
  69. }
  70. @Test
  71. public void search_with_query() {
  72. userSession.logIn();
  73. UserDto user = db.users().insertUser(u -> u
  74. .setLogin("user-%_%-login")
  75. .setName("user-name")
  76. .setEmail("user@mail.com")
  77. .setLocal(true)
  78. .setScmAccounts(singletonList("user1")));
  79. userIndexer.indexOnStartup(null);
  80. assertThat(ws.newRequest()
  81. .setParam("q", "user-%_%-")
  82. .executeProtobuf(SearchWsResponse.class).getUsersList())
  83. .extracting(User::getLogin)
  84. .containsExactlyInAnyOrder(user.getLogin());
  85. assertThat(ws.newRequest()
  86. .setParam("q", "user@MAIL.com")
  87. .executeProtobuf(SearchWsResponse.class).getUsersList())
  88. .extracting(User::getLogin)
  89. .containsExactlyInAnyOrder(user.getLogin());
  90. assertThat(ws.newRequest()
  91. .setParam("q", "user-name")
  92. .executeProtobuf(SearchWsResponse.class).getUsersList())
  93. .extracting(User::getLogin)
  94. .containsExactlyInAnyOrder(user.getLogin());
  95. }
  96. @Test
  97. public void return_avatar() {
  98. UserDto user = db.users().insertUser(u -> u.setEmail("john@doe.com"));
  99. userIndexer.indexOnStartup(null);
  100. userSession.logIn();
  101. SearchWsResponse response = ws.newRequest()
  102. .executeProtobuf(SearchWsResponse.class);
  103. assertThat(response.getUsersList())
  104. .extracting(User::getLogin, User::getAvatar)
  105. .containsExactlyInAnyOrder(tuple(user.getLogin(), "6a6c19fea4a3676970167ce51f39e6ee"));
  106. }
  107. @Test
  108. public void return_scm_accounts() {
  109. UserDto user = db.users().insertUser(u -> u.setScmAccounts(asList("john1", "john2")));
  110. userIndexer.indexOnStartup(null);
  111. userSession.logIn();
  112. SearchWsResponse response = ws.newRequest()
  113. .executeProtobuf(SearchWsResponse.class);
  114. assertThat(response.getUsersList())
  115. .extracting(User::getLogin, u -> u.getScmAccounts().getScmAccountsList())
  116. .containsExactlyInAnyOrder(tuple(user.getLogin(), asList("john1", "john2")));
  117. }
  118. @Test
  119. public void return_tokens_count_when_system_administer() {
  120. UserDto user = db.users().insertUser();
  121. db.users().insertToken(user);
  122. db.users().insertToken(user);
  123. userIndexer.indexOnStartup(null);
  124. userSession.logIn().setSystemAdministrator();
  125. assertThat(ws.newRequest()
  126. .executeProtobuf(SearchWsResponse.class).getUsersList())
  127. .extracting(User::getLogin, User::getTokensCount)
  128. .containsExactlyInAnyOrder(tuple(user.getLogin(), 2));
  129. userSession.logIn();
  130. assertThat(ws.newRequest()
  131. .executeProtobuf(SearchWsResponse.class).getUsersList())
  132. .extracting(User::getLogin, User::hasTokensCount)
  133. .containsExactlyInAnyOrder(tuple(user.getLogin(), false));
  134. }
  135. @Test
  136. public void return_email_only_when_system_administer() {
  137. UserDto user = db.users().insertUser();
  138. userIndexer.indexOnStartup(null);
  139. userSession.logIn().setSystemAdministrator();
  140. assertThat(ws.newRequest()
  141. .executeProtobuf(SearchWsResponse.class).getUsersList())
  142. .extracting(User::getLogin, User::getEmail)
  143. .containsExactlyInAnyOrder(tuple(user.getLogin(), user.getEmail()));
  144. userSession.logIn();
  145. assertThat(ws.newRequest()
  146. .executeProtobuf(SearchWsResponse.class).getUsersList())
  147. .extracting(User::getLogin, User::hasEmail)
  148. .containsExactlyInAnyOrder(tuple(user.getLogin(), false));
  149. }
  150. @Test
  151. public void return_user_not_having_email() {
  152. UserDto user = db.users().insertUser(u -> u.setEmail(null));
  153. userIndexer.indexOnStartup(null);
  154. userSession.logIn().setSystemAdministrator();
  155. SearchWsResponse response = ws.newRequest()
  156. .executeProtobuf(SearchWsResponse.class);
  157. assertThat(response.getUsersList())
  158. .extracting(User::getLogin, User::hasEmail)
  159. .containsExactlyInAnyOrder(tuple(user.getLogin(), false));
  160. }
  161. @Test
  162. public void return_groups_only_when_system_administer() {
  163. UserDto user = db.users().insertUser();
  164. GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
  165. GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
  166. GroupDto group3 = db.users().insertGroup(db.getDefaultOrganization(), "group3");
  167. db.users().insertMember(group1, user);
  168. db.users().insertMember(group2, user);
  169. userIndexer.indexOnStartup(null);
  170. userSession.logIn().setSystemAdministrator();
  171. assertThat(ws.newRequest()
  172. .executeProtobuf(SearchWsResponse.class).getUsersList())
  173. .extracting(User::getLogin, u -> u.getGroups().getGroupsList())
  174. .containsExactlyInAnyOrder(tuple(user.getLogin(), asList(group1.getName(), group2.getName())));
  175. userSession.logIn();
  176. assertThat(ws.newRequest()
  177. .executeProtobuf(SearchWsResponse.class).getUsersList())
  178. .extracting(User::getLogin, User::hasGroups)
  179. .containsExactlyInAnyOrder(tuple(user.getLogin(), false));
  180. }
  181. @Test
  182. public void return_external_information() {
  183. UserDto user = db.users().insertUser();
  184. userIndexer.indexOnStartup(null);
  185. userSession.logIn().setSystemAdministrator();
  186. SearchWsResponse response = ws.newRequest()
  187. .executeProtobuf(SearchWsResponse.class);
  188. assertThat(response.getUsersList())
  189. .extracting(User::getLogin, User::getExternalIdentity, User::getExternalProvider)
  190. .containsExactlyInAnyOrder(tuple(user.getLogin(), user.getExternalLogin(), user.getExternalIdentityProvider()));
  191. }
  192. @Test
  193. public void return_external_identity_only_when_system_administer() {
  194. UserDto user = db.users().insertUser();
  195. userIndexer.indexOnStartup(null);
  196. userSession.logIn().setSystemAdministrator();
  197. assertThat(ws.newRequest()
  198. .executeProtobuf(SearchWsResponse.class).getUsersList())
  199. .extracting(User::getLogin, User::getExternalIdentity)
  200. .containsExactlyInAnyOrder(tuple(user.getLogin(), user.getExternalLogin()));
  201. userSession.logIn();
  202. assertThat(ws.newRequest()
  203. .executeProtobuf(SearchWsResponse.class).getUsersList())
  204. .extracting(User::getLogin, User::hasExternalIdentity)
  205. .containsExactlyInAnyOrder(tuple(user.getLogin(), false));
  206. }
  207. @Test
  208. public void only_return_login_and_name_when_not_logged() {
  209. UserDto user = db.users().insertUser();
  210. db.users().insertToken(user);
  211. GroupDto group = db.users().insertGroup(db.getDefaultOrganization());
  212. db.users().insertMember(group, user);
  213. userIndexer.indexOnStartup(null);
  214. userSession.anonymous();
  215. SearchWsResponse response = ws.newRequest()
  216. .executeProtobuf(SearchWsResponse.class);
  217. assertThat(response.getUsersList())
  218. .extracting(User::getLogin, User::getName, User::hasTokensCount, User::hasScmAccounts, User::hasAvatar, User::hasGroups)
  219. .containsExactlyInAnyOrder(tuple(user.getLogin(), user.getName(), false, false, false, false));
  220. }
  221. @Test
  222. public void return_last_connection_date_when_system_administer() {
  223. UserDto userWithLastConnectionDate = db.users().insertUser();
  224. db.users().updateLastConnectionDate(userWithLastConnectionDate, 10_000_000_000L);
  225. UserDto userWithoutLastConnectionDate = db.users().insertUser();
  226. userIndexer.indexOnStartup(null);
  227. userSession.logIn().setSystemAdministrator();
  228. SearchWsResponse response = ws.newRequest()
  229. .executeProtobuf(SearchWsResponse.class);
  230. assertThat(response.getUsersList())
  231. .extracting(User::getLogin, User::hasLastConnectionDate, User::getLastConnectionDate)
  232. .containsExactlyInAnyOrder(
  233. tuple(userWithLastConnectionDate.getLogin(), true, formatDateTime(10_000_000_000L)),
  234. tuple(userWithoutLastConnectionDate.getLogin(), false, ""));
  235. }
  236. @Test
  237. public void return_all_fields_for_logged_user() {
  238. UserDto user = db.users().insertUser();
  239. db.users().updateLastConnectionDate(user, 10_000_000_000L);
  240. db.users().insertToken(user);
  241. db.users().insertToken(user);
  242. GroupDto group = db.users().insertGroup();
  243. db.users().insertMember(group, user);
  244. UserDto otherUser = db.users().insertUser();
  245. userIndexer.indexOnStartup(null);
  246. userSession.logIn(user);
  247. assertThat(ws.newRequest().setParam("q", user.getLogin())
  248. .executeProtobuf(SearchWsResponse.class).getUsersList())
  249. .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalIdentity, User::getExternalProvider,
  250. User::hasScmAccounts, User::hasAvatar, User::hasGroups, User::getTokensCount, User::hasLastConnectionDate)
  251. .containsExactlyInAnyOrder(
  252. tuple(user.getLogin(), user.getName(), user.getEmail(), user.getExternalLogin(), user.getExternalIdentityProvider(), true, true, true, 2, true));
  253. userSession.logIn(otherUser);
  254. assertThat(ws.newRequest().setParam("q", user.getLogin())
  255. .executeProtobuf(SearchWsResponse.class).getUsersList())
  256. .extracting(User::getLogin, User::getName, User::hasEmail, User::hasExternalIdentity, User::hasExternalProvider,
  257. User::hasScmAccounts, User::hasAvatar, User::hasGroups, User::hasTokensCount, User::hasLastConnectionDate)
  258. .containsExactlyInAnyOrder(
  259. tuple(user.getLogin(), user.getName(), false, false, true, true, true, false, false, false));
  260. }
  261. @Test
  262. public void search_with_paging() {
  263. userSession.logIn();
  264. IntStream.rangeClosed(0, 9).forEach(i -> db.users().insertUser(u -> u.setLogin("user-" + i).setName("User " + i)));
  265. userIndexer.indexOnStartup(null);
  266. SearchWsResponse response = ws.newRequest()
  267. .setParam(Param.PAGE_SIZE, "5")
  268. .executeProtobuf(SearchWsResponse.class);
  269. assertThat(response.getUsersList())
  270. .extracting(User::getLogin)
  271. .containsExactly("user-0", "user-1", "user-2", "user-3", "user-4");
  272. assertThat(response.getPaging())
  273. .extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal)
  274. .containsExactly(1, 5, 10);
  275. response = ws.newRequest()
  276. .setParam(Param.PAGE_SIZE, "5")
  277. .setParam(Param.PAGE, "2")
  278. .executeProtobuf(SearchWsResponse.class);
  279. assertThat(response.getUsersList())
  280. .extracting(User::getLogin)
  281. .containsExactly("user-5", "user-6", "user-7", "user-8", "user-9");
  282. assertThat(response.getPaging())
  283. .extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal)
  284. .containsExactly(2, 5, 10);
  285. }
  286. @Test
  287. public void return_empty_result_when_no_user() {
  288. userSession.logIn();
  289. SearchWsResponse response = ws.newRequest()
  290. .executeProtobuf(SearchWsResponse.class);
  291. assertThat(response.getUsersList()).isEmpty();
  292. assertThat(response.getPaging().getTotal()).isZero();
  293. }
  294. @Test
  295. public void test_json_example() {
  296. UserDto fmallet = db.users().insertUser(u -> u.setLogin("fmallet").setName("Freddy Mallet").setEmail("f@m.com")
  297. .setLocal(true)
  298. .setScmAccounts(emptyList())
  299. .setExternalLogin("fmallet")
  300. .setExternalIdentityProvider("sonarqube"));
  301. UserDto simon = db.users().insertUser(u -> u.setLogin("sbrandhof").setName("Simon").setEmail("s.brandhof@company.tld")
  302. .setLocal(false)
  303. .setExternalLogin("sbrandhof@ldap.com")
  304. .setExternalIdentityProvider("LDAP")
  305. .setScmAccounts(asList("simon.brandhof", "s.brandhof@company.tld")));
  306. GroupDto sonarUsers = db.users().insertGroup(db.getDefaultOrganization(), "sonar-users");
  307. GroupDto sonarAdministrators = db.users().insertGroup(db.getDefaultOrganization(), "sonar-administrators");
  308. db.users().insertMember(sonarUsers, simon);
  309. db.users().insertMember(sonarUsers, fmallet);
  310. db.users().insertMember(sonarAdministrators, fmallet);
  311. db.users().insertToken(simon);
  312. db.users().insertToken(simon);
  313. db.users().insertToken(simon);
  314. db.users().insertToken(fmallet);
  315. userIndexer.indexOnStartup(null);
  316. userSession.logIn().setSystemAdministrator();
  317. String response = ws.newRequest().execute().getInput();
  318. assertJson(response).isSimilarTo(getClass().getResource("search-example.json"));
  319. }
  320. @Test
  321. public void test_definition() {
  322. WebService.Action action = ws.getDef();
  323. assertThat(action).isNotNull();
  324. assertThat(action.isPost()).isFalse();
  325. assertThat(action.responseExampleAsString()).isNotEmpty();
  326. assertThat(action.params()).hasSize(3);
  327. }
  328. }