You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/03/19 14:57:11 UTC
svn commit: r638834 [10/14] - in /jackrabbit/trunk:
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/
jack...
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,429 @@
+/*
+ * 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.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.principal.ItemBasedPrincipal;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventIterator;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation of the <code>AccessControlProvider</code> interface that
+ * is used to protected the 'security workspace' containing the user and
+ * group data. It applies special care to make sure that modifying user data
+ * (e.g. password), group membership and impersonation is properly controlled.
+ * The access control policy defined by this provider has the following
+ * characteristics:
+ * TODO describe policy.
+ */
+public class UserAccessControlProvider extends AbstractAccessControlProvider
+ implements UserConstants {
+
+ private static Logger log = LoggerFactory.getLogger(UserAccessControlProvider.class);
+
+ private Path groupsPath;
+ private Path usersPath;
+
+ private SessionImpl systemSession;
+ private ObservationManager obsMgr;
+
+ private String userAdminGroup;
+ private String groupAdminGroup;
+
+ /**
+ *
+ */
+ public UserAccessControlProvider() {
+ super("Access control policy for the 'security' workspace.",
+ "Policy that defines the general access control rules for the security workspace.");
+ }
+
+ //----------------------------------------------< AccessControlProvider >---
+ /**
+ * @see AccessControlProvider#init(Session, Map)
+ */
+ public void init(Session systemSession, Map options) throws RepositoryException {
+ if (initialized) {
+ throw new IllegalStateException("already initialized");
+ }
+ if (systemSession instanceof SessionImpl) {
+ this.systemSession = (SessionImpl) systemSession;
+ obsMgr = systemSession.getWorkspace().getObservationManager();
+
+ userAdminGroup = (options.containsKey(USER_ADMIN_GROUP_NAME)) ? options.get(USER_ADMIN_GROUP_NAME).toString() : USER_ADMIN_GROUP_NAME;
+ groupAdminGroup = (options.containsKey(GROUP_ADMIN_GROUP_NAME)) ? options.get(GROUP_ADMIN_GROUP_NAME).toString() : GROUP_ADMIN_GROUP_NAME;
+
+ // make sure the groups exist (and ev. create them).
+ // TODO: review again.
+ UserManager uMgr = this.systemSession.getUserManager();
+ if (!initGroup(uMgr, userAdminGroup)) {
+ log.warn("Unable to initialize User admininistrator group -> no user admins.");
+ userAdminGroup = null;
+ }
+ if (!initGroup(uMgr, groupAdminGroup)) {
+ log.warn("Unable to initialize Group admininistrator group -> no group admins.");
+ groupAdminGroup = null;
+ }
+
+ usersPath = this.systemSession.getQPath(USERS_PATH);
+ groupsPath = this.systemSession.getQPath(GROUPS_PATH);
+
+ } else {
+ throw new RepositoryException("SessionImpl (system session) expected.");
+ }
+ initialized = true;
+ }
+
+ public CompiledPermissions compilePermissions(Set principals) throws ItemNotFoundException, RepositoryException {
+ checkInitialized();
+ if (isAdminOrSystem(principals)) {
+ return getAdminPermissions();
+ } else {
+ // determined the 'user' present in the given set of principals.
+ ItemBasedPrincipal userPrincipal = getUserPrincipal(principals);
+ NodeImpl userNode = getUserNode(userPrincipal);
+ if (userNode == null) {
+ // no 'user' within set of principals -> READ-only
+ return getReadOnlyPermissions();
+ } else {
+ return new CompiledPermissionsImpl(principals, userNode);
+ }
+ }
+ }
+
+ //------------------------------------------------------------< private >---
+
+ private ItemBasedPrincipal getUserPrincipal(Set principals) {
+ try {
+ UserManager uMgr = systemSession.getUserManager();
+ for (Iterator it = principals.iterator(); it.hasNext();) {
+ Principal p = (Principal) it.next();
+ if (!(p instanceof Group) && p instanceof ItemBasedPrincipal
+ && uMgr.getAuthorizable(p) != null) {
+ return (ItemBasedPrincipal) p;
+ }
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Internal error while retrieving user principal", e.getMessage());
+ }
+ // none of the principals in the set is assigned to a User.
+ return null;
+ }
+
+ private NodeImpl getUserNode(ItemBasedPrincipal principal) {
+ NodeImpl userNode = null;
+ if (principal != null) {
+ try {
+ String path = principal.getPath();
+ userNode = (NodeImpl) systemSession.getNode(path);
+ } catch (RepositoryException e) {
+ log.warn("Error while retrieving user node.", e.getMessage());
+ }
+ }
+ return userNode;
+ }
+
+ private boolean isMember(Node userNode, Path memberPath) throws RepositoryException, PathNotFoundException {
+ // precondition: memberPath points to a rep:members property
+ String propPath = systemSession.getJCRPath(memberPath);
+ if (systemSession.propertyExists(propPath)) {
+ // check if any of the ref-values equals to the value created from
+ // the user-Node (which must be present if the user is member of the group)
+ Property membersProp = systemSession.getProperty(propPath);
+ List values = Arrays.asList(membersProp.getValues());
+ return values.contains(systemSession.getValueFactory().createValue(userNode));
+ } else {
+ return false;
+ }
+ }
+
+ private Node getExistingNode(Path path) throws RepositoryException {
+ String absPath = systemSession.getJCRPath(path.getNormalizedPath());
+ if (systemSession.nodeExists(absPath)) {
+ return systemSession.getNode(absPath);
+ } else if (systemSession.propertyExists(absPath)) {
+ return systemSession.getProperty(absPath).getParent();
+ } else {
+ String pPath = Text.getRelativeParent(absPath, 1);
+ if (systemSession.nodeExists(pPath)) {
+ return systemSession.getNode(pPath);
+ } else {
+ throw new ItemNotFoundException("Unable to determine permissions: No item and no existing parent for target path " + absPath);
+ }
+ }
+ }
+
+ /**
+ * Determine if for the given <code>path</code>, the set of privileges
+ * must be calculated.
+ *
+ * @param path
+ * @return true if <code>path</code> denotes an existing <code>Node</code>,
+ * false otherwise.
+ * @throws RepositoryException
+ */
+ private boolean doCalculatePrivileges(Path path) throws RepositoryException {
+ String absPath = systemSession.getJCRPath(path.getNormalizedPath());
+ // privileges can only be determined for existing nodes.
+ // not for properties and neither for non-existing nodes.
+ return systemSession.nodeExists(absPath);
+ }
+
+ private static boolean containsGroup(Set principals, String groupName) {
+ for (Iterator it = principals.iterator(); it.hasNext() && groupName != null;) {
+ Principal p = (Principal) it.next();
+ if (p.getName().equals(groupName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean initGroup(UserManager uMgr, String principalName) {
+ boolean success;
+ Principal prnc = new PrincipalImpl(principalName);
+ try {
+ Authorizable auth = uMgr.getAuthorizable(prnc);
+ if (auth == null) {
+ success = (uMgr.createGroup(prnc) != null);
+ } else {
+ success = auth.isGroup();
+ if (!success) {
+ log.warn("Cannot create group '" + principalName + "'; User with that principal already exists.");
+ }
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Error while initializing user/group administrators", e.getMessage());
+ success = false;
+ }
+ return success;
+ }
+
+ //--------------------------------------------------------< inner class >---
+ /**
+ *
+ */
+ private class CompiledPermissionsImpl extends AbstractCompiledPermissions
+ implements EventListener {
+
+ private final NodeImpl userNode;
+ private final boolean isUserAdmin;
+ private final boolean isGroupAdmin;
+
+ protected CompiledPermissionsImpl(Set principals, NodeImpl userNode) throws RepositoryException {
+ this.userNode = userNode;
+
+ isUserAdmin = containsGroup(principals, userAdminGroup);
+ isGroupAdmin = containsGroup(principals, groupAdminGroup);
+
+ int events = Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED;
+ obsMgr.addEventListener(this, events, GROUPS_PATH, true, null, null, false);
+ }
+
+ //------------------------------------< AbstractCompiledPermissions >---
+ /**
+ * @see AbstractCompiledPermissions#buildResult(Path)
+ */
+ protected Result buildResult(Path path) throws RepositoryException {
+ // default permission and default privileges
+ int perms = Permission.READ;
+ int privs;
+ boolean calcPrivs = doCalculatePrivileges(path);
+ if (calcPrivs) {
+ privs = PrivilegeRegistry.READ;
+ } else {
+ privs = 0;
+ }
+
+ Path abs2Path = path.subPath(0, 4);
+ if (usersPath.equals(abs2Path)) {
+ NodeImpl node = (NodeImpl) getExistingNode(path);
+ NodeImpl authN = null;
+ // seek next rep:authorizable parent
+ if (node.isNodeType(NT_REP_AUTHORIZABLE)) {
+ authN = node;
+ } else if (node.isNodeType(NT_REP_AUTHORIZABLE_FOLDER)) {
+ NodeImpl parent = node;
+ while (authN == null && parent.getDepth() > 0) {
+ parent = (NodeImpl) parent.getParent();
+ if (parent.isNodeType(NT_REP_AUTHORIZABLE)) {
+ authN = parent;
+ } else if (!parent.isNodeType(NT_REP_AUTHORIZABLE_FOLDER)) {
+ // outside of user/group-tree
+ break;
+ }
+ }
+ } // else: outside of user tree -> authN = null
+
+ if (authN != null && authN.isNodeType(NT_REP_USER)) {
+ int relDepth = systemSession.getHierarchyManager().getRelativeDepth(userNode.getNodeId(), authN.getNodeId());
+ switch (relDepth) {
+ case -1:
+ // authN is not below the userNode -> can't write anyway.
+ break;
+ case 0:
+ /*
+ authN is same node as userNode. 2 cases to distinguish
+ 1) user is User-Admin -> R, W
+ 2) user is NOT U-admin but nodeID is its own node.
+ */
+ if (isUserAdmin) {
+ // principals contain 'user-admin' -> user can modify
+ // any item below the user-node.
+ perms = Permission.ALL;
+ if (calcPrivs) {
+ privs |= PrivilegeRegistry.WRITE;
+ }
+ } else if (userNode.isSame(node)) {
+ // user can only read && write his own props
+ perms |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
+ if (calcPrivs) {
+ privs |= PrivilegeRegistry.MODIFY_PROPERTIES;
+ }
+ } // else some other node below but not U-admin -> read-only.
+ break;
+ default:
+ /*
+ authN is somewhere below the userNode, i.e.
+ 1) nodeId points to an authorizable below userNode
+ 2) nodeId points to an auth-folder below some authorizable below userNode.
+
+ In either case user-admin group is required to have write
+ permission.
+ */
+ if (isUserAdmin) {
+ perms = Permission.ALL;
+ if (calcPrivs) {
+ privs |= PrivilegeRegistry.WRITE;
+ }
+ }
+ }
+ } // no rep:User parent node found.
+ } else if (groupsPath.equals(abs2Path)) {
+ /*
+ below group-tree:
+ - test if the user is group-administrator.
+ - in addition the following special condition must be checked:
+
+ if the target id is 'rep:members' the user MUST be member of that
+ the containing group in order to have WRITE privilege.
+ this required in order to make sure the group-admin cannot
+ modify the members of some other groups e.g. administrators.
+ */
+ if (isGroupAdmin) {
+ if (P_MEMBERS.equals(path.getNameElement().getName())) {
+ if (isMember(userNode, path)) {
+ perms |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
+ }
+ } else {
+ perms = Permission.ALL;
+ if (calcPrivs) {
+ privs |= PrivilegeRegistry.WRITE;
+ }
+ }
+ }
+
+ } // else outside of user/group tree -> read only.
+
+ return new Result(perms, privs);
+ }
+
+ //--------------------------------------------< CompiledPermissions >---
+ /**
+ * @see CompiledPermissions#close()
+ */
+ public void close() {
+ try {
+ obsMgr.removeEventListener(this);
+ } catch (RepositoryException e) {
+ log.error("Internal error: ", e.getMessage());
+ }
+ super.close();
+ }
+
+ /**
+ * @see CompiledPermissions#grants(Path, int)
+ */
+ public boolean grants(Path absPath, int permissions) throws RepositoryException {
+ if (permissions == Permission.READ) {
+ // read is always granted
+ return true;
+ }
+ // TODO: additional simple checks.... (last accessed... etc)
+
+ // finally retrieve from cache (or build)
+ return super.grants(absPath, permissions);
+ }
+
+ //--------------------------------------------------< EventListener >---
+ /**
+ * Event listener is only interested in changes of group-membership
+ * that effect the permission-evaluation.
+ *
+ * @param events
+ */
+ public void onEvent(EventIterator events) {
+ while (events.hasNext()) {
+ Event ev = events.nextEvent();
+ try {
+ String evPath = ev.getPath();
+ if ("rep:members".equals(Text.getName(evPath))) {
+ // TODO: add better evaluation.
+ clearCache();
+ // only need to clear the cache once. stop processing
+ break;
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Internal error ", e.getMessage());
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,68 @@
+/*
+ * 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.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+
+/**
+ * <code>UserConstants</code>...
+ */
+interface UserConstants {
+
+ NameFactory NF = NameFactoryImpl.getInstance();
+
+ /**
+ * root-path to security related content e.g. principals
+ */
+ String SECURITY_ROOT_PATH = "/rep:security";
+ String AUTHORIZABLES_PATH = SECURITY_ROOT_PATH + "/rep:authorizables";
+ String USERS_PATH = AUTHORIZABLES_PATH + "/rep:users";
+ String GROUPS_PATH = AUTHORIZABLES_PATH + "/rep:groups";
+
+ /**
+ * Configuration key and default value for the the name of the
+ * 'UserAdmin' group-principal.
+ */
+ String USER_ADMIN_GROUP_NAME = "UserAdmin";
+ /**
+ * Configuration key and default value for the the name of the
+ * 'GroupAdmin' group-principal
+ */
+ String GROUP_ADMIN_GROUP_NAME = "GroupAdmin";
+
+ Name P_REFEREES = NF.create(Name.NS_REP_URI, "referees");
+ Name P_PRINCIPAL_NAME = NF.create(Name.NS_REP_URI, "principalName");
+
+ Name P_USERID = NF.create(Name.NS_REP_URI, "userId");
+ Name P_PASSWORD = NF.create(Name.NS_REP_URI, "password");
+
+ Name P_MEMBERS = NF.create(Name.NS_REP_URI, "members");
+
+ /**
+ * Name of the user property containing the principal names of those allowed
+ * to impersonate.
+ */
+ Name P_IMPERSONATORS = NF.create(Name.NS_REP_URI, "impersonators");
+
+ Name NT_REP_AUTHORIZABLE = NF.create(Name.NS_REP_URI, "Authorizable");
+ Name NT_REP_AUTHORIZABLE_FOLDER = NF.create(Name.NS_REP_URI, "AuthorizableFolder");
+ Name NT_REP_USER = NF.create(Name.NS_REP_URI, "User");
+ Name NT_REP_GROUP = NF.create(Name.NS_REP_URI, "Group");
+
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserConstants.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: 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=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,128 @@
+/*
+ * 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.core.NodeImpl;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Impersonation;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials;
+import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.util.Text;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * UserImpl
+ */
+class UserImpl extends AuthorizableImpl implements User {
+
+ private final String id;
+
+ private Principal principal = null;
+ private Impersonation impersonation = null;
+
+ private UserImpl(NodeImpl node, UserManagerImpl userManager) throws RepositoryException {
+ super(node, userManager);
+
+ id = node.getProperty(P_USERID).getString();
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * @param node
+ * @param userManager
+ * @return
+ * @throws RepositoryException
+ */
+ static User create(NodeImpl node, UserManagerImpl userManager) throws RepositoryException {
+ if (node == null || !node.isNodeType(NT_REP_USER)) {
+ throw new IllegalArgumentException();
+ }
+ if(!Text.isDescendant(USERS_PATH, node.getPath())) {
+ throw new IllegalArgumentException("User has to be within the User Path");
+ }
+ return new UserImpl(node, userManager);
+ }
+
+ //-------------------------------------------------------< Authorizable >---
+ /**
+ * @see Authorizable#getID()
+ */
+ public String getID() throws RepositoryException {
+ return id;
+ }
+
+ //------------------------------------------------< User >------------------
+ /**
+ * @see User#isAdmin()
+ */
+ public boolean isAdmin() {
+ return userManager.isAdminId(id);
+ }
+
+ /**
+ * @see User#getCredentials()
+ */
+ public Iterator getCredentials() throws RepositoryException {
+ try {
+ String password = getNode().getProperty(P_PASSWORD).getString();
+ Credentials creds = new CryptedSimpleCredentials(getID(), password);
+ return Collections.singletonList(creds).iterator();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RepositoryException(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new RepositoryException(e);
+ }
+ }
+ /**
+ * @see User#isGroup()
+ */
+ public boolean isGroup() {
+ return false;
+ }
+
+ /**
+ * @see User#getPrincipal()
+ */
+ public Principal getPrincipal() throws RepositoryException {
+ if (principal == null) {
+ if (isAdmin()) {
+ principal = new AdminPrincipal(getPrincipalName());
+ } else {
+ principal = new NodeBasedPrincipal(getPrincipalName());
+ }
+ }
+ return principal;
+ }
+
+ /**
+ * @see User#getImpersonation()
+ */
+ public Impersonation getImpersonation() throws RepositoryException {
+ if (impersonation == null) {
+ impersonation = new ImpersonationImpl(this, userManager);
+ }
+ return impersonation;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: 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=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,535 @@
+/*
+ * 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.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials;
+import org.apache.jackrabbit.core.security.principal.ItemBasedPrincipal;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SecurityItemModifier;
+import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Credentials;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.Node;
+import javax.jcr.Item;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
+import javax.jcr.lock.LockException;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * UserManagerImpl
+ */
+public class UserManagerImpl extends SecurityItemModifier implements UserManager, UserConstants {
+
+ private static final Logger log = LoggerFactory.getLogger(UserManagerImpl.class);
+
+ private final SessionImpl session;
+ private final String adminId;
+ private final NodeResolver authResolver;
+
+ private String currentUserPath;
+
+ public UserManagerImpl(SessionImpl session, String adminId) throws RepositoryException {
+ this.session = session;
+ this.adminId = adminId;
+
+ NodeResolver nr;
+ try {
+ session.getWorkspace().getQueryManager();
+ nr = new IndexNodeResolver(session);
+ } catch (RepositoryException e) {
+ log.debug("UserManger: no QueryManager available for workspace '" + session.getWorkspace().getName() + "' -> Use traversing node resolver.");
+ nr = new TraversingNodeResolver(session);
+ }
+ authResolver = nr;
+ }
+
+ //--------------------------------------------------------< UserManager >---
+ /**
+ * @see UserManager#getAuthorizable(String)
+ */
+ public Authorizable getAuthorizable(String id) throws RepositoryException {
+ if (id == null || id.length() == 0) {
+ throw new IllegalArgumentException("Invalid authorizable name '" + id + "'");
+ }
+ Authorizable authorz = null;
+ NodeImpl n = (NodeImpl) authResolver.findNode(P_USERID, id, NT_REP_USER);
+ if (n != null) {
+ authorz = UserImpl.create(n, this);
+ } else {
+ // TODO: TOBEFIXED. should rather search for node with escaped(id) == Node.getName
+ String principalName = getGroupPrincipalName(id);
+ n = (NodeImpl) authResolver.findNode(P_PRINCIPAL_NAME, principalName, NT_REP_GROUP);
+ if (n != null) {
+ authorz = GroupImpl.create(n, this);
+ }
+ }
+ return authorz;
+ }
+
+ /**
+ * @see UserManager#getAuthorizable(Principal)
+ */
+ public Authorizable getAuthorizable(Principal principal) throws RepositoryException {
+ NodeImpl n = null;
+ // shortcut that avoids executing a query.
+ if (principal instanceof ItemBasedPrincipal) {
+ String authPath = ((ItemBasedPrincipal) principal).getPath();
+ if (session.itemExists(authPath)) {
+ Item authItem = session.getItem(authPath);
+ if (authItem.isNode()) {
+ n = (NodeImpl) authItem;
+ }
+ }
+ }
+ // another Principal -> search
+ if (n == null) {
+ String name = principal.getName();
+ n = (NodeImpl) authResolver.findNode(P_PRINCIPAL_NAME, name, NT_REP_AUTHORIZABLE);
+ }
+ // build the corresponding authorizable object
+ if (n != null) {
+ if (n.isNodeType(NT_REP_USER)) {
+ return UserImpl.create(n, this);
+ } else if (n.isNodeType(NT_REP_GROUP)) {
+ return GroupImpl.create(n, this);
+ } else {
+ log.warn("Unexpected user nodetype " + n.getPrimaryNodeType().getName());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see UserManager#findAuthorizable(String,String)
+ */
+ public Iterator findAuthorizable(String propertyName, String value) throws RepositoryException {
+ Name name = session.getQName(propertyName);
+ NodeIterator auths = authResolver.findNodes(name, value, NT_REP_AUTHORIZABLE, true);
+ return new AuthorizableIterator(auths);
+ }
+
+ /**
+ * Creates a new Node on the repository with the specified
+ * <code>userName</code>.<br>
+ * The <code>userID</code> is expected to be a valid JCR-<code>Name</code>.
+ * The User will be created relative to path of the User who represents the
+ * Session this UserManager has been created for.<br>
+ * If the {@link javax.jcr.Credentials Credentials} are of type
+ * {@link javax.jcr.SimpleCredentials SimpleCredentials} they will be
+ * crypted.
+ *
+ * @param userID
+ * @param credentials
+ * @see UserManager#createUser(String, Credentials, Principal principal)
+ * @inheritDoc
+ */
+ public User createUser(String userID, Credentials credentials,
+ Principal principal) throws RepositoryException {
+ return createUser(userID, credentials, principal, null);
+ }
+
+ /**
+ *
+ * @param userID
+ * @param credentials
+ * @param principal
+ * @param intermediatePath
+ * @return
+ * @throws AuthorizableExistsException
+ * @throws RepositoryException
+ */
+ public User createUser(String userID, Credentials credentials,
+ Principal principal, String intermediatePath)
+ throws AuthorizableExistsException, RepositoryException {
+ if (userID == null || credentials == null || principal == null) {
+ throw new IllegalArgumentException("Not possible to create user with null parameters");
+ }
+ if (getAuthorizable(userID) != null) {
+ throw new AuthorizableExistsException("User for '" + userID + "' already exists");
+ }
+ if (hasAuthorizableOrReferee(principal)) {
+ throw new AuthorizableExistsException("Authorizable for '" + principal.getName() + "' already exists");
+ }
+ if (!(credentials instanceof SimpleCredentials)) {
+ throw new RepositoryException("SimpleCredentials required. Found " + credentials.getClass());
+ } else if (!userID.equals(((SimpleCredentials) credentials).getUserID())) {
+ throw new RepositoryException("UserID mismatch: " + userID + " <-> " + ((SimpleCredentials) credentials).getUserID());
+ }
+
+ NodeImpl parent = null;
+ try {
+ String parentPath = getParentPath(intermediatePath, getCurrentUserPath());
+ parent = createParentNode(parentPath);
+
+ Name nodeName = session.getQName(Text.escapeIllegalJcrChars(userID));
+ NodeImpl userNode = addSecurityNode(parent, nodeName, NT_REP_USER);
+
+ setSecurityProperty(userNode, P_USERID, getValue(userID));
+ CryptedSimpleCredentials creds = new CryptedSimpleCredentials((SimpleCredentials) credentials);
+ setSecurityProperty(userNode, P_PASSWORD, getValue(creds.getPassword()));
+ setSecurityProperty(userNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
+ parent.save();
+
+ log.info("User created: " + userID + "; " + userNode.getPath());
+ return UserImpl.create(userNode, this);
+ } catch (RepositoryException e) {
+ // something went wrong -> revert changes and rethrow
+ if (parent != null) {
+ parent.refresh(false);
+ log.debug("Failed to create new User, reverting changes.");
+ }
+ throw e;
+ } catch (NoSuchAlgorithmException e) {
+ throw new RepositoryException(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * Create a new <code>Group</code> with the given <code>groupName</code>.
+ * It will be created below the this UserManager's root Path.<br>
+ * If non-existant elements of the Path will be created as <code>Nodes</code>
+ * of type {@link #NT_REP_AUTHORIZABLE_FOLDER rep:AuthorizableFolder}
+ *
+ * @param principal
+ * @see UserManager#createGroup(Principal);
+ * @inheritDoc
+ */
+ public Group createGroup(Principal principal) throws RepositoryException {
+ return createGroup(principal, null);
+ }
+
+ /**
+ *
+ * @param principal
+ * @param intermediatePath
+ * @return
+ * @throws AuthorizableExistsException
+ * @throws RepositoryException
+ */
+ public Group createGroup(Principal principal, String intermediatePath) throws AuthorizableExistsException, RepositoryException {
+ if (principal == null) {
+ throw new IllegalArgumentException("Principal might not be null.");
+ }
+ if (hasAuthorizableOrReferee(principal)) {
+ throw new AuthorizableExistsException("Authorizable for '" + principal.getName() + "' already exists: ");
+ }
+
+ NodeImpl parent = null;
+ try {
+ String parentPath = getParentPath(intermediatePath, GROUPS_PATH);
+ parent = createParentNode(parentPath);
+ Name groupID = getGroupId(principal.getName());
+
+ NodeImpl groupNode = addSecurityNode(parent, groupID, NT_REP_GROUP);
+ setSecurityProperty(groupNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
+ parent.save();
+
+ log.info("Group created: " + groupID + "; " + groupNode.getPath());
+
+ return GroupImpl.create(groupNode, this);
+ } catch (RepositoryException e) {
+ if (parent != null) {
+ parent.refresh(false);
+ log.debug("newInstance new Group failed, revert changes on parent");
+ }
+ throw e;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Simple search for <code>User</code>s<br>
+ * The argument is a substring which must match the UserId or main
+ * Principal's name.
+ *
+ * @param simpleFilter substring to match against. The empty String matches
+ * all users.
+ * @return Iterator containing Authorizable-objects
+ * @throws RepositoryException
+ */
+ public Iterator findUsers(String simpleFilter) throws RepositoryException {
+ Set s = new HashSet(2);
+ s.add(P_USERID);
+ s.add(P_PRINCIPAL_NAME);
+ NodeIterator nodes = authResolver.findNodes(s, simpleFilter, NT_REP_USER, false, Long.MAX_VALUE);
+ return new AuthorizableIterator(nodes);
+ }
+
+ /**
+ * Simple search for a <code>Group</code>s<br>
+ * The argument is a substring which must match the Group's Principal name.
+ *
+ * @param simpleFilter substring to match against. The empty String matches
+ * all groups.
+ * @return Iterator containing Authorizable-objects
+ * @throws RepositoryException
+ */
+ public Iterator findGroups(String simpleFilter) throws RepositoryException {
+ NodeIterator nodes = authResolver.findNodes(P_PRINCIPAL_NAME, simpleFilter, NT_REP_GROUP, false);
+ return new AuthorizableIterator(nodes);
+ }
+
+ /**
+ *
+ * @param principal
+ * @return
+ * @throws RepositoryException
+ */
+ boolean hasAuthorizableOrReferee(Principal principal) throws RepositoryException {
+ Set s = new HashSet(2);
+ s.add(P_PRINCIPAL_NAME);
+ s.add(P_REFEREES);
+ NodeIterator res = authResolver.findNodes(s, principal.getName(), NT_REP_AUTHORIZABLE, true, 1);
+ return res.hasNext();
+ }
+
+ void setProtectedProperty(NodeImpl node, Name propName, Value[] values) throws RepositoryException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+ setSecurityProperty(node, propName, values);
+ node.save();
+ }
+
+ void removeProtectedItem(ItemImpl item, Node parent) throws RepositoryException, AccessDeniedException, VersionException {
+ removeSecurityItem(item);
+ parent.save();
+ }
+
+ /**
+ * Escape illegal JCR characters and test if a user exists that has the
+ * principals name as userId, which might happen if userID != principal-name.
+ * In this case: generate another ID for the group to be created.
+ *
+ * @param principalName to be used as hint for the groupid.
+ * @return a group id.
+ * @throws RepositoryException
+ */
+ private Name getGroupId(String principalName) throws RepositoryException {
+ String escHint = Text.escapeIllegalJcrChars(principalName);
+ String groupID = escHint;
+ int i = 0;
+ while (getAuthorizable(groupID) != null) {
+ // TODO: replace separator by "_" (see above)
+ groupID = escHint + "_GR_" + i;
+ i++;
+ }
+ return session.getQName(groupID);
+ }
+
+ /**
+ * TODO: Remove method as soon as searching group-by-id is fixed (see above).
+ */
+ private static String getGroupPrincipalName(String groupId) {
+ int pos = groupId.lastIndexOf("_GR_");
+ String pName = (pos > -1) ? groupId.substring(0, pos) : groupId;
+ return Text.unescapeIllegalJcrChars(pName);
+ }
+
+ private Value getValue(String strValue) throws RepositoryException {
+ return session.getValueFactory().createValue(strValue);
+ }
+
+ /**
+ * @return true if the given userID belongs to the administrator user.
+ */
+ boolean isAdminId(String userID) {
+ return adminId.equals(userID);
+ }
+
+ UserImpl getCurrentUser() {
+ try {
+ String uid = session.getUserID();
+ if (uid != null) {
+ AuthorizableImpl auth = (AuthorizableImpl) getAuthorizable(session.getUserID());
+ if (auth != null && !auth.isGroup()) {
+ return (UserImpl) auth;
+ }
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Internal error: unable to build current user path.", e.getMessage());
+ }
+ return null;
+ }
+
+ private String getCurrentUserPath() {
+ if (currentUserPath == null) {
+ StringBuffer b = new StringBuffer();
+ try {
+ String uid = session.getUserID();
+ if (uid != null) {
+ UserImpl user = getCurrentUser();
+ if (user != null) {
+ b.append(user.getNode().getPath());
+ }
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Internal error: unable to build current user path.", e.getMessage());
+ }
+ if (b.length() == 0) {
+ // fallback: default user-path
+ b.append(USERS_PATH);
+ }
+ currentUserPath = b.toString();
+ }
+ return currentUserPath;
+ }
+
+ private static String getParentPath(String hint, String root) {
+ StringBuffer b = new StringBuffer();
+ if (hint == null || !hint.startsWith(root)) {
+ b.append(root);
+ }
+ if (hint != null && hint.length() > 1) {
+ if (!hint.startsWith("/")) {
+ b.append("/");
+ }
+ b.append(hint);
+ }
+ return b.toString();
+ }
+
+ /**
+ * @param path to the authorizable node to be created
+ * @return
+ * @throws RepositoryException
+ */
+ private NodeImpl createParentNode(String path) throws RepositoryException {
+ NodeImpl parent = (NodeImpl) session.getRootNode();
+ String[] elem = path.split("/");
+ for (int i = 0; i < elem.length; i++) {
+ String name = elem[i];
+ if (name.length() < 1) {
+ continue;
+ }
+ Name nName = session.getQName(name);
+ if (!parent.hasNode(nName)) {
+ Name ntName;
+ if (i == 0) {
+ // rep:security node
+ ntName = NameConstants.NT_UNSTRUCTURED;
+ } else {
+ ntName = NT_REP_AUTHORIZABLE_FOLDER;
+ }
+ NodeImpl added = addSecurityNode(parent, nName, ntName);
+ parent.save();
+ parent = added;
+ } else {
+ parent = parent.getNode(nName);
+ }
+ }
+ return parent;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Inner class
+ */
+ private final class AuthorizableIterator implements Iterator {
+
+ private final Set served = new HashSet();
+
+ private Authorizable next;
+ private NodeIterator authNodeIter;
+
+ private AuthorizableIterator(NodeIterator authNodeIter) {
+ this.authNodeIter = authNodeIter;
+ next = seekNext();
+ }
+
+ //-------------------------------------------------------< Iterator >---
+ /**
+ * @see Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ /**
+ * @see Iterator#next()
+ */
+ public Object next() {
+ Authorizable authr = next;
+ if (authr == null) {
+ throw new NoSuchElementException();
+ }
+ next = seekNext();
+ return authr;
+ }
+
+ /**
+ * @see Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ //----------------------------------------------------------------------
+ private Authorizable seekNext() {
+ while (authNodeIter.hasNext()) {
+ NodeImpl node = (NodeImpl) authNodeIter.nextNode();
+ try {
+ if (!served.contains(node.getUUID())) {
+ Authorizable authr;
+ if (node.isNodeType(NT_REP_USER)) {
+ authr = UserImpl.create(node, UserManagerImpl.this);
+ } else if (node.isNodeType(NT_REP_GROUP)) {
+ authr = GroupImpl.create(node, UserManagerImpl.this);
+ } else {
+ log.warn("Ignoring unexpected nodetype: " + node.getPrimaryNodeType().getName());
+ continue;
+ }
+ served.add(node.getUUID());
+ return authr;
+ }
+ } catch (RepositoryException e) {
+ log.debug(e.getMessage());
+ // continue seeking next authorizable
+ }
+ }
+
+ // no next authorizable -> iteration is completed.
+ return null;
+ }
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd Wed Mar 19 06:56:13 2008
@@ -172,3 +172,54 @@
[rep:versionStorage]
+ * (nt:versionHistory) = nt:versionHistory protected multiple abort
+ * (rep:versionStorage) = rep:versionStorage protected multiple abort
+
+// -----------------------------------------------------------------------------
+// J A C K R A B B I T S E C U R I T Y
+// -----------------------------------------------------------------------------
+
+[rep:AccessControllable]
+ mixin
+ + rep:policy (rep:Policy) protected ignore
+
+[rep:Policy] abstract
+
+[rep:ACL] > rep:Policy
+ + * (rep:ACE) = rep:GrantACE protected ignore
+
+[rep:ACE]
+ - rep:principalName (string) protected mandatory
+ - rep:privileges (string) protected mandatory multiple
+ - rep:nodePath (path) protected
+ - rep:glob (string) protected
+ - * (undefined) protected
+
+[rep:GrantACE] > rep:ACE
+
+[rep:DenyACE] > rep:ACE
+
+[rep:AccessControl] > nt:base, rep:AccessControllable
+ + * (rep:AccessControl) protected ignore
+
+[rep:Authorizable] > nt:base, mix:referenceable abstract
+ + * (rep:Authorizable) = rep:Authorizable protected version
+ + * (rep:AuthorizableFolder) = rep:AuthorizableFolder protected version
+ - rep:principalName (string) protected mandatory
+ - rep:referees (string) protected multiple
+ - * (undefined)
+ - * (undefined) multiple
+
+[rep:Impersonatable]
+ mixin
+ - rep:impersonators (string) protected multiple
+
+[rep:User] > rep:Authorizable, rep:Impersonatable
+ - rep:userId (string) protected mandatory
+ - rep:password (string) mandatory
+
+[rep:Group] > rep:Authorizable
+ - rep:members (reference) protected multiple
+ < 'rep:Authorizable'
+
+[rep:AuthorizableFolder] > nt:base, mix:referenceable
+ + * (rep:Authorizable) = rep:User protected version
+ + * (rep:AuthorizableFolder) = rep:AuthorizableFolder protected version
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml Wed Mar 19 06:56:13 2008
@@ -398,4 +398,126 @@
</childNodeDefinition>
</nodeType>
+ <!-- internal security node types -->
+ <nodeType name="rep:AccessControllable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
+ <childNodeDefinition name="rep:policy" autoCreated="false" mandatory="false" onParentVersion="IGNORE" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:Policy</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </nodeType>
+
+ <nodeType name="rep:Policy" isMixin="false" hasOrderableChildNodes="false" primaryItemName="" abstract="true">
+ <supertypes>
+ <supertype>nt:base</supertype>
+ </supertypes>
+ </nodeType>
+
+ <nodeType name="rep:ACL" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>rep:Policy</supertype>
+ </supertypes>
+ <childNodeDefinition name="*" defaultPrimaryType="rep:GrantACE" autoCreated="false" mandatory="false" onParentVersion="IGNORE" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:ACE</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </nodeType>
+
+ <nodeType name="rep:ACE" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>nt:base</supertype>
+ </supertypes>
+ <propertyDefinition name="rep:principalName" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="false" />
+ <propertyDefinition name="rep:privileges" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="true" />
+ <propertyDefinition name="rep:nodePath" requiredType="Path" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="true" multiple="false" />
+ <propertyDefinition name="rep:glob" requiredType="String" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="true" multiple="false" />
+ <propertyDefinition name="*" requiredType="undefined" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="true" multiple="false" />
+ </nodeType>
+
+ <nodeType name="rep:GrantACE" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>rep:ACE</supertype>
+ </supertypes>
+ </nodeType>
+
+ <nodeType name="rep:DenyACE" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>rep:ACE</supertype>
+ </supertypes>
+ </nodeType>
+
+ <nodeType name="rep:AccessControl" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>nt:base</supertype>
+ <supertype>rep:AccessControllable</supertype>
+ </supertypes>
+ <childNodeDefinition name="*" autoCreated="false" mandatory="false" onParentVersion="IGNORE" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:AccessControl</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </nodeType>
+
+ <nodeType name="rep:Authorizable" isMixin="false" hasOrderableChildNodes="false" primaryItemName="" abstract="true">
+ <supertypes>
+ <supertype>nt:base</supertype>
+ <supertype>mix:referenceable</supertype>
+ </supertypes>
+ <childNodeDefinition name="*" defaultPrimaryType="rep:AuthorizableFolder" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:AuthorizableFolder</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ <childNodeDefinition name="*" defaultPrimaryType="rep:Authorizable" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:Authorizable</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ <propertyDefinition name="rep:principalName" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="false" />
+ <propertyDefinition name="rep:referees" requiredType="String" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="true" multiple="true" />
+ <propertyDefinition name="*" requiredType="undefined" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="false" />
+ <propertyDefinition name="*" requiredType="undefined" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="true" />
+ </nodeType>
+
+ <nodeType name="rep:Impersonatable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
+ <propertyDefinition name="rep:impersonators" requiredType="String" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="true" multiple="true" />
+ </nodeType>
+
+ <nodeType name="rep:User" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>rep:Authorizable</supertype>
+ <supertype>rep:Impersonatable</supertype>
+ </supertypes>
+ <propertyDefinition name="rep:userId" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="false" />
+ <propertyDefinition name="rep:password" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="false" multiple="false" />
+ </nodeType>
+
+ <nodeType name="rep:Group" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>rep:Authorizable</supertype>
+ </supertypes>
+ <propertyDefinition name="rep:members" requiredType="Reference" autoCreated="false" onParentVersion="COPY" protected="true" multiple="true">
+ <valueConstraints>
+ <valueConstraint>rep:Authorizable</valueConstraint>
+ </valueConstraints>
+ </propertyDefinition>
+ </nodeType>
+
+ <nodeType name="rep:AuthorizableFolder" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
+ <supertypes>
+ <supertype>nt:base</supertype>
+ <supertype>mix:referenceable</supertype>
+ </supertypes>
+ <childNodeDefinition name="*" defaultPrimaryType="rep:User" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:Authorizable</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ <childNodeDefinition name="*" defaultPrimaryType="rep:AuthorizableFolder" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="true" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>rep:AuthorizableFolder</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </nodeType>
</nodeTypes>
Modified: jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml Wed Mar 19 06:56:13 2008
@@ -15,9 +15,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.4//EN"
- "http://jackrabbit.apache.org/dtd/repository-1.4.dtd">
-<!-- Example Repository Configuration File -->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.5//EN"
+ "http://svn.apache.org/repos/asf/jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/config/repository-1.5.dtd">
+<!-- Example Repository Configuration File
+ Used by
+ - org.apache.jackrabbit.core.config.RepositoryConfigTest.java
+ -
+-->
<Repository>
<!--
virtual file system where the repository stores global state
@@ -32,16 +36,31 @@
-->
<Security appName="Jackrabbit">
<!--
+ security manager:
+ class: FQN of class implementing the JackrabbitSecurityManager interface
+ -->
+ <SecurityManager class="org.apache.jackrabbit.core.security.simple.SimpleSecurityManager" workspaceName="security">
+ <!--
+ workspace access:
+ class: FQN of class implementing the WorkspaceAccessManager interface
+ -->
+ <!-- <WorkspaceAccessManager class="..."/> -->
+ <!-- <param name="config" value="${rep.home}/security.xml"/> -->
+ </SecurityManager>
+
+ <!--
access manager:
class: FQN of class implementing the AccessManager interface
-->
- <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager">
+ <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">
<!-- <param name="config" value="${rep.home}/access.xml"/> -->
</AccessManager>
- <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule">
- <!-- anonymous user name ('anonymous' is the default value) -->
+ <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule">
+ <!-- anonymous user id -->
<param name="anonymousId" value="anonymous"/>
+ <!-- administrator user id (default value if param is missing is 'admin') -->
+ <param name="adminId" value="admin"/>
<!--
default user name to be used instead of the anonymous user
when no login credentials are provided (unset by default)
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,314 @@
+/*
+ * 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.api.security.principal;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <code>PrincipalManagerTest</code>...
+ */
+public class PrincipalManagerTest extends AbstractJCRTest {
+
+ private static Logger log = LoggerFactory.getLogger(PrincipalManagerTest.class);
+
+ private PrincipalManager principalMgr;
+ private Principal everyone;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!(superuser instanceof JackrabbitSession)) {
+ throw new NotExecutableException();
+ }
+ principalMgr = ((JackrabbitSession) superuser).getPrincipalManager();
+ everyone = principalMgr.getEveryone();
+ }
+
+ private static Principal[] getPrincipals(Session session) {
+ // TODO: get rid of SessionImpl dependency
+ Set princ = ((SessionImpl) session).getSubject().getPrincipals();
+ return (Principal[]) princ.toArray(new Principal[princ.size()]);
+ }
+
+ private static boolean isGroup(Principal p) {
+ return p instanceof java.security.acl.Group;
+ }
+
+ public void testGetEveryone() {
+ Principal principal = principalMgr.getEveryone();
+ assertTrue(principal != null);
+ assertTrue(isGroup(principal));
+ }
+
+ public void testSuperUserIsEveryOne() {
+ java.security.acl.Group everyone = (java.security.acl.Group) principalMgr.getEveryone();
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ if (!(pcpls[i].equals(everyone))) {
+ assertTrue(everyone.isMember(pcpls[i]));
+ }
+ }
+ }
+
+ public void testReadOnlyIsEveryOne() throws RepositoryException {
+ java.security.acl.Group everyone = (java.security.acl.Group) principalMgr.getEveryone();
+ Principal[] pcpls = getPrincipals(helper.getReadOnlySession());
+ for (int i = 0; i < pcpls.length; i++) {
+ if (!(pcpls[i].equals(everyone))) {
+ assertTrue(everyone.isMember(pcpls[i]));
+ }
+ }
+ }
+
+ public void testHasPrincipal() {
+ assertTrue(principalMgr.hasPrincipal(everyone.getName()));
+
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ assertTrue(principalMgr.hasPrincipal(pcpls[i].getName()));
+ }
+ }
+
+ public void testGetPrincipal() throws NoSuchPrincipalException {
+ Principal p = principalMgr.getPrincipal(everyone.getName());
+ assertEquals(everyone, p);
+
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ Principal pp = principalMgr.getPrincipal(pcpls[i].getName());
+ assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpls[i].getName(), pp.getName());
+ }
+ }
+
+ public void testGetPrincipalGetName() throws NoSuchPrincipalException {
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ Principal pp = principalMgr.getPrincipal(pcpls[i].getName());
+ assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpls[i].getName(), pp.getName());
+ }
+ }
+
+ public void testGetPrincipals() throws NoSuchPrincipalException {
+ PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ assertFalse(isGroup(p));
+ }
+ }
+
+ public void testGetGroupPrincipals() throws NoSuchPrincipalException {
+ PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_GROUP);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ assertTrue(isGroup(p));
+ }
+ }
+
+ public void testGetAllPrincipals() throws NoSuchPrincipalException {
+ PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ assertTrue(principalMgr.hasPrincipal(p.getName()));
+ assertEquals(principalMgr.getPrincipal(p.getName()), p);
+ }
+ }
+
+ public void testGroupMembers() {
+ PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (isGroup(p) && !p.equals(principalMgr.getEveryone())) {
+ Enumeration en = ((java.security.acl.Group) p).members();
+ while (en.hasMoreElements()) {
+ Principal memb = (Principal) en.nextElement();
+ assertTrue(principalMgr.hasPrincipal(memb.getName()));
+ }
+ }
+ }
+ }
+
+ public void testGroupMembership() throws NoSuchPrincipalException {
+ testMembership(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ testMembership(PrincipalManager.SEARCH_TYPE_GROUP);
+ testMembership(PrincipalManager.SEARCH_TYPE_ALL);
+ }
+
+ private void testMembership(int searchType) {
+ PrincipalIterator it = principalMgr.getPrincipals(searchType);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (p.equals(everyone)) {
+ for (PrincipalIterator membership = principalMgr.getGroupMembership(p); membership.hasNext();) {
+ Principal gr = membership.nextPrincipal();
+ assertTrue(isGroup(gr));
+ if (gr.equals(everyone)) {
+ fail("Everyone must never be a member of the EveryOne group.");
+ }
+ }
+ } else {
+ boolean atleastEveryone = false;
+ for (PrincipalIterator membership = principalMgr.getGroupMembership(p); membership.hasNext();) {
+ Principal gr = membership.nextPrincipal();
+ assertTrue(isGroup(gr));
+ if (gr.equals(everyone)) {
+ atleastEveryone = true;
+ }
+ }
+ assertTrue("All principals (except everyone) must be member of the everyone group.", atleastEveryone);
+
+ }
+ }
+ }
+
+ public void testGetMembersConsistentWithMembership() {
+ Principal everyone = principalMgr.getEveryone();
+ PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_GROUP);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (p.equals(everyone)) {
+ continue;
+ }
+
+ assertTrue(isGroup(p));
+
+ Enumeration members = ((java.security.acl.Group) p).members();
+ while (members.hasMoreElements()) {
+ Principal memb = (Principal) members.nextElement();
+
+ Principal group = null;
+ PrincipalIterator mship = principalMgr.getGroupMembership(memb);
+ while (mship.hasNext() && group == null) {
+ Principal gr = mship.nextPrincipal();
+ if (p.equals(gr)) {
+ group = gr;
+ }
+ }
+ assertNotNull("Group member " + memb.getName() + "does not reveal group upon getGroupMembership", p.getName());
+ }
+ }
+ }
+
+ public void testFindPrincipal() {
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ if (pcpls[i].equals(everyone)) {
+ continue;
+ }
+ Iterator it = principalMgr.findPrincipals(pcpls[i].getName());
+ // search must find at least a single principal
+ assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+ }
+ }
+
+ public void testFindPrincipalByType() {
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ if (pcpls[i].equals(everyone)) {
+ // special case covered by another test
+ continue;
+ }
+
+ if (isGroup(pcpls[i])) {
+ Iterator it = principalMgr.findPrincipals(pcpls[i].getName(),
+ PrincipalManager.SEARCH_TYPE_GROUP);
+ // search must find at least a single matching group principal
+ assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+ } else {
+ Iterator it = principalMgr.findPrincipals(pcpls[i].getName(),
+ PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ // search must find at least a single matching non-group principal
+ assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+ }
+ }
+ }
+
+ public void testFindPrincipalByTypeAll() {
+ Principal[] pcpls = getPrincipals(superuser);
+ for (int i = 0; i < pcpls.length; i++) {
+ if (pcpls[i].equals(everyone)) {
+ // special case covered by another test
+ continue;
+ }
+
+ PrincipalIterator it = principalMgr.findPrincipals(pcpls[i].getName(), PrincipalManager.SEARCH_TYPE_ALL);
+ PrincipalIterator it2 = principalMgr.findPrincipals(pcpls[i].getName());
+
+ // both search must reveal the same result and size
+ assertTrue(it.getSize() == it2.getSize());
+
+ Set s1 = new HashSet();
+ Set s2 = new HashSet();
+ while (it.hasNext() && it2.hasNext()) {
+ s1.add(it.nextPrincipal());
+ s2.add(it2.nextPrincipal());
+ }
+
+ assertEquals(s1, s2);
+ assertFalse(it.hasNext() && it2.hasNext());
+ }
+ }
+
+ public void testFindEveryone() {
+ Principal everyone = principalMgr.getEveryone();
+
+ boolean containedInResult = false;
+
+ // untyped search -> everyone must be part of the result set
+ PrincipalIterator it = principalMgr.findPrincipals(everyone.getName());
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (p.getName().equals(everyone.getName())) {
+ containedInResult = true;
+ }
+ }
+ assertTrue(containedInResult);
+
+ // search group only -> everyone must be part of the result set
+ containedInResult = false;
+ it = principalMgr.findPrincipals(everyone.getName(), PrincipalManager.SEARCH_TYPE_GROUP);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (p.getName().equals(everyone.getName())) {
+ containedInResult = true;
+ }
+ }
+ assertTrue(containedInResult);
+
+ // search non-group only -> everyone should not be part of the result set
+ containedInResult = false;
+ it = principalMgr.findPrincipals(everyone.getName(), PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ while (it.hasNext()) {
+ Principal p = it.nextPrincipal();
+ if (p.getName().equals(everyone.getName())) {
+ containedInResult = true;
+ }
+ }
+ assertFalse(containedInResult);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,39 @@
+/*
+ * 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.api.security.principal;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestAll extends TestCase {
+
+ /**
+ * Returns a <code>Test</code> suite that executes all tests inside this
+ * package.
+ *
+ * @return a <code>Test</code> suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("api.security.principal tests");
+
+ suite.addTestSuite(PrincipalManagerTest.class);
+
+ return suite;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/TestAll.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,126 @@
+/*
+ * 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.api.security.user;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.TestPrincipal;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.uuid.UUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <code>AbstractUserTest</code>...
+ */
+public abstract class AbstractUserTest extends AbstractJCRTest {
+
+ private static Logger log = LoggerFactory.getLogger(AbstractUserTest.class);
+
+ protected UserManager userMgr;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ userMgr = getUserManager(superuser);
+ }
+
+ protected static UserManager getUserManager(Session session) throws RepositoryException, NotExecutableException {
+ if (!(session instanceof JackrabbitSession)) {
+ throw new NotExecutableException();
+ }
+ try {
+ return ((JackrabbitSession) session).getUserManager();
+ } catch (UnsupportedRepositoryOperationException e) {
+ throw new NotExecutableException(e.getMessage());
+ } catch (UnsupportedOperationException e) {
+ throw new NotExecutableException(e.getMessage());
+ }
+ }
+
+ protected static Subject buildSubject(Principal p) {
+ return new Subject(true, Collections.singleton(p), Collections.EMPTY_SET, Collections.EMPTY_SET);
+ }
+
+ protected Principal getTestPrincipal() throws RepositoryException {
+ String pn = "any_principal" + UUID.randomUUID();
+ Principal p = new TestPrincipal(pn);
+ return p;
+ }
+
+ protected Credentials buildCredentials(String uid, String pw) {
+ // todo: retrieve creds impl from config
+ return new SimpleCredentials(uid, pw.toCharArray());
+ }
+
+ protected Credentials buildCredentials(Principal p) {
+ return buildCredentials(p.getName(), p.getName());
+ }
+
+ protected static Set getPrincipalSetFromSession(Session session) throws NotExecutableException {
+ if (session instanceof SessionImpl) {
+ return ((SessionImpl) session).getSubject().getPrincipals();
+ } else {
+ // TODO add fallback
+ throw new NotExecutableException();
+ }
+ }
+
+ protected User getTestUser(Session session) throws NotExecutableException, RepositoryException {
+ Set principals = getPrincipalSetFromSession(session);
+ for (Iterator it = principals.iterator(); it.hasNext();) {
+ try {
+ Authorizable auth = userMgr.getAuthorizable((Principal) it.next());
+ if (auth != null && !auth.isGroup()) {
+ return (User) auth;
+ }
+ } catch (RepositoryException e) {
+ // ignore
+ }
+ }
+ // should never happen. An Session should always have a corresponding User.
+ throw new RepositoryException("Unable to retrieve a User.");
+ }
+
+ protected Group getTestGroup(Session session) throws NotExecutableException, RepositoryException {
+ Set principals = getPrincipalSetFromSession(session);
+ for (Iterator it = principals.iterator(); it.hasNext();) {
+ try {
+ Authorizable auth = userMgr.getAuthorizable((Principal) it.next());
+ if (auth != null && auth.isGroup()) {
+ return (Group) auth;
+ }
+ } catch (RepositoryException e) {
+ // ignore
+ }
+ }
+ // may happen -> don't throw RepositoryException
+ throw new NotExecutableException("No Group found.");
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url