package org.fluxtream.mvc.controllers;
import org.fluxtream.core.Configuration;
import org.fluxtream.core.aspects.FlxLogger;
import org.fluxtream.core.auth.AuthHelper;
import org.fluxtream.core.connectors.Connector;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.Guest;
import org.fluxtream.core.domain.Notification.Type;
import org.fluxtream.core.services.*;
import org.fluxtream.core.utils.SecurityUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
@Controller
public class AppController {
FlxLogger logger = FlxLogger.getLogger(AppController.class);
@Autowired
Configuration env;
@Autowired
GuestService guestService;
@Autowired
ApiDataService apiDataService;
@Autowired
MetadataService metadataService;
@Autowired
NotificationsService notificationsService;
@Autowired
ConnectorUpdateService connectorUpdateService;
@Autowired
BuddiesService buddiesService;
@Autowired
BeanFactory beanFactory;
@Autowired
ErrorController errorController;
@RequestMapping(value = { "*", "/*", "/welcome*" })
public ModelAndView index(HttpServletRequest request,
HttpServletResponse response) {
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0);
if (AuthHelper.isFullyAuthenticated())
return new ModelAndView("redirect:/app");
String indexPageName = "default";
if (env.get("homepage.name")!=null)
indexPageName = env.get("homepage.name");
ModelAndView mav = new ModelAndView(indexPageName);
String release = env.get("release");
if (release != null)
mav.addObject("release", release);
final String facebookAppId = env.get("facebook.appId");
if (facebookAppId !=null&&!facebookAppId.equals("xxx")) {
mav.addObject("facebookAppId", facebookAppId);
mav.addObject("supportsFBLogin", true);
} else
mav.addObject("supportsFBLogin", false);
mav.addObject("tracker", hasTracker(request));
return mav;
}
@RequestMapping(value = "handle404")
public String handle404() {
return "redirect:/welcome";
}
private boolean hasIntercom(HttpServletRequest request) {
String intercomScriptPath = request.getSession().getServletContext().getRealPath("/WEB-INF/jsp/intercom.jsp");
File intercomScriptFile = new File(intercomScriptPath);
final boolean fileExists = intercomScriptFile.exists();
final boolean hasApiKey = env.get("intercomApiKey")!=null;
return fileExists&&hasApiKey;
}
private boolean hasTracker(HttpServletRequest request) {
String trackerPath = request.getSession().getServletContext().getRealPath("/WEB-INF/jsp/tracker.jsp");
File trackerFile = new File(trackerPath);
final boolean fileExists = trackerFile.exists();
return fileExists;
}
@RequestMapping(value = { "/snippets" })
public ModelAndView snippets(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("snippets");
mav.addObject("tracker", hasTracker(request));
if (request.getSession(false) == null)
return mav;
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
if (auth == null || !auth.isAuthenticated())
return mav;
mav.setViewName("snippets");
String release = env.get("release");
mav.addObject("release", release);
return mav;
}
public ModelAndView home(HttpServletRequest request,
HttpServletResponse response) {
logger.info("action=loggedIn");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0);
long guestId = AuthHelper.getGuestId();
ModelAndView mav = new ModelAndView("redirect:main");
mav.addObject("tracker", hasTracker(request));
final boolean hasIntercom = hasIntercom(request);
mav.addObject("intercom", hasIntercom);
if (hasIntercom)
mav.addObject("intercomApiKey", env.get("intercomApiKey"));
if (request.getSession(false) == null)
return mav;
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
if (auth == null || !auth.isAuthenticated())
return mav;
mav.setViewName("home");
Guest guest = guestService.getGuestById(guestId);
mav.addObject("fullname", guest.getGuestName());
String release = env.get("release");
request.setAttribute("guestName", guest.getGuestName());
request.setAttribute("trustingBuddies", buddiesService.getTrustingBuddies(guestId));
request.setAttribute("trustedBuddies", buddiesService.getTrustedBuddies(guestId));
request.setAttribute("useMinifiedJs", Boolean.valueOf(env.get("useMinifiedJs")));
if (env.get("forum.url")!=null)
request.setAttribute("forumUrl", env.get("forum.url"));
if (SecurityUtils.isDemoUser())
request.setAttribute("demo", true);
if (release != null)
mav.addObject("release", release);
return mav;
}
@RequestMapping(value = "/checkIn")
public ModelAndView checkIn(HttpServletRequest request,
HttpServletResponse response) throws IOException, NoSuchAlgorithmException, URISyntaxException {
final Guest guest = AuthHelper.getGuest();
if (!hasTimezoneCookie(request)|| guest ==null)
return new ModelAndView("redirect:/welcome");
long guestId = guest.getId();
checkIn(request, guestId);
final HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
SavedRequest savedRequest =
requestCache.getRequest(request, response);
if (savedRequest!=null) {
final String redirectUrl = savedRequest.getRedirectUrl();
requestCache.removeRequest(request, response);
return new ModelAndView("redirect:" + redirectUrl);
}
return new ModelAndView("redirect:/app");
}
@RequestMapping(value = "/mobile/checkIn")
public ModelAndView mobileCheckIn(HttpServletRequest request,
HttpServletResponse response) throws IOException, NoSuchAlgorithmException, URISyntaxException {
final Guest guest = AuthHelper.getGuest();
long guestId = guest.getId();
checkIn(request, guestId);
final HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
SavedRequest savedRequest =
requestCache.getRequest(request, response);
if (savedRequest!=null) {
final String redirectUrl = savedRequest.getRedirectUrl();
requestCache.removeRequest(request, response);
return new ModelAndView("redirect:" + redirectUrl);
}
return new ModelAndView("redirect:/app");
}
@RequestMapping(value = { "/app*", "/app/**" })
public ModelAndView welcomeHome(HttpServletRequest request, HttpServletResponse response)
throws IOException, NoSuchAlgorithmException {
if (!hasTimezoneCookie(request)|| AuthHelper.getGuest()==null)
return new ModelAndView("redirect:/welcome?signIn");
SavedRequest savedRequest =
new HttpSessionRequestCache().getRequest(request, response);
if (savedRequest!=null) {
final String redirectUrl = savedRequest.getRedirectUrl();
return new ModelAndView(redirectUrl);
}
return home(request, response);
}
@RequestMapping(value = "/app/tokenRenewed/{connectorName}")
public String tokenRenewed(@PathVariable("connectorName") String connectorName) {
final Connector connector = Connector.getConnector(connectorName);
String message = "You have successfully renewed your "
+ connector.prettyName()
+ " authentication tokens. We will now update your data.";
return welcomeBack(connectorName, message);
}
@RequestMapping(value = "/app/from/{connectorName}")
public String home(@PathVariable("connectorName") String connectorName) {
final Connector connector = Connector.getConnector(connectorName);
String message = "<img class=\"loading-animation\" src=\"/static/img/loading.gif\"/>You have successfully added a new connector: "
+ connector.prettyName()
+ ". Your data is now being retrieved. "
+ "It may take a little while until it becomes visible.";
return welcomeBack(connectorName, message);
}
public String welcomeBack(String connectorName, String message) {
long guestId = AuthHelper.getGuestId();
final Connector connector = Connector.getConnector(connectorName);
notificationsService.addNamedNotification(guestId, Type.INFO, connector.statusNotificationName(), message);
ApiKey apiKey = guestService.getApiKey(guestId, connector);
connectorUpdateService.updateConnector(apiKey, true);
return "redirect:/app";
}
private void checkIn(HttpServletRequest request, long guestId)
throws IOException {
String remoteAddr = request.getHeader("X-Forwarded-For");
if (remoteAddr == null)
remoteAddr = request.getRemoteAddr();
initializeWithTimeZone(request, guestId);
guestService.checkIn(guestId, remoteAddr);
connectorUpdateService.updateAllConnectors(guestId, false);
}
private boolean hasTimezoneCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equalsIgnoreCase("timeZone")) {
return true;
}
}
return false;
}
private void initializeWithTimeZone(HttpServletRequest request, long guestId) {
Cookie[] cookies = request.getCookies();
String timeZone = null, date = null;
for (Cookie cookie : cookies) {
if (cookie.getName().equalsIgnoreCase("timeZone")) {
timeZone = cookie.getValue();
} else if (cookie.getName().equalsIgnoreCase("date")) {
date = cookie.getValue();
}
}
metadataService.setTimeZone(guestId, date, timeZone);
}
}