implemented permission checks

This commit is contained in:
Sebastian Sdorra
2019-08-21 09:25:44 +02:00
parent de7d18e026
commit 5694a953af
3 changed files with 222 additions and 133 deletions

View File

@@ -81,7 +81,7 @@ public class AvailablePluginResource {
/**
* Triggers plugin installation.
* @param name plugin artefact name
* @param name plugin name
* @return HTTP Status.
*/
@POST

View File

@@ -74,6 +74,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public Optional<AvailablePlugin> getAvailable(String name) {
PluginPermissions.read().check();
return center.getAvailable()
.stream()
.filter(filterByName(name))
@@ -83,6 +84,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public Optional<InstalledPlugin> getInstalled(String name) {
PluginPermissions.read().check();
return loader.getInstalledPlugins()
.stream()
.filter(filterByName(name))
@@ -91,11 +93,13 @@ public class DefaultPluginManager implements PluginManager {
@Override
public List<InstalledPlugin> getInstalled() {
PluginPermissions.read().check();
return ImmutableList.copyOf(loader.getInstalledPlugins());
}
@Override
public List<AvailablePlugin> getAvailable() {
PluginPermissions.read().check();
return center.getAvailable().stream().filter(this::isNotInstalled).collect(Collectors.toList());
}
@@ -109,6 +113,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void install(String name) {
PluginPermissions.manage().check();
List<AvailablePlugin> plugins = collectPluginsToInstall(name);
List<PendingPluginInstallation> pendingInstallations = new ArrayList<>();
for (AvailablePlugin plugin : plugins) {
@@ -131,6 +136,7 @@ public class DefaultPluginManager implements PluginManager {
collectPluginsToInstall(plugins, name);
return plugins;
}
private void collectPluginsToInstall(List<AvailablePlugin> plugins, String name) {
if (!getInstalled(name).isPresent()) {
AvailablePlugin plugin = getAvailable(name).orElseThrow(() -> NotFoundException.notFound(entity(AvailablePlugin.class, name)));

View File

@@ -2,12 +2,19 @@ package sonia.scm.plugin;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.NotFoundException;
import java.util.List;
import java.util.Optional;
@@ -31,6 +38,22 @@ class DefaultPluginManagerTest {
@InjectMocks
private DefaultPluginManager manager;
@Mock
private Subject subject;
@Nested
class WithAdminPermissions {
@BeforeEach
void setUpSubject() {
ThreadContext.bind(subject);
}
@AfterEach
void clearThreadContext() {
ThreadContext.unbindSubject();
}
@Test
void shouldReturnInstalledPlugins() {
InstalledPlugin review = createInstalled("scm-review-plugin");
@@ -177,6 +200,66 @@ class DefaultPluginManagerTest {
verify(pendingMail).cancel();
}
@Test
void shouldInstallNothingIfOneOfTheDependenciesIsNotAvailable() {
AvailablePlugin review = createAvailable("scm-review-plugin");
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
AvailablePlugin mail = createAvailable("scm-mail-plugin");
when(mail.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-notification-plugin"));
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail));
assertThrows(NotFoundException.class, () -> manager.install("scm-review-plugin"));
verify(installer, never()).install(any());
}
}
@Nested
class WithoutReadPermissions {
@BeforeEach
void setUpSubject() {
ThreadContext.bind(subject);
doThrow(AuthorizationException.class).when(subject).checkPermission("plugin:read");
}
@AfterEach
void clearThreadContext() {
ThreadContext.unbindSubject();
}
@Test
void shouldThrowAuthorizationExceptionsForReadMethods() {
assertThrows(AuthorizationException.class, () -> manager.getInstalled());
assertThrows(AuthorizationException.class, () -> manager.getInstalled("test"));
assertThrows(AuthorizationException.class, () -> manager.getAvailable());
assertThrows(AuthorizationException.class, () -> manager.getAvailable("test"));
}
}
@Nested
class WithoutManagePermissions {
@BeforeEach
void setUpSubject() {
ThreadContext.bind(subject);
doThrow(AuthorizationException.class).when(subject).checkPermission("plugin:manage");
}
@AfterEach
void clearThreadContext() {
ThreadContext.unbindSubject();
}
@Test
void shouldThrowAuthorizationExceptionsForInstallMethod() {
assertThrows(AuthorizationException.class, () -> manager.install("test"));
}
}
private AvailablePlugin createAvailable(String name) {
PluginInformation information = new PluginInformation();
information.setName(name);