Moves Spring Security / Jackrabbit synchronization in JcrSecurityModel
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / JackrabbitSecurityModel.java
index 4d7dbc935e9360d7589c8ae0e30cbf33bbb62535..25de2bea568d977b0f351ce2364f78f2ccb0666b 100644 (file)
@@ -1,5 +1,9 @@
 package org.argeo.security.jackrabbit;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -7,52 +11,83 @@ import javax.jcr.Session;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.jackrabbit.api.JackrabbitSession;
+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.argeo.ArgeoException;
 import org.argeo.jcr.ArgeoNames;
-import org.argeo.security.jcr.JcrSecurityModel;
+import org.argeo.security.jcr.SimpleJcrSecurityModel;
 
 /** Make sure that user authorizable exists before syncing user directories. */
-public class JackrabbitSecurityModel extends JcrSecurityModel {
+public class JackrabbitSecurityModel extends SimpleJcrSecurityModel {
        private final static Log log = LogFactory
                        .getLog(JackrabbitSecurityModel.class);
 
        @Override
-       public Node sync(Session session, String username) {
-               User user = null;
+       public Node sync(Session session, String username, List<String> roles) {
+               if (!(session instanceof JackrabbitSession))
+                       return super.sync(session, username, roles);
+
                try {
-                       if (session instanceof JackrabbitSession) {
-                               UserManager userManager = ((JackrabbitSession) session)
-                                               .getUserManager();
-                               user = (User) userManager.getAuthorizable(username);
-                               if (user != null) {
-                                       String principalName = user.getPrincipal().getName();
-                                       if (!principalName.equals(username)) {
-                                               log.warn("Jackrabbit principal is '" + principalName
-                                                               + "' but username is '" + username
-                                                               + "'. Recreating...");
-                                               user.remove();
-                                               user = userManager.createUser(username, "");
-                                       }
-                               } else {
-                                       // create new principal
-                                       userManager.createUser(username, "");
+                       UserManager userManager = ((JackrabbitSession) session)
+                                       .getUserManager();
+                       User user = (User) userManager.getAuthorizable(username);
+                       if (user != null) {
+                               String principalName = user.getPrincipal().getName();
+                               if (!principalName.equals(username)) {
+                                       log.warn("Jackrabbit principal is '" + principalName
+                                                       + "' but username is '" + username
+                                                       + "'. Recreating...");
+                                       user.remove();
+                                       user = userManager.createUser(username, "");
                                }
+                       } else {
+                               // create new principal
+                               user = userManager.createUser(username, "");
+                               log.info(username + " added as Jackrabbit user " + user);
                        }
-                       Node userProfile = super.sync(session, username);
-                       if (user != null && userProfile != null) {
-                               Boolean enabled = userProfile.getProperty(
-                                               ArgeoNames.ARGEO_ENABLED).getBoolean();
-                               if (enabled && user.isDisabled())
-                                       user.disable(null);
-                               else if (!enabled && !user.isDisabled())
-                                       user.disable(userProfile.getPath() + " is disabled");
-                       }
+
+                       // generic JCR sync
+                       Node userProfile = super.sync(session, username, roles);
+
+                       Boolean enabled = userProfile.getProperty(ArgeoNames.ARGEO_ENABLED)
+                                       .getBoolean();
+                       if (enabled && user.isDisabled())
+                               user.disable(null);
+                       else if (!enabled && !user.isDisabled())
+                               user.disable(userProfile.getPath() + " is disabled");
+
+                       // Sync Jackrabbit roles
+                       if (roles != null)
+                               syncRoles(userManager, user, roles);
+
                        return userProfile;
                } catch (RepositoryException e) {
                        throw new ArgeoException(
                                        "Cannot perform Jackrabbit specific operations", e);
                }
        }
+
+       /** Make sure Jackrabbit roles are in line with authentication */
+       void syncRoles(UserManager userManager, User user, List<String> roles)
+                       throws RepositoryException {
+               List<String> userGroupIds = new ArrayList<String>();
+               for (String role : roles) {
+                       Group group = (Group) userManager.getAuthorizable(role);
+                       if (group == null) {
+                               group = userManager.createGroup(role);
+                               log.info(role + " added as " + group);
+                       }
+                       if (!group.isMember(user))
+                               group.addMember(user);
+                       userGroupIds.add(role);
+               }
+
+               // check if user has not been removed from some groups
+               for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
+                       Group group = it.next();
+                       if (!userGroupIds.contains(group.getID()))
+                               group.removeMember(user);
+               }
+       }
 }