001
014
015 package com.liferay.portal.security.ldap;
016
017 import com.liferay.portal.NoSuchRoleException;
018 import com.liferay.portal.NoSuchUserException;
019 import com.liferay.portal.NoSuchUserGroupException;
020 import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
021 import com.liferay.portal.kernel.cache.PortalCache;
022 import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
023 import com.liferay.portal.kernel.exception.SystemException;
024 import com.liferay.portal.kernel.ldap.LDAPUtil;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.util.CalendarFactoryUtil;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.LocaleUtil;
030 import com.liferay.portal.kernel.util.PropsKeys;
031 import com.liferay.portal.kernel.util.SetUtil;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.StringUtil;
035 import com.liferay.portal.kernel.util.Validator;
036 import com.liferay.portal.model.Company;
037 import com.liferay.portal.model.CompanyConstants;
038 import com.liferay.portal.model.Contact;
039 import com.liferay.portal.model.Group;
040 import com.liferay.portal.model.Role;
041 import com.liferay.portal.model.RoleConstants;
042 import com.liferay.portal.model.User;
043 import com.liferay.portal.model.UserGroup;
044 import com.liferay.portal.security.auth.CompanyThreadLocal;
045 import com.liferay.portal.security.auth.ScreenNameGenerator;
046 import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
047 import com.liferay.portal.service.CompanyLocalServiceUtil;
048 import com.liferay.portal.service.GroupLocalServiceUtil;
049 import com.liferay.portal.service.LockLocalServiceUtil;
050 import com.liferay.portal.service.RoleLocalServiceUtil;
051 import com.liferay.portal.service.UserGroupLocalServiceUtil;
052 import com.liferay.portal.service.UserLocalServiceUtil;
053 import com.liferay.portal.util.PrefsPropsUtil;
054 import com.liferay.portal.util.PropsValues;
055 import com.liferay.portlet.expando.model.ExpandoBridge;
056 import com.liferay.portlet.expando.model.ExpandoTableConstants;
057 import com.liferay.portlet.expando.service.ExpandoValueLocalServiceUtil;
058 import com.liferay.portlet.expando.util.ExpandoConverterUtil;
059
060 import java.io.Serializable;
061
062 import java.text.ParseException;
063
064 import java.util.ArrayList;
065 import java.util.Calendar;
066 import java.util.Date;
067 import java.util.HashMap;
068 import java.util.List;
069 import java.util.Locale;
070 import java.util.Map;
071 import java.util.Properties;
072 import java.util.Set;
073
074 import javax.naming.Binding;
075 import javax.naming.NameNotFoundException;
076 import javax.naming.NamingEnumeration;
077 import javax.naming.directory.Attribute;
078 import javax.naming.directory.Attributes;
079 import javax.naming.directory.SearchControls;
080 import javax.naming.directory.SearchResult;
081 import javax.naming.ldap.LdapContext;
082
083
089 public class PortalLDAPImporterImpl implements PortalLDAPImporter {
090
091 public void importFromLDAP() throws Exception {
092 List<Company> companies = CompanyLocalServiceUtil.getCompanies(false);
093
094 for (Company company : companies) {
095 importFromLDAP(company.getCompanyId());
096 }
097 }
098
099 public void importFromLDAP(long companyId) throws Exception {
100 if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
101 return;
102 }
103
104 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
105
106 if (LockLocalServiceUtil.hasLock(
107 defaultUserId, PortalLDAPImporterUtil.class.getName(),
108 companyId)) {
109
110 if (_log.isDebugEnabled()) {
111 _log.debug(
112 "Skipping LDAP import for company " + companyId +
113 "because another LDAP import is in process");
114 }
115
116 return;
117 }
118
119 LockLocalServiceUtil.lock(
120 defaultUserId, PortalLDAPImporterUtil.class.getName(), companyId,
121 PortalLDAPImporterImpl.class.getName(), false,
122 PropsValues.LDAP_IMPORT_LOCK_EXPIRATION_TIME);
123
124 long threadLocalCompanyId = CompanyThreadLocal.getCompanyId();
125
126 try {
127 if (threadLocalCompanyId == CompanyConstants.SYSTEM) {
128 CompanyThreadLocal.setCompanyId(companyId);
129 }
130
131 long[] ldapServerIds = StringUtil.split(
132 PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
133
134 for (long ldapServerId : ldapServerIds) {
135 importFromLDAP(ldapServerId, companyId);
136 }
137
138 for (int ldapServerId = 0;; ldapServerId++) {
139 String postfix = LDAPSettingsUtil.getPropertyPostfix(
140 ldapServerId);
141
142 String providerUrl = PrefsPropsUtil.getString(
143 companyId, PropsKeys.LDAP_BASE_PROVIDER_URL + postfix);
144
145 if (Validator.isNull(providerUrl)) {
146 break;
147 }
148
149 importFromLDAP(ldapServerId, companyId);
150 }
151 }
152 finally {
153 LockLocalServiceUtil.unlock(
154 PortalLDAPImporterUtil.class.getName(), companyId);
155
156 CompanyThreadLocal.setCompanyId(threadLocalCompanyId);
157 }
158 }
159
160 public void importFromLDAP(long ldapServerId, long companyId)
161 throws Exception {
162
163 if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
164 return;
165 }
166
167 LdapContext ldapContext = PortalLDAPUtil.getContext(
168 ldapServerId, companyId);
169
170 if (ldapContext == null) {
171 return;
172 }
173
174 try {
175 Properties userMappings = LDAPSettingsUtil.getUserMappings(
176 ldapServerId, companyId);
177 Properties userExpandoMappings =
178 LDAPSettingsUtil.getUserExpandoMappings(
179 ldapServerId, companyId);
180 Properties contactMappings = LDAPSettingsUtil.getContactMappings(
181 ldapServerId, companyId);
182 Properties contactExpandoMappings =
183 LDAPSettingsUtil.getContactExpandoMappings(
184 ldapServerId, companyId);
185 Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
186 ldapServerId, companyId);
187
188 String importMethod = PrefsPropsUtil.getString(
189 companyId, PropsKeys.LDAP_IMPORT_METHOD);
190
191 if (importMethod.equals(_IMPORT_BY_GROUP)) {
192 importFromLDAPByGroup(
193 ldapServerId, companyId, ldapContext, userMappings,
194 userExpandoMappings, contactMappings,
195 contactExpandoMappings, groupMappings);
196 }
197 else if (importMethod.equals(_IMPORT_BY_USER)) {
198 importFromLDAPByUser(
199 ldapServerId, companyId, ldapContext, userMappings,
200 userExpandoMappings, contactMappings,
201 contactExpandoMappings, groupMappings);
202 }
203 }
204 catch (Exception e) {
205 _log.error("Error importing LDAP users and groups", e);
206 }
207 finally {
208 if (ldapContext != null) {
209 ldapContext.close();
210 }
211 }
212 }
213
214 public User importLDAPUser(
215 long ldapServerId, long companyId, LdapContext ldapContext,
216 Attributes attributes, String password)
217 throws Exception {
218
219 Properties userMappings = LDAPSettingsUtil.getUserMappings(
220 ldapServerId, companyId);
221 Properties userExpandoMappings =
222 LDAPSettingsUtil.getUserExpandoMappings(ldapServerId, companyId);
223 Properties contactMappings = LDAPSettingsUtil.getContactMappings(
224 ldapServerId, companyId);
225 Properties contactExpandoMappings =
226 LDAPSettingsUtil.getContactExpandoMappings(ldapServerId, companyId);
227
228 User user = importUser(
229 companyId, attributes, userMappings, userExpandoMappings,
230 contactMappings, contactExpandoMappings, password);
231
232 Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
233 ldapServerId, companyId);
234
235 importGroups(
236 ldapServerId, companyId, ldapContext, attributes, user,
237 userMappings, groupMappings);
238
239 return user;
240 }
241
242 public User importLDAPUser(
243 long ldapServerId, long companyId, String emailAddress,
244 String screenName)
245 throws Exception {
246
247 LdapContext ldapContext = null;
248
249 NamingEnumeration<SearchResult> enu = null;
250
251 try {
252 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
253
254 String baseDN = PrefsPropsUtil.getString(
255 companyId, PropsKeys.LDAP_BASE_DN + postfix);
256
257 ldapContext = PortalLDAPUtil.getContext(ldapServerId, companyId);
258
259 if (ldapContext == null) {
260 throw new SystemException("Failed to bind to the LDAP server");
261 }
262
263 String filter = PrefsPropsUtil.getString(
264 companyId, PropsKeys.LDAP_AUTH_SEARCH_FILTER + postfix);
265
266 if (_log.isDebugEnabled()) {
267 _log.debug("Search filter before transformation " + filter);
268 }
269
270 filter = StringUtil.replace(
271 filter,
272 new String[] {
273 "@company_id@", "@email_address@", "@screen_name@"
274 },
275 new String[] {
276 String.valueOf(companyId), emailAddress, screenName
277 });
278
279 if (_log.isDebugEnabled()) {
280 _log.debug("Search filter after transformation " + filter);
281 }
282
283 Properties userMappings = LDAPSettingsUtil.getUserMappings(
284 ldapServerId, companyId);
285
286 String userMappingsScreenName = GetterUtil.getString(
287 userMappings.getProperty("screenName")).toLowerCase();
288
289 SearchControls searchControls = new SearchControls(
290 SearchControls.SUBTREE_SCOPE, 1, 0,
291 new String[] {userMappingsScreenName}, false, false);
292
293 enu = ldapContext.search(baseDN, filter, searchControls);
294
295 if (enu.hasMoreElements()) {
296 if (_log.isDebugEnabled()) {
297 _log.debug("Search filter returned at least one result");
298 }
299
300 Binding binding = enu.nextElement();
301
302 Attributes attributes = PortalLDAPUtil.getUserAttributes(
303 ldapServerId, companyId, ldapContext,
304 PortalLDAPUtil.getNameInNamespace(
305 ldapServerId, companyId, binding));
306
307 return importLDAPUser(
308 ldapServerId, companyId, ldapContext, attributes,
309 StringPool.BLANK);
310 }
311 else {
312 return null;
313 }
314 }
315 catch (Exception e) {
316 if (_log.isWarnEnabled()) {
317 _log.warn("Problem accessing LDAP server " + e.getMessage());
318 }
319
320 if (_log.isDebugEnabled()) {
321 _log.debug(e, e);
322 }
323
324 throw new SystemException(
325 "Problem accessing LDAP server " + e.getMessage());
326 }
327 finally {
328 if (enu != null) {
329 enu.close();
330 }
331
332 if (ldapContext != null) {
333 ldapContext.close();
334 }
335 }
336 }
337
338 public User importLDAPUser(
339 long companyId, String emailAddress, String screenName)
340 throws Exception {
341
342 long[] ldapServerIds = StringUtil.split(
343 PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
344
345 for (long ldapServerId : ldapServerIds) {
346 User user = importLDAPUser(
347 ldapServerId, companyId, emailAddress, screenName);
348
349 if (user != null) {
350 return user;
351 }
352 }
353
354 for (int ldapServerId = 0;; ldapServerId++) {
355 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
356
357 String providerUrl = PrefsPropsUtil.getString(
358 companyId, PropsKeys.LDAP_BASE_PROVIDER_URL + postfix);
359
360 if (Validator.isNull(providerUrl)) {
361 break;
362 }
363
364 User user = importLDAPUser(
365 ldapServerId, companyId, emailAddress, screenName);
366
367 if (user != null) {
368 return user;
369 }
370 }
371
372 if (_log.isDebugEnabled()) {
373 if (Validator.isNotNull(emailAddress)) {
374 _log.debug(
375 "User with the email address " + emailAddress +
376 " was not found in any LDAP servers");
377 }
378 else {
379 _log.debug(
380 "User with the screen name " + screenName +
381 " was not found in any LDAP servers");
382 }
383 }
384
385 return null;
386 }
387
388 public User importLDAPUserByScreenName(long companyId, String screenName)
389 throws Exception {
390
391 long ldapServerId = PortalLDAPUtil.getLdapServerId(
392 companyId, screenName, StringPool.BLANK);
393
394 SearchResult result = (SearchResult)PortalLDAPUtil.getUser(
395 ldapServerId, companyId, screenName, StringPool.BLANK);
396
397 if (result == null) {
398 if (_log.isWarnEnabled()) {
399 _log.warn(
400 "No user was found in LDAP with screenName " + screenName);
401 }
402
403 return null;
404 }
405
406 LdapContext ldapContext = PortalLDAPUtil.getContext(
407 ldapServerId, companyId);
408
409 String fullUserDN = PortalLDAPUtil.getNameInNamespace(
410 ldapServerId, companyId, result);
411
412 Attributes attributes = PortalLDAPUtil.getUserAttributes(
413 ldapServerId, companyId, ldapContext, fullUserDN);
414
415 User user = importLDAPUser(
416 ldapServerId, companyId, ldapContext, attributes, StringPool.BLANK);
417
418 ldapContext.close();
419
420 return user;
421 }
422
423 public void setLDAPToPortalConverter(
424 LDAPToPortalConverter ldapToPortalConverter) {
425
426 _ldapToPortalConverter = ldapToPortalConverter;
427 }
428
429 protected void addRole(
430 long companyId, LDAPGroup ldapGroup, UserGroup userGroup)
431 throws Exception {
432
433 if (!PropsValues.LDAP_IMPORT_CREATE_ROLE_PER_GROUP) {
434 return;
435 }
436
437 Role role = null;
438
439 try {
440 role = RoleLocalServiceUtil.getRole(
441 companyId, ldapGroup.getGroupName());
442 }
443 catch (NoSuchRoleException nsre) {
444 User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
445
446 Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
447
448 descriptionMap.put(
449 LocaleUtil.getDefault(), "Autogenerated role from LDAP import");
450
451 role = RoleLocalServiceUtil.addRole(
452 defaultUser.getUserId(), companyId, ldapGroup.getGroupName(),
453 null, descriptionMap, RoleConstants.TYPE_REGULAR);
454 }
455
456 Group group = userGroup.getGroup();
457
458 if (GroupLocalServiceUtil.hasRoleGroup(
459 role.getRoleId(), group.getGroupId())) {
460
461 return;
462 }
463
464 GroupLocalServiceUtil.addRoleGroups(
465 role.getRoleId(), new long[] {group.getGroupId()});
466 }
467
468 protected User addUser(long companyId, LDAPUser ldapUser, String password)
469 throws Exception {
470
471 if (_log.isDebugEnabled()) {
472 _log.debug("Adding user " + ldapUser.getEmailAddress());
473 }
474
475 boolean autoPassword = ldapUser.isAutoPassword();
476
477 if (!PropsValues.LDAP_IMPORT_USER_PASSWORD_ENABLED) {
478 autoPassword = PropsValues.LDAP_IMPORT_USER_PASSWORD_AUTOGENERATED;
479
480 if (!autoPassword) {
481 String defaultPassword =
482 PropsValues.LDAP_IMPORT_USER_PASSWORD_DEFAULT;
483
484 if (defaultPassword.equalsIgnoreCase(
485 _USER_PASSWORD_SCREEN_NAME)) {
486
487 defaultPassword = ldapUser.getScreenName();
488 }
489
490 password = defaultPassword;
491 }
492 }
493
494 Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
495
496 birthdayCal.setTime(ldapUser.getBirthday());
497
498 int birthdayMonth = birthdayCal.get(Calendar.MONTH);
499 int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
500 int birthdayYear = birthdayCal.get(Calendar.YEAR);
501
502 User user = UserLocalServiceUtil.addUser(
503 ldapUser.getCreatorUserId(), companyId, autoPassword, password,
504 password, ldapUser.isAutoScreenName(), ldapUser.getScreenName(),
505 ldapUser.getEmailAddress(), 0, StringPool.BLANK,
506 ldapUser.getLocale(), ldapUser.getFirstName(),
507 ldapUser.getMiddleName(), ldapUser.getLastName(), 0, 0,
508 ldapUser.isMale(), birthdayMonth, birthdayDay, birthdayYear,
509 StringPool.BLANK, ldapUser.getGroupIds(),
510 ldapUser.getOrganizationIds(), ldapUser.getRoleIds(),
511 ldapUser.getUserGroupIds(), ldapUser.isSendEmail(),
512 ldapUser.getServiceContext());
513
514 if (ldapUser.isUpdatePortrait()) {
515 byte[] portraitBytes = ldapUser.getPortraitBytes();
516
517 if ((portraitBytes != null) && (portraitBytes.length > 0)) {
518 user = UserLocalServiceUtil.updatePortrait(
519 user.getUserId(), portraitBytes);
520 }
521 }
522
523 return user;
524 }
525
526 protected void addUserGroupsNotAddedByLDAPImport(
527 long userId, List<Long> userGroupIds)
528 throws Exception {
529
530 List<UserGroup> userGroups =
531 UserGroupLocalServiceUtil.getUserUserGroups(userId);
532
533 for (UserGroup userGroup : userGroups) {
534 if (!userGroupIds.contains(userGroup.getUserGroupId()) &&
535 !userGroup.isAddedByLDAPImport()) {
536
537 userGroupIds.add(userGroup.getUserGroupId());
538 }
539 }
540 }
541
542 protected String escapeValue(String value) {
543 return StringUtil.replace(value, "\\,", "\\\\,");
544 }
545
546 protected User getUser(long companyId, LDAPUser ldapUser) throws Exception {
547 User user = null;
548
549 try {
550 String authType = PrefsPropsUtil.getString(
551 companyId, PropsKeys.COMPANY_SECURITY_AUTH_TYPE,
552 PropsValues.COMPANY_SECURITY_AUTH_TYPE);
553
554 if (authType.equals(CompanyConstants.AUTH_TYPE_SN) &&
555 !ldapUser.isAutoScreenName()) {
556
557 user = UserLocalServiceUtil.getUserByScreenName(
558 companyId, ldapUser.getScreenName());
559 }
560 else {
561 user = UserLocalServiceUtil.getUserByEmailAddress(
562 companyId, ldapUser.getEmailAddress());
563 }
564 }
565 catch (NoSuchUserException nsue) {
566 }
567
568 return user;
569 }
570
571 protected Attribute getUsers(
572 long ldapServerId, long companyId, LdapContext ldapContext,
573 Attributes attributes, UserGroup userGroup,
574 Properties groupMappings)
575 throws Exception {
576
577 Attribute attribute = attributes.get(groupMappings.getProperty("user"));
578
579 if (attribute == null) {
580 return null;
581 }
582
583 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
584
585 String baseDN = PrefsPropsUtil.getString(
586 companyId, PropsKeys.LDAP_BASE_DN + postfix);
587
588 StringBundler sb = new StringBundler(7);
589
590 sb.append("(&");
591 sb.append(
592 PrefsPropsUtil.getString(
593 companyId,
594 PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
595 sb.append("(");
596 sb.append(groupMappings.getProperty("groupName"));
597 sb.append("=");
598 sb.append(escapeValue(userGroup.getName()));
599 sb.append("))");
600
601 return PortalLDAPUtil.getMultivaluedAttribute(
602 companyId, ldapContext, baseDN, sb.toString(), attribute);
603 }
604
605 protected void importFromLDAPByGroup(
606 long ldapServerId, long companyId, LdapContext ldapContext,
607 Properties userMappings, Properties userExpandoMappings,
608 Properties contactMappings, Properties contactExpandoMappings,
609 Properties groupMappings)
610 throws Exception {
611
612 byte[] cookie = new byte[0];
613
614 while (cookie != null) {
615 List<SearchResult> searchResults = new ArrayList<SearchResult>();
616
617 String groupMappingsGroupName = GetterUtil.getString(
618 groupMappings.getProperty("groupName")).toLowerCase();
619
620 cookie = PortalLDAPUtil.getGroups(
621 ldapServerId, companyId, ldapContext, cookie, 0,
622 new String[] {groupMappingsGroupName}, searchResults);
623
624 for (SearchResult searchResult : searchResults) {
625 try {
626 Attributes attributes = PortalLDAPUtil.getGroupAttributes(
627 ldapServerId, companyId, ldapContext,
628 PortalLDAPUtil.getNameInNamespace(
629 ldapServerId, companyId, searchResult),
630 true);
631
632 UserGroup userGroup = importUserGroup(
633 companyId, attributes, groupMappings);
634
635 Attribute usersAttribute = getUsers(
636 ldapServerId, companyId, ldapContext, attributes,
637 userGroup, groupMappings);
638
639 if (usersAttribute == null) {
640 if (_log.isInfoEnabled()) {
641 _log.info(
642 "No users found in " + userGroup.getName());
643 }
644
645 continue;
646 }
647
648 importUsers(
649 ldapServerId, companyId, ldapContext, userMappings,
650 userExpandoMappings, contactMappings,
651 contactExpandoMappings, userGroup.getUserGroupId(),
652 usersAttribute);
653 }
654 catch (Exception e) {
655 _log.error("Unable to import group " + searchResult, e);
656 }
657 }
658 }
659 }
660
661 protected void importFromLDAPByUser(
662 long ldapServerId, long companyId, LdapContext ldapContext,
663 Properties userMappings, Properties userExpandoMappings,
664 Properties contactMappings, Properties contactExpandoMappings,
665 Properties groupMappings)
666 throws Exception {
667
668 byte[] cookie = new byte[0];
669
670 while (cookie != null) {
671 List<SearchResult> searchResults = new ArrayList<SearchResult>();
672
673 String userMappingsScreenName = GetterUtil.getString(
674 userMappings.getProperty("screenName")).toLowerCase();
675
676 cookie = PortalLDAPUtil.getUsers(
677 ldapServerId, companyId, ldapContext, cookie, 0,
678 new String[] {userMappingsScreenName}, searchResults);
679
680 for (SearchResult searchResult : searchResults) {
681 try {
682 Attributes userAttributes =
683 PortalLDAPUtil.getUserAttributes(
684 ldapServerId, companyId, ldapContext,
685 PortalLDAPUtil.getNameInNamespace(
686 ldapServerId, companyId, searchResult));
687
688 User user = importUser(
689 companyId, userAttributes, userMappings,
690 userExpandoMappings, contactMappings,
691 contactExpandoMappings, StringPool.BLANK);
692
693 importGroups(
694 ldapServerId, companyId, ldapContext, userAttributes,
695 user, userMappings, groupMappings);
696 }
697 catch (Exception e) {
698 _log.error("Unable to import user " + searchResult, e);
699 }
700 }
701 }
702 }
703
704 protected List<Long> importGroup(
705 long ldapServerId, long companyId, LdapContext ldapContext,
706 String fullGroupDN, User user, Properties groupMappings,
707 List<Long> newUserGroupIds)
708 throws Exception {
709
710 String userGroupIdKey = null;
711
712 Long userGroupId = null;
713
714 if (PropsValues.LDAP_IMPORT_GROUP_CACHE_ENABLED) {
715 StringBundler sb = new StringBundler(5);
716
717 sb.append(ldapServerId);
718 sb.append(StringPool.UNDERLINE);
719 sb.append(companyId);
720 sb.append(StringPool.UNDERLINE);
721 sb.append(fullGroupDN);
722
723 userGroupIdKey = sb.toString();
724
725 userGroupId = (Long)_portalCache.get(userGroupIdKey);
726 }
727
728 if (userGroupId != null) {
729 if (_log.isDebugEnabled()) {
730 _log.debug("Skipping reimport of full group DN " + fullGroupDN);
731 }
732 }
733 else {
734 if (_log.isDebugEnabled()) {
735 _log.debug("Importing full group DN " + fullGroupDN);
736 }
737
738 Attributes groupAttributes = null;
739
740 try {
741 groupAttributes = PortalLDAPUtil.getGroupAttributes(
742 ldapServerId, companyId, ldapContext, fullGroupDN);
743 }
744 catch (NameNotFoundException nnfe) {
745 _log.error(
746 "LDAP group not found with full group DN " + fullGroupDN,
747 nnfe);
748 }
749
750 UserGroup userGroup = importUserGroup(
751 companyId, groupAttributes, groupMappings);
752
753 userGroupId = userGroup.getUserGroupId();
754
755 if (PropsValues.LDAP_IMPORT_GROUP_CACHE_ENABLED) {
756 _portalCache.put(userGroupIdKey, userGroupId);
757 }
758 }
759
760 if (userGroupId != null) {
761 if (_log.isDebugEnabled()) {
762 _log.debug(
763 "Adding " + user.getUserId() + " to group " + userGroupId);
764 }
765
766 newUserGroupIds.add(userGroupId);
767 }
768
769 return newUserGroupIds;
770 }
771
772 protected void importGroups(
773 long ldapServerId, long companyId, LdapContext ldapContext,
774 Attributes attributes, User user, Properties userMappings,
775 Properties groupMappings)
776 throws Exception {
777
778 List<Long> newUserGroupIds = new ArrayList<Long>();
779
780 if (PrefsPropsUtil.getBoolean(
781 companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER_ENABLED)) {
782
783 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
784
785 String baseDN = PrefsPropsUtil.getString(
786 companyId, PropsKeys.LDAP_BASE_DN + postfix);
787
788 Binding binding = PortalLDAPUtil.getUser(
789 ldapServerId, companyId, user.getScreenName(),
790 user.getEmailAddress());
791
792 String fullUserDN = PortalLDAPUtil.getNameInNamespace(
793 ldapServerId, companyId, binding);
794
795 StringBundler sb = new StringBundler(9);
796
797 sb.append(StringPool.OPEN_PARENTHESIS);
798 sb.append(StringPool.AMPERSAND);
799 sb.append(
800 PrefsPropsUtil.getString(
801 companyId,
802 PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
803 sb.append(StringPool.OPEN_PARENTHESIS);
804 sb.append(groupMappings.getProperty("user"));
805 sb.append(StringPool.EQUAL);
806 sb.append(escapeValue(fullUserDN));
807 sb.append(StringPool.CLOSE_PARENTHESIS);
808 sb.append(StringPool.CLOSE_PARENTHESIS);
809
810 byte[] cookie = new byte[0];
811
812 while (cookie != null) {
813 List<SearchResult> searchResults =
814 new ArrayList<SearchResult>();
815
816 String groupMappingsGroupName = GetterUtil.getString(
817 groupMappings.getProperty("groupName")).toLowerCase();
818
819 cookie = PortalLDAPUtil.searchLDAP(
820 companyId, ldapContext, cookie, 0, baseDN, sb.toString(),
821 new String[] {groupMappingsGroupName}, searchResults);
822
823 for (SearchResult searchResult : searchResults) {
824 String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
825 ldapServerId, companyId, searchResult);
826
827 newUserGroupIds = importGroup(
828 ldapServerId, companyId, ldapContext, fullGroupDN, user,
829 groupMappings, newUserGroupIds);
830 }
831 }
832 }
833 else {
834 String userMappingsGroup = userMappings.getProperty("group");
835
836 if (Validator.isNull(userMappingsGroup)) {
837 return;
838 }
839
840 Attribute userGroupAttribute = attributes.get(userMappingsGroup);
841
842 if (userGroupAttribute == null) {
843 return;
844 }
845
846 for (int i = 0; i < userGroupAttribute.size(); i++) {
847 String fullGroupDN = (String)userGroupAttribute.get(i);
848
849 newUserGroupIds = importGroup(
850 ldapServerId, companyId, ldapContext, fullGroupDN, user,
851 groupMappings, newUserGroupIds);
852 }
853 }
854
855 addUserGroupsNotAddedByLDAPImport(user.getUserId(), newUserGroupIds);
856
857 for (long newUserGroupId : newUserGroupIds) {
858 UserLocalServiceUtil.addUserGroupUsers(
859 newUserGroupId, new long[] {user.getUserId()});
860 }
861
862 List<UserGroup> userUserGroups =
863 UserGroupLocalServiceUtil.getUserUserGroups(user.getUserId());
864
865 for (UserGroup userGroup : userUserGroups) {
866 if (!newUserGroupIds.contains(userGroup.getUserGroupId())) {
867 UserLocalServiceUtil.deleteUserGroupUser(
868 userGroup.getUserGroupId(), user.getUserId());
869 }
870 }
871 }
872
873 protected User importUser(
874 long companyId, Attributes attributes, Properties userMappings,
875 Properties userExpandoMappings, Properties contactMappings,
876 Properties contactExpandoMappings, String password)
877 throws Exception {
878
879 LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);
880
881 try {
882 AttributesTransformer attributesTransformer =
883 AttributesTransformerFactory.getInstance();
884
885 attributes = attributesTransformer.transformUser(attributes);
886
887 LDAPUser ldapUser = _ldapToPortalConverter.importLDAPUser(
888 companyId, attributes, userMappings, userExpandoMappings,
889 contactMappings, contactExpandoMappings, password);
890
891 User user = getUser(companyId, ldapUser);
892
893 if ((user != null) && user.isDefaultUser()) {
894 return user;
895 }
896
897 if (user == null) {
898 user = addUser(companyId, ldapUser, password);
899 }
900
901 String modifiedDate = LDAPUtil.getAttributeString(
902 attributes, "modifyTimestamp");
903
904 user = updateUser(
905 companyId, ldapUser, user, password, modifiedDate);
906
907 updateExpandoAttributes(user, ldapUser);
908
909 return user;
910 }
911 finally {
912 LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
913 }
914 }
915
916 protected UserGroup importUserGroup(
917 long companyId, Attributes attributes, Properties groupMappings)
918 throws Exception {
919
920 AttributesTransformer attributesTransformer =
921 AttributesTransformerFactory.getInstance();
922
923 attributes = attributesTransformer.transformGroup(attributes);
924
925 LDAPGroup ldapGroup = _ldapToPortalConverter.importLDAPGroup(
926 companyId, attributes, groupMappings);
927
928 UserGroup userGroup = null;
929
930 try {
931 userGroup = UserGroupLocalServiceUtil.getUserGroup(
932 companyId, ldapGroup.getGroupName());
933
934 UserGroupLocalServiceUtil.updateUserGroup(
935 companyId, userGroup.getUserGroupId(), ldapGroup.getGroupName(),
936 ldapGroup.getDescription());
937 }
938 catch (NoSuchUserGroupException nsuge) {
939 if (_log.isDebugEnabled()) {
940 _log.debug(
941 "Adding user group to portal " + ldapGroup.getGroupName());
942 }
943
944 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
945 companyId);
946
947 LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(true);
948
949 try {
950 userGroup = UserGroupLocalServiceUtil.addUserGroup(
951 defaultUserId, companyId, ldapGroup.getGroupName(),
952 ldapGroup.getDescription());
953 }
954 catch (Exception e) {
955 if (_log.isWarnEnabled()) {
956 _log.warn(
957 "Unable to create user group " +
958 ldapGroup.getGroupName());
959 }
960
961 if (_log.isDebugEnabled()) {
962 _log.debug(e, e);
963 }
964 }
965 finally {
966 LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(
967 false);
968 }
969 }
970
971 addRole(companyId, ldapGroup, userGroup);
972
973 return userGroup;
974 }
975
976 protected void importUsers(
977 long ldapServerId, long companyId, LdapContext ldapContext,
978 Properties userMappings, Properties userExpandoMappings,
979 Properties contactMappings, Properties contactExpandoMappings,
980 long userGroupId, Attribute attribute)
981 throws Exception {
982
983 List<Long> newUserIds = new ArrayList<Long>(attribute.size());
984
985 for (int i = 0; i < attribute.size(); i++) {
986 String fullUserDN = (String)attribute.get(i);
987
988 Attributes userAttributes = null;
989
990 try {
991 userAttributes = PortalLDAPUtil.getUserAttributes(
992 ldapServerId, companyId, ldapContext, fullUserDN);
993 }
994 catch (NameNotFoundException nnfe) {
995 _log.error(
996 "LDAP user not found with fullUserDN " + fullUserDN, nnfe);
997
998 continue;
999 }
1000
1001 try {
1002 User user = importUser(
1003 companyId, userAttributes, userMappings,
1004 userExpandoMappings, contactMappings,
1005 contactExpandoMappings, StringPool.BLANK);
1006
1007 if (user != null) {
1008 if (_log.isDebugEnabled()) {
1009 _log.debug(
1010 "Adding " + user.getUserId() + " to group " +
1011 userGroupId);
1012 }
1013
1014 UserLocalServiceUtil.addUserGroupUsers(
1015 userGroupId, new long[] {user.getUserId()});
1016
1017 newUserIds.add(user.getUserId());
1018 }
1019 }
1020 catch (Exception e) {
1021 _log.error("Unable to load user " + userAttributes, e);
1022 }
1023 }
1024
1025 List<User> userGroupUsers = UserLocalServiceUtil.getUserGroupUsers(
1026 userGroupId);
1027
1028 for (User user : userGroupUsers) {
1029 if (!newUserIds.contains(user.getUserId())) {
1030 UserLocalServiceUtil.deleteUserGroupUser(
1031 userGroupId, user.getUserId());
1032 }
1033 }
1034 }
1035
1036 protected void populateExpandoAttributes(
1037 ExpandoBridge expandoBridge, Map<String, String[]> expandoAttributes) {
1038
1039 for (Map.Entry<String, String[]> expandoAttribute :
1040 expandoAttributes.entrySet()) {
1041
1042 String name = expandoAttribute.getKey();
1043
1044 if (!expandoBridge.hasAttribute(name)) {
1045 continue;
1046 }
1047
1048 int type = expandoBridge.getAttributeType(name);
1049
1050 Serializable value =
1051 ExpandoConverterUtil.getAttributeFromStringArray(
1052 type, expandoAttribute.getValue());
1053
1054 try {
1055 ExpandoValueLocalServiceUtil.addValue(
1056 expandoBridge.getCompanyId(), expandoBridge.getClassName(),
1057 ExpandoTableConstants.DEFAULT_TABLE_NAME, name,
1058 expandoBridge.getClassPK(), value);
1059 }
1060 catch (Exception e) {
1061 _log.error(e, e);
1062 }
1063 }
1064 }
1065
1066 protected void updateExpandoAttributes(User user, LDAPUser ldapUser)
1067 throws Exception {
1068
1069 ExpandoBridge userExpandoBridge = user.getExpandoBridge();
1070
1071 populateExpandoAttributes(
1072 userExpandoBridge, ldapUser.getUserExpandoAttributes());
1073
1074 Contact contact = user.getContact();
1075
1076 ExpandoBridge contactExpandoBridge = contact.getExpandoBridge();
1077
1078 populateExpandoAttributes(
1079 contactExpandoBridge, ldapUser.getContactExpandoAttributes());
1080 }
1081
1082 protected User updateUser(
1083 long companyId, LDAPUser ldapUser, User user, String password,
1084 String modifiedDate)
1085 throws Exception {
1086
1087 Date ldapUserModifiedDate = null;
1088
1089 try {
1090 if (Validator.isNull(modifiedDate)) {
1091 if (_log.isInfoEnabled()) {
1092 _log.info(
1093 "LDAP entry never modified, skipping user " +
1094 user.getEmailAddress());
1095 }
1096
1097 return user;
1098 }
1099 else {
1100 ldapUserModifiedDate = LDAPUtil.parseDate(modifiedDate);
1101 }
1102
1103 if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
1104 ldapUser.isAutoPassword()) {
1105
1106 if (_log.isDebugEnabled()) {
1107 _log.debug(
1108 "User is already synchronized, skipping user " +
1109 user.getEmailAddress());
1110 }
1111
1112 return user;
1113 }
1114 }
1115 catch (ParseException pe) {
1116 if (_log.isDebugEnabled()) {
1117 _log.debug(
1118 "Unable to parse LDAP modify timestamp " + modifiedDate,
1119 pe);
1120 }
1121 }
1122
1123 boolean passwordReset = ldapUser.isPasswordReset();
1124
1125 if (PrefsPropsUtil.getBoolean(
1126 companyId, PropsKeys.LDAP_EXPORT_ENABLED,
1127 PropsValues.LDAP_EXPORT_ENABLED)) {
1128
1129 passwordReset = user.isPasswordReset();
1130 }
1131
1132 if (!PropsValues.LDAP_IMPORT_USER_PASSWORD_ENABLED) {
1133 password = PropsValues.LDAP_IMPORT_USER_PASSWORD_DEFAULT;
1134
1135 if (password.equalsIgnoreCase(_USER_PASSWORD_SCREEN_NAME)) {
1136 password = ldapUser.getScreenName();
1137 }
1138 }
1139
1140 if (Validator.isNull(ldapUser.getScreenName())) {
1141 ldapUser.setAutoScreenName(true);
1142 }
1143
1144 if (ldapUser.isAutoScreenName()) {
1145 ScreenNameGenerator screenNameGenerator =
1146 ScreenNameGeneratorFactory.getInstance();
1147
1148 ldapUser.setScreenName(
1149 screenNameGenerator.generate(
1150 companyId, user.getUserId(), ldapUser.getEmailAddress()));
1151 }
1152
1153 Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
1154
1155 birthdayCal.setTime(user.getContact().getBirthday());
1156
1157 int birthdayMonth = birthdayCal.get(Calendar.MONTH);
1158 int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
1159 int birthdayYear = birthdayCal.get(Calendar.YEAR);
1160
1161 if (ldapUser.isUpdatePassword()) {
1162 UserLocalServiceUtil.updatePassword(
1163 user.getUserId(), password, password, passwordReset, true);
1164 }
1165
1166 Contact contact = user.getContact();
1167
1168 Set<String> ldapIgnoreAttributes = SetUtil.fromArray(
1169 PropsValues.LDAP_USER_IGNORE_ATTRIBUTES);
1170
1171 for (String attribute : ldapIgnoreAttributes) {
1172 Object value = BeanPropertiesUtil.getObjectSilent(user, attribute);
1173
1174 if (value == null) {
1175 value = BeanPropertiesUtil.getObjectSilent(contact, attribute);
1176 }
1177
1178 if (value != null) {
1179 BeanPropertiesUtil.setProperty(ldapUser, attribute, value);
1180 }
1181 }
1182
1183 user = UserLocalServiceUtil.updateUser(
1184 user.getUserId(), password, StringPool.BLANK, StringPool.BLANK,
1185 passwordReset, ldapUser.getReminderQueryQuestion(),
1186 ldapUser.getReminderQueryAnswer(), ldapUser.getScreenName(),
1187 ldapUser.getEmailAddress(), ldapUser.getFacebookId(),
1188 ldapUser.getOpenId(), ldapUser.getLanguageId(),
1189 ldapUser.getTimeZoneId(), ldapUser.getGreeting(),
1190 ldapUser.getComments(), ldapUser.getFirstName(),
1191 ldapUser.getMiddleName(), ldapUser.getLastName(),
1192 ldapUser.getPrefixId(), ldapUser.getSuffixId(), ldapUser.isMale(),
1193 birthdayMonth, birthdayDay, birthdayYear, ldapUser.getSmsSn(),
1194 ldapUser.getAimSn(), ldapUser.getFacebookSn(), ldapUser.getIcqSn(),
1195 ldapUser.getJabberSn(), ldapUser.getMsnSn(),
1196 ldapUser.getMySpaceSn(), ldapUser.getSkypeSn(),
1197 ldapUser.getTwitterSn(), ldapUser.getYmSn(), ldapUser.getJobTitle(),
1198 ldapUser.getGroupIds(), ldapUser.getOrganizationIds(),
1199 ldapUser.getRoleIds(), ldapUser.getUserGroupRoles(),
1200 ldapUser.getUserGroupIds(), ldapUser.getServiceContext());
1201
1202 if (ldapUserModifiedDate != null) {
1203 user = UserLocalServiceUtil.updateModifiedDate(
1204 user.getUserId(), ldapUserModifiedDate);
1205 }
1206
1207 if (ldapUser.isUpdatePortrait()) {
1208 byte[] portraitBytes = ldapUser.getPortraitBytes();
1209
1210 if ((portraitBytes != null) && (portraitBytes.length > 0)) {
1211 UserLocalServiceUtil.updatePortrait(
1212 user.getUserId(), portraitBytes);
1213 }
1214 else {
1215 UserLocalServiceUtil.deletePortrait(user.getUserId());
1216 }
1217 }
1218
1219 return user;
1220 }
1221
1222 private static final String _IMPORT_BY_GROUP = "group";
1223
1224 private static final String _IMPORT_BY_USER = "user";
1225
1226 private static final String _USER_PASSWORD_SCREEN_NAME = "screenName";
1227
1228 private static Log _log = LogFactoryUtil.getLog(
1229 PortalLDAPImporterImpl.class);
1230
1231 private LDAPToPortalConverter _ldapToPortalConverter;
1232 private PortalCache _portalCache = SingleVMPoolUtil.getCache(
1233 PortalLDAPImporter.class.getName(), false);
1234
1235 }