]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Update license headers
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
index 6b58c6f6903fcec70f7b0e5d8174d4f45be264e3..1109980696d61d110aab683ddbde53f937286d4b 100644 (file)
@@ -1,35 +1,48 @@
+/*
+ * Copyright (C) 2007-2012 Mathieu Baudier
+ *
+ * Licensed 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.argeo.security.jackrabbit;
 
 import java.security.Principal;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
-import javax.jcr.AccessDeniedException;
 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.lock.LockException;
-import javax.jcr.security.AccessControlException;
-import javax.jcr.security.AccessControlList;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.AccessControlPolicy;
-import javax.jcr.security.AccessControlPolicyIterator;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
 import javax.jcr.security.Privilege;
-import javax.jcr.version.VersionException;
 import javax.security.auth.Subject;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
 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.DefaultSecurityManager;
+import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.SecurityConstants;
-import org.apache.jackrabbit.core.security.SystemPrincipal;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
 import org.argeo.ArgeoException;
 import org.argeo.jcr.JcrUtils;
@@ -40,13 +53,23 @@ import org.springframework.security.GrantedAuthority;
 public class ArgeoSecurityManager extends DefaultSecurityManager {
        private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
 
+       /**
+        * Since this is called once when the session is created, we take the
+        * opportunity to make sure that Jackrabbit users and groups reflect Spring
+        * Security name and authorities.
+        */
        @Override
-       /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
        public String getUserID(Subject subject, String workspaceName)
                        throws RepositoryException {
                long begin = System.currentTimeMillis();
 
-               if (!subject.getPrincipals(SystemPrincipal.class).isEmpty())
+               if (log.isTraceEnabled())
+                       log.trace(subject);
+               // skip anonymous user (no rights)
+               if (!subject.getPrincipals(AnonymousPrincipal.class).isEmpty())
+                       return super.getUserID(subject, workspaceName);
+               // skip Jackrabbit system user (all rights)
+               if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty())
                        return super.getUserID(subject, workspaceName);
 
                Authentication authen;
@@ -65,10 +88,11 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                if (user == null) {
                        user = systemUm.createUser(userId, authen.getCredentials()
                                        .toString(), authen, null);
+                       JcrUtils.createUserHomeIfNeeded(getSystemSession(), userId);
+                       getSystemSession().save();
+                       setSecurityHomeAuthorizations(user);
                        log.info(userId + " added as " + user);
                }
-               
-               setHomeNodeAuthorizations(user);
 
                // process groups
                List<String> userGroupIds = new ArrayList<String>();
@@ -81,7 +105,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                        if (!group.isMember(user))
                                group.addMember(user);
                        userGroupIds.add(ga.getAuthority());
-
                }
 
                // check if user has not been removed from some groups
@@ -98,38 +121,45 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                return userId;
        }
 
-       protected void setHomeNodeAuthorizations(User user) {
-               // give all privileges on user home
-               // FIXME: fails on an empty repo
+       protected synchronized void setSecurityHomeAuthorizations(User user) {
+               // give read privileges on user security home
                String userId = "<not yet set>";
                try {
                        userId = user.getID();
                        Node userHome = JcrUtils.getUserHome(getSystemSession(), userId);
-                       if (userHome != null) {
-                               String path = userHome.getPath();
-                               AccessControlPolicy policy = null;
-                               AccessControlManager acm = getSystemSession()
-                                               .getAccessControlManager();
-                               AccessControlPolicyIterator policyIterator = acm
-                                               .getApplicablePolicies(path);
-                               if (policyIterator.hasNext()) {
-                                       policy = policyIterator.nextAccessControlPolicy();
-                               } else {
-                                       AccessControlPolicy[] existingPolicies = acm
-                                                       .getPolicies(path);
-                                       policy = existingPolicies[0];
-                               }
-                               if (policy instanceof AccessControlList) {
-                                       Privilege[] privileges = { acm
-                                                       .privilegeFromName(Privilege.JCR_ALL) };
-                                       ((AccessControlList) policy).addAccessControlEntry(
-                                                       user.getPrincipal(), privileges);
-                                       acm.setPolicy(path, policy);
-                               }
+                       if (userHome == null)
+                               throw new ArgeoException("No security home available for user "
+                                               + userId);
+
+                       String path = userHome.getPath();
+                       Principal principal = user.getPrincipal();
+
+                       JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession()
+                                       .getAccessControlManager();
+                       JackrabbitAccessControlPolicy[] ps = acm
+                                       .getApplicablePolicies(principal);
+                       if (ps.length == 0) {
+                               // log.warn("No ACL found for " + user);
+                               return;
                        }
+
+                       JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
+
+                       // add entry
+                       Privilege[] privileges = new Privilege[] { acm
+                                       .privilegeFromName(Privilege.JCR_READ) };
+                       Map<String, Value> restrictions = new HashMap<String, Value>();
+                       ValueFactory vf = getSystemSession().getValueFactory();
+                       restrictions.put("rep:nodePath",
+                                       vf.createValue(path, PropertyType.PATH));
+                       restrictions.put("rep:glob", vf.createValue("*"));
+                       list.addEntry(principal, privileges, true /* allow or deny */,
+                                       restrictions);
                } catch (Exception e) {
-                       log.warn("Cannot set authorization on user node for " + userId
-                                       + ": " + e.getMessage());
+                       e.printStackTrace();
+                       throw new ArgeoException(
+                                       "Cannot set authorization on security home for " + userId
+                                                       + ": " + e.getMessage());
                }
 
        }