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.

GlobalActionTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2022 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.ui.ws;
  21. import java.util.Optional;
  22. import org.junit.Rule;
  23. import org.junit.Test;
  24. import org.sonar.api.config.internal.MapSettings;
  25. import org.sonar.api.platform.Server;
  26. import org.sonar.api.resources.ResourceType;
  27. import org.sonar.api.resources.ResourceTypeTree;
  28. import org.sonar.api.resources.ResourceTypes;
  29. import org.sonar.api.web.page.Page;
  30. import org.sonar.api.web.page.PageDefinition;
  31. import org.sonar.core.extension.CoreExtensionRepository;
  32. import org.sonar.core.platform.EditionProvider;
  33. import org.sonar.core.platform.PlatformEditionProvider;
  34. import org.sonar.core.platform.PluginInfo;
  35. import org.sonar.core.platform.PluginRepository;
  36. import org.sonar.db.DbClient;
  37. import org.sonar.db.dialect.H2;
  38. import org.sonar.db.dialect.PostgreSql;
  39. import org.sonar.server.almsettings.MultipleAlmFeatureProvider;
  40. import org.sonar.server.authentication.DefaultAdminCredentialsVerifier;
  41. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  42. import org.sonar.server.platform.WebServer;
  43. import org.sonar.server.tester.UserSessionRule;
  44. import org.sonar.server.ui.PageRepository;
  45. import org.sonar.server.ui.WebAnalyticsLoader;
  46. import org.sonar.server.ws.WsActionTester;
  47. import org.sonar.updatecenter.common.Version;
  48. import static org.assertj.core.api.Assertions.assertThat;
  49. import static org.mockito.ArgumentMatchers.any;
  50. import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
  51. import static org.mockito.Mockito.mock;
  52. import static org.mockito.Mockito.when;
  53. import static org.sonar.test.JsonAssert.assertJson;
  54. public class GlobalActionTest {
  55. @Rule
  56. public UserSessionRule userSession = UserSessionRule.standalone();
  57. private final MapSettings settings = new MapSettings();
  58. private final Server server = mock(Server.class);
  59. private final WebServer webServer = mock(WebServer.class);
  60. private final DbClient dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS);
  61. private final IssueIndexSyncProgressChecker indexSyncProgressChecker = mock(IssueIndexSyncProgressChecker.class);
  62. private final BranchFeatureRule branchFeature = new BranchFeatureRule();
  63. private final PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
  64. private final MultipleAlmFeatureProvider multipleAlmFeatureProvider = mock(MultipleAlmFeatureProvider.class);
  65. private final WebAnalyticsLoader webAnalyticsLoader = mock(WebAnalyticsLoader.class);
  66. private final DefaultAdminCredentialsVerifier defaultAdminCredentialsVerifier = mock(DefaultAdminCredentialsVerifier.class);
  67. private WsActionTester ws;
  68. @Test
  69. public void empty_call() {
  70. init();
  71. assertJson(call()).isSimilarTo("{" +
  72. " \"globalPages\": []," +
  73. " \"settings\": {}," +
  74. " \"qualifiers\": []" +
  75. "}");
  76. }
  77. @Test
  78. public void return_qualifiers() {
  79. init(new Page[] {}, new ResourceTypeTree[] {
  80. ResourceTypeTree.builder()
  81. .addType(ResourceType.builder("POL").build())
  82. .addType(ResourceType.builder("LOP").build())
  83. .addRelations("POL", "LOP")
  84. .build(),
  85. ResourceTypeTree.builder()
  86. .addType(ResourceType.builder("PAL").build())
  87. .addType(ResourceType.builder("LAP").build())
  88. .addRelations("PAL", "LAP")
  89. .build()
  90. });
  91. assertJson(call()).isSimilarTo("{" +
  92. " \"qualifiers\": [\"POL\", \"PAL\"]" +
  93. "}");
  94. }
  95. @Test
  96. public void return_settings() {
  97. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  98. settings.setProperty("sonar.lf.logoWidthPx", 135);
  99. settings.setProperty("sonar.lf.gravatarServerUrl", "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon");
  100. settings.setProperty("sonar.lf.enableGravatar", true);
  101. settings.setProperty("sonar.updatecenter.activate", false);
  102. settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
  103. settings.setProperty("sonar.developerAggregatedInfo.disabled", false);
  104. // This setting should be ignored as it's not needed
  105. settings.setProperty("sonar.defaultGroup", "sonar-users");
  106. init();
  107. assertJson(call()).isSimilarTo("{" +
  108. " \"settings\": {" +
  109. " \"sonar.lf.logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  110. " \"sonar.lf.logoWidthPx\": \"135\"," +
  111. " \"sonar.lf.gravatarServerUrl\": \"https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon\"," +
  112. " \"sonar.lf.enableGravatar\": \"true\"," +
  113. " \"sonar.updatecenter.activate\": \"false\"," +
  114. " \"sonar.technicalDebt.ratingGrid\": \"0.05,0.1,0.2,0.5\"" +
  115. " \"sonar.developerAggregatedInfo.disabled\": \"false\"" +
  116. " }" +
  117. "}");
  118. }
  119. @Test
  120. public void return_developer_info_disabled_setting() {
  121. init();
  122. settings.setProperty("sonar.developerAggregatedInfo.disabled", true);
  123. assertJson(call()).isSimilarTo("{" +
  124. " \"settings\": {" +
  125. " \"sonar.developerAggregatedInfo.disabled\": \"true\"" +
  126. " }" +
  127. "}");
  128. }
  129. @Test
  130. public void return_deprecated_logo_settings() {
  131. init();
  132. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  133. settings.setProperty("sonar.lf.logoWidthPx", 135);
  134. assertJson(call()).isSimilarTo("{" +
  135. " \"settings\": {" +
  136. " \"sonar.lf.logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  137. " \"sonar.lf.logoWidthPx\": \"135\"" +
  138. " }," +
  139. " \"logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  140. " \"logoWidth\": \"135\"" +
  141. "}");
  142. }
  143. @Test
  144. public void the_returned_global_pages_do_not_include_administration_pages() {
  145. init(createPages(), new ResourceTypeTree[] {});
  146. assertJson(call()).isSimilarTo("{" +
  147. " \"globalPages\": [" +
  148. " {" +
  149. " \"key\": \"another_plugin/page\"," +
  150. " \"name\": \"My Another Page\"" +
  151. " }," +
  152. " {" +
  153. " \"key\": \"my_plugin/page\"," +
  154. " \"name\": \"My Plugin Page\"" +
  155. " }" +
  156. " ]" +
  157. "}");
  158. }
  159. @Test
  160. public void return_sonarqube_version() {
  161. init();
  162. when(server.getVersion()).thenReturn("6.2");
  163. assertJson(call()).isSimilarTo("{" +
  164. " \"version\": \"6.2\"" +
  165. "}");
  166. }
  167. @Test
  168. public void functional_version_when_4_digits() {
  169. init();
  170. when(server.getVersion()).thenReturn("6.3.1.1234");
  171. String result = call();
  172. assertThat(result).contains("6.3.1 (build 1234)");
  173. }
  174. @Test
  175. public void functional_version_when_third_digit_is_0() {
  176. init();
  177. when(server.getVersion()).thenReturn("6.3.0.1234");
  178. String result = call();
  179. assertThat(result).contains("6.3 (build 1234)");
  180. }
  181. @Test
  182. public void return_if_production_database_or_not() {
  183. init();
  184. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  185. assertJson(call()).isSimilarTo("{" +
  186. " \"productionDatabase\": true" +
  187. "}");
  188. }
  189. @Test
  190. public void branch_support() {
  191. init();
  192. branchFeature.setEnabled(true);
  193. assertJson(call()).isSimilarTo("{\"branchesEnabled\":true}");
  194. branchFeature.setEnabled(false);
  195. assertJson(call()).isSimilarTo("{\"branchesEnabled\":false}");
  196. }
  197. @Test
  198. public void multiple_alm_enabled() {
  199. init();
  200. when(multipleAlmFeatureProvider.enabled()).thenReturn(true);
  201. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":true}");
  202. when(multipleAlmFeatureProvider.enabled()).thenReturn(false);
  203. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":false}");
  204. }
  205. @Test
  206. public void return_need_issue_sync() {
  207. init();
  208. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(true);
  209. assertJson(call()).isSimilarTo("{\"needIssueSync\": true}");
  210. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(false);
  211. assertJson(call()).isSimilarTo("{\"needIssueSync\": false}");
  212. }
  213. @Test
  214. public void instance_uses_default_admin_credentials() {
  215. init();
  216. when(defaultAdminCredentialsVerifier.hasDefaultCredentialUser()).thenReturn(true);
  217. // Even if the default credentials are used, if the current user it not a system admin, the flag is not returned.
  218. assertJson(call()).isNotSimilarTo("{\"instanceUsesDefaultAdminCredentials\":true}");
  219. userSession.logIn().setSystemAdministrator();
  220. assertJson(call()).isSimilarTo("{\"instanceUsesDefaultAdminCredentials\":true}");
  221. when(defaultAdminCredentialsVerifier.hasDefaultCredentialUser()).thenReturn(false);
  222. assertJson(call()).isSimilarTo("{\"instanceUsesDefaultAdminCredentials\":false}");
  223. }
  224. @Test
  225. public void standalone_flag() {
  226. init();
  227. userSession.logIn().setSystemAdministrator();
  228. when(webServer.isStandalone()).thenReturn(true);
  229. assertJson(call()).isSimilarTo("{\"standalone\":true}");
  230. }
  231. @Test
  232. public void not_standalone_flag() {
  233. init();
  234. userSession.logIn().setSystemAdministrator();
  235. when(webServer.isStandalone()).thenReturn(false);
  236. assertJson(call()).isSimilarTo("{\"standalone\":false}");
  237. }
  238. @Test
  239. public void test_example_response() {
  240. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  241. settings.setProperty("sonar.lf.logoWidthPx", 135);
  242. settings.setProperty("sonar.lf.gravatarServerUrl", "http://some-server.tld/logo.png");
  243. settings.setProperty("sonar.lf.enableGravatar", true);
  244. settings.setProperty("sonar.updatecenter.activate", false);
  245. settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
  246. init(createPages(), new ResourceTypeTree[] {
  247. ResourceTypeTree.builder()
  248. .addType(ResourceType.builder("POL").build())
  249. .addType(ResourceType.builder("LOP").build())
  250. .addRelations("POL", "LOP")
  251. .build(),
  252. ResourceTypeTree.builder()
  253. .addType(ResourceType.builder("PAL").build())
  254. .addType(ResourceType.builder("LAP").build())
  255. .addRelations("PAL", "LAP")
  256. .build()
  257. });
  258. when(server.getVersion()).thenReturn("6.2");
  259. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  260. when(webServer.isStandalone()).thenReturn(true);
  261. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.COMMUNITY));
  262. String result = call();
  263. assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
  264. }
  265. @Test
  266. public void edition_is_not_returned_if_not_defined() {
  267. init();
  268. when(editionProvider.get()).thenReturn(Optional.empty());
  269. String json = call();
  270. assertThat(json).doesNotContain("edition");
  271. }
  272. @Test
  273. public void edition_is_returned_if_defined() {
  274. init();
  275. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.DEVELOPER));
  276. String json = call();
  277. assertJson(json).isSimilarTo("{\"edition\":\"developer\"}");
  278. }
  279. @Test
  280. public void web_analytics_js_path_is_not_returned_if_not_defined() {
  281. init();
  282. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.empty());
  283. String json = call();
  284. assertThat(json).doesNotContain("webAnalyticsJsPath");
  285. }
  286. @Test
  287. public void web_analytics_js_path_is_returned_if_defined() {
  288. init();
  289. String path = "static/googleanalytics/analytics.js";
  290. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.of(path));
  291. String json = call();
  292. assertJson(json).isSimilarTo("{\"webAnalyticsJsPath\":\"" + path + "\"}");
  293. }
  294. private void init() {
  295. init(new org.sonar.api.web.page.Page[] {}, new ResourceTypeTree[] {});
  296. }
  297. private void init(org.sonar.api.web.page.Page[] pages, ResourceTypeTree[] resourceTypeTrees) {
  298. when(dbClient.getDatabase().getDialect()).thenReturn(new H2());
  299. when(server.getVersion()).thenReturn("6.42");
  300. PluginRepository pluginRepository = mock(PluginRepository.class);
  301. when(pluginRepository.hasPlugin(any())).thenReturn(true);
  302. when(pluginRepository.getPluginInfo(any())).thenReturn(new PluginInfo("unused").setVersion(Version.create("1.0")));
  303. CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
  304. when(coreExtensionRepository.isInstalled(any())).thenReturn(false);
  305. PageRepository pageRepository = new PageRepository(pluginRepository, coreExtensionRepository, new PageDefinition[] {context -> {
  306. for (Page page : pages) {
  307. context.addPage(page);
  308. }
  309. }});
  310. pageRepository.start();
  311. GlobalAction wsAction = new GlobalAction(pageRepository, settings.asConfig(), new ResourceTypes(resourceTypeTrees), server,
  312. webServer, dbClient, branchFeature, userSession, editionProvider, multipleAlmFeatureProvider, webAnalyticsLoader,
  313. indexSyncProgressChecker, defaultAdminCredentialsVerifier);
  314. ws = new WsActionTester(wsAction);
  315. wsAction.start();
  316. }
  317. private String call() {
  318. return ws.newRequest().execute().getInput();
  319. }
  320. private Page[] createPages() {
  321. Page page = Page.builder("my_plugin/page").setName("My Plugin Page").build();
  322. Page anotherPage = Page.builder("another_plugin/page").setName("My Another Page").build();
  323. Page adminPage = Page.builder("my_plugin/admin_page").setName("Admin Page").setAdmin(true).build();
  324. return new Page[] {page, anotherPage, adminPage};
  325. }
  326. }