#781 process all kinds authorization relevant event and produce AuthorizationChangedEvent

This commit is contained in:
Sebastian Sdorra
2017-02-26 13:19:35 +01:00
parent b6a49570cf
commit acc3ff791b
10 changed files with 718 additions and 377 deletions

View File

@@ -72,8 +72,11 @@ 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 {
@@ -105,6 +108,9 @@ public class DefaultRepositoryManagerPerfTest {
private AuthorizationCollector authzCollector;
/**
* Setup object under test.
*/
@Before
public void setUpObjectUnderTest(){
when(repositoryHandler.getType()).thenReturn(new Type(REPOSITORY_TYPE, REPOSITORY_TYPE));
@@ -132,11 +138,17 @@ public class DefaultRepositoryManagerPerfTest {
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"));

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.HandlerEvent;
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(user, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new UserEvent(user, HandlerEvent.CREATE));
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(userModified, user, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.CREATE));
assertEventIsNotFired();
userModified.setAdmin(true);
producer.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.CREATE));
assertUserEventIsFired("dent");
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.group.GroupEvent)}.
*/
@Test
public void testOnGroupEvent()
{
Group group = new Group("xml", "base");
producer.onEvent(new GroupEvent(group, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new GroupEvent(group, HandlerEvent.CREATE));
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(modifiedGroup, group, HandlerEvent.BEFORE_MODIFY));
assertEventIsNotFired();
producer.onEvent(new GroupModificationEvent(modifiedGroup, group, HandlerEvent.MODIFY));
assertEventIsNotFired();
modifiedGroup.add("test");
producer.onEvent(new GroupModificationEvent(modifiedGroup, group, HandlerEvent.MODIFY));
assertGlobalEventIsFired();
}
/**
* Tests {@link AuthorizationChangedEventProducer#onEvent(sonia.scm.repository.RepositoryEvent)}.
*/
@Test
public void testOnRepositoryEvent()
{
Repository repository = RepositoryTestData.createHeartOfGold();
producer.onEvent(new RepositoryEvent(repository, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new RepositoryEvent(repository, HandlerEvent.CREATE));
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(repositoryModified, repository, HandlerEvent.BEFORE_CREATE));
assertEventIsNotFired();
producer.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
assertEventIsNotFired();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
producer.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
assertEventIsNotFired();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test123")));
producer.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
assertGlobalEventIsFired();
resetStoredEvent();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.READ, true))
);
producer.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
assertGlobalEventIsFired();
resetStoredEvent();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.WRITE))
);
producer.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
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(HandlerEvent.BEFORE_CREATE, groupPermission));
assertEventIsNotFired();
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.CREATE, groupPermission));
assertGlobalEventIsFired();
resetStoredEvent();
StoredAssignedPermission userPermission = new StoredAssignedPermission(
"123", new AssignedPermission("trillian", false, "repository:read:*")
);
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.BEFORE_CREATE, userPermission));
assertEventIsNotFired();
resetStoredEvent();
producer.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.CREATE, userPermission));
assertUserEventIsFired("trillian");
}
private static class StoringAuthorizationChangedEventProducer extends AuthorizationChangedEventProducer {
private AuthorizationChangedEvent event;
@Override
protected void sendEvent(AuthorizationChangedEvent event) {
this.event = event;
}
}
}

View File

