Merge pull request #1403 from scm-manager/bugfix/anonymous-ssh-clone

Bugfix/anonymous ssh clone
This commit is contained in:
Sebastian Sdorra
2020-11-03 08:40:05 +01:00
committed by GitHub
4 changed files with 75 additions and 9 deletions

View File

@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Internal server error for git sub modules without tree object ([#1397](https://github.com/scm-manager/scm-manager/pull/1397))
- Do not expose subversion commit with id 0 ([#1395](https://github.com/scm-manager/scm-manager/pull/1395))
- Disable cloning repositories via ssh for anonymous users ([#1403](https://github.com/scm-manager/scm-manager/pull/1403))
- SVN diff with property changes ([#1400](https://github.com/scm-manager/scm-manager/pull/1400))
- Branches link in repository overview ([#1404](https://github.com/scm-manager/scm-manager/pull/1404))

View File

@@ -34,6 +34,7 @@ import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryPermissions;
import sonia.scm.repository.spi.RepositoryServiceProvider;
import sonia.scm.repository.work.WorkdirProvider;
import sonia.scm.security.Authentications;
import sonia.scm.user.EMail;
import javax.annotation.Nullable;
@@ -453,7 +454,8 @@ public final class RepositoryService implements Closeable {
public Stream<ScmProtocol> getSupportedProtocols() {
return protocolProviders.stream()
.filter(protocolProvider -> protocolProvider.getType().equals(getRepository().getType()))
.map(this::createProviderInstanceForRepository);
.map(this::createProviderInstanceForRepository)
.filter(protocol -> !Authentications.isAuthenticatedSubjectAnonymous() || protocol.isAnonymousEnabled());
}
@SuppressWarnings({"rawtypes", "java:S3740"})

View File

@@ -40,4 +40,11 @@ public interface ScmProtocol {
* The URL to access the repository providing this protocol.
*/
String getUrl();
/**
* Whether the protocol can be used as an anonymous user.
*/
default boolean isAnonymousEnabled() {
return true;
}
}

View File

@@ -24,7 +24,15 @@
package sonia.scm.repository.api;
import org.junit.Test;
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 org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.SCMContext;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.Repository;
import sonia.scm.repository.spi.HttpScmProtocol;
@@ -42,16 +50,32 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.assertj.core.util.IterableUtil.sizeOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class RepositoryServiceTest {
@ExtendWith(MockitoExtension.class)
class RepositoryServiceTest {
private final RepositoryServiceProvider provider = mock(RepositoryServiceProvider.class);
private final Repository repository = new Repository("", "git", "space", "repo");
private final EMail eMail = new EMail(new ScmConfiguration());
@Mock
private Subject subject;
@BeforeEach
void bindSubject() {
ThreadContext.bind(subject);
}
@AfterEach
void unbindSubject() {
ThreadContext.unbindSubject();
}
@Test
public void shouldReturnMatchingProtocolsFromProvider() {
void shouldReturnMatchingProtocolsFromProvider() {
when(subject.getPrincipal()).thenReturn("Hitchhiker");
RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider()), null, eMail);
Stream<ScmProtocol> supportedProtocols = repositoryService.getSupportedProtocols();
@@ -59,7 +83,17 @@ public class RepositoryServiceTest {
}
@Test
public void shouldFindKnownProtocol() {
void shouldFilterOutNonAnonymousEnabledProtocolsForAnonymousUser() {
when(subject.getPrincipal()).thenReturn(SCMContext.USER_ANONYMOUS);
RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Stream.of(new DummyScmProtocolProvider(), new DummyScmProtocolProvider(false)).collect(Collectors.toSet()), null, eMail);
Stream<ScmProtocol> supportedProtocols = repositoryService.getSupportedProtocols();
assertThat(sizeOf(supportedProtocols.collect(Collectors.toList()))).isEqualTo(1);
}
@Test
void shouldFindKnownProtocol() {
when(subject.getPrincipal()).thenReturn("Hitchhiker");
RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider()), null, eMail);
HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class);
@@ -68,23 +102,44 @@ public class RepositoryServiceTest {
}
@Test
public void shouldFailForUnknownProtocol() {
void shouldFailForUnknownProtocol() {
when(subject.getPrincipal()).thenReturn("Hitchhiker");
RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider()), null, eMail);
assertThrows(IllegalArgumentException.class, () -> repositoryService.getProtocol(UnknownScmProtocol.class));
}
private static class DummyHttpProtocol extends HttpScmProtocol {
public DummyHttpProtocol(Repository repository) {
private final boolean anonymousEnabled;
public DummyHttpProtocol(Repository repository, boolean anonymousEnabled) {
super(repository, "");
this.anonymousEnabled = anonymousEnabled;
}
@Override
public void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) {
}
@Override
public boolean isAnonymousEnabled() {
return anonymousEnabled;
}
}
private static class DummyScmProtocolProvider implements ScmProtocolProvider {
private final boolean anonymousEnabled;
public DummyScmProtocolProvider() {
this(true);
}
public DummyScmProtocolProvider(boolean anonymousEnabled) {
this.anonymousEnabled = anonymousEnabled;
}
@Override
public String getType() {
return "git";
@@ -92,9 +147,10 @@ public class RepositoryServiceTest {
@Override
public ScmProtocol get(Repository repository) {
return new DummyHttpProtocol(repository);
return new DummyHttpProtocol(repository, anonymousEnabled);
}
}
private interface UnknownScmProtocol extends ScmProtocol {}
private interface UnknownScmProtocol extends ScmProtocol {
}
}