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 2012/10/19 14:03:02 UTC
svn commit: r1400057 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/
oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/ oak-jcr/
Author: angela
Date: Fri Oct 19 12:03:02 2012
New Revision: 1400057
URL: http://svn.apache.org/viewvc?rev=1400057&view=rev
Log:
OAK-50 : Implement User Management (WIP)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserQueryManager.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java
jackrabbit/oak/trunk/oak-jcr/pom.xml
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java Fri Oct 19 12:03:02 2012
@@ -48,6 +48,7 @@ abstract class AuthorizableImpl implemen
private static final Logger log = LoggerFactory.getLogger(AuthorizableImpl.class);
private final String id;
+ private final String principalName;
private final UserManagerImpl userManager;
private Node node;
@@ -55,10 +56,16 @@ abstract class AuthorizableImpl implemen
private int hashCode;
AuthorizableImpl(String id, Tree tree, UserManagerImpl userManager) throws RepositoryException {
+ checkValidTree(tree);
this.id = id;
+ if (tree.hasProperty(REP_PRINCIPAL_NAME)) {
+ principalName = tree.getProperty(REP_PRINCIPAL_NAME).getValue(STRING);
+ } else {
+ String msg = "Authorizable without principal name " + id;
+ log.warn(msg);
+ throw new RepositoryException(msg);
+ }
this.userManager = userManager;
-
- checkValidTree(tree);
}
abstract void checkValidTree(Tree tree) throws RepositoryException;
@@ -185,14 +192,8 @@ abstract class AuthorizableImpl implemen
}
@Nonnull
- String getPrincipalName(Tree thisTree) throws RepositoryException {
- if (thisTree.hasProperty(REP_PRINCIPAL_NAME)) {
- return thisTree.getProperty(REP_PRINCIPAL_NAME).getValue(STRING);
- } else {
- String msg = "Authorizable without principal name " + id;
- log.warn(msg);
- throw new RepositoryException(msg);
- }
+ String getPrincipalName() throws RepositoryException {
+ return principalName;
}
@CheckForNull
@@ -224,7 +225,7 @@ abstract class AuthorizableImpl implemen
* @throws RepositoryException If an error occurs.
*/
boolean isEveryone() throws RepositoryException {
- return isGroup() && EveryonePrincipal.NAME.equals(getPrincipalName(getTree()));
+ return isGroup() && EveryonePrincipal.NAME.equals(getPrincipalName());
}
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java Fri Oct 19 12:03:02 2012
@@ -66,8 +66,7 @@ class GroupImpl extends AuthorizableImpl
@Override
public Principal getPrincipal() throws RepositoryException {
- Tree groupTree = getTree();
- return new GroupPrincipal(getPrincipalName(groupTree), groupTree);
+ return new GroupPrincipal(getPrincipalName(), getTree());
}
//--------------------------------------------------------------< Group >---
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImpl.java?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImpl.java Fri Oct 19 12:03:02 2012
@@ -65,7 +65,7 @@ class UserImpl extends AuthorizableImpl
@Override
public Principal getPrincipal() throws RepositoryException {
Tree userTree = getTree();
- String principalName = getPrincipalName(userTree);
+ String principalName = getPrincipalName();
if (isAdmin()) {
return new AdminPrincipalImpl(principalName, userTree, getUserManager().getNamePathMapper());
} else {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserQueryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserQueryManager.java?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserQueryManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserQueryManager.java Fri Oct 19 12:03:02 2012
@@ -18,16 +18,23 @@ package org.apache.jackrabbit.oak.securi
import java.util.Iterator;
import javax.annotation.Nonnull;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.QueryManager;
+import com.google.common.base.Function;
+import com.google.common.collect.Iterators;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Query;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.security.user.query.XPathQueryBuilder;
import org.apache.jackrabbit.oak.security.user.query.XPathQueryEvaluator;
import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,11 +52,24 @@ class UserQueryManager {
private final Root root;
private final QueryManager queryManager;
+ private final String userRoot;
+ private final String groupRoot;
+ private final String authorizableRoot;
+
// TODO: replace usage of jcr-query-manager by oak query manager and drop session from constructor.
UserQueryManager(UserManagerImpl userManager, Session session, Root root) throws RepositoryException {
this.userManager = userManager;
this.root = root;
this.queryManager = (session != null) ? session.getWorkspace().getQueryManager() : null;
+
+ this.userRoot = userManager.getConfig().getConfigValue(UserConstants.PARAM_USER_PATH, UserConstants.DEFAULT_USER_PATH);
+ this.groupRoot = userManager.getConfig().getConfigValue(UserConstants.PARAM_GROUP_PATH, UserConstants.DEFAULT_GROUP_PATH);;
+
+ String parent = userRoot;
+ while (!Text.isDescendant(parent, groupRoot)) {
+ parent = Text.getRelativeParent(parent, 1);
+ }
+ authorizableRoot = parent;
}
Iterator<Authorizable> find(Query query) throws RepositoryException {
@@ -65,28 +85,22 @@ class UserQueryManager {
}
@Nonnull
- Iterator<Authorizable> findAuthorizables(String relativePath, String value, AuthorizableType authorizableType) {
- String[] oakPaths = new String[] {userManager.getNamePathMapper().getOakPath(relativePath)};
- return findAuthorizables(oakPaths, value, null, true, Long.MAX_VALUE, authorizableType);
+ Iterator<Authorizable> findAuthorizables(String relativePath, String value,
+ AuthorizableType authorizableType)
+ throws RepositoryException {
+ String oakPath = userManager.getNamePathMapper().getOakPath(relativePath);
+ return findAuthorizables(oakPath, value, true, authorizableType);
}
/**
* Find the authorizable trees matching the following search parameters within
* the sub-tree defined by an authorizable tree:
*
- * @param propertyRelPaths An array of property names or relative paths
- * pointing to properties within the tree defined by a given authorizable node.
+ * @param relPath A relative path (or a name) pointing to properties within
+ * the tree defined by a given authorizable node.
* @param value The property value to look for.
- * @param ntNames An array of node type names to restrict the search within
- * the authorizable tree to a subset of nodes that match any of the node
- * type names; {@code null} indicates that no filtering by node type is
- * desired. Specifying a node type name that defines an authorizable node
- * )e.g. {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#NT_REP_USER rep:User} will limit the search to
- * properties defined with the authorizable node itself instead of searching
- * the complete sub-tree.
* @param exact A boolean flag indicating if the value must match exactly or not.s
- * @param maxSize The maximal number of search results to look for.
- * @param authorizableType Filter the search results to only return authorizable
+ * @param type Filter the search results to only return authorizable
* trees of a given type. Passing {@link org.apache.jackrabbit.oak.spi.security.user.AuthorizableType#AUTHORIZABLE} indicates that
* no filtering for a specific authorizable type is desired. However, properties
* might still be search in the complete sub-tree of authorizables depending
@@ -96,11 +110,120 @@ class UserQueryManager {
* found.
*/
@Nonnull
- Iterator<Authorizable> findAuthorizables(String[] propertyRelPaths, String value, String[] ntNames, boolean exact, long maxSize, AuthorizableType authorizableType) {
- // TODO
- throw new UnsupportedOperationException("not yet implemented");
+ Iterator<Authorizable> findAuthorizables(String relPath, String value,
+ boolean exact, AuthorizableType type)
+ throws RepositoryException {
+ // TODO replace usage of jcr query manager by oak-query api.
+ String statement = buildXPathStatement(relPath, value, exact, type);
+ if (queryManager != null) {
+ NodeIterator results = queryManager.createQuery(statement, javax.jcr.query.Query.XPATH).execute().getNodes();
+ return Iterators.transform(results, new NodeToAuthorizable());
+ } else {
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+ }
+
+ private String buildXPathStatement(String relPath, String value, boolean exact, AuthorizableType type) {
+ StringBuilder stmt = new StringBuilder();
+ String searchRoot = getSearchRoot(type);
+ if (!"/".equals(searchRoot)) {
+ stmt.append(searchRoot);
+ }
+
+ String path;
+ String propName;
+ String ntName;
+ if (relPath.indexOf('/') == -1) {
+ // search for properties somewhere below an authorizable node
+ path = null;
+ propName = relPath;
+ ntName = null;
+ } else {
+ // FIXME: proper normalization of the relative path
+ path = (relPath.startsWith("./") ? null : Text.getRelativeParent(relPath, 1));
+ propName = Text.getName(relPath);
+ ntName = getNodeTypeName(type);
+ }
+
+ stmt.append("//");
+ if (path != null) {
+ stmt.append(path);
+ } else {
+ if (ntName != null) {
+ stmt.append("element(*,");
+ stmt.append(ntName);
+ } else {
+ stmt.append("element(*");
+ }
+ stmt.append(')');
+ }
- //return AuthorizableIterator.create(result, this);
+ if (value != null) {
+ stmt.append('[');
+ stmt.append((exact) ? "@" : "jcr:like(@");
+ stmt.append(ISO9075.encode(propName));
+ if (exact) {
+ stmt.append("='");
+ stmt.append(value.replaceAll("'", "''"));
+ stmt.append('\'');
+ } else {
+ stmt.append(",'%");
+ stmt.append(escapeForQuery(value));
+ stmt.append("%')");
+ }
+ stmt.append(']');
+ }
+ return stmt.toString();
+ }
+
+ /**
+ * @param type
+ * @return The path of search root for the specified authorizable type.
+ */
+ private String getSearchRoot(AuthorizableType type) {
+ if (type == AuthorizableType.USER) {
+ return userRoot;
+ } else if (type == AuthorizableType.GROUP) {
+ return groupRoot;
+ } else {
+ return authorizableRoot;
+ }
+ }
+ private static String escapeForQuery(String value) {
+ StringBuilder ret = new StringBuilder();
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '\\') {
+ ret.append("\\\\");
+ } else if (c == '\'') {
+ ret.append("''");
+ } else {
+ ret.append(c);
+ }
+ }
+ return ret.toString();
+ }
+
+ private static String getNodeTypeName(AuthorizableType type) {
+ if (type == AuthorizableType.USER) {
+ return UserConstants.NT_REP_USER;
+ } else if (type == AuthorizableType.GROUP) {
+ return UserConstants.NT_REP_GROUP;
+ } else {
+ return UserConstants.NT_REP_AUTHORIZABLE;
+ }
+ }
+
+ private class NodeToAuthorizable implements Function<Node, Authorizable> {
+ @Override
+ public Authorizable apply(Node node) {
+ try {
+ return userManager.getAuthorizable(node.getPath());
+ } catch (RepositoryException e) {
+ log.debug("Failed to access authorizable " + node);
+ return null;
+ }
+ }
}
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java Fri Oct 19 12:03:02 2012
@@ -20,17 +20,29 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.ContentSession;
+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.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.nodetype.InitialContent;
+import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.oak.security.AbstractSecurityTest;
import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtility;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
@@ -38,70 +50,90 @@ import static org.junit.Assert.fail;
*/
public class UserManagerImplTest extends AbstractSecurityTest {
- @Override
+ SecurityProvider securityProvider = new SecurityProviderImpl();
+ ContentSession admin;
+ Root root;
+ UserManagerImpl userMgr;
+
+ @Before
+ public void before() throws Exception {
+ super.before();
+ admin = login(getAdminCredentials());
+ root = admin.getLatestRoot();
+ userMgr = (UserManagerImpl) new UserConfigurationImpl(ConfigurationParameters.EMPTY, securityProvider).getUserManager(root, NamePathMapper.DEFAULT);
+ }
+
+ @After
+ public void after() throws Exception {
+ admin.close();
+ }
+
+ @Override
protected ContentRepository createRepository() {
- // TODO
- return null;
+ return new Oak()
+ .with(new InitialContent())
+ .with(securityProvider)
+ .createContentRepository();
}
-// @Test
-// public void testSetPassword() throws Exception {
-// UserManagerImpl userMgr = createUserManager();
-// User user = userMgr.createUser("a", "pw");
-//
-// List<String> pwds = new ArrayList<String>();
-// pwds.add("pw");
-// pwds.add("");
-// pwds.add("{sha1}pw");
-//
-// for (String pw : pwds) {
-// user.setPassword(user, pw, true);
-// String pwHash = up.getPasswordHash(user);
-// assertNotNull(pwHash);
-// assertTrue(PasswordUtility.isSame(pwHash, pw));
-// }
-//
-// for (String pw : pwds) {
-// up.setPassword(user, pw, false);
-// String pwHash = up.getPasswordHash(user);
-// assertNotNull(pwHash);
-// if (!pw.startsWith("{")) {
-// assertTrue(PasswordUtility.isSame(pwHash, pw));
-// } else {
-// assertFalse(PasswordUtility.isSame(pwHash, pw));
-// assertEquals(pw, pwHash);
-// }
-// }
-// }
-//
-// @Test
-// public void setPasswordNull() throws Exception {
-// UserProviderImpl up = createUserProvider();
-// Tree user = up.createUser("a", null);
-//
-// try {
-// up.setPassword(user, null, true);
-// fail("setting null password should fail");
-// } catch (IllegalArgumentException e) {
-// // expected
-// }
-//
-// try {
-// up.setPassword(user, null, false);
-// fail("setting null password should fail");
-// } catch (IllegalArgumentException e) {
-// // expected
-// }
-// }
-
-
-//
-// @Test
-// public void testGetPasswordHash() throws Exception {
-// UserProviderImpl up = createUserProvider();
-// Tree user = up.createUser("a", null);
-//
-// assertNull(up.getPasswordHash(user));
-// }
+ @Test
+ public void testSetPassword() throws Exception {
+ User user = userMgr.createUser("a", "pw");
+ root.commit();
+
+ List<String> pwds = new ArrayList<String>();
+ pwds.add("pw");
+ pwds.add("");
+ pwds.add("{sha1}pw");
+
+ Tree userTree = root.getTree(user.getPath());
+ for (String pw : pwds) {
+ userMgr.setPassword(userTree, pw, true);
+ String pwHash = userTree.getProperty(UserConstants.REP_PASSWORD).getValue(Type.STRING);
+ assertNotNull(pwHash);
+ assertTrue(PasswordUtility.isSame(pwHash, pw));
+ }
+
+ for (String pw : pwds) {
+ userMgr.setPassword(userTree, pw, false);
+ String pwHash = userTree.getProperty(UserConstants.REP_PASSWORD).getValue(Type.STRING);
+ assertNotNull(pwHash);
+ if (!pw.startsWith("{")) {
+ assertTrue(PasswordUtility.isSame(pwHash, pw));
+ } else {
+ assertFalse(PasswordUtility.isSame(pwHash, pw));
+ assertEquals(pw, pwHash);
+ }
+ }
+ }
+ @Test
+ public void setPasswordNull() throws Exception {
+ User user = userMgr.createUser("a", null);
+ root.commit();
+
+ Tree userTree = root.getTree(user.getPath());
+ try {
+ userMgr.setPassword(userTree, null, true);
+ fail("setting null password should fail");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ userMgr.setPassword(userTree, null, false);
+ fail("setting null password should fail");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testGetPasswordHash() throws Exception {
+ User user = userMgr.createUser("a", null);
+ root.commit();
+
+ Tree userTree = root.getTree(user.getPath());
+ assertNull(userTree.getProperty(UserConstants.REP_PASSWORD));
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1400057&r1=1400056&r2=1400057&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Fri Oct 19 12:03:02 2012
@@ -252,13 +252,11 @@
org.apache.jackrabbit.test.api.observation.LockingTest#testAddLockToNode
org.apache.jackrabbit.test.api.observation.LockingTest#testRemoveLockFromNode
org.apache.jackrabbit.oak.jcr.security.user.EveryoneGroupTest#testMembers <!-- findAuthorizables not yet implemented -->
- org.apache.jackrabbit.oak.jcr.security.user.UserQueryTest <!-- findAuthorizables not yet implemented -->
- org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAuthorizableByAddedProperty <!-- findAuthorizables not yet implemented -->
- org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAuthorizableByRelativePath <!-- findAuthorizables not yet implemented -->
+ org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAuthorizableByAddedProperty <!-- OAK-343 -->
+ org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAuthorizableByRelativePath <!-- OAK-343 -->
org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindUser <!-- findAuthorizables not yet implemented -->
org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindGroup <!-- findAuthorizables not yet implemented -->
- org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAllUsers <!-- findAuthorizables not yet implemented -->
- org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testFindAllGroups <!-- findAuthorizables not yet implemented -->
+ org.apache.jackrabbit.oak.jcr.security.user.UserQueryTest <!-- OAK-343 -->
org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testGetNewAuthorizable <!-- OAK-343 -->
org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testCreateGroupWithExistingPrincipal2 <!-- OAK-343 -->
org.apache.jackrabbit.oak.jcr.security.user.UserManagerTest#testCreateGroupWithExistingPrincipal3 <!-- OAK-343 -->