jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1199635 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/security/user/ main/java/org/apache/jackrabbit/core/security/user/action/ test/java/org/apache/jackrabbit/core/security/user/
Date Wed, 09 Nov 2011 07:45:56 GMT
Author: angela
Date: Wed Nov  9 07:45:55 2011
New Revision: 1199635

URL: http://svn.apache.org/viewvc?rev=1199635&view=rev
Log:
JCR-3140 : Add configurable hook for password validation

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AbstractAuthorizableAction.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AccessControlAction.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AuthorizableAction.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/ClearMembershipAction.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
Wed Nov  9 07:45:55 2011
@@ -126,6 +126,7 @@ public class UserImpl extends Authorizab
      * @see User#changePassword(String)
      */
     public void changePassword(String password) throws RepositoryException {
+        userManager.onPasswordChange(this, password);
         Value v = getSession().getValueFactory().createValue(buildPasswordValue(password));
         userManager.setProtectedProperty(getNode(), P_PASSWORD, v);
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
Wed Nov  9 07:45:55 2011
@@ -559,7 +559,7 @@ public class UserManagerImpl extends Pro
             setProperty(userNode, P_PASSWORD, getValue(UserImpl.buildPasswordValue(password)),
true);
 
             User user = createUser(userNode);
-            onCreate(user);
+            onCreate(user, password);
             if (isAutoSave()) {
                 session.save();
             }
@@ -1042,15 +1042,30 @@ public class UserManagerImpl extends Pro
     //--------------------------------------------------------------------------
     /**
      * Let the configured <code>AuthorizableAction</code>s perform additional
-     * tasks associated with the creation of the new authorizable before the
+     * tasks associated with the creation of the new user before the
      * corresponding new node is persisted.
      *
-     * @param authorizable The new authorizable.
+     * @param user The new user.
+     * @param pw The password.
      * @throws RepositoryException If an exception occurs.
      */
-    void onCreate(Authorizable authorizable) throws RepositoryException {
+    private void onCreate(User user, String pw) throws RepositoryException {
         for (AuthorizableAction action : authorizableActions) {
-            action.onCreate(authorizable, session);
+            action.onCreate(user, pw, session);
+        }
+    }
+
+    /**
+     * Let the configured <code>AuthorizableAction</code>s perform additional
+     * tasks associated with the creation of the new group before the
+     * corresponding new node is persisted.
+     *
+     * @param group The new group.
+     * @throws RepositoryException If an exception occurs.
+     */
+    private void onCreate(Group group) throws RepositoryException {
+        for (AuthorizableAction action : authorizableActions) {
+            action.onCreate(group, session);
         }
     }
 
@@ -1068,6 +1083,21 @@ public class UserManagerImpl extends Pro
         }
     }
 
