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