]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java
First working remote node
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.ldap / src / main / java / org / argeo / security / ldap / jcr / JcrUserDetailsContextMapper.java
index ec4255af9a6a1777583f058fda55cae186e2e902..b6657f0c597998dc015290ac713d7e1e6651161e 100644 (file)
@@ -3,6 +3,7 @@ package org.argeo.security.ldap.jcr;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
@@ -13,7 +14,6 @@ import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -23,6 +23,7 @@ import org.argeo.jcr.JcrUtils;
 import org.argeo.security.jcr.JcrUserDetails;
 import org.springframework.ldap.core.DirContextAdapter;
 import org.springframework.ldap.core.DirContextOperations;
+import org.springframework.security.BadCredentialsException;
 import org.springframework.security.GrantedAuthority;
 import org.springframework.security.context.SecurityContextHolder;
 import org.springframework.security.providers.encoding.PasswordEncoder;
@@ -51,6 +52,9 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
        private PasswordEncoder passwordEncoder;
        private final Random random;
 
+       /** 0 is always sync */
+       private Long syncLatency = 10 * 60 * 1000l;
+
        public JcrUserDetailsContextMapper() {
                random = createRandom();
        }
@@ -108,23 +112,50 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
        }
 
        /** @return path to the user home node */
-       protected String mapLdapToJcr(String username, DirContextOperations ctx) {
+       protected synchronized String mapLdapToJcr(String username,
+                       DirContextOperations ctx) {
+               String usernameLdap = ctx.getStringAttribute(usernameAttribute);
+               // log.debug("username=" + username + ", usernameLdap=" + usernameLdap);
+               if (!username.equals(usernameLdap)) {
+                       String msg = "Provided username '" + username
+                                       + "' is different from username stored in LDAP '"
+                                       + usernameLdap + "'";
+                       // we log it because the exception may not be displayed
+                       log.error(msg);
+                       throw new BadCredentialsException(msg);
+               }
+
                try {
+
                        Node userHome = JcrUtils.getUserHome(session, username);
-                       if (userHome == null)
+                       boolean justCreatedHome = false;
+                       if (userHome == null) {
                                userHome = JcrUtils.createUserHome(session, homeBasePath,
                                                username);
+                               justCreatedHome = true;
+                       }
                        String userHomePath = userHome.getPath();
-                       Node userProfile = userHome.getNode(ARGEO_PROFILE);
+                       Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
                        if (userHome.hasNode(ARGEO_PROFILE)) {
                                userProfile = userHome.getNode(ARGEO_PROFILE);
+                               if (syncLatency != 0 && !justCreatedHome) {
+                                       Calendar lastModified = userProfile.getProperty(
+                                                       Property.JCR_LAST_MODIFIED).getDate();
+                                       long timeSinceLastUpdate = System.currentTimeMillis()
+                                                       - lastModified.getTimeInMillis();
+                                       if (timeSinceLastUpdate < syncLatency)// skip sync
+                                               return userHomePath;
+                               }
                        } else {
-                               userProfile = userHome.addNode(ARGEO_PROFILE);
-                               userProfile.addMixin(NodeType.MIX_TITLE);
-                               userProfile.addMixin(NodeType.MIX_CREATED);
-                               userProfile.addMixin(NodeType.MIX_LAST_MODIFIED);
+                               throw new ArgeoException("We should never reach this point");
+                               // userProfile = userHome.addNode(ARGEO_PROFILE);
+                               // userProfile.addMixin(NodeType.MIX_TITLE);
+                               // userProfile.addMixin(NodeType.MIX_CREATED);
+                               // userProfile.addMixin(NodeType.MIX_LAST_MODIFIED);
                        }
 
+                       session.getWorkspace().getVersionManager()
+                                       .checkout(userProfile.getPath());
                        for (String jcrProperty : propertyToAttributes.keySet())
                                ldapToJcr(userProfile, jcrProperty, ctx);
 
@@ -136,8 +167,10 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                                                .getProperty(ARGEO_FIRST_NAME).getString()
                                                + " "
                                                + userProfile.getProperty(ARGEO_LAST_NAME).getString());
-
+                       JcrUtils.updateLastModified(userProfile);
                        session.save();
+                       session.getWorkspace().getVersionManager()
+                                       .checkin(userProfile.getPath());
                        if (log.isTraceEnabled())
                                log.trace("Mapped " + ctx.getDn() + " to " + userProfile);
                        return userHomePath;
@@ -193,9 +226,16 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                                                                + jcrProperty);
 
                        String value = ctx.getStringAttribute(ldapAttribute);
-                       if (value == null)
-                               return;
-                       userProfile.setProperty(jcrProperty, value);
+                       String jcrValue = userProfile.hasProperty(jcrProperty) ? userProfile
+                                       .getProperty(jcrProperty).getString() : null;
+                       if (value != null && jcrValue != null) {
+                               if (!value.equals(jcrValue))
+                                       userProfile.setProperty(jcrProperty, value);
+                       } else if (value != null && jcrValue == null) {
+                               userProfile.setProperty(jcrProperty, value);
+                       } else if (value == null && jcrValue != null) {
+                               userProfile.setProperty(jcrProperty, value);
+                       }
                } catch (Exception e) {
                        throw new ArgeoException("Cannot map JCR property " + jcrProperty
                                        + " from LDAP", e);
@@ -269,4 +309,11 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                this.session = session;
        }
 
+       /**
+        * Time in ms during which the LDAP server is not checked. 0 is always sync.
+        */
+       public void setSyncLatency(Long syncLatency) {
+               this.syncLatency = syncLatency;
+       }
+
 }