]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Add dep folder
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
index 4af5d3f3d5a53997b79418e7a019d7c0f8e8cc4c..3450c75d8dbd51f9e9418814a82023e8cdd4a205 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 Mathieu Baudier
+ * Copyright (C) 2007-2012 Argeo GmbH
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,8 +17,11 @@ package org.argeo.security.jackrabbit;
 
 import java.security.Principal;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
@@ -31,16 +34,45 @@ 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.AMContext;
+import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
-import org.argeo.ArgeoException;
 import org.springframework.security.Authentication;
 import org.springframework.security.GrantedAuthority;
+import org.springframework.security.context.SecurityContextHolder;
 
-/** Integrates Spring Security and Jackrabbit Security user and roles. */
+/** Integrates Spring Security and Jackrabbit Security users and roles. */
 public class ArgeoSecurityManager extends DefaultSecurityManager {
-       private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
+       /** Legacy security sync */
+       final static String PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1 = "argeo.jackarabbit.securitySync.1.1";
+
+       private final static Log log = LogFactory
+                       .getLog(ArgeoSecurityManager.class);
+
+       private static Boolean synchronize = Boolean.parseBoolean(System
+                       .getProperty(PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1, "false"));
+
+       /** TODO? use a bounded buffer */
+       private Map<String, String> userRolesCache = Collections
+                       .synchronizedMap(new HashMap<String, String>());
+
+       @Override
+       public AccessManager getAccessManager(Session session, AMContext amContext)
+                       throws RepositoryException {
+               synchronized (getSystemSession()) {
+                       return super.getAccessManager(session, amContext);
+               }
+       }
+
+       @Override
+       public UserManager getUserManager(Session session)
+                       throws RepositoryException {
+               synchronized (getSystemSession()) {
+                       return super.getUserManager(session);
+               }
+       }
 
        /**
         * Since this is called once when the session is created, we take the
@@ -50,6 +82,15 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
        @Override
        public String getUserID(Subject subject, String workspaceName)
                        throws RepositoryException {
+               if (!synchronize) {
+                       Authentication authentication = SecurityContextHolder.getContext()
+                                       .getAuthentication();
+                       if (authentication != null)
+                               return authentication.getName();
+                       else
+                               return super.getUserID(subject, workspaceName);
+               }
+
                if (log.isTraceEnabled())
                        log.trace(subject);
                // skip anonymous user (no rights)
@@ -64,38 +105,52 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                Authentication authen;
                Set<Authentication> authens = subject
                                .getPrincipals(Authentication.class);
-               if (authens.size() == 0)
-                       throw new ArgeoException("No Spring authentication found in "
-                                       + subject);
-               else
+               String userId = super.getUserID(subject, workspaceName);
+               if (authens.size() == 0) {
+                       // make sure that logged-in user has a Principal, useful for testing
+                       // using an admin user
+                       UserManager systemUm = getSystemUserManager(null);
+                       if (systemUm.getAuthorizable(userId) == null)
+                               systemUm.createUser(userId, "");
+               } else {// Spring Security
                        authen = authens.iterator().next();
 
-               // sync Spring and Jackrabbit
-               syncSpringAndJackrabbitSecurity(authen);
+                       if (!userId.equals(authen.getName()))
+                               log.warn("User ID is '" + userId + "' but authen is "
+                                               + authen.getName());
+                       StringBuffer roles = new StringBuffer("");
+                       GrantedAuthority[] authorities = authen.getAuthorities();
+                       for (GrantedAuthority ga : authorities) {
+                               roles.append(ga.toString());
+                       }
+
+                       // do not sync if not changed
+                       if (userRolesCache.containsKey(userId)
+                                       && userRolesCache.get(userId).equals(roles.toString()))
+                               return userId;
 
-               return authen.getName();
+                       // sync Spring and Jackrabbit
+                       // workspace is irrelevant here
+                       UserManager systemUm = getSystemUserManager(null);
+                       syncSpringAndJackrabbitSecurity(systemUm, authen);
+                       userRolesCache.put(userId, roles.toString());
+               }
+               return userId;
        }
 
        /**
         * Make sure that the Jackrabbit security model contains this user and its
         * granted authorities
         */
-       protected void syncSpringAndJackrabbitSecurity(Authentication authen)
-                       throws RepositoryException {
+       static private void syncSpringAndJackrabbitSecurity(UserManager systemUm,
+                       Authentication authen) throws RepositoryException {
                long begin = System.currentTimeMillis();
 
-               // workspace is irrelevant here
-               UserManager systemUm = getSystemUserManager(null);
-
                String userId = authen.getName();
                User user = (User) systemUm.getAuthorizable(userId);
                if (user == null) {
                        user = systemUm.createUser(userId, authen.getCredentials()
                                        .toString(), authen, null);
-                       // SecurityJcrUtils.createUserHomeIfNeeded(getSystemSession(),
-                       // userId);
-                       // getSystemSession().save();
-                       // setSecurityHomeAuthorizations(user);
                        log.info(userId + " added as " + user);
                }
 
@@ -125,50 +180,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                                        + " ms");
        }
 
-       // protected synchronized void setSecurityHomeAuthorizations(User user) {
-       // // give read privileges on user security home
-       // String userId = "<not yet set>";
-       // try {
-       // userId = user.getID();
-       // Node userHome = SecurityJcrUtils.getUserHome(getSystemSession(), userId);
-       // 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) {
-       // e.printStackTrace();
-       // throw new ArgeoException(
-       // "Cannot set authorization on security home for " + userId
-       // + ": " + e.getMessage());
-       // }
-       //
-       // }
-
        @Override
        protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
                WorkspaceAccessManager wam = super
@@ -180,8 +191,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                        WorkspaceAccessManager {
                private final WorkspaceAccessManager wam;
 
-               // private String defaultWorkspace;
-
                public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
                        super();
                        this.wam = wam;
@@ -189,8 +198,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
 
                public void init(Session systemSession) throws RepositoryException {
                        wam.init(systemSession);
-                       // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
-                       // .getDefaultWorkspaceName();
                }
 
                public void close() throws RepositoryException {
@@ -198,22 +205,8 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
 
                public boolean grants(Set<Principal> principals, String workspaceName)
                                throws RepositoryException {
-                       // everybody has access to all workspaces
                        // TODO: implements finer access to workspaces
                        return true;
-
-                       // anonymous has access to the default workspace (required for
-                       // remoting which does a default login when initializing the
-                       // repository)
-                       // Boolean anonymous = false;
-                       // for (Principal principal : principals)
-                       // if (principal instanceof AnonymousPrincipal)
-                       // anonymous = true;
-                       //
-                       // if (anonymous && workspaceName.equals(defaultWorkspace))
-                       // return true;
-                       // else
-                       // return wam.grants(principals, workspaceName);
                }
        }