Author: angela
Date: Thu Nov 14 15:28:17 2013
New Revision: 1541930
URL: http://svn.apache.org/r1541930
Log:
OAK-527: permissions (wip)
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java?rev=1541930&r1=1541929&r2=1541930&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
Thu Nov 14 15:28:17 2013
@@ -58,42 +58,54 @@ class PermissionValidator extends Defaul
PermissionValidator(Tree parentBefore, Tree parentAfter,
PermissionProvider permissionProvider,
PermissionValidatorProvider provider) {
- this(parentBefore, parentAfter,
- permissionProvider.getTreePermission(parentBefore,
TreePermission.EMPTY),
- permissionProvider, provider, Permissions.NO_PERMISSION);
+ this.parentBefore = parentBefore;
+ this.parentAfter = parentAfter;
+ this.parentPermission =
permissionProvider.getTreePermission(parentBefore, TreePermission.EMPTY);
+
+ this.permissionProvider = permissionProvider;
+ this.provider = provider;
+
+ permission = Permissions.getPermission(getPath(parentBefore,
parentAfter), Permissions.NO_PERMISSION);
}
private PermissionValidator(Tree parentBefore, Tree parentAfter,
@Nullable TreePermission parentPermission,
- PermissionProvider permissionProvider,
- PermissionValidatorProvider provider,
- long permission) {
- this.permissionProvider = permissionProvider;
- this.provider = provider;
+ @Nonnull PermissionValidator parentValidator) {
this.parentBefore = parentBefore;
this.parentAfter = parentAfter;
this.parentPermission = parentPermission;
- if (Permissions.NO_PERMISSION == permission) {
+
+ permissionProvider = parentValidator.permissionProvider;
+ provider = parentValidator.provider;
+
+ if (Permissions.NO_PERMISSION == parentValidator.permission) {
this.permission = Permissions.getPermission(getPath(parentBefore,
parentAfter), Permissions.NO_PERMISSION);
} else {
- this.permission = permission;
+ this.permission = parentValidator.permission;
}
}
//----------------------------------------------------------< Validator
>---
@Override
public void propertyAdded(PropertyState after) throws
CommitFailedException {
- checkPermissions(parentAfter, after, Permissions.ADD_PROPERTY);
+ String name = after.getName();
+ if (!AbstractTree.OAK_CHILD_ORDER.equals(name)) {
+ checkPermissions(parentAfter, after, Permissions.ADD_PROPERTY);
+ }
}
@Override
public void propertyChanged(PropertyState before, PropertyState after)
throws CommitFailedException {
- if (AbstractTree.OAK_CHILD_ORDER.equals(after.getName())) {
+ String name = after.getName();
+ if (AbstractTree.OAK_CHILD_ORDER.equals(name)) {
String childName = ChildOrderDiff.firstReordered(before, after);
if (childName != null) {
Tree child = parentAfter.getChild(childName);
checkPermissions(child, false,
Permissions.MODIFY_CHILD_NODE_COLLECTION);
} // else: no re-order but only internal update
+ } else if (isImmutableProperty(name)) {
+ // parent node has been removed and and re-added as
+ checkPermissions(parentAfter, false,
Permissions.ADD_NODE|Permissions.REMOVE_NODE);
} else {
checkPermissions(parentAfter, after, Permissions.MODIFY_PROPERTY);
}
@@ -101,7 +113,9 @@ class PermissionValidator extends Defaul
@Override
public void propertyDeleted(PropertyState before) throws
CommitFailedException {
- checkPermissions(parentBefore, before, Permissions.REMOVE_PROPERTY);
+ if (!AbstractTree.OAK_CHILD_ORDER.equals(before.getName())) {
+ checkPermissions(parentBefore, before,
Permissions.REMOVE_PROPERTY);
+ }
}
@Override
@@ -137,7 +151,7 @@ class PermissionValidator extends Defaul
//------------------------------------------------------------< private
>---
private Validator nextValidator(@Nullable Tree parentBefore, @Nullable
Tree parentAfter, @Nonnull TreePermission treePermission) {
- Validator validator = new PermissionValidator(parentBefore,
parentAfter, treePermission, permissionProvider, provider, permission);
+ Validator validator = new PermissionValidator(parentBefore,
parentAfter, treePermission, this);
return new VisibleValidator(validator, true, false);
}
@@ -172,11 +186,14 @@ class PermissionValidator extends Defaul
return;
}
long toTest = getPermission(parent, property, defaultPermission);
+ boolean isGranted;
if (Permissions.isRepositoryPermission(toTest)) {
- if
(!permissionProvider.getRepositoryPermission().isGranted(toTest)) {
- throw new CommitFailedException(ACCESS, 0, "Access denied");
- }
- } else if (!parentPermission.isGranted(toTest, property)) {
+ isGranted =
permissionProvider.getRepositoryPermission().isGranted(toTest);
+ } else {
+ isGranted = parentPermission.isGranted(toTest, property);
+ }
+
+ if (!isGranted) {
throw new CommitFailedException(ACCESS, 0, "Access denied");
}
}
@@ -228,7 +245,10 @@ class PermissionValidator extends Defaul
} else if (JcrConstants.JCR_MIXINTYPES.equals(name)) {
perm = Permissions.NODE_TYPE_MANAGEMENT;
} else if (JcrConstants.JCR_UUID.equals(name)) {
- if (provider.getNodeTypeManager().isNodeType(parent,
JcrConstants.MIX_REFERENCEABLE)) {
+ if (isNodeType(parent, JcrConstants.MIX_REFERENCEABLE)) {
+ // property added or removed: jcr:uuid is autocreated in
+ // JCR, thus can't determine here if this was a user supplied
+ // modification or not.
perm = Permissions.NO_PERMISSION;
} else {
/* the parent is not referenceable -> check regular permissions
@@ -262,6 +282,21 @@ class PermissionValidator extends Defaul
}
}
+ private boolean isImmutableProperty(String name) {
+ // TODO: review; cant' rely on autocreated/protected definition as
this doesn't reveal if a given property is expected to be never modified after
creation
+ if (JcrConstants.JCR_UUID.equals(name) && isNodeType(parentAfter,
JcrConstants.MIX_REFERENCEABLE)) {
+ return true;
+ } else if (("jcr:created".equals(name) ||
"jcr:createdBy".equals(name)) && isNodeType(parentAfter, "mix:created")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isNodeType(Tree parent, String ntName) {
+ return provider.getNodeTypeManager().isNodeType(parent, ntName);
+ }
+
private boolean isVersionstorageTree(Tree tree) {
return permission == Permissions.VERSION_MANAGEMENT &&
VersionConstants.REP_VERSIONSTORAGE.equals(TreeUtil.getPrimaryTypeName(tree));
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java?rev=1541930&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
(added)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
Thu Nov 14 15:28:17 2013
@@ -0,0 +1,127 @@
+/*
+ * 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.jcr.security.authorization;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
+import javax.jcr.security.Privilege;
+
+import org.junit.Test;
+
+/**
+ * Testing removing and re-adding node which defines autocreated protected
properties.
+ */
+public abstract class AbstractAutoCreatedPropertyTest extends
AbstractEvaluationTest {
+
+ Node targetNode;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ Node leaf = superuser.getNode(childNPath);
+ targetNode = leaf.addNode(getNodeName());
+ targetNode.addMixin(getMixinName());
+
+ superuser.save();
+ }
+
+ abstract String getNodeName();
+
+ abstract String getMixinName();
+
+ @Test
+ public void testReplaceNode() throws Exception {
+ allow(path, privilegesFromNames(new String[] {
+ Privilege.JCR_MODIFY_PROPERTIES,
+ Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+ testSession.removeItem(targetNode.getPath());
+ Node newNode =
testSession.getNode(childNPath).addNode(targetNode.getName(),
targetNode.getPrimaryNodeType().getName());
+ newNode.addMixin(getMixinName());
+ try {
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ testSession.refresh(false);
+ }
+ }
+
+ @Test
+ public void testReplaceNode2() throws Exception {
+ allow(path, privilegesFromNames(new String[] {
+ Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+ testSession.removeItem(targetNode.getPath());
+ Node newNode =
testSession.getNode(childNPath).addNode(targetNode.getName(),
targetNode.getPrimaryNodeType().getName());
+ newNode.addMixin(getMixinName());
+ try {
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ testSession.refresh(false);
+ }
+ }
+
+ @Test
+ public void testReplaceNode3() throws Exception {
+ allow(path, privilegesFromNames(new String[] {
+ Privilege.JCR_REMOVE_CHILD_NODES,
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+ testSession.removeItem(targetNode.getPath());
+ Node newNode =
testSession.getNode(childNPath).addNode(targetNode.getName(),
targetNode.getPrimaryNodeType().getName());
+ newNode.addMixin(getMixinName());
+ try {
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ testSession.refresh(false);
+ }
+ }
+
+ @Test
+ public void testReplaceNode4() throws Exception {
+ allow(path, privilegesFromNames(new String[] {
+ Privilege.JCR_ADD_CHILD_NODES,
+ Privilege.JCR_REMOVE_NODE,
+ Privilege.JCR_REMOVE_CHILD_NODES,
+ Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+ testSession.removeItem(targetNode.getPath());
+ Node newNode =
testSession.getNode(childNPath).addNode(targetNode.getName(),
targetNode.getPrimaryNodeType().getName());
+ newNode.addMixin(getMixinName());
+ testSession.save();
+ }
+
+ @Test
+ public void testRemoveReAddMixin() throws Exception {
+ allow(path, privilegesFromNames(new String[] {
+ Privilege.JCR_ADD_CHILD_NODES,
+ Privilege.JCR_REMOVE_NODE,
+ Privilege.JCR_REMOVE_CHILD_NODES}));
+
+ try {
+ Node refNode = testSession.getNode(targetNode.getPath());
+ refNode.removeMixin(getMixinName());
+ refNode.addMixin(getMixinName());
+ testSession.save();
+ fail();
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+}
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java?rev=1541930&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
(added)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
Thu Nov 14 15:28:17 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.security.authorization;
+
+/**
+ * Implementation of {@code AbstractAutoCreatedPropertyTest} for mix:created
+ * nodes.
+ */
+public class MixCreatedTest extends AbstractAutoCreatedPropertyTest {
+
+ String getNodeName() {
+ return "mixCreated";
+ }
+
+ String getMixinName() {
+ return "mix:created";
+ }
+}
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java?rev=1541930&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
(added)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
Thu Nov 14 15:28:17 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.security.authorization;
+
+/**
+ * Implementation of {@code AbstractAutoCreatedPropertyTest} for
mix:referenceable
+ * nodes.
+ */
+public class MixReferenceableTest extends AbstractAutoCreatedPropertyTest {
+
+ String getNodeName() {
+ return "referenceable";
+ }
+
+ String getMixinName() {
+ return mixReferenceable;
+ }
+}