/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.security.authorization;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.xwiki.cache.CacheManager;
import org.xwiki.cache.config.CacheConfiguration;
import org.xwiki.model.internal.DefaultModelConfiguration;
import org.xwiki.model.internal.reference.DefaultEntityReferenceProvider;
import org.xwiki.model.internal.reference.DefaultStringEntityReferenceResolver;
import org.xwiki.model.internal.reference.DefaultStringEntityReferenceSerializer;
import org.xwiki.model.internal.reference.DefaultSymbolScheme;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.WikiReference;
import org.xwiki.security.DefaultSecurityReferenceFactory;
import org.xwiki.security.GroupSecurityReference;
import org.xwiki.security.SecurityReference;
import org.xwiki.security.SecurityReferenceFactory;
import org.xwiki.security.UserSecurityReference;
import org.xwiki.security.authorization.cache.SecurityCache;
import org.xwiki.security.authorization.cache.SecurityCacheRulesInvalidator;
import org.xwiki.security.authorization.cache.internal.DefaultSecurityCache;
import org.xwiki.security.authorization.cache.internal.DefaultSecurityCacheLoader;
import org.xwiki.security.authorization.cache.internal.TestCache;
import org.xwiki.security.authorization.internal.AbstractSecurityRuleEntry;
import org.xwiki.security.authorization.internal.DefaultAuthorizationSettler;
import org.xwiki.security.authorization.testwikis.SecureTestEntity;
import org.xwiki.security.authorization.testwikis.TestAccessRule;
import org.xwiki.security.authorization.testwikis.TestDefinition;
import org.xwiki.security.authorization.testwikis.TestDocument;
import org.xwiki.security.authorization.testwikis.TestEntity;
import org.xwiki.security.authorization.testwikis.TestGroup;
import org.xwiki.security.authorization.testwikis.TestUserDocument;
import org.xwiki.security.authorization.testwikis.TestWiki;
import org.xwiki.security.internal.UserBridge;
import org.xwiki.security.internal.XWikiBridge;
import org.xwiki.test.LogRule;
import org.xwiki.test.annotation.BeforeComponent;
import org.xwiki.test.annotation.ComponentList;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.xwiki.security.authorization.Right.ADMIN;
import static org.xwiki.security.authorization.Right.COMMENT;
import static org.xwiki.security.authorization.Right.CREATE_WIKI;
import static org.xwiki.security.authorization.Right.CREATOR;
import static org.xwiki.security.authorization.Right.DELETE;
import static org.xwiki.security.authorization.Right.EDIT;
import static org.xwiki.security.authorization.Right.ILLEGAL;
import static org.xwiki.security.authorization.Right.LOGIN;
import static org.xwiki.security.authorization.Right.PROGRAM;
import static org.xwiki.security.authorization.Right.REGISTER;
import static org.xwiki.security.authorization.Right.SCRIPT;
import static org.xwiki.security.authorization.Right.VIEW;
import static org.xwiki.security.authorization.Right.values;
/**
* Test XWiki Authorization policy against the authentication module.
* @since 5.0M2
*/
@ComponentList({
DefaultSecurityCache.class,
DefaultStringEntityReferenceResolver.class,
DefaultStringEntityReferenceSerializer.class,
DefaultEntityReferenceProvider.class,
DefaultModelConfiguration.class,
AuthorizationManagerConfiguration.class,
DefaultSecurityReferenceFactory.class,
DefaultSecurityCacheLoader.class,
DefaultAuthorizationSettler.class,
DefaultAuthorizationManager.class,
DefaultSymbolScheme.class
})
public class DefaultAuthorizationManagerIntegrationTest extends AbstractAuthorizationTestCase
{
private AuthorizationManager authorizationManager;
@Rule
public final LogRule logCapture = new LogRule();
/** Mocked xWikiBridge */
private XWikiBridge xWikiBridge;
/** Mocked userBridge */
private UserBridge userBridge;
/** Mocked securityEntryReader */
private SecurityEntryReader securityEntryReader;
/** Mocked securityCacheRulesInvalidator */
private SecurityCacheRulesInvalidator securityCacheRulesInvalidator;
/** Mocked cache */
private TestCache<Object> cache;
/** Factory for security reference */
private SecurityReferenceFactory securityReferenceFactory;
@BeforeComponent
public void initializeMocks() throws Exception {
cache = new TestCache<Object>();
final CacheManager cacheManager = componentManager.registerMockComponent(CacheManager.class);
when(cacheManager.createNewCache(any(CacheConfiguration.class))).thenReturn(cache);
xWikiBridge = componentManager.registerMockComponent(XWikiBridge.class);
userBridge = componentManager.registerMockComponent(UserBridge.class);
securityEntryReader = componentManager.registerMockComponent(SecurityEntryReader.class);
securityCacheRulesInvalidator = componentManager.registerMockComponent(SecurityCacheRulesInvalidator.class);
}
@Before
public void setUp() throws Exception
{
securityReferenceFactory = componentManager.getInstance(SecurityReferenceFactory.class);
authorizationManager = componentManager.getInstance(AuthorizationManager.class);
}
/**
* Assert an allowed access for a given right for a given user on a given entity.
* @param message the assert message
* @param right the right to check for allowance
* @param userReference the reference of the user to test.
* @param entityReference the reference of the entity to test.
* @throws Exception on error.
*/
protected void assertAccessTrue(String message, Right right, DocumentReference userReference,
EntityReference entityReference) throws Exception
{
Assert.assertTrue(message,
authorizationManager.hasAccess(right, userReference, entityReference));
}
/**
* Assert a denied access for a given right for a given user on a given entity.
* @param message the assert message
* @param right the right to check for denial
* @param userReference the reference of the user to test.
* @param entityReference the reference of the entity to test.
* @throws Exception on error.
*/
protected void assertAccessFalse(String message, Right right, DocumentReference userReference,
EntityReference entityReference) throws Exception
{
Assert.assertFalse(message, authorizationManager.hasAccess(right, userReference, entityReference));
}
/**
* Check all rights for access by given user on a given entity.
* @param allowedRights the set of rights that should be allowed.
* @param userReference the reference of the user to test.
* @param entityReference the reference of the entity to test.
* @throws Exception on error.
*/
protected void assertAccess(RightSet allowedRights, DocumentReference userReference,
EntityReference entityReference) throws Exception
{
for (Right right : values()) {
if (allowedRights != null && allowedRights.contains(right)) {
if (!authorizationManager.hasAccess(right, userReference, entityReference)) {
fail(String.format("[%s] should have [%s] right on [%s].",
getUserReadableName(userReference), right, getEntityReadableName(entityReference)));
}
} else {
if (authorizationManager.hasAccess(right, userReference, entityReference)) {
fail(String.format("[%s] should not have [%s] right on [%s].",
getUserReadableName(userReference), right, getEntityReadableName(entityReference)));
}
}
}
}
private boolean compareReferenceNullSafe(EntityReference entity1, EntityReference entity2) {
return entity1 == entity2 || (entity1 != null && entity1.equals(entity2));
}
private SecurityRule mockSecurityRule(SecurityReference reference, final Right right, RuleState state,
final DocumentReference userOrGroup, boolean isUser) {
SecurityRule mockedRule = mock(SecurityRule.class,
String.format("Rule for [%s] %s [%s] right to %s [%s]", reference.toString(),
state == RuleState.ALLOW ? "allowing" : "denying",
right.getName(), (isUser) ? "user" : "group", userOrGroup.toString()));
when(mockedRule.getState()).thenReturn(state);
when(mockedRule.match(any(Right.class))).thenAnswer(new Answer<Boolean>()
{
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable
{
Right reqRight = (Right) invocationOnMock.getArguments()[0];
return (reqRight == right);
}
});
if (isUser) {
when(mockedRule.match(any(UserSecurityReference.class))).thenAnswer(new Answer<Boolean>()
{
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable
{
SecurityReference reference =
(UserSecurityReference) invocationOnMock.getArguments()[0];
return compareReferenceNullSafe(userOrGroup,
reference.getOriginalDocumentReference());
}
});
//when(mockedRule.match(any(GroupSecurityReference.class))).thenReturn(false);
} else {
when(mockedRule.match(any(GroupSecurityReference.class))).thenAnswer(new Answer<Boolean>()
{
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable
{
SecurityReference reference =
(GroupSecurityReference) invocationOnMock.getArguments()[0];
return compareReferenceNullSafe(userOrGroup,
reference.getOriginalDocumentReference());
}
});
//when(mockedRule.match(any(UserSecurityReference.class))).thenReturn(false);
}
return mockedRule;
}
@Override
public TestDefinition initialiseWikiMock(String filename) throws Exception
{
super.initialiseWikiMock(filename);
when(xWikiBridge.getMainWikiReference()).thenReturn(testDefinition.getMainWiki().getWikiReference());
when(xWikiBridge.isWikiReadOnly()).thenReturn(false);
when(userBridge.getAllGroupsFor(any(UserSecurityReference.class), any(WikiReference.class))).thenAnswer(
new Answer<Collection<GroupSecurityReference>>()
{
@Override
public Collection<GroupSecurityReference> answer(InvocationOnMock invocationOnMock) throws Throwable
{
UserSecurityReference userReference = (UserSecurityReference) invocationOnMock.getArguments()[0];
WikiReference wikiReference = (WikiReference) invocationOnMock.getArguments()[1];
if (userReference.getOriginalReference() == null) {
// Public users (not logged in) may not appears in any group
return Collections.emptyList();
}
TestWiki wiki = testDefinition.getWiki(userReference.getOriginalReference().getWikiReference());
if (wiki == null) {
throw new AuthorizationException(
String.format("Failed to get groups for user or group [%s] in wiki [%s]. Unknown wiki.",
userReference, wikiReference), null);
}
TestUserDocument user = wiki.getUser(userReference.getName());
if (user == null) {
return Collections.emptyList();
}
Collection<GroupSecurityReference> groups = new ArrayList<GroupSecurityReference>();
for (TestGroup group : user.getGroups()) {
// Ensure we return only group of the requested wiki
if (group.getGroupReference().getWikiReference().equals(wikiReference)) {
groups.add(securityReferenceFactory.newGroupReference(group.getGroupReference()));
}
}
return groups;
}
}
);
when(securityEntryReader.read(any(SecurityReference.class))).thenAnswer(
new Answer<SecurityRuleEntry>()
{
@Override
public SecurityRuleEntry answer(InvocationOnMock invocationOnMock) throws Throwable
{
final SecurityReference reference = (SecurityReference) invocationOnMock.getArguments()[0];
TestEntity entity = testDefinition.searchEntity(reference);
Collection<TestAccessRule> rules = (entity != null && entity instanceof SecureTestEntity)
? ((SecureTestEntity) entity).getAccessRules()
: Collections.<TestAccessRule>emptyList();
final Collection<SecurityRule> mockedRules = new ArrayList<SecurityRule>();
for (final TestAccessRule rule : rules) {
mockedRules.add(mockSecurityRule(reference, rule.getRight(), rule.getState(), rule.getUser(),
rule.isUser()));
}
if (entity instanceof TestWiki) {
TestWiki wiki = (TestWiki) entity;
if (wiki.getOwner() != null) {
mockedRules.add(mockSecurityRule(reference, Right.ADMIN, RuleState.ALLOW, wiki.getOwner(),
true));
}
}
if (entity instanceof TestDocument) {
TestDocument document = (TestDocument) entity;
if (document.getCreator() != null) {
mockedRules.add(mockSecurityRule(reference, Right.CREATOR, RuleState.ALLOW,
document.getCreator(), true));
}
}
// This mock should be barely comparable for #testLoadUserInAnotherWikiAfterUserDoc()
/*
SecurityRuleEntry accessEntry = mock(SecurityRuleEntry.class,
String.format("Rule entry for %s containing %d rules", reference.toString(), mockedRules.size()));
when(accessEntry.getReference()).thenReturn(reference);
when(accessEntry.isEmpty()).thenReturn(mockedRules.isEmpty());
when(accessEntry.getRules()).thenReturn(mockedRules);
*/
return new AbstractSecurityRuleEntry()
{
@Override
public Collection<SecurityRule> getRules()
{
return mockedRules;
}
@Override
public SecurityReference getReference()
{
return reference;
}
@Override
public String toString()
{
return String.format("Rule entry for %s containing %d rules", reference.toString(), mockedRules.size());
}
@Override
public boolean equals(Object object)
{
if (object == this) {
return true;
}
if (!(object instanceof SecurityRuleEntry)) {
return false;
}
SecurityRuleEntry other = (SecurityRuleEntry) object;
return compareReferenceNullSafe(other.getReference(), reference)
&& other.getRules().size() == mockedRules.size();
}
};
}
}
);
return testDefinition;
}
@Test
public void testDefaultAccessOnEmptyWikis() throws Exception
{
initialiseWikiMock("emptyWikis");
// Public access on main wiki
assertAccess(new RightSet(VIEW, EDIT, COMMENT, REGISTER, LOGIN),
null, getXDoc("an empty main wiki", "anySpace"));
// SuperAdmin access on main wiki
assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, CREATOR, REGISTER, LOGIN, ADMIN, PROGRAM,
CREATE_WIKI, ILLEGAL), SUPERADMIN, getXDoc("an empty main wiki", "anySpace"));
// Any Global user without access rules on main wiki
assertAccess(new RightSet(VIEW, EDIT, COMMENT, REGISTER, LOGIN),
getXUser("a global user without any access rule"), getXDoc("main wiki", "anySpace"));
// Any Local user on main wiki
assertAccess(null,
getUser("a local user", "any SubWiki"), getXDoc("main wiki", "anySpace"));
// Public access on sub wiki
assertAccess(new RightSet(VIEW, EDIT, COMMENT, REGISTER, LOGIN),
null, getDoc("an empty sub wiki", "anySpace", "any SubWiki"));
// SuperAdmin access on sub wiki
assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, CREATOR, REGISTER, LOGIN, ADMIN, PROGRAM,
CREATE_WIKI, ILLEGAL),
SUPERADMIN, getDoc("an empty sub wiki", "anySpace", "any SubWiki"));
// Any Global user without access rules on sub wiki
assertAccess(new RightSet(VIEW, EDIT, COMMENT, REGISTER, LOGIN),
getXUser("a global user without any access rule"), getDoc("a subwiki", "anySpace", "any SubWiki"));
// Any Local user on another subwiki
assertAccess(null,
getUser("a local user", "any SubWiki"), getDoc("an another subwiki", "anySpace", "any Other SubWiki"));
}
@Test
public void testInheritancePolicyForFullFarmAccess() throws Exception
{
initialiseWikiMock("inheritancePolicyFullFarmAccess");
// Main wiki allowing all access to A
assertAccess(ALL_RIGHTS, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getXDoc("any document", "spaceDenyA"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getXDoc("docAllowA", "spaceDenyA"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getXDoc("docDenyA", "any space"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("any document", "any space", "wikiNoRules"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("any document", "spaceDenyA", "wikiNoRules"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("docAllowA", "spaceDenyA", "wikiNoRules"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("docDenyA", "any space", "wikiNoRules"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("any document", "any space", "wikiDenyA"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("any document", "spaceAllowA", "wikiDenyA"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("docDenyA", "spaceAllowA", "wikiDenyA"));
assertAccess(ALL_RIGHTS, getXUser("userA"), getDoc("docAllowA", "any space", "wikiDenyA"));
}
@Test
public void testInheritancePolicyForGlobalFullWikiAccess() throws Exception
{
initialiseWikiMock("inheritancePolicyForGlobalFullWikiAccess");
// Main wiki denying all access to A
assertAccess(null, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(ALL_SPACE_RIGHTS, getXUser("userA"), getXDoc("any document", "spaceAllowA"));
assertAccess(ALL_SPACE_RIGHTS, getXUser("userA"), getXDoc("docDenyA", "spaceAllowA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getXDoc("docAllowA", "any space"));
assertAccess(null, getXUser("userA"), getDoc("any document", "any space", "wikiNoRules"));
assertAccess(ALL_SPACE_RIGHTS, getXUser("userA"), getDoc("any document", "spaceAllowA", "wikiNoRules"));
assertAccess(ALL_SPACE_RIGHTS, getXUser("userA"), getDoc("docDenyA", "spaceAllowA", "wikiNoRules"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getDoc("docAllowA", "any space", "wikiNoRules"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "spaceDenyA", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowA", "spaceDenyA", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("docDenyA", "any space", "wikiAllowA"));
}
@Test
public void testInheritancePolicyForLocalWikiAccess() throws Exception
{
initialiseWikiMock("inheritancePolicyForLocalWikiAccess");
// Main wiki denying all access to A
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiAllowA"), getDoc("any document", "any space", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiAllowA"), getDoc("any document", "spaceDenyA", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiAllowA"), getDoc("docAllowA", "spaceDenyA", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiAllowA"), getDoc("docDenyA", "any space", "wikiAllowA"));
assertAccess(null, getUser("userA", "wikiDenyA"), getDoc("any document", "any space", "wikiDenyA"));
assertAccess(ALL_SPACE_RIGHTS, getUser("userA", "wikiDenyA"), getDoc("any document", "spaceAllowA", "wikiDenyA"));
assertAccess(ALL_SPACE_RIGHTS, getUser("userA", "wikiDenyA"), getDoc("docDenyA", "spaceAllowA", "wikiDenyA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getUser("userA", "wikiDenyA"), getDoc("any document", "spaceAllowANoAdmin", "wikiDenyA"));
assertAccess(null, getUser("userA", "wikiDenyA"), getDoc("docDenyA", "spaceAllowANoAdmin", "wikiDenyA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getUser("userA", "wikiDenyA"), getDoc("docAllowA", "any space", "wikiDenyA"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userA", "wikiAllowNoAdminA"), getDoc("any document", "any space", "wikiAllowNoAdminA"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiAllowNoAdminA"), getDoc("any document", "spaceDenyA", "wikiAllowNoAdminA"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userA", "wikiAllowNoAdminA"), getDoc("docAllowA", "spaceDenyA", "wikiAllowNoAdminA"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiAllowNoAdminA"), getDoc("docDenyA", "any space", "wikiAllowNoAdminA"));
}
@Test
public void testInheritancePolicyForNoAdminFarmAccess() throws Exception
{
initialiseWikiMock("inheritancePolicyForNoAdminFarmAccess");
// Main wiki allowing all but admin access to A
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("any document", "spaceDenyA"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("docAllowA", "spaceDenyA"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("docDenyA", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiNoRules"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getDoc("any document", "spaceDenyA", "wikiNoRules"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowA", "spaceDenyA", "wikiNoRules"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getDoc("docDenyA", "any space", "wikiNoRules"));
assertAccess(null, getXUser("userA"), getDoc("any document", "any space", "wikiDenyA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getDoc("any document", "spaceAllowA", "wikiDenyA"));
assertAccess(null, getXUser("userA"), getDoc("docDenyA", "spaceAllowA", "wikiDenyA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getDoc("docAllowA", "any space", "wikiDenyA"));
}
@Test
public void testInheritancePolicyForNoAdminWikiAccess() throws Exception
{
initialiseWikiMock("inheritancePolicyForNoAdminWikiAccess");
// Main wiki denying all access to A
assertAccess(null, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getXDoc("any document", "spaceAllowA"));
assertAccess(null, getXUser("userA"), getXDoc("docDenyA", "spaceAllowA"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getXDoc("docAllowA", "any space"));
assertAccess(null, getXUser("userA"), getDoc("any document", "any space", "wikiNoRules"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getDoc("any document", "spaceAllowA", "wikiNoRules"));
assertAccess(null, getXUser("userA"), getDoc("docDenyA", "spaceAllowA", "wikiNoRules"));
assertAccess(ALL_DOCUMENT_RIGHTS, getXUser("userA"), getDoc("docAllowA", "any space", "wikiNoRules"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiAllowA"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getDoc("any document", "spaceDenyA", "wikiAllowA"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowA", "spaceDenyA", "wikiAllowA"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getDoc("docDenyA", "any space", "wikiAllowA"));
}
@Test
public void testTieResolutionPolicy() throws Exception
{
initialiseWikiMock("tieResolutionPolicy");
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiUserAllowDeny"), getWiki("wikiUserAllowDeny"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiUserDenyAllow"), getWiki("wikiUserDenyAllow"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiGroupAllowDeny"), getWiki("wikiGroupAllowDeny"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiGroupDenyAllow"), getWiki("wikiGroupDenyAllow"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiUserGroupAllowDeny"), getWiki("wikiUserGroupAllowDeny"));
assertAccess(null, getUser("userA", "wikiUserGroupDenyAllow"), getWiki("wikiUserGroupDenyAllow"));
assertAccess(null, getUser("userA", "wikiGroupUserAllowDeny"), getWiki("wikiGroupUserAllowDeny"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiGroupUserDenyAllow"), getWiki("wikiGroupUserDenyAllow"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiUserAllowDenyNoAdmin"), getWiki("wikiUserAllowDenyNoAdmin"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiUserDenyAllowNoAdmin"), getWiki("wikiUserDenyAllowNoAdmin"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiGroupAllowDenyNoAdmin"), getWiki("wikiGroupAllowDenyNoAdmin"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userA", "wikiGroupDenyAllowNoAdmin"), getWiki("wikiGroupDenyAllowNoAdmin"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userA", "wikiUserGroupAllowDenyNoAdmin"), getWiki("wikiUserGroupAllowDenyNoAdmin"));
assertAccess(null, getUser("userA", "wikiUserGroupDenyAllowNoAdmin"), getWiki("wikiUserGroupDenyAllowNoAdmin"));
assertAccess(null, getUser("userA", "wikiGroupUserAllowDenyNoAdmin"), getWiki("wikiGroupUserAllowDenyNoAdmin"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userA", "wikiGroupUserDenyAllowNoAdmin"), getWiki("wikiGroupUserDenyAllowNoAdmin"));
}
@Test
public void testDocumentCreator() throws Exception
{
initialiseWikiMock("documentCreator");
assertAccess(new RightSet(VIEW, EDIT, COMMENT, DELETE, CREATOR, LOGIN, REGISTER), getXUser("userA"),
getXDoc("userAdoc", "space"));
assertAccess(new RightSet(VIEW, EDIT, COMMENT, LOGIN, REGISTER), getXUser("userA"),
getXDoc("userBdoc", "space"));
assertAccess(new RightSet(VIEW, EDIT, COMMENT, LOGIN, REGISTER), getXUser("userB"),
getXDoc("userAdoc", "space"));
assertAccess(new RightSet(VIEW, EDIT, COMMENT, DELETE, CREATOR, LOGIN, REGISTER), getXUser("userB"),
getXDoc("userBdoc", "space"));
}
@Test
public void testOwnerAccess() throws Exception
{
initialiseWikiMock("ownerAccess");
// Owner of main wiki has admin access to all wikis whatever the wiki access is
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiNoRules"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiLocalUserA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getXUser("userA"), getDoc("any document", "any space", "wikiDenyLocalUserA"));
// Local owner has admin access whatever the wiki access is
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiLocalUserA"), getDoc("any document", "any space", "wikiLocalUserA"));
assertAccess(ALL_RIGHTS_EXCEPT_PROGRAMING_AND_CREATE_WIKI, getUser("userA", "wikiDenyLocalUserA"), getDoc("any document", "any space", "wikiDenyLocalUserA"));
}
@Test
public void testGroupAccess() throws Exception
{
initialiseWikiMock("groupAccess");
assertAccess(DEFAULT_DOCUMENT_RIGHTS, getXUser("userA"), getXDoc("any document", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("docAllowGroupA", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("docAllowGroupB", "any space"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("docDenyGroupA", "any space"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("docDenyGroupB", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("docDenyGroupAAllowUserA", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getXDoc("docDenyGroupBAllowUserA", "any space"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("docDenyGroupBAllowGroupA", "any space"));
assertAccess(new RightSet(LOGIN, REGISTER), getXUser("userA"), getXDoc("docDenyGroupAAllowGroupB", "any space"));
assertAccess(DEFAULT_DOCUMENT_RIGHTS, getUser("userB","subwiki"), getDoc("any document", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userB","subwiki"), getDoc("docAllowGroupA", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getUser("userB","subwiki"), getDoc("docAllowGroupB", "any space", "subwiki"));
assertAccess(new RightSet(LOGIN, REGISTER), getUser("userB","subwiki"), getDoc("docAllowGroupC", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowGlobalGroupA", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowGlobalGroupB", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowGroupA", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowGroupB", "any space", "subwiki"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userA"), getDoc("docAllowGroupC", "any space", "subwiki"));
/** Test XWIKI-13574 **/
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userD"), getXDoc("docAllowGroupB", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userC"), getXDoc("docAllowGroupB", "any space"));
assertAccess(ALL_RIGHTS_EXCEPT_ADMIN_AND_CREATE_WIKI, getXUser("userB"), getXDoc("docAllowGroupB", "any space"));
}
@Test
public void testCheckAccess() throws Exception
{
initialiseWikiMock("emptyWikis");
authorizationManager.checkAccess(VIEW, null, getXDoc("an empty main wiki", "anySpace"));
try {
authorizationManager.checkAccess(ADMIN, null, getXDoc("an empty main wiki", "anySpace"));
fail("checkAccess should throw access denied exception when access is denied.");
} catch (AccessDeniedException e) {
assertThat("checkAccess should throw access denied exception without any cause when access is denied",
e.getCause(), nullValue());
}
}
@Test
public void testLoadUserAfterUserDoc() throws Exception
{
initialiseWikiMock("loadUserAfterUserDoc");
// Check access to the userA document => introduce the userA as a simple document into the cache
authorizationManager.checkAccess(VIEW, getXUser("userB"), getXUser("userA"));
// Check access of userA to the userB document => it prove userA is in groupA and has access
authorizationManager.checkAccess(VIEW, getXUser("userA"), getXUser("userB"));
SecurityCache securityCache = componentManager.getInstance(SecurityCache.class);
// a userA entry is in the cache
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), notNullValue());
assertThat("UserA should be considered as a user by the cache, else the group cache will not be used",
securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))).getReference(),
instanceOf(UserSecurityReference.class));
// remove group A from the cache => this should also remove all members of groupA
securityCache.remove(securityReferenceFactory.newUserReference(getXUser("groupA")));
// check that userA was seen as a member of groupA by the cache => implies document userA was considered as a
// user (and not simply a document) after the second check.
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), nullValue());
}
// Test XWIKI-12016
@Test
public void testGroupCacheLoadingUserAfterGroupDoc() throws Exception
{
initialiseWikiMock("loadUserAfterUserDoc");
// Check access to the groupA document => introduce the groupA as a simple document into the cache
authorizationManager.checkAccess(VIEW, getXUser("userB"), getXUser("groupA"));
// Check access of userA to the userA document => it transform group document into a true group
authorizationManager.checkAccess(VIEW, getXUser("userA"), getXUser("userA"));
// Check access of userA to the userB document => it prove userA is in groupA (from cache) and has access
authorizationManager.checkAccess(VIEW, getXUser("userA"), getXUser("userB"));
SecurityCache securityCache = componentManager.getInstance(SecurityCache.class);
// a userA entry is in the cache
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), notNullValue());
assertThat("UserA should be considered as a user by the cache, else the group cache will not be used",
securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))).getReference(),
instanceOf(UserSecurityReference.class));
// a userA entry in the cache is know as a user, else the group cache is inactive for her
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))).getReference(),
instanceOf(UserSecurityReference.class));
// remove group A from the cache => this should also remove all members of groupA
securityCache.remove(securityReferenceFactory.newUserReference(getXUser("groupA")));
// check that userA was seen as a member of groupA by the cache => implies document userA was considered as a
// user (and not simply a document) after the second check.
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), nullValue());
}
@Test
public void testLoadUserInAnotherWikiAfterUserDoc() throws Exception
{
initialiseWikiMock("loadUserAfterUserDoc");
// Check access to the userA document => introduce the userA as a simple document into the cache
authorizationManager.checkAccess(VIEW, getXUser("userB"), getXUser("userA"));
// Check access of userA to the userB document => it prove userA is in groupA and has access
authorizationManager.checkAccess(VIEW, getXUser("userA"), getDoc("any document", "any space", "subwiki"));
// Check access of userA to the userB document => it prove userA is in groupA and has access
authorizationManager.checkAccess(VIEW, getXUser("userA"), getXUser("userB"));
SecurityCache securityCache = componentManager.getInstance(SecurityCache.class);
// a userA entry is in the cache
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), notNullValue());
// a userA accessEntry is still in the cache for the document in the subwiki
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA")),
securityReferenceFactory.newEntityReference(getDoc("any document", "any space", "subwiki"))),
notNullValue());
// remove group A from the cache => this should also remove all members of groupA
securityCache.remove(securityReferenceFactory.newUserReference(getXUser("groupA")));
// check that userA was seen as a member of groupA by the cache => implies document userA is now a user
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA"))), nullValue());
// check that the shadow userA has also been affected
assertThat(securityCache.get(securityReferenceFactory.newUserReference(getXUser("userA")),
securityReferenceFactory.newEntityReference(getDoc("any document", "any space", "subwiki"))),
nullValue());
}
}