@@ -54,22 +54,14 @@ import static org.junit.Assert.*;
import org.junit.Rule;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.Filter;
import sonia.scm.HandlerEvent;
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;
/**
@@ -85,7 +77,7 @@ public class AuthorizationCollectorTest {
@Mock
private CacheManager cacheManager;
@Mock
private RepositoryDAO repositoryDAO;
@@ -111,160 +103,6 @@ public class AuthorizationCollectorTest {
collector = new AuthorizationCollector(cacheManager, repositoryDAO, securitySystem, resolver);
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.user.UserEvent)}.
*/
@Test
public void testOnUserEvent()
{
User user = UserTestData.createDent();
collector.onEvent(new UserEvent(user, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).clear();
collector.onEvent(new UserEvent(user, HandlerEvent.CREATE));
verify(cache).removeAll(Mockito.any(Filter.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(userModified, user, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).removeAll(Mockito.any(Filter.class));
collector.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.CREATE));
verify(cache, never()).removeAll(Mockito.any(Filter.class));
userModified.setAdmin(true);
collector.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).removeAll(Mockito.any(Filter.class));
collector.onEvent(new UserModificationEvent(userModified, user, HandlerEvent.CREATE));
verify(cache).removeAll(Mockito.any(Filter.class));
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.group.GroupEvent)}.
*/
@Test
public void testOnGroupEvent()
{
Group group = new Group("xml", "base");
collector.onEvent(new GroupEvent(group, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).clear();
collector.onEvent(new GroupEvent(group, HandlerEvent.CREATE));
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(modifiedGroup, group, HandlerEvent.BEFORE_MODIFY));
verify(cache, never()).clear();
collector.onEvent(new GroupModificationEvent(modifiedGroup, group, HandlerEvent.MODIFY));
verify(cache, never()).clear();
modifiedGroup.add("test");
collector.onEvent(new GroupModificationEvent(modifiedGroup, group, HandlerEvent.MODIFY));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.repository.RepositoryEvent)}.
*/
@Test
public void testOnRepositoryEvent()
{
Repository repository = RepositoryTestData.createHeartOfGold();
collector.onEvent(new RepositoryEvent(repository, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).clear();
collector.onEvent(new RepositoryEvent(repository, HandlerEvent.CREATE));
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(repositoryModified, repository, HandlerEvent.BEFORE_CREATE));
verify(cache, never()).clear();
collector.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
verify(cache, never()).clear();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
collector.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
verify(cache, never()).clear();
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test123")));
collector.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
verify(cache).clear();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.READ, true))
);
collector.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
verify(cache, times(2)).clear();
repositoryModified.setPermissions(
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.WRITE))
);
collector.onEvent(new RepositoryModificationEvent(repositoryModified, repository, HandlerEvent.CREATE));
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(HandlerEvent.BEFORE_CREATE, groupPermission));
verify(cache, never()).clear();
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.CREATE, groupPermission));
verify(cache).clear();
StoredAssignedPermission userPermission = new StoredAssignedPermission(
"123", new AssignedPermission("trillian", false, "repository:read:*")
);
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.BEFORE_CREATE, userPermission));
verify(cache, never()).removeAll(Mockito.any(Filter.class));
verify(cache).clear();
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEvent.CREATE, userPermission));
verify(cache).removeAll(Mockito.any(Filter.class));
verify(cache).clear();
}
/**
* Tests {@link AuthorizationCollector#collect()} without user role.
*/
@@ -402,8 +240,7 @@ public class AuthorizationCollectorTest {
assertThat(authInfo.getObjectPermissions(), containsInAnyOrder(wp1, wp2));
}
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");
@@ -412,4 +249,16 @@ public class AuthorizationCollectorTest {
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(Filter.class));
}
}

View File

@@ -54,8 +54,6 @@ import org.junit.Test;
import org.mockito.Mockito;
import sonia.scm.cache.CacheManager;
import sonia.scm.cache.MapCacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.Group;
import sonia.scm.group.GroupManager;
@@ -89,6 +87,7 @@ import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import sonia.scm.cache.GuavaCacheManager;
/**
*
@@ -477,7 +476,7 @@ public class ScmRealmTest
Collections.EMPTY_LIST
);
CacheManager cacheManager = new MapCacheManager();
GuavaCacheManager cacheManager = new GuavaCacheManager();
AdminDetector adminSelector = new AdminDetector(new ScmConfiguration());
LocalDatabaseSynchronizer synchronizer = new LocalDatabaseSynchronizer(
@@ -494,7 +493,7 @@ public class ScmRealmTest
);
AuthorizationCollector authzCollector = new AuthorizationCollector(
cacheManager,
cacheManager,
repositoryDAO,
securitySystem,
new RepositoryPermissionResolver()
@@ -516,6 +515,7 @@ public class ScmRealmTest
};
return new ScmRealm(
cacheManager,
new AuthenticatorFacade(authManager, requestProvider, responseProvider),
dummyLoginAttemptHandler,
authcCollector,