diff options
author | alain <108417558+alain-kermis-sonarsource@users.noreply.github.com> | 2022-10-27 14:08:20 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-10-27 20:03:02 +0000 |
commit | 83bd18d97d9d8e0b858875b253bc52efff70e810 (patch) | |
tree | 6984dfa8964d739eafa615aa9434cb933a899f3e /server/sonar-webserver-webapi | |
parent | 0806043b590e1d0f3bf08c4d88627dc9bb6cf913 (diff) | |
download | sonarqube-83bd18d97d9d8e0b858875b253bc52efff70e810.tar.gz sonarqube-83bd18d97d9d8e0b858875b253bc52efff70e810.zip |
SONAR-17497 Add web service to reindex issues
Diffstat (limited to 'server/sonar-webserver-webapi')
3 files changed, 201 insertions, 0 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java index 37b3a53adbb..6bf37943b81 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java @@ -67,6 +67,7 @@ public class IssueWsModule extends Module { SetTagsAction.class, SetTypeAction.class, ComponentTagsAction.class, + ReindexAction.class, AuthorsAction.class, ChangelogAction.class, BulkChangeAction.class, diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ReindexAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ReindexAction.java new file mode 100644 index 00000000000..2d2a2618528 --- /dev/null +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ReindexAction.java @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info 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.issue.ws; + +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.project.ProjectDto; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.user.UserSession; + +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT; + +/** + * Implementation of the {@code reindex} action for the Issues WebService. + */ +public class ReindexAction implements IssuesWsAction { + + private static final String ACTION = "reindex"; + private final DbClient dbClient; + private final IssueIndexer issueIndexer; + private final UserSession userSession; + + public ReindexAction(DbClient dbClient, IssueIndexer indexer, UserSession userSession) { + this.dbClient = dbClient; + this.issueIndexer = indexer; + this.userSession = userSession; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context + .createAction(ACTION) + .setPost(true) + .setDescription("Reindex issues for a project.<br> " + + "Requires one of the following permissions: " + + "<ul>" + + "<li>'Administer System'</li>" + + "<li>'Administer' rights on the specified project</li>" + + "</ul>") + .setSince("9.8") + .setHandler(this); + + action + .createParam(PARAM_PROJECT) + .setDescription("Project key") + .setRequired(true) + .setExampleValue(KEY_PROJECT_EXAMPLE_001); + } + + @Override + public void handle(Request request, Response response) throws Exception { + String projectKey = request.mandatoryParam(PARAM_PROJECT); + + ProjectDto projectDto; + try (DbSession dbSession = dbClient.openSession(false)) { + projectDto = dbClient.projectDao().selectProjectByKey(dbSession, projectKey).orElseThrow(() -> new NotFoundException("project not found")); + userSession.checkProjectPermission(UserRole.ADMIN, projectDto); + } + + issueIndexer.indexProject(projectDto.getUuid()); + response.noContent(); + } + +} diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ReindexActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ReindexActionTest.java new file mode 100644 index 00000000000..fb18d387348 --- /dev/null +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ReindexActionTest.java @@ -0,0 +1,113 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info 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.issue.ws; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.web.UserRole; +import org.sonar.db.DbTester; +import org.sonar.db.project.ProjectDto; +import org.sonar.server.es.EsTester; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.issue.index.AsyncIssueIndexing; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.issue.index.IssueIteratorFactory; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.TestResponse; +import org.sonar.server.ws.WsActionTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class ReindexActionTest { + + @Rule + public EsTester es = EsTester.create(); + @Rule + public DbTester db = DbTester.create(); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + + private final AsyncIssueIndexing mock = mock(AsyncIssueIndexing.class); + private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), mock); + private final ReindexAction underTest = new ReindexAction(db.getDbClient(), issueIndexer, userSession); + private final WsActionTester tester = new WsActionTester(underTest); + + @Test + public void test_definition() { + WebService.Action action = tester.getDef(); + + assertThat(action.key()).isEqualTo("reindex"); + assertThat(action.isPost()).isTrue(); + assertThat(action.isInternal()).isFalse(); + assertThat(action.params()).extracting(WebService.Param::key).containsExactly("project"); + } + + @Test + public void reindex_project() { + ProjectDto project = db.components().insertPrivateProjectDto(); + userSession.logIn().setSystemAdministrator(); + userSession.addProjectPermission(UserRole.ADMIN, project); + + TestResponse response = tester.newRequest() + .setParam("project", project.getKey()) + .execute(); + + assertThat(response.getStatus()).isEqualTo(204); + verify(mock, times(1)).triggerForProject(project.getUuid()); + } + + @Test + public void fail_if_project_does_not_exist() { + userSession.logIn().setSystemAdministrator(); + + TestRequest testRequest = tester.newRequest().setParam("project", "some-key"); + assertThatThrownBy(testRequest::execute) + .isInstanceOf(NotFoundException.class) + .hasMessage("project not found"); + } + + @Test + public void fail_if_parameter_not_present() { + userSession.anonymous(); + TestRequest testRequest = tester.newRequest(); + assertThatThrownBy(testRequest::execute) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("The 'project' parameter is missing"); + } + + @Test + public void fail_if_not_authorized() { + ProjectDto project = db.components().insertPrivateProjectDto(); + userSession.addProjectPermission(UserRole.USER, project); + + TestRequest testRequest = tester.newRequest().setParam("project", project.getKey()); + assertThatThrownBy(testRequest::execute) + .isInstanceOf(ForbiddenException.class) + .hasMessage("Insufficient privileges"); + } + +} |