diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2016-07-26 14:43:29 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2016-07-28 17:31:14 +0200 |
commit | fa27bf616fad3cb743994ea8407feabd96a22ae9 (patch) | |
tree | c270d62ddaf679973004712bd64ff9d1d67fd312 /server | |
parent | c61be4f486e6c9fabc5cc5fd03dba40b79e056f1 (diff) | |
download | sonarqube-fa27bf616fad3cb743994ea8407feabd96a22ae9.tar.gz sonarqube-fa27bf616fad3cb743994ea8407feabd96a22ae9.zip |
SONAR-7925 Create WS to list project links
Diffstat (limited to 'server')
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()); + } +} |