Browse Source

SONAR-14094 Fix SSF-131

tags/7.9.5
Julien Lancelot 3 years ago
parent
commit
1732476099

+ 0
- 2
server/sonar-server/src/main/java/org/sonar/server/updatecenter/UpdateCenterModule.java View File

@@ -24,7 +24,6 @@ import org.sonar.server.plugins.UpdateCenterClient;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.updatecenter.ws.InstalledPluginsAction;
import org.sonar.server.updatecenter.ws.UpdateCenterWs;
import org.sonar.server.updatecenter.ws.UploadAction;

public class UpdateCenterModule extends Module {
@Override
@@ -32,7 +31,6 @@ public class UpdateCenterModule extends Module {
add(
UpdateCenterClient.class,
UpdateCenterMatrixFactory.class,
UploadAction.class,
InstalledPluginsAction.class,
UpdateCenterWs.class);
}

+ 6
- 0
server/sonar-server/src/main/java/org/sonar/server/updatecenter/ws/UpdateCenterWs.java View File

@@ -21,6 +21,7 @@ package org.sonar.server.updatecenter.ws;

import java.util.Arrays;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.ws.RemovedWebServiceHandler;

public class UpdateCenterWs implements WebService {

@@ -35,6 +36,11 @@ public class UpdateCenterWs implements WebService {
NewController controller = context.createController("api/updatecenter")
.setDescription("Get list of installed plugins")
.setSince("2.10");
controller.createAction("upload")
.setDescription("This web service is removed")
.setSince("6.0")
.setHandler(RemovedWebServiceHandler.INSTANCE)
.setResponseExample(RemovedWebServiceHandler.INSTANCE.getResponseExample());
Arrays.stream(actions).forEach(action -> action.define(controller));
controller.done();
}

+ 0
- 78
server/sonar-server/src/main/java/org/sonar/server/updatecenter/ws/UploadAction.java View File

@@ -1,78 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.updatecenter.ws;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.server.user.UserSession;

import static com.google.common.base.Preconditions.checkArgument;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.apache.commons.io.IOUtils.closeQuietly;
import static org.sonar.api.server.ws.Request.Part;

public class UploadAction implements UpdateCenterWsAction {

public static final String PARAM_FILE = "file";

private final UserSession userSession;
private final File downloadDir;

public UploadAction(UserSession userSession, ServerFileSystem fileSystem) {
this.userSession = userSession;
this.downloadDir = fileSystem.getDownloadedPluginsDir();
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("upload")
.setDescription("Upload a plugin.<br /> Requires 'Administer System' permission.")
.setSince("6.0")
.setPost(true)
.setInternal(true)
.setHandler(this);

action.createParam(PARAM_FILE)
.setDescription("The jar file of the plugin to install")
.setRequired(true);
}

@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkIsSystemAdministrator();

Part part = request.mandatoryParamAsPart(PARAM_FILE);
String fileName = part.getFileName();
checkArgument(fileName.endsWith(".jar"), "Only jar file is allowed");
InputStream inputStream = part.getInputStream();
try {
File destPlugin = new File(downloadDir, fileName);
Files.copy(inputStream, destPlugin.toPath(), REPLACE_EXISTING);
response.noContent();
} finally {
closeQuietly(inputStream);
}
}
}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/updatecenter/UpdateCenterModuleTest.java View File

@@ -29,6 +29,6 @@ public class UpdateCenterModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new UpdateCenterModule().configure(container);
assertThat(container.size()).isEqualTo(2 + 5);
assertThat(container.size()).isGreaterThan(2);
}
}

+ 5
- 7
server/sonar-server/src/test/java/org/sonar/server/updatecenter/ws/UpdateCenterWsTest.java View File

