Author: bcarothers
Date: 2009-06-11 21:07:00 -0400 (Thu, 11 Jun 2009)
New Revision: 1047
Added:
trunk/dna-jcr/.settings/
trunk/dna-jcr/.settings/org.eclipse.jdt.core.prefs
trunk/dna-jcr/.settings/org.eclipse.wst.common.component
trunk/dna-jcr/.settings/org.eclipse.wst.common.project.facet.core.xml
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
trunk/dna-jcr/src/test/resources/security/tck_roles.properties
trunk/dna-jcr/src/test/resources/security/tck_users.properties
Log:
DNA-399 Need to Add Session.checkPermission Calls to Guard Read, Add Node, Set Property,
and Remove Item Access
Applied patch that adds permission checks to item reads, item removes, property
modification and node addition calls and adds a new test case that extends the JR TCK
framework, and adds a new workspace in RepositoryStubImpl creatively named
'otherWorkspace';
Adding the extra workspace will cause some false regressions in the nightly TCK run as it
enables 3 cloning tests that silently passed when there was only one workspace in the
repository.
I will leave this defect open for a few days (and probably post a forum topic) to try to
get some feedback on if this is sufficient security for the 1.0 release. I am curious
whether there is any interest in being able to assign roles on a per repository and
workspace basis in the case of multiple repositories feeding from a single JAAS source, if
there is interest in adding an admin role that is required for type and namespace
registration, or any other needed enhancements.
Added: trunk/dna-jcr/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- trunk/dna-jcr/.settings/org.eclipse.jdt.core.prefs (rev 0)
+++ trunk/dna-jcr/.settings/org.eclipse.jdt.core.prefs 2009-06-12 01:07:00 UTC (rev 1047)
@@ -0,0 +1,7 @@
+#Fri May 15 17:59:45 EDT 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
Added: trunk/dna-jcr/.settings/org.eclipse.wst.common.component
===================================================================
--- trunk/dna-jcr/.settings/org.eclipse.wst.common.component (rev
0)
+++ trunk/dna-jcr/.settings/org.eclipse.wst.common.component 2009-06-12 01:07:00 UTC (rev
1047)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="dna-jcr">
+ <wb-resource deploy-path="/"
source-path="/src/main/java"/>
+ <wb-resource deploy-path="/"
source-path="/src/main/resources"/>
+ <wb-resource deploy-path="/"
source-path="/src/test/java"/>
+ <wb-resource deploy-path="/"
source-path="/src/test/resources"/>
+ </wb-module>
+</project-modules>
Added: trunk/dna-jcr/.settings/org.eclipse.wst.common.project.facet.core.xml
===================================================================
--- trunk/dna-jcr/.settings/org.eclipse.wst.common.project.facet.core.xml
(rev 0)
+++ trunk/dna-jcr/.settings/org.eclipse.wst.common.project.facet.core.xml 2009-06-12
01:07:00 UTC (rev 1047)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="jst.java" version="6.0"/>
+ <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
Property changes on:
trunk/dna-jcr/.settings/org.eclipse.wst.common.project.facet.core.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-06-11 21:23:33
UTC (rev 1046)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-06-12 01:07:00
UTC (rev 1047)
@@ -478,7 +478,8 @@
// It's just a name, so look for it directly ...
Property property = getProperty(nameFrom(relativePath));
if (property != null) return property;
- throw new PathNotFoundException();
+ I18n msg = JcrI18n.pathNotFoundRelativeTo;
+ throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-06-11 21:23:33 UTC
(rev 1046)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-06-12 01:07:00 UTC
(rev 1047)
@@ -81,9 +81,14 @@
private static final String[] NO_ATTRIBUTES_NAMES = new String[] {};
- private static final String READ_PERMISSION = "readonly";
- private static final String WRITE_PERMISSION = "readwrite";
+ public static final String DNA_READ_PERMISSION = "readonly";
+ public static final String DNA_WRITE_PERMISSION = "readwrite";
+ public static final String JCR_ADD_NODE_PERMISSION = "add_node";
+ public static final String JCR_SET_PROPERTY_PERMISSION = "set_property";
+ public static final String JCR_REMOVE_PERMISSION = "remove";
+ public static final String JCR_READ_PERMISSION = "read";
+
/**
* The repository that created this session.
*/
@@ -305,25 +310,52 @@
this.checkPermission(executionContext.getValueFactories().getPathFactory().create(path),
actions);
}
+ /**
+ * Throws an {@link AccessControlException} if the current user does not have
permission for all of the named actions in the
+ * current workspace, otherwise returns silently.
+ * <p>
+ * The {@code path} parameter is included for future use and is currently ignored
+ * </p>
+ *
+ * @param path the path on which the actions are occurring
+ * @param actions a comma-delimited list of actions to check
+ */
void checkPermission( Path path,
- String actions ) {
+ String actions ) {
+ checkPermission(this.workspace().getName(), path, actions);
+ }
- CheckArg.isNotNull(path, "path");
+ /**
+ * Throws an {@link AccessControlException} if the current user does not have
permission for all of the named actions in the
+ * named workspace, otherwise returns silently.
+ * <p>
+ * The {@code path} parameter is included for future use and is currently ignored
+ * </p>
+ *
+ * @param workspaceName the name of the workspace in which the path exists
+ * @param path the path on which the actions are occurring
+ * @param actions a comma-delimited list of actions to check
+ */
+ void checkPermission( String workspaceName,
+ Path path,
+ String actions ) {
+
CheckArg.isNotEmpty(actions, "actions");
if ("read".equals(actions)) {
// readonly access is sufficient
- if (hasRole(READ_PERMISSION) || hasRole(READ_PERMISSION + "." +
this.workspace.getName())) {
+ if (hasRole(DNA_READ_PERMISSION) || hasRole(DNA_READ_PERMISSION +
"." + workspaceName)) {
return;
}
}
// need readwrite access
- if (hasRole(WRITE_PERMISSION) || hasRole(WRITE_PERMISSION + "." +
this.workspace.getName())) {
+ if (hasRole(DNA_WRITE_PERMISSION) || hasRole(DNA_WRITE_PERMISSION + "."
+ workspaceName)) {
return;
}
- throw new AccessControlException(JcrI18n.permissionDenied.text(path, actions));
+ String pathAsString = path != null ? path.getString(this.namespaces()) :
"<unknown>";
+ throw new AccessControlException(JcrI18n.permissionDenied.text(pathAsString,
actions));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-06-11 21:23:33
UTC (rev 1046)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-06-12 01:07:00
UTC (rev 1047)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr;
+import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -36,6 +37,7 @@
import java.util.Set;
import java.util.Stack;
import java.util.UUID;
+import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
import javax.jcr.ItemExistsException;
@@ -229,6 +231,23 @@
}
/**
+ * Checks whether the current session has the appropriate permissions to perform the
given action.
+ *
+ * @param the node on which the action will be performed
+ * @param action the name of the action to perform, should be "add_node",
"remove", or "set_property"
+ * @throws AccessDeniedException if the current session does not have the requisite
privileges to perform this task
+ * @throws RepositoryException if any other error occurs
+ */
+ private void checkPermission( NodeInfo node,
+ String action ) throws AccessDeniedException,
RepositoryException {
+ try {
+ this.session.checkPermission(SessionCache.this.getPathFor(node), action);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+ }
+
+ /**
* Returns whether the session cache has any pending changes that need to be
executed.
*
* @return true if there are pending changes, or false if there is currently no
changes
@@ -387,11 +406,11 @@
throws ConstraintViolationException, ItemExistsException, RepositoryException {
assert nodeUuid != null;
-
+
if (this.deletedNodes.containsKey(nodeUuid)) {
nodeUuid = this.deletedNodes.get(nodeUuid).getParent();
}
-
+
NodeInfo nodeInfo = findNodeInfo(nodeUuid);
AbstractJcrNode node = findJcrNode(nodeUuid);
@@ -637,9 +656,9 @@
*/
public void save() throws RepositoryException {
if (operations.isExecuteRequired()) {
- for (UUID changedUuid : this.changedNodes.keySet()) {
- checkAgainstTypeDefinitions(changedUuid, false);
- }
+ for (UUID changedUuid : this.changedNodes.keySet()) {
+ checkAgainstTypeDefinitions(changedUuid, false);
+ }
// Execute the batched operations ...
try {
@@ -732,11 +751,11 @@
*/
Set<UUID> uuidsUnderBranch = new HashSet<UUID>();
LinkedList<UUID> peersToCheck = new LinkedList<UUID>();
-
- for (UUID changedUuid : branchUuids) {
- checkAgainstTypeDefinitions(changedUuid, false);
- }
+ for (UUID changedUuid : branchUuids) {
+ checkAgainstTypeDefinitions(changedUuid, false);
+ }
+
for (UUID branchUuid : branchUuids) {
uuidsUnderBranch.add(branchUuid);
ChangedNodeInfo changedNode = changedNodes.get(branchUuid);
@@ -1053,18 +1072,38 @@
* @return the identifier for the property; never null
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
*/
public PropertyId setProperty( Name name,
- JcrValue value ) throws
ConstraintViolationException, RepositoryException {
+ JcrValue value )
+ throws AccessDeniedException, ConstraintViolationException,
RepositoryException {
return setProperty(name, value, true);
}
+ /**
+ * Set the value for the property. If the property does not exist, it will be
added. If the property does exist, the
+ * existing values will be replaced with the supplied value. Protected property
definitions may be considered, based on
+ * the {@code skipProtected} flag.
+ *
+ * @param name the property name; may not be null
+ * @param value the new property values; may not be null
+ * @param skipProtected indicates whether protected property definitions should
be ignored
+ * @return the identifier for the property; never null
+ * @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
+ * definition constraint
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
+ * @throws RepositoryException if any other error occurs
+ */
public PropertyId setProperty( Name name,
JcrValue value,
- boolean skipProtected ) throws
ConstraintViolationException, RepositoryException {
+ boolean skipProtected )
+ throws AccessDeniedException, ConstraintViolationException,
RepositoryException {
assert name != null;
assert value != null;
+
+ SessionCache.this.checkPermission(node,
JcrSession.JCR_SET_PROPERTY_PERMISSION);
+
JcrPropertyDefinition definition = null;
PropertyId id = null;
@@ -1146,12 +1185,13 @@
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws javax.jcr.ValueFormatException
- * @throws RepositoryException
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
+ * @throws RepositoryException if any other error occurs
*/
public PropertyId setProperty( Name name,
Value[] values,
int valueType )
- throws ConstraintViolationException, RepositoryException,
javax.jcr.ValueFormatException {
+ throws AccessDeniedException, ConstraintViolationException,
RepositoryException, javax.jcr.ValueFormatException {
return setProperty(name, values, valueType, true);
}
@@ -1169,16 +1209,18 @@
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws javax.jcr.ValueFormatException
- * @throws RepositoryException
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
+ * @throws RepositoryException if any other error occurs
*/
public PropertyId setProperty( Name name,
Value[] values,
int valueType,
boolean skipProtected )
- throws ConstraintViolationException, RepositoryException,
javax.jcr.ValueFormatException {
+ throws AccessDeniedException, ConstraintViolationException,
RepositoryException, javax.jcr.ValueFormatException {
assert name != null;
assert values != null;
+ SessionCache.this.checkPermission(node,
JcrSession.JCR_SET_PROPERTY_PERMISSION);
checkCardinalityOfExistingProperty(name, true);
int len = values.length;
@@ -1321,8 +1363,12 @@
*
* @param name the property name; may not be null
* @return true if there was a property with the supplied name, or false if no
such property existed
+ * @throws AccessDeniedException if the current session does not have the
requisite permissions to remove this property
+ * @throws RepositoryException if any other error occurs
*/
- public boolean removeProperty( Name name ) {
+ public boolean removeProperty( Name name ) throws AccessDeniedException,
RepositoryException {
+ SessionCache.this.checkPermission(node, JcrSession.JCR_REMOVE_PERMISSION);
+
PropertyInfo info = node.removeProperty(name);
if (info != null) {
operations.remove(name).on(currentLocation);
@@ -1416,8 +1462,8 @@
if (!definition.getId().equals(node.getDefinitionId())) {
// The node definition changed, so try to set the property ...
try {
- JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, definition.getId()
-
.getString());
+ JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING,
+ definition.getId().getString());
setProperty(DnaIntLexicon.NODE_DEFINITON, value);
} catch (ConstraintViolationException e) {
// We can't set this property on the node (according to the node
definition).
@@ -1521,12 +1567,16 @@
* @throws InvalidItemStateException if the specified child has been marked for
deletion within this session
* @throws ConstraintViolationException if moving the node into this node
violates this node's definition
* @throws NoSuchNodeTypeException if the node type for the primary type could
not be found
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs while reading
information from the repository
*/
public ChildNode createChild( Name name,
UUID desiredUuid,
Name primaryTypeName )
- throws InvalidItemStateException, ConstraintViolationException,
RepositoryException {
+ throws InvalidItemStateException, ConstraintViolationException,
AccessDeniedException, RepositoryException {
+
+ SessionCache.this.checkPermission(node, JcrSession.JCR_ADD_NODE_PERMISSION);
+
if (desiredUuid == null) desiredUuid = UUID.randomUUID();
// Verify that this node accepts a child of the supplied name (given any
existing SNS nodes) ...
@@ -1666,9 +1716,13 @@
* and haven't been persisted.
*
* @param nodeUuid the UUID of the child node; may not be null
+ * @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
+ * @throws RepositoryException if any other error occurs
* @return true if the child was successfully removed, or false if the node did
not exist as a child
*/
- public boolean destroyChild( UUID nodeUuid ) {
+ public boolean destroyChild( UUID nodeUuid ) throws AccessDeniedException,
RepositoryException {
+ SessionCache.this.checkPermission(node, JcrSession.JCR_REMOVE_PERMISSION);
+
ChildNode deleted = node.removeChild(nodeUuid, pathFactory);
if (deleted != null) {
@@ -1812,14 +1866,18 @@
* @see #findNodeInfo(UUID, Path)
* @see #findNodeInfoForRoot()
*/
- NodeInfo findNodeInfo( UUID uuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
+ NodeInfo findNodeInfo( UUID uuid )
+ throws AccessDeniedException, ItemNotFoundException, InvalidItemStateException,
RepositoryException {
assert uuid != null;
// See if we already have something in the cache ...
NodeInfo info = findNodeInfoInCache(uuid);
if (info == null) {
// Nope, so go ahead and load it ...
info = loadFromGraph(uuid, null);
+
}
+ SessionCache.this.checkPermission(info, JcrSession.JCR_READ_PERMISSION);
+
return info;
}
@@ -1903,10 +1961,12 @@
// If the relative path is of zero-length ...
if (relativePath.size() == 0) {
+ SessionCache.this.checkPermission(fromInfo, JcrSession.JCR_READ_PERMISSION);
return fromInfo;
}
// Or it is of length 1 but it is a self reference ...
if (relativePath.size() == 1 &&
relativePath.getLastSegment().isSelfReference()) {
+ SessionCache.this.checkPermission(fromInfo, JcrSession.JCR_READ_PERMISSION);
return fromInfo;
}
@@ -2000,6 +2060,7 @@
}
}
}
+ SessionCache.this.checkPermission(info, JcrSession.JCR_READ_PERMISSION);
return info;
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -26,6 +26,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.io.PrintStream;
+import java.util.Collections;
import java.util.concurrent.TimeUnit;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
@@ -33,6 +34,7 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -90,7 +92,8 @@
repository = new JcrRepository(context, connectionFactory, "unused");
- session = (JcrSession) repository.login(new SecurityContextCredentials(new
MockSecurityContext(null)));
+ SecurityContext mockSecurityContext = new
MockSecurityContext("testuser",
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ session = (JcrSession) repository.login(new
SecurityContextCredentials(mockSecurityContext));
}
@After
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
(rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java 2009-06-12 01:07:00 UTC
(rev 1047)
@@ -0,0 +1,186 @@
+package org.jboss.dna.jcr;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.junit.Test;
+
+/**
+ * Additional DNA tests that check for JCR compliance.
+ *
+ */
+public class DnaTckTest extends AbstractJCRTest {
+
+ Session session;
+
+ protected void tearDown() throws Exception {
+ try {
+ superuser.getRootNode().getNode(this.nodeName1).remove();
+ superuser.save();
+ }
+ catch (PathNotFoundException ignore) { }
+
+ if (session != null) {
+ session.logout();
+ session = null;
+ }
+ super.tearDown();
+ }
+
+ private void testRead(Session session) throws Exception {
+ Node rootNode = session.getRootNode();
+
+ for (NodeIterator iter = rootNode.getNodes(); iter.hasNext(); ) {
+ iter.nextNode();
+ }
+ }
+
+ private void testAddNode(Session session) throws Exception {
+ session.refresh(false);
+ Node root = session.getRootNode();
+ root.addNode(nodeName1, testNodeType);
+ session.save();
+ }
+
+ private void testRemoveNode(Session session) throws Exception {
+ session.refresh(false);
+ Node root = session.getRootNode();
+ Node node = root.getNode(nodeName1);
+ node.remove();
+ session.save();
+ }
+
+ private void testSetProperty(Session session) throws Exception {
+ session.refresh(false);
+ Node root = session.getRootNode();
+ root.setProperty(this.propertyName1, "test value");
+ session.save();
+
+ }
+
+ private void testRemoveProperty(Session session) throws Exception {
+ Session localAdmin =
helper.getRepository().login(helper.getSuperuserCredentials(),
session.getWorkspace().getName());
+ assertEquals(session.getWorkspace().getName(),
superuser.getWorkspace().getName());
+
+ Node superRoot = localAdmin.getRootNode();
+ Node superNode;
+ try {
+ superNode = superRoot.getNode(this.nodeName1);
+ }
+ catch (PathNotFoundException pnfe) {
+ superNode = superRoot.addNode(nodeName1, testNodeType);
+ }
+ superNode.setProperty(this.propertyName1, "test value");
+
+ localAdmin.save();
+ localAdmin.logout();
+
+ session.refresh(false);
+ Node root = session.getRootNode();
+ Node node = root.getNode(nodeName1);
+ Property property = node.getProperty(this.propertyName1);
+ property.remove();
+ session.save();
+ }
+
+ private void testWrite(Session session) throws Exception {
+ testAddNode(session);
+ testSetProperty(session);
+ testRemoveProperty(session);
+ testRemoveNode(session);
+ }
+
+ /**
+ * Tests that read-only sessions can read nodes by loading all of the children of the
root node
+ * @throws Exception
+ */
+ public void testShouldAllowReadOnlySessionToRead() throws Exception {
+ session = helper.getReadOnlySession();
+ testRead(session);
+ }
+
+ /**
+ * Tests that read-only sessions cannot add nodes, remove nodes, set nodes, or set
properties.
+ * @throws Exception
+ */
+ public void testShouldNotAllowReadOnlySessionToWrite() throws Exception {
+ session = helper.getReadOnlySession();
+ try {
+ testAddNode(session);
+ fail("Read-only sessions should not be able to add nodes");
+ }
+ catch (AccessDeniedException expected) {
+ }
+ try {
+ testSetProperty(session);
+ fail("Read-only sessions should not be able to set properties");
+ }
+ catch (AccessDeniedException expected) {
+ }
+ try {
+ testRemoveProperty(session);
+ fail("Read-only sessions should not be able to remove
properties");
+ }
+ catch (AccessDeniedException expected) {
+ }
+ try {
+ testRemoveNode(session);
+ fail("Read-only sessions should not be able to remove nodes");
+ }
+ catch (AccessDeniedException expected) {
+ }
+ }
+
+ /**
+ * Tests that read-write sessions can read nodes by loading all of the children of
the root node
+ * @throws Exception
+ */
+ @Test
+ public void testShouldAllowReadWriteSessionToRead() throws Exception {
+ session = helper.getReadWriteSession();
+ testRead(session);
+ }
+
+ /**
+ * Tests that read-write sessions can add nodes, remove nodes, set nodes, and set
properties.
+ * @throws Exception
+ */
+ @Test
+ public void testShouldAllowReadWriteSessionToWrite() throws Exception {
+ session = helper.getReadWriteSession();
+ testWrite(session);
+ }
+
+ /**
+ * User defaultuser is configured to have readwrite in "otherWorkspace" and
readonly in the default
+ * workspace. This test makes sure both work.
+ * @throws Exception
+ */
+ @Test
+ public void testShouldMapRolesToWorkspacesWhenSpecified() throws Exception {
+ Credentials creds = new SimpleCredentials("defaultonly",
"defaultonly".toCharArray());
+ session = helper.getRepository().login(creds);
+
+ testRead(session);
+ testWrite(session);
+
+ session.logout();
+
+ session = helper.getRepository().login(creds, "otherWorkspace");
+ testRead(session);
+ try {
+ testWrite(session);
+ fail("User 'defaultuser' should not have write access to
'otherWorkspace'");
+ }
+ catch (AccessDeniedException expected) {
+ }
+ session.logout();
+ }
+
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -27,11 +27,13 @@
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.util.Collections;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.Node;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -98,7 +100,8 @@
repository = new JcrRepository(context, connectionFactory, "unused");
- session = (JcrSession) repository.login(new SecurityContextCredentials(new
MockSecurityContext(null)));
+ SecurityContext mockSecurityContext = new
MockSecurityContext("testuser",
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ session = (JcrSession) repository.login(new
SecurityContextCredentials(mockSecurityContext));
}
@After
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-06-11
21:23:33 UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -97,6 +97,8 @@
// URI xmlContent = new
File("src/test/resources/repositoryForTckTests.xml").toURI();
URI xmlContent =
getClass().getClassLoader().getResource("repositoryForTckTests.xml").toURI();
graph.importXmlFrom(xmlContent).into(destinationPath);
+
+ graph.createWorkspace().named("otherWorkspace");
} catch (Exception ex) {
// The TCK tries to quash this exception. Print it out to be more obvious.
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -41,6 +41,8 @@
import javax.jcr.nodetype.PropertyDefinition;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -148,7 +150,8 @@
sessionAttributes.put("attribute1", "value1");
// Now create the workspace ...
- workspace = new JcrWorkspace(repository, workspaceName, context,
sessionAttributes);
+ SecurityContext mockSecurityContext = new
MockSecurityContext("testuser",
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
// Create the session and log in ...
session = (JcrSession)workspace.getSession();
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -184,6 +184,7 @@
repository.login();
}
+ @SuppressWarnings("cast")
@Test
public void shouldAllowLoginWithNoCredentialsInPrivilegedBlock() throws Exception {
LoginContext login = new LoginContext("dna-jcr", new
UserPasswordCallbackHandler("superuser", "superuser".toCharArray()));
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-06-11 21:23:33
UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-06-12 01:07:00
UTC (rev 1047)
@@ -61,6 +61,8 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.JaasSecurityContext;
+import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -154,7 +156,8 @@
sessionAttributes.put("attribute1", "value1");
// Now create the workspace ...
- workspace = new JcrWorkspace(repository, workspaceName, context,
sessionAttributes);
+ SecurityContext mockSecurityContext = new MockSecurityContext(null,
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
// Create the session and log in ...
session = (JcrSession)workspace.getSession();
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -155,8 +155,8 @@
workspace.copy("/a/b", "/b/b-copy");
}
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowCopyFromOtherWorkspace() throws Exception {
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowCopyFromOtherWorkspaceWithNullWorkspace() throws Exception
{
workspace.copy(null, null, null);
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java 2009-06-11 21:23:33 UTC
(rev 1046)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java 2009-06-12 01:07:00 UTC
(rev 1047)
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.stub;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
@@ -43,6 +44,8 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -160,7 +163,8 @@
sessionAttributes = new HashMap<String, Object>();
// Now create the workspace ...
- workspace = new JcrWorkspace(repository, workspaceName, context,
sessionAttributes);
+ SecurityContext mockSecurityContext = new
MockSecurityContext("testuser",
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
// Create the session and log in ...
session = (JcrSession)workspace.getSession();
Modified:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-06-11
21:23:33 UTC (rev 1046)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-06-12
01:07:00 UTC (rev 1047)
@@ -50,6 +50,8 @@
import javax.jcr.version.OnParentVersionAction;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -144,7 +146,8 @@
sessionAttributes.put("attribute1", "value1");
// Now create the workspace ...
- workspace = new JcrWorkspace(repository, workspaceName, context,
sessionAttributes);
+ SecurityContext mockSecurityContext = new
MockSecurityContext("testuser",
Collections.singleton(JcrSession.DNA_READ_PERMISSION));
+ workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
// Create the session and log in ...
session = (JcrSession)workspace.getSession();
Modified: trunk/dna-jcr/src/test/resources/security/tck_roles.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/security/tck_roles.properties 2009-06-11 21:23:33 UTC
(rev 1046)
+++ trunk/dna-jcr/src/test/resources/security/tck_roles.properties 2009-06-12 01:07:00 UTC
(rev 1047)
@@ -2,3 +2,5 @@
superuser=readwrite
readwrite=readwrite
readonly=readonly
+# default workspace name is the empty string
+defaultonly=readwrite.,readonly.otherWorkspace
Modified: trunk/dna-jcr/src/test/resources/security/tck_users.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/security/tck_users.properties 2009-06-11 21:23:33 UTC
(rev 1046)
+++ trunk/dna-jcr/src/test/resources/security/tck_users.properties 2009-06-12 01:07:00 UTC
(rev 1047)
@@ -2,3 +2,4 @@
superuser=superuser
readwrite=readwrite
readonly=readonly
+defaultonly=defaultonly