/**
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2014 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
package com.axelor.auth;

import java.io.IOException;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;

public class AuthFilter extends FormAuthenticationFilter {
	
	private static Logger log = LoggerFactory.getLogger(AuthFilter.class);

	@Inject
	@Named("app.loginUrl")
	private String loginUrl;

	@Override
	public String getLoginUrl() {
		if (loginUrl != null) {
			return loginUrl;
		}
		return super.getLoginUrl();
	}

	@Override
	public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
			throws ServletException, IOException {
		if (isLoginRequest(request, response) && SecurityUtils.getSubject().isAuthenticated()) {
			WebUtils.issueRedirect(request, response, "/");
		}
		super.doFilterInternal(request, response, chain);
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

		if (isXHR(request)) {
			if (isLoginRequest(request, response) && isLoginSubmission(request, response)) {
				return doLogin(request, response);
			}
			((HttpServletResponse) response).setStatus(401);
			return false;
		}
		return super.onAccessDenied(request, response);
	}

	@SuppressWarnings("unchecked")
	private boolean doLogin(ServletRequest request, ServletResponse response) throws Exception {

		ObjectMapper mapper = new ObjectMapper();
		Map<String, String> data = mapper.readValue(request.getInputStream(), Map.class);

		String username = data.get("username");
		String password = data.get("password");

		AuthenticationToken token = createToken(username, password, request, response);

		try {
			Subject subject = getSubject(request, response);
			subject.login(token);
			return onLoginSuccess(token, subject, request, response);
		} catch (AuthenticationException e) {
			log.error("Password authentication failed for user: {}", token.getPrincipal());
		}
		return false;
	}

	private boolean isXHR(ServletRequest request) {
		return "XMLHttpRequest".equals(((HttpServletRequest) request).getHeader("X-Requested-With"));
	}
}

@@ -1371,65 +1371,8 @@
 ils;
-%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aim
@@ -1484,82 +1484,8 @@
 er %7B
-%0A%09%0A%09private static Logger log = LoggerFactory.getLogger(AuthFilter.class);
 %0A%0A%09@
@@ -2136,16 +2136,18 @@
 ption %7B%0A
+%09%09
 %0A%09%09if (i
@@ -2163,16 +2163,41 @@
 est)) %7B%0A
+%09%09%09%0A%09%09%09int status = 401;%0A
 %09%09%09if (i
@@ -2276,23 +2276,20 @@
 ) %7B%0A%09%09%09%09
-return 
+if (
 doLogin(
@@ -2310,18 +2310,40 @@
 nse)
+) %7B%0A%09%09%09%09%09status = 200
 ;%0A
+%09
 %09%09%09%7D%0A%09%09%09
 ((Ht
@@ -2342,56 +2342,189 @@
 %0A%09%09%09
-((HttpServletResponse) response).setStatus(401);
+%7D%0A%0A%09%09%09// set HTTP status for ajax requests%0A%09%09%09((HttpServletResponse) response).setStatus(status);%0A%0A%09%09%09// don't process further, otherwise login.jsp will be rendered as response data
 %0A%09%09%09
@@ -2537,24 +2537,25 @@
  false;%0A%09%09%7D%0A
+%0A
 %09%09return sup
@@ -2725,16 +2725,22 @@
 on %7B%0A%0A%09%09
+final 
 ObjectMa
@@ -2775,16 +2775,22 @@
 er();%0A%09%09
+final 
 Map%3CStri
@@ -2866,16 +2866,22 @@
 ss);%0A%0A%09%09
+final 
 String u
@@ -2914,16 +2914,22 @@
 me%22);%0A%09%09
+final 
 String p
@@ -2963,16 +2963,22 @@
 d%22);%0A%0A%09%09
+final 
 Authenti
@@ -3053,20 +3053,16 @@
 e);%0A
-%0A
 %09%09
-try %7B%0A%09%09%09
+final 
 Subj
@@ -3105,16 +3105,25 @@
 sponse);
+%0A%0A%09%09try %7B
 %0A%09%09%09subj
@@ -3146,194 +3146,68 @@
 ;%0A%09%09
-%09return onLoginSuccess(token, subject, request, response);%0A%09%09%7D catch (AuthenticationException e) %7B%0A%09%09%09log.error(%22Password authentication failed for user: %7B%7D%22, token.getPrincipal())
+%7D catch (AuthenticationException e) %7B%0A%09%09%09return false
 ;%0A%09%09%7D%0A
+%0A
 %09%09re
@@ -3207,28 +3207,27 @@
 %7D%0A%0A%09%09return 
-fals
+tru
 e;%0A%09%7D%0A%0A%09priv

Fix redirect issue on ajax login requests