Guard import log

This commit is contained in:
René Pfeuffer
2021-02-23 13:21:33 +01:00
parent 8170d981cd
commit 8f5fcf6911
2 changed files with 86 additions and 12 deletions

View File

@@ -24,7 +24,11 @@
package sonia.scm.importexport;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import sonia.scm.NotFoundException;
import sonia.scm.store.DataStore;
import sonia.scm.store.DataStoreFactory;
import javax.inject.Inject;
@@ -45,7 +49,9 @@ public class RepositoryImportLoggerFactory {
}
public void getLog(String logId, OutputStream out) {
RepositoryImportLog log = dataStoreFactory.withType(RepositoryImportLog.class).withName("imports").build().getOptional(logId).orElseThrow(() -> new NotFoundException("Log", logId));
DataStore<RepositoryImportLog> importStore = dataStoreFactory.withType(RepositoryImportLog.class).withName("imports").build();
RepositoryImportLog log = importStore.getOptional(logId).orElseThrow(() -> new NotFoundException("Log", logId));
checkPermission(log);
PrintStream printStream = new PrintStream(out);
log.toLogHeader().forEach(printStream::println);
log.getEntries()
@@ -53,4 +59,11 @@ public class RepositoryImportLoggerFactory {
.map(RepositoryImportLog.Entry::toLogMessage)
.forEach(printStream::println);
}
private void checkPermission(RepositoryImportLog log) {
Subject subject = SecurityUtils.getSubject();
if (!subject.isPermitted("only:admin:allowed") && !subject.getPrincipal().toString().equals(log.getUserId())) {
throw new AuthorizationException("not permitted");
}
}
}

View File

@@ -24,6 +24,11 @@
package sonia.scm.importexport;
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.Test;
import sonia.scm.NotFoundException;
import sonia.scm.store.InMemoryDataStore;
@@ -33,26 +38,55 @@ import java.io.ByteArrayOutputStream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class RepositoryImportLoggerFactoryTest {
private final Subject subject = mock(Subject.class);
private final InMemoryDataStore<RepositoryImportLog> store = new InMemoryDataStore<>();
private final RepositoryImportLoggerFactory factory = new RepositoryImportLoggerFactory(new InMemoryDataStoreFactory(store));
@BeforeEach
void initSubject() {
ThreadContext.bind(subject);
}
@AfterEach
void cleanupSubject() {
ThreadContext.unbindSubject();
}
@Test
void shouldReadLog() {
RepositoryImportLog log = new RepositoryImportLog();
log.setRepositoryType("git");
log.setNamespace("hitchhiker");
log.setName("HeartOfGold");
log.setUserId("dent");
log.setUserName("Arthur Dent");
log.setSuccess(true);
void shouldReadLogForExportingUser() {
when(subject.getPrincipal()).thenReturn("dent");
log.addEntry(new RepositoryImportLog.Entry("import started"));
log.addEntry(new RepositoryImportLog.Entry("import finished"));
createLog();
store.put("42", log);
ByteArrayOutputStream out = new ByteArrayOutputStream();
factory.getLog("42", out);
assertThat(out).asString().contains(
"Import of repository hitchhiker/HeartOfGold",
"Repository type: null",
"Imported from: null",
"Imported by dent (Arthur Dent)",
"Finished successful"
)
.containsPattern(".+ - import started")
.containsPattern(".+ - import finished");
}
@Test
void shouldReadLogForAdmin() {
when(subject.getPrincipal()).thenReturn("trillian");
when(subject.isPermitted(anyString())).thenReturn(true);
createLog();
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -75,4 +109,31 @@ class RepositoryImportLoggerFactoryTest {
assertThrows(NotFoundException.class, () -> factory.getLog("42", out));
}
@Test
void shouldFailWithoutPermission() {
when(subject.getPrincipal()).thenReturn("trillian");
createLog();
doThrow(AuthorizationException.class).when(subject).checkPermission("only:admin:allowed");
ByteArrayOutputStream out = new ByteArrayOutputStream();
assertThrows(AuthorizationException.class, () -> factory.getLog("42", out));
}
private void createLog() {
RepositoryImportLog log = new RepositoryImportLog();
log.setRepositoryType("git");
log.setNamespace("hitchhiker");
log.setName("HeartOfGold");
log.setUserId("dent");
log.setUserName("Arthur Dent");
log.setSuccess(true);
log.addEntry(new RepositoryImportLog.Entry("import started"));
log.addEntry(new RepositoryImportLog.Entry("import finished"));
store.put("42", log);
}
}