blob: 0133b4f1aa136fcee5c0fdcbf698efeae504b3a1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.AbstractRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinitionImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
/**
* Tests for functionality provided by {@link AbstractAccessControlList}.
*/
public class AbstractAccessControlListTest extends AbstractAccessControlTest {
protected String getTestPath() {
return "/testPath";
}
protected NamePathMapper getNamePathMapper() {
return NamePathMapper.DEFAULT;
}
protected RestrictionProvider getRestrictionProvider() {
Map<String, RestrictionDefinition> rDefs = new HashMap();
rDefs.put("r1", new RestrictionDefinitionImpl("r1", Type.STRING, true));
rDefs.put("r2", new RestrictionDefinitionImpl("r2", Type.LONGS, false));
return new AbstractRestrictionProvider(rDefs) {
@NotNull
@Override
public RestrictionPattern getPattern(@Nullable String oakPath, @NotNull Tree tree) {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public RestrictionPattern getPattern(@Nullable String oakPath, @NotNull Set<Restriction> restrictions) {
throw new UnsupportedOperationException();
}
};
}
protected AbstractAccessControlList createEmptyACL() {
return createACL(getTestPath(), Collections.<JackrabbitAccessControlEntry>emptyList(), getNamePathMapper());
}
protected AbstractAccessControlList createACL(@NotNull JackrabbitAccessControlEntry... entries) {
return createACL(getTestPath(), Lists.newArrayList(entries), getNamePathMapper());
}
protected AbstractAccessControlList createACL(@NotNull List<JackrabbitAccessControlEntry> entries) {
return createACL(getTestPath(), entries, getNamePathMapper());
}
protected AbstractAccessControlList createACL(@Nullable String jcrPath,
@NotNull ACE... entries) {
return createACL(jcrPath, Lists.newArrayList(entries), getNamePathMapper());
}
protected AbstractAccessControlList createACL(@Nullable String jcrPath,
@NotNull List<JackrabbitAccessControlEntry> entries,
@NotNull NamePathMapper namePathMapper) {
return createACL(jcrPath, entries, namePathMapper, getRestrictionProvider());
}
protected AbstractAccessControlList createACL(@Nullable String jcrPath,
@NotNull List<JackrabbitAccessControlEntry> entries,
@NotNull NamePathMapper namePathMapper,
@NotNull RestrictionProvider restrictionProvider) {
return new TestACL(jcrPath, restrictionProvider, namePathMapper, entries);
}
protected List<JackrabbitAccessControlEntry> createTestEntries() throws RepositoryException {
List<JackrabbitAccessControlEntry> entries = new ArrayList(3);
for (int i = 0; i < 3; i++) {
entries.add(createEntry(
new PrincipalImpl("testPrincipal" + i), PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ), true));
}
return entries;
}
@Test
public void testGetNamePathMapper() throws Exception {
assertSame(getNamePathMapper(), createEmptyACL().getNamePathMapper());
assertSame(NamePathMapper.DEFAULT, createACL(getTestPath(), ImmutableList.<JackrabbitAccessControlEntry>of(), NamePathMapper.DEFAULT).getNamePathMapper());
}
@Test
public void testGetPath() {
NamePathMapper npMapper = mockNamePathMapper(getTestPath());
// map of jcr-path to standard jcr-path
Map<String, String> paths = new HashMap<String, String>();
paths.put(null, null);
paths.put(getTestPath(), getTestPath());
paths.put("/", "/");
paths.put("/jr:testPath", "/jr:testPath");
paths.put("/{http://jackrabbit.apache.org}testPath", "/jr:testPath");
for (String path : paths.keySet()) {
AbstractAccessControlList acl = createACL(path, Collections.<JackrabbitAccessControlEntry>emptyList(), npMapper);
assertEquals(paths.get(path), acl.getPath());
}
}
@Test
public void testGetOakPath() {
NamePathMapper npMapper = mockNamePathMapper(getTestPath());
// map of jcr-path to oak path
Map<String, String> paths = new HashMap<String, String>();
paths.put(null, null);
paths.put(getTestPath(), getTestPath());
paths.put("/", "/");
String oakPath = "/oak:testPath";
paths.put("/jr:testPath", oakPath);
paths.put("/{http://jackrabbit.apache.org}testPath", oakPath);
// test if oak-path is properly set.
for (String path : paths.keySet()) {
AbstractAccessControlList acl = createACL(path, Collections.<JackrabbitAccessControlEntry>emptyList(), npMapper);
assertEquals(paths.get(path), acl.getOakPath());
}
}
private static NamePathMapper mockNamePathMapper(String testPath) {
NamePathMapper npMapper = Mockito.mock(NamePathMapper.class);
when(npMapper.getOakPath("/")).thenReturn("/");
when(npMapper.getOakPath(null)).thenReturn(null);
when(npMapper.getOakPath(testPath)).thenReturn(testPath);
when(npMapper.getOakPath("/jr:testPath")).thenReturn("/oak:testPath");
when(npMapper.getOakPath("/{http://jackrabbit.apache.org}testPath")).thenReturn("/oak:testPath");
when(npMapper.getJcrPath("/")).thenReturn("/");
when(npMapper.getJcrPath(null)).thenReturn(null);
when(npMapper.getJcrPath(testPath)).thenReturn(testPath);
when(npMapper.getJcrPath("/oak:testPath")).thenReturn("/jr:testPath");
when(npMapper.getJcrPath("/{http://jackrabbit.apache.org}testPath")).thenReturn("/jr:testPath");
return npMapper;
}
@Test
public void testEmptyAcl() throws RepositoryException {
AbstractAccessControlList acl = createEmptyACL();
assertNotNull(acl.getAccessControlEntries());
assertNotNull(acl.getEntries());
assertTrue(acl.getAccessControlEntries().length == 0);
assertEquals(acl.getAccessControlEntries().length, acl.getEntries().size());
assertEquals(0, acl.size());
assertTrue(acl.isEmpty());
}
@Test
public void testSize() throws RepositoryException {
AbstractAccessControlList acl = createACL(createTestEntries());
assertEquals(3, acl.size());
}
@Test
public void testIsEmpty() throws RepositoryException {
AbstractAccessControlList acl = createACL(createTestEntries());
assertFalse(acl.isEmpty());
}
@Test
public void testGetEntries() throws RepositoryException {
List<JackrabbitAccessControlEntry> aces = createTestEntries();
AbstractAccessControlList acl = createACL(aces);
assertNotNull(acl.getEntries());
assertNotNull(acl.getAccessControlEntries());
assertEquals(aces.size(), acl.getEntries().size());
assertEquals(aces.size(), acl.getAccessControlEntries().length);
assertTrue(acl.getEntries().containsAll(aces));
assertTrue(Arrays.asList(acl.getAccessControlEntries()).containsAll(aces));
}
@Test
public void testGetRestrictionNames() throws RepositoryException {
AbstractAccessControlList acl = createEmptyACL();
String[] restrNames = acl.getRestrictionNames();
assertNotNull(restrNames);
List<String> names = Lists.newArrayList(restrNames);
for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
assertTrue(names.remove(getNamePathMapper().getJcrName(def.getName())));
}
assertTrue(names.isEmpty());
}
@Test
public void testGetRestrictionType() throws RepositoryException {
AbstractAccessControlList acl = createEmptyACL();
for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
int reqType = acl.getRestrictionType(getNamePathMapper().getJcrName(def.getName()));
assertTrue(reqType > PropertyType.UNDEFINED);
assertEquals(def.getRequiredType().tag(), reqType);
}
}
@Test
public void testGetRestrictionTypeForUnknownName() throws RepositoryException {
AbstractAccessControlList acl = createEmptyACL();
// for backwards compatibility getRestrictionType(String) must return
// UNDEFINED for a unknown restriction name:
assertEquals(PropertyType.UNDEFINED, acl.getRestrictionType("unknownRestrictionName"));
}
@Test
public void testIsMultiValueRestriction() throws RepositoryException {
AbstractAccessControlList acl = createEmptyACL();
for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
boolean isMv = acl.isMultiValueRestriction(getNamePathMapper().getJcrName(def.getName()));
assertEquals(def.getRequiredType().isArray(), isMv);
}
}
@Test
public void testIsMultiValueRestrictionForUnknownName() throws RepositoryException {
assertFalse(createEmptyACL().isMultiValueRestriction("unknownRestrictionName"));
}
}