001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.ldap;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020    import com.liferay.portal.kernel.util.PropsKeys;
021    import com.liferay.portal.kernel.workflow.WorkflowConstants;
022    import com.liferay.portal.model.Contact;
023    import com.liferay.portal.model.User;
024    import com.liferay.portal.model.UserGroup;
025    import com.liferay.portal.security.exportimport.UserExporter;
026    import com.liferay.portal.security.exportimport.UserOperation;
027    import com.liferay.portal.service.UserGroupLocalServiceUtil;
028    import com.liferay.portal.service.UserLocalServiceUtil;
029    import com.liferay.portal.util.PrefsPropsUtil;
030    import com.liferay.portal.util.PropsValues;
031    
032    import java.io.Serializable;
033    
034    import java.util.List;
035    import java.util.Map;
036    import java.util.Properties;
037    
038    import javax.naming.Binding;
039    import javax.naming.CompositeName;
040    import javax.naming.Name;
041    import javax.naming.NameNotFoundException;
042    import javax.naming.directory.Attribute;
043    import javax.naming.directory.Attributes;
044    import javax.naming.directory.ModificationItem;
045    import javax.naming.directory.SchemaViolationException;
046    import javax.naming.ldap.LdapContext;
047    
048    /**
049     * @author Michael C. Han
050     * @author Brian Wing Shun Chan
051     * @author Marcellus Tavares
052     * @author Wesley Gong
053     * @author Vilmos Papp
054     */
055    @DoPrivileged
056    public class LDAPUserExporterImpl implements UserExporter {
057    
058            @Override
059            public void exportUser(
060                            Contact contact, Map<String, Serializable> contactExpandoAttributes)
061                    throws Exception {
062    
063                    long companyId = contact.getCompanyId();
064    
065                    if (!PrefsPropsUtil.getBoolean(
066                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
067                                    PropsValues.LDAP_AUTH_ENABLED) ||
068                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
069    
070                            return;
071                    }
072    
073                    User user = UserLocalServiceUtil.getUserByContactId(
074                            contact.getContactId());
075    
076                    if (user.isDefaultUser() ||
077                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
078    
079                            return;
080                    }
081    
082                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
083                            companyId, user.getScreenName(), user.getEmailAddress());
084    
085                    LdapContext ldapContext = PortalLDAPUtil.getContext(
086                            ldapServerId, companyId);
087    
088                    try {
089                            if (ldapContext == null) {
090                                    return;
091                            }
092    
093                            Properties contactMappings = LDAPSettingsUtil.getContactMappings(
094                                    ldapServerId, companyId);
095                            Properties contactExpandoMappings =
096                                    LDAPSettingsUtil.getContactExpandoMappings(
097                                            ldapServerId, companyId);
098    
099                            Binding binding = PortalLDAPUtil.getUser(
100                                    ldapServerId, contact.getCompanyId(), user.getScreenName(),
101                                    user.getEmailAddress());
102    
103                            if (binding == null) {
104                                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
105                                            ldapServerId, companyId);
106    
107                                    binding = addUser(
108                                            ldapServerId, ldapContext, user, userMappings);
109                            }
110    
111                            Name name = new CompositeName();
112    
113                            name.add(
114                                    PortalLDAPUtil.getNameInNamespace(
115                                            ldapServerId, companyId, binding));
116    
117                            Modifications modifications =
118                                    _portalToLDAPConverter.getLDAPContactModifications(
119                                            contact, contactExpandoAttributes, contactMappings,
120                                            contactExpandoMappings);
121    
122                            if (modifications == null) {
123                                    return;
124                            }
125    
126                            ModificationItem[] modificationItems = modifications.getItems();
127    
128                            ldapContext.modifyAttributes(name, modificationItems);
129                    }
130                    finally {
131                            if (ldapContext != null) {
132                                    ldapContext.close();
133                            }
134                    }
135            }
136    
137            @Override
138            public void exportUser(
139                            long userId, long userGroupId, UserOperation userOperation)
140                    throws Exception {
141    
142                    User user = UserLocalServiceUtil.getUser(userId);
143    
144                    long companyId = user.getCompanyId();
145    
146                    if (!PrefsPropsUtil.getBoolean(
147                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
148                                    PropsValues.LDAP_AUTH_ENABLED) ||
149                            !LDAPSettingsUtil.isExportEnabled(companyId) ||
150                            !LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
151    
152                            return;
153                    }
154    
155                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
156                            companyId, user.getScreenName(), user.getEmailAddress());
157    
158                    LdapContext ldapContext = PortalLDAPUtil.getContext(
159                            ldapServerId, companyId);
160    
161                    if (ldapContext == null) {
162                            return;
163                    }
164    
165                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
166                            userGroupId);
167    
168                    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
169                            ldapServerId, companyId);
170                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
171                            ldapServerId, companyId);
172    
173                    Binding binding = PortalLDAPUtil.getGroup(
174                            ldapServerId, companyId, userGroup.getName());
175    
176                    try {
177                            if (binding == null) {
178                                    if (userOperation == UserOperation.ADD) {
179                                            addGroup(
180                                                    ldapServerId, ldapContext, userGroup, user,
181                                                    groupMappings, userMappings);
182                                    }
183    
184                                    return;
185                            }
186    
187                            Name name = new CompositeName();
188    
189                            name.add(
190                                    PortalLDAPUtil.getNameInNamespace(
191                                            ldapServerId, companyId, binding));
192    
193                            Modifications modifications =
194                                    _portalToLDAPConverter.getLDAPGroupModifications(
195                                            ldapServerId, userGroup, user, groupMappings, userMappings,
196                                            userOperation);
197    
198                            ModificationItem[] modificationItems = modifications.getItems();
199    
200                            ldapContext.modifyAttributes(name, modificationItems);
201                    }
202                    catch (SchemaViolationException sve) {
203                            String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
204                                    ldapServerId, companyId, binding);
205    
206                            Attributes attributes = PortalLDAPUtil.getGroupAttributes(
207                                    ldapServerId, companyId, ldapContext, fullGroupDN, true);
208    
209                            Attribute groupMembers = attributes.get(
210                                    groupMappings.getProperty(GroupConverterKeys.USER));
211    
212                            if ((groupMembers != null) && (groupMembers.size() == 1)) {
213                                    ldapContext.unbind(fullGroupDN);
214                            }
215                    }
216                    finally {
217                            if (ldapContext != null) {
218                                    ldapContext.close();
219                            }
220                    }
221            }
222    
223            @Override
224            public void exportUser(
225                            User user, Map<String, Serializable> userExpandoAttributes)
226                    throws Exception {
227    
228                    if (user.isDefaultUser() ||
229                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
230    
231                            return;
232                    }
233    
234                    long companyId = user.getCompanyId();
235    
236                    if (!PrefsPropsUtil.getBoolean(
237                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
238                                    PropsValues.LDAP_AUTH_ENABLED) ||
239                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
240    
241                            return;
242                    }
243    
244                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
245                            companyId, user.getScreenName(), user.getEmailAddress());
246    
247                    LdapContext ldapContext = PortalLDAPUtil.getContext(
248                            ldapServerId, companyId);
249    
250                    try {
251                            if (ldapContext == null) {
252                                    return;
253                            }
254    
255                            Properties userMappings = LDAPSettingsUtil.getUserMappings(
256                                    ldapServerId, companyId);
257                            Properties userExpandoMappings =
258                                    LDAPSettingsUtil.getUserExpandoMappings(
259                                            ldapServerId, companyId);
260    
261                            Binding binding = PortalLDAPUtil.getUser(
262                                    ldapServerId, user.getCompanyId(), user.getScreenName(),
263                                    user.getEmailAddress(), true);
264    
265                            if (binding == null) {
266                                    binding = addUser(
267                                            ldapServerId, ldapContext, user, userMappings);
268                            }
269    
270                            Name name = new CompositeName();
271    
272                            name.add(
273                                    PortalLDAPUtil.getNameInNamespace(
274                                            ldapServerId, companyId, binding));
275    
276                            Modifications modifications =
277                                    _portalToLDAPConverter.getLDAPUserModifications(
278                                            user, userExpandoAttributes, userMappings,
279                                            userExpandoMappings);
280    
281                            if (modifications == null) {
282                                    return;
283                            }
284    
285                            ModificationItem[] modificationItems = modifications.getItems();
286    
287                            ldapContext.modifyAttributes(name, modificationItems);
288    
289                            if (!LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
290                                    return;
291                            }
292    
293                            List<UserGroup> userGroups =
294                                    UserGroupLocalServiceUtil.getUserUserGroups(user.getUserId());
295    
296                            for (UserGroup userGroup : userGroups) {
297                                    exportUser(
298                                            user.getUserId(), userGroup.getUserGroupId(),
299                                            UserOperation.ADD);
300                            }
301    
302                            Modifications groupModifications =
303                                    _portalToLDAPConverter.getLDAPUserGroupModifications(
304                                            ldapServerId, userGroups, user, userMappings);
305    
306                            ModificationItem[] groupModificationItems =
307                                    groupModifications.getItems();
308    
309                            if (groupModificationItems.length > 0) {
310                                    ldapContext.modifyAttributes(name, groupModificationItems);
311                            }
312                    }
313                    catch (NameNotFoundException nnfe) {
314                            if (PrefsPropsUtil.getBoolean(
315                                            companyId, PropsKeys.LDAP_AUTH_REQUIRED)) {
316    
317                                    throw nnfe;
318                            }
319    
320                            _log.error(nnfe, nnfe);
321                    }
322                    finally {
323                            if (ldapContext != null) {
324                                    ldapContext.close();
325                            }
326                    }
327            }
328    
329            public void setPortalToLDAPConverter(
330                    PortalToLDAPConverter portalToLDAPConverter) {
331    
332                    _portalToLDAPConverter = portalToLDAPConverter;
333            }
334    
335            protected Binding addGroup(
336                            long ldapServerId, LdapContext ldapContext, UserGroup userGroup,
337                            User user, Properties groupMappings, Properties userMappings)
338                    throws Exception {
339    
340                    Name name = new CompositeName();
341    
342                    name.add(
343                            _portalToLDAPConverter.getGroupDNName(
344                                    ldapServerId, userGroup, groupMappings));
345    
346                    Attributes attributes = _portalToLDAPConverter.getLDAPGroupAttributes(
347                            ldapServerId, userGroup, user, groupMappings, userMappings);
348    
349                    ldapContext.bind(name, new PortalLDAPContext(attributes));
350    
351                    Binding binding = PortalLDAPUtil.getGroup(
352                            ldapServerId, userGroup.getCompanyId(), userGroup.getName());
353    
354                    return binding;
355            }
356    
357            protected Binding addUser(
358                            long ldapServerId, LdapContext ldapContext, User user,
359                            Properties userMappings)
360                    throws Exception {
361    
362                    Name name = new CompositeName();
363    
364                    name.add(
365                            _portalToLDAPConverter.getUserDNName(
366                                    ldapServerId, user, userMappings));
367    
368                    Attributes attributes = _portalToLDAPConverter.getLDAPUserAttributes(
369                            ldapServerId, user, userMappings);
370    
371                    ldapContext.bind(name, new PortalLDAPContext(attributes));
372    
373                    Binding binding = PortalLDAPUtil.getUser(
374                            ldapServerId, user.getCompanyId(), user.getScreenName(),
375                            user.getEmailAddress());
376    
377                    return binding;
378            }
379    
380            private static final Log _log = LogFactoryUtil.getLog(
381                    LDAPUserExporterImpl.class);
382    
383            private PortalToLDAPConverter _portalToLDAPConverter;
384    
385    }