Przeglądaj źródła

SONAR-16096 Create webservices to get and clear scanner plugin cache

tags/9.4.0.54424
Duarte Meneses 2 lat temu
rodzic
commit
eb34454afc
15 zmienionych plików z 747 dodań i 6 usunięć
  1. 0
    5
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java
  2. 52
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ScannerCache.java
  3. 23
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/package-info.java
  4. 62
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ClearAction.java
  5. 129
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/GetAction.java
  6. 45
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWs.java
  7. 30
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWsAction.java
  8. 33
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWsModule.java
  9. 23
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/package-info.java
  10. 2
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/queue/CeQueueCleanerTest.java
  11. 93
    0
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ClearActionTest.java
  12. 158
    0
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/GetActionTest.java
  13. 35
    0
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ScannerCacheWsModuleTest.java
  14. 56
    0
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ScannerCacheWsTest.java
  15. 6
    0
      server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java

+ 0
- 5
server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java Wyświetl plik

@@ -126,11 +126,6 @@ public class ComponentFinder {
.orElseThrow(() -> new IllegalStateException(String.format("Can't find main branch for project '%s'", projectDto.getKey())));
}

public BranchDto getMainBranch(DbSession dbSession, ComponentDto projectDto) {
return dbClient.branchDao().selectByUuid(dbSession, projectDto.uuid())
.orElseThrow(() -> new IllegalStateException(String.format("Can't find main branch for project '%s'", projectDto.getKey())));
}

private static void checkByUuidOrKey(@Nullable String componentUuid, @Nullable String componentKey, ParamNames parameterNames) {
checkArgument(componentUuid != null ^ componentKey != null, MSG_COMPONENT_ID_OR_KEY_TEMPLATE, parameterNames.getUuidParam(), parameterNames.getKeyParam());
}

+ 52
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ScannerCache.java Wyświetl plik

