blob: f64bf77d5b4c618d28822f1c3d6b529b1ff79b57 [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.sling.jcr.jackrabbit.accessmanager.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.Principal;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
import javax.json.JsonValue;
import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
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.PrivilegeConstants;
import org.apache.jackrabbit.value.ValueFactoryImpl;
import org.apache.sling.jcr.base.util.AccessControlUtil;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
/**
*
*/
public class JsonConvertTest {
@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
private AccessControlManager acm;
private Map<String, RestrictionDefinition> srMap;
@Before
public void buildPrivilegesMap() throws RepositoryException {
context.registerService(new RestrictionProviderImpl());
Session session = context.resourceResolver().adaptTo(Session.class);
acm = AccessControlUtil.getAccessControlManager(session);
}
private Privilege priv(String privilegeName) throws RepositoryException {
return acm.privilegeFromName(privilegeName);
}
private RestrictionDefinition rd(String restrictionName) {
if (srMap == null) {
//make a temp map for quick lookup below
@NotNull
RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
srMap.put(restrictionDefinition.getName(), restrictionDefinition);
}
}
return srMap.get(restrictionName);
}
private Value val(String value) {
return ValueFactoryImpl.getInstance().createValue(value);
}
private Value[] vals(String ... value) {
Value[] values = new Value[value.length];
ValueFactory vf = ValueFactoryImpl.getInstance();
for (int i = 0; i < value.length; i++) {
values[i] = vf.createValue(value[i]);
}
return values;
}
/**
* Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#convertToJson(java.security.Principal, java.util.Map, int)}.
*/
@Test
public void testConvertToJson() throws RepositoryException {
Principal principal = new PrincipalImpl("testuser");
LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
lp1.setAllow(true);
LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
lp2.setDeny(true);
LocalPrivilege lp3 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
LocalPrivilege lp4 = new LocalPrivilege(priv(PrivilegeConstants.JCR_NODE_TYPE_MANAGEMENT));
lp4.setAllow(true);
lp4.setAllowRestrictions(Collections.singleton(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello"))));
LocalPrivilege lp5 = new LocalPrivilege(priv(PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL));
lp5.setDeny(true);
lp5.setDenyRestrictions(Collections.singleton(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2"))));
Map<Privilege, LocalPrivilege> entry = new HashMap<>();
entry.put(lp1.getPrivilege(), lp1);
entry.put(lp2.getPrivilege(), lp2);
entry.put(lp3.getPrivilege(), lp3);
entry.put(lp4.getPrivilege(), lp4);
entry.put(lp5.getPrivilege(), lp5);
int order = 1;
JsonObjectBuilder principalObj = JsonConvert.convertToJson(principal, entry, order);
assertNotNull(principalObj);
JsonObject build = principalObj.build();
assertEquals("testuser", build.getString(JsonConvert.KEY_PRINCIPAL));
assertEquals(1, build.getInt(JsonConvert.KEY_ORDER));
JsonObject privilegesObj = build.getJsonObject(JsonConvert.KEY_PRIVILEGES);
assertNotNull(privilegesObj);
assertEquals(4, privilegesObj.size());
JsonValue jsonValue1 = privilegesObj.get(PrivilegeConstants.JCR_READ);
assertTrue(jsonValue1 instanceof JsonObject);
assertTrue(((JsonObject)jsonValue1).getBoolean(JsonConvert.KEY_ALLOW));
JsonValue jsonValue2 = privilegesObj.get(PrivilegeConstants.JCR_WRITE);
assertTrue(jsonValue2 instanceof JsonObject);
assertTrue(((JsonObject)jsonValue2).getBoolean(JsonConvert.KEY_DENY));
JsonValue jsonValue4 = privilegesObj.get(PrivilegeConstants.JCR_NODE_TYPE_MANAGEMENT);
assertTrue(jsonValue4 instanceof JsonObject);
JsonObject allowObj4 = ((JsonObject)jsonValue4).getJsonObject(JsonConvert.KEY_ALLOW);
assertNotNull(allowObj4);
Object globRestrictionObj4 = allowObj4.get(AccessControlConstants.REP_GLOB);
assertTrue(globRestrictionObj4 instanceof JsonString);
assertEquals("/hello", ((JsonString)globRestrictionObj4).getString());
JsonValue jsonValue5 = privilegesObj.get(PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL);
assertTrue(jsonValue5 instanceof JsonObject);
JsonObject allowObj5 = ((JsonObject)jsonValue5).getJsonObject(JsonConvert.KEY_DENY);
assertNotNull(allowObj5);
Object itemNamesRestrictionObj5 = allowObj5.get(AccessControlConstants.REP_ITEM_NAMES);
assertTrue(itemNamesRestrictionObj5 instanceof JsonArray);
assertEquals("item1", ((JsonArray)itemNamesRestrictionObj5).getString(0));
assertEquals("item2", ((JsonArray)itemNamesRestrictionObj5).getString(1));
}
/**
* Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addRestrictions(javax.json.JsonObjectBuilder, java.lang.String, java.util.Set)}.
*/
@Test
public void testAddRestrictions() {
JsonObjectBuilder privilegeObj = Json.createObjectBuilder();
String key = JsonConvert.KEY_ALLOW;
Set<LocalRestriction> restrictions = new HashSet<>();
restrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
restrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
JsonConvert.addRestrictions(privilegeObj, key, restrictions);
JsonObject build = privilegeObj.build();
assertNotNull(build);
JsonObject allowObj = build.getJsonObject(JsonConvert.KEY_ALLOW);
assertNotNull(allowObj);
Object globRestrictionObj = allowObj.get(AccessControlConstants.REP_GLOB);
assertTrue(globRestrictionObj instanceof JsonString);
assertEquals("/hello", ((JsonString)globRestrictionObj).getString());
Object itemNamesRestrictionObj = allowObj.get(AccessControlConstants.REP_ITEM_NAMES);
assertTrue(itemNamesRestrictionObj instanceof JsonArray);
assertEquals("item1", ((JsonArray)itemNamesRestrictionObj).getString(0));
assertEquals("item2", ((JsonArray)itemNamesRestrictionObj).getString(1));
}
/**
* Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addTo(javax.json.JsonObjectBuilder, java.lang.String, java.lang.Object)}.
*/
@Test
public void testAddToJsonObjectBuilderStringObject() throws RepositoryException {
JsonObjectBuilder builder = Json.createObjectBuilder();
String key = JsonConvert.KEY_ALLOW;
Function<JsonObject, Object> doubleFn = json -> json.getJsonNumber(key).doubleValue();
Function<JsonObject, Object> bigDecimalFn = json -> json.getJsonNumber(key).bigDecimalValue();
Function<JsonObject, Object> bigIntegerFn = json -> json.getJsonNumber(key).bigIntegerValue();
Function<JsonObject, Object> longFn = json -> json.getJsonNumber(key).longValue();
Function<JsonObject, Object> intFn = json -> json.getJsonNumber(key).intValue();
Function<JsonObject, Object> booleanFn = json -> json.getBoolean(key);
Function<JsonObject, Object> stringFn = json -> json.getString(key);
Function<JsonObject, Object> privFn = json -> json.getJsonObject(key).getString("name");
ValueFactory vf = ValueFactoryImpl.getInstance();
// data to test [label, value, expectedValueFromJson, lookupFromJsonFn]
Object[][] candidates = new Object[][] {
// JCR Value types
{"JCR double Value", vf.createValue((double)1.1), 1.1, doubleFn},
{"JCR BigDecimal Value", vf.createValue(new BigDecimal("1.1")), new BigDecimal("1.1"), bigDecimalFn},
{"JCR long Value", vf.createValue(1L), 1L, longFn},
{"JCR boolean Value", vf.createValue(true), true, booleanFn},
{"JCR string Value", vf.createValue("hello"), "hello", stringFn},
// non-JCR values
{"byte value", (byte)1, 1, intFn},
{"short value", (short)1, 1, intFn},
{"int value", 1, 1, intFn},
{"long value", 1L, 1L, longFn},
{"BigDecimal value", new BigDecimal("1.1"), new BigDecimal("1.1"), bigDecimalFn},
{"BigInteger value", new BigInteger("1"), new BigInteger("1"), bigIntegerFn},
{"true boolean value", true, true, booleanFn},
{"false boolean value", false, false, booleanFn},
{"float value", (float)1.1, (double)1.1, doubleFn},
{"double value", 1.1, 1.1, doubleFn},
{"string value", "hello", "hello", stringFn},
{"privilege value", priv(PrivilegeConstants.JCR_READ), PrivilegeConstants.JCR_READ, privFn},
{"object value", new StringBuilder().append("hello"), "hello", stringFn}
};
for (Object[] objects : candidates) {
Object value = objects[1];
JsonConvert.addTo(builder, key, value);
JsonObject build = builder.build();
assertNotNull(build);
assertEquals(1, build.size());
@SuppressWarnings("unchecked")
Function<JsonObject, Object> supplier = (Function<JsonObject, Object>)objects[3];
if (objects[2] instanceof Double) {
double epsilon = 0.000001d;
assertEquals(String.format("%s was not the expected value", objects[0]), (double)objects[2], (double)supplier.apply(build), epsilon);
} else {
assertEquals(String.format("%s was not the expected value", objects[0]), objects[2], supplier.apply(build));
}
}
}
/**
* Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addTo(javax.json.JsonArrayBuilder, java.lang.Object)}.
*/
@Test
public void testAddToJsonArrayBuilderObject() {
JsonArrayBuilder builder = Json.createArrayBuilder();
Function<JsonArray, Object> doubleFn = json -> json.getJsonNumber(0).doubleValue();
Function<JsonArray, Object> bigDecimalFn = json -> json.getJsonNumber(0).bigDecimalValue();
Function<JsonArray, Object> bigIntegerFn = json -> json.getJsonNumber(0).bigIntegerValue();
Function<JsonArray, Object> longFn = json -> json.getJsonNumber(0).longValue();
Function<JsonArray, Object> intFn = json -> json.getJsonNumber(0).intValue();
Function<JsonArray, Object> booleanFn = json -> json.getBoolean(0);
Function<JsonArray, Object> stringFn = json -> json.getString(0);
ValueFactory vf = ValueFactoryImpl.getInstance();
// data to test [label, value, expectedValueFromJson, lookupFromJsonFn]
Object[][] candidates = new Object[][] {
// JCR Value types
{"JCR double Value", vf.createValue((double)1.1), 1.1, doubleFn},
{"JCR BigDecimal Value", vf.createValue(new BigDecimal("1.1")), new BigDecimal("1.1"), bigDecimalFn},
{"JCR long Value", vf.createValue(1L), 1L, longFn},
{"JCR boolean Value", vf.createValue(true), true, booleanFn},
{"JCR string Value", vf.createValue("hello"), "hello", stringFn},
// non-JCR values
{"byte value", (byte)1, 1, intFn},
{"short value", (short)1, 1, intFn},
{"int value", 1, 1, intFn},
{"long value", 1L, 1L, longFn},
{"BigDecimal value", new BigDecimal("1.1"), new BigDecimal("1.1"), bigDecimalFn},
{"BigInteger value", new BigInteger("1"), new BigInteger("1"), bigIntegerFn},
{"true boolean value", true, true, booleanFn},
{"false boolean value", false, false, booleanFn},
{"float value", (float)1.1, (double)1.1, doubleFn},
{"double value", 1.1, 1.1, doubleFn},
{"string value", "hello", "hello", stringFn},
{"object value", new StringBuilder().append("hello"), "hello", stringFn}
};
for (Object[] objects : candidates) {
Object value = objects[1];
JsonConvert.addTo(builder, value);
JsonArray build = builder.build();
assertNotNull(build);
assertEquals(1, build.size());
@SuppressWarnings("unchecked")
Function<JsonArray, Object> supplier = (Function<JsonArray, Object>)objects[3];
if (objects[2] instanceof Double) {
double epsilon = 0.000001d;
assertEquals(String.format("%s was not the expected value", objects[0]), (double)objects[2], (double)supplier.apply(build), epsilon);
} else {
assertEquals(String.format("%s was not the expected value", objects[0]), objects[2], supplier.apply(build));
}
}
}
}