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.StringUtil;
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 actionMapping, ActionForm actionForm,
069                            PortletConfig portletConfig, RenderRequest renderRequest,
070                            RenderResponse renderResponse)
071                    throws Exception {
072    
073                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
074                            WebKeys.THEME_DISPLAY);
075    
076                    if (!FacebookConnectUtil.isEnabled(themeDisplay.getCompanyId())) {
077                            return actionMapping.findForward("portlet.login.login");
078                    }
079    
080                    return actionMapping.findForward("portlet.login.facebook_login");
081            }
082    
083            @Override
084            public ActionForward strutsExecute(
085                            ActionMapping actionMapping, ActionForm actionForm,
086                            HttpServletRequest request, HttpServletResponse response)
087                    throws Exception {
088    
089                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
090                            WebKeys.THEME_DISPLAY);
091    
092                    if (!FacebookConnectUtil.isEnabled(themeDisplay.getCompanyId())) {
093                            throw new PrincipalException();
094                    }
095    
096                    HttpSession session = request.getSession();
097    
098                    String redirect = ParamUtil.getString(request, "redirect");
099    
100                    String code = ParamUtil.getString(request, "code");
101    
102                    String token = FacebookConnectUtil.getAccessToken(
103                            themeDisplay.getCompanyId(), redirect, code);
104    
105                    if (Validator.isNotNull(token)) {
106                            User user = setFacebookCredentials(
107                                    session, themeDisplay.getCompanyId(), token);
108    
109                            if ((user != null) &&
110                                    (user.getStatus() == WorkflowConstants.STATUS_INCOMPLETE)) {
111    
112                                    redirectUpdateAccount(request, response, user);
113    
114                                    return null;
115                            }
116                    }
117                    else {
118                            return actionMapping.findForward(
119                                    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.FAST_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                            session.setAttribute(WebKeys.FACEBOOK_ACCESS_TOKEN, token);
241    
242                            user = UserLocalServiceUtil.fetchUserByFacebookId(
243                                    companyId, facebookId);
244    
245                            if ((user != null) &&
246                                    (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE)) {
247    
248                                    session.setAttribute(
249                                            WebKeys.FACEBOOK_USER_ID, String.valueOf(facebookId));
250                            }
251                    }
252    
253                    String emailAddress = jsonObject.getString("email");
254    
255                    if ((user == null) && Validator.isNotNull(emailAddress)) {
256                            user = UserLocalServiceUtil.fetchUserByEmailAddress(
257                                    companyId, emailAddress);
258    
259                            if ((user != null) &&
260                                    (user.getStatus() != WorkflowConstants.STATUS_INCOMPLETE)) {
261    
262                                    session.setAttribute(
263                                            WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
264                            }
265                    }
266    
267                    if (user != null) {
268                            if (user.getStatus() == WorkflowConstants.STATUS_INCOMPLETE) {
269                                    session.setAttribute(
270                                            WebKeys.FACEBOOK_INCOMPLETE_USER_ID, facebookId);
271    
272                                    user.setEmailAddress(jsonObject.getString("email"));
273                                    user.setFirstName(jsonObject.getString("first_name"));
274                                    user.setLastName(jsonObject.getString("last_name"));
275    
276                                    return user;
277                            }
278    
279                            user = updateUser(user, jsonObject);
280                    }
281                    else {
282                            user = addUser(session, companyId, jsonObject);
283                    }
284    
285                    return user;
286            }
287    
288            protected User updateUser(User user, JSONObject jsonObject)
289                    throws Exception {
290    
291                    long facebookId = jsonObject.getLong("id");
292                    String emailAddress = jsonObject.getString("email");
293                    String firstName = jsonObject.getString("first_name");
294                    String lastName = jsonObject.getString("last_name");
295                    boolean male = Validator.equals(jsonObject.getString("gender"), "male");
296    
297                    if ((facebookId == user.getFacebookId()) &&
298                            emailAddress.equals(user.getEmailAddress()) &&
299                            firstName.equals(user.getFirstName()) &&
300                            lastName.equals(user.getLastName()) && (male == user.isMale())) {
301    
302                            return user;
303                    }
304    
305                    Contact contact = user.getContact();
306    
307                    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
308    
309                    birthdayCal.setTime(contact.getBirthday());
310    
311                    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
312                    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
313                    int birthdayYear = birthdayCal.get(Calendar.YEAR);
314    
315                    long[] groupIds = null;
316                    long[] organizationIds = null;
317                    long[] roleIds = null;
318                    List<UserGroupRole> userGroupRoles = null;
319                    long[] userGroupIds = null;
320    
321                    ServiceContext serviceContext = new ServiceContext();
322    
323                    if (!StringUtil.equalsIgnoreCase(
324                                    emailAddress, user.getEmailAddress())) {
325    
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    }