You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:50:10 UTC

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 06/14: SLING-6747 support setting nested properties

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.2.6
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit a6edcb4e19999c89ea96590bc6aa8ec2f018d0e7
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Thu Mar 30 09:58:45 2017 +0000

    SLING-6747 support setting nested properties
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/jackrabbit-usermanager@1789483 13f79535-47bb-0310-9956-ffa450edef68
---
 .../impl/post/AbstractAuthorizablePostServlet.java | 107 ++++++++++++---------
 .../usermanager/impl/post/CreateGroupServlet.java  |   4 +-
 .../usermanager/impl/post/CreateUserServlet.java   |   4 +-
 .../usermanager/impl/post/UpdateGroupServlet.java  |   3 +-
 .../usermanager/impl/post/UpdateUserServlet.java   |   3 +-
 5 files changed, 67 insertions(+), 54 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 bbdc579..464b471 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
@@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -41,6 +42,8 @@ import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 import org.apache.sling.servlets.post.impl.helper.DateParser;
 import org.apache.sling.servlets.post.impl.helper.RequestProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Base class for all the POST servlets for the UserManager operations
@@ -51,6 +54,8 @@ public abstract class AbstractAuthorizablePostServlet extends
 
     public static final String PROP_DATE_FORMAT = "servlet.post.dateFormats";
 
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractAuthorizablePostServlet.class);
+
     private DateParser dateParser;
 
     // ---------- SCR Integration ----------------------------------------------
@@ -72,19 +77,18 @@ public abstract class AbstractAuthorizablePostServlet extends
 
     /**
      * Collects the properties that form the content to be written back to the
-     * repository. NOTE: In the returned map, the key is the property name not a
-     * path.
+     * repository.
      *
      * @throws RepositoryException if a repository error occurs
      * @throws ServletException if an internal error occurs
      */
