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 ((jsonObject != null) && jsonObject.getBoolean("verified")) {
262                            String facebookId = jsonObject.getString("id");
263    
264                            if (Validator.isNotNull(facebookId)) {
265                                    session.setAttribute(WebKeys.FACEBOOK_USER_ID, facebookId);
266                            }
267    
268                            String emailAddress = jsonObject.getString("email");
269    
270                            if (Validator.isNotNull(emailAddress)) {
271                                    try {
272                                            UserLocalServiceUtil.getUserByEmailAddress(
273                                                    companyId, emailAddress);
274    
275                                            session.setAttribute(
276                                                    WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
277                                    }
278                                    catch (NoSuchUserException nsue) {
279                                            session.removeAttribute(
280                                                    WebKeys.FACEBOOK_USER_EMAIL_ADDRESS);
281                                    }
282                            }
283                    }
284            }
285    
286            protected String getRedirect(
287                            HttpServletRequest request, ThemeDisplay themeDisplay)
288                    throws Exception {
289    
290                    HttpSession session = request.getSession();
291    
292                    if ((session.getAttribute(WebKeys.FACEBOOK_ACCESS_TOKEN) != null) &&
293                            (session.getAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS) !=
294                                    null)) {
295    
296                            return themeDisplay.getPathContext();
297                    }
298                    else {
299                            PortletURL portletURL = PortletURLFactoryUtil.create(
300                                    request, PortletKeys.LOGIN, themeDisplay.getPlid(),
301                                    PortletRequest.RENDER_PHASE);
302    
303                            portletURL.setWindowState(WindowState.MAXIMIZED);
304                            portletURL.setPortletMode(PortletMode.VIEW);
305    
306                            portletURL.setParameter(
307                                    "struts_action", "/login/facebook_connect_add_user");
308    
309                            return portletURL.toString();
310                    }
311            }
312    
313            protected void setFacebookCredentials(
314                            HttpSession session, long companyId, String token)
315                    throws Exception {
316    
317                    String url = HttpUtil.addParameter(
318                            FacebookConnectUtil.getGraphURL(companyId) + "/me", "access_token",
319                            token);
320    
321                    url = HttpUtil.addParameter(url, "fields", "email,id,verified");
322    
323                    Http.Options options = new Http.Options();
324    
325                    options.setLocation(url);
326    
327                    String content = HttpUtil.URLtoString(options);
328    
329                    if (Validator.isNull(content)) {
330                            return;
331                    }
332    
333                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject(content);
334    
335                    if (!jsonObject.getBoolean("verified")) {
336                            return;
337                    }
338    
339                    String facebookId = jsonObject.getString("id");
340    
341                    if (Validator.isNotNull(facebookId)) {
342                            session.setAttribute(WebKeys.FACEBOOK_USER_ID, facebookId);
343                    }
344    
345                    String emailAddress = jsonObject.getString("email");
346    
347                    if (Validator.isNotNull(emailAddress)) {
348                            try {
349                                    UserLocalServiceUtil.getUserByEmailAddress(
350                                            companyId, emailAddress);
351    
352                                    session.setAttribute(
353                                            WebKeys.FACEBOOK_USER_EMAIL_ADDRESS, emailAddress);
354                            }
355                            catch (NoSuchUserException nsue) {
356                                    session.removeAttribute(WebKeys.FACEBOOK_USER_EMAIL_ADDRESS);
357                            }
358                    }
359            }
360    
361    }