You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2012/01/24 11:10:27 UTC
svn commit: r1235192 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/security/authentication/
main/java/org/apache/jackrabbit/core/security/user/
main/java/org/apache/jackrabbit/core/security/user/action/ test/java/org/...
Author: angela
Date: Tue Jan 24 10:10:27 2012
New Revision: 1235192
URL: http://svn.apache.org/viewvc?rev=1235192&view=rev
Log:
JCR-3218 : UserImporter should trigger execution AuthorizableActions in case of user/group creation
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/CryptedSimpleCredentials.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/CryptedSimpleCredentials.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/CryptedSimpleCredentials.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/CryptedSimpleCredentials.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/CryptedSimpleCredentials.java Tue Jan 24 10:10:27 2012
@@ -22,6 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
@@ -168,6 +169,23 @@ public class CryptedSimpleCredentials im
}
/**
+ * Creates a hash of the specified password if it is found to be plain text.
+ *
+ * @param password
+ * @return
+ * @throws javax.jcr.RepositoryException
+ */
+ public static String buildPasswordHash(String password) throws RepositoryException {
+ try {
+ return new CryptedSimpleCredentials("_", password).getPassword();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RepositoryException(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
* @param pwd Plain text password
* @param algorithm The algorithm to be used for the digest.
* @param salt The salt to be used for the digest.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java Tue Jan 24 10:10:27 2012
@@ -48,18 +48,13 @@ public class UserImpl extends Authorizab
/**
* Creates a hash of the specified password if it is found to be plain text.
*
- * @param password
- * @return
- * @throws RepositoryException
+ * @param password The password string.
+ * @return Hash for the given password string.
+ * @throws RepositoryException If an error occurs.
+ * @see CryptedSimpleCredentials#buildPasswordHash(String)
*/
static String buildPasswordValue(String password) throws RepositoryException {
- try {
- return new CryptedSimpleCredentials("_", password).getPassword();
- } catch (NoSuchAlgorithmException e) {
- throw new RepositoryException(e);
- } catch (UnsupportedEncodingException e) {
- throw new RepositoryException(e);
- }
+ return CryptedSimpleCredentials.buildPasswordHash(password);
}
//-------------------------------------------------------< Authorizable >---
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java Tue Jan 24 10:10:27 2012
@@ -140,6 +140,17 @@ public class UserImporter implements Pro
private int importBehavior = ImportBehavior.IGNORE;
+ /**
+ * Container used to collect group members stored in protected nodes.
+ */
+ private Membership currentMembership;
+
+ /**
+ * Temporary store for the pw an imported new user to be able to call
+ * the creation actions irrespective of the order of protected properties
+ */
+ private Map<String,String> currentPw = new HashMap<String,String>(1);
+
public boolean init(JackrabbitSession session, NamePathResolver resolver,
boolean isWorkspaceImport,
int uuidBehavior, ReferenceChangeTracker referenceTracker) {
@@ -182,8 +193,10 @@ public class UserImporter implements Pro
return initialized;
}
- // -----------------------------------------------------< ProtectedPropertyImporter >---
-
+ // -----------------------------------------< ProtectedPropertyImporter >---
+ /**
+ * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.NodeImpl, org.apache.jackrabbit.core.xml.PropInfo, org.apache.jackrabbit.spi.QPropertyDefinition)
+ */
public boolean handlePropInfo(NodeImpl parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
if (!initialized) {
throw new IllegalStateException("Not initialized");
@@ -222,6 +235,22 @@ public class UserImporter implements Pro
Value v = protectedPropInfo.getValues(PropertyType.STRING, resolver)[0];
String princName = v.getString();
userManager.setPrincipal(parent, new PrincipalImpl(princName));
+
+ /*
+ Execute authorizable actions for a NEW group as this is the
+ same place in the userManager#createGroup that the actions
+ are called.
+ In case of a NEW user the actions are executed if the password
+ has been imported before.
+ */
+ if (parent.isNew()) {
+ if (a.isGroup()) {
+ userManager.onCreate((Group) a);
+ } else if (currentPw.containsKey(a.getID())) {
+ userManager.onCreate((User) a, currentPw.remove(a.getID()));
+ }
+ }
+
return true;
} else if (UserConstants.P_PASSWORD.equals(propName)) {
if (a.isGroup()) {
@@ -236,8 +265,23 @@ public class UserImporter implements Pro
}
Value v = protectedPropInfo.getValues(PropertyType.STRING, resolver)[0];
- ((User) a).changePassword(v.getString());
+ String pw = v.getString();
+ ((User) a).changePassword(pw);
+ /*
+ Execute authorizable actions for a NEW user at this point after
+ having set the password if the principal name has already been
+ processed, otherwise postpone it.
+ */
+ if (parent.isNew()) {
+ if (parent.hasProperty(UserConstants.P_PRINCIPAL_NAME)) {
+ userManager.onCreate((User) a, pw);
+ } else {
+ // principal name not yet available -> remember the pw
+ currentPw.clear();
+ currentPw.put(a.getID(), pw);
+ }
+ }
return true;
} else if (UserConstants.P_IMPERSONATORS.equals(propName)) {
@@ -314,10 +358,16 @@ public class UserImporter implements Pro
}
}
+ /**
+ * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.NodeImpl, org.apache.jackrabbit.core.xml.PropInfo, org.apache.jackrabbit.spi.QPropertyDefinition)
+ */
public boolean handlePropInfo(NodeState parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
return false;
}
+ /**
+ * @see org.apache.jackrabbit.core.xml.ProtectedPropertyImporter#processReferences()
+ */
public void processReferences() throws RepositoryException {
if (!initialized) {
throw new IllegalStateException("Not initialized");
@@ -494,25 +544,10 @@ public class UserImporter implements Pro
}
}
- //------------------------------------------------------------< private >---
- private void handleFailure(String msg) throws RepositoryException {
- switch (importBehavior) {
- case ImportBehavior.IGNORE:
- case ImportBehavior.BESTEFFORT:
- log.warn(msg);
- break;
- case ImportBehavior.ABORT:
- throw new ConstraintViolationException(msg);
- default:
- // no other behavior. nothing to do.
-
- }
- }
-
- // -----------------------------------------------------< ProtectedNodeImporter >---
-
- private Membership currentMembership;
-
+ // ---------------------------------------------< ProtectedNodeImporter >---
+ /**
+ * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.NodeImpl)
+ */
public boolean start(NodeImpl protectedParent) throws RepositoryException {
String repMembers = resolver.getJCRName(UserConstants.NT_REP_MEMBERS);
if (repMembers.equals(protectedParent.getPrimaryNodeType().getName())) {
@@ -537,10 +572,16 @@ public class UserImporter implements Pro
}
}
+ /**
+ * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.state.NodeState)
+ */
public boolean start(NodeState protectedParent) {
return false;
}
+ /**
+ * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.NodeImpl)
+ */
public void startChildInfo(NodeInfo childInfo, List<PropInfo> propInfos) throws RepositoryException {
assert (currentMembership != null);
@@ -558,14 +599,23 @@ public class UserImporter implements Pro
}
}
+ /**
+ * @see org.apache.jackrabbit.core.xml.ProtectedNodeImporter#endChildInfo()
+ */
public void endChildInfo() throws RepositoryException {
}
+ /**
+ * @see ProtectedNodeImporter#end(org.apache.jackrabbit.core.NodeImpl)
+ */
public void end(NodeImpl protectedParent) throws RepositoryException {
referenceTracker.processedReference(currentMembership);
currentMembership = null;
}
+ /**
+ * @see ProtectedNodeImporter#end(org.apache.jackrabbit.core.state.NodeState)
+ */
public void end(NodeState protectedParent) {
}
@@ -585,7 +635,28 @@ public class UserImporter implements Pro
this.importBehavior = ImportBehavior.valueFromName(importBehaviorStr);
}
- //--------------------------------------------------------------------------
+ //------------------------------------------------------------< private >---
+ /**
+ * Handling the import behavior
+ *
+ * @param msg
+ * @throws RepositoryException
+ */
+ private void handleFailure(String msg) throws RepositoryException {
+ switch (importBehavior) {
+ case ImportBehavior.IGNORE:
+ case ImportBehavior.BESTEFFORT:
+ log.warn(msg);
+ break;
+ case ImportBehavior.ABORT:
+ throw new ConstraintViolationException(msg);
+ default:
+ // no other behavior. nothing to do.
+
+ }
+ }
+
+ //------------------------------------------------------< inner classes >---
/**
* Inner class used to postpone import of group membership to the very end
* of the import. This allows to import membership of user/groups that
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Tue Jan 24 10:10:27 2012
@@ -1049,7 +1049,7 @@ public class UserManagerImpl extends Pro
* @param pw The password.
* @throws RepositoryException If an exception occurs.
*/
- private void onCreate(User user, String pw) throws RepositoryException {
+ void onCreate(User user, String pw) throws RepositoryException {
for (AuthorizableAction action : authorizableActions) {
action.onCreate(user, pw, session);
}
@@ -1063,7 +1063,7 @@ public class UserManagerImpl extends Pro
* @param group The new group.
* @throws RepositoryException If an exception occurs.
*/
- private void onCreate(Group group) throws RepositoryException {
+ void onCreate(Group group) throws RepositoryException {
for (AuthorizableAction action : authorizableActions) {
action.onCreate(group, session);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java Tue Jan 24 10:10:27 2012
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.security.user.action;
import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,11 +101,19 @@ public class PasswordValidationAction ex
* doesn't match the specified password pattern.
*/
private void validatePassword(String password) throws RepositoryException {
- if (password != null) {
+ if (password != null && isPlainText(password)) {
if (pattern != null && !pattern.matcher(password).matches()) {
throw new ConstraintViolationException("Password violates password constraint (" + pattern.pattern() + ").");
}
}
}
+ private static boolean isPlainText(String password) {
+ try {
+ return !CryptedSimpleCredentials.buildPasswordHash(password).equals(password);
+ } catch (RepositoryException e) {
+ // failed to build hash from pw -> proceed with the validation.
+ return true;
+ }
+ }
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java Tue Jan 24 10:10:27 2012
@@ -230,7 +230,27 @@ public class AuthorizableActionTest exte
}
}
+ public void testPasswordValidationActionIgnoresHashedPwString() throws Exception {
+ User u = null;
+ try {
+ String uid = getTestPrincipal().getName();
+ u = impl.createUser(uid, buildPassword(uid));
+
+ PasswordValidationAction pwAction = new PasswordValidationAction();
+ pwAction.setConstraint("^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z]).*");
+ setActions(pwAction);
+
+ String hashed = ((UserImpl) u).buildPasswordValue("DWkej32H");
+ u.changePassword(hashed);
+
+ } finally {
+ if (u != null) {
+ u.remove();
+ }
+ save(superuser);
+ }
+ }
//--------------------------------------------------------------------------
private class TestAction extends AbstractAuthorizableAction {
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java?rev=1235192&r1=1235191&r2=1235192&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java Tue Jan 24 10:10:27 2012
@@ -33,6 +33,8 @@ import org.apache.jackrabbit.core.config
import org.apache.jackrabbit.core.security.SecurityConstants;
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
import org.apache.jackrabbit.core.security.user.UserImporter.ImportBehavior;
+import org.apache.jackrabbit.core.security.user.action.AccessControlAction;
+import org.apache.jackrabbit.core.security.user.action.AuthorizableAction;
import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
import org.apache.jackrabbit.core.xml.ImportHandler;
import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
@@ -69,7 +71,11 @@ import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.retention.RetentionManager;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
import javax.jcr.version.VersionException;
import javax.security.auth.Subject;
import java.io.ByteArrayInputStream;
@@ -128,6 +134,7 @@ public class UserImporterTest extends Ab
}
sImpl.save();
+ // make sure the target node for group-import exists
Authorizable administrators = umgr.getAuthorizable(SecurityConstants.ADMINISTRATORS_NAME);
if (administrators == null) {
groupIdToRemove = umgr.createGroup(new PrincipalImpl(SecurityConstants.ADMINISTRATORS_NAME)).getID();
@@ -655,8 +662,23 @@ public class UserImporterTest extends Ab
}
public void testImportNewMembers() throws IOException, RepositoryException, SAXException, NotExecutableException {
- String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sv:node sv:name=\"gFolder\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
- "<sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:AuthorizableFolder</sv:value></sv:property><sv:node sv:name=\"g\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property><sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property><sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>g</sv:value></sv:property></sv:node><sv:node sv:name=\"g1\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property><sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>0120a4f9-196a-3f9e-b9f5-23f31f914da7</sv:value></sv:property><sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>g1</sv:value></sv:property><sv:property sv:name=\"rep:members\" sv:type=\"WeakReference\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property></sv:node></sv:no
de>";
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+ "<sv:node sv:name=\"gFolder\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ "<sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">" +
+ " <sv:value>rep:AuthorizableFolder</sv:value>" +
+ "</sv:property>" +
+ "<sv:node sv:name=\"g\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>g</sv:value></sv:property>" +
+ "</sv:node>" +
+ "<sv:node sv:name=\"g1\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>0120a4f9-196a-3f9e-b9f5-23f31f914da7</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>g1</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:members\" sv:type=\"WeakReference\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property>" +
+ "</sv:node>" +
+ "</sv:node>";
NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getGroupsPath());
try {
@@ -1326,6 +1348,165 @@ public class UserImporterTest extends Ab
}
}
+ public void testActionExecutionForUser() throws Exception {
+ TestAction testAction = new TestAction();
+
+ umgr.setAuthorizableActions(new AuthorizableAction[] {testAction});
+
+ // import user
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"t\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:User</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>e358efa4-89f5-3062-b10d-d7316b65649e</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:password\" sv:type=\"String\"><sv:value>pw</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>tPrincipal</sv:value></sv:property>" +
+ "</sv:node>";
+
+ NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getUsersPath());
+ try {
+ doImport(target, xml);
+ assertEquals(testAction.id, "t");
+ assertEquals(testAction.pw, "pw");
+ } finally {
+ sImpl.refresh(false);
+ }
+ }
+
+ public void testActionExecutionForGroup() throws Exception {
+ TestAction testAction = new TestAction();
+
+ umgr.setAuthorizableActions(new AuthorizableAction[] {testAction});
+
+ // import group
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"g\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>gPrincipal</sv:value></sv:property>" +
+ "</sv:node>";
+
+ NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getGroupsPath());
+ try {
+ doImport(target, xml);
+ assertEquals(testAction.id, "g");
+ assertNull(testAction.pw);
+ } finally {
+ sImpl.refresh(false);
+ }
+ }
+
+ public void testAccessControlActionExecutionForUser() throws Exception {
+ AccessControlAction a1 = new AccessControlAction();
+ a1.setUserPrivilegeNames(Privilege.JCR_ALL);
+
+ umgr.setAuthorizableActions(new AuthorizableAction[] {a1});
+
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"t\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:User</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>e358efa4-89f5-3062-b10d-d7316b65649e</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:password\" sv:type=\"String\"><sv:value>{sha1}8efd86fb78a56a5145ed7739dcb00c78581c5375</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>tPrincipal</sv:value></sv:property>" +
+ "</sv:node>";
+
+ NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getUsersPath());
+ try {
+ doImport(target, xml);
+
+ Authorizable a = umgr.getAuthorizable("t");
+ assertNotNull(a);
+ assertFalse(a.isGroup());
+
+ AccessControlManager acMgr = sImpl.getAccessControlManager();
+ AccessControlPolicy[] policies = acMgr.getPolicies(a.getPath());
+ assertNotNull(policies);
+ assertEquals(1, policies.length);
+ assertTrue(policies[0] instanceof AccessControlList);
+
+ AccessControlEntry[] aces = ((AccessControlList) policies[0]).getAccessControlEntries();
+ assertEquals(1, aces.length);
+ assertEquals("tPrincipal", aces[0].getPrincipal().getName());
+
+ } finally {
+ sImpl.refresh(false);
+ }
+ }
+
+ public void testAccessControlActionExecutionForUser2() throws Exception {
+ AccessControlAction a1 = new AccessControlAction();
+ a1.setUserPrivilegeNames(Privilege.JCR_ALL);
+
+ umgr.setAuthorizableActions(new AuthorizableAction[] {a1});
+
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"t\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:User</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>e358efa4-89f5-3062-b10d-d7316b65649e</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>tPrincipal</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:password\" sv:type=\"String\"><sv:value>{sha1}8efd86fb78a56a5145ed7739dcb00c78581c5375</sv:value></sv:property>" +
+ "</sv:node>";
+
+ NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getUsersPath());
+ try {
+ doImport(target, xml);
+
+ Authorizable a = umgr.getAuthorizable("t");
+ assertNotNull(a);
+ assertFalse(a.isGroup());
+
+ AccessControlManager acMgr = sImpl.getAccessControlManager();
+ AccessControlPolicy[] policies = acMgr.getPolicies(a.getPath());
+ assertNotNull(policies);
+ assertEquals(1, policies.length);
+ assertTrue(policies[0] instanceof AccessControlList);
+
+ AccessControlEntry[] aces = ((AccessControlList) policies[0]).getAccessControlEntries();
+ assertEquals(1, aces.length);
+ assertEquals("tPrincipal", aces[0].getPrincipal().getName());
+
+ } finally {
+ sImpl.refresh(false);
+ }
+ }
+
+ public void testAccessControlActionExecutionForGroup() throws Exception {
+ AccessControlAction a1 = new AccessControlAction();
+ a1.setGroupPrivilegeNames(Privilege.JCR_READ);
+
+ umgr.setAuthorizableActions(new AuthorizableAction[] {a1});
+
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"g\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>b2f5ff47-4366-31b6-a533-d8dc3614845d</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>gPrincipal</sv:value></sv:property>" +
+ "</sv:node>";
+
+ NodeImpl target = (NodeImpl) sImpl.getNode(umgr.getGroupsPath());
+ try {
+ doImport(target, xml);
+
+ Authorizable a = umgr.getAuthorizable("g");
+ assertNotNull(a);
+ assertTrue(a.isGroup());
+
+ AccessControlManager acMgr = sImpl.getAccessControlManager();
+ AccessControlPolicy[] policies = acMgr.getPolicies(a.getPath());
+ assertNotNull(policies);
+ assertEquals(1, policies.length);
+ assertTrue(policies[0] instanceof AccessControlList);
+
+ AccessControlEntry[] aces = ((AccessControlList) policies[0]).getAccessControlEntries();
+ assertEquals(1, aces.length);
+ assertEquals("gPrincipal", aces[0].getPrincipal().getName());
+
+ } finally {
+ sImpl.refresh(false);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
private void doImport(NodeImpl target, String xml) throws IOException, SAXException, RepositoryException {
InputStream in = new ByteArrayInputStream(xml.getBytes("UTF-8"));
SessionImporter importer = new SessionImporter(target, sImpl,
@@ -1377,6 +1558,25 @@ public class UserImporterTest extends Ab
}
+ private final class TestAction implements AuthorizableAction {
+ private String id;
+ private String pw;
+
+ public void onCreate(Group group, Session session) throws RepositoryException {
+ id = group.getID();
+ }
+ public void onCreate(User user, String password, Session session) throws RepositoryException {
+ id = user.getID();
+ pw = password;
+ }
+ public void onRemove(Authorizable authorizable, Session session) throws RepositoryException {
+ // ignore
+ }
+ public void onPasswordChange(User user, String newPassword, Session session) throws RepositoryException {
+ pw = newPassword;
+ }
+ }
+
private final class DummySession implements JackrabbitSession {
private DummySession() {