001    /**
002     * Copyright (c) 2000-2010 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.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.util.Constants;
021    import com.liferay.portal.kernel.util.Http;
022    import com.liferay.portal.kernel.util.HttpUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.ParamUtil;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.service.ServiceContext;
028    import com.liferay.portal.service.UserLocalServiceUtil;
029    import com.liferay.portal.struts.PortletAction;
030    import com.liferay.portal.theme.ThemeDisplay;
031    import com.liferay.portal.util.FacebookConnectUtil;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portal.util.PortletKeys;
034    import com.liferay.portal.util.WebKeys;
035    import com.liferay.portlet.PortletURLFactoryUtil;
036    
037    import java.util.Calendar;
038    import java.util.Locale;
039    
040    import javax.portlet.ActionRequest;
041    import javax.portlet.ActionResponse;
042    import javax.portlet.PortletConfig;
043    import javax.portlet.PortletMode;
044    import javax.portlet.PortletRequest;
045    import javax.portlet.PortletURL;
046    import javax.portlet.WindowState;
047    
048    import javax.servlet.http.HttpServletRequest;
049    import javax.servlet.http.HttpServletResponse;
050    import javax.servlet.http.HttpSession;
051    
052    import org.apache.struts.action.ActionForm;
053    import org.apache.struts.action.ActionForward;
054    import org.apache.struts.action.ActionMapping;
055    
056    /**
057     * @author Wilson Man
058     */
059    public class FacebookConnectAction extends PortletAction {
060    
061            public void processAction(
062                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
063                            ActionRequest actionRequest, ActionResponse actionResponse)
064                    throws Exception {
065    
066                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
067                            WebKeys.THEME_DISPLAY);
068    
069                    long companyId = themeDisplay.getCompanyId();
070    
071                    if (!FacebookConnectUtil.isEnabled(companyId)) {
072                            return;
073                    }
074    
075                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
076    
077                    if (cmd.equals(Constants.ADD)) {
078                            addUser(actionRequest, actionResponse, themeDisplay);
079                    }
080                    else {
081                            String redirect = HttpUtil.addParameter(
082                                    FacebookConnectUtil.getAuthURL(companyId), "client_id",
083                                    FacebookConnectUtil.getAppId(companyId));
084    
085                            redirect = HttpUtil.addParameter(
086                                    redirect, "redirect_uri",
087                                    FacebookConnectUtil.getRedirectURL(companyId));
088    
089                            redirect = HttpUtil.addParameter(redirect, "scope", "email");
090    
091                            actionResponse.sendRedirect(redirect);
092                    }
093            }
094    
095            public ActionForward strutsExecute(
096                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
097                            HttpServletResponse response)
098                    throws Exception {
099    
100                    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(
101                            WebKeys.THEME_DISPLAY);
102    
103                    long companyId = themeDisplay.getCompanyId();
104    
105                    if (!FacebookConnectUtil.isEnabled(companyId)) {
106                            return null;
107                    }
108    
109                    String code = ParamUtil.get(request, "code", StringPool.BLANK);
110    
111                    String token = getAccessToken(companyId, code);
112    
113                    if (Validator.isNotNull(token)) {
114                            HttpSession session = request.getSession();
115    
116                            session.setAttribute(WebKeys.FACEBOOK_ACCESS_TOKEN, token);
117    
118                            setFacebookCredentials(session, companyId, token);
119                    }
120    
121                    String redirect = getRedirect(request, themeDisplay);
122    
123                    response.sendRedirect(redirect);
124    
125                    return null;
126            }
127    
128            protected void addUser(
129                            ActionRequest actionRequest, ActionResponse actionResponse,
130                            ThemeDisplay themeDisplay)
131                    throws Exception {
132    
133                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
134                            actionRequest);
135    
136                    request = PortalUtil.getOriginalServletRequest(request);
137    
138                    HttpSession session = request.getSession();
139    
140                    String token = (String)session.getAttribute(
141                            WebKeys.FACEBOOK_ACCESS_TOKEN);
142    
143                    long companyId = themeDisplay.getCompanyId();
144    
145                    String url = HttpUtil.addParameter(
146                            FacebookConnectUtil.getGraphURL(companyId) + "/me", "access_token",
147                            token);
148    
149                    url = HttpUtil.addParameter(
150                            url, "fields",
151                            "email,first_name,last_name,birthday,gender,verified");
152    
153                    Http.Options options = new Http.Options();
154    
155                    options.setLocation(url);
156    
157                    String content = HttpUtil.URLtoString(options);
158    
159                    if (Validator.isNull(content)) {
160                            return;
161                    }
162    
163                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject(content);
164    
165                    if (!jsonObject.getBoolean("verified")) {
166                            return;
167                    }
168    
169                    long creatorUserId = 0;
170                    boolean autoPassword = true;
171                    String password1 = StringPool.BLANK;
172                    String password2 = StringPool.BLANK;
173                    boolean autoScreenName = true;
174                    String screenName = StringPool.BLANK;
175                    String emailAddress = jsonObject.getString("email");
176                    long facebookId = jsonObject.getLong("id");
177                    String openId = StringPool.BLANK;
178                    Locale locale = LocaleUtil.getDefault();
179                    String firstName = jsonObject.getString("first_name");
180                    String middleName = StringPool.BLANK;
181                    String lastName = jsonObject.getString("last_name");
182                    int prefixId = 0;
183                    int suffixId = 0;
184                    boolean male = Validator.equals(jsonObject.getString("gender"), "male");
185                    int birthdayMonth = Calendar.JANUARY;
186                    int birthdayDay = 1;
187                    int birthdayYear = 1970;
188                    String jobTitle = StringPool.BLANK;
189                    long[] groupIds = null;
190                    long[] organizationIds = null;
191                    long[] roleIds = null;
192                    long[] userGroupIds = null;
193                    boolean sendEmail = true;
194    
195                    ServiceContext serviceContext = new ServiceContext();
196    
197                    UserLocalServiceUtil.addUser(
198                            creatorUserId, companyId, autoPassword, password1, password2,
199                            autoScreenName, screenName, emailAddress, facebookId, openId,
200                            locale, firstName, middleName, lastName, prefixId, suffixId, male,
201                            birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds,
202                            organizationIds, roleIds, userGroupIds, sendEmail, serviceContext);
203    
204                    session.setAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
205    
206                    String redirect = themeDisplay.getPathContext();
207    
208                    if (Validator.isNull(redirect)) {
209                            redirect = StringPool.SLASH;
210                    }
211    
212                    actionResponse.sendRedirect(redirect);
213            }
214    
215            protected String getAccessToken(long companyId, String code)
216                    throws Exception {
217    
218                    String url = HttpUtil.addParameter(
219                            FacebookConnectUtil.getAccessTokenURL(companyId), "client_id",
220                            FacebookConnectUtil.getAppId(companyId));
221    
222                    url = HttpUtil.addParameter(url, "redirect_uri",
223                            FacebookConnectUtil.getRedirectURL(companyId));
224    
225                    url = HttpUtil.addParameter(url, "client_secret",
226                            FacebookConnectUtil.getAppSecret(companyId));
227    
228                    url = HttpUtil.addParameter(url, "code", code);
229    
230                    Http.Options options = new Http.Options();
231    
232                    options.setLocation(url);
233                    options.setPost(true);
234    
235                    String content = HttpUtil.URLtoString(options);
236    
237                    if (Validator.isNotNull(content)) {
238                            int x = content.indexOf("access_token=");
239    
240                            if (x >= 0) {
241                                    int y = content.indexOf(StringPool.AMPERSAND, x);
242    
243                                    if (y < x) {
244                                            y = content.length();
245                                    }
246    
247                                    return content.substring(x + 13, y);
248                            }
249                    }
250    
251                    return null;
252            }
253    
254            protected void getFacebookCredentials(
255                            HttpSession session, long companyId, String token)
256                    throws Exception {
257    
258                    JSONObject jsonObject = FacebookConnectUtil.getGraphResources(
259                            companyId, "/me", token, "id,email,verified");
260    
261                    if (Validator.isNotNull(jsonObject) &&
262                            jsonObject.getBoolean("verified")) {
263    
264                            String facebookId = jsonObject.getString("id");
265    
266                            if (Validator.isNotNull(facebookId)) {
267                                    session.setAttribute(WebKeys.FACEBOOK_USER_ID, facebookId);
268                            }
269    
270                            String emailAddress = jsonObject.getString("email");
271    
272                            if (Validator.isNotNull(emailAddress)) {
273                                    try {
274                                            UserLocalServiceUtil.getUserByEmailAddress(
275                                                    companyId, emailAddress);
276    
277                                            session.setAttribute(
278                                                    WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
279                                    }
280                                    catch (NoSuchUserException nsue) {
281                                            session.removeAttribute(
282                                                    WebKeys.FACEBOOK_USER_EMAIL_ADDRESS);
283                                    }
284                            }
285                    }
286            }
287    
288            protected String getRedirect(
289                            HttpServletRequest request, ThemeDisplay themeDisplay)
290                    throws Exception {
291    
292                    HttpSession session = request.getSession();
293    
294                    if ((session.getAttribute(WebKeys.FACEBOOK_ACCESS_TOKEN) != null) &&
295                            (session.getAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS) !=
296                                    null)) {
297    
298                            return themeDisplay.getPathContext();
299                    }
300                    else {
301                            PortletURL portletURL = PortletURLFactoryUtil.create(
302                                    request, PortletKeys.LOGIN, themeDisplay.getPlid(),
303                                    PortletRequest.RENDER_PHASE);
304    
305                            portletURL.setWindowState(WindowState.MAXIMIZED);
306                            portletURL.setPortletMode(PortletMode.VIEW);
307    
308                            portletURL.setParameter(
309                                    "struts_action", "/login/facebook_connect_add_user");
310    
311                            return portletURL.toString();
312                    }
313            }
314    
315            protected void setFacebookCredentials(
316                            HttpSession session, long companyId, String token)
317                    throws Exception {
318    
319                    String url = HttpUtil.addParameter(
320                            FacebookConnectUtil.getGraphURL(companyId) + "/me", "access_token",
321                            token);
322    
323                    url = HttpUtil.addParameter(url, "fields", "email,id,verified");
324    
325                    Http.Options options = new Http.Options();
326    
327                    options.setLocation(url);
328    
329                    String content = HttpUtil.URLtoString(options);
330    
331                    if (Validator.isNull(content)) {
332                            return;
333                    }
334    
335                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject(content);
336    
337                    if (!jsonObject.getBoolean("verified")) {
338                            return;
339                    }
340    
341                    String facebookId = jsonObject.getString("id");
342    
343                    if (Validator.isNotNull(facebookId)) {
344                            session.setAttribute(WebKeys.FACEBOOK_USER_ID, facebookId);
345                    }
346    
347                    String emailAddress = jsonObject.getString("email");
348    
349                    if (Validator.isNotNull(emailAddress)) {
350                            try {
351                                    UserLocalServiceUtil.getUserByEmailAddress(
352                                            companyId, emailAddress);
353    
354                                    session.setAttribute(
355                                            WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
356                            }
357                            catch (NoSuchUserException nsue) {
358                                    session.removeAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS);
359                            }
360                    }
361            }
362    
363    }