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.

ComponentActionTest.java 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  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.Arrays;
  23. import java.util.Date;
  24. import java.util.List;
  25. import org.junit.Rule;
  26. import org.junit.Test;
  27. import org.junit.rules.ExpectedException;
  28. import org.sonar.api.resources.ResourceType;
  29. import org.sonar.api.resources.ResourceTypes;
  30. import org.sonar.api.server.ws.Change;
  31. import org.sonar.api.server.ws.WebService;
  32. import org.sonar.api.utils.System2;
  33. import org.sonar.api.web.UserRole;
  34. import org.sonar.api.web.page.Page;
  35. import org.sonar.api.web.page.Page.Qualifier;
  36. import org.sonar.api.web.page.PageDefinition;
  37. import org.sonar.core.component.DefaultResourceTypes;
  38. import org.sonar.core.extension.CoreExtensionRepository;
  39. import org.sonar.core.platform.PluginInfo;
  40. import org.sonar.core.platform.PluginRepository;
  41. import org.sonar.db.DbClient;
  42. import org.sonar.db.DbTester;
  43. import org.sonar.db.component.BranchDto;
  44. import org.sonar.db.component.BranchType;
  45. import org.sonar.db.component.ComponentDbTester;
  46. import org.sonar.db.component.ComponentDto;
  47. import org.sonar.db.component.SnapshotDto;
  48. import org.sonar.db.metric.MetricDto;
  49. import org.sonar.db.organization.OrganizationDto;
  50. import org.sonar.db.permission.OrganizationPermission;
  51. import org.sonar.db.project.ProjectDto;
  52. import org.sonar.db.property.PropertyDbTester;
  53. import org.sonar.db.property.PropertyDto;
  54. import org.sonar.db.qualitygate.QualityGateDto;
  55. import org.sonar.db.qualityprofile.QProfileDto;
  56. import org.sonar.db.user.UserDto;
  57. import org.sonar.server.component.ComponentFinder;
  58. import org.sonar.server.exceptions.BadRequestException;
  59. import org.sonar.server.exceptions.ForbiddenException;
  60. import org.sonar.server.exceptions.NotFoundException;
  61. import org.sonar.server.organization.BillingValidations;
  62. import org.sonar.server.organization.BillingValidationsProxy;
  63. import org.sonar.server.qualitygate.QualityGateFinder;
  64. import org.sonar.server.qualityprofile.QPMeasureData;
  65. import org.sonar.server.qualityprofile.QualityProfile;
  66. import org.sonar.server.tester.UserSessionRule;
  67. import org.sonar.server.ui.PageRepository;
  68. import org.sonar.server.ws.WsActionTester;
  69. import org.sonar.updatecenter.common.Version;
  70. import static org.assertj.core.api.Assertions.assertThat;
  71. import static org.assertj.core.api.Assertions.tuple;
  72. import static org.mockito.ArgumentMatchers.any;
  73. import static org.mockito.Mockito.mock;
  74. import static org.mockito.Mockito.when;
  75. import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
  76. import static org.sonar.api.utils.DateUtils.parseDateTime;
  77. import static org.sonar.api.web.page.Page.Scope.COMPONENT;
  78. import static org.sonar.db.component.ComponentTesting.newDirectory;
  79. import static org.sonar.db.component.ComponentTesting.newFileDto;
  80. import static org.sonar.db.component.ComponentTesting.newModuleDto;
  81. import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
  82. import static org.sonar.db.component.SnapshotTesting.newAnalysis;
  83. import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
  84. import static org.sonar.db.metric.MetricTesting.newMetricDto;
  85. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
  86. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
  87. import static org.sonar.server.ui.ws.ComponentAction.PARAM_COMPONENT;
  88. import static org.sonar.test.JsonAssert.assertJson;
  89. public class ComponentActionTest {
  90. @Rule
  91. public ExpectedException expectedException = ExpectedException.none();
  92. @Rule
  93. public DbTester db = DbTester.create(System2.INSTANCE);
  94. @Rule
  95. public UserSessionRule userSession = UserSessionRule.standalone();
  96. private DbClient dbClient = db.getDbClient();
  97. private ComponentDbTester componentDbTester = db.components();
  98. private PropertyDbTester propertyDbTester = new PropertyDbTester(db);
  99. private ResourceTypes resourceTypes = mock(ResourceTypes.class);
  100. private BillingValidationsProxy billingValidations = mock(BillingValidationsProxy.class);
  101. private WsActionTester ws;
  102. @Test
  103. public void return_info_if_user_has_browse_permission_on_project() {
  104. ComponentDto project = insertOrganizationAndProject();
  105. userSession.logIn().addProjectPermission(UserRole.USER, project);
  106. init();
  107. verifySuccess(project.getKey());
  108. }
  109. @Test
  110. public void return_info_if_user_has_administration_permission_on_project() {
  111. ComponentDto project = insertOrganizationAndProject();
  112. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  113. init();
  114. verifySuccess(project.getDbKey());
  115. }
  116. @Test
  117. public void return_info_if_user_is_system_administrator() {
  118. ComponentDto project = insertOrganizationAndProject();
  119. userSession.logIn().setSystemAdministrator();
  120. init();
  121. verifySuccess(project.getDbKey());
  122. }
  123. @Test
  124. public void return_component_info_when_anonymous_no_snapshot() {
  125. ComponentDto project = insertOrganizationAndProject();
  126. userSession.addProjectPermission(UserRole.USER, project);
  127. init();
  128. executeAndVerify(project.getDbKey(), "return_component_info_when_anonymous_no_snapshot.json");
  129. }
  130. @Test
  131. public void return_component_info_with_favourite() {
  132. ComponentDto project = insertOrganizationAndProject();
  133. UserDto user = db.users().insertUser("obiwan");
  134. propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setComponentUuid(project.uuid()).setUserUuid(user.getUuid()));
  135. userSession.logIn(user).addProjectPermission(UserRole.USER, project);
  136. init();
  137. executeAndVerify(project.getDbKey(), "return_component_info_with_favourite.json");
  138. }
  139. @Test
  140. public void return_favourite_for_branch() {
  141. ComponentDto project = insertOrganizationAndProject();
  142. ComponentDto branch = componentDbTester.insertProjectBranch(project, b -> b.setKey("feature1").setUuid("xyz"));
  143. UserDto user = db.users().insertUser("obiwan");
  144. propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setComponentUuid(project.uuid()).setUserUuid(user.getUuid()));
  145. userSession.logIn(user).addProjectPermission(UserRole.USER, project);
  146. init();
  147. String json = ws.newRequest()
  148. .setParam("componentKey", project.getKey())
  149. .setParam("branch", branch.getBranch())
  150. .execute()
  151. .getInput();
  152. assertJson(json).isSimilarTo("{\n" +
  153. " \"organization\": \"my-org\",\n" +
  154. " \"key\": \"polop\",\n" +
  155. " \"isFavorite\": true,\n" +
  156. " \"id\": \"xyz\",\n" +
  157. " \"branch\": \"feature1\"," +
  158. " \"name\": \"Polop\",\n" +
  159. " \"description\": \"test project\"\n" +
  160. "}\n");
  161. }
  162. @Test
  163. public void return_component_info_when_snapshot() {
  164. ComponentDto project = insertOrganizationAndProject();
  165. db.components().insertSnapshot(project, snapshot -> snapshot
  166. .setCreatedAt(parseDateTime("2015-04-22T11:44:00+0200").getTime())
  167. .setProjectVersion("3.14"));
  168. userSession.addProjectPermission(UserRole.USER, project);
  169. init();
  170. executeAndVerify(project.getDbKey(), "return_component_info_when_snapshot.json");
  171. }
  172. @Test
  173. public void return_component_info_when_file_on_master() {
  174. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org2"));
  175. db.qualityGates().createDefaultQualityGate(organization);
  176. ComponentDto main = componentDbTester.insertPrivateProject(organization, p -> p.setName("Sample").setDbKey("sample"));
  177. userSession.addProjectPermission(UserRole.USER, main);
  178. init();
  179. ComponentDto dirDto = componentDbTester.insertComponent(newDirectory(main, "src"));
  180. ComponentDto fileDto = componentDbTester.insertComponent(newFileDto(main, dirDto)
  181. .setUuid("abcd")
  182. .setName("Main.xoo")
  183. .setDbKey("sample:src/Main.xoo"));
  184. executeAndVerify(fileDto.getDbKey(), "return_component_info_when_file_on_master.json");
  185. }
  186. @Test
  187. public void return_component_info_when_file_on_branch() {
  188. OrganizationDto organization = db.organizations().insertForKey("my-org2");
  189. db.qualityGates().createDefaultQualityGate(organization);
  190. ComponentDto project = componentDbTester.insertPrivateProject(organization, p -> p.setName("Sample").setDbKey("sample"));
  191. ComponentDto branch = componentDbTester.insertProjectBranch(project, b -> b.setKey("feature1"));
  192. userSession.addProjectPermission(UserRole.USER, project);
  193. init();
  194. ComponentDto dirDto = componentDbTester.insertComponent(newDirectory(branch, "src"));
  195. ComponentDto fileDto = componentDbTester.insertComponent(newFileDto(branch, dirDto)
  196. .setUuid("abcd")
  197. .setName("Main.xoo"));
  198. String json = ws.newRequest()
  199. .setParam("componentKey", fileDto.getKey())
  200. .setParam("branch", branch.getBranch())
  201. .execute()
  202. .getInput();
  203. assertJson(json).isSimilarTo("{\n" +
  204. " \"key\": \"" + fileDto.getKey() + "\",\n" +
  205. " \"branch\": \"feature1\",\n" +
  206. " \"name\": \"Main.xoo\",\n" +
  207. " \"breadcrumbs\": [\n" +
  208. " {\n" +
  209. " \"key\": \"sample\",\n" +
  210. " \"name\": \"Sample\",\n" +
  211. " \"qualifier\": \"TRK\"\n" +
  212. " },\n" +
  213. " {\n" +
  214. " \"key\": \"sample:src\",\n" +
  215. " \"name\": \"src\",\n" +
  216. " \"qualifier\": \"DIR\"\n" +
  217. " },\n" +
  218. " {\n" +
  219. " \"key\": \"" + fileDto.getKey() + "\",\n" +
  220. " \"name\": \"Main.xoo\",\n" +
  221. " \"qualifier\": \"FIL\"\n" +
  222. " }\n" +
  223. " ]\n" +
  224. "}\n");
  225. }
  226. @Test
  227. public void return_quality_profiles_and_supports_deleted_ones() {
  228. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  229. ComponentDto project = insertProject(organization);
  230. QProfileDto qp1 = db.qualityProfiles().insert(organization, t -> t.setKee("qp1").setName("Sonar Way Java").setLanguage("java"));
  231. QProfileDto qp2 = db.qualityProfiles().insert(organization, t -> t.setKee("qp2").setName("Sonar Way Xoo").setLanguage("xoo"));
  232. addQualityProfiles(project,
  233. new QualityProfile(qp1.getKee(), qp1.getName(), qp1.getLanguage(), new Date()),
  234. new QualityProfile(qp2.getKee(), qp2.getName(), qp2.getLanguage(), new Date()));
  235. userSession.addProjectPermission(UserRole.USER, project);
  236. init();
  237. executeAndVerify(project.getDbKey(), "return_quality_profiles.json");
  238. db.getDbClient().qualityProfileDao().deleteOrgQProfilesByUuids(db.getSession(), ImmutableSet.of(qp1.getKee(), qp2.getKee()));
  239. db.commit();
  240. executeAndVerify(project.getDbKey(), "return_deleted_quality_profiles.json");
  241. }
  242. @Test
  243. public void return_empty_quality_profiles_when_no_measure() {
  244. ComponentDto project = insertOrganizationAndProject();
  245. userSession.addProjectPermission(UserRole.USER, project);
  246. init();
  247. executeAndVerify(project.getDbKey(), "return_empty_quality_profiles_when_no_measure.json");
  248. }
  249. @Test
  250. public void return_quality_gate_defined_on_project() {
  251. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  252. db.qualityGates().createDefaultQualityGate(organization);
  253. ProjectDto project = db.components().insertPrivateProjectDto(organization);
  254. QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate(organization, qg -> qg.setName("Sonar way"));
  255. db.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
  256. userSession.addProjectPermission(UserRole.USER, project);
  257. init();
  258. executeAndVerify(project.getKey(), "return_quality_gate.json");
  259. }
  260. @Test
  261. public void quality_gate_for_a_branch() {
  262. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  263. db.qualityGates().createDefaultQualityGate(organization);
  264. ProjectDto project = db.components().insertPrivateProjectDto(organization);
  265. BranchDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
  266. QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate(organization, qg -> qg.setName("Sonar way"));
  267. db.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
  268. userSession.addProjectPermission(UserRole.USER, project);
  269. init();
  270. String json = ws.newRequest()
  271. .setParam("componentKey", project.getKey())
  272. .setParam("branch", branch.getKey())
  273. .execute()
  274. .getInput();
  275. verify(json, "return_quality_gate.json");
  276. }
  277. @Test
  278. public void return_default_quality_gate() {
  279. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  280. ComponentDto project = db.components().insertPrivateProject(organization);
  281. db.qualityGates().createDefaultQualityGate(organization, qg -> qg.setName("Sonar way"));
  282. userSession.addProjectPermission(UserRole.USER, project);
  283. init();
  284. executeAndVerify(project.getDbKey(), "return_default_quality_gate.json");
  285. }
  286. @Test
  287. public void return_extensions() {
  288. ComponentDto project = insertOrganizationAndProject();
  289. userSession.anonymous().addProjectPermission(UserRole.USER, project);
  290. init(createPages());
  291. executeAndVerify(project.getDbKey(), "return_extensions.json");
  292. }
  293. @Test
  294. public void return_extensions_for_application() {
  295. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  296. db.qualityGates().createDefaultQualityGate(organization);
  297. ProjectDto project = db.components().insertPrivateProjectDto(organization);
  298. Page page = Page.builder("my_plugin/app_page")
  299. .setName("App Page")
  300. .setScope(COMPONENT)
  301. .setComponentQualifiers(Qualifier.VIEW, Qualifier.APP)
  302. .build();
  303. ComponentDto application = componentDbTester.insertPublicApplication(organization);
  304. QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate(organization, qg -> qg.setName("Sonar way"));
  305. db.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
  306. userSession.registerComponents(application);
  307. init(page);
  308. String result = ws.newRequest()
  309. .setParam(PARAM_COMPONENT, application.getDbKey())
  310. .execute().getInput();
  311. assertThat(result).contains("my_plugin/app_page");
  312. }
  313. @Test
  314. public void return_extensions_for_admin() {
  315. ComponentDto project = insertOrganizationAndProject();
  316. userSession.anonymous()
  317. .addProjectPermission(UserRole.USER, project)
  318. .addProjectPermission(UserRole.ADMIN, project);
  319. init(createPages());
  320. executeAndVerify(project.getDbKey(), "return_extensions_for_admin.json");
  321. }
  322. @Test
  323. public void return_configuration_for_admin() {
  324. ComponentDto project = insertOrganizationAndProject();
  325. UserDto user = db.users().insertUser();
  326. userSession.logIn(user)
  327. .addProjectPermission(UserRole.USER, project)
  328. .addProjectPermission(UserRole.ADMIN, project);
  329. Page page1 = Page.builder("my_plugin/first_page")
  330. .setName("First Page")
  331. .setAdmin(true)
  332. .setScope(COMPONENT)
  333. .setComponentQualifiers(Qualifier.PROJECT)
  334. .build();
  335. Page page2 = Page.builder("my_plugin/second_page")
  336. .setName("Second Page")
  337. .setAdmin(true)
  338. .setScope(COMPONENT)
  339. .setComponentQualifiers(Qualifier.PROJECT)
  340. .build();
  341. init(page1, page2);
  342. executeAndVerify(project.getDbKey(), "return_configuration_for_admin.json");
  343. }
  344. @Test
  345. public void return_configuration_with_all_properties() {
  346. ComponentDto project = insertOrganizationAndProject();
  347. userSession.anonymous()
  348. .addProjectPermission(UserRole.USER, project)
  349. .addProjectPermission(UserRole.ADMIN, project);
  350. ResourceType projectResourceType = ResourceType.builder(project.qualifier())
  351. .setProperty("comparable", true)
  352. .setProperty("configurable", true)
  353. .setProperty("hasRolePolicy", true)
  354. .setProperty("modifiable_history", true)
  355. .setProperty("updatable_key", true)
  356. .setProperty("deletable", true)
  357. .build();
  358. when(resourceTypes.get(project.qualifier()))
  359. .thenReturn(projectResourceType);
  360. init();
  361. executeAndVerify(project.getDbKey(), "return_configuration_with_all_properties.json");
  362. }
  363. @Test
  364. public void return_configuration_for_quality_profile_admin() {
  365. ComponentDto project = insertOrganizationAndProject();
  366. userSession.logIn()
  367. .addProjectPermission(UserRole.USER, project)
  368. .addPermission(ADMINISTER_QUALITY_PROFILES, project.getOrganizationUuid());
  369. init();
  370. executeAndVerify(project.getDbKey(), "return_configuration_for_quality_profile_admin.json");
  371. }
  372. @Test
  373. public void return_configuration_for_quality_gate_admin() {
  374. ComponentDto project = insertOrganizationAndProject();
  375. userSession.logIn()
  376. .addProjectPermission(UserRole.USER, project)
  377. .addPermission(ADMINISTER_QUALITY_GATES, project.getOrganizationUuid());
  378. init();
  379. executeAndVerify(project.getDbKey(), "return_configuration_for_quality_gate_admin.json");
  380. }
  381. @Test
  382. public void return_configuration_for_private_projects() {
  383. ComponentDto project = insertOrganizationAndProject();
  384. UserSessionRule userSessionRule = userSession.logIn();
  385. init();
  386. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  387. assertJson(execute(project.getDbKey())).isSimilarTo("{\n" +
  388. " \"configuration\": {\n" +
  389. " \"showSettings\": false,\n" +
  390. " \"showQualityProfiles\": true,\n" +
  391. " \"showQualityGates\": true,\n" +
  392. " \"showManualMeasures\": true,\n" +
  393. " \"showLinks\": true,\n" +
  394. " \"showPermissions\": false,\n" +
  395. " \"showHistory\": false,\n" +
  396. " \"showUpdateKey\": false,\n" +
  397. " \"showBackgroundTasks\": true,\n" +
  398. " \"canApplyPermissionTemplate\": false,\n" +
  399. " \"canBrowseProject\": false,\n" +
  400. " \"canUpdateProjectVisibilityToPrivate\": false\n" +
  401. " }\n" +
  402. "}");
  403. userSessionRule.addProjectPermission(UserRole.USER, project);
  404. assertJson(execute(project.getDbKey())).isSimilarTo("{\n" +
  405. " \"configuration\": {\n" +
  406. " \"showSettings\": false,\n" +
  407. " \"showQualityProfiles\": true,\n" +
  408. " \"showQualityGates\": true,\n" +
  409. " \"showManualMeasures\": true,\n" +
  410. " \"showLinks\": true,\n" +
  411. " \"showPermissions\": false,\n" +
  412. " \"showHistory\": false,\n" +
  413. " \"showUpdateKey\": false,\n" +
  414. " \"showBackgroundTasks\": true,\n" +
  415. " \"canApplyPermissionTemplate\": false,\n" +
  416. " \"canBrowseProject\": true,\n" +
  417. " \"canUpdateProjectVisibilityToPrivate\": false\n" +
  418. " }\n" +
  419. "}");
  420. }
  421. @Test
  422. public void return_bread_crumbs_on_several_levels() {
  423. ComponentDto project = insertOrganizationAndProject();
  424. ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setDbKey("palap").setName("Palap"));
  425. ComponentDto directory = componentDbTester.insertComponent(newDirectory(module, "src/main/xoo"));
  426. ComponentDto file = componentDbTester.insertComponent(newFileDto(directory, directory, "cdef").setName("Source.xoo")
  427. .setDbKey("palap:src/main/xoo/Source.xoo")
  428. .setPath(directory.path()));
  429. userSession.addProjectPermission(UserRole.USER, project);
  430. init();
  431. executeAndVerify(file.getDbKey(), "return_bread_crumbs_on_several_levels.json");
  432. }
  433. @Test
  434. public void project_administrator_is_allowed_to_get_information() {
  435. ComponentDto project = insertOrganizationAndProject();
  436. userSession.addProjectPermission(UserRole.ADMIN, project);
  437. init(createPages());
  438. execute(project.getDbKey());
  439. }
  440. @Test
  441. public void should_return_private_flag_for_project() {
  442. OrganizationDto org = db.organizations().insert();
  443. db.qualityGates().createDefaultQualityGate(org);
  444. ComponentDto project = db.components().insertPrivateProject(org);
  445. init();
  446. userSession.logIn()
  447. .addProjectPermission(UserRole.ADMIN, project)
  448. .addPermission(OrganizationPermission.ADMINISTER, org);
  449. assertJson(execute(project.getDbKey())).isSimilarTo("{\"visibility\": \"private\"}");
  450. }
  451. @Test
  452. public void should_return_public_flag_for_project() {
  453. OrganizationDto org = db.organizations().insert();
  454. db.qualityGates().createDefaultQualityGate(org);
  455. ComponentDto project = db.components().insertPublicProject(org);
  456. init();
  457. userSession.logIn()
  458. .addProjectPermission(UserRole.ADMIN, project)
  459. .addPermission(OrganizationPermission.ADMINISTER, org);
  460. assertJson(execute(project.getDbKey())).isSimilarTo("{\"visibility\": \"public\"}");
  461. }
  462. @Test
  463. public void canApplyPermissionTemplate_is_true_if_logged_in_as_organization_administrator() {
  464. OrganizationDto org = db.organizations().insert();
  465. db.qualityGates().createDefaultQualityGate(org);
  466. ComponentDto project = db.components().insertPrivateProject(org);
  467. init(createPages());
  468. userSession.logIn()
  469. .addProjectPermission(UserRole.ADMIN, project)
  470. .addPermission(OrganizationPermission.ADMINISTER, org);
  471. assertJson(execute(project.getDbKey())).isSimilarTo("{\"configuration\": {\"canApplyPermissionTemplate\": true}}");
  472. userSession.logIn()
  473. .addProjectPermission(UserRole.ADMIN, project);
  474. assertJson(execute(project.getDbKey())).isSimilarTo("{\"configuration\": {\"canApplyPermissionTemplate\": false}}");
  475. }
  476. @Test
  477. public void canUpdateProjectVisibilityToPrivate_is_true_if_logged_in_as_project_administrator_and_extension_returns_false() {
  478. OrganizationDto org = db.organizations().insert();
  479. db.qualityGates().createDefaultQualityGate(org);
  480. ComponentDto project = db.components().insertPublicProject(org);
  481. init(createPages());
  482. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  483. when(billingValidations.canUpdateProjectVisibilityToPrivate(any(BillingValidations.Organization.class))).thenReturn(false);
  484. assertJson(execute(project.getDbKey())).isSimilarTo("{\"configuration\": {\"canUpdateProjectVisibilityToPrivate\": false}}");
  485. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  486. when(billingValidations.canUpdateProjectVisibilityToPrivate(any(BillingValidations.Organization.class))).thenReturn(true);
  487. assertJson(execute(project.getDbKey())).isSimilarTo("{\"configuration\": {\"canUpdateProjectVisibilityToPrivate\": true}}");
  488. }
  489. @Test
  490. public void fail_on_missing_parameters() {
  491. insertOrganizationAndProject();
  492. init();
  493. expectedException.expect(IllegalArgumentException.class);
  494. ws.newRequest().execute();
  495. }
  496. @Test
  497. public void fail_on_unknown_component_key() {
  498. insertOrganizationAndProject();
  499. init();
  500. expectedException.expect(NotFoundException.class);
  501. execute("unknoen");
  502. }
  503. @Test
  504. public void throw_ForbiddenException_if_required_permission_is_not_granted() {
  505. ComponentDto project = insertOrganizationAndProject();
  506. init();
  507. userSession.logIn();
  508. expectedException.expect(ForbiddenException.class);
  509. execute(project.getDbKey());
  510. }
  511. @Test
  512. public void test_example_response() {
  513. init(createPages());
  514. OrganizationDto organizationDto = db.organizations().insertForKey("my-org-1");
  515. ComponentDto project = newPrivateProjectDto(organizationDto, "ABCD")
  516. .setDbKey("org.codehaus.sonar:sonar")
  517. .setName("Sonarqube")
  518. .setDescription("Open source platform for continuous inspection of code quality");
  519. componentDbTester.insertPrivateProject(project);
  520. SnapshotDto analysis = newAnalysis(project)
  521. .setCreatedAt(parseDateTime("2016-12-06T11:44:00+0200").getTime())
  522. .setProjectVersion("6.3")
  523. .setLast(true);
  524. componentDbTester.insertSnapshot(analysis);
  525. when(resourceTypes.get(project.qualifier())).thenReturn(DefaultResourceTypes.get().getRootType());
  526. UserDto user = db.users().insertUser("obiwan");
  527. propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setComponentUuid(project.uuid()).setUserUuid(user.getUuid()));
  528. addQualityProfiles(project,
  529. createQProfile("qp1", "Sonar Way Java", "java"),
  530. createQProfile("qp2", "Sonar Way Xoo", "xoo"));
  531. QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate(db.getDefaultOrganization(), qg -> qg.setName("Sonar way"));
  532. db.qualityGates().associateProjectToQualityGate(db.components().getProjectDto(project), qualityGateDto);
  533. userSession.logIn(user)
  534. .addProjectPermission(UserRole.USER, project)
  535. .addProjectPermission(UserRole.ADMIN, project);
  536. String result = execute(project.getDbKey());
  537. assertJson(result).ignoreFields("snapshotDate", "key", "qualityGate.key").isSimilarTo(ws.getDef().responseExampleAsString());
  538. }
  539. @Test
  540. public void definition() {
  541. init();
  542. WebService.Action action = ws.getDef();
  543. assertThat(action.since()).isEqualTo("5.2");
  544. assertThat(action.isPost()).isFalse();
  545. assertThat(action.isInternal()).isTrue();
  546. assertThat(action.description()).isNotNull();
  547. assertThat(action.responseExample()).isNotNull();
  548. assertThat(action.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactlyInAnyOrder(
  549. tuple("6.4", "The 'visibility' field is added"),
  550. tuple("7.3", "The 'almRepoUrl' and 'almId' fields are added"),
  551. tuple("7.6", "The use of module keys in parameter 'component' is deprecated"));
  552. WebService.Param componentId = action.param(PARAM_COMPONENT);
  553. assertThat(componentId.isRequired()).isFalse();
  554. assertThat(componentId.description()).isNotNull();
  555. assertThat(componentId.exampleValue()).isNotNull();
  556. assertThat(componentId.deprecatedKey()).isEqualTo("componentKey");
  557. assertThat(componentId.deprecatedKeySince()).isEqualTo("6.4");
  558. }
  559. @Test(expected = BadRequestException.class)
  560. public void fail_on_module_key_as_param() {
  561. ComponentDto project = insertOrganizationAndProject();
  562. ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setDbKey("palap").setName("Palap"));
  563. init();
  564. execute(module.getKey());
  565. }
  566. @Test(expected = BadRequestException.class)
  567. public void fail_on_directory_key_as_param() {
  568. ComponentDto project = insertOrganizationAndProject();
  569. ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setDbKey("palap").setName("Palap"));
  570. ComponentDto directory = componentDbTester.insertComponent(newDirectory(module, "src/main/xoo"));
  571. userSession.addProjectPermission(UserRole.USER, project);
  572. init();
  573. execute(directory.getDbKey());
  574. }
  575. private ComponentDto insertOrganizationAndProject() {
  576. OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org"));
  577. return insertProject(organization);
  578. }
  579. private ComponentDto insertProject(OrganizationDto organization) {
  580. db.qualityGates().createDefaultQualityGate(organization);
  581. return db.components().insertPrivateProject(organization, "abcd", p -> p.setDbKey("polop").setName("Polop").setDescription("test project"));
  582. }
  583. private void init(Page... pages) {
  584. PluginRepository pluginRepository = mock(PluginRepository.class);
  585. when(pluginRepository.hasPlugin(any())).thenReturn(true);
  586. when(pluginRepository.getPluginInfo(any())).thenReturn(new PluginInfo("unused").setVersion(Version.create("1.0")));
  587. CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
  588. when(coreExtensionRepository.isInstalled(any())).thenReturn(false);
  589. PageRepository pageRepository = new PageRepository(pluginRepository, coreExtensionRepository, new PageDefinition[] {context -> {
  590. for (Page page : pages) {
  591. context.addPage(page);
  592. }
  593. }});
  594. pageRepository.start();
  595. ws = new WsActionTester(
  596. new ComponentAction(dbClient, pageRepository, resourceTypes, userSession, new ComponentFinder(dbClient, resourceTypes),
  597. new QualityGateFinder(dbClient), billingValidations));
  598. }
  599. private String execute(String componentKey) {
  600. return ws.newRequest().setParam("componentKey", componentKey).execute().getInput();
  601. }
  602. private void verify(String json, String jsonFile) {
  603. assertJson(json).isSimilarTo(getClass().getResource(ComponentActionTest.class.getSimpleName() + "/" + jsonFile));
  604. }
  605. private void executeAndVerify(String componentKey, String expectedJson) {
  606. verify(execute(componentKey), expectedJson);
  607. }
  608. private void addQualityProfiles(ComponentDto project, QualityProfile... qps) {
  609. MetricDto metric = newMetricDto().setKey(QUALITY_PROFILES_KEY);
  610. dbClient.metricDao().insert(db.getSession(), metric);
  611. dbClient.liveMeasureDao().insert(db.getSession(),
  612. newLiveMeasure(project, metric)
  613. .setData(qualityProfilesToJson(qps)));
  614. db.commit();
  615. }
  616. private Page[] createPages() {
  617. Page page1 = Page.builder("my_plugin/first_page")
  618. .setName("First Page")
  619. .setScope(COMPONENT)
  620. .setComponentQualifiers(Qualifier.PROJECT)
  621. .build();
  622. Page page2 = Page.builder("my_plugin/second_page")
  623. .setName("Second Page")
  624. .setScope(COMPONENT)
  625. .setComponentQualifiers(Qualifier.PROJECT)
  626. .build();
  627. Page adminPage = Page.builder("my_plugin/admin_page")
  628. .setName("Admin Page")
  629. .setScope(COMPONENT)
  630. .setComponentQualifiers(Qualifier.PROJECT)
  631. .setAdmin(true)
  632. .build();
  633. return new Page[] {page1, page2, adminPage};
  634. }
  635. private void verifySuccess(String componentKey) {
  636. String json = execute(componentKey);
  637. assertJson(json).isSimilarTo("{\"key\":\"" + componentKey + "\"}");
  638. }
  639. private static QualityProfile createQProfile(String qpKey, String qpName, String languageKey) {
  640. return new QualityProfile(qpKey, qpName, languageKey, new Date());
  641. }
  642. private static String qualityProfilesToJson(QualityProfile... qps) {
  643. List<QualityProfile> qualityProfiles = Arrays.asList(qps);
  644. return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));
  645. }
  646. }