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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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_sonarcloud_settings() {
  121. settings.setProperty("sonar.sonarcloud.enabled", true);
  122. settings.setProperty("sonar.prismic.accessToken", "secret");
  123. settings.setProperty("sonar.analytics.gtm.trackingId", "gtm_id");
  124. settings.setProperty("sonar.homepage.url", "https://s3/homepage.json");
  125. init();
  126. assertJson(call()).isSimilarTo("{" +
  127. " \"settings\": {" +
  128. " \"sonar.prismic.accessToken\": \"secret\"," +
  129. " \"sonar.analytics.gtm.trackingId\": \"gtm_id\"," +
  130. " \"sonar.homepage.url\": \"https://s3/homepage.json\"" +
  131. " }" +
  132. "}");
  133. }
  134. @Test
  135. public void return_developer_info_disabled_setting() {
  136. init();
  137. settings.setProperty("sonar.developerAggregatedInfo.disabled", true);
  138. assertJson(call()).isSimilarTo("{" +
  139. " \"settings\": {" +
  140. " \"sonar.developerAggregatedInfo.disabled\": \"true\"" +
  141. " }" +
  142. "}");
  143. }
  144. @Test
  145. public void return_deprecated_logo_settings() {
  146. init();
  147. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  148. settings.setProperty("sonar.lf.logoWidthPx", 135);
  149. assertJson(call()).isSimilarTo("{" +
  150. " \"settings\": {" +
  151. " \"sonar.lf.logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  152. " \"sonar.lf.logoWidthPx\": \"135\"" +
  153. " }," +
  154. " \"logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  155. " \"logoWidth\": \"135\"" +
  156. "}");
  157. }
  158. @Test
  159. public void the_returned_global_pages_do_not_include_administration_pages() {
  160. init(createPages(), new ResourceTypeTree[] {});
  161. assertJson(call()).isSimilarTo("{" +
  162. " \"globalPages\": [" +
  163. " {" +
  164. " \"key\": \"another_plugin/page\"," +
  165. " \"name\": \"My Another Page\"" +
  166. " }," +
  167. " {" +
  168. " \"key\": \"my_plugin/page\"," +
  169. " \"name\": \"My Plugin Page\"" +
  170. " }" +
  171. " ]" +
  172. "}");
  173. }
  174. @Test
  175. public void return_sonarqube_version() {
  176. init();
  177. when(server.getVersion()).thenReturn("6.2");
  178. assertJson(call()).isSimilarTo("{" +
  179. " \"version\": \"6.2\"" +
  180. "}");
  181. }
  182. @Test
  183. public void functional_version_when_4_digits() {
  184. init();
  185. when(server.getVersion()).thenReturn("6.3.1.1234");
  186. String result = call();
  187. assertThat(result).contains("6.3.1 (build 1234)");
  188. }
  189. @Test
  190. public void functional_version_when_third_digit_is_0() {
  191. init();
  192. when(server.getVersion()).thenReturn("6.3.0.1234");
  193. String result = call();
  194. assertThat(result).contains("6.3 (build 1234)");
  195. }
  196. @Test
  197. public void return_if_production_database_or_not() {
  198. init();
  199. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  200. assertJson(call()).isSimilarTo("{" +
  201. " \"productionDatabase\": true" +
  202. "}");
  203. }
  204. @Test
  205. public void branch_support() {
  206. init();
  207. branchFeature.setEnabled(true);
  208. assertJson(call()).isSimilarTo("{\"branchesEnabled\":true}");
  209. branchFeature.setEnabled(false);
  210. assertJson(call()).isSimilarTo("{\"branchesEnabled\":false}");
  211. }
  212. @Test
  213. public void multiple_alm_enabled() {
  214. init();
  215. when(multipleAlmFeatureProvider.enabled()).thenReturn(true);
  216. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":true}");
  217. when(multipleAlmFeatureProvider.enabled()).thenReturn(false);
  218. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":false}");
  219. }
  220. @Test
  221. public void return_need_issue_sync() {
  222. init();
  223. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(true);
  224. assertJson(call()).isSimilarTo("{\"needIssueSync\": true}");
  225. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(false);
  226. assertJson(call()).isSimilarTo("{\"needIssueSync\": false}");
  227. }
  228. @Test
  229. public void can_admin_on_global_level() {
  230. init();
  231. userSession.logIn().setRoot();
  232. assertJson(call()).isSimilarTo("{\"canAdmin\":true}");
  233. }
  234. @Test
  235. public void instance_uses_default_admin_credentials() {
  236. init();
  237. when(defaultAdminCredentialsVerifier.hasDefaultCredentialUser()).thenReturn(true);
  238. // Even if the default credentials are used, if the current user it not a system admin, the flag is not returned.
  239. assertJson(call()).isNotSimilarTo("{\"instanceUsesDefaultAdminCredentials\":true}");
  240. userSession.logIn().setSystemAdministrator();
  241. assertJson(call()).isSimilarTo("{\"instanceUsesDefaultAdminCredentials\":true}");
  242. when(defaultAdminCredentialsVerifier.hasDefaultCredentialUser()).thenReturn(false);
  243. assertJson(call()).isSimilarTo("{\"instanceUsesDefaultAdminCredentials\":false}");
  244. }
  245. @Test
  246. public void standalone_flag() {
  247. init();
  248. userSession.logIn().setRoot();
  249. when(webServer.isStandalone()).thenReturn(true);
  250. assertJson(call()).isSimilarTo("{\"standalone\":true}");
  251. }
  252. @Test
  253. public void not_standalone_flag() {
  254. init();
  255. userSession.logIn().setRoot();
  256. when(webServer.isStandalone()).thenReturn(false);
  257. assertJson(call()).isSimilarTo("{\"standalone\":false}");
  258. }
  259. @Test
  260. public void test_example_response() {
  261. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  262. settings.setProperty("sonar.lf.logoWidthPx", 135);
  263. settings.setProperty("sonar.lf.gravatarServerUrl", "http://some-server.tld/logo.png");
  264. settings.setProperty("sonar.lf.enableGravatar", true);
  265. settings.setProperty("sonar.updatecenter.activate", false);
  266. settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
  267. init(createPages(), new ResourceTypeTree[] {
  268. ResourceTypeTree.builder()
  269. .addType(ResourceType.builder("POL").build())
  270. .addType(ResourceType.builder("LOP").build())
  271. .addRelations("POL", "LOP")
  272. .build(),
  273. ResourceTypeTree.builder()
  274. .addType(ResourceType.builder("PAL").build())
  275. .addType(ResourceType.builder("LAP").build())
  276. .addRelations("PAL", "LAP")
  277. .build()
  278. });
  279. when(server.getVersion()).thenReturn("6.2");
  280. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  281. when(webServer.isStandalone()).thenReturn(true);
  282. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.COMMUNITY));
  283. String result = call();
  284. assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
  285. }
  286. @Test
  287. public void edition_is_not_returned_if_not_defined() {
  288. init();
  289. when(editionProvider.get()).thenReturn(Optional.empty());
  290. String json = call();
  291. assertThat(json).doesNotContain("edition");
  292. }
  293. @Test
  294. public void edition_is_returned_if_defined() {
  295. init();
  296. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.DEVELOPER));
  297. String json = call();
  298. assertJson(json).isSimilarTo("{\"edition\":\"developer\"}");
  299. }
  300. @Test
  301. public void web_analytics_js_path_is_not_returned_if_not_defined() {
  302. init();
  303. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.empty());
  304. String json = call();
  305. assertThat(json).doesNotContain("webAnalyticsJsPath");
  306. }
  307. @Test
  308. public void web_analytics_js_path_is_returned_if_defined() {
  309. init();
  310. String path = "static/googleanalytics/analytics.js";
  311. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.of(path));
  312. String json = call();
  313. assertJson(json).isSimilarTo("{\"webAnalyticsJsPath\":\"" + path + "\"}");
  314. }
  315. private void init() {
  316. init(new org.sonar.api.web.page.Page[] {}, new ResourceTypeTree[] {});
  317. }
  318. private void init(org.sonar.api.web.page.Page[] pages, ResourceTypeTree[] resourceTypeTrees) {
  319. when(dbClient.getDatabase().getDialect()).thenReturn(new H2());
  320. when(server.getVersion()).thenReturn("6.42");
  321. PluginRepository pluginRepository = mock(PluginRepository.class);
  322. when(pluginRepository.hasPlugin(any())).thenReturn(true);
  323. when(pluginRepository.getPluginInfo(any())).thenReturn(new PluginInfo("unused").setVersion(Version.create("1.0")));
  324. CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
  325. when(coreExtensionRepository.isInstalled(any())).thenReturn(false);
  326. PageRepository pageRepository = new PageRepository(pluginRepository, coreExtensionRepository, new PageDefinition[] {context -> {
  327. for (Page page : pages) {
  328. context.addPage(page);
  329. }
  330. }});
  331. pageRepository.start();
  332. GlobalAction wsAction = new GlobalAction(pageRepository, settings.asConfig(), new ResourceTypes(resourceTypeTrees), server,
  333. webServer, dbClient, branchFeature, userSession, editionProvider, multipleAlmFeatureProvider, webAnalyticsLoader,
  334. indexSyncProgressChecker, defaultAdminCredentialsVerifier);
  335. ws = new WsActionTester(wsAction);
  336. wsAction.start();
  337. }
  338. private String call() {
  339. return ws.newRequest().execute().getInput();
  340. }
  341. private Page[] createPages() {
  342. Page page = Page.builder("my_plugin/page").setName("My Plugin Page").build();
  343. Page anotherPage = Page.builder("another_plugin/page").setName("My Another Page").build();
  344. Page adminPage = Page.builder("my_plugin/admin_page").setName("Admin Page").setAdmin(true).build();
  345. return new Page[] {page, anotherPage, adminPage};
  346. }
  347. }