You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2012/08/10 15:46:06 UTC

svn commit: r1371699 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: namepath/ security/user/ spi/commit/ spi/security/user/ spi/security/user/action/ util/

Author: angela
Date: Fri Aug 10 13:46:06 2012
New Revision: 1371699

URL: http://svn.apache.org/viewvc?rev=1371699&view=rev
Log:
OAK-50 : Implement User Management (WIP)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/UniquePropertyValidator.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java?rev=1371699&r1=1371698&r2=1371699&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java Fri Aug 10 13:46:06 2012
@@ -16,8 +16,49 @@
  */
 package org.apache.jackrabbit.oak.namepath;
 
+import javax.annotation.Nonnull;
+
 /**
- * NamePathMapper...
+ * The {@code NamePathMapper} interface combines {@code NameMapper} and
+ * {@code PathMapper}.
  */
 public interface NamePathMapper extends NameMapper, PathMapper {
+
+    /**
+     * Default implementation that doesn't perform any conversions for cases
+     * where a mapper object only deals with oak internal names and paths.
+     */
+    public class Default implements NamePathMapper {
+
+        @Override
+        public String getOakName(String jcrName) {
+            return jcrName;
+        }
+
+        @Override
+        public boolean hasSessionLocalMappings() {
+            return false;
+        }
+
+        @Override
+        public String getJcrName(String oakName) {
+            return oakName;
+        }
+
+        @Override
+        public String getOakPath(String jcrPath) {
+            return jcrPath;
+        }
+
+        @Override
+        public String getOakPathKeepIndex(String jcrPath) {
+            return jcrPath;
+        }
+
+        @Nonnull
+        @Override
+        public String getJcrPath(String oakPath) {
+            return oakPath;
+        }
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java?rev=1371699&r1=1371698&r2=1371699&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java Fri Aug 10 13:46:06 2012
@@ -138,8 +138,8 @@ public class UserProviderImpl implements
 
         defaultDepth = config.getConfigValue(UserManagerConfig.PARAM_DEFAULT_DEPTH, DEFAULT_DEPTH);
 
-        groupPath = config.getConfigValue(UserManagerConfig.PARAM_GROUP_PATH, "/rep:security/rep:authorizables/rep:groups");
-        userPath = config.getConfigValue(UserManagerConfig.PARAM_USER_PATH, "/rep:security/rep:authorizables/rep:users");
+        groupPath = config.getConfigValue(UserManagerConfig.PARAM_GROUP_PATH, UserConstants.DEFAULT_GROUP_PATH);
+        userPath = config.getConfigValue(UserManagerConfig.PARAM_USER_PATH, UserConstants.DEFAULT_USER_PATH);
     }
 
     @Override
@@ -205,6 +205,7 @@ public class UserProviderImpl implements
         String[] segmts = Text.explode(folderPath, '/', false);
         for (String segment : segmts) {
             folder = folder.getOrAddChild(segment, UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+            // TODO: remove check once UserValidator is active
             if (!folder.hasPrimaryNodeTypeName(UserConstants.NT_REP_AUTHORIZABLE_FOLDER)) {
                 String msg = "Cannot create user/group: Intermediate folders must be of type rep:AuthorizableFolder.";
                 throw new ConstraintViolationException(msg);
@@ -214,6 +215,7 @@ public class UserProviderImpl implements
         // test for colliding folder child node.
         while (folder.hasChild(nodeName)) {
             NodeUtil colliding = folder.getChild(nodeName);
+            // TODO: remove check once UserValidator is active
             if (colliding.hasPrimaryNodeTypeName(UserConstants.NT_REP_AUTHORIZABLE_FOLDER)) {
                 log.debug("Existing folder node collides with user/group to be created. Expanding path by: " + colliding.getName());
                 folder = colliding;
@@ -225,6 +227,7 @@ public class UserProviderImpl implements
             }
         }
 
+        // TODO: remove check once UserValidator is active
         if (!Text.isDescendantOrEqual(authRoot, folder.getTree().getPath())) {
             throw new ConstraintViolationException("Attempt to create user/group outside of configured scope " + authRoot);
         }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java?rev=1371699&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java Fri Aug 10 13:46:06 2012
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.user;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.commit.UniquePropertyValidator;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserManagerConfig;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.apache.jackrabbit.util.Text;
+
+/**
+ * UserValidator... TODO
+ */
+class UserValidator extends UniquePropertyValidator {
+
+    private final UserValidatorProvider provider;
+
+    private final NodeUtil parentBefore;
+    private final NodeUtil parentAfter;
+
+    UserValidator(NodeUtil parentBefore, NodeUtil parentAfter, UserValidatorProvider provider) {
+        this.parentBefore = parentBefore;
+        this.parentAfter = parentAfter;
+
+        this.provider = provider;
+    }
+
+    @Nonnull
+    @Override
+    protected Set<String> getPropertyNames() {
+        // TODO: make configurable
+        return Collections.singleton(UserConstants.REP_PRINCIPAL_NAME);
+    }
+
+    //----------------------------------------------------------< Validator >---
+    @Override
+    public void propertyAdded(PropertyState after) throws CommitFailedException {
+        super.propertyAdded(after);
+    }
+
+    @Override
+    public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
+        super.propertyChanged(before, after);
+    }
+
+    @Override
+    public void propertyDeleted(PropertyState before) throws CommitFailedException {
+        // nothing to do
+    }
+
+    @Override
+    public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
+        NodeUtil node = parentAfter.getChild(name);
+        String authRoot = null;
+        if (node.hasPrimaryNodeTypeName(UserConstants.NT_REP_USER)) {
+            authRoot = provider.getConfig().getConfigValue(UserManagerConfig.PARAM_USER_PATH, UserConstants.DEFAULT_USER_PATH);
+        } else if (node.hasPrimaryNodeTypeName(UserConstants.NT_REP_GROUP)) {
+            authRoot = provider.getConfig().getConfigValue(UserManagerConfig.PARAM_GROUP_PATH, UserConstants.DEFAULT_GROUP_PATH);
+        }
+        if (authRoot != null) {
+            assertHierarchy(node, authRoot);
+        }
+        return new UserValidator(null, node, provider);
+    }
+
+    @Override
+    public Validator childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
+        // TODO: anything to do here?
+        return new UserValidator(parentBefore.getChild(name), parentAfter.getChild(name), provider);
+    }
+
+    @Override
+    public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
+        // nothing to do
+        return null;
+    }
+
+    //------------------------------------------------------------< private >---
+
+    /**
+     * Make sure user and group nodes are located underneath the configured path
+     * and that path consists of rep:authorizableFolder nodes.
+     *
+     * @param userNode
+     * @param pathConstraint
+     * @throws CommitFailedException
+     */
+    void assertHierarchy(NodeUtil userNode, String pathConstraint) throws CommitFailedException {
+        if (!Text.isDescendant(pathConstraint, userNode.getTree().getPath())) {
+            Exception e = new ConstraintViolationException("Attempt to create user/group outside of configured scope " + pathConstraint);
+            throw new CommitFailedException(e);
+        }
+
+        NodeUtil parent = userNode.getParent();
+        while (!parent.getTree().isRoot()) {
+            if (!parent.hasPrimaryNodeTypeName(UserConstants.NT_REP_AUTHORIZABLE_FOLDER)) {
+                String msg = "Cannot create user/group: Intermediate folders must be of type rep:AuthorizableFolder.";
+                Exception e = new ConstraintViolationException(msg);
+                throw new CommitFailedException(e);
+            }
+            parent = parent.getParent();
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java?rev=1371699&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java Fri Aug 10 13:46:06 2012
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.user;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.apache.jackrabbit.oak.core.ReadOnlyTree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.security.user.UserManagerConfig;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+
+/**
+ * Provides a validator for user and group management.
+ */
+public class UserValidatorProvider implements ValidatorProvider {
+
+    private final UserManagerConfig config = null; // TODO
+    private final ContentSession contentSession = null; // TODO
+
+    //--------------------------------------------------< ValidatorProvider >---
+    @Nonnull
+    @Override
+    public Validator getRootValidator(NodeState before, NodeState after) {
+        NamePathMapper mapper = new NamePathMapper.Default();
+        CoreValueFactory vf = contentSession.getCoreValueFactory();
+
+        NodeUtil rootBefore = new NodeUtil(vf, mapper, new ReadOnlyTree(before));
+        NodeUtil rootAfter = new NodeUtil(vf, mapper, new ReadOnlyTree(after));
+
+        return new UserValidator(rootBefore, rootAfter, this);
+    }
+
+    //-----------------------------------------------------------< internal >---
+
+    UserManagerConfig getConfig() {
+        return config;
+    }
+
+    CoreValueFactory getValueFactory() {
+        return contentSession.getCoreValueFactory();
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/UniquePropertyValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/UniquePropertyValidator.java?rev=1371699&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/UniquePropertyValidator.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/UniquePropertyValidator.java Fri Aug 10 13:46:06 2012
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.commit;
+
+import java.util.Set;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Base implementation of a validator that enforces uniqueness constraints
+ * within a given workspace: this includes unique property values for the
+ * properties listed in {@link #getPropertyNames()}.
+ */
+public abstract class UniquePropertyValidator implements Validator {
+
+    // TODO: verify if enforcing uniqueness constraints is really feasible in oak-core
+    // TODO: check if constraint validation needs to take property definition into account
+    //       e.g. a jcr:uuid property that isn't defined by mix:referenceable may
+    //       not necessarily be subject to the validation.
+
+    /**
+     * The property names for which the uniqueness constraint needs to
+     * be enforced.
+     *
+     * @return a set of property names.
+     */
+    @Nonnull
+    protected abstract Set<String> getPropertyNames();
+
+
+    protected void assertUniqueValue(PropertyState property) throws CommitFailedException {
+        // TODO:
+    }
+
+    //----------------------------------------------------------< Validator >---
+    @Override
+    public void propertyAdded(PropertyState after) throws CommitFailedException {
+        if (getPropertyNames().contains(after.getName())) {
+            assertUniqueValue(after);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
+        if (getPropertyNames().contains(after.getName())) {
+            assertUniqueValue(after);
+        }
+    }
+
+    @Override
+    public void propertyDeleted(PropertyState before) throws CommitFailedException {
+        // nothing to do
+    }
+
+    @Override
+    public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
+        return this;
+    }
+
+    @Override
+    public Validator childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
+        return this;
+    }
+
+    @Override
+    public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
+        return this;
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java?rev=1371699&r1=1371698&r2=1371699&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java Fri Aug 10 13:46:06 2012
@@ -32,4 +32,7 @@ public interface UserConstants {
     String REP_MEMBERS = "rep:members";
     String REP_IMPERSONATORS = "rep:impersonators";
 
+    String DEFAULT_USER_PATH = "/rep:security/rep:authorizables/rep:users";
+    String DEFAULT_GROUP_PATH = "/rep:security/rep:authorizables/rep:groups";
+
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java?rev=1371699&r1=1371698&r2=1371699&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java Fri Aug 10 13:46:06 2012
@@ -34,7 +34,7 @@ import javax.jcr.Session;
  * <li>{@link #onPasswordChange(org.apache.jackrabbit.api.security.user.User, String, javax.jcr.Session) User password modification}.</li>
  * </ul>
  *
- * @see org.apache.jackrabbit.oak.jcr.security.user.UserManagerConfig
+ * @see org.apache.jackrabbit.oak.spi.security.user.UserManagerConfig
  */
 public interface AuthorizableAction {
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java?rev=1371699&r1=1371698&r2=1371699&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java Fri Aug 10 13:46:06 2012
@@ -65,6 +65,10 @@ public class NodeUtil {
         return mapper.getJcrName(tree.getName());
     }
 
+    public NodeUtil getParent() {
+        return new NodeUtil(factory, mapper, tree.getParent());
+    }
+
     public boolean hasChild(String name) {
         return tree.getChild(name) != null;
     }
@@ -160,8 +164,7 @@ public class NodeUtil {
             throw new IllegalArgumentException("Invalid name:" + name);
         }
 
-        tree.setProperty(name, factory.createValue(
-                oakName, PropertyType.NAME));
+        tree.setProperty(name, factory.createValue(oakName, PropertyType.NAME));
     }
 
     public String[] getNames(String name, String... defaultValues) {
@@ -183,8 +186,7 @@ public class NodeUtil {
                 throw new IllegalArgumentException("Invalid name:" + name);
             }
 
-            cvs.add(factory.createValue(
-                    oakName, PropertyType.NAME));
+            cvs.add(factory.createValue(oakName, PropertyType.NAME));
         }
         tree.setProperty(name, cvs);
     }