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