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 2014/10/30 11:54:37 UTC
svn commit: r1635464 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/
oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/
oak-jcr/src/test/java/or...
Author: angela
Date: Thu Oct 30 10:54:37 2014
New Revision: 1635464
URL: http://svn.apache.org/r1635464
Log:
OAK-2245 : UserImporter should always set the rep:authorizableID
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java?rev=1635464&r1=1635463&r2=1635464&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java Thu Oct 30 10:54:37 2014
@@ -152,12 +152,12 @@ class UserImporter implements ProtectedP
* 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);
+ private String currentPw;
/**
* Remember all new principals for impersonation handling.
*/
- private Map<String, Principal> principals;
+ private Map<String, Principal> principals = new HashMap<String, Principal>();;
UserImporter(ConfigurationParameters config) {
String importBehaviorStr = config.getConfigValue(PARAM_IMPORT_BEHAVIOR, ImportBehavior.NAME_IGNORE);
@@ -221,146 +221,133 @@ class UserImporter implements ProtectedP
checkInitialized();
String propName = propInfo.getName();
- boolean isPwdNode = isPwdNode(parent);
- Tree authorizableTree = (isPwdNode) ? parent.getParent() : parent;
- Authorizable a = userManager.getAuthorizable(authorizableTree);
-
- if (a == null) {
- log.warn("Cannot handle protected PropInfo " + propInfo + ". Node " + parent + " doesn't represent a valid Authorizable.");
- return false;
- }
-
- if (REP_AUTHORIZABLE_ID.equals(propName)) {
- if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
- return false;
- }
- String id = propInfo.getTextValue().getString();
- Authorizable existing = userManager.getAuthorizable(id);
- if (a.getPath().equals(existing.getPath())) {
- parent.setProperty(REP_AUTHORIZABLE_ID, id);
- } else {
- throw new AuthorizableExistsException(id);
- }
- } else if (REP_PRINCIPAL_NAME.equals(propName)) {
- if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
+ if (isPwdNode(parent)) {
+ // overwrite any properties generated underneath the rep:pwd node
+ // by "UserManagerImpl#setPassword" by the properties defined by
+ // the XML to be imported. see OAK-1943 for the corresponding discussion.
+ return importPwdNodeProperty(parent, propInfo, def);
+ } else {
+ Authorizable a = userManager.getAuthorizable(parent);
+ if (a == null) {
+ log.warn("Cannot handle protected PropInfo " + propInfo + ". Node " + parent + " doesn't represent a valid Authorizable.");
return false;
}
- String principalName = propInfo.getTextValue().getString();
- Principal principal = new PrincipalImpl(principalName);
- userManager.checkValidPrincipal(principal, a.isGroup());
- userManager.setPrincipal(parent, principal);
+ if (REP_AUTHORIZABLE_ID.equals(propName)) {
+ if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
+ return false;
+ }
+ String id = propInfo.getTextValue().getString();
+ Authorizable existing = userManager.getAuthorizable(id);
+ if (a.getPath().equals(existing.getPath())) {
+ parent.setProperty(REP_AUTHORIZABLE_ID, id);
+ } else {
+ throw new AuthorizableExistsException(id);
+ }
+ } else if (REP_PRINCIPAL_NAME.equals(propName)) {
+ if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
+ return false;
+ }
+
+ String principalName = propInfo.getTextValue().getString();
+ Principal principal = new PrincipalImpl(principalName);
+ userManager.checkValidPrincipal(principal, a.isGroup());
+ userManager.setPrincipal(parent, principal);
/*
Remember principal of new user/group for further processing
of impersonators
*/
- if (principals == null) {
- principals = new HashMap<String, Principal>();
- }
- principals.put(principalName, a.getPrincipal());
+ if (principals == null) {
+ principals = new HashMap<String, Principal>();
+ }
+ principals.put(principalName, a.getPrincipal());
- /*
- 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.
- */
- a = userManager.getAuthorizable(parent);
- if (a == null) {
- log.warn("Cannot handle protected PropInfo " + propInfo + ". Node " + parent + " doesn't represent a valid Authorizable.");
- return false;
- }
- if (parent.getStatus() == Tree.Status.NEW) {
- 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 (REP_PASSWORD.equals(propName)) {
+ if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
+ log.warn("Unexpected authorizable or definition for property rep:password");
+ return false;
+ }
+ if (((User) a).isSystemUser()) {
+ log.warn("System users may not have a password set.");
+ return false;
}
- }
- return true;
- } else if (REP_PASSWORD.equals(propName)) {
- if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
- log.warn("Unexpected authorizable or definition for property rep:password");
- return false;
- }
- if (((User) a).isSystemUser()) {
- log.warn("System users may not have a password set.");
- return false;
- }
- String pw = propInfo.getTextValue().getString();
- userManager.setPassword(parent, a.getID(), pw, false);
+ String pw = propInfo.getTextValue().getString();
+ userManager.setPassword(parent, a.getID(), pw, false);
+ currentPw = 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.getStatus() == Tree.Status.NEW) {
- if (parent.hasProperty(REP_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 (REP_IMPERSONATORS.equals(propName)) {
+ if (a.isGroup() || !isValid(def, MIX_REP_IMPERSONATABLE, true)) {
+ log.warn("Unexpected authorizable or definition for property rep:impersonators");
+ return false;
}
- }
- return true;
- } else if (REP_IMPERSONATORS.equals(propName)) {
- if (a.isGroup() || !isValid(def, MIX_REP_IMPERSONATABLE, true)) {
- log.warn("Unexpected authorizable or definition for property rep:impersonators");
- return false;
- }
+ // since impersonators may be imported later on, postpone processing
+ // to the end.
+ // see -> process References
+ referenceTracker.processedReference(new Impersonators(a.getID(), propInfo.getTextValues()));
+ return true;
- // since impersonators may be imported later on, postpone processing
- // to the end.
- // see -> process References
- referenceTracker.processedReference(new Impersonators(a.getID(), propInfo.getTextValues()));
- return true;
-
- } else if (REP_DISABLED.equals(propName)) {
- if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
- log.warn("Unexpected authorizable or definition for property rep:disabled");
- return false;
- }
+ } else if (REP_DISABLED.equals(propName)) {
+ if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
+ log.warn("Unexpected authorizable or definition for property rep:disabled");
+ return false;
+ }
- ((User) a).disable(propInfo.getTextValue().getString());
- return true;
+ ((User) a).disable(propInfo.getTextValue().getString());
+ return true;
- } else if (REP_MEMBERS.equals(propName)) {
- if (!a.isGroup() || !isValid(def, NT_REP_MEMBER_REFERENCES, true)) {
- return false;
- }
- // since group-members are references to user/groups that potentially
- // are to be imported later on -> postpone processing to the end.
- // see -> process References
- getMembership(a.getID()).addMembers(propInfo.getTextValues());
- return true;
+ } else if (REP_MEMBERS.equals(propName)) {
+ if (!a.isGroup() || !isValid(def, NT_REP_MEMBER_REFERENCES, true)) {
+ return false;
+ }
+ // since group-members are references to user/groups that potentially
+ // are to be imported later on -> postpone processing to the end.
+ // see -> process References
+ getMembership(a.getID()).addMembers(propInfo.getTextValues());
+ return true;
- } else if (isPwdNode) {
- // overwrite any properties generated underneath the rep:pwd node
- // by "UserManagerImpl#setPassword" by the properties defined by
- // the XML to be imported. see OAK-1943 for the corresponding discussion.
- int targetType = def.getRequiredType();
- if (targetType == PropertyType.UNDEFINED) {
- targetType = (REP_PASSWORD_LAST_MODIFIED.equals(propName)) ? PropertyType.LONG : PropertyType.STRING;
- }
- PropertyState property;
- if (def.isMultiple()) {
- property = PropertyStates.createProperty(propName, propInfo.getValues(targetType));
- } else {
- property = PropertyStates.createProperty(propName, propInfo.getValue(targetType));
- };
- parent.setProperty(property);
- }// else: cannot handle -> return false
+ } // another protected property -> return false
+ }
+ // neither rep:pwd nor authorizable node -> not covered by this importer.
return false;
}
@Override
+ public void propertiesCompleted(@Nonnull Tree protectedParent) throws IllegalStateException, ConstraintViolationException, RepositoryException {
+ Authorizable a = userManager.getAuthorizable(protectedParent);
+ if (a == null) {
+ // not an authorizable
+ return;
+ }
+
+ // make sure the authorizable ID property is always set even if the
+ // authorizable defined by the imported XML didn't provide rep:authorizableID
+ if (!protectedParent.hasProperty(REP_AUTHORIZABLE_ID)) {
+ protectedParent.setProperty(REP_AUTHORIZABLE_ID, a.getID(), Type.STRING);
+ }
+
+ /*
+ Execute authorizable actions for a NEW user at this point after
+ having set the password and the principal name (all protected properties
+ have been processed now).
+ */
+ if (protectedParent.getStatus() == Tree.Status.NEW) {
+ if (a.isGroup()) {
+ userManager.onCreate((Group) a);
+ } else {
+ userManager.onCreate((User) a, currentPw);
+ }
+ }
+ currentPw = null;
+ }
+
+ @Override
public void processReferences() throws RepositoryException {
checkInitialized();
@@ -498,6 +485,25 @@ class UserImporter implements ProtectedP
return REP_PWD.equals(tree.getName()) && NT_REP_PASSWORD.equals(TreeUtil.getPrimaryTypeName(tree));
}
+ private static boolean importPwdNodeProperty(@Nonnull Tree parent, @Nonnull PropInfo propInfo, @Nonnull PropertyDefinition def) throws RepositoryException {
+ String propName = propInfo.getName();
+ // overwrite any properties generated underneath the rep:pwd node
+ // by "UserManagerImpl#setPassword" by the properties defined by
+ // the XML to be imported. see OAK-1943 for the corresponding discussion.
+ int targetType = def.getRequiredType();
+ if (targetType == PropertyType.UNDEFINED) {
+ targetType = (REP_PASSWORD_LAST_MODIFIED.equals(propName)) ? PropertyType.LONG : PropertyType.STRING;
+ }
+ PropertyState property;
+ if (def.isMultiple()) {
+ property = PropertyStates.createProperty(propName, propInfo.getValues(targetType));
+ } else {
+ property = PropertyStates.createProperty(propName, propInfo.getValue(targetType));
+ }
+ parent.setProperty(property);
+ return true;
+ }
+
/**
* Handling the import behavior
*
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java?rev=1635464&r1=1635463&r2=1635464&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java Thu Oct 30 10:54:37 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.xm
import javax.annotation.Nonnull;
import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.PropertyDefinition;
import org.apache.jackrabbit.oak.api.Tree;
@@ -45,4 +46,20 @@ public interface ProtectedPropertyImport
boolean handlePropInfo(@Nonnull Tree parent, @Nonnull PropInfo protectedPropInfo,
@Nonnull PropertyDefinition def) throws RepositoryException;
+ /**
+ * Informs this importer that all properties to be imported below
+ * {@code protectedParent} have been processed by the importer. If this importer
+ * did not import any protected properties this method doesn't do anything.
+ * Otherwise it may perform some validation and cleanup required based
+ * on the set of protected properties handled by this importer.
+ *
+ * @param protectedParent The protected parent tree.
+ * @throws IllegalStateException If this method is called in an illegal state.
+ * @throws javax.jcr.nodetype.ConstraintViolationException If the set of
+ * properties was incomplete and the importer was not able to fix the problem.
+ * @throws RepositoryException If another error occurs.
+ */
+ void propertiesCompleted(@Nonnull Tree protectedParent) throws IllegalStateException,
+ ConstraintViolationException, RepositoryException;
+
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java?rev=1635464&r1=1635463&r2=1635464&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java Thu Oct 30 10:54:37 2014
@@ -28,6 +28,7 @@ import java.util.UUID;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.ItemExistsException;
import javax.jcr.PathNotFoundException;
@@ -41,6 +42,9 @@ import javax.jcr.nodetype.PropertyDefini
import javax.jcr.version.VersionException;
import javax.jcr.version.VersionManager;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
@@ -295,20 +299,48 @@ public class ImporterImpl implements Imp
log.debug("Protected property " + pi.getName());
// notify the ProtectedPropertyImporter.
- for (ProtectedItemImporter ppi : pItemImporters) {
- if (ppi instanceof ProtectedPropertyImporter
- && ((ProtectedPropertyImporter) ppi).handlePropInfo(tree, pi, def)) {
+ for (ProtectedPropertyImporter ppi : getPropertyImporters()) {
+ if (ppi.handlePropInfo(tree, pi, def)) {
log.debug("Protected property -> delegated to ProtectedPropertyImporter");
break;
- } /* else: p-i-Importer isn't able to deal with this property.
- try next pp-importer */
-
+ } /* else: p-i-Importer isn't able to deal with this property. try next pp-importer */
}
} else if (!ignoreRegular) {
// regular property -> create the property
createProperty(tree, pi, def);
}
}
+ for (ProtectedPropertyImporter ppi : getPropertyImporters()) {
+ ppi.propertiesCompleted(tree);
+ }
+ }
+
+ private Iterable<ProtectedPropertyImporter> getPropertyImporters() {
+ return Iterables.filter(Iterables.transform(pItemImporters, new Function<ProtectedItemImporter, ProtectedPropertyImporter>() {
+ @Nullable
+ @Override
+ public ProtectedPropertyImporter apply(@Nullable ProtectedItemImporter importer) {
+ if (importer instanceof ProtectedPropertyImporter) {
+ return (ProtectedPropertyImporter) importer;
+ } else {
+ return null;
+ }
+ }
+ }), Predicates.notNull());
+ }
+
+ private Iterable<ProtectedNodeImporter> getNodeImporters() {
+ return Iterables.filter(Iterables.transform(pItemImporters, new Function<ProtectedItemImporter, ProtectedNodeImporter>() {
+ @Nullable
+ @Override
+ public ProtectedNodeImporter apply(@Nullable ProtectedItemImporter importer) {
+ if (importer instanceof ProtectedNodeImporter) {
+ return (ProtectedNodeImporter) importer;
+ } else {
+ return null;
+ }
+ }
+ }), Predicates.notNull());
}
//-----------------------------------------------------------< Importer >---
@@ -355,10 +387,10 @@ public class ImporterImpl implements Imp
// if there is one, notify the ProtectedNodeImporter about the
// start of a item tree that is protected by this parent. If it
// potentially is able to deal with it, notify it about the child node.
- for (ProtectedItemImporter pni : pItemImporters) {
- if (pni instanceof ProtectedNodeImporter && ((ProtectedNodeImporter) pni).start(parent)) {
+ for (ProtectedNodeImporter pni : getNodeImporters()) {
+ if (pni.start(parent)) {
log.debug("Protected node -> delegated to ProtectedNodeImporter");
- pnImporter = (ProtectedNodeImporter) pni;
+ pnImporter = pni;
pnImporter.startChildInfo(nodeInfo, propInfos);
break;
} /* else: p-i-Importer isn't able to deal with the protected tree.
Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java?rev=1635464&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java Thu Oct 30 10:54:37 2014
@@ -0,0 +1,413 @@
+/*
+ * 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.jcr.security.user;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.test.api.util.Text;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests to verify the behavior of importing user content packages exported
+ * from Jackrabbit 2.x and their behavior upon import into an Oak repository.
+ *
+ * @since Oak 1.2
+ * @see <a href="https://issues.apache.org/jira/browse/OAK-2245">OAK-2245</a>
+ */
+public class UserImportFromJackrabbit extends AbstractImportTest {
+
+ private String uid = "t";
+ private String randomNodeName = "f5aj6fp7q9834jof";
+ private String intermediatePath = "foo/bar/test";
+
+ @Override
+ protected String getTargetPath() {
+ return USERPATH;
+ }
+
+ @Override
+ protected String getImportBehavior() {
+ return null;
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testImportCreatesAuthorizableId() throws Exception {
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\""+uid+"\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+ assertEquals(uid, newUser.getID());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(uid, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must succeed
+ adminSession.save();
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorReplace() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl("t"), getTargetPath() + "/foo/bar/test");
+ String initialPath = u.getPath();
+ adminSession.save();
+
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\""+uid+"\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // replace should retain path
+ assertEquals(initialPath, newUser.getPath());
+ assertFalse(getTargetPath().equals(Text.getRelativeParent(newUser.getPath(), 1)));
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(uid, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must succeed
+ adminSession.save();
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorRemove() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String initialPath = u.getPath();
+ adminSession.save();
+
+ 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // IMPORT_UUID_COLLISION_REMOVE_EXISTING should result in the user to
+ // be imported a the new path
+ assertEquals(getTargetPath(), Text.getRelativeParent(newUser.getPath(), 1));
+ assertFalse(initialPath.equals(newUser.getPath()));
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(uid, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must succeed
+ adminSession.save();
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorReplaceFromRenamed() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String initialPath = u.getPath();
+ String movedPath = Text.getRelativeParent(initialPath, 1) + '/' + randomNodeName;
+ adminSession.move(initialPath, movedPath);
+ adminSession.save();
+
+ // import 'correct' jr2 package which contains the encoded ID in the node name
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\""+uid+"\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // replace should update the path
+ assertEquals("user path", Text.getRelativeParent(initialPath, 1) + '/' + uid, newUser.getPath());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, uid, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, uid, newUser.getID());
+
+ // saving changes of the import must succeed.
+ adminSession.save();
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorReplaceFromRenamed2() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String initialPath = u.getPath();
+ String movedPath = Text.getRelativeParent(initialPath, 1) + '/' + randomNodeName;
+ adminSession.move(initialPath, movedPath);
+ adminSession.save();
+
+ // we need to include the new node name in the sysview import, so that the importer uses the correct name.
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"" + randomNodeName + "\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // replace should retain path
+ assertEquals("user path", movedPath, newUser.getPath());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, randomNodeName, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes must fail -> the original authorizable has been replaced
+ // and got the ID set as specified by the Jackrabbit XML. Since the latter
+ // specifies the modified authorizable ID, which doesn't represent the
+ // correct ID as hashed in the jcr:uuid, the CommitHook will detect
+ // the mismatch, which for the diff looks like a modified ID.
+ try {
+ adminSession.save();
+ fail("Importing an authorizable with mismatch between authorizableId and uuid must fail.");
+ } catch (ConstraintViolationException e) {
+ // success
+ assertTrue(e.getMessage().contains("OakConstraint0022"));
+ }
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorReplaceFromRenamed3() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String originalPath = u.getPath();
+ adminSession.save();
+
+ // we need to include the new node name in the sysview import, so that the importer uses the correct name.
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"" + randomNodeName + "\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // replace should change the original path
+ String expectedPath = Text.getRelativeParent(originalPath, 1) + '/' + randomNodeName;
+ assertEquals("user path", expectedPath, newUser.getPath());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, randomNodeName, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must fail as the authorizable ID
+ // has been modified (it no longer represents the correct ID due to the
+ // modified node name in combination with the fact that in JR 2.x
+ // the node name MUST contain the id as there is no rep:authorizableId.
+ try {
+ adminSession.save();
+ fail("Importing an authorizable with mismatch between authorizableId and uuid must fail.");
+ } catch (ConstraintViolationException e) {
+ // success
+ assertTrue(e.getMessage().contains("OakConstraint0021"));
+ }
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorRemoveFromRenamed() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String initialPath = u.getPath();
+ String movedPath = Text.getRelativeParent(initialPath, 1) + '/' + randomNodeName;
+ adminSession.move(initialPath, movedPath);
+ adminSession.save();
+
+ // import 'correct' jr2 package which contains the encoded ID in the node name
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\""+uid+"\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // IMPORT_UUID_COLLISION_REMOVE_EXISTING should import the user at the new path
+ assertEquals("user path", getTargetPath() + '/' + uid, newUser.getPath());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, uid, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, uid, newUser.getID());
+
+ // saving changes of the import must succeed.
+ adminSession.save();
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorRemoveFromRenamed2() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String initialPath = u.getPath();
+ String movedPath = Text.getRelativeParent(initialPath, 1) + '/' + randomNodeName;
+ adminSession.move(initialPath, movedPath);
+ adminSession.save();
+
+ // we need to include the new node name in the sysview import, so that the importer uses the correct name.
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"" + randomNodeName + "\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // IMPORT_UUID_COLLISION_REMOVE_EXISTING should import the user at the new path
+ assertEquals("user path", getTargetPath() + '/' + randomNodeName, newUser.getPath());
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, randomNodeName, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must fail as original user has been
+ // removed and the JR 2.x the node name doesn't contain the correct id,
+ // which is detected during save as it looks like the id had been modified.
+ try {
+ adminSession.save();
+ fail("Importing an authorizable with mismatch between authorizableId and uuid must fail.");
+ } catch (ConstraintViolationException e) {
+ // success
+ assertTrue(e.getMessage().contains("OakConstraint0021"));
+ }
+ }
+
+ /**
+ * @since Oak 1.2
+ */
+ @Test
+ public void testUUIDBehaviorRemoveFromRenamed3() throws Exception {
+ // create authorizable
+ User u = userMgr.createUser(uid, null, new PrincipalImpl(uid), intermediatePath);
+ String originalPath = u.getPath();
+ adminSession.save();
+
+ // we need to include the new node name in the sysview import, so that the importer uses the correct name.
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"" + randomNodeName + "\" 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>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:disabled\" sv:type=\"String\"><sv:value>disabledUser</sv:value></sv:property>" +
+ "</sv:node>";
+
+ doImport(getTargetPath(), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+
+ Authorizable newUser = userMgr.getAuthorizable(uid);
+
+ // replace should change the original path
+ String expectedPath = getTargetPath() + '/' + randomNodeName;
+ assertEquals("user path", expectedPath, newUser.getPath());
+ assertFalse((Text.getRelativeParent(originalPath,1) + '/' + randomNodeName).equals(newUser.getPath()));
+
+ Node n = adminSession.getNode(newUser.getPath());
+ assertTrue(n.hasProperty(UserConstants.REP_AUTHORIZABLE_ID));
+ assertEquals(UserConstants.REP_AUTHORIZABLE_ID, randomNodeName, n.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString());
+
+ // saving changes of the import -> must fail as the authorizable ID
+ // has been modified (it no longer represents the correct ID due to the
+ // fact that in JR 2.x the node name MUST contain the id.
+ try {
+ adminSession.save();
+ fail("Importing an authorizable with mismatch between authorizableId and uuid must fail.");
+ } catch (ConstraintViolationException e) {
+ // success
+ assertTrue(e.getMessage().contains("OakConstraint0021"));
+ }
+ }
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java?rev=1635464&r1=1635463&r2=1635464&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java Thu Oct 30 10:54:37 2014
@@ -37,7 +37,8 @@ import static org.junit.Assert.assertTru
* Testing user import with default {@link org.apache.jackrabbit.oak.spi.xml.ImportBehavior}
* and pw-expiry content
*
- * @see OAK-1922
+ * @see <a href="https://issues.apache.org/jira/browse/OAK-1922">OAK-1922</a>
+ * @see <a href="https://issues.apache.org/jira/browse/OAK-1943">OAK-1943</a>
*/
public class UserImportPwExpiryTest extends AbstractImportTest {
@@ -101,6 +102,40 @@ public class UserImportPwExpiryTest exte
* @since Oak 1.1
*/
@Test
+ public void testImportUserCreatesPasswordLastModified2() throws Exception {
+ // import user without rep:pwd child node defined
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"x\" 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>9dd4e461-268c-3034-b5c8-564e155c67a6</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>xPrincipal</sv:value>" +
+ " </sv:property>" +
+ "</sv:node>";
+
+ doImport(USERPATH, xml);
+
+ // verify that the pwd node has still been created
+ Authorizable authorizable = userMgr.getAuthorizable("x");
+ Node userNode = adminSession.getNode(authorizable.getPath());
+ assertTrue(userNode.hasNode(UserConstants.REP_PWD));
+ Node pwdNode = userNode.getNode(UserConstants.REP_PWD);
+ assertTrue(pwdNode.getDefinition().isProtected());
+ assertTrue(pwdNode.hasProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED));
+ assertTrue(pwdNode.getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED).getDefinition().isProtected());
+ }
+
+ /**
+ * @since Oak 1.1
+ */
+ @Test
public void testImportUserWithPwdProperties() throws Exception {
// import user
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
Re: svn commit: r1635464 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/
oak-jcr/src/test/java/or...
Posted by Julian Reschke <ju...@gmx.de>.
On 2014-10-30 11:54, angela@apache.org wrote:
> Author: angela
> Date: Thu Oct 30 10:54:37 2014
> New Revision: 1635464
>
> URL: http://svn.apache.org/r1635464
> Log:
> OAK-2245 : UserImporter should always set the rep:authorizableID
>
> Added:
> jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java
> Modified:
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java
> ...
...it seems this breaks the build:
> [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.
> 5.1:compile (default-compile) on project oak-authorization-cug: Compilation fail
> ure
> [ERROR] C:\projects\apache\oak\trunk\oak-authorization-cug\src\main\java\org\apa
> che\jackrabbit\oak\spi\security\authorization\cug\impl\CugImporter.java:[50,0] o
> rg.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugImporter is not
> abstract and does not override abstract method propertiesCompleted(org.apache.ja
> ckrabbit.oak.api.Tree) in org.apache.jackrabbit.oak.spi.xml.ProtectedPropertyImp
> orter
Best regards, Julian
Re: svn commit: r1635464 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/
oak-jcr/src/test/java/or...
Posted by Julian Reschke <ju...@gmx.de>.
On 2014-10-30 11:54, angela@apache.org wrote:
> Author: angela
> Date: Thu Oct 30 10:54:37 2014
> New Revision: 1635464
>
> URL: http://svn.apache.org/r1635464
> Log:
> OAK-2245 : UserImporter should always set the rep:authorizableID
>
> Added:
> jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java
> Modified:
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ProtectedPropertyImporter.java
> ...
...it seems this breaks the build:
> [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.
> 5.1:compile (default-compile) on project oak-authorization-cug: Compilation fail
> ure
> [ERROR] C:\projects\apache\oak\trunk\oak-authorization-cug\src\main\java\org\apa
> che\jackrabbit\oak\spi\security\authorization\cug\impl\CugImporter.java:[50,0] o
> rg.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugImporter is not
> abstract and does not override abstract method propertiesCompleted(org.apache.ja
> ckrabbit.oak.api.Tree) in org.apache.jackrabbit.oak.spi.xml.ProtectedPropertyImp
> orter
Best regards, Julian