Author: bcarothers
Date: 2009-06-27 22:14:25 -0400 (Sat, 27 Jun 2009)
New Revision: 1067
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNamespaceRegistryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.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 incorporates the feedback-to-date from the forum topic. An additional
"admin" role is added and security checks for permanently registering and
unregistering types and namespaces were added that check for this role. The admin role is
a superset of the readwrite role, which is itself a superset of the readonly role. The
pattern for mapping roles was changed to be <role name>[.<repository
name>[.<workspace name>]] instead of <role name>[.<workspace name>].
Finally, JcrRepository.login was modified to not allow users to log into workspaces to
which they do not have at least readonly access.
JcrWorkspace.getAccessibleWorkspaceNames() was also modified to filter out workspace names
to which the user does not have at least readonly access.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-06-28
00:33:32 UTC (rev 1066)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-06-28
02:14:25 UTC (rev 1067)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr;
+import java.security.AccessControlException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -39,6 +40,7 @@
import org.jboss.dna.graph.JcrMixLexicon;
import org.jboss.dna.graph.JcrNtLexicon;
import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.NamespaceRegistry.Namespace;
/**
@@ -108,17 +110,22 @@
private final Behavior behavior;
private final NamespaceRegistry registry;
private final NamespaceRegistry workspaceRegistry;
+ private final JcrSession session;
- JcrNamespaceRegistry( NamespaceRegistry workspaceRegistry ) {
- this(Behavior.WORKSPACE, null, workspaceRegistry);
+ JcrNamespaceRegistry( NamespaceRegistry workspaceRegistry,
+ JcrSession session ) {
+ this(Behavior.WORKSPACE, null, workspaceRegistry, session);
}
JcrNamespaceRegistry( Behavior behavior,
NamespaceRegistry localRegistry,
- NamespaceRegistry workspaceRegistry ) {
+ NamespaceRegistry workspaceRegistry,
+ JcrSession session ) {
this.behavior = behavior;
this.registry = localRegistry != null ? localRegistry : workspaceRegistry;
this.workspaceRegistry = workspaceRegistry;
+ this.session = session;
+
// Add the built-ins, ensuring we overwrite any badly-initialized values ...
for (Map.Entry<String, String> builtIn :
STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX.entrySet()) {
this.registry.register(builtIn.getKey(), builtIn.getValue());
@@ -126,6 +133,7 @@
assert this.behavior != null;
assert this.registry != null;
assert this.workspaceRegistry != null;
+ assert this.session != null;
}
/**
@@ -272,6 +280,12 @@
// JSR-170 & JSR-283 Workspace namespace registry ...
// --------------------------------------------------
+ try {
+ session.checkPermission((Path)null,
JcrSession.DNA_REGISTER_NAMESPACE_PERMISSION);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+
// Check the zero-length prefix and zero-length URI ...
if (DEFAULT_NAMESPACE_PREFIX.equals(prefix) ||
DEFAULT_NAMESPACE_URI.equals(uri)) {
throw new
NamespaceException(JcrI18n.unableToChangeTheDefaultNamespace.text());
@@ -319,6 +333,16 @@
public synchronized void unregisterNamespace( String prefix )
throws NamespaceException, AccessDeniedException, RepositoryException {
CheckArg.isNotNull(prefix, "prefix");
+
+ // Don't need to check permissions for transient registration/unregistration
+ if (behavior.equals(Behavior.WORKSPACE)) {
+ try {
+ session.checkPermission((Path)null,
JcrSession.DNA_REGISTER_NAMESPACE_PERMISSION);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+ }
+
// Look to see whether the prefix is registered ...
String uri = registry.getNamespaceForPrefix(prefix);
// It is an error to unregister a namespace that is not registered ...
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-06-28
00:33:32 UTC (rev 1066)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-06-28
02:14:25 UTC (rev 1067)
@@ -23,9 +23,11 @@
*/
package org.jboss.dna.jcr;
+import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import javax.jcr.AccessDeniedException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
@@ -40,6 +42,7 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
import org.jboss.dna.jcr.nodetype.InvalidNodeTypeDefinitionException;
import org.jboss.dna.jcr.nodetype.NodeDefinitionTemplate;
import org.jboss.dna.jcr.nodetype.NodeTypeDefinition;
@@ -58,15 +61,19 @@
@Immutable
class JcrNodeTypeManager implements NodeTypeManager {
- private final ExecutionContext context;
+ private final JcrSession session;
private final RepositoryNodeTypeManager repositoryTypeManager;
- JcrNodeTypeManager( ExecutionContext context,
+ JcrNodeTypeManager( JcrSession session,
RepositoryNodeTypeManager repositoryTypeManager ) {
- this.context = context;
+ this.session = session;
this.repositoryTypeManager = repositoryTypeManager;
}
+ private final ExecutionContext context() {
+ return session.getExecutionContext();
+ }
+
/**
* {@inheritDoc}
*
@@ -87,7 +94,7 @@
// Need to return a version of the node type with the current context
for (JcrNodeType type : rawTypes) {
- types.add(type.with(context));
+ types.add(type.with(context()));
}
return new JcrNodeTypeIterator(types);
@@ -99,10 +106,10 @@
* @see javax.jcr.nodetype.NodeTypeManager#getNodeType(java.lang.String)
*/
public JcrNodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException,
RepositoryException {
- Name ntName = context.getValueFactories().getNameFactory().create(nodeTypeName);
+ Name ntName =
context().getValueFactories().getNameFactory().create(nodeTypeName);
JcrNodeType type = repositoryTypeManager.getNodeType(ntName);
if (type != null) {
- type = type.with(context);
+ type = type.with(context());
return type;
}
throw new NoSuchNodeTypeException(JcrI18n.typeNotFound.text(nodeTypeName));
@@ -119,7 +126,7 @@
JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName);
if (nodeType != null) {
- nodeType = nodeType.with(context);
+ nodeType = nodeType.with(context());
}
return nodeType;
@@ -136,7 +143,7 @@
// Need to return a version of the node type with the current context
for (JcrNodeType type : rawTypes) {
- types.add(type.with(context));
+ types.add(type.with(context()));
}
return new JcrNodeTypeIterator(types);
@@ -383,12 +390,20 @@
* name that already exists
* @throws UnsupportedRepositoryOperationException if {@code allowUpdate} is true;
DNA does not allow updating node types at
* this time.
+ * @throws AccessDeniedException if the current session does not have the {@link
JcrSession#DNA_REGISTER_TYPE_PERMISSION
+ * register type permission}.
* @throws RepositoryException if another error occurs
*/
public NodeType registerNodeType( NodeTypeDefinition template,
boolean allowUpdate )
throws InvalidNodeTypeDefinitionException, NodeTypeExistsException,
UnsupportedRepositoryOperationException,
- RepositoryException {
+ AccessDeniedException, RepositoryException {
+
+ try {
+ session.checkPermission((Path)null,
JcrSession.DNA_REGISTER_TYPE_PERMISSION);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
return this.repositoryTypeManager.registerNodeType(template, allowUpdate);
}
@@ -407,12 +422,21 @@
* specifies a node type name that already exists
* @throws UnsupportedRepositoryOperationException if {@code allowUpdate} is true;
DNA does not allow updating node types at
* this time.
+ * @throws AccessDeniedException if the current session does not have the {@link
JcrSession#DNA_REGISTER_TYPE_PERMISSION
+ * register type permission}.
* @throws RepositoryException if another error occurs
*/
public NodeTypeIterator registerNodeTypes( Collection<NodeTypeDefinition>
templates,
boolean allowUpdates )
throws InvalidNodeTypeDefinitionException, NodeTypeExistsException,
UnsupportedRepositoryOperationException,
- RepositoryException {
+ AccessDeniedException, RepositoryException {
+
+ try {
+ session.checkPermission((Path)null,
JcrSession.DNA_REGISTER_TYPE_PERMISSION);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+
return new
JcrNodeTypeIterator(this.repositoryTypeManager.registerNodeTypes(templates,
allowUpdates));
}
@@ -433,8 +457,14 @@
*/
public void unregisterNodeType( Collection<String> nodeTypeNames )
throws NoSuchNodeTypeException, InvalidNodeTypeDefinitionException,
RepositoryException {
- NameFactory nameFactory = this.context.getValueFactories().getNameFactory();
+ NameFactory nameFactory = context().getValueFactories().getNameFactory();
+ try {
+ session.checkPermission((Path)null,
JcrSession.DNA_REGISTER_TYPE_PERMISSION);
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+
Collection<Name> names = new ArrayList<Name>(nodeTypeNames.size());
for (String name : nodeTypeNames) {
names.add(nameFactory.create(name));
@@ -451,7 +481,7 @@
* @throws RepositoryException if another error occurs
*/
public NodeTypeTemplate createNodeTypeTemplate() throws RepositoryException {
- return new JcrNodeTypeTemplate(this.context);
+ return new JcrNodeTypeTemplate(context());
}
/**
@@ -463,7 +493,7 @@
* @throws RepositoryException if another error occurs
*/
public NodeDefinitionTemplate createNodeDefinitionTemplate() throws
RepositoryException {
- return new JcrNodeDefinitionTemplate(this.context);
+ return new JcrNodeDefinitionTemplate(context());
}
/**
@@ -475,6 +505,6 @@
* @throws RepositoryException if another error occurs
*/
public PropertyDefinitionTemplate createPropertyDefinitionTemplate() throws
RepositoryException {
- return new JcrPropertyDefinitionTemplate(this.context);
+ return new JcrPropertyDefinitionTemplate(context());
}
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-06-28 00:33:32
UTC (rev 1066)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-06-28 02:14:25
UTC (rev 1067)
@@ -26,6 +26,7 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.security.AccessControlContext;
+import java.security.AccessControlException;
import java.security.AccessController;
import java.util.Collections;
import java.util.EnumMap;
@@ -428,6 +429,7 @@
// Per JCR 1.0 6.1.1, if the workspaceName is not recognized, a
NoSuchWorkspaceException is thrown
throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(sourceName, workspaceName));
}
+
graph.useWorkspace(workspaceName);
} catch (InvalidWorkspaceException e) {
throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(sourceName, workspaceName),
e);
@@ -440,7 +442,17 @@
// Create the workspace, which will create its own session ...
sessionAttributes = Collections.unmodifiableMap(sessionAttributes);
JcrWorkspace workspace = new JcrWorkspace(this, workspaceName, execContext,
sessionAttributes);
- return workspace.getSession();
+
+ JcrSession session = (JcrSession) workspace.getSession();
+
+ // Need to make sure that the user has access to this session
+ try {
+ session.checkPermission(workspaceName, null,
JcrSession.JCR_READ_PERMISSION);
+ }
+ catch (AccessControlException ace) {
+ throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(sourceName, workspaceName));
+ }
+ return session;
}
/**
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-28 00:33:32 UTC
(rev 1066)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-06-28 02:14:25 UTC
(rev 1067)
@@ -83,7 +83,11 @@
public static final String DNA_READ_PERMISSION = "readonly";
public static final String DNA_WRITE_PERMISSION = "readwrite";
+ public static final String DNA_ADMIN_PERMISSION = "admin";
+ public static final String DNA_REGISTER_NAMESPACE_PERMISSION =
"register_namespace";
+ public static final String DNA_REGISTER_TYPE_PERMISSION = "register_type";
+
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";
@@ -145,7 +149,7 @@
NamespaceRegistry workspaceRegistry = workspaceContext.getNamespaceRegistry();
NamespaceRegistry local = new LocalNamespaceRegistry(workspaceRegistry);
this.executionContext = workspaceContext.with(local);
- this.sessionRegistry = new JcrNamespaceRegistry(Behavior.JSR170_SESSION, local,
workspaceRegistry);
+ this.sessionRegistry = new JcrNamespaceRegistry(Behavior.JSR170_SESSION, local,
workspaceRegistry, this);
this.rootPath =
this.executionContext.getValueFactories().getPathFactory().createRootPath();
// Set up the graph to use for this session (which uses the session's
namespace registry and context) ...
@@ -291,10 +295,16 @@
* Returns whether the authenticated user has the given role.
*
* @param roleName the name of the role to check
+ * @param workspaceName the workspace under which the user must have the role. This
may be different from the current
+ * workspace.
* @return true if the user has the role and is logged in; false otherwise
*/
- final boolean hasRole( String roleName ) {
- return getExecutionContext().getSecurityContext().hasRole(roleName);
+ final boolean hasRole( String roleName,
+ String workspaceName ) {
+ SecurityContext context = getExecutionContext().getSecurityContext();
+
+ return context.hasRole(roleName) || context.hasRole(roleName + "." +
this.repository.getName())
+ || context.hasRole(roleName + "." + this.repository.getName() +
"." + workspaceName);
}
/**
@@ -342,17 +352,19 @@
CheckArg.isNotEmpty(actions, "actions");
- if ("read".equals(actions)) {
- // readonly access is sufficient
- if (hasRole(DNA_READ_PERMISSION) || hasRole(DNA_READ_PERMISSION +
"." + workspaceName)) {
- return;
+ boolean hasPermission = true;
+ for (String action : actions.split(",")) {
+ if (JCR_READ_PERMISSION.equals(action)) {
+ hasPermission &= hasRole(DNA_READ_PERMISSION, workspaceName) ||
hasRole(DNA_WRITE_PERMISSION, workspaceName)
+ || hasRole(DNA_ADMIN_PERMISSION, workspaceName);
+ } else if (DNA_REGISTER_NAMESPACE_PERMISSION.equals(action) ||
DNA_REGISTER_TYPE_PERMISSION.equals(action)) {
+ hasPermission &= hasRole(DNA_ADMIN_PERMISSION, workspaceName);
+ } else {
+ hasPermission &= hasRole(DNA_ADMIN_PERMISSION, workspaceName) ||
hasRole(DNA_WRITE_PERMISSION, workspaceName);
}
}
- // need readwrite access
- if (hasRole(DNA_WRITE_PERMISSION) || hasRole(DNA_WRITE_PERMISSION + "."
+ workspaceName)) {
- return;
- }
+ if (hasPermission) return;
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/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-06-28 00:33:32
UTC (rev 1066)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-06-28 02:14:25
UTC (rev 1067)
@@ -170,9 +170,6 @@
uriProperty, namespaceType);
this.context = context.with(persistentRegistry);
- // Set up and initialize the persistent JCR namespace registry ...
- this.workspaceRegistry = new JcrNamespaceRegistry(persistentRegistry);
-
// Now create a graph with this new execution context ...
this.graph = Graph.create(this.repository.getRepositorySourceName(),
this.repository.getConnectionFactory(), this.context);
this.graph.useWorkspace(workspaceName);
@@ -182,13 +179,17 @@
// This must be initialized after the session
RepositoryNodeTypeManager repoTypeManager =
repository.getRepositoryTypeManager();
- this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(),
repoTypeManager);
+ this.nodeTypeManager = new JcrNodeTypeManager(session, repoTypeManager);
this.queryManager = new JcrQueryManager(this.session);
if (Boolean.valueOf(repository.getOptions().get(Option.PROJECT_NODE_TYPES))) {
Path parentOfTypeNodes =
context.getValueFactories().getPathFactory().create(systemPath, JcrLexicon.NODE_TYPES);
repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
}
+
+ // Set up and initialize the persistent JCR namespace registry ...
+ this.workspaceRegistry = new JcrNamespaceRegistry(persistentRegistry,
this.session);
+
}
final String getSourceName() {
@@ -231,8 +232,20 @@
*/
public String[] getAccessibleWorkspaceNames() throws RepositoryException {
try {
- Set<String> workspaces = graph.getWorkspaces();
- return workspaces.toArray(new String[workspaces.size()]);
+ Set<String> workspaceNamesFromGraph = graph.getWorkspaces();
+ Set<String> workspaceNames = new
HashSet<String>(workspaceNamesFromGraph.size());
+
+ for(String workspaceName : workspaceNamesFromGraph) {
+ try {
+ session.checkPermission(workspaceName, null,
JcrSession.JCR_READ_PERMISSION);
+ workspaceNames.add(workspaceName);
+ }
+ catch (AccessControlException ace) {
+ // Can happen if user doesn't have the privileges to read from
the workspace
+ }
+ }
+
+ return workspaceNames.toArray(new String[workspaceNames.size()]);
} catch (RepositorySourceException e) {
throw new
RepositoryException(JcrI18n.errorObtainingWorkspaceNames.text(getSourceName(),
e.getMessage()), e);
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java 2009-06-28 00:33:32 UTC
(rev 1066)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java 2009-06-28 02:14:25 UTC
(rev 1067)
@@ -2,8 +2,10 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import java.util.Collections;
import javax.jcr.AccessDeniedException;
import javax.jcr.Credentials;
+import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
@@ -12,6 +14,7 @@
import javax.jcr.SimpleCredentials;
import javax.jcr.nodetype.ConstraintViolationException;
import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.jboss.dna.jcr.nodetype.NodeTypeTemplate;
/**
* Additional DNA tests that check for JCR compliance.
@@ -68,6 +71,7 @@
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();
@@ -90,6 +94,21 @@
session.save();
}
+ private void testRegisterNamespace( Session session ) throws Exception {
+ String unusedPrefix = session.getUserID();
+ session.getWorkspace().getNamespaceRegistry().registerNamespace(unusedPrefix,
unusedPrefix);
+ session.getWorkspace().getNamespaceRegistry().unregisterNamespace(unusedPrefix);
+ }
+
+ private void testRegisterType( Session session ) throws Exception {
+ JcrNodeTypeManager nodeTypes =
(JcrNodeTypeManager)session.getWorkspace().getNodeTypeManager();
+ NodeTypeTemplate newType = nodeTypes.createNodeTypeTemplate();
+ String nodeTypeName = session.getUserID() + "Type";
+ newType.setName(nodeTypeName);
+ nodeTypes.registerNodeType(newType, false);
+ nodeTypes.unregisterNodeType(Collections.singleton(nodeTypeName));
+ }
+
private void testWrite( Session session ) throws Exception {
testAddNode(session);
testSetProperty(session);
@@ -97,6 +116,11 @@
testRemoveNode(session);
}
+ private void testAdmin( Session session ) throws Exception {
+ testRegisterNamespace(session);
+ testRegisterType(session);
+ }
+
/**
* Tests that read-only sessions can read nodes by loading all of the children of the
root node
*
@@ -137,6 +161,25 @@
}
/**
+ * Tests that read-only sessions cannot register namespaces or types
+ *
+ * @throws Exception
+ */
+ public void testShouldNotAllowReadOnlySessionToAdmin() throws Exception {
+ session = helper.getReadOnlySession();
+ try {
+ testRegisterNamespace(session);
+ fail("Read-only sessions should not be able to register
namespaces");
+ } catch (AccessDeniedException expected) {
+ }
+ try {
+ testRegisterType(session);
+ fail("Read-only sessions should not be able to register types");
+ } catch (AccessDeniedException expected) {
+ }
+ }
+
+ /**
* Tests that read-write sessions can read nodes by loading all of the children of
the root node
*
* @throws Exception
@@ -157,6 +200,55 @@
}
/**
+ * Tests that read-write sessions cannot register namespaces or types
+ *
+ * @throws Exception
+ */
+ public void testShouldNotAllowReadWriteSessionToAdmin() throws Exception {
+ session = helper.getReadWriteSession();
+ try {
+ testRegisterNamespace(session);
+ fail("Read-write sessions should not be able to register
namespaces");
+ } catch (AccessDeniedException expected) {
+ }
+ try {
+ testRegisterType(session);
+ fail("Read-write sessions should not be able to register types");
+ } catch (AccessDeniedException expected) {
+ }
+ }
+
+ /**
+ * Tests that admin sessions can read nodes by loading all of the children of the
root node
+ *
+ * @throws Exception
+ */
+ public void testShouldAllowAdminSessionToRead() throws Exception {
+ session = helper.getSuperuserSession();
+ testRead(session);
+ }
+
+ /**
+ * Tests that admin sessions can add nodes, remove nodes, set nodes, and set
properties.
+ *
+ * @throws Exception
+ */
+ public void testShouldAllowAdminSessionToWrite() throws Exception {
+ session = helper.getSuperuserSession();
+ testWrite(session);
+ }
+
+ /**
+ * Tests that admin sessions can register namespaces and types
+ *
+ * @throws Exception
+ */
+ public void testShouldAllowAdminSessionToAdmin() throws Exception {
+ session = helper.getSuperuserSession();
+ testAdmin(session);
+ }
+
+ /**
* User defaultuser is configured to have readwrite in "otherWorkspace" and
readonly in the default workspace. This test makes
* sure both work.
*
@@ -181,6 +273,32 @@
session.logout();
}
+ /**
+ * Users should not be able to see workspaces to which they don't at least have
read access.
+ * User 'noaccess' has no access to the default workspace.
+ * @throws Exception
+ */
+ public void testShouldNotSeeWorkspacesWithoutReadPermission() throws Exception {
+ Credentials creds = new SimpleCredentials("noaccess",
"noaccess".toCharArray());
+
+ try {
+ session = helper.getRepository().login(creds);
+ fail("User 'noaccess' with no access to the default workspace
should not be able to log into that workspace");
+ }
+ catch (NoSuchWorkspaceException le) {
+ // Expected
+ }
+
+ session = helper.getRepository().login(creds, "otherWorkspace");
+
+ String[] workspaceNames = session.getWorkspace().getAccessibleWorkspaceNames();
+
+ assertThat(workspaceNames.length, is(1));
+ assertThat(workspaceNames[0], is("otherWorkspace"));
+
+ session.logout();
+ }
+
public void testShouldCopyFromAnotherWorkspace() throws Exception {
session = helper.getSuperuserSession("otherWorkspace");
String nodetype1 = this.getProperty("nodetype");
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNamespaceRegistryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNamespaceRegistryTest.java 2009-06-28
00:33:32 UTC (rev 1066)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNamespaceRegistryTest.java 2009-06-28
02:14:25 UTC (rev 1067)
@@ -31,6 +31,8 @@
import org.jboss.dna.graph.ExecutionContext;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
/**
* @author jverhaeg
@@ -39,11 +41,15 @@
private ExecutionContext executionContext;
private JcrNamespaceRegistry registry;
+ @Mock
+ private JcrSession session;
@Before
public void before() {
+ MockitoAnnotations.initMocks(this);
executionContext = new ExecutionContext();
- registry = new JcrNamespaceRegistry(executionContext.getNamespaceRegistry());
+ registry = new JcrNamespaceRegistry(executionContext.getNamespaceRegistry(),
session);
+
}
protected void assertThatNamespaceIsRegistered( String prefix,
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-28
00:33:32 UTC (rev 1066)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-06-28
02:14:25 UTC (rev 1067)
@@ -30,6 +30,7 @@
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Credentials;
@@ -208,7 +209,10 @@
@Test
public void shouldAllowLoginWithProperCredentials() throws Exception {
repository.login(credentials);
- repository.login(new SecurityContextCredentials(new MockSecurityContext(null)));
+ repository.login(new SecurityContextCredentials(
+ new MockSecurityContext(
+ null,
+
Collections.singleton(JcrSession.DNA_ADMIN_PERMISSION))));
}
@Test
@@ -216,7 +220,11 @@
Session session = repository.login(credentials, null);
assertThat(session, notNullValue());
session.logout();
- session = repository.login(new SecurityContextCredentials(new
MockSecurityContext(null)), (String)null);
+ session = repository.login(new SecurityContextCredentials(
+ new
MockSecurityContext(
+
null,
+
Collections.singleton(JcrSession.DNA_ADMIN_PERMISSION))),
+ (String)null);
assertThat(session, notNullValue());
session.logout();
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-06-28
00:33:32 UTC (rev 1066)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-06-28
02:14:25 UTC (rev 1067)
@@ -114,7 +114,7 @@
throw new IllegalStateException("Could not access node type definition
files", ioe);
}
- nodeTypes = new JcrNodeTypeManager(this.context, repoTypes);
+ nodeTypes = new JcrNodeTypeManager(this.session, repoTypes);
stub(session.nodeTypeManager()).toReturn(nodeTypes);
// Now set up the graph and session cache ...
Modified: trunk/dna-jcr/src/test/resources/security/tck_roles.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/security/tck_roles.properties 2009-06-28 00:33:32 UTC
(rev 1066)
+++ trunk/dna-jcr/src/test/resources/security/tck_roles.properties 2009-06-28 02:14:25 UTC
(rev 1067)
@@ -1,6 +1,7 @@
#<userName>=[readonly[.<workspaceName>] |
readwrite[.<workspaceName>]][, [readonly[.<workspaceName>] |
readwrite[.<workspaceName>]]]*
-superuser=readwrite
+superuser=admin
readwrite=readwrite
readonly=readonly
# default workspace name is the empty string
-defaultonly=readwrite.,readonly.otherWorkspace
+defaultonly=readwrite.Store.,readonly.Store.otherWorkspace
+noaccess=readonly.Store.otherWorkspace
Modified: trunk/dna-jcr/src/test/resources/security/tck_users.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/security/tck_users.properties 2009-06-28 00:33:32 UTC
(rev 1066)
+++ trunk/dna-jcr/src/test/resources/security/tck_users.properties 2009-06-28 02:14:25 UTC
(rev 1067)
@@ -3,3 +3,4 @@
readwrite=readwrite
readonly=readonly
defaultonly=defaultonly
+noaccess=noaccess