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