--- /dev/null
+/*******************************************************************************
+ * Copyright � Igor Barma, Alexandre Desoubeaux, Christian Martel, Eric Brun, Mathieu Amblard, Gwenael Gevet, Pierre Guillot, 2012
+ * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Alexandre Lefevre, Marc Salvat 2014-2016
+ * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Marc Salvat, Marc Suarez, Harifetra Ramamonjy 2017
+ *
+ * This file is part of the work and learning management system Pentila Nero.
+ *
+ * Pentila Nero is free software. You can redistribute it and/or modify since
+ * you respect the terms of either (at least one of the both license) :
+ * - under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * - the CeCILL-C as published by CeCILL-C; either version 1 of the
+ * License, or any later version
+ * - the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the license,
+ * or (at your option) any later version.
+ *
+ * There are special exceptions to the terms and conditions of the
+ * licenses as they are applied to this software. View the full text of
+ * the exception in file LICENSE-PROJECT.txt in the directory of this software
+ * distribution.
+ *
+ * Pentila Nero is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Licenses for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * and the CeCILL-C and the GNU Lesser General Public License along with
+ * Pentila Nero. If not, see :
+ * <http://www.gnu.org/licenses/> and
+ * <http://www.cecill.info/licences.fr.html>.
+ ******************************************************************************/
+package com.pentila.entSavoie.synchroLdap.impl;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.mail.internet.InternetAddress;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchResult;
+
+import com.liferay.contacts.util.OrganizationConstants;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import com.liferay.mail.service.MailServiceUtil;
+import com.liferay.portal.DuplicateUserEmailAddressException;
+import com.liferay.portal.NoSuchUserException;
+import com.liferay.portal.NoSuchUserGroupException;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.exception.SystemException;
+import com.liferay.portal.kernel.ldap.LDAPUtil;
+import com.liferay.portal.kernel.log.Log;
+import com.liferay.portal.kernel.log.LogFactoryUtil;
+import com.liferay.portal.kernel.log.LogUtil;
+import com.liferay.portal.kernel.mail.MailMessage;
+import com.liferay.portal.kernel.util.InstancePool;
+import com.liferay.portal.kernel.util.PrefsPropsUtil;
+import com.liferay.portal.kernel.util.PropertiesUtil;
+import com.liferay.portal.kernel.util.PropsKeys;
+import com.liferay.portal.kernel.util.StringPool;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.model.Company;
+import com.liferay.portal.model.CompanyConstants;
+import com.liferay.portal.model.Contact;
+import com.liferay.portal.model.Organization;
+import com.liferay.portal.model.Role;
+import com.liferay.portal.model.User;
+import com.liferay.portal.model.UserGroup;
+import com.liferay.portal.security.auth.ScreenNameGenerator;
+import com.liferay.portal.security.ldap.ENTAttributesTransformer;
+import com.liferay.portal.security.ldap.ENTAttributesTransformerFactory;
+import com.liferay.portal.security.ldap.LDAPConstants;
+import com.liferay.portal.security.ldap.PortalLDAPUtil;
+import com.liferay.portal.service.CompanyLocalServiceUtil;
+import com.liferay.portal.service.ContactLocalServiceUtil;
+import com.liferay.portal.service.OrganizationLocalServiceUtil;
+import com.liferay.portal.service.RoleLocalServiceUtil;
+import com.liferay.portal.service.ServiceContext;
+import com.liferay.portal.service.UserGroupLocalServiceUtil;
+import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
+import com.liferay.portal.service.UserLocalServiceUtil;
+import com.liferay.portal.util.PropsValues;
+import com.pentila.entSavoie.ENTRoleUtilFactory;
+import com.pentila.entSavoie.ENTRolesConstants;
+import com.pentila.entSavoie.ENTRolesUtil;
+import com.pentila.entSavoie.carnetDAdresses.model.Fiche;
+import com.pentila.entSavoie.carnetDAdresses.service.FicheLocalServiceUtil;
+import com.pentila.entSavoie.communityInfos.model.OrganizationCiteScolaire;
+import com.pentila.entSavoie.communityInfos.model.OrganizationMapping;
+import com.pentila.entSavoie.communityInfos.service.OrganizationCiteScolaireLocalServiceUtil;
+import com.pentila.entSavoie.communityInfos.service.OrganizationMappingLocalServiceUtil;
+import com.pentila.entSavoie.synchroLdap.exceptions.UserSynchronizationException;
+import com.pentila.entSavoie.userManagement.model.LDAPMapping;
+import com.pentila.entSavoie.userManagement.service.LDAPMappingLocalServiceUtil;
+import com.pentila.entSavoie.userProperties.model.NotifyConfig;
+import com.pentila.entSavoie.userProperties.model.UserContact;
+import com.pentila.entSavoie.userProperties.model.UserProperties;
+import com.pentila.entSavoie.userProperties.model.UserRelationship;
+import com.pentila.entSavoie.userProperties.service.NotifyConfigLocalServiceUtil;
+import com.pentila.entSavoie.userProperties.service.UserContactLocalServiceUtil;
+import com.pentila.entSavoie.userProperties.service.UserPropertiesLocalServiceUtil;
+import com.pentila.entSavoie.userProperties.service.UserRelationshipLocalServiceUtil;
+import com.pentila.entSavoie.userRelationship.UserRelationshipConstants;
+import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
+import com.pentila.entSavoie.utils.ENTOrganizationsUtil;
+
+/**
+ * Main class for synchronization process
+ * @author Cedric Lecarpentier
+ *
+ */
+public class SynchronizationManager {
+
+ static DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ private static Log _log = LogFactoryUtil.getLog(SynchronizationManager.class);
+
+ // The organization map <etabId - Organization>
+ private static Map<String, Organization> etabMap;
+
+ // The organization map <ou - ENTStructureUAI>
+ private static Map<String, String> etabOuMap;
+
+ // The user map <screenName - ENTPersonStructRattach>
+ private static Map<String, String> userRattachSchoolMap;
+
+ // The user map <screenName - LDAP attributes>
+ private static Map<String, Attributes> userAttributesMap;
+
+ // The user map <user DN - userId>
+ private static Map<String, Long> userEverImported;
+
+ private static long companyId;
+
+ // Is a synchronization already running ?
+ private static boolean synchronizationOnGoing;
+
+ // Used to generate report
+ private static List<User> createdUserList;
+
+ public static void runSynchronization() throws Exception {
+ runSynchronization(true);
+ }
+
+ /**
+ * Run the synchronization
+ * @param companyId
+ * @param forceSynchro
+ * @throws Exception
+ */
+ public static void runSynchronization(boolean force) throws Exception {
+
+ initCompanyId();
+
+ if (!isImportEnabled(companyId) && !force) {
+ _log.warn("Running synchronization is not possible because it is not allowed and not forced");
+ return;
+ }
+
+ if (synchronizationOnGoing) {
+ _log.warn("Running synchronization is not possible because a synchronization is already on going.");
+ return;
+ }
+
+ _log.info("Synchronization START");
+
+ Date startSynchroTime = new Date();
+
+ try {
+ initSynchronization();
+
+ buildUserMaps();
+
+ // Step 1 : user creation / update
+ runSynchroUserCreation();
+
+ // Step 2 : synchro groups
+ synchronizeGroups();
+
+ // Step 3 : update parent relationships for created users
+ updateParentRelations();
+
+ // Step 4 : Manage memberships
+ MembershipManager.manageMemberships(companyId);
+
+ // Send mail at synchronization's end
+ Date endSynchroTime = new Date();
+ sendSynchronizationEndMail(startSynchroTime, endSynchroTime);
+
+ // Prepare for reporting
+ processCreatedUsers();
+
+ SynchronizationReport.generateReportForSchoolManagers();
+ } catch (Exception e) {
+ _log.error("Error while synchronizing : ", e);
+ }
+ synchronizationOnGoing = false;
+
+ _log.info("Synchronization END");
+ }
+
+
+
+ /**
+ * Initializes all variables for synchronization
+ */
+ private static void initSynchronization () {
+
+ synchronizationOnGoing = true;
+ SynchronizationReport.initReport(companyId);
+
+ createdUserList = new ArrayList<User>();
+
+ userRattachSchoolMap = new HashMap<String, String>();
+ userAttributesMap = new HashMap<String, Attributes>();
+ userEverImported = new HashMap<String, Long>();
+
+ try {
+ initializeSchoolMaps();
+ initializeSchoolComplexes();
+ } catch (Exception e) {
+ _log.error("Error while initializing schools and school complexes");
+ }
+
+ }
+
+ /**
+ * Entry point for user synchronization
+ * @param companyId
+ * @return
+ */
+ public static void runSynchroUserCreation() {
+
+ long time0 = System.currentTimeMillis();
+ try {
+
+ // Count
+ int count = 0;
+ NamingEnumeration<SearchResult> enu2 = PortalLDAPUtil.getUsers(companyId, 0);
+ while (enu2.hasMoreElements()) {
+ enu2.nextElement();
+ count++;
+ }
+
+ _log.info("STARTING user synchronisation for "+count+" users ...");
+ NamingEnumeration<SearchResult> enu = PortalLDAPUtil.getUsers(companyId, 0);
+
+ // Loop through all LDAP users
+ int idx = 1;
+ while (enu.hasMoreElements()) {
+ try {
+ long timeUser1 = System.currentTimeMillis();
+ SearchResult result = enu.nextElement();
+ String nameInNameSpace = PortalLDAPUtil.getNameInNamespace(companyId, result);
+ Attributes attrs = PortalLDAPUtil.getUserAttributes(companyId, nameInNameSpace);
+ synchronizeUser (companyId, attrs, StringPool.BLANK, false);
+ long timeUser2 = System.currentTimeMillis();
+ _log.info("User synchronization took "+(timeUser2 - timeUser1)+" ms : "+idx+"/"+count);
+ idx++;
+
+ } catch (Exception e) {
+ _log.error("Error when synchronizing user");
+ }
+ }
+ enu.close();
+ } catch (Exception e) {
+ _log.error("Error when synchronizing users");
+ }
+
+ long time1 = System.currentTimeMillis();
+ int userSyncTime = (int)((time1 - time0)/60000);
+ SynchronizationReport.setUserSyncTime(userSyncTime);
+ _log.info(" Whole user synchronization took "+userSyncTime +" minutes");
+ }
+
+
+
+ /**
+ * Import a user
+ * @param companyId
+ * @param attrs
+ * @param password
+ * @param importGroupMembership
+ * @param onlyUpdate
+ * @return
+ * @throws Exception
+ */
+ public static User synchronizeUser (long companyId, Attributes attrs, String password, boolean manualCreation)
+ throws Exception {
+
+ _log.info("Synchronizing user ...");
+
+ // Set email default generated if not present
+ ENTAttributesTransformer attrsTransformer = ENTAttributesTransformerFactory.getInstance();
+ Attributes originalAttributes = attrs;
+ attrs = attrsTransformer.transformUser(attrs, companyId);
+
+ Properties userMappings = PropertiesUtil.load(PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_USER_MAPPINGS));
+
+ User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
+
+ boolean autoPassword = password.equals(StringPool.BLANK);
+ boolean autoScreenName = false;
+ ServiceContext serviceContext = new ServiceContext();
+
+
+ String screenName = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("screenName")).toLowerCase();
+ String emailAddress = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("emailAddress"));
+ String firstName = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("firstName"));
+ String middleName = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("middleName"));
+ String lastName = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("lastName"));
+ String jobTitle = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("jobTitle"));
+ boolean male = ((jobTitle.equals("M.") || jobTitle.equals("Mr"))?true:false);
+
+
+ if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
+ String fullName = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("fullName"));
+ String[] names = PortalLDAPUtil.splitFullName(fullName);
+ firstName = names[0];
+ middleName = names[1];
+ lastName = names[2];
+ }
+
+ String birthDay = LDAPUtil.getAttributeString(attrs, userMappings.getProperty("birthDate"));
+ int birthdayMonth;
+ int birthdayDay;
+ int birthdayYear;
+
+ if(!birthDay.equals("")) {
+ birthdayMonth = Integer.valueOf(birthDay.substring(4, 6))-1;
+ birthdayDay =Integer.valueOf(birthDay.substring(6, 8));
+ birthdayYear = Integer.valueOf(birthDay.substring(0, 4));
+ } else {
+ birthdayMonth = Calendar.JANUARY;
+ birthdayDay = 1;
+ birthdayYear = 1970;
+ }
+
+ if (Validator.isNull(screenName) || Validator.isNull(emailAddress)) {
+ _log.warn("Cannot add user because screen name and email address are required");
+ return null;
+ }
+
+ User user = null;
+ Date ldapUserModifiedDate = null;
+
+ try {
+
+ // Find corresponding portal user : search by screenName or email
+
+ String authType = PrefsPropsUtil.getString(companyId, PropsKeys.COMPANY_SECURITY_AUTH_TYPE, PropsValues.COMPANY_SECURITY_AUTH_TYPE);
+ if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
+ user = UserLocalServiceUtil.getUserByScreenName(companyId, screenName);
+ } else {
+ user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
+ }
+
+ // Skip if default user
+ if (user.isDefaultUser()) {
+ return user;
+ }
+
+ // detect users with firstname and lastname different from ldap
+ if (user != null) {
+ if (!firstName.equals(user.getFirstName()) || !lastName.equals(user.getLastName())) {
+ _log.info("+++++ Difference in names for userId "+user.getUserId()+" (screenName "+user.getScreenName()+") : LDAP is "+firstName + " "+lastName+", DB is "+user.getFirstName()+" "+user.getLastName()+", creation date="+new SimpleDateFormat("yyyy-MM-dd").format(user.getCreateDate()));
+ //user.setFirstName(firstName);
+ //user.setLastName(lastName);
+ //user.setGreeting("Bienvenue "+firstName+" "+lastName+" !");
+ //UserLocalServiceUtil.updateUser(user);
+ //Contact contact = user.getContact();
+ //contact.setFirstName(firstName);
+ //contact.setLastName(lastName);
+ //ContactLocalServiceUtil.updateContact(contact);
+ }
+ }
+
+ // User already exists in the Liferay database. Skip import if user
+ // fields have been already synced, if import is part of a scheduled
+ // import, or if the LDAP entry has never been modified.
+
+ String modifiedDate = LDAPUtil.getAttributeString(attrs, "modifyTimestamp");
+ try {
+ if (Validator.isNull(modifiedDate)) {
+ _log.info("LDAP entry never modified, skipping user " + user.getEmailAddress());
+ return user;
+ } else {
+ ldapUserModifiedDate = dateFormat.parse(modifiedDate);
+ }
+
+ if (ldapUserModifiedDate.equals(user.getModifiedDate())
+ && autoPassword && ENTMainUtilsLocalServiceUtil.isLDAPImportModifyDate(companyId)) {
+ _log.info("User is already synchronized, skipping user " + user.getEmailAddress());
+ return user;
+ }
+
+ } catch (ParseException pe) {
+ _log.error("Unable to parse LDAP modify timestamp " + modifiedDate, pe);
+ }
+
+ // Generate screenName
+ if (Validator.isNull(screenName)) {
+ autoScreenName = true;
+ ScreenNameGenerator screenNameGenerator = (ScreenNameGenerator) InstancePool.get(PropsValues.USERS_SCREEN_NAME_GENERATOR);
+ screenName = screenNameGenerator.generate(companyId, user.getUserId(), emailAddress);
+ }
+
+ _log.info("User "+firstName+" "+lastName+" exists in DB");
+
+ } catch (NoSuchUserException nsue) {
+ _log.error("User does not exist so create it");
+
+ } catch (DuplicateUserEmailAddressException dueae) {
+ _log.warn("Duplicate email adress for user "+screenName+" : "+ emailAddress);
+ return null;
+
+ } catch (Exception e) {
+ _log.error("Error updating user with screen name " + screenName + " and email address " + emailAddress, e);
+ return null;
+ }
+
+
+ // User creation (except for those with ENTValidAccount = 2)
+ String entValidAccount = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTVALIDACCOUNT);
+ if (user == null && entValidAccount.equals("1")) {
+ _log.info("+++++ Error : user has ENTValicAccount to 1 but does not exist");
+ }
+ if (user == null && !entValidAccount.equals("2")) {
+
+ try {
+ _log.info("Adding user "+firstName+" "+lastName+ " to portal.");
+ user = UserLocalServiceUtil.addUser(0, companyId,
+ autoPassword, password, password, autoScreenName,
+ screenName, emailAddress, 0, StringPool.BLANK, defaultUser.getLocale(), firstName,
+ middleName, lastName, 0, 0, male,
+ birthdayMonth, birthdayDay, birthdayYear, jobTitle,
+ null, null, null, null,
+ false, serviceContext);
+
+ if (createdUserList == null) {
+ createdUserList = new ArrayList<User>();
+ }
+ createdUserList.add(user);
+
+ Date today = new Date();
+ user.setLastLoginDate(today);
+ user.setModifiedDate(today);
+ user.setNew(false);
+ user.setPasswordModified(true);
+ // If user created in ENT
+ if (manualCreation) {
+ user.setPasswordReset(true);
+ }
+ else {
+ user.setPasswordReset(false);
+ }
+ user.setReminderQueryQuestion("@new@");
+ user.setReminderQueryAnswer("@new@");
+ UserLocalServiceUtil.updateUser(user);
+
+ // Create the user fiche
+ Fiche fiche = FicheLocalServiceUtil.createUserFiche(user, user);
+ _log.debug("create fiche : " + fiche.getFicheId() + " for user " + user.getUserId());
+
+ // Create default user properties
+ UserProperties up = UserPropertiesLocalServiceUtil.addUserProperties(user, false);
+ _log.debug("create user_properties : " + up.getUserPropertiesId() + " for user " + user.getUserId());
+
+ // Create default user notifications
+ NotifyConfig userNotificationConfig = NotifyConfigLocalServiceUtil.getOrCreateNotifyConfig(user.getUserId());
+ _log.debug("create user notification config : " + userNotificationConfig.getNotifyConfigId() + " for user " + user.getUserId());
+
+ } catch (DuplicateUserEmailAddressException dueae) {
+
+ _log.warn("Duplicate email adress for user "+screenName+" : "+ emailAddress);
+
+ try {
+ // In this case we create the account with a generated email and set the user's email in his preferences
+ String newEmail = screenName + ENTMainUtilsLocalServiceUtil.getENTOrgRootSuffixeMail(companyId);
+ _log.info("Adding user "+firstName+" "+lastName+ " to portal with changed email "+newEmail);
+ user = UserLocalServiceUtil.addUser(0, companyId,
+ autoPassword, password, password, autoScreenName,
+ screenName, newEmail, 0, StringPool.BLANK, defaultUser.getLocale(), firstName,
+ middleName, lastName, 0, 0, male,
+ birthdayMonth, birthdayDay, birthdayYear, jobTitle,
+ null, null, null, null,
+ false, serviceContext);
+
+ if (createdUserList == null) {
+ createdUserList = new ArrayList<User>();
+ }
+ createdUserList.add(user);
+
+ Date today = new Date();
+ user.setLastLoginDate(today);
+ user.setModifiedDate(today);
+ user.setNew(false);
+ user.setPasswordModified(true);
+ // If user created in ENT
+ if (manualCreation) {
+ user.setPasswordReset(true);
+ }
+ else {
+ user.setPasswordReset(false);
+ }
+ user.setReminderQueryQuestion("@new@");
+ user.setReminderQueryAnswer("@new@");
+ UserLocalServiceUtil.updateUser(user);
+
+ // Create the user fiche
+ Fiche fiche = FicheLocalServiceUtil.createUserFiche(user, user);
+ _log.debug("create fiche : " + fiche.getFicheId() + " for user " + user.getUserId());
+
+ // Create default user properties
+ UserProperties up = UserPropertiesLocalServiceUtil.addUserProperties(user, false);
+ _log.debug("create user_properties : " + up.getUserPropertiesId()+ " for user " + user.getUserId());
+
+ // Create default user notifications
+ NotifyConfig userNotificationConfig = NotifyConfigLocalServiceUtil.getOrCreateNotifyConfig(user.getUserId());
+ _log.debug("create user notification config : " + userNotificationConfig.getNotifyConfigId() + " for user " + user.getUserId());
+ } catch (Exception e) {
+ _log.error("Error while creating user "+user.getUserId() + " with new email", e);
+ }
+
+ } catch (Exception e) {
+ _log.error("Problem adding user with screen name " + screenName + " and email address " + emailAddress, e);
+ return null;
+ }
+ }
+
+
+ // Store the UID in the DB (LDAPMapping)
+ String uid = LDAPUtil.getAttributeString(attrs, "uid");
+ LDAPMapping ldapMapping = LDAPMappingLocalServiceUtil.fetchLDAPMapping(user.getUserId());
+ if (ldapMapping == null) {
+ ldapMapping = LDAPMappingLocalServiceUtil.createLDAPMapping(user.getUserId());
+ ldapMapping.setUID(uid);
+ LDAPMappingLocalServiceUtil.updateLDAPMapping(ldapMapping);
+ }
+
+ // Synchronize roles
+ RoleEnum roleEnum = synchronizeRoles(user, attrs);
+
+ Organization rattachSchool = null;
+ if (manualCreation) {
+ // Get 'ENTPersonStructRattach' attribute
+ String entPersonStructRattach = attrs.get("ENTPersonStructRattach").get().toString();
+ _log.info("Manual creation : entPersonStructRattach="+entPersonStructRattach);
+ rattachSchool = SynchronizationUtils.getSchoolFromClassName(entPersonStructRattach);
+
+ } else {
+ rattachSchool = getRattachSchool(user);
+ }
+ if (rattachSchool == null) {
+ _log.error("Error : No rattach school found for user "+user.getFullName());
+ return null;
+ }
+
+ // Update user status
+ updateUserActivation(user, attrs, rattachSchool, roleEnum);
+
+ //Synchronize school-level organizations
+ synchronizeSchoolLevelOrganizations(companyId, user, attrs, manualCreation);
+
+ // Update modified date
+ Date today = new Date();
+ UserLocalServiceUtil.updateModifiedDate(user.getUserId(), (ldapUserModifiedDate != null) ? ldapUserModifiedDate : today);
+
+ // Update birth date if needed
+ Date userBirthDay = user.getBirthday();
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(userBirthDay);
+ if (cal.get(Calendar.YEAR) != birthdayYear || cal.get(Calendar.MONTH) != birthdayMonth || cal.get(Calendar.DATE) != birthdayDay) {
+ cal.set(Calendar.YEAR, birthdayYear);
+ cal.set(Calendar.MONTH, birthdayMonth);
+ cal.set(Calendar.DATE, birthdayDay);
+ Date newBirthDay = cal.getTime();
+ _log.info("Updating bithday in contact for user "+user.getFullName()+" (id "+user.getUserId()+") to "+dateFormat.format(newBirthDay));
+ Contact contact = user.getContact();
+ contact.setBirthday(newBirthDay);
+ ContactLocalServiceUtil.updateContact(contact);
+ }
+
+ // Update email if changed
+ try {
+ if (!user.getEmailAddress().equals(emailAddress)) {
+ _log.info("About to update email for user "+user.getFullName()+" : "+emailAddress);
+ user.setEmailAddress(emailAddress);
+ UserLocalServiceUtil.updateUser(user);
+ _log.info("Updated email for user "+user.getFullName()+" : "+emailAddress);
+ }
+ } catch (Exception e) {
+ _log.error("Error while updating user email from "+user.getEmailAddress()+" to "+emailAddress+" (maybe duplicate account)");
+ }
+
+ // Update user properties
+ updateUserProperties(user, attrs);
+ updateContactProperties(user, originalAttributes);
+ updateServiceNotifications(user);
+
+ synchronizeParents(user, attrs);
+
+ return user;
+ }
+
+
+ /**
+ * Update UserProperties table
+ * @param userId
+ * @param attrs
+ */
+ private static void updateUserProperties(User user, Attributes attrs) {
+
+ try {
+ String ENTEleveBoursier = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEBOURSIER);
+ String ENTEleveTransport = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVETRANSPORT);
+ String ENTEleveRegime = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEREGIME);
+
+ UserProperties up = UserPropertiesLocalServiceUtil.getUserPropertiesByUserId(user.getUserId());
+ up.setGrantHolder(ENTEleveBoursier != null && ENTEleveBoursier.equals("O"));
+ up.setTransported(ENTEleveTransport != null && ENTEleveTransport.equals("O"));
+ up.setStatus((ENTEleveRegime != null) ? ENTEleveRegime : "");
+
+ UserPropertiesLocalServiceUtil.updateUserProperties(up);
+
+ } catch (Exception e) {
+ _log.error("Error while updating user properties for user "+user.getUserId());
+ }
+
+ }
+
+ /**
+ * Update UserContact table
+ * @param userId
+ * @param attrs
+ */
+ private static void updateContactProperties(User user, Attributes attrs) {
+
+ try {
+ String ENTPersonAdresse = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONADRESSE);
+ String ENTPersonAdresseDiffusion = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONADRESSEDIFFUSION);
+ String mail = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_MAIL);
+ String ENTPersonMailDiffusion = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONMAILDIFFUSION);
+ String homePhone = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_HOMEPHONE);
+ String proPhone = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_TELEPHONENUMBER);
+ String mobile = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_MOBILE);
+ String mobileSMS = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONMOBILESMS);
+
+ String suffixe = ENTMainUtilsLocalServiceUtil.getENTOrgRootSuffixeMail(user.getCompanyId());
+ boolean isMailValid = !user.getEmailAddress().equals(user.getScreenName()+suffixe);
+
+ if (!isMailValid) {
+ mail = "";
+ }
+
+ UserContact uc = UserContactLocalServiceUtil.getUserContactByUserId(user.getUserId());
+ uc.setAddress((ENTPersonAdresse != null)? ENTPersonAdresse : "");
+ uc.setIsAddressAuthorized(ENTPersonAdresseDiffusion != null && ENTPersonAdresseDiffusion.equals("O"));
+ uc.setMail((mail != null) ? mail : "");
+ uc.setIsMailAuthorized(ENTPersonMailDiffusion != null && ENTPersonMailDiffusion.equals("O"));
+ uc.setMobilePhone((mobile != null) ? mobile: "");
+ uc.setMobilePhoneSMS((mobileSMS != null)? mobileSMS : "");
+ uc.setProPhone((proPhone != null)? proPhone : "");
+ uc.setHomePhone((homePhone != null)? homePhone : "");
+ UserContactLocalServiceUtil.updateUserContact(uc);
+
+ } catch(Exception e) {
+ _log.error("Error while updating user contact properties for user "+user.getUserId());
+ }
+ }
+
+
+ /**
+ * Update NotifyConfig table
+ * @param user
+ * @param attrs
+ */
+ private static void updateServiceNotifications(User user) {
+
+ try {
+ // Force notifications to enable
+ if (ENTMainUtilsLocalServiceUtil.isEnableServicesNotifications(user.getCompanyId())) {
+ NotifyConfig userNotificationConfig = NotifyConfigLocalServiceUtil.getOrCreateNotifyConfig(user.getUserId());
+
+ userNotificationConfig.setNotifyCasier(true);
+ userNotificationConfig.setNotifyActu(true);
+ userNotificationConfig.setNotifyGrpDoc(true);
+ userNotificationConfig.setNotifyForum(true);
+ userNotificationConfig.setNotifyAgenda(true);
+ userNotificationConfig.setDigestPeriod(1);
+ userNotificationConfig.setUserId(user.getUserId());
+
+ userNotificationConfig.setActivate(true);
+
+ NotifyConfigLocalServiceUtil.updateNotifyConfig(userNotificationConfig);
+ }
+ } catch(Exception e) {
+ _log.error("Error while updating user notify config for user "+user.getUserId());
+ }
+ }
+
+
+ /**
+ * Create parent relationships for students
+ * @param user
+ * @param attrs
+ */
+ private static void synchronizeParents(User user, Attributes attrs) {
+
+ _log.info("Synchronizing parents for user "+user.getFullName());
+ try {
+ ENTRolesUtil entRolesUtil = ENTRoleUtilFactory.getInstance(user.getCompanyId());
+
+ // Get user academic code
+ // - if uid and entPersonJointure are equal, then there is no academic code used
+ // - else the uid is entPersonJointure + academic code
+ String uid = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_UID);
+ String entPersonJointure = LDAPUtil.getAttributeString(attrs, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONJOINTURE);
+ String academicCode = "";
+ if (!uid.equals(entPersonJointure)) {
+ academicCode = uid.substring(uid.length() - 3);
+ }
+
+
+ // Get previous user roles
+ Set<Role> userRoles = new HashSet<Role>();
+ CollectionUtils.addAll(userRoles, entRolesUtil.getENTRoles(user));
+
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS) != null){
+ for (int i=0; i<attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS).size(); i++) {
+
+ Role profileRole = entRolesUtil.getRole(attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS).get(i).toString());
+
+ // Student case : update parents
+ if (profileRole.getName().equals(ENTRolesConstants.NATIONAL_1)){
+
+ List<UserRelationship> existingRelations = UserRelationshipLocalServiceUtil.getUserRelationshipByFromUserIdRelationType(user.getUserId(), UserRelationshipConstants.PARENT_RELATION);
+ List<UserRelationship> copyeExistingRelations = new ArrayList<UserRelationship>(existingRelations);
+
+ // Get ENTElevePersRelEleve attributes
+ // New field in ENT2D format. Old fields are still provided in XML files but are not parsed here.
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEPERSRELELEVE) != null) {
+
+ // Loop over parents
+ for (int k=0; k<attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEPERSRELELEVE).size(); k++) {
+ String parentDN = attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEPERSRELELEVE).get(k).toString();
+
+ // ENTElevePersRelEleve is the new parent format : for example uid=5841069$5$1$1$0$0,ou=people,dc=ent,dc=pentila,dc=com
+ // Build newParentDn in this format: uid=5841069024,ou=people,dc=ent,dc=pentila,dc=com
+ String newParentDn = "";
+ String[] parentDnTab = parentDN.split(",");
+ if (parentDnTab != null && parentDnTab.length > 0) {
+ String[] parentUidTab = parentDnTab[0].split("\\$");
+ if (parentUidTab != null && parentUidTab.length > 0) {
+ newParentDn = parentUidTab[0] + academicCode + parentDN.substring(parentDnTab[0].length());
+ }
+ }
+
+ if (newParentDn.equals("")) {
+ _log.error("Error : ENTElevePersRelEleve attribute has an incorrect value : "+parentDN);
+ continue;
+ }
+
+ try {
+ // Check if existing relation. If not => create it with 'toUserId=0'
+ _log.info("Checking for student "+user.getUserId()+" if parent "+newParentDn+" exists");
+ UserRelationship rel = UserRelationshipLocalServiceUtil.checkUserRelationshipByFromUserIdToUserSconetIdRelationType(user.getUserId(), newParentDn, UserRelationshipConstants.PARENT_RELATION);
+ if (copyeExistingRelations.contains(rel)) {
+ copyeExistingRelations.remove(rel);
+ }
+ } catch (Exception e) {
+ _log.error("Error when updating relations for user "+user.getFullName(), e);
+ }
+ }
+ }
+
+
+ // Delete obsolete relations
+ for (UserRelationship oldRelation: copyeExistingRelations) {
+ UserRelationshipLocalServiceUtil.deleteUserRelationship(oldRelation);
+ }
+
+ } // End student case
+
+ }
+ }
+
+ } catch (Exception e) {
+ _log.error("Error when synchronizing parents for user "+user.getFullName(), e);
+ }
+
+ }
+
+ /**
+ * Update user activation
+ * @param user
+ * @param attrs
+ * @param school
+ * @param roleEnum
+ * @throws NamingException
+ * @throws PortalException
+ * @throws SystemException
+ */
+ public static void updateUserActivation(User user, Attributes attrs, Organization school, RoleEnum roleEnum) throws NamingException, PortalException, SystemException {
+
+ try {
+ Boolean active = null;
+
+ String entValidAccount = LDAPUtil.getAttributeString(attrs, "ENTValidAccount");
+ active = !entValidAccount.equals("1") && !entValidAccount.equals("2");
+
+ if (!active){
+ if (user.isActive()) {
+ UserLocalServiceUtil.updateStatus(user.getUserId(), WorkflowConstants.STATUS_INACTIVE);
+ SynchronizationReport.notifyDeactivation(school, user, roleEnum);
+ }
+ }
+ else {
+ if (!user.isActive()) {
+ UserLocalServiceUtil.updateStatus(user.getUserId(), WorkflowConstants.STATUS_APPROVED);
+ SynchronizationReport.notifyReactivation(school, user, roleEnum);
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error when updating activation for user "+user.getFullName());
+ }
+ }
+
+
+
+ /**
+ * Synchronizes user roles
+ * @param user
+ * @param attrs
+ * @param collegeName
+ * @throws UserSynchronizationException
+ * @throws PortalException
+ * @throws SystemException
+ * @throws NamingException
+ */
+ private static RoleEnum synchronizeRoles(final User user, final Attributes attrs) {
+
+ RoleEnum res = null;
+
+ try {
+ ENTRolesUtil entRolesUtil = ENTRoleUtilFactory.getInstance(user.getCompanyId());
+
+ // Get previous user roles
+ Set<Role> userRoles = new HashSet<Role>();
+ CollectionUtils.addAll(userRoles, entRolesUtil.getENTRoles(user));
+
+ // Loop over LDAP attributes 'ENTPersonProfils'
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS) != null){
+ for (int i=0; i<attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS).size(); i++) {
+
+ Role profileRole = entRolesUtil.getRole(attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONPROFILS).get(i).toString());
+ if (userRoles.contains(profileRole)) {
+ userRoles.remove(profileRole);
+ } else {
+ long rId[] = {profileRole.getRoleId()};
+ RoleLocalServiceUtil.addUserRoles(user.getUserId(), rId);
+ }
+
+ if (profileRole.getName().equals(ENTRolesConstants.NATIONAL_1)) {
+ res = RoleEnum.STUDENT_ROLE;
+ } else if (profileRole.getName().equals(ENTRolesConstants.NATIONAL_2)) {
+ res = RoleEnum.PARENT_ROLE;
+ } else if (profileRole.getName().equals(ENTRolesConstants.NATIONAL_3) || profileRole.getName().equals(ENTRolesConstants.NATIONAL_26)) {
+ res = RoleEnum.TEACHER_ROLE;
+ }
+
+ }
+ } // End loop over ENTPersonProfils
+
+ // Loop over 'ENTPersonFonctions' attributes
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS)!=null){
+ for (int i=0; i<attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).size(); i++) {
+ String[] roleDescription = entRolesUtil.translateENTPersonFonctionsToRoleName(attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).get(i).toString());
+ if (roleDescription!= null) {
+ Role profileRole = entRolesUtil.getRole(roleDescription[0], roleDescription[1]);
+
+ if (userRoles.contains(profileRole)) {
+ userRoles.remove(profileRole);
+ } else {
+ long rId[] = {profileRole.getRoleId()};
+ RoleLocalServiceUtil.addUserRoles(user.getUserId(), rId);
+ }
+ }
+ }
+ }
+
+ // If user has role Nat_23, add role Nat_4
+ Role nat23Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_23);
+ Role nat4Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_4);
+ if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat23Role.getRoleId())) {
+ if (userRoles.contains(nat4Role)) {
+ userRoles.remove(nat4Role);
+ } else {
+ long roleIds[] = {nat4Role.getRoleId()};
+ RoleLocalServiceUtil.addUserRoles(user.getUserId(), roleIds);
+ _log.info("Add role Nat4 to user "+user.getFullName());
+ }
+ }
+
+ // If user is National_4 => add it to GROUP_ADMIN
+ if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat4Role.getRoleId())) {
+
+ Role grpAdminRole = entRolesUtil.getRole("Group_admin");
+ if (userRoles.contains(grpAdminRole)) {
+ userRoles.remove(grpAdminRole);
+ } else {
+ long roleIds[] = {grpAdminRole.getRoleId()};
+ RoleLocalServiceUtil.addUserRoles(user.getUserId(), roleIds);
+ _log.info("Add role Group_admin to user "+user.getFullName());
+ }
+ }
+
+ // Remove obsolete roles
+ for (Role r : userRoles) {
+ RoleLocalServiceUtil.unsetUserRoles(user.getUserId(), new long[]{r.getRoleId()});
+ }
+
+
+ // Add default role if user has no role
+ Role[] endedRoles = entRolesUtil.getENTRoles(user);
+ if (endedRoles.length == 0) {
+ // on ajoute le role par defaut si possible
+ String default_role = ENTMainUtilsLocalServiceUtil.getENTSynchroDefaultRole(user.getCompanyId());
+ if (!default_role.equals("")) {
+ try {
+ Role defaultRole = entRolesUtil.getRole(default_role);
+ long rId[] = {defaultRole.getRoleId()};
+ RoleLocalServiceUtil.addUserRoles(user.getUserId(), rId);
+ }
+ catch(Exception exc) {
+ _log.error("Error when adding default role to user "+user.getFullName());
+ }
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error when synchronizing roles for user "+user.getFullName()+" (id "+user.getUserId()+")", e);
+ }
+
+ // Default RoleEnum is OTHER_ROLE
+ if (res == null) {
+ res = RoleEnum.OTHER_ROLE;
+ }
+
+ return res;
+ }
+
+
+
+
+
+ public static UserGroup synchronizeGroup(long companyId, Attributes attrs, String fullGroupDn) throws Exception {
+
+ ENTAttributesTransformer attrsTransformer = ENTAttributesTransformerFactory.getInstance();
+
+ attrs = attrsTransformer.transformGroup(attrs);
+
+ Properties groupMappings = PortalLDAPUtil.getGroupMappings(companyId);
+
+ LogUtil.debug(_log, groupMappings);
+
+ String groupName = LDAPUtil.getAttributeString(attrs, groupMappings.getProperty("groupName")).toLowerCase();
+ String description = LDAPUtil.getAttributeString(attrs, groupMappings.getProperty("description"));
+
+ // Check if empty LDAP group
+ Boolean emptyLDAPGrp = PortalLDAPUtil.isEmptyENTLDAPGroup(groupMappings, attrs);
+ if (emptyLDAPGrp) {
+ // TODO
+ //removeEmptyLdapGroup(companyId, groupName);
+ }
+
+ Date ldapGroupModifiedDate = null;
+ String modifiedDate = LDAPUtil.getAttributeString(attrs, "modifyTimestamp");
+ try {
+ if (!Validator.isNull(modifiedDate)) {
+ ldapGroupModifiedDate = dateFormat.parse(modifiedDate);
+ }
+ } catch (ParseException pe) {
+ }
+
+ // Get or create user group
+ UserGroup userGroup = getOrCreateUserGroup(companyId, groupName, description);
+
+
+ // Import users and membership
+ if (userGroup != null) {
+ // Get'member' user list
+ Attribute memberList = attrs.get(groupMappings.getProperty("user"));
+
+ if (memberList != null) {
+ List<String> membersToRemoveFromGroup = getExpiredUsers(companyId, userGroup.getUserGroupId(), memberList, ldapGroupModifiedDate);
+
+ // Previous method returned the list of members of the group that do not exist anymore in people branch
+ // Let's remove these members from the current group
+ try {
+ if (membersToRemoveFromGroup != null && membersToRemoveFromGroup.size() > 0) {
+
+ Attribute memberListCopy = (Attribute) memberList.clone();
+ int countUser = memberList.size();
+
+ // Loop over existing members
+ boolean isMemberListChanged = false;
+ for (int i = 0; i < countUser; i++) {
+ String attrValue = (String) memberList.get(i);
+
+ // Check if the current member belong to the 'toRemove' list
+ for (String memberToRemove : membersToRemoveFromGroup) {
+ if (memberToRemove.equals(attrValue)) {
+ _log.info("Removing user : "+memberToRemove + " from group "+fullGroupDn);
+ isMemberListChanged = true;
+ memberListCopy.remove(attrValue);
+ }
+ }
+ }
+ if (isMemberListChanged) {
+ ModificationItem[] modifItemArray = new ModificationItem[1];
+ ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, memberListCopy);
+ modifItemArray[0] = item;
+ _log.info("Modifying attribute 'members' for group "+fullGroupDn);
+
+ PortalLDAPUtil.getContext(companyId).modifyAttributes(fullGroupDn, modifItemArray);
+ }
+ }
+ } catch (Exception e) {
+ _log.error("An error occured during member deletion in group "+fullGroupDn+" (group must not have 0 members)");
+ }
+ }
+ }
+
+ return userGroup;
+ }
+
+ private static UserGroup getOrCreateUserGroup(long companyId, String groupName, String description) {
+
+ UserGroup userGroup = null;
+
+ try {
+ userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId, groupName);
+ UserGroupLocalServiceUtil.updateUserGroup(companyId, userGroup.getUserGroupId(), groupName, description);
+
+ } catch (NoSuchUserGroupException nsuge) {
+ _log.info("Adding user group to portal " + groupName);
+
+ try {
+ long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
+ userGroup = UserGroupLocalServiceUtil.addUserGroup(defaultUserId, companyId, groupName, description);
+ } catch (Exception e) {
+ _log.warn("Could not create user group " + groupName);
+ }
+ } catch (Exception e) {
+ _log.error("Error when getting or creating usergroup with groupName="+groupName);
+ }
+ return userGroup;
+ }
+
+ /**
+ * Remove an empty LDAP group, remove its associated UserGroup and Organization, by previoulsy removing users from them
+ * @param companyId
+ * @param groupName
+ */
+ private static void removeEmptyLdapGroup(long companyId, String groupName) {
+
+ System.out.println("Remove empty LDAP group "+groupName);
+ long time0 = System.currentTimeMillis();
+ SynchronizationReport.addEmptyGroup();
+ UserGroup userGroupToDelete = null;
+ String orgNameToDelete = "";
+ try {
+ // le groupe est vide donc on supprime
+ userGroupToDelete = UserGroupLocalServiceUtil.getUserGroup(companyId, groupName);
+
+ orgNameToDelete = SynchronizationUtils.getOrgName(userGroupToDelete);
+ System.out.println("Delete group cause empty LDAP: org name is " + orgNameToDelete);
+
+ // Remove users from this usergroup in DB
+ System.out.println("Deleting all users belonging to obsolete user group "+userGroupToDelete.getName());
+ UserLocalServiceUtil.clearUserGroupUsers(userGroupToDelete.getUserGroupId());
+
+ // Remove the usergroup itself
+ System.out.println("Deleting obsolete user group "+userGroupToDelete.getName());
+ UserGroupLocalServiceUtil.deleteUserGroup(userGroupToDelete);
+
+ } catch (NoSuchUserGroupException nsuge) {
+ return;
+ } catch (Exception e) {
+ _log.error("Error when deleting user group "+groupName);
+ }
+
+ if (orgNameToDelete.isEmpty()) {
+ return ;
+ }
+
+ long time1 = System.currentTimeMillis();
+ System.out.println("Delete user group took "+(time1 - time0)+" ms");
+ System.out.println("About to delete organization "+orgNameToDelete);
+ Organization org = null;
+ try {
+ org = OrganizationLocalServiceUtil.getOrganization(companyId, orgNameToDelete);
+ long[] userIdsToRemoveFromOrg = UserLocalServiceUtil.getOrganizationUserIds(org.getOrganizationId());
+ _log.info("This organization has "+userIdsToRemoveFromOrg.length +" members that we remove first");
+ UserLocalServiceUtil.unsetOrganizationUsers(org.getOrganizationId(), userIdsToRemoveFromOrg);
+ OrganizationLocalServiceUtil.deleteOrganization(org);
+ _log.info("Organization deleted : "+orgNameToDelete);
+
+ } catch (Exception e) {
+ }
+
+ _log.info("About to delete organization " + orgNameToDelete + OrganizationConstants.ORG_SUFFIX_PARENTS);
+ Organization orgParent = null;
+ try {
+ orgParent = OrganizationLocalServiceUtil.getOrganization(companyId, orgNameToDelete + OrganizationConstants.ORG_SUFFIX_PARENTS);
+ long[] userIdsToRemoveFromOrg = UserLocalServiceUtil.getOrganizationUserIds(orgParent.getOrganizationId());
+ _log.info("This parent organization has "+userIdsToRemoveFromOrg.length +" members that we remove first");
+ UserLocalServiceUtil.unsetOrganizationUsers(orgParent.getOrganizationId(), userIdsToRemoveFromOrg);
+ OrganizationLocalServiceUtil.deleteOrganization(orgParent);
+ _log.info("Organization parent deleted : " + orgNameToDelete + OrganizationConstants.ORG_SUFFIX_PARENTS);
+
+ } catch (Exception e) {
+ }
+ long time2 = System.currentTimeMillis();
+ System.out.println("Delete organization took "+(time2 - time1)+" ms");
+
+ return;
+
+ }
+
+
+ private static List<String> getExpiredUsers(long companyId, long userGroupId, Attribute memberList, Date ldapGroupModifiedDate) throws Exception {
+
+ List<String> membersToRemoveFromGroup = new ArrayList<String>();
+
+ long time0 = System.currentTimeMillis();
+ int nbUsersProcessed = 0;
+ int countUser = memberList.size();
+
+ // Loop over member list
+ for (int i = 0; i < countUser; i++) {
+ nbUsersProcessed++;
+ if (nbUsersProcessed%1000==0) {
+ _log.info("Processed "+nbUsersProcessed + "/" + countUser + " users in this group");
+ }
+
+ // Find user in LDAP
+ String fullUserDN = (String) memberList.get(i);
+ User user = null;
+
+ // Empty group (with fake_user only)
+ if (fullUserDN.equals("uid=system_fake_user") ) {
+ continue;
+ }
+
+ // Get user if he was already imported during this sync process
+ if (userEverImported.containsKey(fullUserDN)) {
+ Long userTmpId = userEverImported.get(fullUserDN);
+ if (userTmpId == null) {
+ continue;
+ }
+ user = UserLocalServiceUtil.getUser(userTmpId);
+ }
+
+ if (user == null) {
+
+ // Get user attributes
+ try {
+ PortalLDAPUtil.getUserAttributes(companyId, fullUserDN);
+ } catch (NameNotFoundException nnfe) {
+
+ _log.info("LDAP user not found with fullUserDN " + fullUserDN + " : adding it to deletion list from current group");
+
+ // Delete 'member' attribute from the group in LDAP if the user does not exist anymore (deleted because ENTValidAccount=2)
+ membersToRemoveFromGroup.add(fullUserDN);
+ SynchronizationReport.addExpiredUser();
+ continue;
+
+ } catch (Exception ioexc) {
+ _log.error("Error with LDAP connection");
+ continue;
+ }
+
+ userEverImported.put(fullUserDN, (user==null?null:user.getUserId()));
+
+ }
+
+ }
+ long time1 = System.currentTimeMillis();
+ _log.info("Group synchronization for usergroupid "+userGroupId+ " took "+(time1 - time0)+" ms");
+ return membersToRemoveFromGroup;
+ }
+
+
+
+
+ /**
+ * Initializes static variables etabMap and etabOuMap
+ * @param companyId
+ * @throws Exception
+ */
+ public static void initializeSchoolMaps() {
+
+ etabMap = new HashMap<String, Organization>();
+ etabOuMap = new HashMap<String, String>();
+
+ try{
+ String[] attrs2fetchForEtab = {LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTURENOMCOURANT, "l", LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI, "ou"};
+
+ NamingEnumeration<SearchResult> ldapEtabs = PortalLDAPUtil.getAllEtabs(companyId, attrs2fetchForEtab);
+ while (ldapEtabs.hasMoreElements()) {
+
+ SearchResult result = ldapEtabs.nextElement();
+ Attributes schoolAttributes = result.getAttributes();
+
+ // Build etab name
+ String etabDn = "ou=" + schoolAttributes.get("ou").get().toString() + ",ou=etablissements,"+PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN);
+ etabOuMap.put(schoolAttributes.get("ou").get().toString(), schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI).get().toString());
+ _log.info("Building etabOuMap : adding ou="+schoolAttributes.get("ou").get().toString()+" mapped to ENTStructureUAI="+schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI).get().toString());
+
+ OrganizationMapping orgMapping = null;
+ Organization etabOrg = null;
+ try {
+ orgMapping = OrganizationMappingLocalServiceUtil.getOrganizationMapping(schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI).get().toString());
+ etabOrg = OrganizationLocalServiceUtil.getOrganization(orgMapping.getOrganizationId());
+ if (etabOrg != null) {
+ etabMap.put(etabDn, etabOrg);
+ _log.info("Building etabMap : adding etabDn="+etabDn+" mapped to etabOrg="+etabOrg.getName());
+ }
+ } catch (Exception e) {
+ _log.error("Organization mapping not existing for UAI="+schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI).get().toString());
+ //continue;
+ }
+
+ // Create school if needed
+ if (etabOrg == null) {
+ String newSchoolName = schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTURENOMCOURANT).get().toString();
+ try {
+ _log.info("About to create new school named "+newSchoolName);
+ etabOrg = ENTOrganizationsUtil.getOrCreateSchool(companyId, newSchoolName);
+ } catch (Exception e) {
+ _log.error("Error when creating school named "+newSchoolName, e);
+ }
+
+ // Create org mapping
+ OrganizationMappingLocalServiceUtil.addOrganizationMapping(etabOrg, schoolAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTSTRUCTUREUAI).get().toString());
+
+ _log.info("Added dn "+etabDn+" to school "+etabOrg.getName()+" in etabMap.");
+ etabMap.put(etabDn, etabOrg);
+
+ }
+ }
+ }
+ catch (Exception exc) {
+ _log.error("Error in initializeSchoolMaps for o", exc);
+ }
+
+ }
+
+
+ /**
+ * Add the given user to the '-Parent' or '- Personnels' or '- Enseignants' sub-orgs
+ * @param companyId
+ * @param user
+ */
+ private static void synchronizeSchoolLevelOrganizations (long companyId, User user, Attributes attrs, boolean manualCreation) {
+
+ // Skip inactive users
+ if (user.getStatus() == WorkflowConstants.STATUS_INACTIVE) {
+ return;
+ }
+
+ Boolean hasTeacherGrp = false;
+ Boolean hasPersonnelGrp = false;
+ Boolean hasParentGrp = false;
+ Boolean isParentUser = false;
+ Boolean analyzeSchoolComplex = false;
+
+ long userId = user.getUserId();
+
+ try {
+ // Add user to root organization
+ Organization rootOrg = ENTOrganizationsUtil.getOrCreateRootOrg(user.getCompanyId());
+ if (!UserLocalServiceUtil.hasOrganizationUser(rootOrg.getOrganizationId(), user.getUserId()) ) {
+ UserLocalServiceUtil.addOrganizationUsers(rootOrg.getOrganizationId(), new long[]{user.getUserId()});
+ }
+
+ Organization rattachSchool = null;
+ if (manualCreation) {
+ // Get 'ENTPersonStructRattach' attribute
+ String entPersonStructRattach = attrs.get("ENTPersonStructRattach").get().toString();
+ _log.info("Manual creation : entPersonStructRattach="+entPersonStructRattach);
+ rattachSchool = SynchronizationUtils.getSchoolFromClassName(entPersonStructRattach);
+
+ } else {
+ rattachSchool = getRattachSchool(user);
+ }
+ if (rattachSchool == null) {
+ _log.error("No rattach school found for user "+user.getFullName());
+ return;
+ }
+
+
+ // Add user to this etab if not present
+ boolean addRattachSchool = false;
+ if (!OrganizationLocalServiceUtil.hasUserOrganization(user.getUserId(), rattachSchool.getOrganizationId())) {
+ _log.info("synchronizeSchoolLevelOrganizations : adding user "+user.getFullName()+" to school "+rattachSchool.getName());
+ UserLocalServiceUtil.addOrganizationUsers(rattachSchool.getOrganizationId(), new long[]{user.getUserId()});
+ addRattachSchool = true;
+ }
+
+ // Update rattach school in user properties
+ UserProperties userProp = UserPropertiesLocalServiceUtil.getUserPropertiesByUserId(user.getUserId());
+ userProp.setEtabId(rattachSchool.getOrganizationId());
+ UserPropertiesLocalServiceUtil.updateUserProperties(userProp);
+
+ // Get user roles
+ List<Role> userRolesList = RoleLocalServiceUtil.getUserRoles(userId);
+
+ // Loop over the user's roles to detect school-level orgs
+ for (Role userRole : userRolesList) {
+ // Student => quit
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_1)) {
+ if (addRattachSchool) {
+ SynchronizationReport.notifyStudentMembershipCreation(user, rattachSchool);
+ }
+ }
+
+ // Parent group
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_2)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
+ hasParentGrp = true;
+ }
+
+ // Teacher group
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_3)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_24)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
+ if (addRattachSchool) {
+ SynchronizationReport.notifyTeacherMembershipCreation(user, rattachSchool);
+ }
+ hasTeacherGrp = true;
+ }
+
+ // Personnel group
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_3)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_5)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_6)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_7)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
+ hasPersonnelGrp = true;
+ // Add membership to school except for Nat_3 (done before)
+ if (addRattachSchool && !userRole.getName().equals(ENTRolesConstants.NATIONAL_3)) {
+ SynchronizationReport.notifyOtherMembershipCreation(user, rattachSchool);
+ }
+ }
+
+ // School complex
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_5)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_6)
+ || userRole.getName().equals(ENTRolesConstants.NATIONAL_7)) {
+ analyzeSchoolComplex = true;
+ }
+ }
+
+
+ // Add parents to org
+ SynchronizationUtils.addOrRemoveUserFromOrg(user, rattachSchool, hasParentGrp, OrganizationConstants.ORG_SUFFIX_PARENTS);
+ if (isParentUser) {
+ return;
+ }
+
+ // Add teachers to orgs
+ SynchronizationUtils.addOrRemoveUserFromOrg(user, rattachSchool, hasTeacherGrp, OrganizationConstants.ORG_SUFFIX_TEACHERS);
+
+ // Add personnel to orgs
+ SynchronizationUtils.addOrRemoveUserFromOrg(user, rattachSchool, hasPersonnelGrp, OrganizationConstants.ORG_SUFFIX_PERSONNELS);
+
+ // If school complex => add user into other etabs from the school complex
+ if (analyzeSchoolComplex) {
+ List<Long> etabIdList = getSchoolComplexAttachedEtabs(rattachSchool.getOrganizationId());
+ for (Long etabIdToAttach : etabIdList) {
+ _log.info("Adding user "+user.getFullName()+" to complex school "+etabIdToAttach);
+ Organization org = OrganizationLocalServiceUtil.getOrganization(etabIdToAttach);
+ SynchronizationUtils.addOrRemoveUserFromOrg(user, org, true, "");
+ }
+ }
+
+ // If the user is etab manager, add it to principal organization
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS) != null && attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS).toString().endsWith("CHEF D'ETABLISSEMENT")) {
+ long groupId = rattachSchool.getGroup().getGroupId();
+ long[] roleIds = {RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.SCHOOL_MANAGER).getRoleId()};
+ UserGroupRoleLocalServiceUtil.addUserGroupRoles(userId, groupId, roleIds);
+ }
+
+
+ } catch (Exception e) {
+ _log.error("Error when synchronizing school-level organizations for user "+user.getFullName()+ "(id "+user.getUserId()+")", e);
+ }
+ }
+
+
+
+ private static void synchronizeGroups() {
+
+ long groupSyncAll0 = System.currentTimeMillis();
+ try {
+ String importMethod = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_IMPORT_METHOD);
+
+ if (importMethod.equals(OrganizationConstants.IMPORT_BY_USER)) {
+ // not managed
+
+ } else if (importMethod.equals(OrganizationConstants.IMPORT_BY_GROUP)) {
+
+ // Build the group list
+ Set<String> grpProcessed = new HashSet<String>();
+ NamingEnumeration<SearchResult> enu = PortalLDAPUtil.getGroups(companyId, 0);
+ while (enu.hasMoreElements()) {
+ SearchResult result = enu.nextElement();
+ grpProcessed.add(PortalLDAPUtil.getNameInNamespace(companyId, result));
+ }
+ enu.close();
+ int count=0;
+ int totalGrp = grpProcessed.size();
+
+ // Loop through all LDAP groups
+ for (String grpDN: grpProcessed){
+ count++;
+
+ _log.info("Importing GRP: " + count + "/" + totalGrp + " : "+grpDN);
+
+ // Run the sync for 1 given group
+ try {
+ Attributes attrs = PortalLDAPUtil.getGroupAttributes(companyId, grpDN, true);
+ synchronizeGroup(companyId, attrs, grpDN);
+
+ } catch(Exception grpImportExcept) {
+ _log.error("Error during import group "+ grpDN);
+ }
+ }
+ }
+ } catch (Exception e) {
+ _log.error("Error importing LDAP users and groups", e);
+ }
+ long groupSyncAll1 = System.currentTimeMillis();
+ int groupSyncTime = (int)((groupSyncAll1 - groupSyncAll0)/60000);
+ SynchronizationReport.setGroupSyncTime(groupSyncTime);
+
+ }
+
+
+ /**
+ * Update parent relationships for just created users
+ * Previously created relationships have toUserId set to 0 because the parent may not exist yet when the relationship is created
+ */
+ private static void updateParentRelations() {
+ try {
+ List<UserRelationship> relationsToComplete = UserRelationshipLocalServiceUtil.getUserRelationshipByToUserIdRelationType(0, UserRelationshipConstants.PARENT_RELATION);
+ if (relationsToComplete != null) {
+ for (UserRelationship relation : relationsToComplete) {
+
+ try {
+ // Extract uid from 'toUserSconetId' field (Example uid=123456,ou=people,dc=cartabledesavoie,dc=com)
+ String[] sconetIdTab = relation.getToUserSconetId().split(",");
+ if (sconetIdTab != null && sconetIdTab.length > 0) {
+ String uid = sconetIdTab[0].substring(4);
+ _log.info("updateParentRelations : trying to map uid="+uid+" with existing userId");
+ User parentUser = LDAPMappingLocalServiceUtil.getUserFromUID(uid);
+ relation.setToUserId(parentUser.getUserId());
+ UserRelationshipLocalServiceUtil.updateUserRelationship(relation);
+ _log.info("updateParentRelations : updated relationship with uid="+uid+" with parent userId = "+parentUser.getUserId());
+ User child = UserLocalServiceUtil.getUser(relation.getFromUserId());
+ SynchronizationReport.addChildParentLink(child, parentUser);
+ }
+ } catch (Exception e) {
+ _log.error("Error when updating parent relationship for relation with fromId="+relation.getFromUserId(), e);
+ }
+ }
+ }
+ } catch (SystemException e) {
+ _log.error("Error when updating parent relationships", e);
+ }
+ }
+
+ /**
+ * Returns the list of schools related to the given school id through a school complex
+ * @param etabId
+ * @return the list of related school ids
+ */
+ public static List<Long> getSchoolComplexAttachedEtabs(long etabId) {
+ List<Long> result = new ArrayList<Long>();
+ List<OrganizationCiteScolaire> orgaCiteScolaireList;
+ try {
+
+ // Get ENTStructureUAI of etabId (orgId)
+ String entStructureUAI = "";
+ List<OrganizationMapping> orgMappingList = OrganizationMappingLocalServiceUtil.getOrganizationMappings(-1, -1);
+ for (OrganizationMapping orgMapping : orgMappingList) {
+ if (orgMapping.getOrganizationId() == etabId) {
+ entStructureUAI = orgMapping.getEntStructureUAI();
+ }
+ }
+
+ // Get parent ENTStructureUAI
+ String parentENTStructureUAI = "";
+ orgaCiteScolaireList = OrganizationCiteScolaireLocalServiceUtil.getOrganizationCiteScolaires(-1, -1);
+ if (orgaCiteScolaireList != null) {
+ for (OrganizationCiteScolaire orgaCiteScolaire : orgaCiteScolaireList) {
+ if (orgaCiteScolaire.getParentENTStructureUAI().equals(entStructureUAI)) {
+ parentENTStructureUAI = entStructureUAI;
+ }
+ if (orgaCiteScolaire.getChildENTStructureUAI().equals(entStructureUAI)) {
+ parentENTStructureUAI = orgaCiteScolaire.getParentENTStructureUAI();
+ }
+ }
+ }
+
+ // Get child organizations of the found parent
+ if (!parentENTStructureUAI.equals("") && orgaCiteScolaireList != null) {
+ for (OrganizationCiteScolaire orgaCiteScolaire : orgaCiteScolaireList) {
+ if (orgaCiteScolaire.getParentENTStructureUAI().equals(parentENTStructureUAI)) {
+ // Get etabId associated to the child entStructureUAI
+ long childId = OrganizationMappingLocalServiceUtil.getOrganizationMapping(orgaCiteScolaire.getChildENTStructureUAI()).getOrganizationId();
+ if (childId != etabId) {
+ _log.warn("School complex : adding child "+childId);
+ result.add(new Long(childId));
+ }
+ // Get etabId associated to the parent entStructureUAI
+ long parentId = OrganizationMappingLocalServiceUtil.getOrganizationMapping(orgaCiteScolaire.getParentENTStructureUAI()).getOrganizationId();
+ if (parentId != etabId && !result.contains(new Long(parentId))) {
+ _log.warn("School complex : adding parent "+parentId);
+ result.add(new Long(parentId));
+ }
+ }
+ }
+ }
+
+
+ } catch (SystemException e) {
+ } catch (PortalException e) {
+ }
+ return result;
+ }
+
+ /**
+ * Initialize the scolar cities
+ * @param companyId
+ * @throws Exception
+ */
+ private static void initializeSchoolComplexes() throws Exception {
+
+ _log.info("Initializing school complexes ...");
+
+ String[] attrs2fetchForEtab = {"ENTStructureNomCourant", "l", "ENTStructureUAI", "ou", "ENTStructureJointure", "ENTEtablissementStructRattachFctl"};
+ NamingEnumeration<SearchResult> ldapEtabs = PortalLDAPUtil.getAllEtabs(companyId, attrs2fetchForEtab);
+ while (ldapEtabs.hasMoreElements()) {
+ SearchResult result = ldapEtabs.nextElement();
+ Attributes attrs = result.getAttributes();
+ try{
+
+ // Get 'ENTEtablissementStructRattachFctl' attribute to get school complexes
+ if (attrs.get("ENTEtablissementStructRattachFctl") != null && attrs.get("ENTStructureJointure") != null) {
+ String entStructureUAIStr1 = attrs.get("ENTStructureUAI").get().toString();
+ //String entStructureJointureStr1 = attrs.get("ENTStructureJointure").get().toString();
+ String etabStructRattachFctlStr = attrs.get("ENTEtablissementStructRattachFctl").get().toString();
+
+ // Format is ou=xxxx,ou=etablissements,dc=ent,dc=pentila,dc=com. We want to get xxxx
+ String entStructureJointureCiteScolaire = "";
+ String[] etabStructRattachFctlTab = etabStructRattachFctlStr.split(",");
+ if (etabStructRattachFctlTab != null && etabStructRattachFctlTab.length > 1) {
+ String ouCite = etabStructRattachFctlTab[0];
+ entStructureJointureCiteScolaire = ouCite.substring(3);
+ }
+
+ String mappedEntStructureUAI = "";
+
+ // Loop again over etabs to get the ENTStructureUAI of the given ENTStructureJointure
+ NamingEnumeration<SearchResult> ldapEtabs2 = PortalLDAPUtil.getAllEtabs(companyId, attrs2fetchForEtab);
+ while (ldapEtabs2.hasMoreElements()) {
+ SearchResult result2 = ldapEtabs2.nextElement();
+ Attributes attrs2 = result2.getAttributes();
+ try{
+
+ // Get 'ENTEtablissementStructRattachFctl' attribute to get scolar cities
+ if (attrs2.get("ENTStructureUAI") != null && attrs2.get("ENTStructureJointure") != null) {
+ String entStructureJointureStr2 = attrs2.get("ENTStructureJointure").get().toString();
+ String entStructureUAIStr2 = attrs2.get("ENTStructureUAI").get().toString();
+
+ if (entStructureJointureStr2.equals(entStructureJointureCiteScolaire)) {
+ mappedEntStructureUAI = entStructureUAIStr2;
+ }
+ }
+ }
+ catch (Exception exc) {
+ _log.error("error in initializeCiteScolaire");
+ }
+ }
+
+ // Cite scolaire does not have parent and child ENTStructureUAI equal
+ if (!mappedEntStructureUAI.equals("0") && !mappedEntStructureUAI.equals("") && !mappedEntStructureUAI.equals(entStructureUAIStr1)) {
+
+ OrganizationCiteScolaireLocalServiceUtil.addOrganizationCiteScolaire(mappedEntStructureUAI, entStructureUAIStr1);
+ _log.info("Added cite scolaire between "+mappedEntStructureUAI+" and "+entStructureUAIStr1+".");
+ }
+ }
+
+ }
+ catch (Exception exc) {
+ _log.error("error in initializeCiteScolaire");
+ }
+ }
+
+ }
+
+
+ /**
+ * Build the static maps that contain user infos
+ */
+ private static void buildUserMaps() {
+
+ _log.info("Building user map ...");
+ try {
+ String[] attrs2fetch = {LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONSTRUCTRATTACH, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVECLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTELEVEGROUPES, LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONFONCTIONS, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSGROUPES, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL, LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSMATIEREENSEIGNETAB};
+
+ // Loop over all users in LDAP
+ NamingEnumeration<SearchResult> ldapUsers = PortalLDAPUtil.getUsers(companyId, 0, attrs2fetch);
+ while (ldapUsers.hasMoreElements()) {
+
+ SearchResult result = ldapUsers.nextElement();
+ Attributes attrs = result.getAttributes();
+
+ // Build the user map
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN) == null) {
+ _log.error("User has no ENTPersonLogin");
+ continue;
+ }
+ if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONSTRUCTRATTACH) == null) {
+ _log.error("User "+attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN).get().toString()+" has no ENTPersonStructRattach");
+ continue;
+ }
+ userRattachSchoolMap.put(attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN).get().toString(), attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONSTRUCTRATTACH).get().toString());
+ userAttributesMap.put(attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN).get().toString(), attrs);
+
+ }
+ } catch (Exception e) {
+ _log.error("Error while building user map", e);
+ }
+ _log.info("Built user map with "+userRattachSchoolMap.size()+" users.");
+
+ }
+
+ /**
+ * Get the rattach school based on the global maps
+ * @param user
+ * @return
+ */
+ public static Organization getRattachSchool(User user) {
+
+ //_log.info("In getRattachSchool : userRattachSchoolMap has "+userRattachSchoolMap.size()+" entries and etabMap has "+etabMap.keySet().size()+" entries");
+
+ // Get rattach school
+ Organization etabRattachement = null;
+ try {
+ if (!userRattachSchoolMap.containsKey(user.getScreenName())) {
+ _log.error("User "+user.getScreenName()+" is not in the user map");
+ return null;
+ }
+ String etabUserDn = userRattachSchoolMap.get(user.getScreenName());
+ etabRattachement = etabMap.get(etabUserDn);
+ }
+ catch (Exception e) {
+ _log.error("No attached school in LDAP for user "+ user.getFullName(), e);
+ }
+
+ if (etabRattachement == null) {
+ _log.error("No attached school in LDAP for user " + user.getFullName());
+ }
+ return etabRattachement;
+ }
+
+
+
+ /**
+ * Send email to technical team at synchronization's end
+ */
+ private static void sendSynchronizationEndMail(Date startSynchroTime, Date endSynchroTime) {
+
+ _log.info("Sending synchronization END email ...");
+
+ try {
+ // Get mail source and target
+ String synchroEndMail = ENTMainUtilsLocalServiceUtil.getSupportMail();
+
+ // Get platform name
+ String platformName = ENTMainUtilsLocalServiceUtil.getPlatform();
+ if (platformName == null || platformName.equals("")) {
+ return;
+ }
+
+ // Format synchro duration
+ SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
+ long durationMillis = endSynchroTime.getTime() - startSynchroTime.getTime();
+ int durationMinutes = (int)Math.floor(durationMillis / (60 * 1000) % 60);
+ int durationHours = (int)Math.floor(durationMillis / (60 * 60 * 1000));
+
+ String duration = durationHours + " hours and " + durationMinutes + " minutes";
+ String report = SynchronizationReport.generateSynchroReport();
+
+ String synchroEndMailSubject = "Synchronization ended on "+platformName;
+ String synchroEndMailContent = "Hello,</br></br>The synchronization process has ended on platform "+platformName+".</br></br>"
+ + "Start time : "+sdf.format(startSynchroTime)+"</br>"
+ + "End time : "+sdf.format(endSynchroTime)+"</br>"
+ + "Duration : "+duration+"</br></br>"
+ + report+"</br></br>"
+ + "The technical team</br>";
+
+ // Build and send mail
+ MailMessage mailMessage = new MailMessage();
+ mailMessage.setHTMLFormat(true);
+ mailMessage.setFrom(new InternetAddress(synchroEndMail));
+ mailMessage.setTo(new InternetAddress(synchroEndMail));
+ mailMessage.setSubject(synchroEndMailSubject);
+ mailMessage.setBody(synchroEndMailContent);
+
+ MailServiceUtil.sendEmail(mailMessage);
+
+ } catch (Exception e) {
+ _log.error("Error while sending end synchronization mail");
+ }
+ _log.info("Sent synchronization END email ...");
+ }
+
+ /**
+ * Is the import enabled in the portal-ext.properties file ?
+ * @param companyId
+ * @return
+ * @throws SystemException
+ */
+ private static boolean isImportEnabled(long companyId) throws SystemException {
+ return PrefsPropsUtil.getBoolean(companyId, PropsKeys.LDAP_IMPORT_ENABLED, PropsValues.LDAP_IMPORT_ENABLED);
+ }
+
+ private static void initCompanyId () {
+ try {
+ List<Company> companies = CompanyLocalServiceUtil.getCompanies(false);
+ for (Company company : companies) {
+ companyId = company.getCompanyId();
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ private static void processCreatedUsers() {
+ if (createdUserList != null) {
+ for (User createdUser : createdUserList) {
+
+ try {
+ Organization school = getRattachSchool(createdUser);
+
+ List<Role> userRoles = RoleLocalServiceUtil.getUserRoles(createdUser.getUserId());
+ for (Role userRole : userRoles) {
+ if (userRole.getName().equals(ENTRolesConstants.NATIONAL_1)) {
+ SynchronizationReport.notifyCreation(school, createdUser, RoleEnum.STUDENT_ROLE);
+ return;
+ } else if (userRole.getName().equals(ENTRolesConstants.NATIONAL_2)) {
+ SynchronizationReport.notifyCreation(school, createdUser, RoleEnum.PARENT_ROLE);
+ return;
+ } else if (userRole.getName().equals(ENTRolesConstants.NATIONAL_3)) {
+ SynchronizationReport.notifyCreation(school, createdUser, RoleEnum.TEACHER_ROLE);
+ return;
+ }
+ }
+ // Default
+ SynchronizationReport.notifyCreation(school, createdUser, RoleEnum.OTHER_ROLE);
+ } catch (Exception e) {
+ _log.error("Error when processing newly created user "+createdUser, e);
+ }
+
+ }
+ }
+ }
+
+ public static Map<String, Organization> getEtabMap() {
+ return etabMap;
+ }
+
+ public static Map<String, String> getEtabOuMap() {
+ return etabOuMap;
+ }
+
+ public static Map<String, Long> getUserEverImported() {
+ return userEverImported;
+ }
+
+ public static Map<String, String> getUserRattachSchoolMap() {
+ return userRattachSchoolMap;
+ }
+
+ public static Map<String, Attributes> getUserAttributesMap() {
+ return userAttributesMap;
+ }
+
+ public static void initUserRattachSchoolMap() {
+ userRattachSchoolMap = new HashMap<String, String>();
+ }
+
+ public enum RoleEnum {
+ STUDENT_ROLE,
+ PARENT_ROLE,
+ TEACHER_ROLE,
+ OTHER_ROLE
+ }
+
+
+}