aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-07-26 14:43:29 +0200
committerStas Vilchik <vilchiks@gmail.com>2016-07-28 17:31:14 +0200
commitfa27bf616fad3cb743994ea8407feabd96a22ae9 (patch)
treec270d62ddaf679973004712bd64ff9d1d67fd312 /server
parentc61be4f486e6c9fabc5cc5fd03dba40b79e056f1 (diff)
downloadsonarqube-fa27bf616fad3cb743994ea8407feabd96a22ae9.tar.gz
sonarqube-fa27bf616fad3cb743994ea8407feabd96a22ae9.zip
SONAR-7925 Create WS to list project links
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksModule.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java45
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWsAction.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java139
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/package-info.java23
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json15
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsModuleTest.java35
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java66
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java263
10 files changed, 651 insertions, 0 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
index fd273db83d6..87004e66031 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
@@ -178,6 +178,7 @@ import org.sonar.server.plugins.ws.PluginsWs;
import org.sonar.server.plugins.ws.UninstallAction;
import org.sonar.server.plugins.ws.UpdatesAction;
import org.sonar.server.project.ws.ProjectsWsModule;
+import org.sonar.server.projectlink.ws.ProjectLinksModule;
import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
@@ -622,6 +623,9 @@ public class PlatformLevel4 extends PlatformLevel {
TypeValidationModule.class,
+ // Project Links
+ ProjectLinksModule.class,
+
// System
ProcessSystemInfoClient.class,
ServerLogging.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksModule.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksModule.java
new file mode 100644
index 00000000000..9a034e3729b
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksModule.java
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import org.sonar.core.platform.Module;
+
+public class ProjectLinksModule extends Module {
+
+ @Override
+ protected void configureModule() {
+ add(
+ ProjectLinksWs.class,
+ // actions
+ SearchAction.class);
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java
new file mode 100644
index 00000000000..1ed5d412648
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import org.sonar.api.server.ws.WebService;
+
+public class ProjectLinksWs implements WebService {
+
+ private final ProjectLinksWsAction[] actions;
+
+ public ProjectLinksWs(ProjectLinksWsAction... actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public void define(Context context) {
+ NewController controller = context.createController("api/project_links")
+ .setDescription("Manage projects links.")
+ .setSince("6.1");
+
+ for (ProjectLinksWsAction action : actions) {
+ action.define(controller);
+ }
+
+ controller.done();
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWsAction.java
new file mode 100644
index 00000000000..56d59d9b80c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWsAction.java
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import org.sonar.server.ws.WsAction;
+
+public interface ProjectLinksWsAction extends WsAction {
+
+ // Marker interface
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java
new file mode 100644
index 00000000000..b06605c1235
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java
@@ -0,0 +1,139 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsProjectLinks.Link;
+import org.sonarqube.ws.WsProjectLinks.SearchWsResponse;
+import org.sonarqube.ws.client.projectlinks.SearchWsRequest;
+
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.projectlinks.ProjectLinksWsParameters.ACTION_SEARCH;
+import static org.sonarqube.ws.client.projectlinks.ProjectLinksWsParameters.PARAM_PROJECT_ID;
+import static org.sonarqube.ws.client.projectlinks.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
+
+public class SearchAction implements ProjectLinksWsAction {
+ private final DbClient dbClient;
+ private final UserSession userSession;
+ private final ComponentFinder componentFinder;
+
+ public SearchAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ this.componentFinder = componentFinder;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction(ACTION_SEARCH)
+ .setDescription("List links of a project.<br>" +
+ "The '%s' or '%s' must be provided.<br>" +
+ "Requires one of the following permissions:" +
+ "<ul>" +
+ "<li>'Administer System'</li>" +
+ "<li>'Administer' rights on the specified project</li>" +
+ "<li>'Browse' on the specified project</li>" +
+ "</ul>",
+ PARAM_PROJECT_ID, PARAM_PROJECT_KEY)
+ .setHandler(this)
+ .setResponseExample(getClass().getResource("list-example.json"))
+ .setSince("6.1");
+
+ action.createParam(PARAM_PROJECT_ID)
+ .setDescription("Project Id")
+ .setExampleValue(UUID_EXAMPLE_01);
+
+ action.createParam(PARAM_PROJECT_KEY)
+ .setDescription("Project Key")
+ .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ SearchWsRequest searchWsRequest = toSearchWsRequest(request);
+ SearchWsResponse searchWsResponse = doHandle(searchWsRequest);
+
+ writeProtobuf(searchWsResponse, request, response);
+ }
+
+ private SearchWsResponse doHandle(SearchWsRequest searchWsRequest) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ ComponentDto component = getComponentByUuidOrKey(dbSession, searchWsRequest);
+ List<ComponentLinkDto> links = dbClient.componentLinkDao()
+ .selectByComponentUuid(dbSession, component.uuid());
+ return buildResponse(links);
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private static SearchWsResponse buildResponse(List<ComponentLinkDto> links) {
+ return SearchWsResponse.newBuilder()
+ .addAllLinks(links.stream()
+ .map(SearchAction::buildLink)
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ private static Link buildLink(ComponentLinkDto link) {
+ return Link.newBuilder()
+ .setId(String.valueOf(link.getId()))
+ .setName(link.getName())
+ .setType(link.getType())
+ .setUrl(link.getHref())
+ .build();
+ }
+
+ private ComponentDto getComponentByUuidOrKey(DbSession dbSession, SearchWsRequest request) {
+ ComponentDto component = componentFinder.getByUuidOrKey(
+ dbSession,
+ request.getProjectId(),
+ request.getProjectKey(),
+ ComponentFinder.ParamNames.PROJECT_ID_AND_KEY);
+
+ if (!userSession.hasComponentUuidPermission(UserRole.ADMIN, component.uuid()) &&
+ !userSession.hasComponentUuidPermission(UserRole.USER, component.uuid())) {
+ throw insufficientPrivilegesException();
+ }
+
+ return component;
+ }
+
+ private static SearchWsRequest toSearchWsRequest(Request request) {
+ return new SearchWsRequest()
+ .setProjectId(request.param(PARAM_PROJECT_ID))
+ .setProjectKey(request.param(PARAM_PROJECT_KEY));
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/package-info.java
new file mode 100644
index 00000000000..ab1a2d903e4
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.projectlink.ws;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json b/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json
new file mode 100644
index 00000000000..8638919d9a0
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json
@@ -0,0 +1,15 @@
+{
+ "links": [
+ {
+ "id": "1",
+ "name": "Homepage",
+ "type": "homepage",
+ "url": "http://example.org"
+ },
+ {
+ "id": "2",
+ "name": "Custom",
+ "url": "http://example.org/custom"
+ }
+ ]
+} \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsModuleTest.java
new file mode 100644
index 00000000000..7514fbe35df
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsModuleTest.java
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import org.junit.Test;
+import org.sonar.core.platform.ComponentContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectLinksWsModuleTest {
+
+ @Test
+ public void verify_count_of_added_components() {
+ ComponentContainer container = new ComponentContainer();
+ new ProjectLinksModule().configure(container);
+ assertThat(container.size()).isEqualTo(2 + 2);
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java
new file mode 100644
index 00000000000..c35ba646fdf
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ProjectLinksWsTest {
+
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+ WebService.Controller controller;
+
+ @Before
+ public void setUp() {
+ WsTester tester = new WsTester(new ProjectLinksWs(
+ new SearchAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class))
+ ));
+ controller = tester.controller("api/project_links");
+ }
+
+ @Test
+ public void define_controller() {
+ assertThat(controller).isNotNull();
+ assertThat(controller.description()).isNotEmpty();
+ assertThat(controller.since()).isEqualTo("6.1");
+ assertThat(controller.actions()).hasSize(1);
+ }
+
+ @Test
+ public void define_search_action() {
+ WebService.Action action = controller.action("search");
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isFalse();
+ assertThat(action.handler()).isNotNull();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params()).hasSize(2);
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java
new file mode 100644
index 00000000000..45557966b77
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java
@@ -0,0 +1,263 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectlink.ws;
+
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.WsProjectLinks.Link;
+import org.sonarqube.ws.WsProjectLinks.SearchWsResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.MediaTypes.PROTOBUF;
+import static org.sonarqube.ws.client.projectlinks.ProjectLinksWsParameters.PARAM_PROJECT_ID;
+import static org.sonarqube.ws.client.projectlinks.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
+
+public class SearchActionTest {
+
+ private final String PROJECT_KEY = KEY_PROJECT_EXAMPLE_001;
+ private final String PROJECT_UUID = UUID_EXAMPLE_01;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ DbClient dbClient = db.getDbClient();
+ DbSession dbSession = db.getSession();
+ ComponentDbTester componentDb = new ComponentDbTester(db);
+
+ WsActionTester ws;
+
+ SearchAction underTest;
+
+ @Before
+ public void setUp() {
+ ComponentFinder componentFinder = new ComponentFinder(dbClient);
+ underTest = new SearchAction(dbClient, userSession, componentFinder);
+ ws = new WsActionTester(underTest);
+
+ userSession.login("login").setGlobalPermissions(SYSTEM_ADMIN);
+ }
+
+ @Test
+ public void example() {
+ ComponentDto project = insertProject();
+ insertHomepageLink(project.uuid());
+ insertCustomLink(project.uuid());
+
+ String result = ws.newRequest()
+ .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .execute().getInput();
+
+ assertJson(result).ignoreFields("id").isSimilarTo(getClass().getResource("list-example.json"));
+ }
+
+ @Test
+ public void request_by_project_id() throws IOException {
+ ComponentDto project = insertProject();
+ insertHomepageLink(project.uuid());
+
+ SearchWsResponse response = callByUuid(project.uuid());
+
+ assertThat(response.getLinksCount()).isEqualTo(1);
+ assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
+ }
+
+ @Test
+ public void request_by_project_key() throws IOException {
+ ComponentDto project = insertProject();
+ insertHomepageLink(project.uuid());
+
+ SearchWsResponse response = callByKey(project.key());
+
+ assertThat(response.getLinksCount()).isEqualTo(1);
+ assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
+ }
+
+ @Test
+ public void response_fields() throws IOException {
+ ComponentDto project = insertProject();
+ ComponentLinkDto homepageLink = insertHomepageLink(project.uuid());
+ ComponentLinkDto customLink = insertCustomLink(project.uuid());
+
+ SearchWsResponse response = callByKey(project.key());
+
+ assertThat(response.getLinksCount()).isEqualTo(2);
+ assertThat(response.getLinksList()).extracting(Link::getId, Link::getName, Link::getType, Link::getUrl)
+ .containsOnlyOnce(
+ tuple(homepageLink.getIdAsString(), homepageLink.getName(), homepageLink.getType(), homepageLink.getHref()),
+ tuple(customLink.getIdAsString(), customLink.getName(), customLink.getType(), customLink.getHref()));
+ }
+
+ @Test
+ public void several_projects() throws IOException {
+ ComponentDto project1 = insertProject();
+ ComponentDto project2 = insertProject("another", "abcd");
+ ComponentLinkDto customLink1 = insertCustomLink(project1.uuid());
+ insertCustomLink(project2.uuid());
+
+ SearchWsResponse response = callByKey(project1.key());
+
+ assertThat(response.getLinksCount()).isEqualTo(1);
+ assertThat(response.getLinks(0).getId()).isEqualTo(customLink1.getIdAsString());
+ }
+
+ @Test
+ public void global_admin() throws IOException {
+ userSession.login("login").setGlobalPermissions(SYSTEM_ADMIN);
+ checkItWorks();
+ }
+
+ @Test
+ public void project_admin() throws IOException {
+ userSession.login("login");
+ ComponentDto project = insertProject();
+ userSession.addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+ checkItWorks(project);
+ }
+
+ @Test
+ public void project_user() throws IOException {
+ userSession.login("login");
+ ComponentDto project = insertProject();
+ userSession.addProjectUuidPermissions(UserRole.USER, project.uuid());
+ checkItWorks(project);
+ }
+
+ @Test
+ public void fail_when_no_project() throws IOException {
+ expectedException.expect(NotFoundException.class);
+ callByKey("unknown");
+ }
+
+ @Test
+ public void fail_if_insufficient_privileges() throws IOException {
+ userSession.anonymous();
+ insertProject();
+
+ expectedException.expect(ForbiddenException.class);
+ callByKey(PROJECT_KEY);
+ }
+
+ @Test
+ public void fail_when_both_id_and_key_are_provided() {
+ insertProject();
+
+ expectedException.expect(IllegalArgumentException.class);
+ ws.newRequest()
+ .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .setParam(PARAM_PROJECT_ID, PROJECT_UUID)
+ .execute();
+ }
+
+ @Test
+ public void fail_when_no_id_nor_key_are_provided() {
+ insertProject();
+
+ expectedException.expect(IllegalArgumentException.class);
+ ws.newRequest()
+ .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .setParam(PARAM_PROJECT_ID, PROJECT_UUID)
+ .execute();
+ }
+
+ private ComponentDto insertProject(String projectKey, String projectUuid) {
+ return componentDb.insertComponent(newProjectDto(projectUuid).setKey(projectKey));
+ }
+
+ private ComponentDto insertProject() {
+ return insertProject(PROJECT_KEY, PROJECT_UUID);
+ }
+
+ private void insertLink(ComponentLinkDto linkDto) {
+ dbClient.componentLinkDao().insert(dbSession, linkDto);
+ dbSession.commit();
+ }
+
+ private ComponentLinkDto insertHomepageLink(String projectUuid) {
+ ComponentLinkDto link = new ComponentLinkDto()
+ .setComponentUuid(projectUuid)
+ .setName("Homepage")
+ .setType("homepage")
+ .setHref("http://example.org");
+ insertLink(link);
+ return link;
+ }
+
+ private ComponentLinkDto insertCustomLink(String projectUuid) {
+ ComponentLinkDto link = new ComponentLinkDto()
+ .setComponentUuid(projectUuid)
+ .setName("Custom")
+ .setType("Custom")
+ .setHref("http://example.org/custom");
+ insertLink(link);
+ return link;
+ }
+
+ private SearchWsResponse callByKey(String projectKey) throws IOException {
+ return SearchWsResponse.parseFrom(ws.newRequest()
+ .setParam(PARAM_PROJECT_KEY, projectKey)
+ .setMediaType(PROTOBUF)
+ .execute().getInputStream());
+ }
+
+ private SearchWsResponse callByUuid(String projectUuid) throws IOException {
+ return SearchWsResponse.parseFrom(ws.newRequest()
+ .setParam(PARAM_PROJECT_ID, projectUuid)
+ .setMediaType(PROTOBUF)
+ .execute().getInputStream());
+ }
+
+ private void checkItWorks(ComponentDto project) throws IOException {
+ insertHomepageLink(project.uuid());
+ SearchWsResponse response = callByKey(project.key());
+ assertThat(response.getLinksCount()).isEqualTo(1);
+ assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
+ }
+
+ private void checkItWorks() throws IOException {
+ checkItWorks(insertProject());
+ }
+}