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