From 2f682b5e3cfc3fc5f961b60129be7bc90e0d6a03 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 28 Dec 2016 22:38:21 +0300 Subject: juick-www: now on spring-webmvc --- .../com/juick/www/controllers/FacebookLogin.java | 153 +++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 juick-www/src/main/java/com/juick/www/controllers/FacebookLogin.java (limited to 'juick-www/src/main/java/com/juick/www/controllers/FacebookLogin.java') diff --git a/juick-www/src/main/java/com/juick/www/controllers/FacebookLogin.java b/juick-www/src/main/java/com/juick/www/controllers/FacebookLogin.java new file mode 100644 index 00000000..cc11f99a --- /dev/null +++ b/juick-www/src/main/java/com/juick/www/controllers/FacebookLogin.java @@ -0,0 +1,153 @@ +/* + * Juick + * Copyright (C) 2008-2013, Ugnich Anton + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.juick.www.controllers; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.juick.service.CrosspostService; +import com.juick.service.UserService; +import com.juick.www.Utils; +import com.juick.www.facebook.Graph; +import org.apache.commons.lang3.CharEncoding; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.inject.Inject; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.UUID; + +/** + * + * @author Ugnich Anton + */ +@Controller +public class FacebookLogin { + + private static final Logger logger = LoggerFactory.getLogger(FacebookLogin.class); + + private final String FACEBOOK_APPID; + private final String FACEBOOK_SECRET; + private final String FACEBOOK_REDIRECT = "http://juick.com/_fblogin"; + private final ObjectMapper mapper; + + @Inject + CrosspostService crosspostService; + @Inject + UserService userService; + + @Inject + public FacebookLogin(Environment env) { + FACEBOOK_APPID = env.getProperty("facebook_appid"); + FACEBOOK_SECRET = env.getProperty("facebook_secret"); + + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + } + + @RequestMapping(value = "/_fblogin", method = RequestMethod.GET) + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { + String fbstate; + + String code = request.getParameter("code"); + if (StringUtils.isBlank(code)) { + fbstate = UUID.randomUUID().toString(); + + Cookie c = new Cookie("fbstate", fbstate); + response.addCookie(c); + + response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + response.setHeader("Location", "https://www.facebook.com/dialog/oauth?scope=publish_stream&client_id=" + FACEBOOK_APPID + "&redirect_uri=" + URLEncoder.encode(FACEBOOK_REDIRECT, CharEncoding.UTF_8) + "&state=" + fbstate); + return; + } + + fbstate = Utils.getCookie(request, "fbstate"); + if (fbstate == null || fbstate.isEmpty() || !fbstate.equals(request.getParameter("state"))) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } else { + Cookie c = new Cookie("fbstate", "-"); + c.setMaxAge(0); + response.addCookie(c); + } + + String token = Utils.fetchURL("https://graph.facebook.com/oauth/access_token?client_id=" + FACEBOOK_APPID + "&redirect_uri=" + URLEncoder.encode(FACEBOOK_REDIRECT, CharEncoding.UTF_8) + "&client_secret=" + FACEBOOK_SECRET + "&code=" + URLEncoder.encode(code, CharEncoding.UTF_8)); + if (token == null || token.isEmpty() || !token.startsWith("access_token=")) { + logger.error("FACEBOOK TOKEN ERROR: {}", token); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + token = token.substring(13); // access_token=... + int tokenamp = token.indexOf('&'); // &expires= + if (tokenamp > 0) { + token = token.substring(0, tokenamp); + } + + String graph = Utils.fetchURL("https://graph.facebook.com/me?access_token=" + token); + if (graph == null || graph.isEmpty()) { + logger.error("FACEBOOK GRAPH ERROR"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + + try { + Graph fb = mapper.readValue(graph, Graph.class); + + long fbID = NumberUtils.toLong(fb.getId(), 0); + if (fbID == 0 || StringUtils.isBlank(fb.getName()) || StringUtils.isBlank(fb.getLink())) { + throw new Exception(); + } + + int uid = crosspostService.getUIDbyFBID(fbID); + if (uid > 0) { + if (!crosspostService.updateFacebookUser(fbID, token, fb.getName(), fb.getLink())) { + throw new Exception(); + } + Cookie c = new Cookie("hash", userService.getHashByUID(uid)); + c.setMaxAge(50 * 24 * 60 * 60); + response.addCookie(c); + response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + response.setHeader("Location", "/"); + } else if (fb.getVerified()) { + String loginhash = UUID.randomUUID().toString(); + if (!crosspostService.createFacebookUser(fbID, loginhash, token, fb.getName(), fb.getLink())) { + throw new Exception(); + } + response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + response.setHeader("Location", "/signup?type=fb&hash=" + loginhash); + } else { + throw new Exception(); + } + } catch (Exception e) { + logger.error("fb error", e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + } +} -- cgit v1.2.3