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 36a644a  SLING-9810 Make it possible to change the 
AuthorizableResourceProvider root path via configuration
36a644a is described below

commit 36a644a86180a7e863d0f199285d92488bc46620
Author: Eric Norman <[email protected]>
AuthorDate: Sun Oct 11 11:14:28 2020 -0700

    SLING-9810 Make it possible to change the AuthorizableResourceProvider
    root path via configuration
---
 .../impl/post/AbstractAuthorizablePostServlet.java |  15 +-
 .../impl/post/AbstractGroupPostServlet.java        |   3 +-
 .../impl/post/ChangeUserPasswordServlet.java       |  19 +-
 .../usermanager/impl/post/CreateGroupServlet.java  |  21 +-
 .../usermanager/impl/post/CreateUserServlet.java   |  19 +-
 .../impl/post/DeleteAuthorizableServlet.java       |   9 +-
 .../usermanager/impl/post/UpdateGroupServlet.java  |  14 +-
 .../usermanager/impl/post/UpdateUserServlet.java   |  10 +
 .../impl/resource/AuthorizableResource.java        |   9 +-
 .../resource/AuthorizableResourceProvider.java     | 134 +++++++++--
 .../impl/resource/AuthorizableValueMap.java        |  12 +-
 .../resource/SystemUserManagerPaths.java           |  50 ++++
 .../usermanager/resource/package-info.java         |  23 ++
 .../it/AuthorizablePrivilegesInfoIT.java           |  19 +-
 .../usermanager/it/post/ChangeUserPasswordIT.java  |  20 +-
 .../resource/AuthorizableResourceProviderIT.java   | 251 +++++++++++++++++++++
 16 files changed, 561 insertions(+), 67 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractAuthorizablePostServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractAuthorizablePostServlet.java
index 7017e2f..7328c85 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractAuthorizablePostServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractAuthorizablePostServlet.java
@@ -36,7 +36,7 @@ import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.sling.api.SlingIOException;
 import org.apache.sling.api.request.RequestParameter;
 import org.apache.sling.commons.osgi.OsgiUtil;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 import org.apache.sling.servlets.post.impl.helper.DateParser;
@@ -57,6 +57,12 @@ public abstract class AbstractAuthorizablePostServlet extends
 
     private DateParser dateParser;
 
+    protected SystemUserManagerPaths systemUserManagerPaths;
+
+    protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+       this.systemUserManagerPaths = sump;
+    }
+
     // ---------- SCR Integration 
----------------------------------------------
 
     protected void activate(Map<String, Object> props) {
@@ -333,10 +339,10 @@ public abstract class AbstractAuthorizablePostServlet 
extends
 
         String parentPath;
         if (parent.isGroup()) {
-            parentPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+            parentPath = systemUserManagerPaths.getGroupPrefix()
                 + parent.getID();
         } else {
-            parentPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX
+            parentPath = systemUserManagerPaths.getUserPrefix()
                 + parent.getID();
         }
 
@@ -369,10 +375,10 @@ public abstract class AbstractAuthorizablePostServlet 
extends
                     + relativePath));
             }
         } else if (values.length == 1) {
-            boolean removedProp = removePropertyIfExists(parent, relativePath);
             // if the provided value is the empty string, we don't have to do
             // anything.
             if (values[0].length() == 0) {
+                boolean removedProp = removePropertyIfExists(parent, 
relativePath);
                 if (removedProp) {
                     changes.add(Modification.onDeleted(parentPath + "/"
                         + relativePath));
@@ -420,7 +426,6 @@ public abstract class AbstractAuthorizablePostServlet 
extends
                     + relativePath));
             }
         } else {
-            removePropertyIfExists(parent, relativePath);
             if (type == PropertyType.DATE) {
                 // try conversion
                 ValueFactory valFac = session.getValueFactory();
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractGroupPostServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractGroupPostServlet.java
index b12d8d5..78087f0 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractGroupPostServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractGroupPostServlet.java
@@ -27,7 +27,6 @@ import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
@@ -57,7 +56,7 @@ public abstract class AbstractGroupPostServlet extends
             throws RepositoryException {
         if (authorizable.isGroup()) {
             Group group = ((Group) authorizable);
-            String groupPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+            String groupPath = systemUserManagerPaths.getGroupPrefix()
                 + group.getID();
 
             ResourceResolver resolver = baseResource.getResourceResolver();
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/ChangeUserPasswordServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/ChangeUserPasswordServlet.java
index 8a20afa..f723a66 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/ChangeUserPasswordServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/ChangeUserPasswordServlet.java
@@ -35,7 +35,7 @@ import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jackrabbit.usermanager.ChangeUserPassword;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
@@ -113,9 +113,9 @@ public class ChangeUserPasswordServlet extends 
AbstractAuthorizablePostServlet i
                 description = "Specifies the name of the group whose members 
are allowed to reset the password of another user.")
         String user_admin_group_name() default DEFAULT_USER_ADMIN_GROUP_NAME;
 
-        @AttributeDefinition(name = "Always Allow Self Password Change",
-                description = "Specifies whether a user is allowed to change 
their own password even if they haven't been granted the rep:userManagement 
privilege.")
-        boolean alwaysAllowSelfChangePassword() default false;
+               @AttributeDefinition(name = "Allow Self Password Change",
+                description = "Specifies whether a user is allowed to change 
their own password.")
+        boolean allowSelfChangePassword() default true;
     }
 
     private static final long serialVersionUID = 1923614318474654502L;
@@ -172,6 +172,15 @@ public class ChangeUserPasswordServlet extends 
AbstractAuthorizablePostServlet i
         super.deactivate();
     }
 
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractAuthorizablePostServlet#bindSystemUserManagerPaths(org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths)
+        */
+    @Reference
+       @Override
+       protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+               super.bindSystemUserManagerPaths(sump);
+       }
+    
     /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
@@ -317,7 +326,7 @@ public class ChangeUserPasswordServlet extends 
AbstractAuthorizablePostServlet i
             user.changePassword(newPassword);
         }
 
-        final String passwordPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + user.getID() + 
"/rep:password";
+        final String passwordPath = systemUserManagerPaths.getUserPrefix() + 
user.getID() + "/rep:password";
 
         changes.add(Modification.onModified(passwordPath));
 
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateGroupServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateGroupServlet.java
index 6c540cf..a95e1b3 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateGroupServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateGroupServlet.java
@@ -35,7 +35,7 @@ import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.jackrabbit.usermanager.CreateGroup;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.PostResponse;
@@ -118,7 +118,16 @@ public class CreateGroupServlet extends 
AbstractGroupPostServlet implements Crea
         super.deactivate();
     }
 
-    /**
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractAuthorizablePostServlet#bindSystemUserManagerPaths(org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths)
+        */
+    @Reference
+       @Override
+       protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+               super.bindSystemUserManagerPaths(sump);
+       }
+
+       /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
         * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractPostServlet#bindPostResponseCreator(org.apache.sling.servlets.post.PostResponseCreator,
 java.util.Map)
