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.Time;
036 import com.liferay.portal.kernel.util.Validator;
037 import com.liferay.portal.model.Company;
038 import com.liferay.portal.model.CompanyConstants;
039 import com.liferay.portal.model.Contact;
040 import com.liferay.portal.model.Group;
041 import com.liferay.portal.model.Role;
042 import com.liferay.portal.model.RoleConstants;
043 import com.liferay.portal.model.User;
044 import com.liferay.portal.model.UserGroup;
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, 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, String password)
851 throws Exception {
852
853 LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);
854
855 try {
856 AttributesTransformer attributesTransformer =
857 AttributesTransformerFactory.getInstance();
858
859 attributes = attributesTransformer.transformUser(attributes);
860
861 LDAPUser ldapUser = _ldapToPortalConverter.importLDAPUser(
862 companyId, attributes, userMappings, userExpandoMappings,
863 contactMappings, contactExpandoMappings, password);
864
865 User user = getUser(companyId, ldapUser);
866
867 if ((user != null) && user.isDefaultUser()) {
868 return user;
869 }
870
871 if (user == null) {
872 user = addUser(companyId, ldapUser, password);
873 }
874
875 String modifiedDate = LDAPUtil.getAttributeString(
876 attributes, "modifyTimestamp");
877
878 user = updateUser(
879 companyId, ldapUser, user, password, modifiedDate);
880
881 updateExpandoAttributes(user, ldapUser);
882
883 return user;
884 }
885 finally {
886 LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
887 }
888 }
889
890 protected UserGroup importUserGroup(
891 long companyId, Attributes attributes, Properties groupMappings)
892 throws Exception {
893
894 AttributesTransformer attributesTransformer =
895 AttributesTransformerFactory.getInstance();
896
897 attributes = attributesTransformer.transformGroup(attributes);
898
899 LDAPGroup ldapGroup = _ldapToPortalConverter.importLDAPGroup(
900 companyId, attributes, groupMappings);
901
902 UserGroup userGroup = null;
903
904 try {
905 userGroup = UserGroupLocalServiceUtil.getUserGroup(
906 companyId, ldapGroup.getGroupName());
907
908 UserGroupLocalServiceUtil.updateUserGroup(
909 companyId, userGroup.getUserGroupId(), ldapGroup.getGroupName(),
910 ldapGroup.getDescription());
911 }
912 catch (NoSuchUserGroupException nsuge) {
913 if (_log.isDebugEnabled()) {
914 _log.debug(
915 "Adding user group to portal " + ldapGroup.getGroupName());
916 }
917
918 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
919 companyId);
920
921 LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(true);
922
923 try {
924 userGroup = UserGroupLocalServiceUtil.addUserGroup(
925 defaultUserId, companyId, ldapGroup.getGroupName(),
926 ldapGroup.getDescription());
927 }
928 catch (Exception e) {
929 if (_log.isWarnEnabled()) {
930 _log.warn(
931 "Unable to create user group " +
932 ldapGroup.getGroupName());
933 }
934
935 if (_log.isDebugEnabled()) {
936 _log.debug(e, e);
937 }
938 }
939 finally {
940 LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(
941 false);
942 }
943 }
944
945 addRole(companyId, ldapGroup, userGroup);
946
947 return userGroup;
948 }
949
950 protected void importUsers(
951 long ldapServerId, long companyId, LdapContext ldapContext,
952 Properties userMappings, Properties userExpandoMappings,
953 Properties contactMappings, Properties contactExpandoMappings,
954 long userGroupId, Attribute attribute)
955 throws Exception {
956
957 List<Long> newUserIds = new ArrayList<Long>(attribute.size());
958
959 for (int i = 0; i < attribute.size(); i++) {
960 String fullUserDN = (String)attribute.get(i);
961
962 Attributes userAttributes = null;
963
964 try {
965 userAttributes = PortalLDAPUtil.getUserAttributes(
966 ldapServerId, companyId, ldapContext, fullUserDN);
967 }
968 catch (NameNotFoundException nnfe) {
969 _log.error(
970 "LDAP user not found with fullUserDN " + fullUserDN, nnfe);
971
972 continue;
973 }
974
975 try {
976 User user = importUser(
977 companyId, userAttributes, userMappings,
978 userExpandoMappings, contactMappings,
979 contactExpandoMappings, StringPool.BLANK);
980
981 if (user != null) {
982 if (_log.isDebugEnabled()) {
983 _log.debug(
984 "Adding " + user.getUserId() + " to group " +
985 userGroupId);
986 }
987
988 UserLocalServiceUtil.addUserGroupUsers(
989 userGroupId, new long[] {user.getUserId()});
990
991 newUserIds.add(user.getUserId());
992 }
993 }
994 catch (Exception e) {
995 _log.error("Unable to load user " + userAttributes, e);
996 }
997 }
998
999 List<User> userGroupUsers = UserLocalServiceUtil.getUserGroupUsers(
1000 userGroupId);
1001
1002 for (User user : userGroupUsers) {
1003 if (!newUserIds.contains(user.getUserId())) {
1004 UserLocalServiceUtil.deleteUserGroupUser(
1005 userGroupId, user.getUserId());
1006 }
1007 }
1008 }
1009
1010 protected void populateExpandoAttributes(
1011 ExpandoBridge expandoBridge, Map<String, String> expandoAttributes) {
1012
1013 for (Map.Entry<String, String> expandoAttribute :
1014 expandoAttributes.entrySet()) {
1015
1016 String name = expandoAttribute.getKey();
1017
1018 if (!expandoBridge.hasAttribute(name)) {
1019 continue;
1020 }
1021
1022 int type = expandoBridge.getAttributeType(name);
1023
1024 Serializable value = ExpandoConverterUtil.getAttributeFromString(
1025 type, expandoAttribute.getValue());
1026
1027 try {
1028 ExpandoValueLocalServiceUtil.addValue(
1029 expandoBridge.getCompanyId(), expandoBridge.getClassName(),
1030 ExpandoTableConstants.DEFAULT_TABLE_NAME, name,
1031 expandoBridge.getClassPK(), value);
1032 }
1033 catch (Exception e) {
1034 _log.error(e, e);
1035 }
1036 }
1037 }
1038
1039 protected void updateExpandoAttributes(User user, LDAPUser ldapUser)
1040 throws Exception {
1041
1042 ExpandoBridge userExpandoBridge = user.getExpandoBridge();
1043
1044 populateExpandoAttributes(
1045 userExpandoBridge, ldapUser.getUserExpandoAttributes());
1046
1047 Contact contact = user.getContact();
1048
1049 ExpandoBridge contactExpandoBridge = contact.getExpandoBridge();
1050
1051 populateExpandoAttributes(
1052 contactExpandoBridge, ldapUser.getContactExpandoAttributes());
1053 }
1054
1055 protected User updateUser(
1056 long companyId, LDAPUser ldapUser, User user, String password,
1057 String modifiedDate)
1058 throws Exception {
1059
1060 Date ldapUserModifiedDate = null;
1061
1062 try {
1063 if (Validator.isNull(modifiedDate)) {
1064 if (_log.isInfoEnabled()) {
1065 _log.info(
1066 "LDAP entry never modified, skipping user " +
1067 user.getEmailAddress());
1068 }
1069
1070 return user;
1071 }
1072 else {
1073 ldapUserModifiedDate = LDAPUtil.parseDate(modifiedDate);
1074 }
1075
1076 if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
1077 ldapUser.isAutoPassword()) {
1078
1079 if (_log.isDebugEnabled()) {
1080 _log.debug(
1081 "User is already synchronized, skipping user " +
1082 user.getEmailAddress());
1083 }
1084
1085 return user;
1086 }
1087 }
1088 catch (ParseException pe) {
1089 if (_log.isDebugEnabled()) {
1090 _log.debug(
1091 "Unable to parse LDAP modify timestamp " + modifiedDate,
1092 pe);
1093 }
1094 }
1095
1096 boolean passwordReset = ldapUser.isPasswordReset();
1097
1098 if (PrefsPropsUtil.getBoolean(
1099 companyId, PropsKeys.LDAP_EXPORT_ENABLED,
1100 PropsValues.LDAP_EXPORT_ENABLED)) {
1101
1102 passwordReset = user.isPasswordReset();
1103 }
1104
1105 if (!PropsValues.LDAP_IMPORT_USER_PASSWORD_ENABLED) {
1106 password = PropsValues.LDAP_IMPORT_USER_PASSWORD_DEFAULT;
1107
1108 if (password.equalsIgnoreCase(_USER_PASSWORD_SCREEN_NAME)) {
1109 password = ldapUser.getScreenName();
1110 }
1111 }
1112
1113 if (Validator.isNull(ldapUser.getScreenName())) {
1114 ldapUser.setAutoScreenName(true);
1115 }
1116
1117 if (ldapUser.isAutoScreenName()) {
1118 ScreenNameGenerator screenNameGenerator =
1119 ScreenNameGeneratorFactory.getInstance();
1120
1121 ldapUser.setScreenName(
1122 screenNameGenerator.generate(
1123 companyId, user.getUserId(), ldapUser.getEmailAddress()));
1124 }
1125
1126 Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
1127
1128 birthdayCal.setTime(user.getContact().getBirthday());
1129
1130 int birthdayMonth = birthdayCal.get(Calendar.MONTH);
1131 int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
1132 int birthdayYear = birthdayCal.get(Calendar.YEAR);
1133
1134 if (ldapUser.isUpdatePassword()) {
1135 UserLocalServiceUtil.updatePassword(
1136 user.getUserId(), password, password, passwordReset, true);
1137 }
1138
1139 Contact contact = user.getContact();
1140
1141 Set<String> ldapIgnoreAttributes = SetUtil.fromArray(
1142 PropsValues.LDAP_USER_IGNORE_ATTRIBUTES);
1143
1144 for (String attribute : ldapIgnoreAttributes) {
1145 Object value = BeanPropertiesUtil.getObjectSilent(user, attribute);
1146
1147 if (value == null) {
1148 value = BeanPropertiesUtil.getObjectSilent(contact, attribute);
1149 }
1150
1151 if (value != null) {
1152 BeanPropertiesUtil.setProperty(ldapUser, attribute, value);
1153 }
1154 }
1155
1156 user = UserLocalServiceUtil.updateUser(
1157 user.getUserId(), password, StringPool.BLANK, StringPool.BLANK,
1158 passwordReset, ldapUser.getReminderQueryQuestion(),
1159 ldapUser.getReminderQueryAnswer(), ldapUser.getScreenName(),
1160 ldapUser.getEmailAddress(), ldapUser.getFacebookId(),
1161 ldapUser.getOpenId(), ldapUser.getLanguageId(),
1162 ldapUser.getTimeZoneId(), ldapUser.getGreeting(),
1163 ldapUser.getComments(), ldapUser.getFirstName(),
1164 ldapUser.getMiddleName(), ldapUser.getLastName(),
1165 ldapUser.getPrefixId(), ldapUser.getSuffixId(), ldapUser.isMale(),
1166 birthdayMonth, birthdayDay, birthdayYear, ldapUser.getSmsSn(),
1167 ldapUser.getAimSn(), ldapUser.getFacebookSn(), ldapUser.getIcqSn(),
1168 ldapUser.getJabberSn(), ldapUser.getMsnSn(),
1169 ldapUser.getMySpaceSn(), ldapUser.getSkypeSn(),
1170 ldapUser.getTwitterSn(), ldapUser.getYmSn(), ldapUser.getJobTitle(),
1171 ldapUser.getGroupIds(), ldapUser.getOrganizationIds(),
1172 ldapUser.getRoleIds(), ldapUser.getUserGroupRoles(),
1173 ldapUser.getUserGroupIds(), ldapUser.getServiceContext());
1174
1175 if (ldapUserModifiedDate != null) {
1176 user = UserLocalServiceUtil.updateModifiedDate(
1177 user.getUserId(), ldapUserModifiedDate);
1178 }
1179
1180 if (ldapUser.isUpdatePortrait()) {
1181 byte[] portraitBytes = ldapUser.getPortraitBytes();
1182
1183 if ((portraitBytes != null) && (portraitBytes.length > 0)) {
1184 UserLocalServiceUtil.updatePortrait(
1185 user.getUserId(), portraitBytes);
1186 }
1187 else {
1188 UserLocalServiceUtil.deletePortrait(user.getUserId());
1189 }
1190 }
1191
1192 return user;
1193 }
1194
1195 private static final String _IMPORT_BY_GROUP = "group";
1196
1197 private static final String _IMPORT_BY_USER = "user";
1198
1199 private static final String _USER_PASSWORD_SCREEN_NAME = "screenName";
1200
1201 private static Log _log = LogFactoryUtil.getLog(
1202 PortalLDAPImporterImpl.class);
1203
1204 private LDAPToPortalConverter _ldapToPortalConverter;
1205 private PortalCache _portalCache = SingleVMPoolUtil.getCache(
1206 PortalLDAPImporter.class.getName(), false);
1207
1208 }