+/*
+ * 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.ldap.jcr;
import java.security.NoSuchAlgorithmException;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import javax.jcr.query.Query;
+import javax.jcr.version.VersionManager;
import javax.naming.Binding;
import javax.naming.Name;
import javax.naming.NamingException;
import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.ArgeoTypes;
import org.argeo.jcr.JcrUtils;
+import org.argeo.security.jcr.JcrSecurityModel;
import org.argeo.security.jcr.JcrUserDetails;
import org.springframework.ldap.core.ContextExecutor;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.ldap.UserDetailsContextMapper;
-/** Guarantees that LDAP and JCR are in line. */
+/** Makes sure that LDAP and JCR are in line. */
public class JcrLdapSynchronizer implements UserDetailsContextMapper,
ArgeoNames {
private final static Log log = LogFactory.getLog(JcrLdapSynchronizer.class);
// JCR
/** Admin session on the security workspace */
- private Session securitySession;
+ private Session nodeSession;
private Repository repository;
- private String securityWorkspace = "security";
-
private JcrProfileListener jcrProfileListener;
+ private JcrSecurityModel jcrSecurityModel = new JcrSecurityModel();
// Mapping
private Map<String, String> propertyToAttributes = new HashMap<String, String>();
public void init() {
try {
- securitySession = repository.login(securityWorkspace);
+ nodeSession = repository.login();
synchronize();
jcrProfileListener = new JcrProfileListener();
// noLocal is used so that we are not notified when we modify JCR
// from LDAP
- securitySession
+ nodeSession
.getWorkspace()
.getObservationManager()
.addEventListener(jcrProfileListener,
Event.PROPERTY_CHANGED | Event.NODE_ADDED, "/",
true, null, nodeTypes, true);
} catch (Exception e) {
- JcrUtils.logoutQuietly(securitySession);
+ JcrUtils.logoutQuietly(nodeSession);
throw new ArgeoException("Cannot initialize LDAP/JCR synchronizer",
e);
}
}
public void destroy() {
- JcrUtils.removeListenerQuietly(securitySession, jcrProfileListener);
- JcrUtils.logoutQuietly(securitySession);
+ JcrUtils.removeListenerQuietly(nodeSession, jcrProfileListener);
+ JcrUtils.logoutQuietly(nodeSession);
try {
rawLdapTemplate.executeReadOnly(new ContextExecutor() {
public Object executeWithContext(DirContext ctx)
});
// disable accounts which are not in LDAP
- Query query = securitySession
+ Query query = nodeSession
.getWorkspace()
.getQueryManager()
.createQuery(
Node userProfile = it.nextNode();
String path = userProfile.getPath();
if (!userPaths.contains(path)) {
+ log.warn("Path "
+ + path
+ + " not found in LDAP, disabling user "
+ + userProfile.getProperty(ArgeoNames.ARGEO_USER_ID)
+ .getString());
+ VersionManager versionManager = nodeSession.getWorkspace()
+ .getVersionManager();
+ versionManager.checkout(userProfile.getPath());
userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, false);
+ nodeSession.save();
+ versionManager.checkin(userProfile.getPath());
}
}
} catch (Exception e) {
- throw new ArgeoException("Cannot synchronized LDAP and JCR", e);
+ JcrUtils.discardQuietly(nodeSession);
+ log.error("Cannot synchronize LDAP and JCR", e);
+ // throw new ArgeoException("Cannot synchronize LDAP and JCR", e);
}
}
final String username, GrantedAuthority[] authorities) {
if (ctx == null)
throw new ArgeoException("No LDAP information for user " + username);
- Node userHome = JcrUtils.getUserHome(securitySession, username);
- if (userHome == null)
- throw new ArgeoException("No JCR information for user " + username);
+
+ // Node userProfile = SecurityJcrUtils.createUserProfileIfNeeded(
+ // securitySession, username);
+ Node userProfile = jcrSecurityModel.sync(nodeSession, username);
+ JcrUserDetails.checkAccountStatus(userProfile);
// password
SortedSet<?> passwordAttributes = ctx
}
try {
- return new JcrUserDetails(userHome.getNode(ARGEO_PROFILE),
- password, authorities);
+ return new JcrUserDetails(userProfile, password, authorities);
} catch (RepositoryException e) {
throw new ArgeoException("Cannot retrieve user details for "
+ username, e);
* @return path to user profile
*/
protected synchronized String mapLdapToJcr(DirContextAdapter ctx) {
- Session session = securitySession;
+ Session session = nodeSession;
try {
// process
String username = ctx.getStringAttribute(usernameAttribute);
- Node userHome = JcrUtils.createUserHomeIfNeeded(session, username);
- Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
- if (userHome.hasNode(ARGEO_PROFILE)) {
- userProfile = userHome.getNode(ARGEO_PROFILE);
-
- // compatibility with legacy, will be removed
- if (!userProfile.hasProperty(ARGEO_ENABLED)) {
- session.getWorkspace().getVersionManager()
- .checkout(userProfile.getPath());
- userProfile.setProperty(ARGEO_ENABLED, true);
- userProfile.setProperty(ARGEO_ACCOUNT_NON_EXPIRED, true);
- userProfile.setProperty(ARGEO_ACCOUNT_NON_LOCKED, true);
- userProfile
- .setProperty(ARGEO_CREDENTIALS_NON_EXPIRED, true);
- session.save();
- session.getWorkspace().getVersionManager()
- .checkin(userProfile.getPath());
- }
- } else {
- userProfile = JcrUtils.createUserProfile(securitySession,
- username);
- userProfile.getSession().save();
- userProfile.getSession().getWorkspace().getVersionManager()
- .checkin(userProfile.getPath());
- }
-
+ // Node userHome = SecurityJcrUtils.createUserHomeIfNeeded(session,
+ // username);
+ // Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
+ // if (userHome.hasNode(ARGEO_PROFILE)) {
+ // userProfile = userHome.getNode(ARGEO_PROFILE);
+ //
+ // // compatibility with legacy, will be removed
+ // if (!userProfile.hasProperty(ARGEO_ENABLED)) {
+ // session.getWorkspace().getVersionManager()
+ // .checkout(userProfile.getPath());
+ // userProfile.setProperty(ARGEO_ENABLED, true);
+ // userProfile.setProperty(ARGEO_ACCOUNT_NON_EXPIRED, true);
+ // userProfile.setProperty(ARGEO_ACCOUNT_NON_LOCKED, true);
+ // userProfile
+ // .setProperty(ARGEO_CREDENTIALS_NON_EXPIRED, true);
+ // session.save();
+ // session.getWorkspace().getVersionManager()
+ // .checkin(userProfile.getPath());
+ // }
+ // } else {
+ // userProfile = SecurityJcrUtils.createUserProfile(
+ // securitySession, username);
+ // userProfile.getSession().save();
+ // userProfile.getSession().getWorkspace().getVersionManager()
+ // .checkin(userProfile.getPath());
+ // }
+
+ Node userProfile = jcrSecurityModel.sync(session, username);
Map<String, String> modifications = new HashMap<String, String>();
for (String jcrProperty : propertyToAttributes.keySet())
ldapToJcr(userProfile, jcrProperty, ctx, modifications);
final JcrUserDetails jcrUserDetails = (JcrUserDetails) user;
try {
- Node userProfile = securitySession.getNode(
- jcrUserDetails.getHomePath()).getNode(ARGEO_PROFILE);
+ Node userProfile = nodeSession
+ .getNode(jcrUserDetails.getHomePath()).getNode(
+ ARGEO_PROFILE);
for (String jcrProperty : propertyToAttributes.keySet()) {
if (userProfile.hasProperty(jcrProperty)) {
ModificationItem mi = jcrToLdap(jcrProperty, userProfile
this.repository = repository;
}
- public void setSecurityWorkspace(String securityWorkspace) {
- this.securityWorkspace = securityWorkspace;
- }
-
public void setUserBase(String userBase) {
this.userBase = userBase;
}
this.passwordEncoder = passwordEncoder;
}
+ public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) {
+ this.jcrSecurityModel = jcrSecurityModel;
+ }
+
/** Listen to LDAP */
class LdapUserListener implements ObjectChangeListener,
NamespaceChangeListener, UnsolicitedNotificationListener {
Event event = events.nextEvent();
try {
if (Event.PROPERTY_CHANGED == event.getType()) {
- Property property = (Property) securitySession
+ Property property = (Property) nodeSession
.getItem(event.getPath());
String propertyName = property.getName();
Node userProfile = property.getParent();
modifications.get(name).add(mi);
}
} else if (Event.NODE_ADDED == event.getType()) {
- Node userProfile = securitySession.getNode(event
+ Node userProfile = nodeSession.getNode(event
.getPath());
String username = userProfile.getProperty(
ARGEO_USER_ID).getString();