merge with branch 1.x

This commit is contained in:
Sebastian Sdorra
2017-06-25 19:01:33 +02:00
81 changed files with 4617 additions and 1319 deletions

View File

@@ -158,8 +158,7 @@ public abstract class CacheManagerTestBase<C extends Cache>
* @param c1
* @param c2
*/
protected void assertIsSame(Cache<String, String> c1,
Cache<String, String> c2)
protected void assertIsSame(Cache<String, String> c1, Cache<String, String> c2)
{
assertSame(c1, c2);
}

View File

@@ -76,8 +76,6 @@ public class CreateRepositoriesITCase extends AbstractAdminITCaseBase
*/
public CreateRepositoriesITCase(String repositoryType)
{
System.out.append("==> CreateRepositoriesITCase - ").println(
repositoryType);
this.repositoryType = repositoryType;
}
@@ -92,14 +90,14 @@ public class CreateRepositoriesITCase extends AbstractAdminITCaseBase
@Parameters
public static Collection<String[]> createParameters()
{
Collection<String[]> params = new ArrayList<String[]>();
Collection<String[]> params = new ArrayList<>();
params.add(new String[] { "git" });
params.add(new String[] { "git" });
params.add(new String[] { "svn" });
if (IOUtil.search("hg") != null)
{
params.add(new String[] { "git" });
params.add(new String[] { "hg" });
}
return params;

View File

@@ -125,8 +125,7 @@ public class DeactivatedUserITCase
public void testFailedAuthentication()
{
Client client = createClient();
ClientResponse response = authenticate(client, slarti.getName(),
"slart123");
ClientResponse response = authenticate(client, slarti.getName(), "slart123");
assertNotNull(response);
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus());
}

View File

