mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
merge
This commit is contained in:
@@ -8,6 +8,7 @@ import de.otto.edison.hal.Links;
|
|||||||
import sonia.scm.plugin.AvailablePlugin;
|
import sonia.scm.plugin.AvailablePlugin;
|
||||||
import sonia.scm.plugin.InstalledPlugin;
|
import sonia.scm.plugin.InstalledPlugin;
|
||||||
import sonia.scm.plugin.PluginManager;
|
import sonia.scm.plugin.PluginManager;
|
||||||
|
import sonia.scm.plugin.PluginPermissions;
|
||||||
import sonia.scm.web.VndMediaType;
|
import sonia.scm.web.VndMediaType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -68,8 +69,12 @@ public class PendingPluginResource {
|
|||||||
List<PluginDto> updateDtos = updatePlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList());
|
List<PluginDto> updateDtos = updatePlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList());
|
||||||
List<PluginDto> uninstallDtos = uninstallPlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList());
|
List<PluginDto> uninstallDtos = uninstallPlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList());
|
||||||
|
|
||||||
if (!installDtos.isEmpty() || !updateDtos.isEmpty() || !uninstallDtos.isEmpty()) {
|
if (
|
||||||
|
PluginPermissions.manage().isPermitted() &&
|
||||||
|
(!installDtos.isEmpty() || !updateDtos.isEmpty() || !uninstallDtos.isEmpty())
|
||||||
|
) {
|
||||||
linksBuilder.single(link("execute", resourceLinks.pendingPluginCollection().executePending()));
|
linksBuilder.single(link("execute", resourceLinks.pendingPluginCollection().executePending()));
|
||||||
|
linksBuilder.single(link("cancel", resourceLinks.pendingPluginCollection().cancelPending()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Embedded.Builder embedded = Embedded.embeddedBuilder();
|
Embedded.Builder embedded = Embedded.embeddedBuilder();
|
||||||
|
|||||||
@@ -743,6 +743,10 @@ class ResourceLinks {
|
|||||||
return pendingPluginCollectionLinkBuilder.method("pendingPlugins").parameters().method("executePending").parameters().href();
|
return pendingPluginCollectionLinkBuilder.method("pendingPlugins").parameters().method("executePending").parameters().href();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String cancelPending() {
|
||||||
|
return pendingPluginCollectionLinkBuilder.method("pendingPlugins").parameters().method("cancelPending").parameters().href();
|
||||||
|
}
|
||||||
|
|
||||||
String self() {
|
String self() {
|
||||||
return pendingPluginCollectionLinkBuilder.method("pendingPlugins").parameters().method("getPending").parameters().href();
|
return pendingPluginCollectionLinkBuilder.method("pendingPlugins").parameters().method("getPending").parameters().href();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import com.google.inject.util.Providers;
|
import com.google.inject.util.Providers;
|
||||||
|
import org.apache.shiro.ShiroException;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.apache.shiro.util.ThreadContext;
|
||||||
import org.jboss.resteasy.core.Dispatcher;
|
import org.jboss.resteasy.core.Dispatcher;
|
||||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -19,6 +24,8 @@ import sonia.scm.plugin.PluginInformation;
|
|||||||
import sonia.scm.plugin.PluginManager;
|
import sonia.scm.plugin.PluginManager;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
@@ -44,6 +51,9 @@ class PendingPluginResourceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
PluginDtoMapper mapper;
|
PluginDtoMapper mapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Subject subject;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
PendingPluginResource pendingPluginResource;
|
PendingPluginResource pendingPluginResource;
|
||||||
|
|
||||||
@@ -52,6 +62,7 @@ class PendingPluginResourceTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
void prepareEnvironment() {
|
void prepareEnvironment() {
|
||||||
dispatcher = MockDispatcherFactory.createDispatcher();
|
dispatcher = MockDispatcherFactory.createDispatcher();
|
||||||
|
dispatcher.getProviderFactory().register(new PermissionExceptionMapper());
|
||||||
PluginRootResource pluginRootResource = new PluginRootResource(null, null, Providers.of(pendingPluginResource));
|
PluginRootResource pluginRootResource = new PluginRootResource(null, null, Providers.of(pendingPluginResource));
|
||||||
dispatcher.getRegistry().addSingletonResource(pluginRootResource);
|
dispatcher.getRegistry().addSingletonResource(pluginRootResource);
|
||||||
}
|
}
|
||||||
@@ -70,83 +81,138 @@ class PendingPluginResourceTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Nested
|
||||||
void shouldGetEmptyPluginListsWithoutInstallLinkWhenNoPendingPluginsPresent() throws URISyntaxException, UnsupportedEncodingException {
|
class withAuthorization {
|
||||||
AvailablePlugin availablePlugin = createAvailablePlugin("not-pending-plugin");
|
|
||||||
when(availablePlugin.isPending()).thenReturn(false);
|
|
||||||
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
@BeforeEach
|
||||||
dispatcher.invoke(request, response);
|
void bindSubject() {
|
||||||
|
ThreadContext.bind(subject);
|
||||||
|
lenient().when(subject.isPermitted("plugin:manage")).thenReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void unbindSubject() {
|
||||||
|
ThreadContext.unbindSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetEmptyPluginListsWithoutInstallLinkWhenNoPendingPluginsPresent() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
|
AvailablePlugin availablePlugin = createAvailablePlugin("not-pending-plugin");
|
||||||
|
when(availablePlugin.isPending()).thenReturn(false);
|
||||||
|
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
||||||
|
|
||||||
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
assertThat(response.getContentAsString()).contains("\"_links\":{\"self\":{\"href\":\"/v2/plugins/pending\"}}");
|
||||||
|
assertThat(response.getContentAsString()).doesNotContain("not-pending-plugin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetPendingAvailablePluginListWithInstallAndCancelLink() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
|
AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin");
|
||||||
|
when(availablePlugin.isPending()).thenReturn(true);
|
||||||
|
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
||||||
|
|
||||||
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
assertThat(response.getContentAsString()).contains("\"new\":[{\"name\":\"pending-available-plugin\"");
|
||||||
|
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
||||||
|
assertThat(response.getContentAsString()).contains("\"cancel\":{\"href\":\"/v2/plugins/pending/cancel\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetPendingUpdatePluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
|
AvailablePlugin availablePlugin = createAvailablePlugin("available-plugin");
|
||||||
|
when(availablePlugin.isPending()).thenReturn(true);
|
||||||
|
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
||||||
|
InstalledPlugin installedPlugin = createInstalledPlugin("available-plugin");
|
||||||
|
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
|
||||||
|
|
||||||
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
assertThat(response.getContentAsString()).contains("\"update\":[{\"name\":\"available-plugin\"");
|
||||||
|
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetPendingUninstallPluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
|
when(pluginManager.getAvailable()).thenReturn(emptyList());
|
||||||
|
InstalledPlugin installedPlugin = createInstalledPlugin("uninstalled-plugin");
|
||||||
|
when(installedPlugin.isMarkedForUninstall()).thenReturn(true);
|
||||||
|
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
|
||||||
|
|
||||||
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
assertThat(response.getContentAsString()).contains("\"uninstall\":[{\"name\":\"uninstalled-plugin\"");
|
||||||
|
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldExecutePendingPlugins() throws URISyntaxException {
|
||||||
|
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/pending/execute");
|
||||||
|
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
verify(pluginManager).executePendingAndRestart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCancelPendingPlugins() throws URISyntaxException {
|
||||||
|
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/pending/cancel");
|
||||||
|
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
verify(pluginManager).cancelPending();
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
|
||||||
assertThat(response.getContentAsString()).contains("\"_links\":{\"self\":{\"href\":\"/v2/plugins/pending\"}}");
|
|
||||||
assertThat(response.getContentAsString()).doesNotContain("not-pending-plugin");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Nested
|
||||||
void shouldGetPendingAvailablePluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
|
class WithoutAuthorization {
|
||||||
AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin");
|
|
||||||
when(availablePlugin.isPending()).thenReturn(true);
|
|
||||||
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
@BeforeEach
|
||||||
dispatcher.invoke(request, response);
|
void bindSubject() {
|
||||||
|
ThreadContext.bind(subject);
|
||||||
|
when(subject.isPermitted("plugin:manage")).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
@AfterEach
|
||||||
assertThat(response.getContentAsString()).contains("\"new\":[{\"name\":\"pending-available-plugin\"");
|
void unbindSubject() {
|
||||||
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
ThreadContext.unbindSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetPendingAvailablePluginListWithoutInstallAndCancelLink() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
|
AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin");
|
||||||
|
when(availablePlugin.isPending()).thenReturn(true);
|
||||||
|
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
||||||
|
|
||||||
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
||||||
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
assertThat(response.getContentAsString()).contains("\"new\":[{\"name\":\"pending-available-plugin\"");
|
||||||
|
assertThat(response.getContentAsString()).doesNotContain("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
||||||
|
assertThat(response.getContentAsString()).doesNotContain("\"cancel\":{\"href\":\"/v2/plugins/pending/cancel\"}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
static class PermissionExceptionMapper implements ExceptionMapper<ShiroException> {
|
||||||
void shouldGetPendingUpdatePluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
|
|
||||||
AvailablePlugin availablePlugin = createAvailablePlugin("available-plugin");
|
|
||||||
when(availablePlugin.isPending()).thenReturn(true);
|
|
||||||
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
|
|
||||||
InstalledPlugin installedPlugin = createInstalledPlugin("available-plugin");
|
|
||||||
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
|
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
@Override
|
||||||
dispatcher.invoke(request, response);
|
public Response toResponse(ShiroException exception) {
|
||||||
|
return Response.status(401).entity(exception.getMessage()).build();
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
}
|
||||||
assertThat(response.getContentAsString()).contains("\"update\":[{\"name\":\"available-plugin\"");
|
|
||||||
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldGetPendingUninstallPluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
|
|
||||||
when(pluginManager.getAvailable()).thenReturn(emptyList());
|
|
||||||
InstalledPlugin installedPlugin = createInstalledPlugin("uninstalled-plugin");
|
|
||||||
when(installedPlugin.isMarkedForUninstall()).thenReturn(true);
|
|
||||||
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
|
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
|
|
||||||
dispatcher.invoke(request, response);
|
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
|
||||||
assertThat(response.getContentAsString()).contains("\"uninstall\":[{\"name\":\"uninstalled-plugin\"");
|
|
||||||
assertThat(response.getContentAsString()).contains("\"execute\":{\"href\":\"/v2/plugins/pending/execute\"}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldExecutePendingPlugins() throws URISyntaxException {
|
|
||||||
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/pending/execute");
|
|
||||||
|
|
||||||
dispatcher.invoke(request, response);
|
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
|
||||||
verify(pluginManager).executePendingAndRestart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldCancelPendingPlugins() throws URISyntaxException {
|
|
||||||
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/pending/cancel");
|
|
||||||
|
|
||||||
dispatcher.invoke(request, response);
|
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
|
||||||
verify(pluginManager).cancelPending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AvailablePlugin createAvailablePlugin(String name) {
|
private AvailablePlugin createAvailablePlugin(String name) {
|
||||||
|
|||||||
Reference in New Issue
Block a user