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.

GlobalAction.java 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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 com.google.common.collect.ImmutableSet;
  22. import java.util.HashMap;
  23. import java.util.Locale;
  24. import java.util.Map;
  25. import java.util.Set;
  26. import org.sonar.api.Startable;
  27. import org.sonar.api.config.Configuration;
  28. import org.sonar.api.platform.Server;
  29. import org.sonar.api.resources.ResourceType;
  30. import org.sonar.api.resources.ResourceTypes;
  31. import org.sonar.api.server.ws.Request;
  32. import org.sonar.api.server.ws.Response;
  33. import org.sonar.api.server.ws.WebService.NewController;
  34. import org.sonar.api.utils.text.JsonWriter;
  35. import org.sonar.api.web.page.Page;
  36. import org.sonar.core.platform.PlatformEditionProvider;
  37. import org.sonar.db.DbClient;
  38. import org.sonar.db.DbSession;
  39. import org.sonar.db.dialect.H2;
  40. import org.sonar.server.almsettings.MultipleAlmFeatureProvider;
  41. import org.sonar.server.branch.BranchFeatureProxy;
  42. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  43. import org.sonar.server.organization.DefaultOrganizationProvider;
  44. import org.sonar.server.organization.OrganizationFlags;
  45. import org.sonar.server.platform.WebServer;
  46. import org.sonar.server.ui.PageRepository;
  47. import org.sonar.server.ui.VersionFormatter;
  48. import org.sonar.server.ui.WebAnalyticsLoader;
  49. import org.sonar.server.user.UserSession;
  50. import static org.sonar.api.CoreProperties.DEVELOPER_AGGREGATED_INFO_DISABLED;
  51. import static org.sonar.api.CoreProperties.RATING_GRID;
  52. import static org.sonar.core.config.WebConstants.SONAR_LF_ENABLE_GRAVATAR;
  53. import static org.sonar.core.config.WebConstants.SONAR_LF_GRAVATAR_SERVER_URL;
  54. import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_URL;
  55. import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_WIDTH_PX;
  56. import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED;
  57. import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_HOMEPAGE_URL;
  58. import static org.sonar.process.ProcessProperties.Property.SONAR_ANALYTICS_GTM_TRACKING_ID;
  59. import static org.sonar.process.ProcessProperties.Property.SONAR_PRISMIC_ACCESS_TOKEN;
  60. import static org.sonar.process.ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE;
  61. public class GlobalAction implements NavigationWsAction, Startable {
  62. private static final Set<String> DYNAMIC_SETTING_KEYS = ImmutableSet.of(
  63. SONAR_LF_LOGO_URL,
  64. SONAR_LF_LOGO_WIDTH_PX,
  65. SONAR_LF_ENABLE_GRAVATAR,
  66. SONAR_LF_GRAVATAR_SERVER_URL,
  67. RATING_GRID,
  68. DEVELOPER_AGGREGATED_INFO_DISABLED);
  69. private final Map<String, String> systemSettingValuesByKey;
  70. private final PageRepository pageRepository;
  71. private final Configuration config;
  72. private final ResourceTypes resourceTypes;
  73. private final Server server;
  74. private final WebServer webServer;
  75. private final DbClient dbClient;
  76. private final OrganizationFlags organizationFlags;
  77. private final DefaultOrganizationProvider defaultOrganizationProvider;
  78. private final BranchFeatureProxy branchFeature;
  79. private final UserSession userSession;
  80. private final PlatformEditionProvider editionProvider;
  81. private final MultipleAlmFeatureProvider multipleAlmFeatureProvider;
  82. private final WebAnalyticsLoader webAnalyticsLoader;
  83. private final IssueIndexSyncProgressChecker issueIndexSyncChecker;
  84. public GlobalAction(PageRepository pageRepository, Configuration config, ResourceTypes resourceTypes, Server server,
  85. WebServer webServer, DbClient dbClient, OrganizationFlags organizationFlags,
  86. DefaultOrganizationProvider defaultOrganizationProvider, BranchFeatureProxy branchFeature, UserSession userSession, PlatformEditionProvider editionProvider,
  87. MultipleAlmFeatureProvider multipleAlmFeatureProvider, WebAnalyticsLoader webAnalyticsLoader, IssueIndexSyncProgressChecker issueIndexSyncChecker) {
  88. this.pageRepository = pageRepository;
  89. this.config = config;
  90. this.resourceTypes = resourceTypes;
  91. this.server = server;
  92. this.webServer = webServer;
  93. this.dbClient = dbClient;
  94. this.organizationFlags = organizationFlags;
  95. this.defaultOrganizationProvider = defaultOrganizationProvider;
  96. this.branchFeature = branchFeature;
  97. this.userSession = userSession;
  98. this.editionProvider = editionProvider;
  99. this.multipleAlmFeatureProvider = multipleAlmFeatureProvider;
  100. this.webAnalyticsLoader = webAnalyticsLoader;
  101. this.systemSettingValuesByKey = new HashMap<>();
  102. this.issueIndexSyncChecker = issueIndexSyncChecker;
  103. }
  104. @Override
  105. public void start() {
  106. this.systemSettingValuesByKey.put(SONAR_UPDATECENTER_ACTIVATE.getKey(), config.get(SONAR_UPDATECENTER_ACTIVATE.getKey()).orElse(null));
  107. boolean isOnSonarCloud = config.getBoolean(SONARCLOUD_ENABLED.getKey()).orElse(false);
  108. if (isOnSonarCloud) {
  109. this.systemSettingValuesByKey.put(SONAR_PRISMIC_ACCESS_TOKEN.getKey(), config.get(SONAR_PRISMIC_ACCESS_TOKEN.getKey()).orElse(null));
  110. this.systemSettingValuesByKey.put(SONAR_ANALYTICS_GTM_TRACKING_ID.getKey(), config.get(SONAR_ANALYTICS_GTM_TRACKING_ID.getKey()).orElse(null));
  111. this.systemSettingValuesByKey.put(SONARCLOUD_HOMEPAGE_URL.getKey(), config.get(SONARCLOUD_HOMEPAGE_URL.getKey()).orElse(null));
  112. }
  113. }
  114. @Override
  115. public void stop() {
  116. // Nothing to do
  117. }
  118. @Override
  119. public void define(NewController context) {
  120. context.createAction("global")
  121. .setDescription("Get information concerning global navigation for the current user.")
  122. .setHandler(this)
  123. .setInternal(true)
  124. .setResponseExample(getClass().getResource("global-example.json"))
  125. .setSince("5.2");
  126. }
  127. @Override
  128. public void handle(Request request, Response response) throws Exception {
  129. try (JsonWriter json = response.newJsonWriter()) {
  130. json.beginObject();
  131. writeActions(json);
  132. writePages(json);
  133. writeSettings(json);
  134. writeDeprecatedLogoProperties(json);
  135. writeQualifiers(json);
  136. writeVersion(json);
  137. writeDatabaseProduction(json);
  138. writeOrganizationSupport(json);
  139. writeBranchSupport(json);
  140. writeMultipleAlmEnabled(json);
  141. editionProvider.get().ifPresent(e -> json.prop("edition", e.name().toLowerCase(Locale.ENGLISH)));
  142. writeNeedIssueSync(json);
  143. json.prop("standalone", webServer.isStandalone());
  144. writeWebAnalytics(json);
  145. json.endObject();
  146. }
  147. }
  148. private void writeActions(JsonWriter json) {
  149. json.prop("canAdmin", userSession.isSystemAdministrator());
  150. }
  151. private void writePages(JsonWriter json) {
  152. json.name("globalPages").beginArray();
  153. for (Page page : pageRepository.getGlobalPages(false)) {
  154. json.beginObject()
  155. .prop("key", page.getKey())
  156. .prop("name", page.getName())
  157. .endObject();
  158. }
  159. json.endArray();
  160. }
  161. private void writeSettings(JsonWriter json) {
  162. json.name("settings").beginObject();
  163. DYNAMIC_SETTING_KEYS.forEach(key -> json.prop(key, config.get(key).orElse(null)));
  164. systemSettingValuesByKey.forEach(json::prop);
  165. json.endObject();
  166. }
  167. private void writeDeprecatedLogoProperties(JsonWriter json) {
  168. json.prop("logoUrl", config.get(SONAR_LF_LOGO_URL).orElse(null));
  169. json.prop("logoWidth", config.get(SONAR_LF_LOGO_WIDTH_PX).orElse(null));
  170. }
  171. private void writeQualifiers(JsonWriter json) {
  172. json.name("qualifiers").beginArray();
  173. for (ResourceType rootType : resourceTypes.getRoots()) {
  174. json.value(rootType.getQualifier());
  175. }
  176. json.endArray();
  177. }
  178. private void writeVersion(JsonWriter json) {
  179. String displayVersion = VersionFormatter.format(server.getVersion());
  180. json.prop("version", displayVersion);
  181. }
  182. private void writeDatabaseProduction(JsonWriter json) {
  183. json.prop("productionDatabase", !dbClient.getDatabase().getDialect().getId().equals(H2.ID));
  184. }
  185. private void writeOrganizationSupport(JsonWriter json) {
  186. try (DbSession dbSession = dbClient.openSession(false)) {
  187. json.prop("organizationsEnabled", organizationFlags.isEnabled(dbSession));
  188. json.prop("defaultOrganization", defaultOrganizationProvider.get().getKey());
  189. }
  190. }
  191. private void writeBranchSupport(JsonWriter json) {
  192. json.prop("branchesEnabled", branchFeature.isEnabled());
  193. }
  194. private void writeMultipleAlmEnabled(JsonWriter json) {
  195. json.prop("multipleAlmEnabled", multipleAlmFeatureProvider.enabled());
  196. }
  197. private void writeNeedIssueSync(JsonWriter json) {
  198. try (DbSession dbSession = dbClient.openSession(false)) {
  199. json.prop("needIssueSync", issueIndexSyncChecker.isIssueSyncInProgress(dbSession));
  200. }
  201. }
  202. private void writeWebAnalytics(JsonWriter json) {
  203. webAnalyticsLoader.getUrlPathToJs().ifPresent(p -> json.prop("webAnalyticsJsPath", p));
  204. }
  205. }