@@ -0,0 +1,343 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
import com.google.common.base.Charsets;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import java.io.IOException;
import java.util.UUID;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import static org.junit.Assert.*;
import org.junit.rules.ExpectedException;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User;
import sonia.scm.user.UserTestData;
/**
* Integration tests for git lfs.
*
* @author Sebastian Sdorra
*/
public class GitLfsITCase {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private final ObjectMapper mapper = new ObjectMapper();
private Client adminClient;
private Repository repository;
public GitLfsITCase() {
mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector());
}
// lifecycle methods
@Before
public void setUpTestDependencies() {
adminClient = createAdminClient();
repository = createRepository(adminClient, RepositoryTestData.createHeartOfGold("git"));
}
@After
public void tearDownTestDependencies() {
deleteRepository(adminClient, repository.getId());
adminClient.destroy();
}
// tests
@Test
public void testLfsAPIWithAdminPermissions() throws IOException {
uploadAndDownload(adminClient);
}
@Test
public void testLfsAPIWithOwnerPermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.OWNER);
}
private void uploadAndDownloadAsUser(PermissionType permissionType) throws IOException {
User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123");
createUser(trillian);
try {
repository.getPermissions().add(new Permission(trillian.getId(), permissionType));
modifyRepository(repository);
Client client = createClient();
authenticate(client, trillian.getId(), "secret123");
uploadAndDownload(client);
} finally {
removeUser(trillian);
}
}
@Test
public void testLfsAPIWithWritePermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.WRITE);
}
private void createUser(User user) {
adminClient.resource(REST_BASE_URL + "users.json").post(user);
}
private void modifyRepository(Repository repository) {
adminClient.resource(REST_BASE_URL + "repositories/" + repository.getId() + ".json").put(repository);
}
private void removeUser(User user) {
adminClient.resource(REST_BASE_URL + "users/" + user.getId() + ".json").delete();
}
@Test
public void testLfsAPIWithoutWritePermissions() throws IOException {
User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123");
createUser(trillian);
expectedException.expect(UniformInterfaceException.class);
expectedException.expectMessage(Matchers.containsString("403"));
try {
repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
modifyRepository(repository);
Client client = createClient();
authenticate(client, trillian.getId(), "secret123");
uploadAndDownload(client);
} finally {
removeUser(trillian);
}
}
@Test
public void testLfsDownloadWithReadPermissions() throws IOException {
User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123");
createUser(trillian);
try {
repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
modifyRepository(repository);
// upload data as admin
String data = UUID.randomUUID().toString();
byte[] dataAsBytes = data.getBytes(Charsets.UTF_8);
LfsObject lfsObject = upload(adminClient, dataAsBytes);
Client client = createClient();
authenticate(client, trillian.getId(), "secret123");
// download as user
byte[] downloadedData = download(client, lfsObject);
// assert both are equal
assertArrayEquals(dataAsBytes, downloadedData);
} finally {
removeUser(trillian);
}
}
// lfs api
private void uploadAndDownload(Client client) throws IOException {
String data = UUID.randomUUID().toString();
byte[] dataAsBytes = data.getBytes(Charsets.UTF_8);
LfsObject lfsObject = upload(client, dataAsBytes);
byte[] downloadedData = download(client, lfsObject);
assertArrayEquals(dataAsBytes, downloadedData);
}
private LfsObject upload(Client client, byte[] data) throws IOException {
LfsObject lfsObject = createLfsObject(data);
LfsRequestBody request = LfsRequestBody.createUploadRequest(lfsObject);
LfsResponseBody response = request(client, request);
String uploadURL = response.objects[0].actions.upload.href;
client.resource(uploadURL).put(data);
return lfsObject;
}
private LfsResponseBody request(Client client, LfsRequestBody request) throws IOException {
String batchUrl = createBatchUrl();
String requestAsString = mapper.writeValueAsString(request);
return client
.resource(batchUrl)
.accept("application/vnd.git-lfs+json")
.header("Content-Type", "application/vnd.git-lfs+json")
.post(LfsResponseBody.class, requestAsString);
}
private String createBatchUrl() {
String url = repository.createUrl(BASE_URL);
return url + "/info/lfs/objects/batch";
}
private byte[] download(Client client, LfsObject lfsObject) throws IOException {
LfsRequestBody request = LfsRequestBody.createDownloadRequest(lfsObject);
LfsResponseBody response = request(client, request);
String downloadUrl = response.objects[0].actions.download.href;
return client.resource(downloadUrl).get(byte[].class);
}
private LfsObject createLfsObject(byte[] data) {
Sha256Hash hash = new Sha256Hash(data);
String oid = hash.toHex();
return new LfsObject(oid, data.length);
}
// LFS DTO objects
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
private static class LfsRequestBody {
private String operation;
private String[] transfers = new String[]{ "basic" };
private LfsObject[] objects;
public LfsRequestBody() {
}
private LfsRequestBody(String operation, LfsObject[] objects) {
this.operation = operation;
this.objects = objects;
}
public static LfsRequestBody createUploadRequest(LfsObject object) {
return new LfsRequestBody("upload", new LfsObject[]{object});
}
public static LfsRequestBody createDownloadRequest(LfsObject object) {
return new LfsRequestBody("download", new LfsObject[]{object});
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
private static class LfsResponseBody {
private LfsObject[] objects;
public LfsResponseBody() {
}
public LfsResponseBody(LfsObject[] objects) {
this.objects = objects;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
private static class LfsObject {
private String oid;
private long size;
private LfsActions actions;
public LfsObject() {
}
public LfsObject(String oid, long size) {
this.oid = oid;
this.size = size;
}
public LfsObject(String oid, long size, LfsActions actions) {
this.oid = oid;
this.size = size;
this.actions = actions;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
private static class LfsActions {
private LfsAction upload;
private LfsAction download;
public LfsActions() {
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
private static class LfsAction {
private String href;
public LfsAction() {
}
public LfsAction(String href) {
this.href = href;
}
}
}

View File

@@ -0,0 +1,143 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.sun.jersey.api.client.Client;
import java.io.File;
import java.io.IOException;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
import sonia.scm.repository.Person;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.client.api.ClientCommand;
import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientFactory;
/**
* Integration test for RepositoryPathMatching with ".git" and without ".git".
*
* @author Sebastian Sdorra
* @since 1.54
*/
public class GitRepositoryPathMatcherITCase {
private static final RepositoryClientFactory REPOSITORY_CLIENT_FACTORY = new RepositoryClientFactory();
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
private Client apiClient;
private Repository repository;
@Before
public void setUp() {
apiClient = createAdminClient();
Repository testRepository = RepositoryTestData.createHeartOfGold("git");
this.repository = createRepository(apiClient, testRepository);
}
@After
public void tearDown() {
deleteRepository(apiClient, repository.getId());
}
// tests begin
@Test
public void testWithoutDotGit() throws IOException {
String urlWithoutDotGit = createUrl();
cloneAndPush(urlWithoutDotGit);
}
@Test
public void testWithDotGit() throws IOException {
String urlWithDotGit = createUrl() + ".git";
cloneAndPush(urlWithDotGit);
}
// tests end
private String createUrl() {
return BASE_URL + "git/" + repository.getName();
}
private void cloneAndPush( String url ) throws IOException {
cloneRepositoryAndPushFiles(url);
cloneRepositoryAndCheckFiles(url);
}
private void cloneRepositoryAndPushFiles(String url) throws IOException {
RepositoryClient repositoryClient = createRepositoryClient(url);
Files.write("a", new File(repositoryClient.getWorkingCopy(), "a.txt"), Charsets.UTF_8);
repositoryClient.getAddCommand().add("a.txt");
commit(repositoryClient, "added a");
Files.write("b", new File(repositoryClient.getWorkingCopy(), "b.txt"), Charsets.UTF_8);
repositoryClient.getAddCommand().add("b.txt");
commit(repositoryClient, "added b");
}
private void cloneRepositoryAndCheckFiles(String url) throws IOException {
RepositoryClient repositoryClient = createRepositoryClient(url);
File workingCopy = repositoryClient.getWorkingCopy();
File a = new File(workingCopy, "a.txt");
assertTrue(a.exists());
assertEquals("a", Files.toString(a, Charsets.UTF_8));
File b = new File(workingCopy, "b.txt");
assertTrue(b.exists());
assertEquals("b", Files.toString(b, Charsets.UTF_8));
}
private void commit(RepositoryClient repositoryClient, String message) throws IOException {
repositoryClient.getCommitCommand().commit(
new Person("scmadmin", "scmadmin@scm-manager.org"), message
);
if ( repositoryClient.isCommandSupported(ClientCommand.PUSH) ) {
repositoryClient.getPushCommand().push();
}
}
private RepositoryClient createRepositoryClient(String url) throws IOException {
return REPOSITORY_CLIENT_FACTORY.create("git", url, ADMIN_USERNAME, ADMIN_PASSWORD, tempFolder.newFolder());
}
}

View File

@@ -181,7 +181,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
private Changeset commit(String message) throws IOException {
Changeset a = repositoryClient.getCommitCommand().commit(
new Person("scmadmin", "scmadmin@scm-manager.org"), "added a"
new Person("scmadmin", "scmadmin@scm-manager.org"), message
);
if ( repositoryClient.isCommandSupported(ClientCommand.PUSH) ) {
repositoryClient.getPushCommand().push();

View File

@@ -0,0 +1,225 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ThreadContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.SCMContextProvider;
import sonia.scm.Type;
import sonia.scm.cache.GuavaCacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.AuthorizationCollector;
import sonia.scm.security.DefaultKeyGenerator;
import sonia.scm.security.KeyGenerator;
import sonia.scm.security.SecuritySystem;
import sonia.scm.user.UserTestData;
/**
* Performance test for {@link RepositoryManager#getAll()}.
*
* @see <a href="https://goo.gl/PD1AeM">Issue 781</a>
* @author Sebastian Sdorra
* @since 1.52
*/
@RunWith(MockitoJUnitRunner.class)
public class DefaultRepositoryManagerPerfTest {
private static final int REPOSITORY_COUNT = 2000;
private static final String REPOSITORY_TYPE = "perf";
@Mock
private SCMContextProvider contextProvider;
@Mock
private RepositoryDAO repositoryDAO;
private final ScmConfiguration configuration = new ScmConfiguration();
private final KeyGenerator keyGenerator = new DefaultKeyGenerator();
@Mock
private RepositoryHandler repositoryHandler;
private DefaultRepositoryManager repositoryManager;
@Mock
private AuthorizationCollector authzCollector;
/**
* Setup object under test.
*/
@Before
public void setUpObjectUnderTest(){
when(repositoryHandler.getType()).thenReturn(new Type(REPOSITORY_TYPE, REPOSITORY_TYPE));
Set<RepositoryHandler> handlerSet = ImmutableSet.of(repositoryHandler);
RepositoryMatcher repositoryMatcher = new RepositoryMatcher(Collections.<RepositoryPathMatcher>emptySet());
repositoryManager = new DefaultRepositoryManager(
configuration,
contextProvider,
keyGenerator,
repositoryDAO,
handlerSet,
repositoryMatcher
);
setUpTestRepositories();
GuavaCacheManager cacheManager = new GuavaCacheManager();
DefaultSecurityManager securityManager = new DefaultSecurityManager(new DummyRealm(authzCollector, cacheManager));
ThreadContext.bind(securityManager);
}
/**
* Tear down test objects.
*/
@After
public void tearDown(){
ThreadContext.unbindSecurityManager();
}
/**
* Start performance test and ensure that the timeout is not reached.
*/
@Test(timeout = 6000l)
public void perfTestGetAll(){
SecurityUtils.getSubject().login(new UsernamePasswordToken("trillian", "secret"));
List<Long> times = new ArrayList<>();
for ( int i=0; i<3; i++ ) {
times.add(benchGetAll());
}
long average = calculateAverage(times);
double value = (double) average / TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS);
// Too bad this functionality is not exposed as a regular method call
System.out.println( String.format("%.4g s", value) );
}
private long calculateAverage(List<Long> times) {
Long sum = 0l;
if(!times.isEmpty()) {
for (Long time : times) {
sum += time;
}
return Math.round(sum.doubleValue() / times.size());
}
return sum;
}
private long benchGetAll(){
Stopwatch sw = Stopwatch.createStarted();
System.out.append("found ").append(String.valueOf(repositoryManager.getAll().size()));
sw.stop();
System.out.append(" in ").println(sw);
return sw.elapsed(TimeUnit.MILLISECONDS);
}
private void setUpTestRepositories() {
Map<String,Repository> repositories = new LinkedHashMap<>();
for ( int i=0; i<REPOSITORY_COUNT; i++ ) {
Repository repository = createTestRepository(i);
repositories.put(repository.getId(), repository);
}
when(repositoryDAO.getAll()).thenReturn(repositories.values());
}
private Repository createTestRepository(int number){
Repository repository = new Repository(keyGenerator.createKey(), REPOSITORY_TYPE, "repo-" + number);
repository.getPermissions().add(new Permission("trillian", PermissionType.READ));
return repository;
}
static class DummyRealm extends AuthorizingRealm {
private final AuthorizationCollector authzCollector;
public DummyRealm(AuthorizationCollector authzCollector, org.apache.shiro.cache.CacheManager cacheManager) {
this.authzCollector = authzCollector;
setCredentialsMatcher(new AllowAllCredentialsMatcher());
setCacheManager(cacheManager);
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
SimplePrincipalCollection spc = new SimplePrincipalCollection(token.getPrincipal(), REPOSITORY_TYPE);
spc.add(UserTestData.createTrillian(), REPOSITORY_TYPE);
return new SimpleAuthenticationInfo(spc, REPOSITORY_TYPE);
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return authzCollector.collect();
}
}
private static class SetProvider implements Provider {
@Override
public Object get() {
return Collections.emptySet();
}
}
}

View File

@@ -55,12 +55,12 @@ import static org.hamcrest.Matchers.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import org.apache.shiro.authz.UnauthorizedException;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.mockito.invocation.InvocationOnMock;
@@ -492,19 +492,18 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
@Test
public void getRepositoryFromRequestUriTest() throws RepositoryException, IOException {
RepositoryManager m = createManager();
m.init(contextProvider);
createRepository(m, new Repository("1", "hg", "scm"));
createRepository(m, new Repository("2", "hg", "scm-test"));
createRepository(m, new Repository("3", "git", "project1/test-1"));
createRepository(m, new Repository("4", "git", "project1/test-2"));
assertEquals("scm", m.getFromUri("hg/scm").getName());
assertEquals("scm-test", m.getFromUri("hg/scm-test").getName());
assertEquals("scm-test", m.getFromUri("/hg/scm-test").getName());
assertEquals("project1/test-1",
m.getFromUri("/git/project1/test-1").getName());
assertEquals("project1/test-1",
m.getFromUri("/git/project1/test-1/ka/some/path").getName());
assertEquals("project1/test-1", m.getFromUri("/git/project1/test-1").getName());
assertEquals("project1/test-1", m.getFromUri("/git/project1/test-1/ka/some/path").getName());
assertNull(m.getFromUri("/git/project1/test-3/ka/some/path"));
}
@@ -543,7 +542,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
configuration.setEnableRepositoryArchive(archiveEnabled);
return new DefaultRepositoryManager(configuration, contextProvider,
keyGenerator, repositoryDAO, handlerSet);
keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher());
}
private void createRepository(RepositoryManager m, Repository repository)
@@ -569,6 +568,10 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
assertEquals(repo.getCreationDate(), other.getCreationDate());
assertEquals(repo.getLastModified(), other.getLastModified());
}
private RepositoryMatcher createRepositoryMatcher() {
return new RepositoryMatcher(Collections.<RepositoryPathMatcher>emptySet());
}
private Repository createRepository(Repository repository) throws RepositoryException, IOException {
manager.create(repository);

View File

@@ -0,0 +1,88 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository;
import com.google.common.collect.Sets;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Before;
/**
* Unit tests for {@link RepositoryMatcher}.
*
* @author Sebastian Sdorra
* @since 1.54
*/
public class RepositoryMatcherTest {
private RepositoryMatcher matcher;
@Before
public void setUp() {
Set<RepositoryPathMatcher> pathMatchers = Sets.<RepositoryPathMatcher>newHashSet(new AbcRepositoryPathMatcher());
this.matcher = new RepositoryMatcher(pathMatchers);
}
@Test
public void testMatches() {
assertFalse(matcher.matches(repository("hg", "scm"), "hg", "scm-test/ka"));
assertFalse(matcher.matches(repository("git", "scm-test"), "hg", "scm-test"));
assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "scm-test/ka"));
assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "scm-test"));
}
@Test
public void testMatchesWithCustomPathMatcher() {
assertFalse(matcher.matches(repository("abc", "scm"), "hg", "/long/path/with/abc"));
assertTrue(matcher.matches(repository("abc", "scm"), "abc", "/long/path/with/abc"));
}
private Repository repository(String type, String name) {
return new Repository(type + "-" + name, type, name);
}
private static class AbcRepositoryPathMatcher implements RepositoryPathMatcher {
@Override
public boolean isPathMatching(Repository repository, String path) {
return path.endsWith("abc");
}
@Override
public String getType() {
return "abc";
}
}
}

View File

@@ -0,0 +1,256 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.security;
import com.google.common.collect.Lists;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Before;
import sonia.scm.HandlerEventType;
import sonia.scm.group.Group;
import sonia.scm.group.GroupEvent;
import sonia.scm.group.GroupModificationEvent;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryEvent;
import sonia.scm.repository.RepositoryModificationEvent;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User;
import sonia.scm.user.UserEvent;
import sonia.scm.user.UserModificationEvent;
import sonia.scm.user.UserTestData;
/**
* Unit tests for {@link AuthorizationChangedEventProducer}.
*
* @author Sebastian Sdorra
*/
public class AuthorizationChangedEventProducerTest {
private StoringAuthorizationChangedEventProducer producer;
@Before
public void setUpProducer() {
producer = new StoringAuthorizationChangedEventProducer();
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.user.UserEvent)}.
*/
@Test
public void testOnUserEvent()
{
User user = UserTestData.createDent();
producer.onEvent(new UserEvent(HandlerEventType.BEFORE_CREATE, user));
assertEventIsNotFired();
producer.onEvent(new UserEvent(HandlerEventType.CREATE, user));
assertUserEventIsFired("dent");
}
private void assertEventIsNotFired(){
assertNull(producer.event);
}
private void assertUserEventIsFired(String username){
assertNotNull(producer.event);
assertTrue(producer.event.isEveryUserAffected());
assertEquals(username, producer.event.getNameOfAffectedUser());
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.user.UserEvent)} with modified user.
*/
@Test
public void testOnUserModificationEvent()
{
User user = UserTestData.createDent();
User userModified = UserTestData.createDent();
userModified.setDisplayName("Super Dent");
producer.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
assertEventIsNotFired();
producer.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
assertEventIsNotFired();
userModified.setAdmin(true);
producer.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
assertEventIsNotFired();
producer.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
assertUserEventIsFired("dent");
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.group.GroupEvent)}.
*/
@Test
public void testOnGroupEvent()
{
Group group = new Group("xml", "base");
producer.onEvent(new GroupEvent(HandlerEventType.BEFORE_CREATE, group));
assertEventIsNotFired();
producer.onEvent(new GroupEvent(HandlerEventType.CREATE, group));
assertGlobalEventIsFired();
}
private void assertGlobalEventIsFired(){
assertNotNull(producer.event);
assertFalse(producer.event.isEveryUserAffected());
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.group.GroupEvent)} with modified groups.
*/
@Test
public void testOnGroupModificationEvent()
{
Group group = new Group("xml", "base");
Group modifiedGroup = new Group("xml", "base");
producer.onEvent(new GroupModificationEvent(HandlerEventType.BEFORE_MODIFY, modifiedGroup, group));
assertEventIsNotFired();
producer.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
assertEventIsNotFired();
modifiedGroup.add("test");
producer.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
assertGlobalEventIsFired();
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.repository.RepositoryEvent)}.
*/
@Test
public void testOnRepositoryEvent()
{
Repository repository = RepositoryTestData.createHeartOfGold();
producer.onEvent(new RepositoryEvent(HandlerEventType.BEFORE_CREATE, repository));
assertEventIsNotFired();
producer.onEvent(new RepositoryEvent(HandlerEventType.CREATE, repository));
assertGlobalEventIsFired();
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.repository.RepositoryEvent)} with modified
* repository.
*/
@Test
public void testOnRepositoryModificationEvent()
{
Repository repositoryModified = RepositoryTestData.createHeartOfGold();
repositoryModified.setName("test123");
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
Repository repository = RepositoryTestData.createHeartOfGold();
repository.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.BEFORE_CREATE, repositoryModified, repository));
assertEventIsNotFired();
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
assertEventIsNotFired();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
assertEventIsNotFired();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test123")));
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
assertGlobalEventIsFired();
resetStoredEvent();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.READ, true))
);
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
assertGlobalEventIsFired();
resetStoredEvent();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.WRITE))
);
producer.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
assertGlobalEventIsFired();
}
private void resetStoredEvent(){
producer.event = null;
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.security.StoredAssignedPermissionEvent)}.
*/
@Test
public void testOnStoredAssignedPermissionEvent()
{
StoredAssignedPermission groupPermission = new StoredAssignedPermission(
"123", new AssignedPermission("_authenticated", true, "repository:read:*")
);
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, groupPermission));
assertEventIsNotFired();
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, groupPermission));
assertGlobalEventIsFired();
resetStoredEvent();
StoredAssignedPermission userPermission = new StoredAssignedPermission(
"123", new AssignedPermission("trillian", false, "repository:read:*")
);
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, userPermission));
assertEventIsNotFired();
resetStoredEvent();
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, userPermission));
assertUserEventIsFired("trillian");
}
private static class StoringAuthorizationChangedEventProducer extends AuthorizationChangedEventProducer {
private AuthorizationChangedEvent event;
@Override
protected void sendEvent(AuthorizationChangedEvent event) {
this.event = event;
}
}
}

