You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/07/23 15:28:41 UTC
svn commit: r1506037 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/
oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/
oak-core/src/main/java/org/apache/jackrabbit/oak/security/a...
Author: angela
Date: Tue Jul 23 13:28:41 2013
New Revision: 1506037
URL: http://svn.apache.org/r1506037
Log:
OAK-923 : Runtime exception while creating a group (part 2: runtime exception. see comments in the issue for details)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java Tue Jul 23 13:28:41 2013
@@ -34,6 +34,7 @@ import java.util.Collection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
@@ -63,21 +64,21 @@ public class IndexUtils {
/**
* Create a new property index definition below the given {@code indexNode}.
*
- * @param index The oak:index node builder
- * @param indexDefName The name of the new property index.
- * @param reindex {@code true} if the the reindex flag should be turned on.
- * @param unique {@code true} if the index is expected the assert property
- * uniqueness.
- * @param propertyNames The property names that should be indexed.
+ * @param index The oak:index node builder
+ * @param indexDefName The name of the new property index.
+ * @param reindex {@code true} if the the reindex flag should be turned on.
+ * @param unique {@code true} if the index is expected the assert property
+ * uniqueness.
+ * @param propertyNames The property names that should be indexed.
* @param declaringNodeTypeNames The declaring node type names or {@code null}.
* @return the NodeBuilder of the new index definition.
*/
public static NodeBuilder createIndexDefinition(@Nonnull NodeBuilder index,
- @Nonnull String indexDefName,
- boolean reindex,
- boolean unique,
- @Nonnull Collection<String> propertyNames,
- @Nullable Collection<String> declaringNodeTypeNames) {
+ @Nonnull String indexDefName,
+ boolean reindex,
+ boolean unique,
+ @Nonnull Collection<String> propertyNames,
+ @Nullable Collection<String> declaringNodeTypeNames) {
NodeBuilder entry = index.child(indexDefName)
.setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME)
.setProperty(TYPE_PROPERTY_NAME, PropertyIndexEditorProvider.TYPE)
@@ -105,7 +106,7 @@ public class IndexUtils {
@Nonnull String indexDefName,
boolean unique,
@Nonnull String[] propertyNames,
- @Nullable String[] declaringNodeTypeNames) {
+ @Nullable String[] declaringNodeTypeNames) throws RepositoryException {
NodeUtil entry = indexNode.getOrAddChild(indexDefName, INDEX_DEFINITIONS_NODE_TYPE);
entry.setString(TYPE_PROPERTY_NAME, PropertyIndexEditorProvider.TYPE);
entry.setBoolean(REINDEX_PROPERTY_NAME, true);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java Tue Jul 23 13:28:41 2013
@@ -16,9 +16,6 @@
*/
package org.apache.jackrabbit.oak.security.authentication.token;
-import static org.apache.jackrabbit.oak.api.Type.STRING;
-import static org.apache.jackrabbit.oak.core.IdentifierManager.getIdentifier;
-
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@@ -32,9 +29,9 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
import javax.jcr.Credentials;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
@@ -63,13 +60,16 @@ import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.core.IdentifierManager.getIdentifier;
+
/**
* Default implementation of the {@code TokenProvider} interface that keeps login
* tokens in the content repository. As a precondition the configured the user
* management implementation must provide paths for all
* {@link org.apache.jackrabbit.api.security.user.User users} that refer to
* a valid {@link Tree} in the content repository.
- *
+ * <p/>
* <h3>Backwards compatibility with Jackrabbit 2.x</h3>
* For security reasons the nodes storing the token information now have a
* dedicated node type (rep:Token) which has the following definition:
@@ -81,7 +81,7 @@ import org.slf4j.LoggerFactory;
* Consequently the hash of the token and the expiration time of tokens generated
* by this provider can no longer be manipulated using regular JCR item
* modifications.<p>
- *
+ * <p/>
* Existing login tokens generated by Jackrabbit 2.x which are migrated to
* OAK will still be valid (unless they expire) due to the fact that
* {@link #getTokenInfo(String)} and the implementation of the {@link TokenInfo}
@@ -114,6 +114,7 @@ public class TokenProviderImpl implement
private static final char DELIM = '_';
private static final Set<String> RESERVED_ATTRIBUTES = new HashSet(2);
+
static {
RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE);
RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE_EXPIRY);
@@ -145,9 +146,9 @@ public class TokenProviderImpl implement
*
* @param credentials The current credentials.
* @return {@code true} if the specified credentials are {@link SimpleCredentials}
- * or {@link ImpersonationCredentials} and if the (extracted) simple credentials
- * object contain a {@link #TOKEN_ATTRIBUTE} attribute with an empty value;
- * {@code false} otherwise.
+ * or {@link ImpersonationCredentials} and if the (extracted) simple credentials
+ * object contain a {@link #TOKEN_ATTRIBUTE} attribute with an empty value;
+ * {@code false} otherwise.
*/
@Override
public boolean doCreateToken(Credentials credentials) {
@@ -168,7 +169,7 @@ public class TokenProviderImpl implement
*
* @param credentials The current credentials.
* @return A new {@code TokenInfo} or {@code null} if the token could not
- * be created.
+ * be created.
*/
@Override
public TokenInfo createToken(Credentials credentials) {
@@ -196,11 +197,11 @@ public class TokenProviderImpl implement
* expiration time and additional mandatory attributes that will be verified
* during login.
*
- * @param userId The identifier of the user for which a new token should
- * be created.
+ * @param userId The identifier of the user for which a new token should
+ * be created.
* @param attributes The attributes associated with the new token.
* @return A new {@code TokenInfo} or {@code null} if the token could not
- * be created.
+ * be created.
*/
@Override
public TokenInfo createToken(String userId, Map<String, ?> attributes) {
@@ -242,6 +243,8 @@ public class TokenProviderImpl implement
} catch (CommitFailedException e) {
// conflict while committing changes
log.warn(error, e.getMessage());
+ } catch (AccessDeniedException e) {
+ log.warn(error, e.getMessage());
}
} else {
log.warn("Unable to get/create token store for user " + userId);
@@ -256,8 +259,8 @@ public class TokenProviderImpl implement
*
* @param token A valid login token.
* @return The {@code TokenInfo} associated with the specified token or
- * {@code null} of the corresponding information does not exist or is not
- * associated with a valid user.
+ * {@code null} of the corresponding information does not exist or is not
+ * associated with a valid user.
*/
@Override
public TokenInfo getTokenInfo(String token) {
@@ -299,7 +302,7 @@ public class TokenProviderImpl implement
return false;
}
- if (expTime - loginTime <= tokenExpiration/2) {
+ if (expTime - loginTime <= tokenExpiration / 2) {
long expirationTime = loginTime + tokenExpiration;
try {
tokenNode.setDate(TOKEN_ATTRIBUTE_EXPIRY, expirationTime);
@@ -398,7 +401,7 @@ public class TokenProviderImpl implement
} catch (RepositoryException e) {
// error while accessing user.
log.debug("Error while accessing user " + userId + '.', e);
- } catch (CommitFailedException e) {
+ } catch (CommitFailedException e) {
// conflict while creating token store for this user -> refresh and
// try to get the tree from the updated root.
log.debug("Conflict while creating token store -> retrying", e.getMessage());
@@ -414,6 +417,7 @@ public class TokenProviderImpl implement
}
//--------------------------------------------------------------------------
+
/**
* TokenInfo
*/
@@ -518,7 +522,7 @@ public class TokenProviderImpl implement
*
* @param attributeName The attribute name.
* @return {@code true} if the specified {@code attributeName}
- * starts with or equals {@link #TOKEN_ATTRIBUTE}.
+ * starts with or equals {@link #TOKEN_ATTRIBUTE}.
*/
private static boolean isMandatoryAttribute(String attributeName) {
return attributeName != null && attributeName.startsWith(TOKEN_ATTRIBUTE);
@@ -530,9 +534,9 @@ public class TokenProviderImpl implement
* a lazy evaluation in order to avoid testing the defining node type of
* the associated jcr property.
*
- * @param attributeName The attribute name.
+ * @param attributeName The attribute name.
* @return {@code true} if the specified property name doesn't seem
- * to represent repository internal information.
+ * to represent repository internal information.
*/
private static boolean isInfoAttribute(String attributeName) {
String prefix = Text.getNamespacePrefix(attributeName);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Tue Jul 23 13:28:41 2013
@@ -489,13 +489,13 @@ public class AccessControlManagerImpl im
}
/**
- *
* @param oakPath the Oak path as specified with the ac mgr call.
* @param tree the access controlled node.
* @return the new acl tree.
+ * @throws AccessDeniedException In case the new acl tree is not accessible.
*/
@Nonnull
- private Tree createAclTree(@Nullable String oakPath, @Nonnull Tree tree) {
+ private Tree createAclTree(@Nullable String oakPath, @Nonnull Tree tree) throws AccessDeniedException {
if (!AccessControlUtils.isAccessControlled(oakPath, tree, ntMgr)) {
PropertyState mixins = tree.getProperty(JcrConstants.JCR_MIXINTYPES);
String mixinName = AccessControlUtils.getMixinName(oakPath);
@@ -814,7 +814,8 @@ public class AccessControlManagerImpl im
private static final NamedAccessControlPolicy INSTANCE = new ReadPolicy();
- private ReadPolicy() {}
+ private ReadPolicy() {
+ }
@Override
public String getName() {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java Tue Jul 23 13:28:41 2013
@@ -20,8 +20,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
-
-import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import com.google.common.collect.ImmutableMap;
@@ -122,7 +120,7 @@ class PrivilegeDefinitionWriter implemen
}
}
- private void writePrivilegeNode(NodeUtil privilegesNode, PrivilegeDefinition definition) {
+ private void writePrivilegeNode(NodeUtil privilegesNode, PrivilegeDefinition definition) throws RepositoryException {
String name = definition.getName();
NodeUtil privNode = privilegesNode.addChild(name, NT_REP_PRIVILEGE);
if (definition.isAbstract()) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@@ -50,30 +51,30 @@ import static org.apache.jackrabbit.oak.
* with the {@code Tree} associated with a given {@link org.apache.jackrabbit.api.security.user.Group}.
* Depending on the configuration there are two variants on how group members
* are recorded:
- *
+ * <p/>
* <h3>Membership stored in multi-valued property</h3>
* This is the default way of storing membership information with the following
* characteristics:
* <ul>
- * <li>Multivalued property {@link #REP_MEMBERS}</li>
- * <li>Property type: {@link javax.jcr.PropertyType#WEAKREFERENCE}</li>
- * <li>Used if the config option {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} is missing or <4</li>
+ * <li>Multivalued property {@link #REP_MEMBERS}</li>
+ * <li>Property type: {@link javax.jcr.PropertyType#WEAKREFERENCE}</li>
+ * <li>Used if the config option {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} is missing or <4</li>
* </ul>
- *
+ * <p/>
* <h3>Membership stored in individual properties</h3>
* Variant to store group membership based on the
* {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} configuration parameter:
- *
+ * <p/>
* <ul>
- * <li>Membership information stored underneath a {@link #REP_MEMBERS} node hierarchy</li>
- * <li>Individual member information is stored each in a {@link javax.jcr.PropertyType#WEAKREFERENCE}
- * property</li>
- * <li>Node hierarchy is split based on the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE}
- * configuration parameter.</li>
- * <li>{@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} must be greater than 4
- * in order to turn on this behavior</li>
+ * <li>Membership information stored underneath a {@link #REP_MEMBERS} node hierarchy</li>
+ * <li>Individual member information is stored each in a {@link javax.jcr.PropertyType#WEAKREFERENCE}
+ * property</li>
+ * <li>Node hierarchy is split based on the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE}
+ * configuration parameter.</li>
+ * <li>{@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} must be greater than 4
+ * in order to turn on this behavior</li>
* </ul>
- *
+ * <p/>
* <h3>Compatibility</h3>
* This membership provider is able to deal with both options being present in
* the content. If the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} configuration
@@ -102,7 +103,7 @@ class MembershipProvider extends Authori
Set<String> groupPaths = new HashSet<String>();
Set<String> refPaths = identifierManager.getReferences(true, authorizableTree, REP_MEMBERS, NT_REP_GROUP, NT_REP_MEMBERS);
for (String propPath : refPaths) {
- int index = propPath.indexOf('/'+REP_MEMBERS);
+ int index = propPath.indexOf('/' + REP_MEMBERS);
if (index > 0) {
groupPaths.add(propPath.substring(0, index));
} else {
@@ -181,11 +182,11 @@ class MembershipProvider extends Authori
return false;
}
- boolean addMember(Tree groupTree, Tree newMemberTree) {
+ boolean addMember(Tree groupTree, Tree newMemberTree) throws RepositoryException {
return addMember(groupTree, newMemberTree.getName(), getContentID(newMemberTree));
}
- boolean addMember(Tree groupTree, String treeName, String memberContentId) {
+ boolean addMember(Tree groupTree, String treeName, String memberContentId) throws RepositoryException {
if (useMemberNode(groupTree)) {
NodeUtil groupNode = new NodeUtil(groupTree);
NodeUtil membersNode = groupNode.getOrAddChild(REP_MEMBERS, NT_REP_MEMBERS);
@@ -233,10 +234,10 @@ class MembershipProvider extends Authori
* Returns {@code true} if the given {@code newMember} is a Group
* and contains {@code this} Group as declared or inherited member.
*
- * @param newMemberTree The new member to be tested for cyclic membership.
+ * @param newMemberTree The new member to be tested for cyclic membership.
* @param groupContentId The content ID of the group.
* @return true if the 'newMember' is a group and 'this' is an declared or
- * inherited member of it.
+ * inherited member of it.
*/
boolean isCyclicMembership(Tree newMemberTree, String groupContentId) {
if (UserUtility.isType(newMemberTree, AuthorizableType.GROUP)) {
@@ -271,8 +272,7 @@ class MembershipProvider extends Authori
* Returns an iterator of authorizables which includes all indirect members
* of the given iterator of authorizables.
*
- *
- * @param declaredMembers Iterator containing the paths to the declared members.
+ * @param declaredMembers Iterator containing the paths to the declared members.
* @param authorizableType Flag used to filter the result by authorizable type.
* @return Iterator of Authorizable objects
*/
@@ -344,6 +344,7 @@ class MembershipProvider extends Authori
private static final class ProcessedPathPredicate implements Predicate<String> {
private final Set<String> processed = new HashSet<String>();
+
@Override
public boolean apply(@Nullable String path) {
return processed.add(path);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.Iterator;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.query.Query;
@@ -32,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Res
import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -272,21 +274,24 @@ class UserProvider extends AuthorizableB
private NodeUtil createFolderNodes(String authorizableId, String nodeName,
boolean isGroup, String intermediatePath) throws RepositoryException {
String authRoot = (isGroup) ? groupPath : userPath;
+ String folderPath = new StringBuilder()
+ .append(authRoot)
+ .append(getFolderPath(authorizableId, intermediatePath, authRoot)).toString();
NodeUtil folder;
- Tree authTree = root.getTree(authRoot);
- if (!authTree.exists()) {
- folder = new NodeUtil(root.getTree("/"));
- for (String name : Text.explode(authRoot, '/', false)) {
- folder = folder.getOrAddChild(name, NT_REP_AUTHORIZABLE_FOLDER);
+ Tree tree = root.getTree(folderPath);
+ while (!tree.isRoot() && !tree.exists()) {
+ tree = tree.getParent();
+ }
+ if (tree.exists()) {
+ folder = new NodeUtil(tree);
+ String relativePath = PathUtils.relativize(tree.getPath(), folderPath);
+ if (!relativePath.isEmpty()) {
+ folder = folder.getOrAddTree(relativePath, NT_REP_AUTHORIZABLE_FOLDER);
}
} else {
- folder = new NodeUtil(authTree);
+ throw new AccessDeniedException("Missing permission to create intermediate authorizable folders.");
}
- // verification of hierarchy and node types is delegated to UserValidator upon commit
- String folderPath = getFolderPath(authorizableId, intermediatePath, authRoot);
- folder = folder.getOrAddTree(folderPath, NT_REP_AUTHORIZABLE_FOLDER);
-
// test for colliding folder child node.
while (folder.hasChild(nodeName)) {
NodeUtil colliding = folder.getChild(nodeName);
@@ -315,7 +320,7 @@ class UserProvider extends AuthorizableB
StringBuilder sb = new StringBuilder();
if (intermediatePath != null && !intermediatePath.isEmpty()) {
- sb.append(intermediatePath);
+ sb.append(DELIMITER).append(intermediatePath);
} else {
int idLength = authorizableId.length();
StringBuilder segment = new StringBuilder();
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
import javax.jcr.NamespaceRegistry;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -129,7 +130,7 @@ public abstract class AbstractRestrictio
}
@Override
- public void writeRestrictions(String oakPath, Tree aceTree, Set<Restriction> restrictions) {
+ public void writeRestrictions(String oakPath, Tree aceTree, Set<Restriction> restrictions) throws AccessDeniedException {
// validation of the restrictions is delegated to the commit hook
// see #validateRestrictions below
if (!restrictions.isEmpty()) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java Tue Jul 23 13:28:41 2013
@@ -30,6 +30,7 @@ import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
@@ -68,11 +69,6 @@ public class NodeUtil {
}
@Nonnull
- public NameMapper getNameMapper() {
- return mapper;
- }
-
- @Nonnull
public Tree getTree() {
return tree;
}
@@ -101,16 +97,42 @@ public class NodeUtil {
return child.exists() ? new NodeUtil(child, mapper) : null;
}
+ /**
+ * Adds a new child tree with the given name and primary type name.
+ * This method is a shortcut for calling {@link Tree#addChild(String)} and
+ * {@link Tree#setProperty(String, Object, org.apache.jackrabbit.oak.api.Type)}
+ * where the property name is {@link JcrConstants#JCR_PRIMARYTYPE}.
+ * Note, that this method in addition verifies if the created tree exists
+ * and is accessible in order to avoid {@link IllegalStateException} upon
+ * subsequent modification of the new child.
+ *
+ * @param name The name of the child item.
+ * @param primaryTypeName The name of the primary node type.
+ * @return The new child node with the specified name and primary type.
+ * @throws AccessDeniedException If the child does not exist after creation.
+ */
@Nonnull
- public NodeUtil addChild(String name, String primaryNodeTypeName) {
+ public NodeUtil addChild(String name, String primaryTypeName) throws AccessDeniedException {
Tree child = tree.addChild(name);
+ if (!child.exists()) {
+ throw new AccessDeniedException();
+ }
NodeUtil childUtil = new NodeUtil(child, mapper);
- childUtil.setName(JcrConstants.JCR_PRIMARYTYPE, primaryNodeTypeName);
+ childUtil.setName(JcrConstants.JCR_PRIMARYTYPE, primaryTypeName);
return childUtil;
}
+ /**
+ * Combination of {@link #getChild(String)} and {@link #addChild(String, String)}
+ * in case no tree exists with the specified name.
+ *
+ * @param name The name of the child item.
+ * @param primaryTypeName The name of the primary node type.
+ * @return The new child node with the specified name and primary type.
+ * @throws AccessDeniedException If the child does not exist after creation.
+ */
@Nonnull
- public NodeUtil getOrAddChild(String name, String primaryTypeName) {
+ public NodeUtil getOrAddChild(String name, String primaryTypeName) throws AccessDeniedException {
NodeUtil child = getChild(name);
return (child != null) ? child : addChild(name, primaryTypeName);
}
@@ -130,9 +152,11 @@ public class NodeUtil {
* @param primaryTypeName A oak name of a primary node type that is used
* to create the missing trees.
* @return The node util of the tree at the specified {@code relativePath}.
+ * @throws AccessDeniedException If the any intermediate tree does not exist
+ * and cannot be created.
*/
@Nonnull
- public NodeUtil getOrAddTree(String relativePath, String primaryTypeName) {
+ public NodeUtil getOrAddTree(String relativePath, String primaryTypeName) throws AccessDeniedException {
if (relativePath.indexOf('/') == -1) {
return getOrAddChild(relativePath, primaryTypeName);
} else {
@@ -176,8 +200,8 @@ public class NodeUtil {
*
* @param name The name of the property.
* @return the boolean representation of the property state with the given
- * name. This utility returns {@code false} if the property does not exist
- * or is an multivalued property.
+ * name. This utility returns {@code false} if the property does not exist
+ * or is an multivalued property.
*/
public boolean getBoolean(String name) {
return TreeUtil.getBoolean(tree, name);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java Tue Jul 23 13:28:41 2013
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.oak.api;
-import static org.junit.Assert.fail;
-
import java.util.UUID;
import org.apache.jackrabbit.JcrConstants;
@@ -28,13 +26,15 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.Test;
+import static org.junit.Assert.fail;
+
/**
* UniquePropertyTest...
*/
public class UniquePropertyTest {
@Test
- public void testUniqueness() throws CommitFailedException {
+ public void testUniqueness() throws Exception {
Root root = new Oak()
.with(new OpenSecurityProvider())
@@ -42,7 +42,7 @@ public class UniquePropertyTest {
.with(new InitialContent()).createRoot();
NodeUtil node = new NodeUtil(root.getTree("/"));
- String uuid = UUID.randomUUID().toString();
+ String uuid = UUID.randomUUID().toString();
node.setString(JcrConstants.JCR_UUID, uuid);
root.commit();
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java Tue Jul 23 13:28:41 2013
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.oak.securi
import java.security.Principal;
+import javax.jcr.AccessDeniedException;
+
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -71,7 +73,7 @@ public class AccessControlValidatorTest
return new NodeUtil(root.getTree(testPath));
}
- private NodeUtil createAcl() {
+ private NodeUtil createAcl() throws AccessDeniedException {
NodeUtil testRoot = getTestRoot();
testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
@@ -81,7 +83,7 @@ public class AccessControlValidatorTest
return acl;
}
- private static NodeUtil createACE(NodeUtil acl, String aceName, String ntName, String principalName, String... privilegeNames) {
+ private static NodeUtil createACE(NodeUtil acl, String aceName, String ntName, String principalName, String... privilegeNames) throws AccessDeniedException {
NodeUtil ace = acl.addChild(aceName, ntName);
ace.setString(REP_PRINCIPAL_NAME, principalName);
ace.setNames(REP_PRIVILEGES, privilegeNames);
@@ -89,7 +91,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testPolicyWithOutChildOrder() {
+ public void testPolicyWithOutChildOrder() throws AccessDeniedException {
NodeUtil testRoot = getTestRoot();
testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
testRoot.addChild(REP_POLICY, NT_REP_ACL);
@@ -119,7 +121,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddInvalidRepoPolicy() {
+ public void testAddInvalidRepoPolicy() throws Exception {
NodeUtil testRoot = getTestRoot();
testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
NodeUtil policy = getTestRoot().addChild(REP_REPO_POLICY, NT_REP_ACL);
@@ -135,7 +137,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddPolicyWithAcContent() {
+ public void testAddPolicyWithAcContent() throws Exception {
NodeUtil acl = createAcl();
NodeUtil ace = acl.getChild(aceName);
@@ -155,7 +157,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddRepoPolicyWithAcContent() {
+ public void testAddRepoPolicyWithAcContent() throws Exception {
NodeUtil acl = createAcl();
NodeUtil ace = acl.getChild(aceName);
@@ -175,7 +177,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddAceWithAcContent() {
+ public void testAddAceWithAcContent() throws Exception {
NodeUtil acl = createAcl();
NodeUtil ace = acl.getChild(aceName);
@@ -195,7 +197,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddRestrictionWithAcContent() {
+ public void testAddRestrictionWithAcContent() throws Exception {
NodeUtil acl = createAcl();
NodeUtil ace = acl.getChild(aceName);
@@ -215,7 +217,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddIsolatedPolicy() {
+ public void testAddIsolatedPolicy() throws Exception {
String[] policyNames = new String[]{"isolatedACL", REP_POLICY, REP_REPO_POLICY};
NodeUtil node = getTestRoot();
@@ -236,7 +238,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddIsolatedAce() {
+ public void testAddIsolatedAce() throws Exception {
String[] ntNames = new String[]{NT_REP_DENY_ACE, NT_REP_GRANT_ACE};
NodeUtil node = getTestRoot();
@@ -256,7 +258,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testAddIsolatedRestriction() {
+ public void testAddIsolatedRestriction() throws Exception {
NodeUtil node = getTestRoot();
NodeUtil restriction = node.addChild("isolatedRestriction", NT_REP_RESTRICTIONS);
try {
@@ -272,7 +274,7 @@ public class AccessControlValidatorTest
}
@Test
- public void testInvalidPrivilege() {
+ public void testInvalidPrivilege() throws Exception {
NodeUtil acl = createAcl();
String privName = "invalidPrivilegeName";
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java Tue Jul 23 13:28:41 2013
@@ -73,13 +73,13 @@ public class RestrictionProviderImplTest
assertEquals(Type.NAMES, def.getRequiredType());
assertFalse(def.isMandatory());
} else {
- fail("unexpected restriction "+def.getName());
+ fail("unexpected restriction " + def.getName());
}
}
}
@Test
- public void testGetRestrictionPattern() {
+ public void testGetRestrictionPattern() throws Exception {
Map<PropertyState, RestrictionPattern> map = newHashMap();
map.put(PropertyStates.createProperty(REP_GLOB, "/*/jcr:content"), GlobPattern.create("/testPath", "/*/jcr:content"));
List<String> ntNames = ImmutableList.of(JcrConstants.NT_FOLDER, JcrConstants.NT_LINKEDFILE);
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java Tue Jul 23 13:28:41 2013
@@ -21,6 +21,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.query.Query;
import javax.jcr.security.AccessControlEntry;
@@ -32,7 +33,9 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.util.Text;
@@ -43,8 +46,8 @@ import org.junit.Test;
* Testing permission evaluation for user management operations.
*
* @since OAK 1.0 As of OAK user mgt related operations require a specific
- * user management permission (unless the system in configured to behave like
- * jackrabbit 2x).
+ * user management permission (unless the system in configured to behave like
+ * jackrabbit 2x).
*/
public class UserManagementTest extends AbstractEvaluationTest {
@@ -132,7 +135,7 @@ public class UserManagementTest extends
@Test
public void testCreateUser2() throws Exception {
UserManager testUserMgr = getUserManager(testSession);
- Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ Privilege[] privs = privilegesFromNames(new String[]{PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
allow("/", privs);
// creating user should succeed
@@ -153,7 +156,7 @@ public class UserManagementTest extends
@Test
public void testCreateGroup2() throws Exception {
UserManager testUserMgr = getUserManager(testSession);
- Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ Privilege[] privs = privilegesFromNames(new String[]{PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
allow("/", privs);
// creating group should succeed
@@ -162,6 +165,71 @@ public class UserManagementTest extends
}
@Test
+ public void testCreateWithoutReadAccess() throws Exception {
+ UserManager testUserMgr = getUserManager(testSession);
+ deny("/", privilegesFromName(PrivilegeConstants.JCR_READ));
+ allow("/", privilegesFromName(PrivilegeConstants.REP_USER_MANAGEMENT));
+
+ try {
+ Group gr = testUserMgr.createGroup(groupId);
+ testSession.save();
+ fail("Creating group without read-access on the folder node should fail");
+ } catch (AccessDeniedException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testCreateWithIntermediateReadDeny() throws Exception {
+ String path = UserConstants.DEFAULT_GROUP_PATH + "/a/b/c";
+ Node groupRoot = JcrUtils.getOrCreateByPath(path, UserConstants.NT_REP_AUTHORIZABLE_FOLDER, superuser);
+ superuser.save();
+
+ try {
+ deny(UserConstants.DEFAULT_GROUP_PATH, privilegesFromName(Privilege.JCR_READ));
+
+ Privilege[] privs = privilegesFromNames(new String[]{Privilege.JCR_READ, PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ allow(path, privs);
+
+ Group gr = getUserManager(testSession).createGroup(groupId, new PrincipalImpl(groupId), "a/b/c");
+ testSession.save();
+ } finally {
+ superuser.refresh(false);
+ superuser.getNode(UserConstants.DEFAULT_GROUP_PATH + "/a").remove();
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, UserConstants.DEFAULT_GROUP_PATH);
+ if (acl != null) {
+ acMgr.removePolicy(UserConstants.DEFAULT_GROUP_PATH, acl);
+ }
+ superuser.save();
+ }
+ }
+
+ @Test
+ public void testCreateWithIntermediateReadDeny2() throws Exception {
+ String path = UserConstants.DEFAULT_GROUP_PATH + "/a";
+ JcrUtils.getOrCreateByPath(path, UserConstants.NT_REP_AUTHORIZABLE_FOLDER, superuser);
+ superuser.save();
+
+ try {
+ deny(UserConstants.DEFAULT_GROUP_PATH, privilegesFromName(Privilege.JCR_READ));
+
+ Privilege[] privs = privilegesFromNames(new String[]{Privilege.JCR_READ, PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+ allow(path, privs);
+
+ Group gr = getUserManager(testSession).createGroup(groupId, new PrincipalImpl(groupId), "a/b/c");
+ testSession.save();
+ } finally {
+ superuser.refresh(false);
+ superuser.getNode(UserConstants.DEFAULT_GROUP_PATH + "/a").remove();
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, UserConstants.DEFAULT_GROUP_PATH);
+ if (acl != null) {
+ acMgr.removePolicy(UserConstants.DEFAULT_GROUP_PATH, acl);
+ }
+ superuser.save();
+ }
+ }
+
+ @Test
public void testChangePasswordWithoutPermission() throws Exception {
createUser(userId);
@@ -297,7 +365,7 @@ public class UserManagementTest extends
createUser(userId);
// testSession has user-mgt permission -> removal should succeed.
- Privilege[] privs = privilegesFromNames(new String[] {
+ Privilege[] privs = privilegesFromNames(new String[]{
PrivilegeConstants.REP_USER_MANAGEMENT,
PrivilegeConstants.REP_WRITE});
allow("/", privs);
@@ -364,8 +432,8 @@ public class UserManagementTest extends
/**
* @see <a href="https://issues.apache.org/jira/browse/JCR-3412">JCR-3412 :
- * UserManager.findAuthorizables() does not work, if session does not have
- * read access to common root of all user and groups. </a>
+ * UserManager.findAuthorizables() does not work, if session does not have
+ * read access to common root of all user and groups. </a>
*/
@Test
public void testFindAuthorizables() throws Exception {