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.

CreateActionIT.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 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.projectlink.ws;
  21. import org.apache.commons.lang.StringUtils;
  22. import org.junit.Rule;
  23. import org.junit.Test;
  24. import org.sonar.api.server.ws.WebService;
  25. import org.sonar.api.utils.System2;
  26. import org.sonar.api.web.UserRole;
  27. import org.sonar.core.util.UuidFactoryFast;
  28. import org.sonar.db.DbClient;
  29. import org.sonar.db.DbSession;
  30. import org.sonar.db.DbTester;
  31. import org.sonar.db.component.BranchDto;
  32. import org.sonar.db.component.ComponentDto;
  33. import org.sonar.db.component.ComponentTesting;
  34. import org.sonar.db.component.PortfolioData;
  35. import org.sonar.db.component.ProjectData;
  36. import org.sonar.db.component.ProjectLinkDto;
  37. import org.sonar.db.project.ProjectDto;
  38. import org.sonar.server.component.TestComponentFinder;
  39. import org.sonar.server.exceptions.ForbiddenException;
  40. import org.sonar.server.exceptions.NotFoundException;
  41. import org.sonar.server.tester.UserSessionRule;
  42. import org.sonar.server.ws.WsActionTester;
  43. import org.sonarqube.ws.ProjectLinks;
  44. import static java.lang.String.format;
  45. import static org.assertj.core.api.Assertions.assertThat;
  46. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  47. import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_NAME;
  48. import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_ID;
  49. import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
  50. import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_URL;
  51. import static org.sonar.test.JsonAssert.assertJson;
  52. public class CreateActionIT {
  53. @Rule
  54. public UserSessionRule userSession = UserSessionRule.standalone();
  55. @Rule
  56. public DbTester db = DbTester.create(System2.INSTANCE);
  57. private final DbClient dbClient = db.getDbClient();
  58. private final DbSession dbSession = db.getSession();
  59. private final WsActionTester ws = new WsActionTester(new CreateAction(dbClient, userSession, TestComponentFinder.from(db), UuidFactoryFast.getInstance()));
  60. @Test
  61. public void example_with_key() {
  62. ProjectDto project = db.components().insertPrivateProject().getProjectDto();
  63. logInAsProjectAdministrator(project);
  64. String result = ws.newRequest()
  65. .setMethod("POST")
  66. .setParam(PARAM_PROJECT_KEY, project.getKey())
  67. .setParam(PARAM_NAME, "Custom")
  68. .setParam(PARAM_URL, "http://example.org")
  69. .execute().getInput();
  70. assertJson(result).ignoreFields("id").isSimilarTo(getClass().getResource("create-example.json"));
  71. }
  72. @Test
  73. public void example_with_id() {
  74. ProjectDto project = db.components().insertPrivateProject().getProjectDto();
  75. logInAsProjectAdministrator(project);
  76. String result = ws.newRequest()
  77. .setMethod("POST")
  78. .setParam(PARAM_PROJECT_ID, project.getUuid())
  79. .setParam(PARAM_NAME, "Custom")
  80. .setParam(PARAM_URL, "http://example.org")
  81. .execute().getInput();
  82. assertJson(result).ignoreFields("id").isSimilarTo(getClass().getResource("create-example.json"));
  83. }
  84. @Test
  85. public void require_project_admin() {
  86. ProjectDto project = db.components().insertPrivateProject().getProjectDto();
  87. logInAsProjectAdministrator(project);
  88. createAndTest(project);
  89. }
  90. @Test
  91. public void with_long_name() {
  92. ProjectDto project = db.components().insertPrivateProject().getProjectDto();
  93. logInAsProjectAdministrator(project);
  94. String longName = StringUtils.leftPad("", 60, "a");
  95. String expectedType = StringUtils.leftPad("", 20, "a");
  96. createAndTest(project, longName, "http://example.org", expectedType);
  97. }
  98. @Test
  99. public void fail_if_no_name() {
  100. assertThatThrownBy(() -> ws.newRequest()
  101. .setParam(PARAM_PROJECT_KEY, "unknown")
  102. .setParam(PARAM_URL, "http://example.org")
  103. .execute())
  104. .isInstanceOf(IllegalArgumentException.class);
  105. }
  106. @Test
  107. public void fail_if_long_name() {
  108. assertThatThrownBy(() -> ws.newRequest()
  109. .setParam(PARAM_PROJECT_KEY, "unknown")
  110. .setParam(PARAM_NAME, StringUtils.leftPad("", 129, "*"))
  111. .setParam(PARAM_URL, "http://example.org")
  112. .execute())
  113. .isInstanceOf(IllegalArgumentException.class);
  114. }
  115. @Test
  116. public void fail_if_no_url() {
  117. assertThatThrownBy(() -> ws.newRequest()
  118. .setParam(PARAM_PROJECT_KEY, "unknown")
  119. .setParam(PARAM_NAME, "Custom")
  120. .execute())
  121. .isInstanceOf(IllegalArgumentException.class);
  122. }
  123. @Test
  124. public void fail_if_long_url() {
  125. assertThatThrownBy(() -> ws.newRequest()
  126. .setParam(PARAM_PROJECT_KEY, "unknown")
  127. .setParam(PARAM_NAME, "random")
  128. .setParam(PARAM_URL, StringUtils.leftPad("", 2049, "*"))
  129. .execute())
  130. .isInstanceOf(IllegalArgumentException.class);
  131. }
  132. @Test
  133. public void fail_when_no_project() {
  134. assertThatThrownBy(() -> ws.newRequest()
  135. .setParam(PARAM_PROJECT_KEY, "unknown")
  136. .setParam(PARAM_NAME, "Custom")
  137. .setParam(PARAM_URL, "http://example.org")
  138. .execute())
  139. .isInstanceOf(NotFoundException.class);
  140. }
  141. @Test
  142. public void fail_if_anonymous() {
  143. userSession.anonymous();
  144. ProjectData projectData = db.components().insertPublicProject();
  145. ComponentDto project = projectData.getMainBranchComponent();
  146. userSession.registerProjects(projectData.getProjectDto());
  147. assertThatThrownBy(() -> ws.newRequest()
  148. .setParam(PARAM_PROJECT_KEY, project.getKey())
  149. .setParam(PARAM_NAME, "Custom")
  150. .setParam(PARAM_URL, "http://example.org")
  151. .execute())
  152. .isInstanceOf(ForbiddenException.class);
  153. }
  154. @Test
  155. public void fail_if_not_project_admin() {
  156. userSession.logIn();
  157. ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
  158. assertThatThrownBy(() -> ws.newRequest()
  159. .setParam(PARAM_PROJECT_KEY, project.getKey())
  160. .setParam(PARAM_NAME, "Custom")
  161. .setParam(PARAM_URL, "http://example.org")
  162. .execute())
  163. .isInstanceOf(ForbiddenException.class);
  164. }
  165. @Test
  166. public void fail_if_directory() {
  167. ProjectData project = db.components().insertPrivateProject();
  168. ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project.getMainBranchComponent(), "A/B"));
  169. failIfNotAProjectWithKey(project.getProjectDto(), directory);
  170. failIfNotAProjectWithUuid(project.getProjectDto(), directory);
  171. }
  172. @Test
  173. public void fail_if_file() {
  174. ProjectData project = db.components().insertPrivateProject();
  175. ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project.getMainBranchComponent()));
  176. failIfNotAProjectWithKey(project.getProjectDto(), file);
  177. failIfNotAProjectWithUuid(project.getProjectDto(), file);
  178. }
  179. @Test
  180. public void fail_if_view() {
  181. PortfolioData view = db.components().insertPrivatePortfolioData();
  182. userSession.logIn().addProjectPermission(UserRole.ADMIN, view.getRootComponent());
  183. assertThatThrownBy(() -> ws.newRequest()
  184. .setParam(PARAM_NAME, "Custom")
  185. .setParam(PARAM_URL, "http://example.org")
  186. .setParam(PARAM_PROJECT_KEY, view.getPortfolioDto().getKey())
  187. .execute())
  188. .isInstanceOf(NotFoundException.class)
  189. .hasMessageContaining("Project '" + view.getPortfolioDto().getKey() + "' not found");
  190. assertThatThrownBy(() -> ws.newRequest()
  191. .setParam(PARAM_NAME, "Custom")
  192. .setParam(PARAM_URL, "http://example.org")
  193. .setParam(PARAM_PROJECT_ID, view.getPortfolioDto().getUuid())
  194. .execute())
  195. .isInstanceOf(NotFoundException.class)
  196. .hasMessageContaining("Project '" + view.getPortfolioDto().getUuid() + "' not found");
  197. }
  198. @Test
  199. public void fail_when_using_branch_db_uuid() {
  200. ProjectData project = db.components().insertPrivateProject();
  201. userSession.logIn().addProjectPermission(UserRole.USER, project.getProjectDto());
  202. BranchDto branch = db.components().insertProjectBranch(project.getProjectDto());
  203. assertThatThrownBy(() -> ws.newRequest()
  204. .setParam(PARAM_PROJECT_ID, branch.getUuid())
  205. .setParam(PARAM_NAME, "Custom")
  206. .setParam(PARAM_URL, "http://example.org")
  207. .execute())
  208. .isInstanceOf(NotFoundException.class)
  209. .hasMessageContaining(format("Project '%s' not found", branch.getUuid()));
  210. }
  211. @Test
  212. public void define_create_action() {
  213. WebService.Action action = ws.getDef();
  214. assertThat(action).isNotNull();
  215. assertThat(action.isPost()).isTrue();
  216. assertThat(action.handler()).isNotNull();
  217. assertThat(action.responseExampleAsString()).isNotEmpty();
  218. assertThat(action.params()).hasSize(4);
  219. }
  220. private void failIfNotAProjectWithKey(ProjectDto project, ComponentDto component) {
  221. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  222. assertThatThrownBy(() -> ws.newRequest()
  223. .setParam(PARAM_NAME, "Custom")
  224. .setParam(PARAM_URL, "http://example.org")
  225. .setParam(PARAM_PROJECT_KEY, component.getKey())
  226. .execute())
  227. .isInstanceOf(NotFoundException.class)
  228. .hasMessageContaining("Project '" + component.getKey() + "' not found");
  229. }
  230. private void failIfNotAProjectWithUuid(ProjectDto project, ComponentDto component) {
  231. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  232. assertThatThrownBy(() -> ws.newRequest()
  233. .setParam(PARAM_NAME, "Custom")
  234. .setParam(PARAM_URL, "http://example.org")
  235. .setParam(PARAM_PROJECT_ID, component.uuid())
  236. .execute())
  237. .isInstanceOf(NotFoundException.class)
  238. .hasMessageContaining("Project '" + component.uuid() + "' not found");
  239. }
  240. private void createAndTest(ProjectDto project, String name, String url, String type) {
  241. ProjectLinks.CreateWsResponse response = ws.newRequest()
  242. .setMethod("POST")
  243. .setParam(PARAM_PROJECT_KEY, project.getKey())
  244. .setParam(PARAM_NAME, name)
  245. .setParam(PARAM_URL, url)
  246. .executeProtobuf(ProjectLinks.CreateWsResponse.class);
  247. String newId = response.getLink().getId();
  248. ProjectLinkDto link = dbClient.projectLinkDao().selectByUuid(dbSession, newId);
  249. assertThat(link.getName()).isEqualTo(name);
  250. assertThat(link.getHref()).isEqualTo(url);
  251. assertThat(link.getType()).isEqualTo(type);
  252. }
  253. private void createAndTest(ProjectDto project) {
  254. createAndTest(project, "Custom", "http://example.org", "custom");
  255. }
  256. private void logInAsProjectAdministrator(ProjectDto project) {
  257. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  258. }
  259. }