This is an automated email from the ASF dual-hosted git repository.
enorman pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git
The following commit(s) were added to refs/heads/master by this push:
new abea574 SLING-12202 add canChangePasswordWithoutOldPassword (#24)
abea574 is described below
commit abea5742f5bd668685a0407f0ff7de686d6a733e
Author: Eric Norman <[email protected]>
AuthorDate: Mon Dec 18 14:55:11 2023 -0800
SLING-12202 add canChangePasswordWithoutOldPassword (#24)
---
.../usermanager/AuthorizablePrivilegesInfo.java | 16 +++++
.../impl/AuthorizablePrivilegesInfoImpl.java | 45 +++++++++++--
.../sling/jackrabbit/usermanager/package-info.java | 2 +-
.../AuthorizablePrivilegesInfoTest.java | 75 ++++++++++++++++++++++
.../it/AuthorizablePrivilegesInfoIT.java | 44 +++++++++++++
5 files changed, 177 insertions(+), 5 deletions(-)
diff --git
a/src/main/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfo.java
b/src/main/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfo.java
index 19ffb7b..ff03cf8 100644
---
a/src/main/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfo.java
+++
b/src/main/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfo.java
@@ -18,6 +18,8 @@ package org.apache.sling.jackrabbit.usermanager;
import javax.jcr.Session;
+import org.jetbrains.annotations.NotNull;
+
public interface AuthorizablePrivilegesInfo {
/**
@@ -171,4 +173,18 @@ public interface AuthorizablePrivilegesInfo {
throw new UnsupportedOperationException();
}
+ /**
+ * Checks whether the current user has been granted privileges
+ * to change the password of the specified user without knowing
+ * the current password of the user.
+ *
+ * @param jcrSession the JCR session of the current user
+ * @param userId the user id to check
+ * @return true if the current user has the privileges, false otherwise
+ */
+ default boolean canChangePasswordWithoutOldPassword(@NotNull Session
jcrSession,
+ @NotNull String userId) {
+ throw new UnsupportedOperationException();
+ }
+
}
\ No newline at end of file
diff --git
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
index 3e0edbb..0b82fc8 100644
---
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
+++
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
@@ -37,6 +37,7 @@ import
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo;
import org.apache.sling.jackrabbit.usermanager.ChangeUserPassword;
import org.apache.sling.jackrabbit.usermanager.CreateUser;
import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.jetbrains.annotations.NotNull;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@@ -98,6 +99,7 @@ public class AuthorizablePrivilegesInfoImpl implements
AuthorizablePrivilegesInf
private String groupsPath;
private boolean selfRegistrationEnabled;
private boolean allowSelfChangePassword = false;
+ private String userAdminGroupName;
@Reference(cardinality=ReferenceCardinality.OPTIONAL, policy =
ReferencePolicy.DYNAMIC)
private void bindChangeUserPassword(ChangeUserPassword changeUserPassword,
Map<String, Object> properties) {
@@ -108,6 +110,8 @@ public class AuthorizablePrivilegesInfoImpl implements
AuthorizablePrivilegesInf
} else {
allowSelfChangePassword =
OsgiUtil.toBoolean(properties.get("allowSelfChangePassword"), false);
}
+
+ userAdminGroupName =
OsgiUtil.toString(properties.get(PAR_USER_ADMIN_GROUP_NAME),
DEFAULT_USER_ADMIN_GROUP_NAME);
}
@SuppressWarnings("unused")
private void unbindChangeUserPassword(ChangeUserPassword
changeUserPassword, Map<String, Object> properties) {
@@ -381,17 +385,50 @@ public class AuthorizablePrivilegesInfoImpl implements
AuthorizablePrivilegesInf
return hasRights;
}
+ /* (non-Javadoc)
+ * @see
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canChangePasswordWithoutOldPassword(javax.jcr.Session,
java.lang.String)
+ */
+ @Override
+ public boolean canChangePasswordWithoutOldPassword(@NotNull Session
jcrSession, @NotNull String userId) {
+ boolean can = false;
+ try {
+ // can't change your own password without the old password
+ if (!jcrSession.getUserID().equals(userId)) {
+ UserManager um = AccessControlUtil.getUserManager(jcrSession);
+ Authorizable currentUser =
um.getAuthorizable(jcrSession.getUserID());
+ if (currentUser instanceof User) {
+ Authorizable targetUser = um.getAuthorizable(userId);
+ //system users and anonymous have no passwords
+ if (targetUser instanceof User &&
!((User)targetUser).isSystemUser() && !"anonymous".equals(targetUser.getID())) {
+ if (((User)currentUser).isAdmin()) {
+ can = true;
+ } else if (userAdminGroupName != null) {
+ Authorizable group =
um.getAuthorizable(userAdminGroupName);
+ if (group instanceof Group) {
+ can = ((Group)group).isMember(currentUser);
+ }
+ }
+ }
+ }
+ }
+ } catch (RepositoryException e) {
+ log.warn("Failed to determine if {} is a user admin", userId);
+ }
+ return can;
+ }
+
+
// ---------- SCR Integration
----------------------------------------------
@Activate
protected void activate(BundleContext bundleContext, Map<String, Object>
properties) {
- String userAdminGroupName =
OsgiUtil.toString(properties.get(PAR_USER_ADMIN_GROUP_NAME), null);
- if ( userAdminGroupName != null && !
DEFAULT_USER_ADMIN_GROUP_NAME.equals(userAdminGroupName)) {
+ String deprecatedUserAdminGroupName =
OsgiUtil.toString(properties.get(PAR_USER_ADMIN_GROUP_NAME), null);
+ if ( deprecatedUserAdminGroupName != null && !
DEFAULT_USER_ADMIN_GROUP_NAME.equals(deprecatedUserAdminGroupName)) {
log.warn("Configuration setting for {} is deprecated and will not
have any effect", PAR_USER_ADMIN_GROUP_NAME);
}
- String groupAdminGroupName =
OsgiUtil.toString(properties.get(PAR_GROUP_ADMIN_GROUP_NAME), null);
- if ( groupAdminGroupName != null && !
DEFAULT_GROUP_ADMIN_GROUP_NAME.equals(userAdminGroupName)) {
+ String deprecatedGroupAdminGroupName =
OsgiUtil.toString(properties.get(PAR_GROUP_ADMIN_GROUP_NAME), null);
+ if ( deprecatedGroupAdminGroupName != null && !
DEFAULT_GROUP_ADMIN_GROUP_NAME.equals(deprecatedUserAdminGroupName)) {
log.warn("Configuration setting for {} is deprecated and will not
have any effect", PAR_GROUP_ADMIN_GROUP_NAME);
}
}
diff --git
a/src/main/java/org/apache/sling/jackrabbit/usermanager/package-info.java
b/src/main/java/org/apache/sling/jackrabbit/usermanager/package-info.java
index 003bd56..c3526b4 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/package-info.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/package-info.java
@@ -17,7 +17,7 @@
* under the License.
*/
[email protected]("2.5.0")
[email protected]("2.6.0")
package org.apache.sling.jackrabbit.usermanager;
diff --git
a/src/test/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfoTest.java
b/src/test/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfoTest.java
index b53504a..fa08608 100644
---
a/src/test/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfoTest.java
+++
b/src/test/java/org/apache/sling/jackrabbit/usermanager/AuthorizablePrivilegesInfoTest.java
@@ -18,6 +18,8 @@ package org.apache.sling.jackrabbit.usermanager;
import static org.junit.Assert.*;
+import javax.jcr.Session;
+
import
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo.PropertyUpdateTypes;
import org.junit.Test;
@@ -26,6 +28,38 @@ import org.junit.Test;
*/
public class AuthorizablePrivilegesInfoTest {
+ /**
+ * An implementation to facilitate testing of default methods in the
interface
+ */
+ public static class TestDefaultMethodsAuthorizablePrivlegesInfo implements
AuthorizablePrivilegesInfo {
+
+ @Override
+ public boolean canAddUser(Session jcrSession) {
+ return false;
+ }
+
+ @Override
+ public boolean canAddGroup(Session jcrSession) {
+ return false;
+ }
+
+ @Override
+ public boolean canUpdateProperties(Session jcrSession, String
principalId) {
+ return false;
+ }
+
+ @Override
+ public boolean canRemove(Session jcrSession, String principalId) {
+ return false;
+ }
+
+ @Override
+ public boolean canUpdateGroupMembers(Session jcrSession, String
groupId) {
+ return false;
+ }
+
+ }
+
@SuppressWarnings("deprecation")
@Test
public void testConvertDeprecated() {
@@ -38,4 +72,45 @@ public class AuthorizablePrivilegesInfoTest {
assertEquals(PropertyUpdateTypes.REMOVE_PROPERTY,
PropertyUpdateTypes.convertDeprecated(PropertyUpdateTypes.REMOVE_PROPERTY));
}
+
+ /**
+ * Test method for {@link
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canUpdateProperties(javax.jcr.Session,
java.lang.String,
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo.PropertyUpdateTypes[])}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testCanUpdatePropertiesSessionStringPropertyUpdateTypesArray()
{
+ AuthorizablePrivilegesInfo api = new
TestDefaultMethodsAuthorizablePrivlegesInfo();
+ Session jcrSession = null;
+ api.canUpdateProperties(jcrSession, "testuser1",
PropertyUpdateTypes.ALTER_PROPERTY);
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canDisable(javax.jcr.Session,
java.lang.String)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testCanDisable() {
+ AuthorizablePrivilegesInfo api = new
TestDefaultMethodsAuthorizablePrivlegesInfo();
+ Session jcrSession = null;
+ api.canDisable(jcrSession, "testuser1");
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canChangePassword(javax.jcr.Session,
java.lang.String)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testCanChangePassword() {
+ AuthorizablePrivilegesInfo api = new
TestDefaultMethodsAuthorizablePrivlegesInfo();
+ Session jcrSession = null;
+ api.canChangePassword(jcrSession, "testuser1");
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canChangePasswordWithoutOldPassword(javax.jcr.Session,
java.lang.String)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testCanChangePasswordWithoutOldPassword() {
+ AuthorizablePrivilegesInfo api = new
TestDefaultMethodsAuthorizablePrivlegesInfo();
+ Session jcrSession = null;
+ api.canChangePasswordWithoutOldPassword(jcrSession, "testuser1");
+ }
+
}
diff --git
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/AuthorizablePrivilegesInfoIT.java
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/AuthorizablePrivilegesInfoIT.java
index f239503..29c2437 100644
---
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/AuthorizablePrivilegesInfoIT.java
+++
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/AuthorizablePrivilegesInfoIT.java
@@ -39,6 +39,7 @@ import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.security.Privilege;
+import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
@@ -1080,4 +1081,47 @@ public class AuthorizablePrivilegesInfoIT extends
UserManagerTestSupport {
privilegesInfo.canChangePassword(adminSession,
"sling-jcr-usermanager"));
}
+ /**
+ * Tests for SLING-12202
+ */
+ @Test
+ public void canChangePasswordWithoutOldPasswordForSelf() throws
RepositoryException {
+
assertFalse(privilegesInfo.canChangePasswordWithoutOldPassword(adminSession,
"admin"));
+ }
+ @Test
+ public void canChangePasswordWithoutOldPasswordForAdminUser() throws
RepositoryException {
+
assertTrue(privilegesInfo.canChangePasswordWithoutOldPassword(adminSession,
user1.getID()));
+ }
+ @Test
+ public void canChangePasswordWithoutOldPasswordForAnonymousUser() throws
RepositoryException {
+
assertFalse(privilegesInfo.canChangePasswordWithoutOldPassword(adminSession,
"anonymous"));
+ }
+ @Test
+ public void canChangePasswordWithoutOldPasswordForServiceUser() throws
RepositoryException {
+ User systemuser1 =
((JackrabbitSession)adminSession).getUserManager().createSystemUser("systemuser1",
null);
+
assertFalse(privilegesInfo.canChangePasswordWithoutOldPassword(adminSession,
systemuser1.getID()));
+ }
+ @Test
+ public void canChangePasswordWithoutOldPasswordForUserAdminGroupMember()
throws RepositoryException {
+ User testuser2 =
((JackrabbitSession)adminSession).getUserManager().createUser("testuser2",
"testPwd");
+ Group userAdmin = createGroup.createGroup(adminSession, "UserAdmin",
new HashMap<>(), new ArrayList<>());
+ // grant user1 rights to user2 profile
+ Map<String, String> privileges = new HashMap<>();
+ privileges.put(String.format("privilege@%s", Privilege.JCR_READ),
"granted");
+ modifyAce.modifyAce(adminSession, userAdmin.getPath(), user1.getID(),
+ privileges,
+ "first");
+ modifyAce.modifyAce(adminSession, testuser2.getPath(), user1.getID(),
+ privileges,
+ "first");
+ adminSession.save();
+ user1Session.refresh(true);
+
assertFalse(privilegesInfo.canChangePasswordWithoutOldPassword(user1Session,
testuser2.getID()));
+
+ userAdmin.addMember(user1);
+ adminSession.save();
+ user1Session.refresh(true);
+
assertTrue(privilegesInfo.canChangePasswordWithoutOldPassword(user1Session,
testuser2.getID()));
+ }
+
}