blob: ca994bb7453bef758fa2852a0d92bccc72174559 [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.security.authorization.restriction;
import java.util.Set;
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlException;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositePattern;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
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.RestrictionImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Additional tests for {@link CompositeRestrictionProvider} that require a full
* oak repository.
*/
public class CompositeRestrictionProviderTest extends AbstractSecurityTest implements AccessControlConstants {
private RestrictionProvider rp1 = new TestProvider(ImmutableMap.<String, RestrictionDefinition>of(
REP_GLOB, new RestrictionDefinitionImpl(REP_GLOB, Type.STRING, false),
REP_NT_NAMES, new RestrictionDefinitionImpl(REP_NT_NAMES, Type.NAMES, false),
REP_PREFIXES, new RestrictionDefinitionImpl(REP_PREFIXES, Type.STRINGS, false)
));
private RestrictionProvider rp2 = new TestProvider(ImmutableMap.of(
"boolean", new RestrictionDefinitionImpl("boolean", Type.BOOLEAN, true),
"longs", new RestrictionDefinitionImpl("longs", Type.LONGS, false)
));
private RestrictionProvider rp3 = new TestProvider(ImmutableMap.of(
"string", new RestrictionDefinitionImpl("string", Type.STRING, false)),
true
);
private Set<String> supported = ImmutableSet.of("boolean", "longs", REP_NT_NAMES, REP_GLOB);
private RestrictionProvider provider = CompositeRestrictionProvider.newInstance(rp1, rp2);
private ValueFactory vf;
@Override
@Before
public void before() throws Exception {
super.before();
vf = getValueFactory();
}
@Override
@After
public void after() throws Exception {
try {
root.refresh();
} finally {
super.after();
}
}
@Test
public void testReadRestrictions() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
aceNode.setBoolean("boolean", true);
aceNode.setValues("longs", new Value[] {vf.createValue(10), vf.createValue(290)});
aceNode.setString(REP_GLOB, "*");
aceNode.setNames(REP_NT_NAMES); // empty array
aceNode.setString("invalid", "val");
aceNode.setStrings("invalid2", "val1", "val2", "val3");
Set<Restriction> restrictions = provider.readRestrictions("/test", aceNode.getTree());
assertEquals(4, restrictions.size());
for (Restriction r : restrictions) {
String name = r.getDefinition().getName();
if (!supported.contains(name)) {
fail("read unsupported restriction");
}
}
}
@Test
public void testWriteRestrictions() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
Set<Restriction> restrictions = ImmutableSet.of(
provider.createRestriction("/test","boolean", vf.createValue(true)),
provider.createRestriction("/test", "longs"),
provider.createRestriction("/test", REP_GLOB, vf.createValue("*")),
provider.createRestriction("/test", REP_NT_NAMES, vf.createValue("nt:base", PropertyType.NAME), vf.createValue("nt:version", PropertyType.NAME)));
provider.writeRestrictions("/test", aceNode.getTree(), restrictions);
}
@Test
public void testWriteUnsupportedRestrictions() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
Restriction invalid = new RestrictionImpl(PropertyStates.createProperty("invalid", vf.createValue(true)), false);
try {
provider.writeRestrictions("/test", aceNode.getTree(), ImmutableSet.<Restriction>of(invalid));
fail("AccessControlException expected");
} catch (AccessControlException e) {
// success
}
}
@Test
public void testValidateRestrictions() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
NodeUtil rNode = aceNode.addChild(REP_RESTRICTIONS, NT_REP_RESTRICTIONS);
rNode.setBoolean("boolean", true);
rNode.setValues("longs", new Value[] {vf.createValue(10), vf.createValue(290)});
rNode.setString(REP_GLOB, "*");
rNode.setNames(REP_NT_NAMES); // empty array
provider.validateRestrictions("/test", aceNode.getTree());
// remove mandatory restriction
rNode.removeProperty("boolean");
try {
provider.validateRestrictions("/test", aceNode.getTree());
fail("validation should detect missing mandatory restrictions");
} catch (AccessControlException e) {
// success
}
// set with wrong type
rNode.setName("boolean", "nt:base");
try {
provider.validateRestrictions("/test", aceNode.getTree());
fail("validation should detect wrong restriction type");
} catch (AccessControlException e) {
// success
} finally {
rNode.setBoolean("boolean", true);
}
rNode.setStrings(REP_GLOB, "*", "/jcr:content");
try {
provider.validateRestrictions("/test", aceNode.getTree());
fail("validation should detect wrong restriction type (multi vs single valued)");
} catch (AccessControlException e) {
// success
}
}
@Test
public void testValidateRestrictionsAtEntryNode() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
aceNode.setBoolean("boolean", true);
aceNode.setValues("longs", new Value[] {vf.createValue(10), vf.createValue(290)});
aceNode.setString(REP_GLOB, "*");
aceNode.setNames(REP_NT_NAMES); // empty array
provider.validateRestrictions("/test", aceNode.getTree());
}
@Test
public void testValidateInvalidRestrictionDef() throws Exception {
RestrictionProvider rp = CompositeRestrictionProvider.newInstance(rp1, rp3);
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
NodeUtil rNode = aceNode.addChild(REP_RESTRICTIONS, NT_REP_RESTRICTIONS);
rNode.setValues(REP_GLOB, new Value[]{vf.createValue(10), vf.createValue(290)});
try {
rp.validateRestrictions("/test", aceNode.getTree());
fail("Validation must detect invalid restriction definition");
} catch (AccessControlException e) {
// success
}
}
@Test
public void testValidateUnsupportedRestriction() throws Exception {
RestrictionProvider rp = CompositeRestrictionProvider.newInstance(rp1, rp3);
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
NodeUtil rNode = aceNode.addChild(REP_RESTRICTIONS, NT_REP_RESTRICTIONS);
rNode.setString("unsupported", "value");
try {
rp.validateRestrictions("/test", aceNode.getTree());
fail("Validation must detect unsupported restriction");
} catch (AccessControlException e) {
// success
}
}
@Test
public void testGetRestrictionPattern() throws Exception {
NodeUtil aceNode = new NodeUtil(root.getTree("/")).addChild("test", NT_REP_GRANT_ACE);
NodeUtil rNode = aceNode.addChild(REP_RESTRICTIONS, NT_REP_RESTRICTIONS);
rNode.setString(REP_GLOB, "*");
assertFalse(provider.getPattern("/test", aceNode.getTree()) instanceof CompositePattern);
rNode.setBoolean("boolean", true);
rNode.setValues("longs", new Value[]{vf.createValue(10), vf.createValue(290)});
assertTrue(provider.getPattern("/test", rNode.getTree()) instanceof CompositePattern);
}
}