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