View File

@@ -50,22 +50,14 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.HandlerEventType;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
import sonia.scm.group.Group;
import sonia.scm.group.GroupEvent;
import sonia.scm.group.GroupModificationEvent;
import sonia.scm.group.GroupNames;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryDAO;
import sonia.scm.repository.RepositoryEvent;
import sonia.scm.repository.RepositoryModificationEvent;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User;
import sonia.scm.user.UserEvent;
import sonia.scm.user.UserModificationEvent;
import sonia.scm.user.UserTestData;
/**
@@ -82,7 +74,7 @@ public class DefaultAuthorizationCollectorTest {
@Mock
private CacheManager cacheManager;
@Mock
private RepositoryDAO repositoryDAO;
@@ -104,160 +96,6 @@ public class DefaultAuthorizationCollectorTest {
collector = new DefaultAuthorizationCollector(cacheManager, repositoryDAO, securitySystem);
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.user.UserEvent)}.
*/
@Test
public void testOnUserEvent()
{
User user = UserTestData.createDent();
collector.onEvent(new UserEvent(HandlerEventType.BEFORE_CREATE, user));
verify(cache, never()).clear();
collector.onEvent(new UserEvent(HandlerEventType.CREATE, user));
verify(cache).removeAll(Mockito.any(Predicate.class));
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.user.UserEvent)} with modified user.
*/
@Test
public void testOnUserModificationEvent()
{
User user = UserTestData.createDent();
User userModified = UserTestData.createDent();
userModified.setDisplayName("Super Dent");
collector.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
collector.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
userModified.setAdmin(true);
collector.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
collector.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
verify(cache).removeAll(Mockito.any(Predicate.class));
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.group.GroupEvent)}.
*/
@Test
public void testOnGroupEvent()
{
Group group = new Group("xml", "base");
collector.onEvent(new GroupEvent(HandlerEventType.BEFORE_CREATE, group));
verify(cache, never()).clear();
collector.onEvent(new GroupEvent(HandlerEventType.CREATE, group));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.group.GroupEvent)} with modified groups.
*/
@Test
public void testOnGroupModificationEvent()
{
Group group = new Group("xml", "base");
Group modifiedGroup = new Group("xml", "base");
collector.onEvent(new GroupModificationEvent(HandlerEventType.BEFORE_MODIFY, modifiedGroup, group));
verify(cache, never()).clear();
collector.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
verify(cache, never()).clear();
modifiedGroup.add("test");
collector.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.repository.RepositoryEvent)}.
*/
@Test
public void testOnRepositoryEvent()
{
Repository repository = RepositoryTestData.createHeartOfGold();
collector.onEvent(new RepositoryEvent(HandlerEventType.BEFORE_CREATE, repository));
verify(cache, never()).clear();
collector.onEvent(new RepositoryEvent(HandlerEventType.CREATE, repository));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.repository.RepositoryEvent)} with modified repository.
*/
@Test
public void testOnRepositoryModificationEvent()
{
Repository repositoryModified = RepositoryTestData.createHeartOfGold();
repositoryModified.setName("test123");
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
Repository repository = RepositoryTestData.createHeartOfGold();
repository.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.BEFORE_CREATE, repositoryModified, repository));
verify(cache, never()).clear();
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
verify(cache, never()).clear();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
verify(cache, never()).clear();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test123")));
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
verify(cache).clear();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.READ, true))
);
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
verify(cache, times(2)).clear();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.WRITE))
);
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
verify(cache, times(3)).clear();
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.security.StoredAssignedPermissionEvent)}.
*/
@Test
public void testOnStoredAssignedPermissionEvent()
{
StoredAssignedPermission groupPermission = new StoredAssignedPermission(
"123", new AssignedPermission("_authenticated", true, "repository:read:*")
);
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, groupPermission));
verify(cache, never()).clear();
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, groupPermission));
verify(cache).clear();
StoredAssignedPermission userPermission = new StoredAssignedPermission(
"123", new AssignedPermission("trillian", false, "repository:read:*")
);
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, userPermission));
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
verify(cache).clear();
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, userPermission));
verify(cache).removeAll(Mockito.any(Predicate.class));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#collect()} without user role.
*/
@@ -386,8 +224,7 @@ public class DefaultAuthorizationCollectorTest {
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two"));
}
private void authenticate(User user, String group, String... groups)
{
private void authenticate(User user, String group, String... groups) {
SimplePrincipalCollection spc = new SimplePrincipalCollection();
spc.add(user.getName(), "unit");
spc.add(user, "unit");
@@ -396,4 +233,16 @@ public class DefaultAuthorizationCollectorTest {
shiro.setSubject(subject);
}
}
/**
* Tests {@link AuthorizationCollector#invalidateCache(sonia.scm.security.AuthorizationChangedEvent)}.
*/
@Test
public void testInvalidateCache() {
collector.invalidateCache(AuthorizationChangedEvent.createForEveryUser());
verify(cache).clear();
collector.invalidateCache(AuthorizationChangedEvent.createForUser("dent"));
verify(cache).removeAll(Mockito.any(Predicate.class));
}
}