@@ -0,0 +1,52 @@
/*
* 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.scannercache;

import javax.annotation.CheckForNull;
import org.sonar.api.server.ServerSide;
import org.sonar.db.DbClient;
import org.sonar.db.DbInputStream;
import org.sonar.db.DbSession;
import org.sonar.db.scannercache.ScannerCacheDao;

@ServerSide
public class ScannerCache {
private final DbClient dbClient;
private final ScannerCacheDao dao;

public ScannerCache(DbClient dbClient, ScannerCacheDao dao) {
this.dbClient = dbClient;
this.dao = dao;
}

@CheckForNull
public DbInputStream get(String branchUuid) {
try (DbSession session = dbClient.openSession(false)) {
return dao.selectData(session, branchUuid);
}
}

public void clear() {
try (DbSession session = dbClient.openSession(false)) {
dao.removeAll(session);
session.commit();
}
}
}

+ 23
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/package-info.java Wyświetl plik

@@ -0,0 +1,23 @@
/*
* 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.scannercache;

import javax.annotation.ParametersAreNonnullByDefault;

+ 62
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ClearAction.java Wyświetl plik

@@ -0,0 +1,62 @@
/*
* 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.scannercache.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.db.permission.GlobalPermission;
import org.sonar.server.scannercache.ScannerCache;
import org.sonar.server.user.UserSession;

import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;

public class ClearAction implements ScannerCacheWsAction {
private final UserSession userSession;
private final ScannerCache cache;

public ClearAction(UserSession userSession, ScannerCache cache) {
this.userSession = userSession;
this.cache = cache;
}

@Override
public void define(WebService.NewController context) {
context.createAction("clear")
.setInternal(true)
.setPost(true)
.setDescription("Clear the scanner's cached data for all projects and branches. Requires global administration permission. ")
.setSince("9.4")
.setHandler(this);
}

@Override
public void handle(Request request, Response response) throws Exception {
checkPermission();
cache.clear();
response.noContent();
}

private void checkPermission() {
if (!userSession.hasPermission(GlobalPermission.ADMINISTER)) {
throw insufficientPrivilegesException();
}
}
}

+ 129
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/GetAction.java Wyświetl plik

@@ -0,0 +1,129 @@
/*
* 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.scannercache.ws;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;
import org.apache.commons.io.IOUtils;
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.DbInputStream;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.scannercache.ScannerCache;
import org.sonar.server.user.UserSession;

import static org.sonar.db.permission.GlobalPermission.SCAN;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;

public class GetAction implements ScannerCacheWsAction {
private static final String PROJECT = "project";
private static final String BRANCH = "branch";

private final DbClient dbClient;
private final UserSession userSession;
private final ComponentFinder componentFinder;
private final ScannerCache cache;

public GetAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, ScannerCache cache) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
this.cache = cache;
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("get")
.setInternal(true)
.setDescription("Get the scanner's cached data for a branch. Requires scan permission on the project. "
+ "Data is returned gzipped if the corresponding 'Accept-Encoding' header is set in the request.")
.setSince("9.4")
.setHandler(this);

action.createParam(PROJECT)
.setDescription("Project key")
.setExampleValue(KEY_PROJECT_EXAMPLE_001)
.setRequired(true);

action.createParam(BRANCH)
.setDescription("Branch key. If not provided, main branch will be used.")
.setExampleValue(KEY_BRANCH_EXAMPLE_001)
.setRequired(false);
}

@Override
public void handle(Request request, Response response) throws Exception {
String projectKey = request.mandatoryParam(PROJECT);
String branchKey = request.param(BRANCH);

try (DbSession dbSession = dbClient.openSession(false)) {
ComponentDto component = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branchKey, null);
checkPermission(component);

try (DbInputStream dbInputStream = cache.get(component.uuid())) {
if (dbInputStream == null) {
throw new NotFoundException("No cache for given branch");
}

boolean compressed = requestedCompressedData(request);
try (OutputStream output = response.stream().output()) {
if (compressed) {
response.setHeader("Content-Encoding", "gzip");
// data is stored compressed
IOUtils.copy(dbInputStream, output);
} else {
try (InputStream uncompressedInput = new GZIPInputStream(dbInputStream)) {
IOUtils.copy(uncompressedInput, output);
}
}
}
}
}
}

private static boolean requestedCompressedData(Request request) {
String encoding = request.getHeaders().get("Accept-Encoding");
if (encoding == null) {
return false;
}
return Arrays.stream(encoding.split(","))
.map(String::trim)
.anyMatch("gzip"::equals);
}

private void checkPermission(ComponentDto project) {
if (userSession.hasComponentPermission(UserRole.SCAN, project) ||
userSession.hasComponentPermission(UserRole.ADMIN, project) ||
userSession.hasPermission(SCAN)) {
return;
}
throw insufficientPrivilegesException();
}
}

+ 45
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWs.java Wyświetl plik

@@ -0,0 +1,45 @@
/*
* 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.scannercache.ws;

import org.sonar.api.server.ws.WebService;

public class ScannerCacheWs implements WebService {

private final ScannerCacheWsAction[] actions;

public ScannerCacheWs(ScannerCacheWsAction... actions) {
this.actions = actions;
}

@Override
public void define(Context context) {
NewController controller = context
.createController("api/scanner_cache")
.setSince("9.4")
.setDescription("Access the scanner cache");

for (ScannerCacheWsAction action : actions) {
action.define(controller);
}

controller.done();
}
}

+ 30
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWsAction.java Wyświetl plik

@@ -0,0 +1,30 @@
/*
* 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.scannercache.ws;

import org.sonar.server.ws.WsAction;

/**
* Marker interface for coding rule related actions
*
*/
interface ScannerCacheWsAction extends WsAction {
// Marker interface
}

+ 33
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/ScannerCacheWsModule.java Wyświetl plik