@@ -22,11 +22,9 @@ package org.sonar.server.updatecenter.ws;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.server.ws.WsTester;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class UpdateCenterWsTest {

@@ -34,7 +32,7 @@ public class UpdateCenterWsTest {

@Before
public void setUp() {
tester = new WsTester(new UpdateCenterWs(new UploadAction(null, mock(ServerFileSystem.class))));
tester = new WsTester(new UpdateCenterWs(new InstalledPluginsAction(null)));
}

@Test
@@ -43,18 +41,18 @@ public class UpdateCenterWsTest {
assertThat(controller).isNotNull();
assertThat(controller.since()).isEqualTo("2.10");
assertThat(controller.description()).isNotEmpty();
assertThat(controller.actions()).hasSize(1);
assertThat(controller.actions()).hasSize(2);
}

@Test
public void define_upload_action() {
public void define_installed_plugins_action() {
WebService.Controller controller = tester.controller("api/updatecenter");

WebService.Action action = controller.action("upload");
WebService.Action action = controller.action("installed_plugins");
assertThat(action).isNotNull();
assertThat(action.handler()).isNotNull();
assertThat(action.isInternal()).isTrue();
assertThat(action.isPost()).isTrue();
assertThat(action.isPost()).isFalse();
assertThat(action.params()).hasSize(1);
}
}

+ 0
- 147
server/sonar-server/src/test/java/org/sonar/server/updatecenter/ws/UploadActionTest.java View File

@@ -1,147 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.updatecenter.ws;

import java.io.File;
import java.io.InputStream;
import java.nio.channels.ClosedChannelException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;

import static java.nio.file.Files.newInputStream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.test.ExceptionCauseMatcher.hasType;

public class UploadActionTest {

private static final String PLUGIN_NAME = "plugin.jar";

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Rule
public UserSessionRule userSession = UserSessionRule.standalone();

private ServerFileSystem fileSystem = mock(ServerFileSystem.class);
private File pluginDirectory;
private File plugin = new File(getClass().getResource("UploadActionTest/plugin.jar").getFile());
private WsActionTester wsTester;

@Before
public void setUp() throws Exception {
pluginDirectory = folder.newFolder();
when(fileSystem.getDownloadedPluginsDir()).thenReturn(pluginDirectory);
wsTester = new WsActionTester(new UploadAction(userSession, fileSystem));
}

@Test
public void upload_plugin() throws Exception {
logInAsSystemAdministrator();

TestResponse response = call(newInputStream(plugin.toPath()), PLUGIN_NAME);

assertThat(response.getStatus()).isEqualTo(204);
assertPluginIsUploaded(PLUGIN_NAME);
}

@Test
public void erase_existing_plugin_if_already_exists() throws Exception {
logInAsSystemAdministrator();

File plugin1 = new File(getClass().getResource("UploadActionTest/plugin.jar").getFile());
call(newInputStream(plugin1.toPath()), PLUGIN_NAME);

File plugin2 = new File(getClass().getResource("UploadActionTest/anotherPlugin.jar").getFile());
call(newInputStream(plugin2.toPath()), PLUGIN_NAME);

File result = new File(pluginDirectory, PLUGIN_NAME);
assertThat(result.exists()).isTrue();
assertThat(result.length()).isNotEqualTo(plugin1.length()).isEqualTo(plugin2.length());
}

@Test
public void fail_when_plugin_extension_is_not_jar() throws Exception {
logInAsSystemAdministrator();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only jar file is allowed");
call(newInputStream(plugin.toPath()), "plugin.zip");
}

@Test
public void fail_when_no_files_param() {
logInAsSystemAdministrator();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The 'file' parameter is missing");
wsTester.newRequest().execute();
}

@Test
public void input_stream_should_be_closed() throws Exception {
logInAsSystemAdministrator();

InputStream inputStream = newInputStream(plugin.toPath());
call(inputStream, PLUGIN_NAME);

// As the same InputStream is used, it will fail as it should have been called during the first execution of the WS
expectedException.expectCause(hasType(ClosedChannelException.class));
call(inputStream, PLUGIN_NAME);
}

@Test
public void throw_ForbiddenException_if_not_system_administrator() throws Exception {
userSession.logIn().setNonSystemAdministrator();

expectedException.expect(ForbiddenException.class);
expectedException.expectMessage("Insufficient privileges");

call(newInputStream(plugin.toPath()), PLUGIN_NAME);
}

private TestResponse call(InputStream inputStream, String fileName) {
return wsTester.newRequest()
.setPart("file", inputStream, fileName)
.execute();
}

private void logInAsSystemAdministrator() {
userSession.logIn().setSystemAdministrator();
}

private void assertPluginIsUploaded(String pluginName) {
File result = new File(pluginDirectory, pluginName);
assertThat(result.exists()).isTrue();
}

}

Loading…
Cancel
Save