-    protected Map<String, RequestProperty> collectContent(
+    protected Collection<RequestProperty> collectContent(
             Map<String, ?> properties,
             String authorizablePath) {
 
         boolean requireItemPrefix = requireItemPathPrefix(properties);
 
-        // walk the request parameters and collect the properties
+        // walk the request parameters and collect the properties (the key is the property path).
         Map<String, RequestProperty> reqProperties = new HashMap<String, RequestProperty>();
         for (Map.Entry<String, ?> e : properties.entrySet()) {
             final String paramName = e.getKey();
@@ -102,21 +106,20 @@ public abstract class AbstractAuthorizablePostServlet extends
                 continue;
             }
 
-            // ensure the paramName is an absolute property name
+            // ensure the paramName is an absolute property path (i.e. starts with "/", where root refers to the authorizable's root, https://issues.apache.org/jira/browse/SLING-1577)
             String propPath;
             if (paramName.startsWith("./")) {
-                propPath = paramName.substring(2);
+                propPath = paramName.substring(1);
             } else {
-                propPath = paramName;
+                propPath = "/" + paramName;
             }
-            if (propPath.indexOf('/') != -1) {
-                // only one path segment is valid here, so this paramter can't
-                // be used.
+
+            if (propPath.indexOf("..") != -1) {
+                // it is not supported to set properties potentially outside of the authorizable node
+                LOG.warn("Property path containing '..' is not supported, skipping parameter {}", SlingPostConstants.SUFFIX_COPY_FROM, paramName);
                 continue; // skip it.
             }
 
-            propPath = authorizablePath + "/" + propPath;
-
             // @TypeHint example
             // <input type="text" name="./age" />
             // <input type="hidden" name="./age@TypeHint" value="long" />
@@ -189,6 +192,7 @@ public abstract class AbstractAuthorizablePostServlet extends
             // property to Text.
             if (propPath.endsWith(SlingPostConstants.SUFFIX_MOVE_FROM)) {
                 // don't support @MoveFrom here
+                LOG.warn("Suffix {} not supported, skipping parameter {}", SlingPostConstants.SUFFIX_MOVE_FROM, paramName);
                 continue;
             }
 
@@ -199,6 +203,7 @@ public abstract class AbstractAuthorizablePostServlet extends
             // property to Text.
             if (propPath.endsWith(SlingPostConstants.SUFFIX_COPY_FROM)) {
                 // don't support @CopyFrom here
+                LOG.warn("Suffix {} not supported, skipping parameter {}", SlingPostConstants.SUFFIX_COPY_FROM, paramName);
                 continue;
             }
 
@@ -208,7 +213,7 @@ public abstract class AbstractAuthorizablePostServlet extends
             prop.setValues(convertToRequestParameterArray(e.getValue()));
         }
 
-        return reqProperties;
+        return reqProperties.values();
     }
 
     /**
@@ -216,7 +221,8 @@ public abstract class AbstractAuthorizablePostServlet extends
      * request property does not exist yet it is created and stored in the
      * <code>props</code>.
      *
-     * @param props The map of already seen request properties.
+     * @param props The map of already seen request properties 
+     *               (key is the property path).
      * @param paramPath The absolute path of the property including the
      *            <code>suffix</code> to be looked up.
      * @param suffix The (optional) suffix to remove from the
@@ -246,7 +252,7 @@ public abstract class AbstractAuthorizablePostServlet extends
      * @param authorizable The
      *            <code>org.apache.jackrabbit.api.security.user.Authorizable</code>
      *            that should have properties deleted.
-     * @param reqProperties The map of request properties to check for
+     * @param reqProperties The collection of request properties to check for
      *            properties to be removed.
      * @param changes The <code>List</code> to be updated with
      *            information on deleted properties.
@@ -254,10 +260,10 @@ public abstract class AbstractAuthorizablePostServlet extends
      *             removing properties.
      */
     protected void processDeletes(Authorizable authorizable,
-            Map<String, RequestProperty> reqProperties,
+            Collection<RequestProperty> reqProperties,
             List<Modification> changes) throws RepositoryException {
 
-        for (RequestProperty property : reqProperties.values()) {
+        for (RequestProperty property : reqProperties) {
             if (property.isDelete()) {
                 if (authorizable.hasProperty(property.getName())) {
                     authorizable.removeProperty(property.getName());
@@ -274,25 +280,28 @@ public abstract class AbstractAuthorizablePostServlet extends
      * @throws ServletException if an internal error occurs
      */
     protected void writeContent(Session session, Authorizable authorizable,
-            Map<String, RequestProperty> reqProperties,
+            Collection<RequestProperty> reqProperties,
             List<Modification> changes) throws RepositoryException {
 
-        for (RequestProperty prop : reqProperties.values()) {
+        for (RequestProperty prop : reqProperties) {
             if (prop.hasValues()) {
+                // remove artificial "/" prepended to the prop path
+                String relativePath = prop.getPath().substring(1);
+                
                 // skip jcr special properties
-                if (prop.getName().equals("jcr:primaryType")
-                    || prop.getName().equals("jcr:mixinTypes")) {
+                if (relativePath.equals("jcr:primaryType")
+                    || relativePath.equals("jcr:mixinTypes")) {
                     continue;
                 }
                 if (authorizable.isGroup()) {
-                    if (prop.getName().equals("groupId")) {
+                    if (relativePath.equals("groupId")) {
                         // skip these
                         continue;
                     }
                 } else {
-                    if (prop.getName().equals("userId")
-                        || prop.getName().equals("pwd")
-                        || prop.getName().equals("pwdConfirm")) {
+                    if (relativePath.equals("userId")
+                        || relativePath.equals("pwd")
+                        || relativePath.equals("pwdConfirm")) {
                         // skip these
                         continue;
                     }
@@ -337,31 +346,33 @@ public abstract class AbstractAuthorizablePostServlet extends
                 // ignore
             }
         }
+        // remove artificial "/" prepended to the prop path
+        String relativePath = prop.getPath().substring(1);
 
         String[] values = prop.getStringValues();
         if (values == null) {
             // remove property
-            boolean removedProp = removePropertyIfExists(parent, prop.getName());
+            boolean removedProp = removePropertyIfExists(parent, relativePath);
             if (removedProp) {
                 changes.add(Modification.onDeleted(parentPath + "/"
-                    + prop.getName()));
+                    + relativePath));
             }
         } else if (values.length == 0) {
             // do not create new prop here, but clear existing
-            if (parent.hasProperty(prop.getName())) {
+            if (parent.hasProperty(relativePath) {
                 Value val = session.getValueFactory().createValue("");
-                parent.setProperty(prop.getName(), val);
+                parent.setProperty(relativePath, val);
                 changes.add(Modification.onModified(parentPath + "/"
-                    + prop.getName()));
+                    + relativePath));
             }
         } else if (values.length == 1) {
-            boolean removedProp = removePropertyIfExists(parent, prop.getName());
+            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) {
                 if (removedProp) {
                     changes.add(Modification.onDeleted(parentPath + "/"
-                        + prop.getName()));
+                        + relativePath));
                 }
             } else {
                 // modify property
@@ -372,15 +383,15 @@ public abstract class AbstractAuthorizablePostServlet extends
                         if (prop.hasMultiValueTypeHint()) {
                             final Value[] array = new Value[1];
                             array[0] = session.getValueFactory().createValue(c);
-                            parent.setProperty(prop.getName(), array);
+                            parent.setProperty(relativePath, array);
                             changes.add(Modification.onModified(parentPath
-                                + "/" + prop.getName()));
+                                + "/" + relativePath));
                         } else {
                             Value cVal = session.getValueFactory().createValue(
                                 c);
                             parent.setProperty(prop.getName(), cVal);
                             changes.add(Modification.onModified(parentPath
-                                + "/" + prop.getName()));
+                                + "/" + relativePath));
                         }
                         return;
                     }
@@ -389,32 +400,32 @@ public abstract class AbstractAuthorizablePostServlet extends
                 if (type == PropertyType.UNDEFINED) {
                     Value val = session.getValueFactory().createValue(
                         values[0], PropertyType.STRING);
-                    parent.setProperty(prop.getName(), val);
+                    parent.setProperty(relativePath, val);
                 } else {
                     if (prop.hasMultiValueTypeHint()) {
                         final Value[] array = new Value[1];
                         array[0] = session.getValueFactory().createValue(
                             values[0], type);
-                        parent.setProperty(prop.getName(), array);
+                        parent.setProperty(relativePath, array);
                     } else {
                         Value val = session.getValueFactory().createValue(
                             values[0], type);
-                        parent.setProperty(prop.getName(), val);
+                        parent.setProperty(relativePath, val);
                     }
                 }
                 changes.add(Modification.onModified(parentPath + "/"
-                    + prop.getName()));
+                    + relativePath));
             }
         } else {
-            removePropertyIfExists(parent, prop.getName());
+            removePropertyIfExists(parent, relativePath);
             if (type == PropertyType.DATE) {
                 // try conversion
                 ValueFactory valFac = session.getValueFactory();
                 Value[] c = dateParser.parse(values, valFac);
                 if (c != null) {
-                    parent.setProperty(prop.getName(), c);
+                    parent.setProperty(relativePath, c);
                     changes.add(Modification.onModified(parentPath + "/"
-                        + prop.getName()));
+                        + relativePath));
                     return;
                 }
                 // fall back to default behaviour
