From f624269d85f829af2429158cb0d7580c66d70ba7 Mon Sep 17 00:00:00 2001 From: Michael Clarke Date: Mon, 20 Apr 2020 07:14:39 +0100 Subject: [PATCH] Add support for Sonarqube 8.2.0 Sonarqube 8.2 introduced a new `ProjectDto` with associated changes in `ProjectAlmSettingsDao` to require this new class in various methods, as well as changes in `ComponentFinder` to allow retrieval of instances of a project. This change makes use of these new classes and methods to allow the Web Services for setting up ALM bindings to operate. As this class and the associated methods did not exist in previous versions of Sonarqube, this change breaks backwards compatibility, so means the plugin will now only support Sonarqube 8.2. Sonarqube 8.2 also provides the ability to set the optional URL parameter on a Gitlab project so that scans run outside of Gitlab CI operate properly, so the additional parameter is now included in the appropriate WebServices and the Gitlab decorator. --- build.gradle | 2 +- .../GitlabServerPullRequestDecorator.java | 8 +- .../ws/action/DeleteBindingAction.java | 6 +- .../ws/action/GetBindingAction.java | 15 ++- .../pullrequest/ws/action/ListAction.java | 17 ++- .../ws/action/ListDefinitionsAction.java | 9 +- .../ws/action/ProjectWsAction.java | 33 ++++-- .../ws/action/SetBindingAction.java | 10 +- .../ws/action/gitlab/CreateGitlabAction.java | 3 + .../ws/action/gitlab/UpdateGitlabAction.java | 5 +- .../ws/action/DeleteBindingActionTest.java | 20 ++-- .../ws/action/GetBindingActionTest.java | 100 ++++++++++++------ .../pullrequest/ws/action/ListActionTest.java | 19 ++-- .../ws/action/ListDefinitionsActionTest.java | 44 ++++++++ .../ws/action/SetBindingActionTest.java | 32 +++--- .../action/gitlab/CreateGitlabActionTest.java | 25 +++++ .../action/gitlab/UpdateGitlabActionTest.java | 24 +++++ 17 files changed, 264 insertions(+), 108 deletions(-) diff --git a/build.gradle b/build.gradle index 312a4309e..237b6ab0f 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ repositories { } } -def sonarqubeVersion = '8.1.0.31237' +def sonarqubeVersion = '8.2.0.32929' def sonarqubeLibDir = "${projectDir}/sonarqube-lib" def sonarLibraries = "${sonarqubeLibDir}/sonarqube-${sonarqubeVersion}/lib" diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/gitlab/GitlabServerPullRequestDecorator.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/gitlab/GitlabServerPullRequestDecorator.java index 25d14f752..7864f1353 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/gitlab/GitlabServerPullRequestDecorator.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/gitlab/GitlabServerPullRequestDecorator.java @@ -32,6 +32,7 @@ import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.gitlab.response.User; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.MarkdownFormatterFactory; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -102,10 +103,11 @@ public DecorationResult decorateQualityGateStatus(AnalysisDetails analysis, AlmS String revision = analysis.getCommitSha(); try { - final String apiURL = analysis.getScannerProperty(PULLREQUEST_GITLAB_INSTANCE_URL).orElseThrow( - () -> new IllegalStateException(String.format( + final String apiURL = Optional.ofNullable(StringUtils.stripToNull(almSettingDto.getUrl())) + .orElse(analysis.getScannerProperty(PULLREQUEST_GITLAB_INSTANCE_URL) + .orElseThrow(() -> new IllegalStateException(String.format( "Could not decorate Gitlab merge request. '%s' has not been set in scanner properties", - PULLREQUEST_GITLAB_INSTANCE_URL))); + PULLREQUEST_GITLAB_INSTANCE_URL)))); final String apiToken = almSettingDto.getPersonalAccessToken(); final String projectId = analysis.getScannerProperty(PULLREQUEST_GITLAB_PROJECT_ID).orElseThrow( () -> new IllegalStateException(String.format( diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingAction.java index 96f5f853d..f65e77f69 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingAction.java @@ -23,7 +23,7 @@ import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; @@ -32,7 +32,7 @@ public class DeleteBindingAction extends ProjectWsAction { private final DbClient dbClient; public DeleteBindingAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) { - super("delete_binding", dbClient, componentFinder, userSession); + super("delete_binding", dbClient, componentFinder, userSession, true); this.dbClient = dbClient; } @@ -43,7 +43,7 @@ protected void configureAction(WebService.NewAction action) { } @Override - protected void handleProjectRequest(ComponentDto project, Request request, Response response, DbSession dbSession) { + protected void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) { dbClient.projectAlmSettingDao().deleteByProject(dbSession, project); dbSession.commit(); diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingAction.java index 1517cf39a..744698f1d 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingAction.java @@ -18,10 +18,7 @@ */ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static java.lang.String.format; - -import java.util.Optional; - +import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.AlmTypeMapper; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -29,14 +26,16 @@ import org.sonar.db.DbSession; import org.sonar.db.alm.setting.AlmSettingDto; import org.sonar.db.alm.setting.ProjectAlmSettingDto; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UserSession; import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.AlmSettings.GetBindingWsResponse; -import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.AlmTypeMapper; +import java.util.Optional; + +import static java.lang.String.format; public class GetBindingAction extends ProjectWsAction { @@ -48,7 +47,7 @@ public GetBindingAction(DbClient dbClient, ComponentFinder componentFinder, User } GetBindingAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ProtoBufWriter protoBufWriter) { - super("get_binding", dbClient, componentFinder, userSession); + super("get_binding", dbClient, componentFinder, userSession, true); this.dbClient = dbClient; this.protoBufWriter = protoBufWriter; } @@ -59,7 +58,7 @@ protected void configureAction(WebService.NewAction action) { } @Override - protected void handleProjectRequest(ComponentDto project, Request request, Response response, DbSession dbSession) { + protected void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) { ProjectAlmSettingDto projectAlmSetting = dbClient.projectAlmSettingDao().selectByProject(dbSession, project) .orElseThrow(() -> new NotFoundException( format("Project '%s' is not bound to any ALM", project.getKey()))); diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListAction.java index 0ce6c9f16..1a760fb3f 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListAction.java @@ -18,25 +18,24 @@ */ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static java.util.Optional.ofNullable; - -import java.util.List; -import java.util.stream.Collectors; - +import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.AlmTypeMapper; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.alm.setting.AlmSettingDto; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.AlmSettings.AlmSetting; import org.sonarqube.ws.AlmSettings.ListWsResponse; -import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.AlmTypeMapper; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.Optional.ofNullable; public class ListAction extends ProjectWsAction { @@ -48,7 +47,7 @@ public ListAction(DbClient dbClient, UserSession userSession, ComponentFinder co } public ListAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, ProtoBufWriter protoBufWriter) { - super("list", dbClient, componentFinder, userSession); + super("list", dbClient, componentFinder, userSession, false); this.dbClient = dbClient; this.protoBufWriter = protoBufWriter; } @@ -59,7 +58,7 @@ protected void configureAction(WebService.NewAction action) { } @Override - protected void handleProjectRequest(ComponentDto project, Request request, Response response, DbSession dbSession) { + protected void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) { List settings = dbClient.almSettingDao().selectAll(dbSession); List wsAlmSettings = settings.stream().map(almSetting -> { AlmSetting.Builder almSettingBuilder = AlmSetting.newBuilder().setKey(almSetting.getKey()) diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsAction.java index 1528da7a8..ea81d0999 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsAction.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static java.util.Collections.emptyList; @@ -115,8 +116,12 @@ private static AlmSettingBitbucket toBitbucket(AlmSettingDto settingDto) { } private static AlmSettings.AlmSettingGitlab toGitlab(AlmSettingDto settingDto) { - return AlmSettings.AlmSettingGitlab.newBuilder() + AlmSettings.AlmSettingGitlab.Builder almSettingBuilder = AlmSettings.AlmSettingGitlab.newBuilder() .setKey(settingDto.getKey()) - .setPersonalAccessToken(requireNonNull(settingDto.getPersonalAccessToken(), "Personal Access Token cannot be null for Gitlab ALM setting")).build(); + .setPersonalAccessToken(requireNonNull(settingDto.getPersonalAccessToken(), "Personal Access Token cannot be null for Gitlab ALM setting")); + + Optional.ofNullable(settingDto.getUrl()).ifPresent(almSettingBuilder::setUrl); + + return almSettingBuilder.build(); } } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ProjectWsAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ProjectWsAction.java index ca6c6e999..e2ef68508 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ProjectWsAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ProjectWsAction.java @@ -1,16 +1,18 @@ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static org.sonar.api.web.UserRole.ADMIN; - import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; +import java.util.Optional; + +import static org.sonar.api.web.UserRole.ADMIN; + public abstract class ProjectWsAction extends AlmSettingsWsAction { private static final String PROJECT_PARAMETER = "project"; @@ -19,19 +21,21 @@ public abstract class ProjectWsAction extends AlmSettingsWsAction { private final DbClient dbClient; private final ComponentFinder componentFinder; private final UserSession userSession; + private final boolean projectParameterRequired; - protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) { + protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, boolean projectParameterRequired) { super(dbClient); this.actionName = actionName; this.dbClient = dbClient; this.componentFinder = componentFinder; this.userSession = userSession; + this.projectParameterRequired = projectParameterRequired; } @Override public void define(WebService.NewController context) { WebService.NewAction action = context.createAction(actionName).setHandler(this); - action.createParam(PROJECT_PARAMETER).setRequired(true); + action.createParam(PROJECT_PARAMETER).setRequired(projectParameterRequired); configureAction(action); } @@ -41,14 +45,23 @@ public void define(WebService.NewController context) { @Override public void handle(Request request, Response response) { - String projectKey = request.mandatoryParam(PROJECT_PARAMETER); - try (DbSession dbSession = dbClient.openSession(false)) { - ComponentDto project = componentFinder.getByKey(dbSession, projectKey); - userSession.checkComponentPermission(ADMIN, project); + Optional projectKey = Optional.ofNullable(request.param(PROJECT_PARAMETER)); + try (DbSession dbSession = dbClient.openSession(false)) { + ProjectDto project; + if (projectKey.isPresent()) { + project = componentFinder.getProjectByKey(dbSession, projectKey.get()); + userSession.checkProjectPermission(ADMIN, project); + } else { + if (projectParameterRequired) { + throw new IllegalArgumentException("The 'project' parameter is missing"); + } else { + project = null; + } + } handleProjectRequest(project, request, response, dbSession); } } - protected abstract void handleProjectRequest(ComponentDto project, Request request, Response response, DbSession dbSession); + protected abstract void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession); } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingAction.java index 74b524307..a9ff97fed 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingAction.java @@ -25,7 +25,7 @@ import org.sonar.db.DbSession; import org.sonar.db.alm.setting.AlmSettingDto; import org.sonar.db.alm.setting.ProjectAlmSettingDto; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; @@ -34,18 +34,20 @@ public abstract class SetBindingAction extends ProjectWsAction { private static final String ALM_SETTING_PARAMETER = "almSetting"; protected SetBindingAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, String actionName) { - super(actionName, dbClient, componentFinder, userSession); + super(actionName, dbClient, componentFinder, userSession, true); } + @Override protected void configureAction(WebService.NewAction action) { action.createParam(ALM_SETTING_PARAMETER).setRequired(true); } - protected void handleProjectRequest(ComponentDto project, Request request, Response response, DbSession dbSession) { + @Override + protected void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) { String almSetting = request.mandatoryParam(ALM_SETTING_PARAMETER); AlmSettingDto almSettingDto = getAlmSetting(dbSession, almSetting); - getDbClient().projectAlmSettingDao().insertOrUpdate(dbSession, createProjectAlmSettingDto(project.uuid(), almSettingDto.getUuid(), request)); + getDbClient().projectAlmSettingDao().insertOrUpdate(dbSession, createProjectAlmSettingDto(project.getUuid(), almSettingDto.getUuid(), request)); dbSession.commit(); response.noContent(); diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabAction.java index 31d9dff4c..256e4b433 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabAction.java @@ -29,6 +29,7 @@ public class CreateGitlabAction extends CreateAction { + private static final String URL_PARAMETER = "url"; private static final String PERSONAL_ACCESS_TOKEN_PARAMETER = "personalAccessToken"; public CreateGitlabAction(DbClient dbClient, UserSession userSession) { @@ -37,6 +38,7 @@ public CreateGitlabAction(DbClient dbClient, UserSession userSession) { @Override public void configureAction(WebService.NewAction action) { + action.createParam(URL_PARAMETER).setMaximumLength(2000); action.createParam(PERSONAL_ACCESS_TOKEN_PARAMETER).setRequired(true).setMaximumLength(2000); } @@ -45,6 +47,7 @@ public AlmSettingDto createAlmSettingDto(String key, Request request) { return new AlmSettingDto() .setAlm(GITLAB) .setKey(key) + .setUrl(request.param(URL_PARAMETER)) .setPersonalAccessToken(request.mandatoryParam(PERSONAL_ACCESS_TOKEN_PARAMETER)); } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabAction.java index 351d69790..298e74d09 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabAction.java @@ -27,6 +27,7 @@ public class UpdateGitlabAction extends UpdateAction { + private static final String URL_PARAMETER = "url"; private static final String PERSONAL_ACCESS_TOKEN_PARAMETER = "personalAccessToken"; public UpdateGitlabAction(DbClient dbClient, UserSession userSession) { @@ -35,12 +36,14 @@ public UpdateGitlabAction(DbClient dbClient, UserSession userSession) { @Override protected void configureAction(WebService.NewAction action) { + action.createParam(URL_PARAMETER).setMaximumLength(2000); action.createParam(PERSONAL_ACCESS_TOKEN_PARAMETER).setRequired(true).setMaximumLength(2000); } @Override protected AlmSettingDto updateAlmSettingsDto(AlmSettingDto almSettingDto, Request request) { - return almSettingDto.setPersonalAccessToken(request.mandatoryParam(PERSONAL_ACCESS_TOKEN_PARAMETER)); + return almSettingDto.setPersonalAccessToken(request.mandatoryParam(PERSONAL_ACCESS_TOKEN_PARAMETER)) + .setUrl(request.param(URL_PARAMETER)); } } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingActionTest.java index 244f0c555..678140ef8 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/DeleteBindingActionTest.java @@ -1,10 +1,5 @@ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.server.ws.Request; @@ -14,10 +9,15 @@ import org.sonar.db.DbSession; import org.sonar.db.alm.setting.AlmSettingDao; import org.sonar.db.alm.setting.ProjectAlmSettingDao; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + public class DeleteBindingActionTest { @Test @@ -58,14 +58,14 @@ public void testHandle() { UserSession userSession = mock(UserSession.class); - ComponentDto componentDto = mock(ComponentDto.class); + ProjectDto componentDto = mock(ProjectDto.class); ComponentFinder componentFinder = mock(ComponentFinder.class); - when(componentFinder.getByKey(eq(dbSession), eq("projectKey"))).thenReturn(componentDto); + when(componentFinder.getProjectByKey(eq(dbSession), eq("projectKey"))).thenReturn(componentDto); DeleteBindingAction testCase = new DeleteBindingAction(dbClient, userSession, componentFinder); Request request = mock(Request.class, Mockito.RETURNS_DEEP_STUBS); - when(request.mandatoryParam("project")).thenReturn("projectKey"); + when(request.param("project")).thenReturn("projectKey"); Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); testCase.handle(request, response); @@ -73,7 +73,7 @@ public void testHandle() { verify(dbSession).commit(); verify(projectAlmSettingDao).deleteByProject(eq(dbSession), eq(componentDto)); verify(response).noContent(); - verify(userSession).checkComponentPermission("admin", componentDto); + verify(userSession).checkProjectPermission("admin", componentDto); } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingActionTest.java index ce0c6b68d..4f2a260de 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/GetBindingActionTest.java @@ -1,17 +1,6 @@ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - +import com.google.protobuf.Message; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -25,13 +14,23 @@ import org.sonar.db.alm.setting.AlmSettingDto; import org.sonar.db.alm.setting.ProjectAlmSettingDao; import org.sonar.db.alm.setting.ProjectAlmSettingDto; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UserSession; import org.sonarqube.ws.AlmSettings; -import com.google.protobuf.Message; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class GetBindingActionTest { @@ -73,18 +72,18 @@ public void testHandle() { when(almSettingDto.getKey()).thenReturn("key"); when(almSettingDto.getUrl()).thenReturn("url"); when(dbClient.almSettingDao()).thenReturn(almSettingDao); - ComponentDto componentDto = mock(ComponentDto.class); + ProjectDto projectDto = mock(ProjectDto.class); ProjectAlmSettingDao projectAlmSettingDao = mock(ProjectAlmSettingDao.class); when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao); ComponentFinder componentFinder = mock(ComponentFinder.class); - when(componentDto.uuid()).thenReturn("projectUuid"); - when(componentFinder.getByKey(eq(dbSession), eq("project"))).thenReturn(componentDto); + when(projectDto.getKey()).thenReturn("projectUuid"); + when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(projectDto); UserSession userSession = mock(UserSession.class); ProjectAlmSettingDto projectAlmSettingDto = mock(ProjectAlmSettingDto.class); when(projectAlmSettingDto.getAlmSettingUuid()).thenReturn("almSettingUuid"); when(projectAlmSettingDto.getAlmRepo()).thenReturn("repository"); when(projectAlmSettingDto.getAlmSlug()).thenReturn("slug"); - when(projectAlmSettingDao.selectByProject(eq(dbSession), eq(componentDto))).thenReturn(Optional.of(projectAlmSettingDto)); + when(projectAlmSettingDao.selectByProject(eq(dbSession), eq(projectDto))).thenReturn(Optional.of(projectAlmSettingDto)); ProtoBufWriter protoBufWriter = mock(ProtoBufWriter.class); GetBindingAction testCase = new GetBindingAction(dbClient, componentFinder, userSession, protoBufWriter); @@ -93,7 +92,7 @@ public void testHandle() { Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); when(request.mandatoryParam("almSetting")).thenReturn("almSetting"); - when(request.mandatoryParam("project")).thenReturn("project"); + when(request.param("project")).thenReturn("project"); when(request.getMediaType()).thenReturn("dummy"); testCase.handle(request, response); @@ -112,6 +111,45 @@ public void testHandle() { assertThat(message).isInstanceOf(AlmSettings.GetBindingWsResponse.class).isEqualTo(expectedResponse); } + @Test + public void testHandleMissingProjectParameter() { + DbClient dbClient = mock(DbClient.class); + DbSession dbSession = mock(DbSession.class); + when(dbClient.openSession(eq(false))).thenReturn(dbSession); + AlmSettingDao almSettingDao = mock(AlmSettingDao.class); + AlmSettingDto almSettingDto = mock(AlmSettingDto.class); + when(almSettingDto.getUuid()).thenReturn("almSettingsUuid"); + when(almSettingDao.selectByUuid(eq(dbSession), eq("almSettingUuid"))).thenReturn(Optional.of(almSettingDto)); + when(almSettingDto.getAlm()).thenReturn(ALM.GITHUB); + when(almSettingDto.getKey()).thenReturn("key"); + when(almSettingDto.getUrl()).thenReturn("url"); + when(dbClient.almSettingDao()).thenReturn(almSettingDao); + ProjectDto projectDto = mock(ProjectDto.class); + ProjectAlmSettingDao projectAlmSettingDao = mock(ProjectAlmSettingDao.class); + when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao); + ComponentFinder componentFinder = mock(ComponentFinder.class); + when(projectDto.getKey()).thenReturn("projectUuid"); + when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(projectDto); + UserSession userSession = mock(UserSession.class); + ProjectAlmSettingDto projectAlmSettingDto = mock(ProjectAlmSettingDto.class); + when(projectAlmSettingDto.getAlmSettingUuid()).thenReturn("almSettingUuid"); + when(projectAlmSettingDto.getAlmRepo()).thenReturn("repository"); + when(projectAlmSettingDto.getAlmSlug()).thenReturn("slug"); + when(projectAlmSettingDao.selectByProject(eq(dbSession), eq(projectDto))).thenReturn(Optional.of(projectAlmSettingDto)); + ProtoBufWriter protoBufWriter = mock(ProtoBufWriter.class); + + GetBindingAction testCase = new GetBindingAction(dbClient, componentFinder, userSession, protoBufWriter); + + Request request = mock(Request.class, Mockito.RETURNS_DEEP_STUBS); + Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); + + when(request.mandatoryParam("almSetting")).thenReturn("almSetting"); + when(request.getMediaType()).thenReturn("dummy"); + + assertThatThrownBy(() -> testCase.handle(request, response)) + .isInstanceOf(IllegalArgumentException.class).hasMessage("The 'project' parameter is missing"); + } + @Test public void testHandleUnboundProject() { DbClient dbClient = mock(DbClient.class); @@ -122,12 +160,12 @@ public void testHandleUnboundProject() { when(projectAlmSettingDao.selectByProject(eq(dbSession), eq("projectUuid"))).thenReturn(Optional.empty()); when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao); - ComponentDto componentDto = mock(ComponentDto.class); - when(componentDto.getKey()).thenReturn("projectKey"); + ProjectDto projectDto = mock(ProjectDto.class); + when(projectDto.getKey()).thenReturn("project"); ComponentFinder componentFinder = mock(ComponentFinder.class); - when(componentDto.uuid()).thenReturn("projectUuid"); - when(componentFinder.getByKey(eq(dbSession), eq("project"))).thenReturn(componentDto); + when(projectDto.getKey()).thenReturn("project"); + when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(projectDto); UserSession userSession = mock(UserSession.class); GetBindingAction testCase = new GetBindingAction(dbClient, componentFinder, userSession); @@ -136,10 +174,10 @@ public void testHandleUnboundProject() { Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); when(request.mandatoryParam("almSetting")).thenReturn("almSetting"); - when(request.mandatoryParam("project")).thenReturn("project"); + when(request.param("project")).thenReturn("project"); when(request.getMediaType()).thenReturn("dummy"); - assertThatThrownBy(() -> testCase.handle(request, response)).isInstanceOf(NotFoundException.class).hasMessage("Project 'projectKey' is not bound to any ALM"); + assertThatThrownBy(() -> testCase.handle(request, response)).isInstanceOf(NotFoundException.class).hasMessage("Project 'project' is not bound to any ALM"); } @Test @@ -151,10 +189,10 @@ public void testHandleUnknownAlmSetting() { ProjectAlmSettingDto projectAlmSettingDto = mock(ProjectAlmSettingDto.class); when(projectAlmSettingDto.getAlmSettingUuid()).thenReturn("settingUuid"); - ComponentDto componentDto = mock(ComponentDto.class); - when(componentDto.getKey()).thenReturn("projectKey"); + ProjectDto projectDto = mock(ProjectDto.class); + when(projectDto.getKey()).thenReturn("project"); - when(projectAlmSettingDao.selectByProject(eq(dbSession), eq(componentDto))).thenReturn(Optional.of(projectAlmSettingDto)); + when(projectAlmSettingDao.selectByProject(eq(dbSession), eq(projectDto))).thenReturn(Optional.of(projectAlmSettingDto)); when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao); AlmSettingDao almSettingDao = mock(AlmSettingDao.class); @@ -162,8 +200,8 @@ public void testHandleUnknownAlmSetting() { when(almSettingDao.selectByKey(eq(dbSession), eq("settingUuid"))).thenReturn(Optional.empty()); ComponentFinder componentFinder = mock(ComponentFinder.class); - when(componentDto.uuid()).thenReturn("projectUuid"); - when(componentFinder.getByKey(eq(dbSession), eq("project"))).thenReturn(componentDto); + when(projectDto.getKey()).thenReturn("projectUuid"); + when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(projectDto); UserSession userSession = mock(UserSession.class); GetBindingAction testCase = new GetBindingAction(dbClient, componentFinder, userSession); @@ -172,7 +210,7 @@ public void testHandleUnknownAlmSetting() { Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); when(request.mandatoryParam("almSetting")).thenReturn("almSetting"); - when(request.mandatoryParam("project")).thenReturn("project"); + when(request.param("project")).thenReturn("project"); when(request.getMediaType()).thenReturn("dummy"); assertThatThrownBy(() -> testCase.handle(request, response)).isInstanceOf(IllegalStateException.class).hasMessage("ALM setting 'settingUuid' cannot be found"); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListActionTest.java index 7b2a86ffc..2e42c0e78 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListActionTest.java @@ -1,13 +1,6 @@ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Arrays; - +import com.google.protobuf.Message; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -23,7 +16,13 @@ import org.sonar.server.user.UserSession; import org.sonarqube.ws.AlmSettings; -import com.google.protobuf.Message; +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class ListActionTest { @@ -44,7 +43,7 @@ public void testDefine() { testCase.define(newController); verify(newAction).setHandler(eq(testCase)); - verify(param).setRequired(true); + verify(param).setRequired(false); } @Test diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsActionTest.java index 25480f113..15e8cc26e 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/ListDefinitionsActionTest.java @@ -7,6 +7,7 @@ import static org.mockito.Mockito.when; import java.util.Arrays; +import java.util.Collections; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -117,4 +118,47 @@ public void testHandle() { assertThat(message).isInstanceOf(AlmSettings.ListDefinitionsWsResponse.class).isEqualTo(expectedResponse); } + @Test + public void testHandleWithGitlabUrl() { + DbClient dbClient = mock(DbClient.class); + DbSession dbSession = mock(DbSession.class); + when(dbClient.openSession(eq(false))).thenReturn(dbSession); + AlmSettingDao almSettingDao = mock(AlmSettingDao.class); + + AlmSettingDto gitlabAlmSettingDto = mock(AlmSettingDto.class); + when(gitlabAlmSettingDto.getAlm()).thenReturn(ALM.GITLAB); + when(gitlabAlmSettingDto.getKey()).thenReturn("gitlabKey"); + when(gitlabAlmSettingDto.getUrl()).thenReturn("url"); + when(gitlabAlmSettingDto.getPersonalAccessToken()).thenReturn("gitlabPersonalAccessToken"); + when(gitlabAlmSettingDto.getUrl()).thenReturn("url"); + + when(almSettingDao.selectAll(eq(dbSession))).thenReturn(Collections.singletonList(gitlabAlmSettingDto)); + when(dbClient.almSettingDao()).thenReturn(almSettingDao); + + UserSession userSession = mock(UserSession.class); + + ProtoBufWriter protoBufWriter = mock(ProtoBufWriter.class); + + ListDefinitionsAction testCase = new ListDefinitionsAction(dbClient, userSession, protoBufWriter); + + Request request = mock(Request.class, Mockito.RETURNS_DEEP_STUBS); + Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS); + + testCase.handle(request, response); + + ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); + verify(protoBufWriter).write(messageArgumentCaptor.capture(), eq(request), eq(response)); + Message message = messageArgumentCaptor.getValue(); + + AlmSettings.ListDefinitionsWsResponse expectedResponse = AlmSettings.ListDefinitionsWsResponse.newBuilder() + .addGitlab(AlmSettings.AlmSettingGitlab.newBuilder() + .setKey("gitlabKey") + .setUrl("url") + .setPersonalAccessToken("gitlabPersonalAccessToken") + .build()) + .build(); + + assertThat(message).isInstanceOf(AlmSettings.ListDefinitionsWsResponse.class).isEqualTo(expectedResponse); + } + } \ No newline at end of file diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingActionTest.java index c5206901a..149f9f1d3 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/SetBindingActionTest.java @@ -1,16 +1,5 @@ package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - import org.junit.Test; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -21,10 +10,21 @@ import org.sonar.db.alm.setting.AlmSettingDto; import org.sonar.db.alm.setting.ProjectAlmSettingDao; import org.sonar.db.alm.setting.ProjectAlmSettingDto; -import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + public class SetBindingActionTest { @Test @@ -74,9 +74,9 @@ public void testHandle() { ProjectAlmSettingDao projectAlmSettingDao = mock(ProjectAlmSettingDao.class); when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao); ComponentFinder componentFinder = mock(ComponentFinder.class); - ComponentDto componentDto = mock(ComponentDto.class); - when(componentDto.uuid()).thenReturn("projectUuid"); - when(componentFinder.getByKey(eq(dbSession), eq("project"))).thenReturn(componentDto); + ProjectDto componentDto = mock(ProjectDto.class); + when(componentDto.getUuid()).thenReturn("projectUuid"); + when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(componentDto); UserSession userSession = mock(UserSession.class); ThreadLocal capturedAction = new ThreadLocal<>(); ProjectAlmSettingDto projectAlmSettingDto = mock(ProjectAlmSettingDto.class); @@ -99,7 +99,7 @@ protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, St Response response = mock(Response.class); when(request.mandatoryParam("almSetting")).thenReturn("almSetting"); - when(request.mandatoryParam("project")).thenReturn("project"); + when(request.param("project")).thenReturn("project"); testCase.handle(request, response); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabActionTest.java index c7c18e6da..92ebfb70f 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/CreateGitlabActionTest.java @@ -30,11 +30,17 @@ public void testConfigureAction() { when(personalAccessTokenParameter.setRequired(anyBoolean())).thenReturn(personalAccessTokenParameter); when(newAction.createParam(eq("personalAccessToken"))).thenReturn(personalAccessTokenParameter); + WebService.NewParam urlParameter = mock(WebService.NewParam.class); + when(urlParameter.setMaximumLength(any(Integer.class))).thenReturn(urlParameter); + when(newAction.createParam(eq("url"))).thenReturn(urlParameter); + CreateGitlabAction testCase = new CreateGitlabAction(dbClient, userSession); testCase.configureAction(newAction); verify(personalAccessTokenParameter).setRequired(eq(true)); verify(personalAccessTokenParameter).setMaximumLength(2000); + + verify(urlParameter).setMaximumLength(2000); } @Test @@ -50,4 +56,23 @@ public void testCreateAlmSettingDto() { assertThat(result).isEqualToComparingFieldByField(new AlmSettingDto().setAlm(ALM.GITLAB).setKey("key").setPersonalAccessToken("personalAccessToken")); } + + @Test + public void testCreateAlmSettingDtoWithUrl() { + DbClient dbClient = mock(DbClient.class); + UserSession userSession = mock(UserSession.class); + + Request request = mock(Request.class); + when(request.mandatoryParam(eq("personalAccessToken"))).thenReturn("personalAccessToken"); + when(request.param(eq("url"))).thenReturn("url"); + + CreateGitlabAction testCase = new CreateGitlabAction(dbClient, userSession); + AlmSettingDto result = testCase.createAlmSettingDto("key", request); + + assertThat(result).isEqualToComparingFieldByField(new AlmSettingDto() + .setAlm(ALM.GITLAB) + .setKey("key") + .setUrl("url") + .setPersonalAccessToken("personalAccessToken")); + } } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabActionTest.java index a016fa250..573eec9b2 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/action/gitlab/UpdateGitlabActionTest.java @@ -29,11 +29,17 @@ public void testConfigureAction() { when(personalAccessTokenParameter.setRequired(anyBoolean())).thenReturn(personalAccessTokenParameter); when(newAction.createParam(eq("personalAccessToken"))).thenReturn(personalAccessTokenParameter); + WebService.NewParam urlParameter = mock(WebService.NewParam.class); + when(urlParameter.setMaximumLength(any(Integer.class))).thenReturn(urlParameter); + when(newAction.createParam(eq("url"))).thenReturn(urlParameter); + UpdateGitlabAction testCase = new UpdateGitlabAction(dbClient, userSession); testCase.configureAction(newAction); verify(personalAccessTokenParameter).setRequired(eq(true)); verify(personalAccessTokenParameter).setMaximumLength(2000); + + verify(urlParameter).setMaximumLength(2000); } @Test @@ -49,4 +55,22 @@ public void testUpdateAlmSettingsDto() { assertThat(result).isEqualToComparingFieldByField(new AlmSettingDto().setKey("originalKey").setPersonalAccessToken("personalAccessToken")); } + + @Test + public void testUpdateAlmSettingsDtoWithUrl() { + DbClient dbClient = mock(DbClient.class); + UserSession userSession = mock(UserSession.class); + + Request request = mock(Request.class); + when(request.mandatoryParam(eq("personalAccessToken"))).thenReturn("personalAccessToken"); + when(request.param(eq("url"))).thenReturn("url"); + + UpdateGitlabAction testCase = new UpdateGitlabAction(dbClient, userSession); + AlmSettingDto result = testCase.updateAlmSettingsDto(new AlmSettingDto().setKey("originalKey").setUrl("url"), request); + + assertThat(result).isEqualToComparingFieldByField(new AlmSettingDto() + .setKey("originalKey") + .setUrl("url") + .setPersonalAccessToken("personalAccessToken")); + } }