@@ -0,0 +1,33 @@
/*
* 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.scannercache.ws;

import org.sonar.core.platform.Module;

public class ScannerCacheWsModule extends Module {
@Override
protected void configureModule() {
add(
ScannerCacheWs.class,
GetAction.class,
ClearAction.class
);
}
}

+ 23
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/scannercache/ws/package-info.java Wyświetl plik

@@ -0,0 +1,23 @@
/*
* 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.scannercache.ws;

import javax.annotation.ParametersAreNonnullByDefault;

+ 2
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/queue/CeQueueCleanerTest.java Wyświetl plik

@@ -27,6 +27,7 @@ import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.api.utils.System2;
import org.sonar.ce.queue.CeQueue;
import org.sonar.db.DbInputStream;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskInputDao;
@@ -89,7 +90,7 @@ public class CeQueueCleanerTest {
runCleaner();

CeTaskInputDao dataDao = dbTester.getDbClient().ceTaskInputDao();
Optional<CeTaskInputDao.DataStream> task1Data = dataDao.selectData(dbTester.getSession(), "TASK_1");
Optional<DbInputStream> task1Data = dataDao.selectData(dbTester.getSession(), "TASK_1");
assertThat(task1Data).isPresent();
task1Data.get().close();


+ 93
- 0
server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ClearActionTest.java Wyświetl plik

@@ -0,0 +1,93 @@
/*
* 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.scannercache.ws;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbInputStream;
import org.sonar.db.DbTester;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.scannercache.ScannerCacheDao;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.scannercache.ScannerCache;
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.sonar.api.web.UserRole.SCAN;

public class ClearActionTest {
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);

private final ScannerCacheDao dao = new ScannerCacheDao();
private final ScannerCache cache = new ScannerCache(dbTester.getDbClient(), dao);
private final ClearAction ws = new ClearAction(userSession, cache);
private final WsActionTester wsTester = new WsActionTester(ws);

@Test
public void should_clear_all_entries() throws IOException {
ProjectDto project1 = dbTester.components().insertPrivateProjectDto();
ProjectDto project2 = dbTester.components().insertPrivateProjectDto();

dao.insert(dbTester.getSession(), project1.getUuid(), stringToInputStream("test data"));
dao.insert(dbTester.getSession(), project2.getUuid(), stringToInputStream("test data"));

assertThat(dataStreamToString(dao.selectData(dbTester.getSession(), project1.getUuid()))).isEqualTo("test data");
userSession.logIn().addPermission(GlobalPermission.ADMINISTER);
TestResponse response = wsTester.newRequest().execute();

response.assertNoContent();
assertThat(dbTester.countRowsOfTable("scanner_cache")).isZero();
}

@Test
public void fail_if_not_global_admin() throws IOException {
ProjectDto project = dbTester.components().insertPrivateProjectDto();
dao.insert(dbTester.getSession(), "branch1", stringToInputStream("test data"));
assertThat(dataStreamToString(dao.selectData(dbTester.getSession(), "branch1"))).isEqualTo("test data");
userSession.logIn().addProjectPermission(SCAN, project);
TestRequest request = wsTester.newRequest();

assertThatThrownBy(request::execute).isInstanceOf(ForbiddenException.class);
}

private static String dataStreamToString(DbInputStream dbInputStream) throws IOException {
try (DbInputStream ds = dbInputStream) {
return IOUtils.toString(ds, StandardCharsets.UTF_8);
}
}

private static InputStream stringToInputStream(String str) {
return new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
}
}

+ 158
- 0
server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/GetActionTest.java Wyświetl plik

@@ -0,0 +1,158 @@
/*
* 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.scannercache.ws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.scannercache.ScannerCacheDao;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.scannercache.ScannerCache;
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 java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.api.web.UserRole.SCAN;

public class GetActionTest {
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);

private final ScannerCacheDao dao = new ScannerCacheDao();
private final ScannerCache cache = new ScannerCache(dbTester.getDbClient(), dao);
private final ComponentFinder finder = new ComponentFinder(dbTester.getDbClient(), null);
private final GetAction ws = new GetAction(dbTester.getDbClient(), userSession, finder, cache);
private final WsActionTester wsTester = new WsActionTester(ws);

@Test
public void get_data_for_project() throws IOException {
ProjectDto project1 = dbTester.components().insertPrivateProjectDto();
BranchDto branch = dbTester.components().insertProjectBranch(project1);
ProjectDto project2 = dbTester.components().insertPrivateProjectDto();

dao.insert(dbTester.getSession(), project1.getUuid(), stringToCompressedInputStream("test data1"));
dao.insert(dbTester.getSession(), branch.getUuid(), stringToCompressedInputStream("test data2"));
dao.insert(dbTester.getSession(), project2.getUuid(), stringToCompressedInputStream("test data3"));

userSession.logIn().addProjectPermission(SCAN, project1);
TestResponse response = wsTester.newRequest()
.setParam("project", project1.getKey())
.setHeader("Accept-Encoding", "gzip")
.execute();

assertThat(compressedInputStreamToString(response.getInputStream())).isEqualTo("test data1");
assertThat(response.getHeader("Content-Encoding")).isEqualTo("gzip");
}

@Test
public void get_uncompressed_data_for_project() throws IOException {
ProjectDto project1 = dbTester.components().insertPrivateProjectDto();

dao.insert(dbTester.getSession(), project1.getUuid(), stringToCompressedInputStream("test data1"));

userSession.logIn().addProjectPermission(SCAN, project1);

TestResponse response = wsTester.newRequest()
.setParam("project", project1.getKey())
.execute();

assertThat(response.getHeader("Content-Encoding")).isNull();
assertThat(response.getInput()).isEqualTo("test data1");
}

@Test
public void get_data_for_branch() throws IOException {
ProjectDto project1 = dbTester.components().insertPrivateProjectDto();
BranchDto branch = dbTester.components().insertProjectBranch(project1);

dao.insert(dbTester.getSession(), project1.getUuid(), stringToCompressedInputStream("test data1"));
dao.insert(dbTester.getSession(), branch.getUuid(), stringToCompressedInputStream("test data2"));

userSession.logIn().addProjectPermission(SCAN, project1);
TestResponse response = wsTester.newRequest()
.setParam("project", project1.getKey())
.setParam("branch", branch.getKey())
.setHeader("Accept-Encoding", "gzip")
.execute();

assertThat(compressedInputStreamToString(response.getInputStream())).isEqualTo("test data2");
}

@Test
public void return_not_found_if_project_not_found() {
TestRequest request = wsTester
.newRequest()
.setParam("project", "project1");
assertThatThrownBy(request::execute).isInstanceOf(NotFoundException.class);
}

@Test
public void return_not_found_if_cache_not_found() {
ProjectDto project1 = dbTester.components().insertPrivateProjectDto();

userSession.logIn().addProjectPermission(SCAN, project1);
TestRequest request = wsTester
.newRequest()
.setParam("project", "project1");
assertThatThrownBy(request::execute).isInstanceOf(NotFoundException.class);
}

@Test
public void fail_if_no_permissions() {
ProjectDto project = dbTester.components().insertPrivateProjectDto();
userSession.logIn().addProjectPermission(UserRole.CODEVIEWER, project);
TestRequest request = wsTester
.newRequest()
.setParam("project", project.getKey());

assertThatThrownBy(request::execute).isInstanceOf(ForbiddenException.class);
}

private static String compressedInputStreamToString(InputStream inputStream) throws IOException {
return IOUtils.toString(new GZIPInputStream(inputStream), UTF_8);
}

private static InputStream stringToCompressedInputStream(String str) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
IOUtils.write(str.getBytes(UTF_8), gzipOutputStream);
}
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
}

+ 35
- 0
server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ScannerCacheWsModuleTest.java Wyświetl plik

@@ -0,0 +1,35 @@
/*
* 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.scannercache.ws;

import org.junit.Test;
import org.sonar.core.platform.ListContainer;

import static org.assertj.core.api.Assertions.assertThat;

public class ScannerCacheWsModuleTest {
@Test
public void verify_count_of_added_components() {
ListContainer container = new ListContainer();
new ScannerCacheWsModule().configure(container);
assertThat(container.getAddedObjects()).hasSize(3);
}

}

+ 56
- 0
server/sonar-webserver-webapi/src/test/java/org/sonar/server/scannercache/ws/ScannerCacheWsTest.java Wyświetl plik

@@ -0,0 +1,56 @@
/*
* 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.scannercache.ws;

import org.junit.Test;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;

import static org.assertj.core.api.Assertions.assertThat;

public class ScannerCacheWsTest {
@Test
public void define_ws() {
ScannerCacheWsAction action = new FakeAction();
ScannerCacheWs underTest = new ScannerCacheWs(action);
WebService.Context context = new WebService.Context();

underTest.define(context);

WebService.Controller controller = context.controller("api/scanner_cache");
assertThat(controller).isNotNull();
assertThat(controller.since()).isEqualTo("9.4");
assertThat(controller.description()).isNotEmpty();
assertThat(controller.actions()).hasSize(1);
}

private static class FakeAction implements ScannerCacheWsAction {
@Override
public void define(WebService.NewController newController) {
newController.createAction("fake").setHandler(this);
}

@Override
public void handle(Request request, Response response) throws Exception {

}
}
}

+ 6
- 0
server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java Wyświetl plik

@@ -221,6 +221,8 @@ import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.rule.ws.RuleWsSupport;
import org.sonar.server.rule.ws.RulesWs;
import org.sonar.server.rule.ws.TagsAction;
import org.sonar.server.scannercache.ScannerCache;
import org.sonar.server.scannercache.ws.ScannerCacheWsModule;
import org.sonar.server.setting.ProjectConfigurationLoaderImpl;
import org.sonar.server.setting.SettingsChangeNotifier;
import org.sonar.server.setting.ws.SettingsWsModule;
@@ -523,6 +525,10 @@ public class PlatformLevel4 extends PlatformLevel {
CancelAllAction.class,
PluginsWs.class,

// Scanner Cache
ScannerCache.class,
new ScannerCacheWsModule(),

// ALM integrations
TimeoutConfigurationImpl.class,
CredentialsEncoderHelper.class,

Ładowanie…
Anuluj
Zapisz