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 2019/06/25 14:54:41 UTC
svn commit: r1862074 - 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-doc/src/site/markdown/security/user/
oak-jcr/src/test/java/org/apache/j...
Author: angela
Date: Tue Jun 25 14:54:40 2019
New Revision: 1862074
URL: http://svn.apache.org/viewvc?rev=1862074&view=rev
Log:
OAK-8408: UserImporter must not trigger creation of rep:pwd node unless included in xml (initial-pw-change)
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportInitialPwChangeTest.java
- copied, changed from r1861142, 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/UserImpl.java
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/security/user/UserManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryAndForceInitialChangeTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordForceInitialPasswordChangeTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/expiry.md
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=1862074&r1=1862073&r2=1862074&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 Tue Jun 25 14:54:40 2019
@@ -113,7 +113,7 @@ class UserImpl extends AuthorizableImpl
pwHistory.updatePasswordHistory(getTree(), password);
- userManager.setPassword(getTree(), getID(), password, true);
+ userManager.setPassword(getTree(), getID(), password, false);
}
@Override
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=1862074&r1=1862073&r2=1862074&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 Tue Jun 25 14:54:40 2019
@@ -280,7 +280,7 @@ class UserImporter implements ProtectedP
}
String pw = propInfo.getTextValue().getString();
- userManager.setPassword(parent, a.getID(), pw, false);
+ userManager.setPassword(parent, a.getID(), pw, true);
currentPw = pw;
return true;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java?rev=1862074&r1=1862073&r2=1862074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java Tue Jun 25 14:54:40 2019
@@ -164,7 +164,7 @@ public class UserManagerImpl implements
Tree userTree = userProvider.createUser(userID, intermediatePath);
setPrincipal(userTree, principal);
if (password != null) {
- setPassword(userTree, userID, password, true);
+ setPassword(userTree, userID, password, false);
}
User user = new UserImpl(userID, userTree, this);
@@ -454,9 +454,9 @@ public class UserManagerImpl implements
authorizableTree.setProperty(UserConstants.REP_PRINCIPAL_NAME, principal.getName());
}
- void setPassword(@NotNull Tree userTree, @NotNull String userId, @NotNull String password, boolean forceHash) throws RepositoryException {
+ void setPassword(@NotNull Tree userTree, @NotNull String userId, @NotNull String password, boolean isImport) throws RepositoryException {
String pwHash;
- if (forceHash || PasswordUtil.isPlainTextPassword(password)) {
+ if (!isImport || PasswordUtil.isPlainTextPassword(password)) {
try {
pwHash = PasswordUtil.buildPasswordHash(password, config);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
@@ -469,24 +469,26 @@ public class UserManagerImpl implements
// set last-modified property if pw-expiry is enabled and the user is not
// admin. if initial-pw-change is enabled, we don't set the last modified
- // for new users, in order to force a pw change upon the next login
- boolean expiryEnabled = passwordExpiryEnabled();
- boolean forceInitialPwChange = forceInitialPasswordChangeEnabled();
- boolean isNewUser = userTree.getStatus() == Tree.Status.NEW;
-
- if (Utils.canHavePasswordExpired(userId, config)
- // only expiry is enabled, set in all cases
- && ((expiryEnabled && !forceInitialPwChange)
- // as soon as force initial pw is enabled, we set in all cases except new users,
- // irrespective of password expiry being enabled or not
- || (forceInitialPwChange && !isNewUser))) {
-
+ // for new or imported users, in order to force a pw change upon the next login
+ if (Utils.canHavePasswordExpired(userId, config) && setPasswordLastModified(userTree, isImport)) {
Tree pwdTree = TreeUtil.getOrAddChild(userTree, UserConstants.REP_PWD, UserConstants.NT_REP_PASSWORD);
// System.currentTimeMillis() may be inaccurate on windows. This is accepted for this feature.
pwdTree.setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, System.currentTimeMillis(), Type.LONG);
}
}
+ private boolean setPasswordLastModified(@NotNull Tree userTree, boolean isImport) {
+ if (forceInitialPasswordChangeEnabled()) {
+ // initial-pw-change: set last-mod property except for new or imported users (irrespective of pw-expiry configuration)
+ return !(isImport || userTree.getStatus() == Tree.Status.NEW);
+ } else if (passwordExpiryEnabled()) {
+ // only expiry is enabled: set for all user mgt api calls. for user-import only set upon user creation (new tree)
+ return !isImport || userTree.getStatus() == Tree.Status.NEW;
+ } else {
+ return false;
+ }
+ }
+
private boolean passwordExpiryEnabled() {
return config.getConfigValue(UserConstants.PARAM_PASSWORD_MAX_AGE, UserConstants.DEFAULT_PASSWORD_MAX_AGE) > 0;
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryAndForceInitialChangeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryAndForceInitialChangeTest.java?rev=1862074&r1=1862073&r2=1862074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryAndForceInitialChangeTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryAndForceInitialChangeTest.java Tue Jun 25 14:54:40 2019
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.security.user;
import java.util.UUID;
+import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.security.auth.login.CredentialExpiredException;
@@ -24,14 +25,17 @@ import com.google.common.collect.Immutab
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.Authentication;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
+import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.REP_PWD;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -57,6 +61,11 @@ public class PasswordExpiryAndForceIniti
return ConfigurationParameters.of(ImmutableMap.of(UserConfiguration.NAME, parameters));
}
+ @NotNull
+ private Tree getUserTree(@NotNull User user) throws RepositoryException {
+ return root.getTree(user.getPath());
+ }
+
@Test
public void testCreateUser() throws Exception {
String newUserId = "newuser" + UUID.randomUUID();
@@ -65,7 +74,7 @@ public class PasswordExpiryAndForceIniti
user = getUserManager(root).createUser(newUserId, newUserId);
root.commit();
- assertFalse(root.getTree(user.getPath()).hasChild(UserConstants.REP_PWD));
+ assertFalse(getUserTree(user).hasChild(UserConstants.REP_PWD));
assertFalse(user.hasProperty(UserConstants.REP_PWD + "/" + UserConstants.REP_PASSWORD_LAST_MODIFIED));
} finally {
if (user != null) {
@@ -93,7 +102,7 @@ public class PasswordExpiryAndForceIniti
User user = getTestUser();
user.changePassword(userId);
root.commit();
- PropertyState p = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
+ PropertyState p = getUserTree(user).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
long newModTime = p.getValue(Type.LONG);
assertTrue(newModTime > 0);
@@ -101,4 +110,31 @@ public class PasswordExpiryAndForceIniti
// during user creation pw last modified is set, thus it shouldn't expire
a.authenticate(new SimpleCredentials(userId, userId.toCharArray()));
}
+
+ /**
+ * rep:passwordLastModified must NOT be created otherwise the user might never be forced to change pw upon first login.
+ */
+ @Test
+ public void testSetPasswordImportExistingUser() throws Exception {
+ UserManagerImpl userManager = (UserManagerImpl) getUserManager(root);
+ Tree userTree = getUserTree(getTestUser());
+ assertFalse(userTree.hasChild(REP_PWD));
+
+ userManager.setPassword(userTree, getTestUser().getID(), "pwd", true);
+ assertFalse(userTree.hasChild(REP_PWD));
+ }
+
+ /**
+ * rep:passwordLastModified must NOT be created in accordance to UserManager.createUser
+ */
+ @Test
+ public void testSetPasswordImportNewUser() throws Exception {
+ UserManagerImpl userManager = (UserManagerImpl) getUserManager(root);
+ User u = userManager.createUser("uNew", null);
+ Tree userTree = getUserTree(u);
+ assertFalse(userTree.hasChild(REP_PWD));
+
+ userManager.setPassword(userTree, "uNew", "pwd", true);
+ assertFalse(userTree.hasChild(REP_PWD));
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java?rev=1862074&r1=1862073&r2=1862074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java Tue Jun 25 14:54:40 2019
@@ -16,28 +16,34 @@
*/
package org.apache.jackrabbit.oak.security.user;
-import java.util.UUID;
-import javax.jcr.SimpleCredentials;
-import javax.security.auth.login.CredentialExpiredException;
-import javax.security.auth.login.LoginException;
-
import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.Authentication;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
-import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
+import javax.jcr.RepositoryException;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.CredentialExpiredException;
+import javax.security.auth.login.LoginException;
+import java.util.UUID;
+
+import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.REP_PASSWORD_LAST_MODIFIED;
+import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.REP_PWD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -61,6 +67,11 @@ public class PasswordExpiryTest extends
return ConfigurationParameters.of(UserConfiguration.NAME, userConfig);
}
+ @NotNull
+ private Tree getUserTree(@NotNull User user) throws RepositoryException {
+ return root.getTree(user.getPath());
+ }
+
@Test
public void testCreateUser() throws Exception {
String newUserId = "newuser" + UUID.randomUUID();
@@ -70,7 +81,7 @@ public class PasswordExpiryTest extends
user = getUserManager(root).createUser(newUserId, newUserId);
root.commit();
- Tree pwdTree = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD);
+ Tree pwdTree = getUserTree(user).getChild(UserConstants.REP_PWD);
assertTrue(pwdTree.exists());
assertTrue(TreeUtil.isNodeType(pwdTree, UserConstants.NT_REP_PASSWORD, root.getTree(NodeTypeConstants.NODE_TYPES_PATH)));
@@ -95,13 +106,13 @@ public class PasswordExpiryTest extends
@Test
public void testChangePassword() throws Exception {
User user = getTestUser();
- PropertyState p1 = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
+ PropertyState p1 = getUserTree(user).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
long oldModTime = p1.getValue(Type.LONG, 0);
assertTrue(oldModTime > 0);
waitForSystemTimeIncrement(oldModTime);
user.changePassword(userId);
root.commit();
- PropertyState p2 = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
+ PropertyState p2 = getUserTree(user).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
long newModTime = p2.getValue(Type.LONG, 0);
assertTrue(newModTime > oldModTime);
}
@@ -117,7 +128,7 @@ public class PasswordExpiryTest extends
public void testAuthenticatePasswordExpired() throws Exception {
Authentication a = new UserAuthentication(getUserConfiguration(), root, userId);
// set password last modified to beginning of epoch
- root.getTree(getTestUser().getPath()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
+ getUserTree(getTestUser()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
root.commit();
try {
a.authenticate(new SimpleCredentials(userId, userId.toCharArray()));
@@ -131,7 +142,7 @@ public class PasswordExpiryTest extends
public void testAuthenticateBeforePasswordExpired() throws Exception {
Authentication a = new UserAuthentication(getUserConfiguration(), root, userId);
// set password last modified to beginning of epoch
- root.getTree(getTestUser().getPath()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
+ getUserTree(getTestUser()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
root.commit();
try {
a.authenticate(new SimpleCredentials(userId, "wrong".toCharArray()));
@@ -146,7 +157,7 @@ public class PasswordExpiryTest extends
public void testAuthenticatePasswordExpiredChangePassword() throws Exception {
Authentication a = new UserAuthentication(getUserConfiguration(), root, userId);
// set password last modified to beginning of epoch
- root.getTree(getTestUser().getPath()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
+ getUserTree(getTestUser()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0);
root.commit();
// changing the password should reset the pw last mod and the pw no longer be expired
@@ -160,4 +171,40 @@ public class PasswordExpiryTest extends
User adminUser = getUserManager(root).getAuthorizable(getUserConfiguration().getParameters().getConfigValue(UserConstants.PARAM_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID), User.class);
assertFalse(root.getTree(adminUser.getPath()).getChild(UserConstants.REP_PWD).exists());
}
+
+ /**
+ * import existing user: rep:passwordLastModified must not be updated (unless this property is explicitly included in the xml import)
+ */
+ @Test
+ public void testSetPasswordImportExistingUser() throws Exception {
+ UserManager userManager = getUserManager(root);
+ if (userManager instanceof UserManagerImpl) {
+ Tree userTree = getUserTree(getTestUser());
+ assertTrue(userTree.hasChild(REP_PWD));
+ PropertyState lastMod = userTree.getChild(REP_PWD).getProperty(REP_PASSWORD_LAST_MODIFIED);
+
+ waitForSystemTimeIncrement(lastMod.getValue(Type.LONG));
+
+ ((UserManagerImpl) userManager).setPassword(userTree, getTestUser().getID(), "pwd", true);
+ assertTrue(userTree.hasChild(REP_PWD));
+ assertEquals(lastMod.getValue(Type.LONG), userTree.getChild(REP_PWD).getProperty(REP_PASSWORD_LAST_MODIFIED).getValue(Type.LONG));
+ }
+ }
+
+ /**
+ * import new user: rep:passwordLastModified must be created as it would when calling UserManager.createUser
+ */
+ @Test
+ public void testSetPasswordImportNewUser() throws Exception {
+ UserManager userManager = getUserManager(root);
+ if (userManager instanceof UserManagerImpl) {
+ User u = userManager.createUser("uNew", null);
+ Tree userTree = getUserTree(u);
+ assertFalse(userTree.hasChild(REP_PWD));
+
+ ((UserManagerImpl) userManager).setPassword(userTree, "uNew", "pwd", true);
+ assertTrue(userTree.hasChild(REP_PWD));
+ assertTrue(userTree.getChild(REP_PWD).hasProperty(REP_PASSWORD_LAST_MODIFIED));
+ }
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordForceInitialPasswordChangeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordForceInitialPasswordChangeTest.java?rev=1862074&r1=1862073&r2=1862074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordForceInitialPasswordChangeTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordForceInitialPasswordChangeTest.java Tue Jun 25 14:54:40 2019
@@ -19,18 +19,22 @@ package org.apache.jackrabbit.oak.securi
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.Authentication;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
+import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.security.auth.login.CredentialExpiredException;
import java.util.UUID;
+import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.REP_PWD;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -57,6 +61,11 @@ public class PasswordForceInitialPasswor
return ConfigurationParameters.of(UserConfiguration.NAME, userConfig);
}
+ @NotNull
+ private Tree getUserTree(@NotNull User user) throws RepositoryException {
+ return root.getTree(user.getPath());
+ }
+
@Test
public void testCreateUser() throws Exception {
String newUserId = "newuser" + UUID.randomUUID();
@@ -66,8 +75,8 @@ public class PasswordForceInitialPasswor
user = getUserManager(root).createUser(newUserId, newUserId);
root.commit();
- assertFalse(root.getTree(user.getPath()).hasChild(UserConstants.REP_PWD));
- assertFalse(user.hasProperty(UserConstants.REP_PWD + "/" + UserConstants.REP_PASSWORD_LAST_MODIFIED));
+ assertFalse(getUserTree(user).hasChild(REP_PWD));
+ assertFalse(user.hasProperty(REP_PWD + "/" + UserConstants.REP_PASSWORD_LAST_MODIFIED));
} finally {
if (user != null) {
user.remove();
@@ -90,11 +99,11 @@ public class PasswordForceInitialPasswor
@Test
public void testChangePassword() throws Exception {
User user = getTestUser();
- PropertyState p1 = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
+ PropertyState p1 = getUserTree(user).getChild(REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
assertNull(p1);
user.changePassword(userId);
root.commit();
- PropertyState p2 = root.getTree(user.getPath()).getChild(UserConstants.REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
+ PropertyState p2 = getUserTree(user).getChild(REP_PWD).getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED);
assertNotNull(p2);
assertTrue(p2.getValue(Type.LONG) > 0);
@@ -102,4 +111,31 @@ public class PasswordForceInitialPasswor
Authentication a = new UserAuthentication(getUserConfiguration(), root, userId);
a.authenticate(new SimpleCredentials(userId, userId.toCharArray()));
}
+
+ /**
+ * rep:passwordLastModified must NOT be created otherwise the user might never be forced to change pw upon first login.
+ */
+ @Test
+ public void testSetPasswordImportExistingUser() throws Exception {
+ UserManagerImpl userManager = (UserManagerImpl) getUserManager(root);
+ Tree userTree = getUserTree(getTestUser());
+ assertFalse(userTree.hasChild(REP_PWD));
+
+ userManager.setPassword(userTree, getTestUser().getID(), "pwd", true);
+ assertFalse(userTree.hasChild(REP_PWD));
+ }
+
+ /**
+ * rep:passwordLastModified must NOT be created in accordance to UserManager.createUser
+ */
+ @Test
+ public void testSetPasswordImportNewUser() throws Exception {
+ UserManagerImpl userManager = (UserManagerImpl) getUserManager(root);
+ User u = userManager.createUser("uNew", null);
+ Tree userTree = getUserTree(u);
+ assertFalse(userTree.hasChild(REP_PWD));
+
+ userManager.setPassword(userTree, "uNew", "pwd", true);
+ assertFalse(userTree.hasChild(REP_PWD));
+ }
}
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=1862074&r1=1862073&r2=1862074&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 Tue Jun 25 14:54:40 2019
@@ -184,14 +184,14 @@ public class UserManagerImplTest extends
Tree userTree = root.getTree(user.getPath());
for (String pw : pwds) {
- userMgr.setPassword(userTree, testUserId, pw, true);
+ userMgr.setPassword(userTree, testUserId, pw, false);
String pwHash = userTree.getProperty(UserConstants.REP_PASSWORD).getValue(Type.STRING);
assertNotNull(pwHash);
assertTrue(PasswordUtil.isSame(pwHash, pw));
}
for (String pw : pwds) {
- userMgr.setPassword(userTree, testUserId, pw, false);
+ userMgr.setPassword(userTree, testUserId, pw, true);
String pwHash = userTree.getProperty(UserConstants.REP_PASSWORD).getValue(Type.STRING);
assertNotNull(pwHash);
if (!pw.startsWith("{")) {
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/expiry.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/expiry.md?rev=1862074&r1=1862073&r2=1862074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/expiry.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/expiry.md Tue Jun 25 14:54:40 2019
@@ -195,6 +195,15 @@ potential need to enable password expiry
imported data to make sense, and/or the effect on already existing/overwritten
data.
+With the changes made in the light of [OAK-8408](https://issues.apache.org/jira/browse/OAK-8408)
+the following rules apply when importing a user without an extra `rep:pw` node:
+
+- if `initialPasswordChange` is enabled, `rep:passwordLastModified` will never be set irrespective if the user node is
+ new or modified. i.e. the user will be force to change the pw upon login.
+- if `pw-expiry` is enabled, `rep:passwordLastModified` will only be set for a new user node (but not if node gets modified).
+ this ensures that the password will expire but doesn't reset the expiry when changing an existing user with XML import.
+- if both `initialPasswordChange` and `pw-expiry` are enabled, the rules for `initialPasswordChange` apply.
+
<!-- hidden references -->
[SimpleCredentials]: http://www.day.com/specs/javax.jcr/javadocs/jcr-2.0/javax/jcr/SimpleCredentials.html
[CredentialExpiredException]: https://docs.oracle.com/javase/7/docs/api/javax/security/auth/login/CredentialExpiredException.html
Copied: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportInitialPwChangeTest.java (from r1861142, 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/UserImportInitialPwChangeTest.java?p2=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportInitialPwChangeTest.java&p1=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java&r1=1861142&r2=1862074&rev=1862074&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/UserImportInitialPwChangeTest.java Tue Jun 25 14:54:40 2019
@@ -16,30 +16,44 @@
*/
package org.apache.jackrabbit.oak.jcr.security.user;
-import java.util.HashMap;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.Session;
-
+import jdk.nashorn.internal.ir.annotations.Ignore;
+import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
+import org.apache.jackrabbit.spi.Name;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.LoginException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.security.auth.login.CredentialExpiredException;
+import java.util.HashMap;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Testing user import with default {@link org.apache.jackrabbit.oak.spi.xml.ImportBehavior}
- * and pw-expiry content
- *
- * @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>
+ * and initial-pw-change option enabled
*/
-public class UserImportPwExpiryTest extends AbstractImportTest {
+public class UserImportInitialPwChangeTest extends AbstractImportTest {
@Override
protected String getTargetPath() {
@@ -48,178 +62,139 @@ public class UserImportPwExpiryTest exte
@Override
protected String getImportBehavior() {
- return null;
+ return ImportBehavior.NAME_BESTEFFORT;
}
@Nullable
protected ConfigurationParameters getConfigurationParameters() {
HashMap<String, Object> userParams = new HashMap<String, Object>() {{
- put(UserConstants.PARAM_PASSWORD_MAX_AGE, 10);
+ put(UserConstants.PARAM_PASSWORD_INITIAL_CHANGE, true);
}};
return ConfigurationParameters.of(UserConfiguration.NAME, ConfigurationParameters.of(userParams));
}
- /**
- * @since Oak 1.1
- */
@Test
- public void testImportUserCreatesPasswordLastModified() throws Exception {
+ public void testImportUserWithoutPwdNode() throws Exception {
// import user
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 sv:name=\"" + UserConstants.REP_PWD + "\">" +
- " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">" +
- " <sv:value>"+ UserConstants.NT_REP_PASSWORD +"</sv:value>" +
- " </sv:property>" +
- " </sv:node>" +
+ "<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:authorizableId\" sv:type=\"String\"><sv:value>t</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:node>";
doImport(USERPATH, xml);
- Authorizable authorizable = getUserManager().getAuthorizable("x");
+ Authorizable authorizable = getUserManager().getAuthorizable("t");
Node userNode = getImportSession().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());
+ assertFalse(userNode.hasNode(UserConstants.REP_PWD));
+ getImportSession().save();
+
+ try {
+ getImportSession().getRepository().login(new SimpleCredentials("t", "t".toCharArray())).logout();
+ fail("must be prompted for initial pw change!");
+ } catch (LoginException e) {
+ assertTrue(e.getCause() instanceof CredentialExpiredException);
+ }
}
- /**
- * @since Oak 1.1
- */
@Test
- public void testImportUserCreatesPasswordLastModified2() throws Exception {
- // import user without rep:pwd child node defined
+ public void testImportExistingUserWithoutPwdNode() throws Exception {
+ User user = getUserManager().createUser("t", "t");
+ getImportSession().save();
+ String userPath = user.getPath();
+ String uuid = getImportSession().getProperty(PathUtils.concat(userPath, JcrConstants.JCR_UUID)).getString();
+
+ // import user
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 sv:name=\""+PathUtils.getName(userPath)+"\" 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>"+uuid+"</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:authorizableId\" sv:type=\"String\"><sv:value>t</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:node sv:name=\"profile\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>"+ JcrConstants.NT_UNSTRUCTURED +"</sv:value></sv:property>" +
+ " </sv:node>" +
"</sv:node>";
- doImport(USERPATH, xml);
+ doImport(PathUtils.getParentPath(userPath), xml, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
- // verify that the pwd node has still been created
- Authorizable authorizable = getUserManager().getAuthorizable("x");
+ Authorizable authorizable = getUserManager().getAuthorizable("t");
Node userNode = getImportSession().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());
+ assertFalse(userNode.hasNode(UserConstants.REP_PWD));
+ getImportSession().save();
+
+ try {
+ getImportSession().getRepository().login(new SimpleCredentials("t", "t".toCharArray())).logout();
+ fail("must be prompted for initial pw change!");
+ } catch (LoginException e) {
+ assertTrue(e.getCause() instanceof CredentialExpiredException);
+ }
}
- /**
- * @since Oak 1.1
- */
@Test
- public void testImportUserWithPwdProperties() throws Exception {
+ public void testImportUserWithPwdNodeMissingLastModified() throws Exception {
// import user
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
- "<sv:node sv:name=\"y\" 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>41529076-9594-360e-ae48-5922904f345d</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>yPrincipal</sv:value>" +
- " </sv:property>" +
+ "<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:authorizableId\" sv:type=\"String\"><sv:value>t</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:node sv:name=\"" + UserConstants.REP_PWD + "\">" +
- " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">" +
- " <sv:value>" + UserConstants.NT_REP_PASSWORD + "</sv:value>" +
- " </sv:property>" +
- " <sv:property sv:name=\"" + UserConstants.REP_PASSWORD_LAST_MODIFIED + "\" sv:type=\"Long\">" +
- " <sv:value>1404036716000</sv:value>" +
- " </sv:property>" +
- " <sv:property sv:name=\"customProp\" sv:type=\"String\">" +
- " <sv:value>abc</sv:value>" +
- " </sv:property>" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>"+ UserConstants.NT_REP_PASSWORD +"</sv:value></sv:property>" +
" </sv:node>" +
"</sv:node>";
doImport(USERPATH, xml);
- Authorizable authorizable = getUserManager().getAuthorizable("y");
+ Authorizable authorizable = getUserManager().getAuthorizable("t");
Node userNode = getImportSession().getNode(authorizable.getPath());
assertTrue(userNode.hasNode(UserConstants.REP_PWD));
-
Node pwdNode = userNode.getNode(UserConstants.REP_PWD);
- assertTrue(pwdNode.hasProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED));
- assertEquals(1404036716000L, pwdNode.getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED).getLong());
+ assertFalse(pwdNode.hasProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED));
+ getImportSession().save();
- assertTrue(pwdNode.hasProperty("customProp"));
- Property custom = pwdNode.getProperty("customProp");
- assertTrue(custom.getDefinition().isProtected());
- assertEquals("abc", custom.getString());
+ try {
+ getImportSession().getRepository().login(new SimpleCredentials("t", "t".toCharArray())).logout();
+ fail("must be prompted for initial pw change!");
+ } catch (LoginException e) {
+ assertTrue(e.getCause() instanceof CredentialExpiredException);
+ }
}
- /**
- * @since Oak 1.1
- */
@Test
- public void testImportExistingUserWithoutExpiryProperty() throws Exception {
-
- String uid = "existing";
- User user = getUserManager().createUser(uid, uid);
-
- Session s = getImportSession();
- // change password to force existence of password last modified property
- user.changePassword(uid);
- s.save();
-
- Node userNode = s.getNode(user.getPath());
- assertTrue(userNode.hasNode(UserConstants.REP_PWD));
- Node pwdNode = userNode.getNode(UserConstants.REP_PWD);
- assertTrue(pwdNode.hasProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED));
-
- // overwrite user via import
+ public void testImportUserWithPwdNodeWithLastModified() throws Exception {
+ // import user
+ long now = System.currentTimeMillis();
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=\"rep:password\" sv:type=\"String\">" +
- " <sv:value>" + uid + "</sv:value>" +
- " </sv:property>" +
- " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\">" +
- " <sv:value>" + uid + "Principal</sv:value>" +
- " </sv:property>" +
+ "<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:authorizableId\" sv:type=\"String\"><sv:value>t</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:node sv:name=\"" + UserConstants.REP_PWD + "\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>"+ UserConstants.NT_REP_PASSWORD +"</sv:value></sv:property>" +
+ " <sv:property sv:name=\"" + UserConstants.REP_PASSWORD_LAST_MODIFIED + "\" sv:type=\"Long\"><sv:value>"+now+"</sv:value></sv:property>" +
+ " </sv:node>" +
"</sv:node>";
doImport(USERPATH, xml);
- Authorizable authorizable = getUserManager().getAuthorizable(uid);
- userNode = s.getNode(authorizable.getPath());
+ Authorizable authorizable = getUserManager().getAuthorizable("t");
+ Node userNode = getImportSession().getNode(authorizable.getPath());
assertTrue(userNode.hasNode(UserConstants.REP_PWD));
-
- pwdNode = userNode.getNode(UserConstants.REP_PWD);
+ Node pwdNode = userNode.getNode(UserConstants.REP_PWD);
assertTrue(pwdNode.hasProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED));
+ assertEquals(now, pwdNode.getProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED).getLong());
+ getImportSession().save();
+
+ // login must succeed
+ getImportSession().getRepository().login(new SimpleCredentials("t", "t".toCharArray())).logout();
}
}