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