@@ -158,12 +167,12 @@ public class CreateGroupServlet extends 
AbstractGroupPostServlet implements Crea
                 request.getRequestParameterMap(), 
                 changes);
 
-        String groupPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+        String groupPath = systemUserManagerPaths.getGroupPrefix()
             + group.getID();
         response.setPath(groupPath);
         response.setLocation(externalizePath(request, groupPath));
         response.setParentLocation(externalizePath(request,
-            AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH));
+                       systemUserManagerPaths.getGroupsPath()));
         
     }
     
@@ -198,7 +207,7 @@ public class CreateGroupServlet extends 
AbstractGroupPostServlet implements Crea
                 }
             });
 
-            String groupPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+            String groupPath = systemUserManagerPaths.getGroupPrefix()
                 + group.getID();
             
             Collection<RequestProperty> reqProperties = 
collectContent(properties);
@@ -214,7 +223,7 @@ public class CreateGroupServlet extends 
AbstractGroupPostServlet implements Crea
                final Map<String, Object> authInfo = new HashMap<String, 
Object>();
                
authInfo.put(org.apache.sling.jcr.resource.api.JcrResourceConstants.AUTHENTICATION_INFO_SESSION,
 jcrSession);
                 resourceResolver = 
resourceResolverFactory.getResourceResolver(authInfo);
-                Resource baseResource = 
resourceResolver.getResource(AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH);
+                Resource baseResource = 
resourceResolver.getResource(systemUserManagerPaths.getGroupsPath());
                 updateGroupMembership(baseResource, properties, group, 
changes);
             } catch (LoginException e) {
                                throw new RepositoryException(e);
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
index 34285c1..63b316d 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
@@ -35,7 +35,7 @@ import 
org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jackrabbit.usermanager.CreateUser;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
@@ -95,7 +95,6 @@ import org.slf4j.LoggerFactory;
  * curl -F:name=ieb -Fpwd=password -FpwdConfirm=password -Fproperty1=value1 
http://localhost:8080/system/userManager/user.create.html
  * </code>
  */
-@Designate(ocd = CreateUserServlet.Config.class)
 @Component(service = {Servlet.class, CreateUser.class},
     property = {
                   "sling.servlet.resourceTypes=sling/users",
@@ -109,6 +108,7 @@ import org.slf4j.LoggerFactory;
                   AbstractAuthorizablePostServlet.PROP_DATE_FORMAT + 
"=dd.MM.yyyy",
                   ChangeUserPasswordServlet.PAR_USER_ADMIN_GROUP_NAME + "=" + 
ChangeUserPasswordServlet.DEFAULT_USER_ADMIN_GROUP_NAME
 })
+@Designate(ocd = CreateUserServlet.Config.class)
 public class CreateUserServlet extends AbstractAuthorizablePostServlet 
implements CreateUser {
     private static final long serialVersionUID = 6871481922737658675L;
 
@@ -185,6 +185,15 @@ public class CreateUserServlet extends 
AbstractAuthorizablePostServlet implement
         super.deactivate();
     }
 
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractAuthorizablePostServlet#bindSystemUserManagerPaths(org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths)
+        */
+    @Reference
+       @Override
+       protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+               super.bindSystemUserManagerPaths(sump);
+       }
+
     /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
