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/08 12:24:32 UTC
svn commit: r1370730 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/
oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ oak-jcr...
Author: angela
Date: Wed Aug 8 10:24:32 2012
New Revision: 1370730
URL: http://svn.apache.org/viewvc?rev=1370730&view=rev
Log:
OAK-50 : Implement User Management (WIP)
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java (contents, props changed)
- copied, changed from r1368830, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/
- copied from r1368830, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/action/
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractAuthorizableAction.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AccessControlAction.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java
- copied, changed from r1370710, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/action/AuthorizableAction.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/ClearMembershipAction.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationAction.java
Removed:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/action/
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableNodeCreator.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakRepositoryStub.java
Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java (from r1368830, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java&p1=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java&r1=1368830&r2=1370730&rev=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java Wed Aug 8 10:24:32 2012
@@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.jcr.security.user;
+package org.apache.jackrabbit.oak.spi.security.user;
-import org.apache.jackrabbit.oak.jcr.security.user.action.AuthorizableAction;
+import org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,7 +26,9 @@ import java.util.Set;
import javax.annotation.Nonnull;
/**
- * UserManagerConfig...
+ * UserManagerConfig provides utilities to retrieve configuration options
+ * related to user management. In addition it defines some constants that
+ * have been used in Jackrabbit 2.0 default user management implementation.
*/
public class UserManagerConfig {
@@ -51,11 +53,15 @@ public class UserManagerConfig {
public static final String PARAM_DEFAULT_DEPTH = "defaultDepth";
/**
- * If this parameter is present group members are collected in a node
- * structure below a {@link UserConstants#REP_MEMBERS} node instead of the
- * default multi valued property {@link UserConstants#REP_MEMBERS}.
- * Its value determines the maximum number of member properties until
- * additional intermediate nodes are inserted.
+ * Its value determines the maximum number of members within a given
+ * content structure until additional intermediate structuring is being
+ * added. This may for example be used to
+ * <ul>
+ * <li>switch storing group members in JCR properties or nodes</li>
+ * <li>define maximum number of members is a multivalued property</li>
+ * <li>define maximum number of member properties within a given
+ * node structure</li>
+ * </ul>
*/
public static final String PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE = "groupMembershipSplitSize";
@@ -81,6 +87,10 @@ public class UserManagerConfig {
private final Map<String, Object> options;
private final Set<AuthorizableAction> actions;
+ public UserManagerConfig(String adminId) {
+ this(adminId, null, null);
+ }
+
public UserManagerConfig(String adminId, Map<String, Object> options, Set<AuthorizableAction> actions) {
assert adminId != null;
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserManagerConfig.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractAuthorizableAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractAuthorizableAction.java?rev=1370730&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractAuthorizableAction.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractAuthorizableAction.java Wed Aug 8 10:24:32 2012
@@ -0,0 +1,69 @@
+/*
+ * 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.security.user.action;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+
+/**
+ * Abstract implementation of the {@code AuthorizableAction} 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
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AccessControlAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AccessControlAction.java?rev=1370730&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AccessControlAction.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AccessControlAction.java Wed Aug 8 10:24:32 2012
@@ -0,0 +1,220 @@
+/*
+ * 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.security.user.action;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+import javax.jcr.security.Privilege;
+
+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.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@code AccessControlAction} 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>
+ * groupPrivilegeNames : "jcr:read"
+ * userPrivilegeNames : "jcr:read, rep:write"
+ * </pre>
+ * </p>
+ * <p>This configuration could for example lead to the following content
+ * structure upon user or group creation. Note however that the resulting
+ * structure depends on the actual access control management being in place:
+ *
+ * <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 extends AbstractAuthorizableAction {
+
+ /**
+ * logger instance
+ */
+ private static final Logger log = LoggerFactory.getLogger(AccessControlAction.class);
+
+ private String[] groupPrivilegeNames = new String[0];
+ private String[] userPrivilegeNames = new String[0];
+
+ //-------------------------------------------------< AuthorizableAction >---
+ /**
+ * @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)
+ */
+ @Override
+ public void onCreate(User user, String password, Session session) throws RepositoryException {
+ setAC(user, session);
+ }
+
+ //------------------------------------------------------< Configuration >---
+ /**
+ * 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();
+
+ JackrabbitAccessControlList acl = null;
+ AccessControlManager acMgr = session.getAccessControlManager();
+ for (AccessControlPolicyIterator it = acMgr.getApplicablePolicies(path); it.hasNext();) {
+ AccessControlPolicy plc = it.nextAccessControlPolicy();
+ if (plc instanceof JackrabbitAccessControlList) {
+ acl = (JackrabbitAccessControlList) plc;
+ break;
+ }
+ }
+
+ if (acl == null) {
+ log.warn("Cannot process AccessControlAction: no applicable ACL at " + path);
+ } else {
+ // setup acl according to configuration.
+ Principal principal = authorizable.getPrincipal();
+ boolean modified = false;
+ if (authorizable.isGroup()) {
+ // new authorizable is a Group
+ if (groupPrivilegeNames.length > 0) {
+ modified = acl.addAccessControlEntry(principal, getPrivileges(groupPrivilegeNames, acMgr));
+ }
+ } else {
+ // new authorizable is a User
+ if (userPrivilegeNames.length > 0) {
+ modified = acl.addAccessControlEntry(principal, getPrivileges(userPrivilegeNames, acMgr));
+ }
+ }
+ if (modified) {
+ acMgr.setPolicy(path, acl);
+ }
+ }
+ }
+
+ /**
+ * Retrieve privileges for the specified privilege names.
+ *
+ * @param privNames The privilege names.
+ * @param acMgr The access control manager.
+ * @return Array of {@code Privilege}
+ * @throws javax.jcr.RepositoryException If a privilege name cannot be
+ * resolved to a valid privilege.
+ */
+ private static Privilege[] getPrivileges(String[] privNames, AccessControlManager acMgr) throws RepositoryException {
+ if (privNames == null || privNames.length == 0) {
+ return new Privilege[0];
+ }
+ Privilege[] privileges = new Privilege[privNames.length];
+ for (int i = 0; i < privNames.length; i++) {
+ privileges[i] = acMgr.privilegeFromName(privNames[i]);
+ }
+ return privileges;
+ }
+
+ /**
+ * Split the specified configuration parameter into privilege names.
+ *
+ * @param configParam The configuration parameter defining a comma separated
+ * list of privilege names.
+ * @return An array of privilege names.
+ */
+ private static String[] split(String configParam) {
+ List<String> nameList = new ArrayList<String>();
+ for (String pn : Text.explode(configParam, ',', false)) {
+ String privName = pn.trim();
+ if (privName.length() > 0) {
+ nameList.add(privName);
+ }
+ }
+ return nameList.toArray(new String[nameList.size()]);
+ }
+}
Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java (from r1370710, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/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?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java&p1=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/action/AuthorizableAction.java&r1=1370710&r2=1370730&rev=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/action/AuthorizableAction.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AuthorizableAction.java Wed Aug 8 10:24:32 2012
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.jcr.security.user.action;
+package org.apache.jackrabbit.oak.spi.security.user.action;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/ClearMembershipAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/ClearMembershipAction.java?rev=1370730&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/ClearMembershipAction.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/ClearMembershipAction.java Wed Aug 8 10:24:32 2012
@@ -0,0 +1,45 @@
+/*
+ * 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.security.user.action;
+
+import java.util.Iterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+
+/**
+ * Authorizable action attempting to clear all group membership before removing
+ * the specified authorizable. If {@link Group#removeMember(org.apache.jackrabbit.api.security.user.Authorizable)}
+ * fails due to lack of permissions {@link #onRemove(org.apache.jackrabbit.api.security.user.Authorizable, javax.jcr.Session)}
+ * throws an exception and removing the specified authorizable will be aborted.
+ */
+public class ClearMembershipAction extends AbstractAuthorizableAction {
+
+ //-------------------------------------------------< AuthorizableAction >---
+ /**
+ * @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()) {
+ membership.next().removeMember(authorizable);
+ }
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationAction.java?rev=1370730&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationAction.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationAction.java Wed Aug 8 10:24:32 2012
@@ -0,0 +1,100 @@
+/*
+ * 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.security.user.action;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.spi.security.user.PasswordUtility;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code PasswordValidationAction} 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 java.util.regex.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} if the password
+ * validation fails.</p>
+ *
+ * @see org.apache.jackrabbit.api.security.user.UserManager#createUser(String, String)
+ * @see org.apache.jackrabbit.api.security.user.User#changePassword(String)
+ * @see org.apache.jackrabbit.api.security.user.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);
+ }
+
+ //------------------------------------------------------< Configuration >---
+ /**
+ * 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 && isPlainText(password)) {
+ if (pattern != null && !pattern.matcher(password).matches()) {
+ throw new ConstraintViolationException("Password violates password constraint (" + pattern.pattern() + ").");
+ }
+ }
+ }
+
+ private static boolean isPlainText(String password) {
+ return !PasswordUtility.isPlainTextPassword(password);
+ }
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java?rev=1370730&r1=1370729&r2=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java Wed Aug 8 10:24:32 2012
@@ -50,7 +50,6 @@ import org.apache.jackrabbit.commons.Abs
import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.jcr.security.principal.PrincipalManagerImpl;
-import org.apache.jackrabbit.oak.jcr.security.user.UserManagerConfig;
import org.apache.jackrabbit.oak.jcr.security.user.UserManagerImpl;
import org.apache.jackrabbit.oak.jcr.xml.XmlImportHandler;
import org.apache.jackrabbit.oak.security.principal.KernelPrincipalProvider;
@@ -534,8 +533,7 @@ public class SessionImpl extends Abstrac
@Override
@Nonnull
public UserManager getUserManager() throws RepositoryException {
- return TODO.unimplemented().returnValue(new UserManagerImpl(
- dlg, new UserManagerConfig("admin", null, null)));
+ return TODO.unimplemented().returnValue(new UserManagerImpl(dlg, null));
}
//------------------------------------------------------------< private >---
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableNodeCreator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableNodeCreator.java?rev=1370730&r1=1370729&r2=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableNodeCreator.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableNodeCreator.java Wed Aug 8 10:24:32 2012
@@ -21,6 +21,7 @@ import org.apache.jackrabbit.oak.api.Cor
import org.apache.jackrabbit.oak.jcr.SessionDelegate;
import org.apache.jackrabbit.oak.jcr.value.ValueConverter;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.user.UserManagerConfig;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java?rev=1370730&r1=1370729&r2=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java Wed Aug 8 10:24:32 2012
@@ -16,6 +16,20 @@
*/
package org.apache.jackrabbit.oak.jcr.security.user;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.List;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
+
import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
@@ -26,27 +40,14 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.jcr.PropertyDelegate;
import org.apache.jackrabbit.oak.jcr.SessionDelegate;
-import org.apache.jackrabbit.oak.jcr.security.user.action.AuthorizableAction;
import org.apache.jackrabbit.oak.jcr.value.ValueConverter;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
import org.apache.jackrabbit.oak.spi.security.user.PasswordUtility;
+import org.apache.jackrabbit.oak.spi.security.user.UserManagerConfig;
+import org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.Value;
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.util.Iterator;
-import java.util.List;
-
/**
* UserManagerImpl...
*/
@@ -62,7 +63,7 @@ public class UserManagerImpl implements
public UserManagerImpl(SessionDelegate sessionDelegate, UserManagerConfig config) {
this.sessionDelegate = sessionDelegate;
- this.config = config;
+ this.config = (config == null) ? new UserManagerConfig("admin") : config;
nodeCreator = new AuthorizableNodeCreator(sessionDelegate, this.config);
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakRepositoryStub.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakRepositoryStub.java?rev=1370730&r1=1370729&r2=1370730&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakRepositoryStub.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakRepositoryStub.java Wed Aug 8 10:24:32 2012
@@ -23,6 +23,8 @@ import java.security.Principal;
import java.util.Properties;
import java.util.concurrent.Executors;
+import javax.jcr.Credentials;
+import javax.jcr.GuestCredentials;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@@ -74,6 +76,11 @@ public class OakRepositoryStub extends R
}
@Override
+ public Credentials getReadOnlyCredentials() {
+ return new GuestCredentials();
+ }
+
+ @Override
public Principal getKnownPrincipal(Session session) throws RepositoryException {
throw new UnsupportedRepositoryOperationException();
}