/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.http; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import nl.strohalm.cyclos.annotations.Inject; import nl.strohalm.cyclos.entities.access.Session; import nl.strohalm.cyclos.entities.access.User; import nl.strohalm.cyclos.services.access.AccessService; import nl.strohalm.cyclos.services.access.exceptions.NotConnectedException; import nl.strohalm.cyclos.utils.RequestHelper; import nl.strohalm.cyclos.utils.TransactionHelper; import nl.strohalm.cyclos.utils.access.LoggedUser; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** * Filter that will set a ThreadLocal with the logged user * @author luis */ public class LoggedUserFilter extends OncePerRequestFilter { private final Map<String, Object> attributes = new HashMap<String, Object>(); private AccessService accessService; private TransactionHelper transactionHelper; @Override public void destroy() { super.destroy(); attributes.clear(); } @Override public void init(final FilterConfig config) throws ServletException { super.init(config); final ServletContext servletContext = config.getServletContext(); final WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); attributes.put("servletContext", servletContext); attributes.put("applicationContext", webApplicationContext); } @Inject public void setAccessService(final AccessService accessService) { this.accessService = accessService; } @Inject public void setTransactionHelper(final TransactionHelper transactionHelper) { this.transactionHelper = transactionHelper; } @Override protected void execute(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpSession httpSession = request.getSession(false); final Long userId = (Long) (httpSession == null ? null : httpSession.getAttribute("loggedUserId")); if (userId == null) { // No current user: ensure the LoggedUser is cleared up and proceed the chain LoggedUser.cleanup(); chain.doFilter(request, response); } else { // There is a current user. First, make sure the session is correctly handled by the service layer User user; try { user = findLoggedUser(httpSession.getId()); // Update the reference to the session user request.setAttribute("loggedUser", user); request.setAttribute("loggedElement", user.getElement()); } catch (final NotConnectedException e) { // The current session is not mirrored in the database - invalidate it httpSession.invalidate(); if (RequestHelper.isAjax(request)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return; } else { // FIXME If posWeb should redirect to posweb, not to root response.sendRedirect(request.getContextPath() + "/"); return; } } // Initialize the LoggedUser, and proceed the chain try { LoggedUser.init(user, request.getRemoteAddr(), attributes); LoggedUser.setAttribute("request", request); chain.doFilter(request, response); } finally { LoggedUser.cleanup(); } } } private User findLoggedUser(final String sessionId) { return transactionHelper.runInCurrentThread(new TransactionCallback<User>() { @Override public User doInTransaction(final TransactionStatus status) { final Session session = accessService.checkSession(sessionId); return session.getUser(); } }); } }