@@ -237,7 +246,7 @@ public class CreateUserServlet extends 
AbstractAuthorizablePostServlet implement
                 }
             }
         } else {
-            userPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX
+            userPath = systemUserManagerPaths.getUserPrefix()
                     + user.getID();
         }
 
@@ -246,7 +255,7 @@ public class CreateUserServlet extends 
AbstractAuthorizablePostServlet implement
             response.setLocation(externalizePath(request, userPath));
         }
         response.setParentLocation(externalizePath(request,
-            AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PATH));
+                       systemUserManagerPaths.getUsersPath()));
     }
 
     /* (non-Javadoc)
@@ -330,7 +339,7 @@ public class CreateUserServlet extends 
AbstractAuthorizablePostServlet implement
                         + name);
             } else {
                 user = userManager.createUser(name, password);
-                String userPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX
+                String userPath = systemUserManagerPaths.getUserPrefix()
                     + user.getID();
 
                 Collection<RequestProperty> reqProperties = 
collectContent(properties);
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/DeleteAuthorizableServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/DeleteAuthorizableServlet.java
index 75801af..f989875 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/DeleteAuthorizableServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/DeleteAuthorizableServlet.java
@@ -37,7 +37,7 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.jackrabbit.usermanager.DeleteAuthorizables;
 import org.apache.sling.jackrabbit.usermanager.DeleteGroup;
 import org.apache.sling.jackrabbit.usermanager.DeleteUser;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.PostResponse;
@@ -94,6 +94,9 @@ public class DeleteAuthorizableServlet extends 
AbstractPostServlet
         implements DeleteUser, DeleteGroup, DeleteAuthorizables {
     private static final long serialVersionUID = 5874621724096106496L;
 
+    @Reference 
+    private SystemUserManagerPaths systemUserManagerPaths;
+
     /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
@@ -168,7 +171,7 @@ public class DeleteAuthorizableServlet extends 
AbstractPostServlet
                 "User to delete could not be determined");
         }
         
-        String userPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX
+        String userPath = systemUserManagerPaths.getUserPrefix()
                             + user.getID();
         user.remove();
         changes.add(Modification.onDeleted(userPath));
@@ -191,7 +194,7 @@ public class DeleteAuthorizableServlet extends 
AbstractPostServlet
                 "Group to delete could not be determined");
         }
         
-        String groupPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+        String groupPath = systemUserManagerPaths.getGroupPrefix()
                                 + group.getID();
         group.remove();
         changes.add(Modification.onDeleted(groupPath));
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateGroupServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateGroupServlet.java
index 8f03748..c5c90f0 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateGroupServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateGroupServlet.java
@@ -35,7 +35,7 @@ import 
org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.jackrabbit.usermanager.UpdateGroup;
-import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.PostResponse;
@@ -119,6 +119,15 @@ public class UpdateGroupServlet extends 
AbstractGroupPostServlet
         super.deactivate();
     }
 
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractAuthorizablePostServlet#bindSystemUserManagerPaths(org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths)
+        */
+    @Reference
+       @Override
+       protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+               super.bindSystemUserManagerPaths(sump);
+       }
+
     /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
@@ -178,7 +187,8 @@ public class UpdateGroupServlet extends 
AbstractGroupPostServlet
                 "Group to update could not be determined");
         }
         
