mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 07:25:44 +01:00
implemented permission checks
This commit is contained in:
@@ -81,7 +81,7 @@ public class AvailablePluginResource {
|
||||
|
||||
/**
|
||||
* Triggers plugin installation.
|
||||
* @param name plugin artefact name
|
||||
* @param name plugin name
|
||||
* @return HTTP Status.
|
||||
*/
|
||||
@POST
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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,150 +38,226 @@ class DefaultPluginManagerTest {
|
||||
@InjectMocks
|
||||
private DefaultPluginManager manager;
|
||||
|
||||
@Test
|
||||
void shouldReturnInstalledPlugins() {
|
||||
InstalledPlugin review = createInstalled("scm-review-plugin");
|
||||
InstalledPlugin git = createInstalled("scm-git-plugin");
|
||||
@Mock
|
||||
private Subject subject;
|
||||
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(review, git));
|
||||
@Nested
|
||||
class WithAdminPermissions {
|
||||
|
||||
@BeforeEach
|
||||
void setUpSubject() {
|
||||
ThreadContext.bind(subject);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearThreadContext() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnInstalledPlugins() {
|
||||
InstalledPlugin review = createInstalled("scm-review-plugin");
|
||||
InstalledPlugin git = createInstalled("scm-git-plugin");
|
||||
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(review, git));
|
||||
|
||||
List<InstalledPlugin> installed = manager.getInstalled();
|
||||
assertThat(installed).containsOnly(review, git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnReviewPlugin() {
|
||||
InstalledPlugin review = createInstalled("scm-review-plugin");
|
||||
InstalledPlugin git = createInstalled("scm-git-plugin");
|
||||
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(review, git));
|
||||
|
||||
Optional<InstalledPlugin> plugin = manager.getInstalled("scm-review-plugin");
|
||||
assertThat(plugin).contains(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForNonInstalledPlugin() {
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of());
|
||||
|
||||
Optional<InstalledPlugin> plugin = manager.getInstalled("scm-review-plugin");
|
||||
assertThat(plugin).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnAvailablePlugins() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
|
||||
List<AvailablePlugin> available = manager.getAvailable();
|
||||
assertThat(available).containsOnly(review, git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFilterOutAllInstalled() {
|
||||
InstalledPlugin installedGit = createInstalled("scm-git-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedGit));
|
||||
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
|
||||
List<AvailablePlugin> available = manager.getAvailable();
|
||||
assertThat(available).containsOnly(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnAvailable() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).contains(git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForNonExistingAvailable() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForInstalledPlugin() {
|
||||
InstalledPlugin installedGit = createInstalled("scm-git-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedGit));
|
||||
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(git));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInstallThePlugin() {
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(git));
|
||||
|
||||
manager.install("scm-git-plugin");
|
||||
|
||||
verify(installer).install(git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInstallDependingPlugins() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
|
||||
AvailablePlugin mail = createAvailable("scm-mail-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail));
|
||||
|
||||
manager.install("scm-review-plugin");
|
||||
|
||||
verify(installer).install(mail);
|
||||
verify(installer).install(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotInstallAlreadyInstalledDependencies() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
|
||||
AvailablePlugin mail = createAvailable("scm-mail-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail));
|
||||
|
||||
InstalledPlugin installedMail = createInstalled("scm-mail-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedMail));
|
||||
|
||||
manager.install("scm-review-plugin");
|
||||
|
||||
verify(installer).install(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRollbackOnFailedInstallation() {
|
||||
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"));
|
||||
AvailablePlugin notification = createAvailable("scm-notification-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail, notification));
|
||||
|
||||
PendingPluginInstallation pendingNotification = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingNotification).when(installer).install(notification);
|
||||
|
||||
PendingPluginInstallation pendingMail = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingMail).when(installer).install(mail);
|
||||
|
||||
doThrow(new PluginChecksumMismatchException("checksum does not match")).when(installer).install(review);
|
||||
|
||||
assertThrows(PluginInstallException.class, () -> manager.install("scm-review-plugin"));
|
||||
|
||||
verify(pendingNotification).cancel();
|
||||
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());
|
||||
}
|
||||
|
||||
List<InstalledPlugin> installed = manager.getInstalled();
|
||||
assertThat(installed).containsOnly(review, git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnReviewPlugin() {
|
||||
InstalledPlugin review = createInstalled("scm-review-plugin");
|
||||
InstalledPlugin git = createInstalled("scm-git-plugin");
|
||||
@Nested
|
||||
class WithoutReadPermissions {
|
||||
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(review, git));
|
||||
@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"));
|
||||
}
|
||||
|
||||
Optional<InstalledPlugin> plugin = manager.getInstalled("scm-review-plugin");
|
||||
assertThat(plugin).contains(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForNonInstalledPlugin() {
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of());
|
||||
@Nested
|
||||
class WithoutManagePermissions {
|
||||
|
||||
Optional<InstalledPlugin> plugin = manager.getInstalled("scm-review-plugin");
|
||||
assertThat(plugin).isEmpty();
|
||||
}
|
||||
@BeforeEach
|
||||
void setUpSubject() {
|
||||
ThreadContext.bind(subject);
|
||||
doThrow(AuthorizationException.class).when(subject).checkPermission("plugin:manage");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnAvailablePlugins() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
@AfterEach
|
||||
void clearThreadContext() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
@Test
|
||||
void shouldThrowAuthorizationExceptionsForInstallMethod() {
|
||||
assertThrows(AuthorizationException.class, () -> manager.install("test"));
|
||||
}
|
||||
|
||||
List<AvailablePlugin> available = manager.getAvailable();
|
||||
assertThat(available).containsOnly(review, git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFilterOutAllInstalled() {
|
||||
InstalledPlugin installedGit = createInstalled("scm-git-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedGit));
|
||||
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
|
||||
List<AvailablePlugin> available = manager.getAvailable();
|
||||
assertThat(available).containsOnly(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnAvailable() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, git));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).contains(git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForNonExistingAvailable() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyForInstalledPlugin() {
|
||||
InstalledPlugin installedGit = createInstalled("scm-git-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedGit));
|
||||
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(git));
|
||||
|
||||
Optional<AvailablePlugin> available = manager.getAvailable("scm-git-plugin");
|
||||
assertThat(available).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInstallThePlugin() {
|
||||
AvailablePlugin git = createAvailable("scm-git-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(git));
|
||||
|
||||
manager.install("scm-git-plugin");
|
||||
|
||||
verify(installer).install(git);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInstallDependingPlugins() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
|
||||
AvailablePlugin mail = createAvailable("scm-mail-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail));
|
||||
|
||||
manager.install("scm-review-plugin");
|
||||
|
||||
verify(installer).install(mail);
|
||||
verify(installer).install(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotInstallAlreadyInstalledDependencies() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
|
||||
AvailablePlugin mail = createAvailable("scm-mail-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail));
|
||||
|
||||
InstalledPlugin installedMail = createInstalled("scm-mail-plugin");
|
||||
when(loader.getInstalledPlugins()).thenReturn(ImmutableList.of(installedMail));
|
||||
|
||||
manager.install("scm-review-plugin");
|
||||
|
||||
verify(installer).install(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRollbackOnFailedInstallation() {
|
||||
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"));
|
||||
AvailablePlugin notification = createAvailable("scm-notification-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail, notification));
|
||||
|
||||
PendingPluginInstallation pendingNotification = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingNotification).when(installer).install(notification);
|
||||
|
||||
PendingPluginInstallation pendingMail = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingMail).when(installer).install(mail);
|
||||
|
||||
doThrow(new PluginChecksumMismatchException("checksum does not match")).when(installer).install(review);
|
||||
|
||||
assertThrows(PluginInstallException.class, () -> manager.install("scm-review-plugin"));
|
||||
|
||||
verify(pendingNotification).cancel();
|
||||
verify(pendingMail).cancel();
|
||||
}
|
||||
|
||||
private AvailablePlugin createAvailable(String name) {
|
||||
|
||||
Reference in New Issue
Block a user