@@ -431,9 +442,9 @@ public abstract class AbstractAuthorizablePostServlet extends
                         type);
                 }
             }
-            parent.setProperty(prop.getName(), vals);
+            parent.setProperty(relativePath, vals);
             changes.add(Modification.onModified(parentPath + "/"
-                + prop.getName()));
+                + relativePath));
         }
 
     }
@@ -444,15 +455,15 @@ public abstract class AbstractAuthorizablePostServlet extends
      *
      * @param authorizable the <code>org.apache.jackrabbit.api.security.user.Authorizable</code>
      *         that should have properties deleted.
-     * @param name the name of the property to remove
+     * @param path the path of the property to remove
      * @return path of the property that was removed or <code>null</code> if it
      *         was not removed
      * @throws RepositoryException if a repository error occurs.
      */
-    private boolean removePropertyIfExists(Authorizable authorizable, String name)
+    private boolean removePropertyIfExists(Authorizable authorizable, String path)
             throws RepositoryException {
-        if (authorizable.getProperty(name) != null) {
-            authorizable.removeProperty(name);
+        if (authorizable.getProperty(path) != null) {
+            authorizable.removeProperty(path);
             return true;
         }
         return false;
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 d0e26a7..c2c60dd 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
@@ -17,6 +17,7 @@
 package org.apache.sling.jackrabbit.usermanager.impl.post;
 
 import java.security.Principal;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -176,8 +177,7 @@ public class CreateGroupServlet extends AbstractGroupPostServlet implements Crea
             String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
                 + group.getID();
             
-            Map<String, RequestProperty> reqProperties = collectContent(
-                properties, groupPath);
+            Collection<RequestProperty> reqProperties = collectContent(properties, groupPath);
             changes.add(Modification.onCreated(groupPath));
 
             // write content from form
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 4992055..76fd94b 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
@@ -16,6 +16,7 @@
  */
 package org.apache.sling.jackrabbit.usermanager.impl.post;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -296,8 +297,7 @@ public class CreateUserServlet extends AbstractAuthorizablePostServlet implement
                 String userPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX
                     + user.getID();
 
-                Map<String, RequestProperty> reqProperties = collectContent(
-                    properties, userPath);
+                Collection<RequestProperty> reqProperties = collectContent(properties, userPath);
 
                 changes.add(Modification.onCreated(userPath));
 
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 0a8df63..b1f4e4c 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
@@ -16,6 +16,7 @@
  */
 package org.apache.sling.jackrabbit.usermanager.impl.post;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -156,7 +157,7 @@ public class UpdateGroupServlet extends AbstractGroupPostServlet
         String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
             + group.getID();
 
-        Map<String, RequestProperty> reqProperties = collectContent(properties, groupPath);
+        Collection<RequestProperty> reqProperties = collectContent(properties, groupPath);
         try {
             // cleanup any old content (@Delete parameters)
             processDeletes(group, reqProperties, changes);
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 aa11544..139ebab 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
@@ -16,6 +16,7 @@
  */
 package org.apache.sling.jackrabbit.usermanager.impl.post;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -146,7 +147,7 @@ public class UpdateUserServlet extends AbstractAuthorizablePostServlet
         String userPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX
             + user.getID();
 
-        Map<String, RequestProperty> reqProperties = collectContent(properties, userPath);
+        Collection<RequestProperty> reqProperties = collectContent(properties, userPath);
         try {
             // cleanup any old content (@Delete parameters)
             processDeletes(user, reqProperties, changes);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.