-        String groupPath = 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
+        
+        String groupPath = systemUserManagerPaths.getGroupPrefix()
             + group.getID();
 
         Collection<RequestProperty> reqProperties = collectContent(properties);
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateUserServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateUserServlet.java
index 52c4dbd..ab6e2ea 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateUserServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/UpdateUserServlet.java
@@ -31,6 +31,7 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.jackrabbit.usermanager.UpdateUser;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.PostResponse;
@@ -111,6 +112,15 @@ public class UpdateUserServlet extends 
AbstractAuthorizablePostServlet
         super.deactivate();
     }
 
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.post.AbstractAuthorizablePostServlet#bindSystemUserManagerPaths(org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths)
+        */
+    @Reference
+       @Override
+       protected void bindSystemUserManagerPaths(SystemUserManagerPaths sump) {
+               super.bindSystemUserManagerPaths(sump);
+       }
+    
     /**
      * Overridden since the @Reference annotation is not inherited from the 
super method
      *  
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResource.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResource.java
index 8f1c5f2..d914cd3 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResource.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResource.java
@@ -30,6 +30,7 @@ import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 
 /**
  * Resource implementation for Authorizable
@@ -50,13 +51,17 @@ public class AuthorizableResource extends AbstractResource {
 
     private final ResourceMetadata metadata;
 
+       private final SystemUserManagerPaths systemUserManagerPaths;
+
     public AuthorizableResource(Authorizable authorizable,
-            ResourceResolver resourceResolver, String path) {
+            ResourceResolver resourceResolver, String path,
+            SystemUserManagerPaths systemUserManagerPaths) {
         super();
 
         this.resourceResolver = resourceResolver;
         this.authorizable = authorizable;
         this.path = path;
+        this.systemUserManagerPaths = systemUserManagerPaths;
         if (authorizable.isGroup()) {
             this.resourceType = "sling/group";
         } else {
@@ -114,7 +119,7 @@ public class AuthorizableResource extends AbstractResource {
     @SuppressWarnings("unchecked")
     public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
         if (type == Map.class || type == ValueMap.class) {
-            return (AdapterType) new AuthorizableValueMap(authorizable); // 
unchecked
+            return (AdapterType) new AuthorizableValueMap(authorizable, 
systemUserManagerPaths); // unchecked
                                                                          // 
cast
         } else if (type == Authorizable.class
             || (type == User.class && !authorizable.isGroup())
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResourceProvider.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResourceProvider.java
index ce42ed1..fb75210 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResourceProvider.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableResourceProvider.java
@@ -20,6 +20,7 @@ import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -32,67 +33,158 @@ import org.apache.sling.api.SlingException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.commons.osgi.OsgiUtil;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.spi.resource.provider.ResolveContext;
 import org.apache.sling.spi.resource.provider.ResourceContext;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Resource Provider implementation for jackrabbit UserManager resources.
  */
