Author: angela
Date: Mon Feb 9 11:03:21 2015
New Revision: 1658358
URL: http://svn.apache.org/r1658358
Log:
OAK-2485 : Add validating commit hook for login tokens
OAK-2486 : TokenProviderImpl.createToken should always create valid node
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/CommitMarker.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorProvider.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorTest.java
- copied, changed from r1656763,
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConfigurationImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/AbstractTokenTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenInfoTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/CommitMarker.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/CommitMarker.java?rev=1658358&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/CommitMarker.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/CommitMarker.java
Mon Feb 9 11:03:21 2015
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.token;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+
+/**
+ * Marker object to help the {@link
org.apache.jackrabbit.oak.security.authentication.token.TokenValidatorProvider.TokenValidator}
+ * identifying if login tokens have been issued and updated by the {@code
TokenProvider}
+ * implementation provided by this package and not through regular write
+ * operations on the Oak API which doesn't enforce the protected status
+ * of the login tokens as defined by this implementation.
+ */
+final class CommitMarker {
+
+ private static final String KEY = CommitMarker.class.getName();
+
+ private static final CommitMarker INSTANCE = new CommitMarker();
+
+ static Map<String, Object> asCommitAttributes() {
+ return Collections.<String, Object>singletonMap(CommitMarker.KEY,
CommitMarker.INSTANCE);
+ }
+
+ static boolean isValidCommitInfo(@Nonnull CommitInfo commitInfo) {
+ return CommitMarker.INSTANCE ==
commitInfo.getInfo().get(CommitMarker.KEY);
+ }
+
+ private CommitMarker() {}
+}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConfigurationImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConfigurationImpl.java?rev=1658358&r1=1658357&r2=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConfigurationImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConfigurationImpl.java
Mon Feb 9 11:03:21 2015
@@ -16,15 +16,21 @@
*/
package org.apache.jackrabbit.oak.security.authentication.token;
+import java.security.Principal;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.annotation.Nonnull;
+import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
@@ -82,6 +88,13 @@ public class TokenConfigurationImpl exte
return NAME;
}
+ @Nonnull
+ @Override
+ public List<? extends ValidatorProvider> getValidators(String
workspaceName, Set<Principal> principals, MoveTracker moveTracker) {
+ ValidatorProvider vp = new
TokenValidatorProvider(getSecurityProvider().getParameters(UserConfiguration.NAME));
+ return ImmutableList.of(vp);
+ }
+
//-------------------------------------------------< TokenConfiguration
>---
/**
* Returns a new instance of {@link
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenProvider}.
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConstants.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConstants.java?rev=1658358&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConstants.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenConstants.java
Mon Feb 9 11:03:21 2015
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.token;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+
+interface TokenConstants {
+
+ /**
+ * Constant for the token attribute passed with valid simple credentials to
+ * trigger the generation of a new token.
+ */
+ String TOKEN_ATTRIBUTE = ".token";
+ String TOKEN_ATTRIBUTE_EXPIRY = "rep:token.exp";
+ String TOKEN_ATTRIBUTE_KEY = "rep:token.key";
+
+ String TOKENS_NODE_NAME = ".tokens";
+ String TOKENS_NT_NAME = NodeTypeConstants.NT_REP_UNSTRUCTURED;
+
+ String TOKEN_NT_NAME = "rep:Token";
+
+ Set<String> RESERVED_ATTRIBUTES = ImmutableSet.of(
+ TOKEN_ATTRIBUTE,
+ TOKEN_ATTRIBUTE_EXPIRY,
+ TOKEN_ATTRIBUTE_KEY);
+
+ Set<String> TOKEN_PROPERTY_NAMES = ImmutableSet.of(TOKEN_ATTRIBUTE_EXPIRY,
TOKEN_ATTRIBUTE_KEY);
+}
\ No newline at end of file
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=1658358&r1=1658357&r2=1658358&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
Mon Feb 9 11:03:21 2015
@@ -26,9 +26,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
@@ -46,10 +44,9 @@ import org.apache.jackrabbit.oak.api.Com
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.plugins.name.NamespaceConstants;
-import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import
org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
@@ -93,35 +90,17 @@ import static org.apache.jackrabbit.oak.
* interface will not validate the node type of the token node associated with
* a given token.
*/
-class TokenProviderImpl implements TokenProvider {
+class TokenProviderImpl implements TokenProvider, TokenConstants {
private static final Logger log =
LoggerFactory.getLogger(TokenProviderImpl.class);
/**
- * Constant for the token attribute passed with valid simple credentials to
- * trigger the generation of a new token.
- */
- private static final String TOKEN_ATTRIBUTE = ".token";
- private static final String TOKEN_ATTRIBUTE_EXPIRY = "rep:token.exp";
- private static final String TOKEN_ATTRIBUTE_KEY = "rep:token.key";
- private static final String TOKENS_NODE_NAME = ".tokens";
- private static final String TOKENS_NT_NAME =
NodeTypeConstants.NT_REP_UNSTRUCTURED;
- private static final String TOKEN_NT_NAME = "rep:Token";
-
- /**
* Default expiration time in ms for login tokens is 2 hours.
*/
private static final long DEFAULT_TOKEN_EXPIRATION = 2 * 3600 * 1000;
private static final int DEFAULT_KEY_SIZE = 8;
private static final char DELIM = '_';
- private static final Set<String> RESERVED_ATTRIBUTES = new HashSet(3);
- static {
- RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE);
- RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE_EXPIRY);
- RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE_KEY);
- }
-
private final Root root;
private final ConfigurationParameters options;
@@ -133,7 +112,7 @@ class TokenProviderImpl implements Token
this.root = root;
this.options = options;
- this.tokenExpiration = options.getConfigValue(PARAM_TOKEN_EXPIRATION,
Long.valueOf(DEFAULT_TOKEN_EXPIRATION));
+ this.tokenExpiration = options.getConfigValue(PARAM_TOKEN_EXPIRATION,
DEFAULT_TOKEN_EXPIRATION);
this.userManager = userConfiguration.getUserManager(root,
NamePathMapper.DEFAULT);
this.identifierManager = new IdentifierManager(root);
}
@@ -213,16 +192,6 @@ class TokenProviderImpl implements Token
try {
String id = user.getID();
long creationTime = new Date().getTime();
- NodeUtil tokenNode = createTokenNode(tokenParent,
creationTime);
- tokenNode.setString(JcrConstants.JCR_UUID,
IdentifierManager.generateUUID());
-
- String key =
generateKey(options.getConfigValue(PARAM_TOKEN_LENGTH, DEFAULT_KEY_SIZE));
- String nodeId = getIdentifier(tokenNode.getTree());
- String token = new
StringBuilder(nodeId).append(DELIM).append(key).toString();
-
- String keyHash =
PasswordUtil.buildPasswordHash(getKeyValue(key, id), options);
- tokenNode.setString(TOKEN_ATTRIBUTE_KEY, keyHash);
-
long exp;
if (attributes.containsKey(PARAM_TOKEN_EXPIRATION)) {
exp =
Long.parseLong(attributes.get(PARAM_TOKEN_EXPIRATION).toString());
@@ -230,16 +199,21 @@ class TokenProviderImpl implements Token
exp = tokenExpiration;
}
long expTime = createExpirationTime(creationTime, exp);
- tokenNode.setDate(TOKEN_ATTRIBUTE_EXPIRY, expTime);
+ String uuid = UUID.randomUUID().toString();
- for (String name : attributes.keySet()) {
- if (!RESERVED_ATTRIBUTES.contains(name)) {
- String attr = attributes.get(name).toString();
- tokenNode.setString(name, attr);
- }
+ TokenInfo tokenInfo;
+ try {
+ String tokenName = generateTokenName(creationTime);
+ tokenInfo = createTokenNode(tokenParent, tokenName,
expTime, uuid, id, attributes);
+ root.commit(CommitMarker.asCommitAttributes());
+ } catch (CommitFailedException e) {
+ // conflict while creating token node -> retry
+ log.debug("Failed to create token node. Using random name
as fallback.");
+ root.refresh();
+ tokenInfo = createTokenNode(tokenParent,
UUID.randomUUID().toString(), expTime, uuid, id, attributes);
+ root.commit(CommitMarker.asCommitAttributes());
}
- root.commit();
- return new TokenInfoImpl(tokenNode, token, id);
+ return tokenInfo;
} catch (NoSuchAlgorithmException e) {
// error while generating login token
log.error(error, e.getMessage());
@@ -326,7 +300,7 @@ class TokenProviderImpl implements Token
return key + userId;
}
- private static boolean isValidTokenTree(Tree tokenTree) {
+ private static boolean isValidTokenTree(@CheckForNull Tree tokenTree) {
if (tokenTree == null || !tokenTree.exists()) {
return false;
} else {
@@ -335,8 +309,15 @@ class TokenProviderImpl implements Token
}
}
+ @Nonnull
+ private static String generateTokenName(long creationTime) {
+ Calendar creation = GregorianCalendar.getInstance();
+ creation.setTimeInMillis(creationTime);
+ return Text.replace(ISO8601.format(creation), ":", ".");
+ }
+
@CheckForNull
- private Tree getTokenTree(TokenInfo tokenInfo) {
+ private Tree getTokenTree(@Nonnull TokenInfo tokenInfo) {
if (tokenInfo instanceof TokenInfoImpl) {
return root.getTree(((TokenInfoImpl) tokenInfo).tokenPath);
} else {
@@ -345,7 +326,7 @@ class TokenProviderImpl implements Token
}
@CheckForNull
- private String getUserId(Tree tokenTree) {
+ private String getUserId(@CheckForNull Tree tokenTree) {
if (tokenTree != null && tokenTree.exists()) {
try {
String userPath = Text.getRelativeParent(tokenTree.getPath(),
2);
@@ -361,7 +342,7 @@ class TokenProviderImpl implements Token
}
@CheckForNull
- private User getUser(String userId) {
+ private User getUser(@Nonnull String userId) {
try {
Authorizable user = userManager.getAuthorizable(userId);
if (user != null && !user.isGroup()) {
@@ -385,13 +366,12 @@ class TokenProviderImpl implements Token
String parentPath = null;
try {
String userPath = user.getPath();
+ parentPath = userPath + '/' + TOKENS_NODE_NAME;
+
NodeUtil userNode = new NodeUtil(root.getTree(userPath));
- tokenParent = userNode.getChild(TOKENS_NODE_NAME);
- if (tokenParent == null) {
- tokenParent = userNode.addChild(TOKENS_NODE_NAME,
TOKENS_NT_NAME);
- parentPath = userPath + '/' + TOKENS_NODE_NAME;
- root.commit();
- }
+ tokenParent = userNode.getOrAddChild(TOKENS_NODE_NAME,
TOKENS_NT_NAME);
+
+ root.commit();
} catch (RepositoryException e) {
// error while creating token node.
log.debug("Error while creating token node ", e.getMessage());
@@ -400,11 +380,9 @@ class TokenProviderImpl implements Token
// try to get the tree from the updated root.
log.debug("Conflict while creating token store -> retrying",
e.getMessage());
root.refresh();
- if (parentPath != null) {
- Tree parentTree = root.getTree(parentPath);
- if (parentTree.exists()) {
- tokenParent = new NodeUtil(parentTree);
- }
+ Tree parentTree = root.getTree(parentPath);
+ if (parentTree.exists()) {
+ tokenParent = new NodeUtil(parentTree);
}
}
return tokenParent;
@@ -414,25 +392,38 @@ class TokenProviderImpl implements Token
* Create a new token node below the specified {@code parent}.
*
* @param parent The parent node.
- * @param creationTime The creation time that is used as name hint.
- * @return The new token node
- * @throws AccessDeniedException
+ * @param expTime The expiration time of the new token.
+ * @param uuid The uuid of the token node.
+ * @param id The id of the user that issues the token.
+ * @param attributes The additional attributes of the token to be created.
+ * @return The new token info
+ * @throws AccessDeniedException If the editing session cannot access the
+ * new token node.
+ *
*/
- private NodeUtil createTokenNode(@Nonnull NodeUtil parent, @Nonnull long
creationTime) throws AccessDeniedException {
- Calendar creation = GregorianCalendar.getInstance();
- creation.setTimeInMillis(creationTime);
- String tokenName = Text.replace(ISO8601.format(creation), ":", ".");
- NodeUtil tokenNode;
- try {
- tokenNode = parent.addChild(tokenName, TOKEN_NT_NAME);
- root.commit();
- } catch (CommitFailedException e) {
- // conflict while creating token node -> retry
- log.debug("Failed to create token node " + tokenName + ". Using
random name as fallback.");
- root.refresh();
- tokenNode = parent.addChild(UUID.randomUUID().toString(),
TOKEN_NT_NAME);
+ private TokenInfo createTokenNode(@Nonnull NodeUtil parent, @Nonnull
String tokenName,
+ long expTime, @Nonnull String uuid,
+ @Nonnull String id, Map<String, ?>
attributes)
+ throws AccessDeniedException, UnsupportedEncodingException,
NoSuchAlgorithmException {
+
+ NodeUtil tokenNode = parent.addChild(tokenName, TOKEN_NT_NAME);
+ tokenNode.setString(JcrConstants.JCR_UUID, uuid);
+
+ String key = generateKey(options.getConfigValue(PARAM_TOKEN_LENGTH,
DEFAULT_KEY_SIZE));
+ String nodeId = getIdentifier(tokenNode.getTree());
+ String token = nodeId + DELIM + key;
+
+ String keyHash = PasswordUtil.buildPasswordHash(getKeyValue(key, id),
options);
+ tokenNode.setString(TOKEN_ATTRIBUTE_KEY, keyHash);
+ tokenNode.setDate(TOKEN_ATTRIBUTE_EXPIRY, expTime);
+
+ for (String name : attributes.keySet()) {
+ if (!RESERVED_ATTRIBUTES.contains(name)) {
+ String attr = attributes.get(name).toString();
+ tokenNode.setString(name, attr);
+ }
}
- return tokenNode;
+ return new TokenInfoImpl(tokenNode, token, id);
}
//--------------------------------------------------------------------------
@@ -509,7 +500,7 @@ class TokenProviderImpl implements Token
try {
long expTime = createExpirationTime(loginTime,
tokenExpiration);
tokenNode.setDate(TOKEN_ATTRIBUTE_EXPIRY, expTime);
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
log.debug("Successfully reset token expiration time.");
return true;
} catch (CommitFailedException e) {
@@ -527,7 +518,7 @@ class TokenProviderImpl implements Token
if (tokenTree != null && tokenTree.exists()) {
try {
if (tokenTree.remove()) {
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
return true;
}
} catch (CommitFailedException e) {
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorProvider.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorProvider.java?rev=1658358&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorProvider.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorProvider.java
Mon Feb 9 11:03:21 2015
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.token;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtil;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class TokenValidatorProvider extends ValidatorProvider implements
TokenConstants {
+
+ private static final Logger log =
LoggerFactory.getLogger(TokenValidatorProvider.class);
+
+ private final String userRootPath;
+
+ TokenValidatorProvider(@Nonnull ConfigurationParameters userConfig) {
+ userRootPath =
userConfig.getConfigValue(UserConstants.PARAM_USER_PATH,
UserConstants.DEFAULT_USER_PATH);
+ }
+
+ @Override
+ protected Validator getRootValidator(NodeState before, NodeState after,
CommitInfo commitInfo) {
+ return new TokenValidator(before, after, commitInfo);
+ }
+
+ private static CommitFailedException constraintViolation(int code,
@Nonnull String message) {
+ return new CommitFailedException(CommitFailedException.CONSTRAINT,
code, message);
+ }
+
+ private final class TokenValidator extends DefaultValidator implements
TokenConstants {
+
+ private final Tree parentBefore;
+ private final Tree parentAfter;
+ private final CommitInfo commitInfo;
+
+ TokenValidator(@Nonnull NodeState parentBefore, @Nonnull NodeState
parentAfter, @Nonnull CommitInfo commitInfo) {
+ this(TreeFactory.createReadOnlyTree(parentBefore),
TreeFactory.createReadOnlyTree(parentAfter), commitInfo);
+ }
+
+ private TokenValidator(@Nullable Tree parentBefore, @Nonnull Tree
parentAfter, @Nonnull CommitInfo commitInfo) {
+ this.parentBefore = parentBefore;
+ this.parentAfter = parentAfter;
+ this.commitInfo = commitInfo;
+ }
+
+ //------------------------------------------------------< Validator
>---
+
+ @Override
+ public void propertyAdded(PropertyState after) throws
CommitFailedException {
+ String name = after.getName();
+ if (TOKEN_PROPERTY_NAMES.contains(name)) {
+ // ensure that token specific properties are managed by the
token provider.
+ verifyCommitInfo();
+ // make sure they are not solely located with a token node.
+ if (!isTokenTree(parentAfter)) {
+ String msg = "Attempt to create reserved token property "
+ name;
+ throw constraintViolation(60, msg);
+ }
+ }
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after)
throws CommitFailedException {
+ String beforeName = after.getName();
+ if (TOKEN_ATTRIBUTE_KEY.equals(beforeName)) {
+ String msg = "Attempt to change reserved token property " +
beforeName;
+ throw constraintViolation(61, msg);
+ } else if (TOKEN_ATTRIBUTE_EXPIRY.equals(beforeName)) {
+ verifyCommitInfo();
+ } else if (JcrConstants.JCR_PRIMARYTYPE.equals(beforeName)) {
+ if (TOKEN_NT_NAME.equals(after.getValue(Type.STRING))) {
+ throw constraintViolation(62, "Changing primary type of
existing node to the reserved token node type.");
+ }
+ if (isTokensParent(parentAfter) &&
TOKENS_NT_NAME.equals(before.getValue(Type.STRING))) {
+ throw constraintViolation(69, "Cannot change the primary
type of an existing .tokens node.");
+ }
+ }
+ }
+
+ @Override
+ public Validator childNodeAdded(String name, NodeState after) throws
CommitFailedException {
+ Tree tree = checkNotNull(parentAfter.getChild(name));
+
+ if (isTokenTree(tree)) {
+ validateTokenTree(tree);
+ // no further validation required
+ return null;
+ } else if (isTokensParent(tree)) {
+ validateTokensParent(tree);
+ }
+ return new VisibleValidator(new TokenValidator(null, tree,
commitInfo), true, true);
+ }
+
+ @Override
+ public Validator childNodeChanged(String name, NodeState before,
NodeState after) throws CommitFailedException {
+ Tree beforeTree = (parentBefore == null) ? null :
parentBefore.getChild(name);
+ Tree afterTree = parentAfter.getChild(name);
+
+ if (isTokenTree(beforeTree) || isTokenTree(afterTree)) {
+ validateTokenTree(afterTree);
+ } else if (isTokensParent(beforeTree) ||
isTokensParent(afterTree)) {
+ validateTokensParent(afterTree);
+ }
+
+ return new VisibleValidator(new TokenValidator(beforeTree,
afterTree, commitInfo), true, true);
+ }
+
+ //--------------------------------------------------------< private
>---
+ private void verifyCommitInfo() throws CommitFailedException {
+ if (!CommitMarker.isValidCommitInfo(commitInfo)) {
+ throw constraintViolation(63, "Attempt to manually create or
change a token node or it's parent.");
+ }
+ }
+
+ private void verifyHierarchy(@Nonnull String path) throws
CommitFailedException {
+ if (!Text.isDescendant(userRootPath, path)) {
+ String msg = "Attempt to create a token (or it's parent)
outside of configured scope " + path;
+ throw constraintViolation(64, msg);
+ }
+ }
+
+ private boolean isTokenTree(@CheckForNull Tree tree) {
+ return tree != null &&
TOKEN_NT_NAME.equals(TreeUtil.getPrimaryTypeName(tree));
+ }
+
+ private void validateTokenTree(@Nonnull Tree tokenTree) throws
CommitFailedException {
+ // enforce changing being made by the TokenProvider implementation
+ verifyCommitInfo();
+
+ verifyHierarchy(tokenTree.getPath());
+
+ Tree parent = tokenTree.getParent();
+ if (!TOKENS_NODE_NAME.equals(parent.getName()) ||
!UserConstants.NT_REP_USER.equals(TreeUtil.getPrimaryTypeName(parent.getParent())))
{
+ throw constraintViolation(65, "Invalid location of token
node.");
+ }
+
+ // assert mandatory properties are present
+ String key = TreeUtil.getString(tokenTree, TOKEN_ATTRIBUTE_KEY);
+ if (PasswordUtil.isPlainTextPassword(key)) {
+ throw constraintViolation(66, "Invalid token key.");
+ }
+
+ if (TreeUtil.getString(tokenTree, TOKEN_ATTRIBUTE_EXPIRY) == null)
{
+ throw constraintViolation(67, "Mandatory token expiration
missing.");
+ }
+ }
+
+ private boolean isTokensParent(@CheckForNull Tree tree) {
+ return tree != null && TOKENS_NODE_NAME.equals(tree.getName());
+ }
+
+ private void validateTokensParent(@Nonnull Tree tokensParent) throws
CommitFailedException {
+
+ verifyHierarchy(tokensParent.getPath());
+
+ Tree userTree = tokensParent.getParent();
+ if
(!UserConstants.NT_REP_USER.equals(TreeUtil.getPrimaryTypeName(userTree))) {
+ throw constraintViolation(68, "Invalid location of .tokens
node.");
+ }
+
+ String nt = TreeUtil.getPrimaryTypeName(tokensParent);
+ if (!TOKENS_NT_NAME.equals(nt)) {
+ log.debug("Unexpected node type of .tokens node " + nt + '.');
+ }
+ }
+ }
+}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/AbstractTokenTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/AbstractTokenTest.java?rev=1658358&r1=1658357&r2=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/AbstractTokenTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/AbstractTokenTest.java
Mon Feb 9 11:03:21 2015
@@ -16,14 +16,23 @@
*/
package org.apache.jackrabbit.oak.security.authentication.token;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
+
+import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
+import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.Before;
/**
* AbstractTokenTest...
*/
-public abstract class AbstractTokenTest extends AbstractSecurityTest {
+public abstract class AbstractTokenTest extends AbstractSecurityTest
implements TokenConstants {
TokenProviderImpl tokenProvider;
@@ -35,6 +44,33 @@ public abstract class AbstractTokenTest
tokenProvider = new TokenProviderImpl(root,
ConfigurationParameters.EMPTY,
getUserConfiguration());
- root.commit();
+ }
+
+ @Override
+ public void after() throws Exception {
+ try {
+ root.refresh();
+ } finally {
+ super.after();
+ }
+ }
+
+ @CheckForNull
+ Tree getTokenTree(@Nonnull TokenInfo info) {
+ String token = info.getToken();
+ int pos = token.indexOf('_');
+ String nodeId = (pos == -1) ? token : token.substring(0, pos);
+ return new IdentifierManager(root).getTree(nodeId);
+ }
+
+ @Nonnull
+ Tree createTokenTree(@Nonnull TokenInfo base, @Nonnull NodeUtil parent,
+ @Nonnull String ntName) throws AccessDeniedException {
+ Tree tokenTree = getTokenTree(base);
+ Tree tree = parent.addChild("token", ntName).getTree();
+ tree.setProperty(tokenTree.getProperty(JcrConstants.JCR_UUID));
+ tree.setProperty(tokenTree.getProperty(TOKEN_ATTRIBUTE_KEY));
+ tree.setProperty(tokenTree.getProperty(TOKEN_ATTRIBUTE_EXPIRY));
+ return tree;
}
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenInfoTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenInfoTest.java?rev=1658358&r1=1658357&r2=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenInfoTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenInfoTest.java
Mon Feb 9 11:03:21 2015
@@ -103,9 +103,9 @@ public class TokenInfoTest extends Abstr
@Test
public void testGetAttributes() {
Map<String, String> reserved = new HashMap<String, String>();
- reserved.put(".token", "value");
- reserved.put("rep:token.key", "value");
- reserved.put("rep:token.exp", "value");
+ reserved.put(TOKEN_ATTRIBUTE, "value");
+ reserved.put(TOKEN_ATTRIBUTE_KEY, "value");
+ reserved.put(TOKEN_ATTRIBUTE_EXPIRY, "value");
Map<String, String> privateAttributes = new HashMap<String, String>();
privateAttributes.put(".token_exp", "value");
@@ -160,7 +160,7 @@ public class TokenInfoTest extends Abstr
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
- Tree tokens = userTree.getChild(".tokens");
+ Tree tokens = userTree.getChild(TOKENS_NODE_NAME);
String tokenNodePath =
tokens.getChildren().iterator().next().getPath();
info.remove();
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java?rev=1658358&r1=1658357&r2=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
Mon Feb 9 11:03:21 2015
@@ -27,7 +27,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import javax.jcr.AccessDeniedException;
import javax.jcr.Credentials;
import javax.jcr.GuestCredentials;
import javax.jcr.SimpleCredentials;
@@ -39,7 +38,6 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import
org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
@@ -132,9 +130,9 @@ public class TokenProviderImplTest exten
@Test
public void testTokenNode() throws Exception {
Map<String, String> reserved = new HashMap<String, String>();
- reserved.put(".token", "value");
- reserved.put("rep:token.key", "value");
- reserved.put("rep:token.exp", "value");
+ reserved.put(TOKEN_ATTRIBUTE, "value");
+ reserved.put(TOKEN_ATTRIBUTE_KEY, "value");
+ reserved.put(TOKEN_ATTRIBUTE_EXPIRY, "value");
Map<String, String> privateAttributes = new HashMap<String, String>();
privateAttributes.put(".token_exp", "value");
@@ -152,11 +150,11 @@ public class TokenProviderImplTest exten
TokenInfo info = tokenProvider.createToken(userId, attributes);
Tree tokenTree = getTokenTree(info);
- PropertyState prop = tokenTree.getProperty("rep:token.key");
+ PropertyState prop = tokenTree.getProperty(TOKEN_ATTRIBUTE_KEY);
assertNotNull(prop);
assertEquals(Type.STRING, prop.getType());
- prop = tokenTree.getProperty("rep:token.exp");
+ prop = tokenTree.getProperty(TOKEN_ATTRIBUTE_EXPIRY);
assertNotNull(prop);
assertEquals(Type.DATE, prop.getType());
@@ -201,16 +199,15 @@ public class TokenProviderImplTest exten
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
- NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
"nt:unstructured");
+ NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
try {
- createTokenTree(info, node, "rep:Token");
+ createTokenTree(info, node, TOKEN_NT_NAME);
tokenTree.remove();
- root.commit();
assertNull(tokenProvider.getTokenInfo(info.getToken()));
} finally {
node.getTree().remove();
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
}
}
@@ -222,16 +219,14 @@ public class TokenProviderImplTest exten
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
- NodeUtil node = new NodeUtil(userTree).addChild("testNode",
"nt:unstructured");
+ NodeUtil node = new NodeUtil(userTree).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
try {
- createTokenTree(info, node, "rep:Token");
+ createTokenTree(info, node, TOKEN_NT_NAME);
tokenTree.remove();
- root.commit();
assertNull(tokenProvider.getTokenInfo(info.getToken()));
} finally {
- node.getTree().remove();
- root.commit();
+ root.refresh();
}
}
@@ -243,16 +238,14 @@ public class TokenProviderImplTest exten
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
- NodeUtil node = new NodeUtil(userTree.getChild(".tokens"));
+ NodeUtil node = new NodeUtil(userTree.getChild(TOKENS_NODE_NAME));
try {
- createTokenTree(info, node, "nt:unstructured");
+ createTokenTree(info, node, JcrConstants.NT_UNSTRUCTURED);
tokenTree.remove();
- root.commit();
assertNull(tokenProvider.getTokenInfo(info.getToken()));
} finally {
- node.getTree().remove();
- root.commit();
+ root.refresh();
}
}
@@ -266,17 +259,14 @@ public class TokenProviderImplTest exten
TokenInfo info2 = null;
try {
Tree adminTree =
root.getTree(getUserManager(root).getAuthorizable(adminSession.getAuthInfo().getUserID()).getPath());
- NodeUtil node = new NodeUtil(adminTree).getOrAddChild(".tokens",
"nt:unstructured");
- assertTrue(root.move(tokenTree.getPath(), node.getTree().getPath()
+ "/" + tokenTree.getName()));
- root.commit();
+ NodeUtil node = new
NodeUtil(adminTree).getOrAddChild(TOKENS_NODE_NAME,
JcrConstants.NT_UNSTRUCTURED);
+ assertTrue(root.move(tokenTree.getPath(), node.getTree().getPath()
+ '/' + tokenTree.getName()));
info2 = tokenProvider.getTokenInfo(info.getToken());
assertNotNull(info2);
assertFalse(info2.matches(new TokenCredentials(info.getToken())));
} finally {
- Tree t = getTokenTree(info2);
- t.remove();
- root.commit();
+ root.refresh();
}
}
@@ -361,7 +351,7 @@ public class TokenProviderImplTest exten
}
/**
- * @see OAK-1985
+ * @see <a
href="https://issues.apache.org/jira/browse/OAK-1985">OAK-1985</a>
*/
@Test
public void testTokenValidationIsCaseInsensitive() throws Exception {
@@ -381,6 +371,21 @@ public class TokenProviderImplTest exten
assertEquals(userId, info.getUserId());
}
+ @Test
+ public void testTokenNodeName() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ Tree tokenTree = getTokenTree(info);
+
+ // name must not be a uuid which is only used in case of conflict
during
+ // creation which is not expected here.
+ try {
+ UUID.fromString(tokenTree.getName());
+ fail("UUID-name should only be used in case of conflict");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
//--------------------------------------------------------------------------
private static void assertTokenInfo(TokenInfo info, String userId) {
assertNotNull(info);
@@ -388,21 +393,6 @@ public class TokenProviderImplTest exten
assertEquals(userId, info.getUserId());
assertFalse(info.isExpired(new Date().getTime()));
}
-
- private Tree getTokenTree(TokenInfo info) {
- String token = info.getToken();
- int pos = token.indexOf('_');
- String nodeId = (pos == -1) ? token : token.substring(0, pos);
- return new IdentifierManager(root).getTree(nodeId);
- }
-
- private void createTokenTree(TokenInfo base, NodeUtil parent, String
ntName) throws AccessDeniedException {
- Tree tokenTree = getTokenTree(base);
- Tree tree = parent.addChild("token", ntName).getTree();
- tree.setProperty(tokenTree.getProperty(JcrConstants.JCR_UUID));
- tree.setProperty(tokenTree.getProperty("rep:token.key"));
- tree.setProperty(tokenTree.getProperty("rep:token.exp"));
- }
private static class DataFuture {
public Future<TokenInfo> future;
Copied:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorTest.java
(from r1656763,
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java)
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorTest.java?p2=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorTest.java&p1=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java&r1=1656763&r2=1658358&rev=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImplTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenValidatorTest.java
Mon Feb 9 11:03:21 2015
@@ -16,49 +16,25 @@
*/
package org.apache.jackrabbit.oak.security.authentication.token;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.GuestCredentials;
-import javax.jcr.SimpleCredentials;
import org.apache.jackrabbit.JcrConstants;
-import
org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
-import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
-import
org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
-import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
-import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenProvider;
+import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtil;
import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-/**
- * TokenProviderImplTest...
- */
-public class TokenProviderImplTest extends AbstractTokenTest {
+public class TokenValidatorTest extends AbstractTokenTest {
private String userId;
@@ -70,356 +46,325 @@ public class TokenProviderImplTest exten
}
@Test
- public void testDoCreateToken() throws Exception {
- assertFalse(tokenProvider.doCreateToken(new GuestCredentials()));
- assertFalse(tokenProvider.doCreateToken(new
TokenCredentials("token")));
- assertFalse(tokenProvider.doCreateToken(getAdminCredentials()));
-
- SimpleCredentials sc = new SimpleCredentials("uid",
"pw".toCharArray());
- assertFalse(tokenProvider.doCreateToken(sc));
-
- sc.setAttribute("any_attribute", "value");
- assertFalse(tokenProvider.doCreateToken(sc));
-
- sc.setAttribute("rep:token_key", "value");
- assertFalse(tokenProvider.doCreateToken(sc));
-
- sc.setAttribute(".token", "existing");
- assertFalse(tokenProvider.doCreateToken(sc));
-
- sc.setAttribute(".token", "");
- assertTrue(tokenProvider.doCreateToken(sc));
+ public void testCreateReservedKeyProperty() throws Exception {
+ NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
+ try {
+ node.setString(TOKEN_ATTRIBUTE_KEY, "anyValue");
+ root.commit(CommitMarker.asCommitAttributes());
+ fail("The reserved token key property must not used with other
node types.");
+ } catch (CommitFailedException e) {
+ assertEquals(60, e.getCode());
+ } finally {
+ node.getTree().remove();
+ root.commit();
+ }
}
@Test
- public void testCreateTokenFromInvalidCredentials() throws Exception {
- List<Credentials> invalid = new ArrayList<Credentials>();
- invalid.add(new GuestCredentials());
- invalid.add(new TokenCredentials("sometoken"));
- invalid.add(new ImpersonationCredentials(new GuestCredentials(),
null));
- invalid.add(new SimpleCredentials("unknownUserId", new char[0]));
-
- for (Credentials creds : invalid) {
- assertNull(tokenProvider.createToken(creds));
+ public void testCreateReservedKeyProperty2() throws Exception {
+ NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
+ try {
+ node.setString(TOKEN_ATTRIBUTE_KEY, "anyValue");
+ root.commit();
+ fail("The reserved token key property must only be created by the
TokenProvider.");
+ } catch (CommitFailedException e) {
+ assertEquals(63, e.getCode());
+ } finally {
+ node.getTree().remove();
+ root.commit();
}
}
@Test
- public void testCreateTokenFromCredentials() throws Exception {
- SimpleCredentials sc = new SimpleCredentials(userId, new char[0]);
- List<Credentials> valid = new ArrayList<Credentials>();
- valid.add(sc);
- valid.add(new ImpersonationCredentials(sc, null));
+ public void testChangingTokenKey() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ NodeUtil tokenTree = new NodeUtil(getTokenTree(info));
- for (Credentials creds : valid) {
- TokenInfo info = tokenProvider.createToken(creds);
- assertTokenInfo(info, userId);
+ try {
+ tokenTree.setString(TOKEN_ATTRIBUTE_KEY,
PasswordUtil.buildPasswordHash("anotherValue"));
+ root.commit(CommitMarker.asCommitAttributes());
+ fail("The token key must never be modified.");
+ } catch (CommitFailedException e) {
+ assertEquals(61, e.getCode());
}
}
@Test
- public void testCreateTokenFromInvalidUserId() throws Exception {
- TokenInfo info = tokenProvider.createToken("unknownUserId",
Collections.<String, Object>emptyMap());
- assertNull(info);
- }
-
- @Test
- public void testCreateTokenFromUserId() throws Exception {
+ public void testPlaintextTokenKey() throws Exception {
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
- assertTokenInfo(info, userId);
+ NodeUtil tokenTree = new NodeUtil(getTokenTree(info));
+
+ try {
+ tokenTree.setString(TOKEN_ATTRIBUTE_KEY, "anotherValue");
+ root.commit(CommitMarker.asCommitAttributes());
+ fail("The token key must not be plaintext.");
+ } catch (CommitFailedException e) {
+ assertEquals(66, e.getCode());
+ }
}
@Test
- public void testTokenNode() throws Exception {
- Map<String, String> reserved = new HashMap<String, String>();
- reserved.put(".token", "value");
- reserved.put("rep:token.key", "value");
- reserved.put("rep:token.exp", "value");
-
- Map<String, String> privateAttributes = new HashMap<String, String>();
- privateAttributes.put(".token_exp", "value");
- privateAttributes.put(".tokenTest", "value");
- privateAttributes.put(".token_something", "value");
-
- Map<String, String> publicAttributes = new HashMap<String, String>();
- publicAttributes.put("any", "value");
- publicAttributes.put("another", "value");
-
- Map<String, String> attributes = new HashMap<String, String>();
- attributes.putAll(reserved);
- attributes.putAll(publicAttributes);
- attributes.putAll(privateAttributes);
+ public void testManuallyModifyExpirationDate() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ NodeUtil tokenTree = new NodeUtil(getTokenTree(info));
- TokenInfo info = tokenProvider.createToken(userId, attributes);
- Tree tokenTree = getTokenTree(info);
- PropertyState prop = tokenTree.getProperty("rep:token.key");
- assertNotNull(prop);
- assertEquals(Type.STRING, prop.getType());
-
- prop = tokenTree.getProperty("rep:token.exp");
- assertNotNull(prop);
- assertEquals(Type.DATE, prop.getType());
-
- for (String key : reserved.keySet()) {
- PropertyState p = tokenTree.getProperty(key);
- if (p != null) {
- assertFalse(reserved.get(key).equals(p.getValue(Type.STRING)));
- }
+ try {
+ tokenTree.setDate(TOKEN_ATTRIBUTE_EXPIRY, new Date().getTime());
+ root.commit();
+ fail("The token expiry must not manually be changed");
+ } catch (CommitFailedException e) {
+ assertEquals(63, e.getCode());
}
+ }
- for (String key : privateAttributes.keySet()) {
- assertEquals(privateAttributes.get(key),
tokenTree.getProperty(key).getValue(Type.STRING));
- }
+ @Test
+ public void testModifyExpirationDate() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ NodeUtil tokenTree = new NodeUtil(getTokenTree(info));
- for (String key : publicAttributes.keySet()) {
- assertEquals(publicAttributes.get(key),
tokenTree.getProperty(key).getValue(Type.STRING));
- }
+ tokenTree.setDate(TOKEN_ATTRIBUTE_EXPIRY, new Date().getTime());
+ root.commit(CommitMarker.asCommitAttributes());
}
@Test
- public void testGetTokenInfoFromInvalidToken() throws Exception {
- List<String> invalid = new ArrayList<String>();
- invalid.add("/invalid");
- invalid.add(UUID.randomUUID().toString());
+ public void testCreateTokenAtInvalidLocationBelowTestNode() throws
Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ Tree tokenTree = getTokenTree(info);
- for (String token : invalid) {
- TokenInfo info = tokenProvider.getTokenInfo(token);
- assertNull(info);
- }
+ assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
+ NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
try {
- assertNull(tokenProvider.getTokenInfo("invalidToken"));
- } catch (Exception e) {
- // success
+ createTokenTree(info, node, TOKEN_NT_NAME);
+ tokenTree.remove();
+ root.commit(CommitMarker.asCommitAttributes());
+
+ fail("Creating a new token not at '/testNode' must fail.");
+ } catch (CommitFailedException e) {
+ assertEquals(64, e.getCode());
+ } finally {
+ node.getTree().remove();
+ root.commit(CommitMarker.asCommitAttributes());
}
}
@Test
- public void testGetTokenInfoFromInvalidLocation() throws Exception {
+ public void testCreateTokenAtInvalidLocationInsideUser() throws Exception {
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
Tree tokenTree = getTokenTree(info);
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
- NodeUtil node = new NodeUtil(root.getTree("/")).addChild("testNode",
"nt:unstructured");
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
try {
- createTokenTree(info, node, "rep:Token");
+ createTokenTree(info, node, TOKEN_NT_NAME);
tokenTree.remove();
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
- assertNull(tokenProvider.getTokenInfo(info.getToken()));
+ fail("Creating a new token '" + node.getTree().getPath() + "' must
fail.");
+ } catch (CommitFailedException e) {
+ assertEquals(65, e.getCode());
} finally {
node.getTree().remove();
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
}
}
@Test
- public void testGetTokenInfoFromInvalidLocation2() throws Exception {
+ public void testCreateTokenAtInvalidLocationInsideUser2() throws Exception
{
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
Tree tokenTree = getTokenTree(info);
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
- NodeUtil node = new NodeUtil(userTree).addChild("testNode",
"nt:unstructured");
+ NodeUtil node = new NodeUtil(userTree).getOrAddChild(TOKENS_NODE_NAME,
TOKENS_NT_NAME);
try {
- createTokenTree(info, node, "rep:Token");
+ node = node.addChild("invalid", JcrConstants.NT_UNSTRUCTURED);
+ createTokenTree(info, node, TOKEN_NT_NAME);
tokenTree.remove();
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
- assertNull(tokenProvider.getTokenInfo(info.getToken()));
+ fail("Creating a new token '" + node.getTree().getPath() + "' must
fail.");
+ } catch (CommitFailedException e) {
+ assertEquals(65, e.getCode());
} finally {
node.getTree().remove();
- root.commit();
+ root.commit(CommitMarker.asCommitAttributes());
}
}
@Test
- public void testGetTokenInfoFromInvalidLocation3() throws Exception {
+ public void testManuallyCreateToken() throws Exception {
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
Tree tokenTree = getTokenTree(info);
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
- Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
- NodeUtil node = new NodeUtil(userTree.getChild(".tokens"));
+ NodeUtil tokensNode = new NodeUtil(tokenTree.getParent());
try {
- createTokenTree(info, node, "nt:unstructured");
+ // create a valid token node using the test root
+ createTokenTree(info, tokensNode, TOKEN_NT_NAME);
tokenTree.remove();
root.commit();
- assertNull(tokenProvider.getTokenInfo(info.getToken()));
+ fail("Manually creating a token node must fail.");
+ } catch (CommitFailedException e) {
+ assertEquals(63, e.getCode());
} finally {
- node.getTree().remove();
+ root.refresh();
root.commit();
}
}
@Test
- public void testGetTokenInfoFromInvalidLocation4() throws Exception {
+ public void testCreateTokenWithInvalidNodeType() throws Exception {
TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
Tree tokenTree = getTokenTree(info);
assertNotNull(tokenProvider.getTokenInfo(info.getToken()));
- TokenInfo info2 = null;
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree.getChild(TOKENS_NODE_NAME));
+ Tree t = null;
try {
- Tree adminTree =
root.getTree(getUserManager(root).getAuthorizable(adminSession.getAuthInfo().getUserID()).getPath());
- NodeUtil node = new NodeUtil(adminTree).getOrAddChild(".tokens",
"nt:unstructured");
- assertTrue(root.move(tokenTree.getPath(), node.getTree().getPath()
+ "/" + tokenTree.getName()));
- root.commit();
+ t = createTokenTree(info, node, JcrConstants.NT_UNSTRUCTURED);
+ tokenTree.remove();
+ root.commit(CommitMarker.asCommitAttributes());
- info2 = tokenProvider.getTokenInfo(info.getToken());
- assertNotNull(info2);
- assertFalse(info2.matches(new TokenCredentials(info.getToken())));
+ fail("The token node must be of type rep:Token.");
+ } catch (CommitFailedException e) {
+ assertEquals(60, e.getCode());
} finally {
- Tree t = getTokenTree(info2);
- t.remove();
- root.commit();
+ if (t != null) {
+ t.remove();
+ root.commit(CommitMarker.asCommitAttributes());
+ }
}
}
@Test
- public void testGetTokenInfo() throws Exception {
- String token = tokenProvider.createToken(userId, Collections.<String,
Object>emptyMap()).getToken();
- TokenInfo info = tokenProvider.getTokenInfo(token);
- assertTokenInfo(info, userId);
+ public void testRemoveTokenNode() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
+ getTokenTree(info).remove();
+ root.commit();
}
@Test
- public void testCreateTokenWithExpirationParam() throws Exception {
- SimpleCredentials sc = new SimpleCredentials(userId, new char[0]);
- sc.setAttribute(TokenProvider.PARAM_TOKEN_EXPIRATION, 100000);
+ public void testInvalidTokenParentNode() throws Exception {
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree).addChild("testNode",
JcrConstants.NT_UNSTRUCTURED);
+ try {
+ // Invalid node type of '.tokens' node
+ node.addChild(TOKENS_NODE_NAME, JcrConstants.NT_UNSTRUCTURED);
+ root.commit(CommitMarker.asCommitAttributes());
+
+ fail("Creating a new token '" + node.getTree().getPath() + "' must
fail.");
+ } catch (CommitFailedException e) {
+ assertEquals(68, e.getCode());
+ } finally {
+ node.getTree().remove();
+ root.commit(CommitMarker.asCommitAttributes());
+ }
+ }
- TokenInfo info = tokenProvider.createToken(sc);
- assertTokenInfo(info, userId);
+ @Test
+ public void testManuallyCreateTokenParent() throws Exception {
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree);
- Tree tokenTree = getTokenTree(info);
- assertNotNull(tokenTree);
- assertTrue(tokenTree.exists());
-
assertTrue(tokenTree.hasProperty(TokenProvider.PARAM_TOKEN_EXPIRATION));
- assertEquals(100000,
tokenTree.getProperty(TokenProvider.PARAM_TOKEN_EXPIRATION).getValue(Type.LONG).longValue());
+ node.addChild(TOKENS_NODE_NAME, TOKENS_NT_NAME);
+ root.commit();
}
@Test
- public void testCreateTokenWithInvalidExpirationParam() throws Exception {
- SimpleCredentials sc = new SimpleCredentials(userId, new char[0]);
- sc.setAttribute(TokenProvider.PARAM_TOKEN_EXPIRATION, "invalid");
+ public void testManuallyCreateTokenParentWithNtUnstructured() throws
Exception {
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree);
- try {
- tokenProvider.createToken(sc);
- fail();
- } catch (NumberFormatException e) {
- // success
- }
+ node.addChild(TOKENS_NODE_NAME, JcrConstants.NT_UNSTRUCTURED);
+ root.commit();
}
- /**
- *@see <a
href="https://issues.apache.org/jira/browse/OAK-1697">OAK-1697</a>
- */
@Test
- public void testValidTokenCredentialsWithConflict() throws Exception {
- ExecutorService pool = Executors.newFixedThreadPool(10);
- List<ContentSession> sessions = new ArrayList<ContentSession>();
-
+ public void testTokensNodeBelowRoot() throws Exception {
+ NodeUtil rootNode = new NodeUtil(root.getTree("/"));
+ NodeUtil n = null;
try {
- TokenConfiguration tc = getSecurityProvider().getConfiguration(
- TokenConfiguration.class);
- SimpleCredentials sc = (SimpleCredentials) getAdminCredentials();
-
- List<TokenProvider> tokenProviders = new
ArrayList<TokenProvider>();
+ // Invalid node type of '.tokens' node
+ n = rootNode.addChild(TOKENS_NODE_NAME, TOKENS_NT_NAME);
+ root.commit();
- for (int i = 0; i < 10; i++) {
- ContentSession session = login(getAdminCredentials());
- Root r = session.getLatestRoot();
- tokenProviders.add(tc.getTokenProvider(r));
- sessions.add(session);
+ fail("The token parent node must be located below the configured
user root.");
+ } catch (CommitFailedException e) {
+ assertEquals(64, e.getCode());
+ } finally {
+ if (n != null) {
+ n.getTree().remove();
+ root.commit(CommitMarker.asCommitAttributes());
}
+ }
+ }
- ArrayList<DataFuture> list = new ArrayList<DataFuture>();
-
- for (TokenProvider tokenProvider : tokenProviders) {
- list.add(createDataFuture(pool, tokenProvider, sc.getUserID(),
- Collections.<String, Object> emptyMap()));
- }
+ @Test
+ public void testTokensNodeAtInvalidPathBelowUser() throws Exception {
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil userNode = new NodeUtil(userTree);
+ NodeUtil n = null;
+ try {
+ // Invalid node type of '.tokens' node
+ n = userNode.addChild("test", JcrConstants.NT_UNSTRUCTURED);
+ n.addChild(TOKENS_NODE_NAME, TOKENS_NT_NAME);
+ root.commit();
- for (DataFuture df : list) {
- assertNotNull(df.future.get());
- }
+ fail("The token parent node must be located below the user home
node.");
+ } catch (CommitFailedException e) {
+ assertEquals(68, e.getCode());
} finally {
- for (ContentSession session : sessions) {
- if (session != null) {
- session.close();
- }
- }
-
- if (pool != null) {
- pool.shutdown();
+ if (n != null) {
+ n.getTree().remove();
+ root.commit(CommitMarker.asCommitAttributes());
}
}
}
- /**
- * @see OAK-1985
- */
@Test
- public void testTokenValidationIsCaseInsensitive() throws Exception {
- Root root = adminSession.getLatestRoot();
- TokenConfiguration tokenConfig =
getSecurityProvider().getConfiguration(TokenConfiguration.class);
- TokenProvider tp = tokenConfig.getTokenProvider(root);
-
- String userId = ((SimpleCredentials)
getAdminCredentials()).getUserID();
- TokenInfo info = tp.createToken(userId.toUpperCase(),
Collections.<String, Object>emptyMap());
-
- assertTrue(info.matches(new TokenCredentials(info.getToken())));
- assertEquals(userId, info.getUserId());
-
- info = tp.getTokenInfo(info.getToken());
+ public void testChangeTokenParentPrimaryTypeToRepUnstructured() throws
Exception {
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil node = new NodeUtil(userTree);
- assertTrue(info.matches(new TokenCredentials(info.getToken())));
- assertEquals(userId, info.getUserId());
- }
+ node = node.addChild(TOKENS_NODE_NAME, JcrConstants.NT_UNSTRUCTURED);
+ root.commit();
-
//--------------------------------------------------------------------------
- private static void assertTokenInfo(TokenInfo info, String userId) {
- assertNotNull(info);
- assertNotNull(info.getToken());
- assertEquals(userId, info.getUserId());
- assertFalse(info.isExpired(new Date().getTime()));
+ node.setName(JcrConstants.JCR_PRIMARYTYPE, TOKENS_NT_NAME);
+ root.commit();
}
- private Tree getTokenTree(TokenInfo info) {
- String token = info.getToken();
- int pos = token.indexOf('_');
- String nodeId = (pos == -1) ? token : token.substring(0, pos);
- return new IdentifierManager(root).getTree(nodeId);
- }
+ @Test
+ public void testChangeTokenParentPrimaryType() throws Exception {
+ TokenInfo info = tokenProvider.createToken(userId,
Collections.<String, Object>emptyMap());
- private void createTokenTree(TokenInfo base, NodeUtil parent, String
ntName) throws AccessDeniedException {
- Tree tokenTree = getTokenTree(base);
- Tree tree = parent.addChild("token", ntName).getTree();
- tree.setProperty(tokenTree.getProperty(JcrConstants.JCR_UUID));
- tree.setProperty(tokenTree.getProperty("rep:token.key"));
- tree.setProperty(tokenTree.getProperty("rep:token.exp"));
- }
-
- private static class DataFuture {
- public Future<TokenInfo> future;
+ try {
+ Tree tokensTree = getTokenTree(info).getParent();
+ tokensTree.setProperty(JcrConstants.JCR_PRIMARYTYPE,
JcrConstants.NT_UNSTRUCTURED, Type.NAME);
- public DataFuture(Future<TokenInfo> future) {
- super();
- this.future = future;
+ root.commit();
+ fail("The primary type of the token parent must not be changed
from rep:Unstructured to another type.");
+ } catch (CommitFailedException e) {
+ assertEquals(69, e.getCode());
+ } finally {
+ root.refresh();
}
}
-
- private DataFuture createDataFuture(ExecutorService pool , final
TokenProvider tp,final String userId, final Map<String, ?> attributes){
- Future<TokenInfo> future = pool.submit(new Callable<TokenInfo>() {
- @Override
- public TokenInfo call() throws Exception {
- return tp.createToken(userId, attributes);
- }
- });
- return new DataFuture(future);
+
+ @Test
+ public void testChangeRegularRepUnstructuredPrimaryType() throws Exception
{
+ Tree userTree =
root.getTree(getUserManager(root).getAuthorizable(userId).getPath());
+ NodeUtil n = new NodeUtil(userTree).getOrAddChild("test",
NodeTypeConstants.NT_REP_UNSTRUCTURED);
+ root.commit();
+
+ n.setName(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ root.commit();
}
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1658358&r1=1658357&r2=1658358&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
Mon Feb 9 11:03:21 2015
@@ -21,7 +21,6 @@ package org.apache.jackrabbit.oak.jcr.qu
import static com.google.common.collect.Sets.newHashSet;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
-import static org.apache.jackrabbit.JcrConstants.NT_FOLDER;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
@@ -49,6 +48,10 @@ import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+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.cnd.CndImporter;
import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
@@ -582,10 +585,12 @@ public class QueryTest extends AbstractR
public void xpathEscapeTest() throws RepositoryException {
Session writer = createAdminSession();
Session reader = createAdminSession();
+
+ UserManager uMgr = ((JackrabbitSession) writer).getUserManager();
+ String uid = "testUser";
try {
- Node rootNode = writer.getRootNode();
- Node node = rootNode.addNode("test", "nt:unstructured");
- node.addNode(".tokens");
+ User user = uMgr.createUser("testUser", "pw");
+ writer.getNode(user.getPath()).addNode(".tokens",
"rep:Unstructured");
writer.save();
QueryManager qm = reader.getWorkspace().getQueryManager();
@@ -593,6 +598,11 @@ public class QueryTest extends AbstractR
NodeIterator res = q.execute().getNodes();
assertEquals(1, res.getSize());
} finally {
+ Authorizable a = uMgr.getAuthorizable(uid);
+ if (a != null) {
+ a.remove();
+ writer.save();
+ }
if (reader != null) {
reader.logout();
}