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.portlet.login.action;
016    
017    import com.liferay.portal.NoSuchUserException;
018    import com.liferay.portal.kernel.facebook.FacebookConnectUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.portlet.LiferayWindowState;
021    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
022    import com.liferay.portal.kernel.util.LocaleUtil;
023    import com.liferay.portal.kernel.util.ParamUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.kernel.workflow.WorkflowConstants;
027    import com.liferay.portal.model.Contact;
028    import com.liferay.portal.model.User;
029    import com.liferay.portal.model.UserGroupRole;
030    import com.liferay.portal.security.auth.PrincipalException;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portal.service.UserLocalServiceUtil;
033    import com.liferay.portal.struts.ActionConstants;
034    import com.liferay.portal.struts.PortletAction;
035    import com.liferay.portal.theme.ThemeDisplay;
036    import com.liferay.portal.util.PortletKeys;
037    import com.liferay.portal.util.WebKeys;
038    import com.liferay.portlet.PortletURLFactoryUtil;
039    
040    import java.util.Calendar;
041    import java.util.List;
042    import java.util.Locale;
043    
044    import javax.portlet.PortletConfig;
045    import javax.portlet.PortletMode;
046    import javax.portlet.PortletRequest;
047    import javax.portlet.PortletURL;
048    import javax.portlet.RenderRequest;
049    import javax.portlet.RenderResponse;
050    
051    import javax.servlet.http.HttpServletRequest;
052    import javax.servlet.http.HttpServletResponse;
053    import javax.servlet.http.HttpSession;
054    
055    import org.apache.struts.action.ActionForm;
056    import org.apache.struts.action.ActionForward;
057    import org.apache.struts.action.ActionMapping;
058    
059    /**
060     * @author Wilson Man
061     * @author Sergio González
062     * @author Mika Koivisto
063     */
064    public class FacebookConnectAction extends PortletAction {
065    
066            @Override
067            public ActionForward render(
068                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
069                            RenderRequest renderRequest, RenderResponse renderResponse)
070                    throws Exception {
071    
072                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
073                            WebKeys.THEME_DISPLAY);
074    
075                    if (!FacebookConnectUtil.isEnabled(themeDisplay.getCompanyId())) {
076                            return mapping.findForward("portlet.login.login");
077                    }
078    
079                    return mapping.findForward("portlet.login.facebook_login");
080            }
081    
082            @Override
083            public ActionForward strutsExecute(
084                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
085                            HttpServletResponse response)
086                    throws Exception {
087    
088                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
089                            WebKeys.THEME_DISPLAY);
090    
091                    if (!FacebookConnectUtil.isEnabled(themeDisplay.getCompanyId())) {
092                            throw new PrincipalException();
093                    }
094    
095                    HttpSession session = request.getSession();
096    
097                    String redirect = ParamUtil.getString(request, "redirect");
098    
099                    String code = ParamUtil.getString(request, "code");
100    
101                    String token = FacebookConnectUtil.getAccessToken(
102                            themeDisplay.getCompanyId(), redirect, code);
103    
104                    if (Validator.isNotNull(token)) {
105                            session.setAttribute(WebKeys.FACEBOOK_ACCESS_TOKEN, token);
106    
107                            User user = setFacebookCredentials(
108                                    session, themeDisplay.getCompanyId(), token);
109    
110                            if ((user != null) &&
111                                    (user.getStatus() == WorkflowConstants.STATUS_INCOMPLETE)) {
112    
113                                    redirectUpdateAccount(request, response, user);
114    
115                                    return null;
116                            }
117                    }
118                    else {
119                            return mapping.findForward(ActionConstants.COMMON_REFERER_JSP);
120                    }
121    
122                    response.sendRedirect(redirect);
123    
124                    return null;
125            }
126    
127            protected User addUser(
128                            HttpSession session, long companyId, JSONObject jsonObject)
129                    throws Exception {
130    
131                    long creatorUserId = 0;
132                    boolean autoPassword = true;
133                    String password1 = StringPool.BLANK;
134                    String password2 = StringPool.BLANK;
135                    boolean autoScreenName = true;
136                    String screenName = StringPool.BLANK;
137                    String emailAddress = jsonObject.getString("email");
138                    long facebookId = jsonObject.getLong("id");
139                    String openId = StringPool.BLANK;
140                    Locale locale = LocaleUtil.getDefault();
141                    String firstName = jsonObject.getString("first_name");
142                    String middleName = StringPool.BLANK;
143                    String lastName = jsonObject.getString("last_name");
144                    int prefixId = 0;
145                    int suffixId = 0;
146                    boolean male = Validator.equals(jsonObject.getString("gender"), "male");
147                    int birthdayMonth = Calendar.JANUARY;
148                    int birthdayDay = 1;
149                    int birthdayYear = 1970;
150                    String jobTitle = StringPool.BLANK;
151                    long[] groupIds = null;
152                    long[] organizationIds = null;
153                    long[] roleIds = null;
154                    long[] userGroupIds = null;
155                    boolean sendEmail = true;
156    
157                    ServiceContext serviceContext = new ServiceContext();
158    
159                    User user = UserLocalServiceUtil.addUser(
160                            creatorUserId, companyId, autoPassword, password1, password2,
161                            autoScreenName, screenName, emailAddress, facebookId, openId,
162                            locale, firstName, middleName, lastName, prefixId, suffixId, male,
163                            birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds,
164                            organizationIds, roleIds, userGroupIds, sendEmail, serviceContext);
165    
166                    user = UserLocalServiceUtil.updateLastLogin(
167                            user.getUserId(), user.getLoginIP());
168    
169                    user = UserLocalServiceUtil.updatePasswordReset(
170                            user.getUserId(), false);
171    
172                    user = UserLocalServiceUtil.updateEmailAddressVerified(
173                            user.getUserId(), true);
174    
175                    session.setAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
176    
177                    return user;
178            }
179    
180            protected void redirectUpdateAccount(
181                            HttpServletRequest request, HttpServletResponse response, User user)
182                    throws Exception {
183    
184                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
185                            WebKeys.THEME_DISPLAY);
186    
187                    PortletURL portletURL = PortletURLFactoryUtil.create(
188                            request, PortletKeys.LOGIN, themeDisplay.getPlid(),
189                            PortletRequest.RENDER_PHASE);
190    
191                    portletURL.setParameter("saveLastPath", Boolean.FALSE.toString());
192                    portletURL.setParameter("struts_action", "/login/update_account");
193    
194                    PortletURL redirectURL = PortletURLFactoryUtil.create(
195                            request, PortletKeys.LOGIN, themeDisplay.getPlid(),
196                            PortletRequest.RENDER_PHASE);
197    
198                    redirectURL.setParameter("struts_action", "/login/login_redirect");
199                    redirectURL.setParameter("emailAddress", user.getEmailAddress());
200                    redirectURL.setParameter("anonymousUser", Boolean.FALSE.toString());
201                    redirectURL.setPortletMode(PortletMode.VIEW);
202                    redirectURL.setWindowState(LiferayWindowState.POP_UP);
203    
204                    portletURL.setParameter("redirect", redirectURL.toString());
205                    portletURL.setParameter("userId", String.valueOf(user.getUserId()));
206                    portletURL.setParameter("emailAddress", user.getEmailAddress());
207                    portletURL.setParameter("firstName", user.getFirstName());
208                    portletURL.setParameter("lastName", user.getLastName());
209                    portletURL.setPortletMode(PortletMode.VIEW);
210                    portletURL.setWindowState(LiferayWindowState.POP_UP);
211    
212                    response.sendRedirect(portletURL.toString());
213            }
214    
215            protected User setFacebookCredentials(
216                            HttpSession session, long companyId, String token)
217                    throws Exception {
218    
219                    JSONObject jsonObject = FacebookConnectUtil.getGraphResources(
220                            companyId, "/me", token,
221                            "id,email,first_name,last_name,gender");
222    
223                    if ((jsonObject == null) ||
224                            (jsonObject.getJSONObject("error") != null)) {
225    
226                            return null;
227                    }
228    
229                    if (FacebookConnectUtil.isVerifiedAccountRequired(companyId) &&
230                            !jsonObject.getBoolean("verified")) {
231    
232                            return null;
233                    }
234    
235                    User user = null;
236    
237                    long facebookId = jsonObject.getLong("id");
238    
239                    if (facebookId > 0) {
240                            try {
241                                    user = UserLocalServiceUtil.getUserByFacebookId(
242                                            companyId, facebookId);
243    
244                                    if (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE) {
245                                            session.setAttribute(
246                                                    WebKeys.FACEBOOK_USER_ID, String.valueOf(facebookId));
247                                    }
248                            }
249                            catch (NoSuchUserException nsue) {
250                            }
251                    }
252    
253                    String emailAddress = jsonObject.getString("email");
254    
255                    if ((user == null) && Validator.isNotNull(emailAddress)) {
256                            try {
257                                    user = UserLocalServiceUtil.getUserByEmailAddress(
258                                            companyId, emailAddress);
259    
260                                    if (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE) {
261                                            session.setAttribute(
262                                                    WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
263                                    }
264                            }
265                            catch (NoSuchUserException nsue) {
266                            }
267                    }
268    
269                    if (user != null) {
270                            if (user.getStatus() == WorkflowConstants.STATUS_INCOMPLETE) {
271                                    session.setAttribute(
272                                            WebKeys.FACEBOOK_INCOMPLETE_USER_ID, facebookId);
273    
274                                    user.setEmailAddress(jsonObject.getString("email"));
275                                    user.setFirstName(jsonObject.getString("first_name"));
276                                    user.setLastName(jsonObject.getString("last_name"));
277    
278                                    return user;
279                            }
280    
281                            user = updateUser(user, jsonObject);
282                    }
283                    else {
284                            user = addUser(session, companyId, jsonObject);
285                    }
286    
287                    return user;
288            }
289    
290            protected User updateUser(User user, JSONObject jsonObject)
291                    throws Exception {
292    
293                    long facebookId = jsonObject.getLong("id");
294                    String emailAddress = jsonObject.getString("email");
295                    String firstName = jsonObject.getString("first_name");
296                    String lastName = jsonObject.getString("last_name");
297                    boolean male = Validator.equals(jsonObject.getString("gender"), "male");
298    
299                    if ((facebookId == user.getFacebookId()) &&
300                            emailAddress.equals(user.getEmailAddress()) &&
301                            firstName.equals(user.getFirstName()) &&
302                            lastName.equals(user.getLastName()) && (male == user.isMale())) {
303    
304                            return user;
305                    }
306    
307                    Contact contact = user.getContact();
308    
309                    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
310    
311                    birthdayCal.setTime(contact.getBirthday());
312    
313                    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
314                    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
315                    int birthdayYear = birthdayCal.get(Calendar.YEAR);
316    
317                    long[] groupIds = null;
318                    long[] organizationIds = null;
319                    long[] roleIds = null;
320                    List<UserGroupRole> userGroupRoles = null;
321                    long[] userGroupIds = null;
322    
323                    ServiceContext serviceContext = new ServiceContext();
324    
325                    if (!emailAddress.equalsIgnoreCase(user.getEmailAddress())) {
326                            UserLocalServiceUtil.updateEmailAddress(
327                                    user.getUserId(), StringPool.BLANK, emailAddress, emailAddress);
328                    }
329    
330                    UserLocalServiceUtil.updateEmailAddressVerified(user.getUserId(), true);
331    
332                    return UserLocalServiceUtil.updateUser(
333                            user.getUserId(), StringPool.BLANK, StringPool.BLANK,
334                            StringPool.BLANK, false, user.getReminderQueryQuestion(),
335                            user.getReminderQueryAnswer(), user.getScreenName(), emailAddress,
336                            facebookId, user.getOpenId(), user.getLanguageId(),
337                            user.getTimeZoneId(), user.getGreeting(), user.getComments(),
338                            firstName, user.getMiddleName(), lastName, contact.getPrefixId(),
339                            contact.getSuffixId(), male, birthdayMonth, birthdayDay,
340                            birthdayYear, contact.getSmsSn(), contact.getAimSn(),
341                            contact.getFacebookSn(), contact.getIcqSn(), contact.getJabberSn(),
342                            contact.getMsnSn(), contact.getMySpaceSn(), contact.getSkypeSn(),
343                            contact.getTwitterSn(), contact.getYmSn(), contact.getJobTitle(),
344                            groupIds, organizationIds, roleIds, userGroupRoles, userGroupIds,
345                            serviceContext);
346            }
347    
348    }