-@Component(service = ResourceProvider.class,
+@Component(service = { ResourceProvider.class, SystemUserManagerPaths.class },
     property={
                "service.description=Resource provider implementation for 
UserManager resources",
                "service.vendor=The Apache Software Foundation",
-               ResourceProvider.PROPERTY_ROOT + "=" + 
AuthorizableResourceProvider.SYSTEM_USER_MANAGER_PATH
+               ResourceProvider.PROPERTY_ROOT + "=" + 
AuthorizableResourceProvider.DEFAULT_SYSTEM_USER_MANAGER_PATH
     })
-public class AuthorizableResourceProvider extends ResourceProvider<Object> {
+@Designate(ocd=AuthorizableResourceProvider.Config.class)
+public class AuthorizableResourceProvider extends ResourceProvider<Object> 
implements SystemUserManagerPaths {
+       
+       @ObjectClassDefinition(name ="Apache Sling UserManager Resource 
Provider")
+    public @interface Config {
+
+               @AttributeDefinition(name = "Provider Root",
+                description = "Specifies the root path for the UserManager 
resources.")
+        String provider_root() default DEFAULT_SYSTEM_USER_MANAGER_PATH;
+    }
 
     /**
      * default log
      */
     private final Logger log = LoggerFactory.getLogger(getClass());
 
+       private String systemUserManagerPath;
+       private String systemUserManagerUserPath;
+       private String systemUserManagerUserPrefix;
+       private String systemUserManagerGroupPath;
+       private String systemUserManagerGroupPrefix;
+
+    public static final String DEFAULT_SYSTEM_USER_MANAGER_PATH = 
"/system/userManager";
+
+    /**
+     * @deprecated no longer used.  Use {@link SystemUserManagerPaths} service 
instead.
+     */
+    @Deprecated
     public static final String SYSTEM_USER_MANAGER_PATH = 
"/system/userManager";
 
+    /**
+     * @deprecated no longer used.  Use {@link SystemUserManagerPaths} service 
instead.
+     */
+    @Deprecated
     public static final String SYSTEM_USER_MANAGER_USER_PATH = 
SYSTEM_USER_MANAGER_PATH
         + "/user";
 
+    /**
+     * @deprecated no longer used.  Use {@link SystemUserManagerPaths} service 
instead.
+     */
+    @Deprecated
     public static final String SYSTEM_USER_MANAGER_GROUP_PATH = 
SYSTEM_USER_MANAGER_PATH
         + "/group";
 
+    /**
+     * @deprecated no longer used.  Use {@link SystemUserManagerPaths} service 
instead.
+     */
+    @Deprecated
     public static final String SYSTEM_USER_MANAGER_USER_PREFIX = 
SYSTEM_USER_MANAGER_USER_PATH
         + "/";
 
+    /**
+     * @deprecated no longer used.  Use {@link SystemUserManagerPaths} service 
instead.
+     */
+    @Deprecated
     public static final String SYSTEM_USER_MANAGER_GROUP_PREFIX = 
SYSTEM_USER_MANAGER_GROUP_PATH
         + "/";
 
+    @Activate
+    protected void activate(final Map<String, Object> props) {
+       systemUserManagerPath = 
OsgiUtil.toString(props.get(ResourceProvider.PROPERTY_ROOT), 
DEFAULT_SYSTEM_USER_MANAGER_PATH);
+       systemUserManagerUserPath = String.format("%s/user", 
systemUserManagerPath);
+       systemUserManagerUserPrefix = String.format("%s/", 
systemUserManagerUserPath);
+       systemUserManagerGroupPath = String.format("%s/group", 
systemUserManagerPath);
+       systemUserManagerGroupPrefix = String.format("%s/", 
systemUserManagerGroupPath);
+    }
     
-    @Override
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths#getPath()
+        */
+       @Override
+       public String getRootPath() {
+               return systemUserManagerPath;
+       }
+
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths#getUserPath()
+        */
+       @Override
+       public String getUsersPath() {
+               return systemUserManagerUserPath;
+       }
+
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths#getUserPrefix()
+        */
+       @Override
+       public String getUserPrefix() {
+               return systemUserManagerUserPrefix;
+       }
+
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths#getGroupPath()
+        */
+       @Override
+       public String getGroupsPath() {
+               return systemUserManagerGroupPath;
+       }
+
+       /* (non-Javadoc)
+        * @see 
org.apache.sling.jackrabbit.usermanager.impl.resource.SystemUserManagerPaths#getGroupPrefix()
+        */
+       @Override
+       public String getGroupPrefix() {
+               return systemUserManagerGroupPrefix;
+       }
+
+       @Override
        public Resource getResource(ResolveContext<Object> ctx, 
                    String path, 
                    ResourceContext resourceContext,
                        Resource parent) {
 
         // handle resources for the virtual container resources
-        if (path.equals(SYSTEM_USER_MANAGER_PATH)) {
+        if (path.equals(systemUserManagerPath)) {
             return new SyntheticResource(ctx.getResourceResolver(), path,
                 "sling/userManager");
-        } else if (path.equals(SYSTEM_USER_MANAGER_USER_PATH)) {
+        } else if (path.equals(systemUserManagerUserPath)) {
             return new SyntheticResource(ctx.getResourceResolver(), path, 
"sling/users");
-        } else if (path.equals(SYSTEM_USER_MANAGER_GROUP_PATH)) {
+        } else if (path.equals(systemUserManagerGroupPath)) {
             return new SyntheticResource(ctx.getResourceResolver(), path, 
"sling/groups");
         }
 
         // the principalId should be the first segment after the prefix
         String pid = null;
-        if (path.startsWith(SYSTEM_USER_MANAGER_USER_PREFIX)) {
-            pid = path.substring(SYSTEM_USER_MANAGER_USER_PREFIX.length());
-        } else if (path.startsWith(SYSTEM_USER_MANAGER_GROUP_PREFIX)) {
-            pid = path.substring(SYSTEM_USER_MANAGER_GROUP_PREFIX.length());
+        if (path.startsWith(systemUserManagerUserPrefix)) {
+            pid = path.substring(systemUserManagerUserPrefix.length());
+        } else if (path.startsWith(systemUserManagerGroupPrefix)) {
+            pid = path.substring(systemUserManagerGroupPrefix.length());
         }
 
         if (pid != null) {
@@ -110,7 +202,8 @@ public class AuthorizableResourceProvider extends 
ResourceProvider<Object> {
                             // found the Authorizable, so return the resource
                             // that wraps it.
                             return new AuthorizableResource(authorizable,
-                                       ctx.getResourceResolver(), path);
+                                       ctx.getResourceResolver(), path, 
+                                       AuthorizableResourceProvider.this);
                         }
                     }
                 }
@@ -129,21 +222,21 @@ public class AuthorizableResourceProvider extends 
ResourceProvider<Object> {
             ResourceResolver resourceResolver = parent.getResourceResolver();
 
             // handle children of /system/userManager
-            if (SYSTEM_USER_MANAGER_PATH.equals(path)) {
+            if (systemUserManagerPath.equals(path)) {
                 List<Resource> resources = new ArrayList<Resource>();
                 if (resourceResolver != null) {
                     resources.add(getResource(ctx,
-                        SYSTEM_USER_MANAGER_USER_PATH, null, null));
+                        systemUserManagerUserPath, null, null));
                     resources.add(getResource(ctx,
-                        SYSTEM_USER_MANAGER_GROUP_PATH, null, null));
+                        systemUserManagerGroupPath, null, null));
                 }
                 return resources.iterator();
             }
 
             int searchType = -1;
-            if (SYSTEM_USER_MANAGER_USER_PATH.equals(path)) {
+            if (systemUserManagerUserPath.equals(path)) {
                 searchType = PrincipalManager.SEARCH_TYPE_NOT_GROUP;
-            } else if (SYSTEM_USER_MANAGER_GROUP_PATH.equals(path)) {
+            } else if (systemUserManagerGroupPath.equals(path)) {
                 searchType = PrincipalManager.SEARCH_TYPE_GROUP;
             }
             if (searchType != -1) {
@@ -193,14 +286,15 @@ public class AuthorizableResourceProvider extends 
ResourceProvider<Object> {
                             if (authorizable != null) {
                                 String path;
                                 if (authorizable.isGroup()) {
-                                    path = SYSTEM_USER_MANAGER_GROUP_PREFIX
+                                    path = systemUserManagerGroupPrefix
                                         + nextPrincipal.getName();
                                 } else {
-                                    path = SYSTEM_USER_MANAGER_USER_PREFIX
+                                    path = systemUserManagerUserPrefix
                                         + nextPrincipal.getName();
                                 }
                                 return new AuthorizableResource(authorizable,
-                                    resourceResolver, path);
+                                    resourceResolver, path,
+                                    AuthorizableResourceProvider.this);
                             }
                         }
                     }
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableValueMap.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableValueMap.java
index 5640754..5eef744 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableValueMap.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/resource/AuthorizableValueMap.java
@@ -39,6 +39,7 @@ import javax.jcr.ValueFormatException;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,10 +66,13 @@ public class AuthorizableValueMap implements ValueMap {
 
     private Authorizable authorizable;
 
-    public AuthorizableValueMap(Authorizable authorizable) {
+       private final SystemUserManagerPaths systemUserManagerPaths;
+
+    public AuthorizableValueMap(Authorizable authorizable, 
SystemUserManagerPaths systemUserManagerPaths) {
         this.authorizable = authorizable;
         this.cache = new LinkedHashMap<String, Object>();
         this.fullyRead = false;
+        this.systemUserManagerPaths = systemUserManagerPaths;
     }
 
     @SuppressWarnings("unchecked")
@@ -395,9 +399,9 @@ public class AuthorizableValueMap implements ValueMap {
                 it.hasNext();) {
             Authorizable auth = it.next();
             if (auth.isGroup()) {
-                
results.add(AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + 
auth.getID());
+                results.add(systemUserManagerPaths.getGroupPrefix() + 
auth.getID());
             } else {
-                
results.add(AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + 
auth.getID());
+                results.add(systemUserManagerPaths.getUserPrefix() + 
auth.getID());
             }
         }
         return results.toArray(new String[results.size()]);
@@ -408,7 +412,7 @@ public class AuthorizableValueMap implements ValueMap {
         for (Iterator<Group> it = includeAll ? authorizable.memberOf() : 
authorizable.declaredMemberOf();
                 it.hasNext();) {
             Group group = it.next();
-            
results.add(AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + 
group.getID());
+            results.add(systemUserManagerPaths.getGroupPrefix() + 
group.getID());
         }
         return results.toArray(new String[results.size()]);
     }
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/SystemUserManagerPaths.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/SystemUserManagerPaths.java
new file mode 100644
index 0000000..ce26e98
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/SystemUserManagerPaths.java
@@ -0,0 +1,50 @@
+/*
+ * 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.sling.jackrabbit.usermanager.resource;
+
+/**
+ * Helper for components that need to know the 
+ * UserManager resource paths
+ */
+public interface SystemUserManagerPaths {
+
+       /**
+        * The root path for usermanager resources
+        */
+       String getRootPath();
+
+       /**
+        * The root path for all user resources
+        */
+       String getUsersPath();
+
+       /**
+        * The path prefix (before the id) for users
+        */
+       String getUserPrefix();
+
+       /**
+        * The root path for all group resources
+        */
+       String getGroupsPath();
+
+       /**
+        * The path prefix (before the id) for groups
+        */
+       String getGroupPrefix();
+
+}
\ No newline at end of file
diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/package-info.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/package-info.java
new file mode 100644
index 0000000..9e00de3
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
[email protected]("1.0.0")
+package org.apache.sling.jackrabbit.usermanager.resource;
+
+
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 7dc8196..419c235 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
@@ -134,20 +134,29 @@ public class AuthorizablePrivilegesInfoIT extends 
UserManagerTestSupport {
                                Collections.emptyMap(), new 
ArrayList<Modification>());
                assertNotNull("Expected user1 to not be null", user1);
                
+               if (adminSession.hasPendingChanges()) {
+                       adminSession.save();
+               }
+               
                user1Session = repository.login(new 
SimpleCredentials(user1.getID(), "testPwd".toCharArray()));
                assertNotNull("Expected user1Session to not be null", 
user1Session);
     }
 
     @After
     public void teardown() {
-               if (user1 != null) {
-                       try {
-                               adminSession.refresh(false);
+       try {
+                       adminSession.refresh(false);
+                       if (user1 != null) {
                                deleteUser.deleteUser(adminSession, 
user1.getID(), new ArrayList<>());
-                       } catch (RepositoryException e) {
-                               logger.warn("Failed to delete user: " + 
e.getMessage(), e);                     
                        }
+
+                       if (adminSession.hasPendingChanges()) {
+                               adminSession.save();
+                       }
+               } catch (RepositoryException e) {
+                       logger.warn("Failed to delete user: " + e.getMessage(), 
e);
                }
+
        user1Session.logout();
         adminSession.logout();
     }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/ChangeUserPasswordIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/ChangeUserPasswordIT.java
index 2b749bd..007575f 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/ChangeUserPasswordIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/ChangeUserPasswordIT.java
@@ -140,14 +140,18 @@ public class ChangeUserPasswordIT extends 
UserManagerTestSupport {
 
     @After
     public void teardown() {
-        if (user1 != null) {
-            try {
-                adminSession.refresh(false);
-                deleteUser.deleteUser(adminSession, user1.getID(), new 
ArrayList<>());
-            } catch (RepositoryException e) {
-                logger.warn("Failed to delete user: " + e.getMessage(), e);
-            }
-        }
+       try {
+                       adminSession.refresh(false);
+                       if (user1 != null) {
+                               deleteUser.deleteUser(adminSession, 
user1.getID(), new ArrayList<>());
+                       }
+                       if (adminSession.hasPendingChanges()) {
+                               adminSession.save();
+                       }
+               } catch (RepositoryException e) {
+                       logger.warn("Failed to delete user: " + e.getMessage(), 
e);
+               }
+
         user1Session.logout();
         adminSession.logout();
     }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/resource/AuthorizableResourceProviderIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/resource/AuthorizableResourceProviderIT.java
new file mode 100644
index 0000000..8ef380d
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/resource/AuthorizableResourceProviderIT.java
@@ -0,0 +1,251 @@
+/*
+ * 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.sling.jcr.jackrabbit.usermanager.it.resource;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.options;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.inject.Inject;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.jackrabbit.usermanager.CreateGroup;
+import org.apache.sling.jackrabbit.usermanager.CreateUser;
+import org.apache.sling.jackrabbit.usermanager.DeleteGroup;
+import org.apache.sling.jackrabbit.usermanager.DeleteUser;
+import 
org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider;
+import org.apache.sling.jackrabbit.usermanager.resource.SystemUserManagerPaths;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.jackrabbit.usermanager.it.UserManagerTestSupport;
+import org.apache.sling.jcr.resource.api.JcrResourceConstants;
+import org.apache.sling.servlets.post.Modification;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Basic test of AuthorizableResourceProvider component
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class AuthorizableResourceProviderIT extends UserManagerTestSupport {
+       private static AtomicLong counter = new AtomicLong(0);
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Inject
+    protected BundleContext bundleContext;
+    
+    @Inject
+    protected SlingRepository repository;
+
+    @Inject
+    protected ResourceResolverFactory resourceResolverFactory;
+
+    @Inject
+    protected ConfigurationAdmin configAdmin;
+    
+       @Inject
+       private CreateUser createUser;
+
+       @Inject
+       private CreateGroup createGroup;
+
+       @Inject
+       private DeleteUser deleteUser;
+
+       @Inject
+       private DeleteGroup deleteGroup;
+
+       @Rule
+       public TestName testName = new TestName();
+    
+    protected Session adminSession;
+    protected User user1;
+    protected Group group1;
+
+    @Configuration
+    public Option[] configuration() {
+        return options(
+            baseConfiguration()
+        );
+    }
+
+    @Before
+    public void setup() throws Exception {
+        adminSession = repository.login(new SimpleCredentials("admin", 
"admin".toCharArray()));
+        assertNotNull("Expected adminSession to not be null", adminSession);
+
+               user1 = createUser.createUser(adminSession, 
createUniqueName("user"), "testPwd", "testPwd", 
+                               Collections.emptyMap(), new 
ArrayList<Modification>());
+               assertNotNull("Expected user1 to not be null", user1);
+
+               group1 = createGroup.createGroup(adminSession, 
createUniqueName("group"), 
+                               Collections.emptyMap(), new 
ArrayList<Modification>());
+               assertNotNull("Expected group1 to not be null", group1);
+               
+               if (adminSession.hasPendingChanges()) {
+                       adminSession.save();
+               }
+    }
+
+    @After
+    public void teardown() {
+       try {
+                       adminSession.refresh(false);
+                       if (user1 != null) {
+                               deleteUser.deleteUser(adminSession, 
user1.getID(), new ArrayList<>());
+                       }
+
+                       if (adminSession.hasPendingChanges()) {
+                               adminSession.save();
+                       }
+               } catch (RepositoryException e) {
+                       logger.warn("Failed to delete user: " + e.getMessage(), 
e);
+               }
+       try {
+                       adminSession.refresh(false);
+                       if (group1 != null) {
+                               deleteGroup.deleteGroup(adminSession, 
group1.getID(), new ArrayList<>());
+                       }
+
+                       if (adminSession.hasPendingChanges()) {
+                               adminSession.save();
+                       }
+               } catch (RepositoryException e) {
+                       logger.warn("Failed to delete group: " + 
e.getMessage(), e);
+               }
+
+               adminSession.logout();
+    }
+
+    protected String createUniqueName(String prefix) {
+               return String.format("%s_%s%d", prefix, 
testName.getMethodName(), counter.incrementAndGet());
+       }
+    
+    /**
+     * Test changing the usermanager provider.root value
+     */
+    @Test
+    public void changeProviderRoot() throws Exception {
+        // the userManager resource should be mounted under /system/userManager
+       checkResourceTypes("/system/userManager", "/people");
+       
+        org.osgi.service.cm.Configuration configuration = 
configAdmin.getConfiguration("org.apache.sling.jackrabbit.usermanager.impl.resource.AuthorizableResourceProvider",
 null);
+        Dictionary<String, Object> originalServiceProps = 
configuration.getProperties();
+        ServiceReference<SystemUserManagerPaths> serviceReference = null;
+        try {
+            // update the service configuration to ensure the option is enabled
+            Dictionary<String, Object> newServiceProps = 
replaceConfigProp(originalServiceProps, "provider.root", "/people");
+            configuration.update(newServiceProps);
+            new WaitForServiceUpdated(5000, 100, bundleContext, 
SystemUserManagerPaths.class, 
+                    "provider.root", "/people");
+            
+            serviceReference = 
bundleContext.getServiceReference(SystemUserManagerPaths.class);
+            assertEquals("/people", 
serviceReference.getProperty("provider.root"));
+
+            // now the userManager resource should be mounted under /people
+               checkResourceTypes("/people", "/system/userManager");
+        } finally {
+            if (serviceReference != null) {
+                // done with this.
+                bundleContext.ungetService(serviceReference);
+            }
+            
+            //put the original config back
+            configuration.update(originalServiceProps);
+            new WaitForServiceUpdated(5000, 100, bundleContext, 
SystemUserManagerPaths.class, "provider.root", 
+                    originalServiceProps == null ? 
AuthorizableResourceProvider.DEFAULT_SYSTEM_USER_MANAGER_PATH : 
originalServiceProps.get("provider.root"));
+        }
+    }
+
+       protected void checkResourceTypes(String expectedPrefix, String 
unexpectedPrefix) throws Exception {
+               try (ResourceResolver resourceResolver = 
resourceResolverFactory.getResourceResolver(Collections.singletonMap(JcrResourceConstants.AUTHENTICATION_INFO_SESSION,
 adminSession))) {
+               // --- expected resources paths ----
+               
+               Resource resource = resourceResolver.resolve(expectedPrefix);
+               assertTrue("Expected resource type of sling/userManager for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling/userManager"));
+
+               resource = resourceResolver.resolve(expectedPrefix + "/user");
+               assertTrue("Expected resource type of sling/users for: " + 
resource.getPath(), 
+                               resource.isResourceType("sling/users"));
+
+               resource = resourceResolver.resolve(expectedPrefix + "/group");
+               assertTrue("Expected resource type of sling/groups for: " + 
resource.getPath(), 
+                               resource.isResourceType("sling/groups"));
+
+               resource = resourceResolver.resolve(expectedPrefix + "/user/" + 
user1.getID());
+               assertTrue("Expected resource type of sling/user for: " + 
resource.getPath(), 
+                               resource.isResourceType("sling/user"));
+
+               resource = resourceResolver.resolve(expectedPrefix + "/group/" 
+ group1.getID());
+               assertTrue("Expected resource type of sling/group for: " + 
resource.getPath(), 
+                               resource.isResourceType("sling/group"));
+
+               // --- unexpected resources paths ----
+               
+               resource = resourceResolver.resolve(unexpectedPrefix);
+               assertTrue("Expected resource type of sling:nonexisting for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling:nonexisting"));
+
+               resource = resourceResolver.resolve(unexpectedPrefix + "/user");
+               assertTrue("Expected resource type of sling:nonexisting for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling:nonexisting"));
+
+               resource = resourceResolver.resolve(unexpectedPrefix + 
"/group");
+               assertTrue("Expected resource type of sling:nonexisting for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling:nonexisting"));
+
+               resource = resourceResolver.resolve(unexpectedPrefix + "/user/" 
+ user1.getID());
+               assertTrue("Expected resource type of sling:nonexisting for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling:nonexisting"));
+
+               resource = resourceResolver.resolve(unexpectedPrefix + 
"/group/" + group1.getID());
+               assertTrue("Expected resource type of sling:nonexisting for: " 
+ resource.getPath(), 
+                               resource.isResourceType("sling:nonexisting"));
+               }
+       }
+
+}

Reply via email to