+    /**
+     * Let the configured <code>AuthorizableAction</code>s perform additional
+     * tasks associated with password changing of a given user before the
+     * corresponding property is being changed.
+     *
+     * @param user The target user.
+     * @param password The new password.
+     * @throws RepositoryException If an exception occurs.
+     */
+    void onPasswordChange(User user, String password) throws RepositoryException {
+        for (AuthorizableAction action : authorizableActions) {
+            action.onPasswordChange(user, password, session);
+        }
+    }
+
     //----------------------------------------------------< SessionListener >---
     /**
      * @see SessionListener#loggingOut(org.apache.jackrabbit.core.SessionImpl)

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AbstractAuthorizableAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AbstractAuthorizableAction.java?rev=1199635&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AbstractAuthorizableAction.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AbstractAuthorizableAction.java
Wed Nov  9 07:45:55 2011
@@ -0,0 +1,72 @@
+/*
+ * 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.core.security.user.action;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.util.Text;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract implementation of the <code>AuthorizableAction</code> interface that
+ * doesn't perform any action. This is a convenience implementation allowing
+ * subclasses to only implement methods that need extra attention.
+ */
+public abstract class AbstractAuthorizableAction implements AuthorizableAction {
+
+    /**
+     * Doesn't perform any action.
+     *
+     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.Group, javax.jcr.Session)
+     */
+    public void onCreate(Group group, Session session) throws RepositoryException {
+        // nothing to do
+
+    }
+
+    /**
+     * Doesn't perform any action.
+     *
+     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.User, String,
javax.jcr.Session)
+     */
+    public void onCreate(User user, String password, Session session) throws RepositoryException
{
+        // nothing to do
+    }
+
+    /**
+     * Doesn't perform any action.
+     *
+     * @see AuthorizableAction#onRemove(org.apache.jackrabbit.api.security.user.Authorizable,
javax.jcr.Session)
+     */
+    public void onRemove(Authorizable authorizable, Session session) throws RepositoryException
{
+        // nothing to do
+    }
+
+    /**
+     * Doesn't perform any action.
+     *
+     * @see AuthorizableAction#onPasswordChange(org.apache.jackrabbit.api.security.user.User,
String, javax.jcr.Session)
+     */
+    public void onPasswordChange(User user, String newPassword, Session session) throws RepositoryException
{
+        // nothing to do
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AccessControlAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AccessControlAction.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AccessControlAction.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AccessControlAction.java
Wed Nov  9 07:45:55 2011
@@ -1,25 +1,25 @@
 /*
+ * 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
  *
- *  * 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.
+ *      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.core.security.user.action;
 
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.core.security.principal.UnknownPrincipal;
 import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
@@ -37,9 +37,65 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * <code>AccessControlAction</code>
+ * The <code>AccessControlAction</code> allows to setup permissions upon creation
+ * of a new authorizable; namely the privileges the new authorizable should be
+ * granted on it's own 'home directory' being represented by the new node
+ * associated with that new authorizable.
+ *
+ * <p>The following to configuration parameters are available with this implementation:
+ * <ul>
+ *    <li><strong>groupPrivilegeNames</strong>: the value is expected to
be a
+ *    comma separated list of privileges that will be granted to the new group on
+ *    the group node</li>
+ *    <li><strong>userPrivilegeNames</strong>: the value is expected to
be a
+ *    comma separated list of privileges that will be granted to the new user on
+ *    the user node.</li>
+ * </ul>
+ * </p>
+ * <p>Example configuration:
+ * <pre>
+ *    &lt;UserManager class="org.apache.jackrabbit.core.security.user.UserPerWorkspaceUserManager"&gt;
+ *       &lt;AuthorizableAction class="org.apache.jackrabbit.core.security.user.action.AccessControlAction"&gt;
+ *          &lt;param name="groupPrivilegeNames" value="jcr:read"/&gt;
+ *          &lt;param name="userPrivilegeNames" value="jcr:read, rep:write"/&gt;
+ *       &lt;/AuthorizableAction&gt;
+ *    &lt;/UserManager&gt;
+ * </pre>
+ * </p>
+ * <p>The example configuration will lead to the following content structure upon
+ * user or group creation::
+ *
+ * <pre>
+ *     UserManager umgr = ((JackrabbitSession) session).getUserManager();
+ *     User user = umgr.createUser("testUser", "t");
+ *
+ *     + t                           rep:AuthorizableFolder
+ *       + te                        rep:AuthorizableFolder
+ *         + testUser                rep:User, mix:AccessControllable
+ *           + rep:policy            rep:ACL
+ *             + allow               rep:GrantACE
+ *               - rep:principalName = "testUser"
+ *               - rep:privileges    = ["jcr:read","rep:write"]
+ *           - rep:password
+ *           - rep:principalName     = "testUser"
+ * </pre>
+ *
+ * <pre>
+ *     UserManager umgr = ((JackrabbitSession) session).getUserManager();
+ *     Group group = umgr.createGroup("testGroup");
+ *
+ *     + t                           rep:AuthorizableFolder
+ *       + te                        rep:AuthorizableFolder
+ *         + testGroup               rep:Group, mix:AccessControllable
+ *           + rep:policy            rep:ACL
+ *             + allow               rep:GrantACE
+ *               - rep:principalName = "testGroup"
+ *               - rep:privileges    = ["jcr:read"]
+ *           - rep:principalName     = "testGroup"
+ * </pre>
+ * </p>
  */
-public class AccessControlAction implements AuthorizableAction {
+public class AccessControlAction extends AbstractAuthorizableAction {
 
     /**
      * logger instance
@@ -56,9 +112,48 @@ public class AccessControlAction impleme
 
     //-------------------------------------------------< AuthorizableAction >---
     /**
-     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.Authorizable,
javax.jcr.Session)
+     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.Group, javax.jcr.Session)
+     */
+    @Override
+    public void onCreate(Group group, Session session) throws RepositoryException {
+        setAC(group, session);
+    }
+
+    /**
+     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.User, String,
javax.jcr.Session)
      */
-    public void onCreate(Authorizable authorizable, Session session) throws RepositoryException
{
+    @Override
+    public void onCreate(User user, String password, Session session) throws RepositoryException
{
+        setAC(user, session);
+    }
+
+    //--------------------------------------------------------< Bean Config >---
+
+    /**
+     * Sets the privileges a new group will be granted on the group's home directory.
+     *
+     * @param privilegeNames A comma separated list of privilege names.
+     */
+    public void setGroupPrivilegeNames(String privilegeNames) {
+        if (privilegeNames != null && privilegeNames.length() > 0) {
+            groupPrivilegeNames = split(privilegeNames);
+        }
+
+    }
+
+    /**
+     * Sets the privileges a new user will be granted on the user's home directory.
+     *
+     * @param privilegeNames  A comma separated list of privilege names.
+     */
+    public void setUserPrivilegeNames(String privilegeNames) {
+        if (privilegeNames != null && privilegeNames.length() > 0) {
+            userPrivilegeNames = split(privilegeNames);
+        }
+    }
+
+    //------------------------------------------------------------< private >---
+    private void setAC(Authorizable authorizable, Session session) throws RepositoryException
{
         Node aNode;
         String path = authorizable.getPath();
 
@@ -96,29 +191,6 @@ public class AccessControlAction impleme
     }
 
     /**
-     * @see AuthorizableAction#onRemove(org.apache.jackrabbit.api.security.user.Authorizable,
javax.jcr.Session)
-     */
-    public void onRemove(Authorizable authorizable, Session session) throws RepositoryException
{
-        // nothing to do.
-    }
-
-    //--------------------------------------------------------< Bean Config >---
-
-    public void setGroupPrivilegeNames(String privilegeNames) {
-        if (privilegeNames != null && privilegeNames.length() > 0) {
-            groupPrivilegeNames = split(privilegeNames);
-        }
-
-    }
-
-    public void setUserPrivilegeNames(String privilegeNames) {
-        if (privilegeNames != null && privilegeNames.length() > 0) {
-            userPrivilegeNames = split(privilegeNames);
-        }
-    }
-
-    //------------------------------------------------------------< private >---
-    /**
      * Retrieve privileges for the specified privilege names.
      *
      * @param privNames

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AuthorizableAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AuthorizableAction.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AuthorizableAction.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/AuthorizableAction.java
Wed Nov  9 07:45:55 2011
@@ -1,24 +1,24 @@
 /*
+ * 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
  *
- *  * 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.
+ *      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.core.security.user.action;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -29,16 +29,29 @@ import javax.jcr.Session;
 public interface AuthorizableAction {
 
     /**
-     * Allows to add application specific modifications associated with the
-     * creation of a new authorizable. Note, that this method is called
+     * Allows to add application specific modifications or validation associated
+     * with the creation of a new group. Note, that this method is called
      * <strong>before</strong> any <code>Session.save</code> call.
      *
-     * @param authorizable The new authorizable that has not yet been persisted;
+     * @param group The new group that has not yet been persisted;
      * e.g. the associated node is still 'NEW'.
      * @param session The editing session associated with the user manager.
      * @throws RepositoryException If an error occurs.
      */
-    void onCreate(Authorizable authorizable, Session session) throws RepositoryException;
+    void onCreate(Group group, Session session) throws RepositoryException;
+
+    /**
+     * Allows to add application specific modifications or validation associated
+     * with the creation of a new user. Note, that this method is called
+     * <strong>before</strong> any <code>Session.save</code> call.
+     *
+     * @param user The new user that has not yet been persisted;
+     * e.g. the associated node is still 'NEW'.
+     * @param password The password that was specified upon user creation.
+     * @param session The editing session associated with the user manager.
+     * @throws RepositoryException If an error occurs.
+     */
+    void onCreate(User user, String password, Session session) throws RepositoryException;
 
     /**
      * Allows to add application specific behavior associated with the removal
@@ -51,4 +64,16 @@ public interface AuthorizableAction {
      * @throws RepositoryException If an error occurs.
      */
     void onRemove(Authorizable authorizable, Session session) throws RepositoryException;
+
+    /**
+     * Allows to add application specific action or validation associated with
+     * changing a user password. Note, that this method is called <strong>before</strong>
+     * the password property is being modified in the content.
+     *
+     * @param user The user that whose password is going to change.
+     * @param newPassword The new password as specified in {@link User#changePassword}
+     * @param session The editing session associated with the user manager.
+     * @throws RepositoryException If an exception or error occurs.
+     */
+    void onPasswordChange(User user, String newPassword, Session session) throws RepositoryException;
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/ClearMembershipAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/ClearMembershipAction.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/ClearMembershipAction.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/ClearMembershipAction.java
Wed Nov  9 07:45:55 2011
@@ -1,20 +1,18 @@
 /*
+ * 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
  *
- *  * 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.
+ *      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.core.security.user.action;
 
@@ -30,7 +28,7 @@ import java.util.Iterator;
 /**
  * <code>ClearMembershipAction</code>...
  */
-public class ClearMembershipAction implements AuthorizableAction {
+public class ClearMembershipAction extends AbstractAuthorizableAction {
 
     /**
      * logger instance
@@ -44,15 +42,9 @@ public class ClearMembershipAction imple
 
     //-------------------------------------------------< AuthorizableAction >---
     /**
-     * @see AuthorizableAction#onCreate(org.apache.jackrabbit.api.security.user.Authorizable,
javax.jcr.Session)
-     */
-    public void onCreate(Authorizable authorizable, Session session) throws RepositoryException
{
-        // nothing to do
-    }
-
-    /**
      * @see AuthorizableAction#onRemove(org.apache.jackrabbit.api.security.user.Authorizable,
javax.jcr.Session)
      */
+    @Override
     public void onRemove(Authorizable authorizable, Session session) throws RepositoryException
{
         Iterator<Group> membership = authorizable.declaredMemberOf();
         while (membership.hasNext()) {

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java?rev=1199635&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/action/PasswordValidationAction.java
Wed Nov  9 07:45:55 2011
@@ -0,0 +1,110 @@
+/*
+ * 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.core.security.user.action;
+
+import org.apache.jackrabbit.api.security.user.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.ConstraintViolationException;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * <code>PasswordValidationAction</code> provides a simple password validation
+ * mechanism with the following configurable option:
+ *
+ * <ul>
+ *     <li><strong>constraint</strong>: a regular expression that can be
compiled
+ *     to a {@link Pattern} defining validation rules for a password.</li>
+ * </ul>
+ *
+ * <p>The password validation is executed on user creation and upon password
+ * change. It throws a <code>ConstraintViolationException</code> if the password
+ * validation fails.</p>
+ *
+ * <p>Example configuration:
+ * <pre>
+ *    &lt;UserManager class="org.apache.jackrabbit.core.security.user.UserPerWorkspaceUserManager"&gt;
+ *       &lt;AuthorizableAction class="org.apache.jackrabbit.core.security.user.action.PasswordValidationAction"&gt;
+ *          &lt;!--
+ *          password length must be at least 8 chars and it must contain at least
+ *          one upper and one lowercase ASCII character.
+ *          --&gt;
+ *          &lt;param name="constraint" value="^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z]).*"/&gt;
+ *       &lt;/AuthorizableAction&gt;
+ *    &lt;/UserManager&gt;
+ * </pre>
+ * </p>
+ *
+ * @see org.apache.jackrabbit.api.security.user.UserManager#createUser(String, String)
+ * @see User#changePassword(String)
+ * @see User#changePassword(String, String)
+ */
+public class PasswordValidationAction extends AbstractAuthorizableAction {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(PasswordValidationAction.class);
+
+    private Pattern pattern;
+
+    //-------------------------------------------------< AuthorizableAction >---
+    @Override
+    public void onCreate(User user, String password, Session session) throws RepositoryException
{
+        validatePassword(password);
+    }
+
+    @Override
+    public void onPasswordChange(User user, String newPassword, Session session) throws RepositoryException
{
+        validatePassword(newPassword);
+    }
+
+    //---------------------------------------------------------< BeanConfig >---
+    /**
+     * Set the password constraint.
+     *
+     * @param constraint A regular expression that can be used to validate a new password.
+     */
+    public void setConstraint(String constraint) {
+        try {
+            pattern = Pattern.compile(constraint);
+        } catch (PatternSyntaxException e) {
+            log.warn("Invalid password constraint: ", e.getMessage());
+        }
+    }
+
+    //------------------------------------------------------------< private >---
+    /**
+     * Validate the specified password.
+     *
+     * @param password The password to be validated
+     * @throws RepositoryException If the specified password is too short or
+     * doesn't match the specified password pattern.
+     */
+    private void validatePassword(String password) throws RepositoryException {
+        if (password != null) {
+            if (pattern != null && !pattern.matcher(password).matches()) {
+                throw new ConstraintViolationException("Password violates password constraint
(" + pattern.pattern() + ").");
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java?rev=1199635&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AuthorizableActionTest.java
Wed Nov  9 07:45:55 2011
@@ -0,0 +1,245 @@
+/*
+ * 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.core.security.user;
+
+import org.apache.jackrabbit.api.security.user.AbstractUserTest;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.core.security.user.action.AbstractAuthorizableAction;
+import org.apache.jackrabbit.core.security.user.action.AccessControlAction;
+import org.apache.jackrabbit.core.security.user.action.AuthorizableAction;
+import org.apache.jackrabbit.core.security.user.action.ClearMembershipAction;
+import org.apache.jackrabbit.core.security.user.action.PasswordValidationAction;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <code>AuthorizableActionTest</code>...
+ */
+public class AuthorizableActionTest extends AbstractUserTest {
+
+    private UserManagerImpl impl;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        impl = (UserManagerImpl) userMgr;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // reset the actions
+        setActions(null);
+
+        super.tearDown();
+    }
+
+    private void setActions(AuthorizableAction action) {
+        AuthorizableAction[] actions = (action == null) ?
+                new AuthorizableAction[0] :
+                new AuthorizableAction[] {action};
+        impl.setAuthorizableActions(actions);
+    }
+
+    public void testAccessControlAction() throws Exception {
+        AccessControlAction action = new AccessControlAction();
+        action.setUserPrivilegeNames("jcr:all");
+        action.setGroupPrivilegeNames("jcr:read");
+
+        User u = null;
+        Group gr = null;
+        try {
+            setActions(action);
+
+            String uid = getTestPrincipal().getName();
+            u = impl.createUser(uid, buildPassword(uid));
+            save(superuser);
+            assertAcAction(u, impl);
+
+            String grId = getTestPrincipal().getName();
+            gr = impl.createGroup(grId);
+            save(superuser);
+            assertAcAction(gr, impl);
+        } catch (UnsupportedRepositoryOperationException e) {
+            throw new NotExecutableException(e.getMessage());
+        } finally {
+            if (u != null) {
+                u.remove();
+            }
+            if (gr != null) {
+                gr.remove();
+            }
+            save(superuser);
+        }
+    }
+
+    private static void assertAcAction(Authorizable a, UserManagerImpl umgr) throws RepositoryException,
NotExecutableException {
+        Session s = umgr.getSession();
+        AccessControlManager acMgr = s.getAccessControlManager();
+        boolean hasACL = false;
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies("/");
+        while (it.hasNext()) {
+            if (it.nextAccessControlPolicy() instanceof AccessControlList) {
+                hasACL = true;
+                break;
+            }
+        }
+
+        if (!hasACL) {
+            for (AccessControlPolicy p : acMgr.getPolicies("/")) {
+                if (p instanceof AccessControlList) {
+                    hasACL = true;
+                    break;
+                }
+            }
+        }
+
+        if (!hasACL) {
+            throw new NotExecutableException("No ACLs in workspace containing users.");
+        }
+
+        String path = a.getPath();
+        assertEquals(1, acMgr.getPolicies(path).length);
+        assertTrue(acMgr.getPolicies(path)[0] instanceof AccessControlList);
+    }
+
+    public void testClearMembershipAction() throws Exception {
+        User u = null;
+        Group gr = null;
+        try {
+            setActions(new ClearMembershipAction());
+
+            String uid = getTestPrincipal().getName();
+            u = impl.createUser(uid, buildPassword(uid));
+
+            String grId = getTestPrincipal().getName();
+            gr = impl.createGroup(grId);
+            gr.addMember(u);
+
+            save(superuser);
+
+            assertTrue(gr.isMember(u));
+
+            u.remove();
+            u = null;
+
+            assertFalse(gr.isMember(u));
+        } finally {
+            if (u != null) {
+                u.remove();
+            }
+            if (gr != null) {
+                gr.remove();
+            }
+            save(superuser);
+        }
+    }
+
+    public void testPasswordAction() throws Exception {
+        User u = null;
+
+        try {
+            TestAction action = new TestAction();
+            setActions(action);
+
+            String uid = getTestPrincipal().getName();
+            u = impl.createUser(uid, buildPassword(uid));
+
+            u.changePassword("pw1");
+            assertEquals(1, action.called);
+
+            u.changePassword("pw2", "pw1");
+            assertEquals(2, action.called);
+        } finally {
+            if (u != null) {
+                u.remove();
+            }
+            save(superuser);
+        }
+    }
+
+    public void testPasswordValidationAction() throws Exception {
+        User u = null;
+
+        try {
+            String uid = getTestPrincipal().getName();
+            u = impl.createUser(uid, buildPassword(uid));
+
+            PasswordValidationAction pwAction = new PasswordValidationAction();
+            pwAction.setConstraint("^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z]).*");
+            setActions(pwAction);
+
+            List<String> invalid = new ArrayList<String>();
+            invalid.add("pw1");
+            invalid.add("only6C");
+            invalid.add("12345678");
+            invalid.add("WITHOUTLOWERCASE");
+            invalid.add("withoutuppercase");
+
+            for (String pw : invalid) {
+                try {
+                    u.changePassword(pw);
+                    fail("should throw constraint violation");
+                } catch (ConstraintViolationException e) {
+                    // success
+                }
+            }
+
+            List<String> valid = new ArrayList<String>();
+            valid.add("abCDefGH");
+            valid.add("Abbbbbbbbbbbb");
+            valid.add("cDDDDDDDDDDDDDDDDD");
+            valid.add("gH%%%%%%%%%%%%%%%%^^");
+            valid.add("&)(*&^%23qW");
+
+            for (String pw : valid) {
+                u.changePassword(pw);
+            }
+
+        } finally {
+            if (u != null) {
+                u.remove();
+            }
+            save(superuser);
+        }
+    }
+
+
+
+    //--------------------------------------------------------------------------
+    private class TestAction extends AbstractAuthorizableAction {
+
+        private int called = 0;
+
+        @Override
+        public void onPasswordChange(User user, String newPassword, Session session) throws
RepositoryException {
+            called++;
+        }
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java
Wed Nov  9 07:45:55 2011
@@ -37,6 +37,7 @@ public class TestAll extends TestCase {
         suite.addTestSuite(UserImplTest.class);
         suite.addTestSuite(GroupImplTest.class);
         suite.addTestSuite(ImpersonationImplTest.class);
+        suite.addTestSuite(AuthorizableActionTest.class);
 
         suite.addTestSuite(UserAdministratorTest.class);
         suite.addTestSuite(NotUserAdministratorTest.class);

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java?rev=1199635&r1=1199634&r2=1199635&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java
Wed Nov  9 07:45:55 2011
@@ -862,105 +862,4 @@ public class UserManagerImplTest extends
             }
         }
     }
-
-    public void testAccessControlAction() throws Exception {
-        UserManagerImpl impl = (UserManagerImpl) userMgr;
-
-        AccessControlAction action = new AccessControlAction();
-        action.setUserPrivilegeNames("jcr:all");
-        action.setGroupPrivilegeNames("jcr:read");
-        AuthorizableAction[] testActions = new AuthorizableAction[] {action};
-
-        User u = null;
-        Group gr = null;
-        try {
-            impl.setAuthorizableActions(testActions);
-            String uid = getTestPrincipal().getName();
-            u = impl.createUser(uid, buildPassword(uid));
-            save(superuser);
-            assertAcAction(u, impl);
-
-            String grId = getTestPrincipal().getName();
-            gr = impl.createGroup(grId);
-            save(superuser);
-            assertAcAction(gr, impl);
-        } catch (UnsupportedRepositoryOperationException e) {
-            throw new NotExecutableException(e.getMessage());
-        } finally {
-            impl.setAuthorizableActions(new AuthorizableAction[0]);
-            if (u != null) {
-                u.remove();
-            }
-            if (gr != null) {
-                gr.remove();
-            }
-            save(superuser);
-        }
-    }
-
-    private static void assertAcAction(Authorizable a, UserManagerImpl umgr) throws RepositoryException,
NotExecutableException {
-        Session s = umgr.getSession();
-        AccessControlManager acMgr = s.getAccessControlManager();
-        boolean hasACL = false;
-        AccessControlPolicyIterator it = acMgr.getApplicablePolicies("/");
-        while (it.hasNext()) {
-            if (it.nextAccessControlPolicy() instanceof AccessControlList) {
-                hasACL = true;
-                break;
-            }
-        }
-
-        if (!hasACL) {
-            for (AccessControlPolicy p : acMgr.getPolicies("/")) {
-                if (p instanceof AccessControlList) {
-                    hasACL = true;
-                    break;
-                }
-            }
-        }
-
-        if (!hasACL) {
-            throw new NotExecutableException("No ACLs in workspace containing users.");
-        }
-
-        String path = a.getPath();
-        assertEquals(1, acMgr.getPolicies(path).length);
-        assertTrue(acMgr.getPolicies(path)[0] instanceof AccessControlList);
-    }
-
-    public void testClearMembershipAction() throws Exception {
-        UserManagerImpl impl = (UserManagerImpl) userMgr;
-
-        AuthorizableAction[] testActions = new AuthorizableAction[] {new ClearMembershipAction()};
-
-        User u = null;
-        Group gr = null;
-        try {
-            impl.setAuthorizableActions(testActions);
-            String uid = getTestPrincipal().getName();
-            u = impl.createUser(uid, buildPassword(uid));
-
-            String grId = getTestPrincipal().getName();
-            gr = impl.createGroup(grId);
-            gr.addMember(u);
-
-            save(superuser);
-
-            assertTrue(gr.isMember(u));
-
-            u.remove();
-            u = null;
-
-            assertFalse(gr.isMember(u));
-        } finally {
-            impl.setAuthorizableActions(new AuthorizableAction[0]);
-            if (u != null) {
-                u.remove();
-            }
-            if (gr != null) {
-                gr.remove();
-            }
-            save(superuser);
-        }
-    }
 }



Mime
View raw message