/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.security.authentication;
import java.io.IOException;
import java.util.Locale;
import java.util.Random;
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 javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.Globals;
import org.mifos.application.admin.system.ShutdownManager;
import org.mifos.application.servicefacade.ApplicationContextProvider;
import org.mifos.application.servicefacade.NewLoginServiceFacade;
import org.mifos.config.AccountingRules;
import org.mifos.config.Localization;
import org.mifos.config.SitePreferenceType;
import org.mifos.core.MifosRuntimeException;
import org.mifos.customers.personnel.business.PersonnelBO;
import org.mifos.customers.personnel.persistence.LegacyPersonnelDao;
import org.mifos.dto.domain.LoginDto;
import org.mifos.framework.components.batchjobs.MifosBatchJob;
import org.mifos.framework.exceptions.ApplicationException;
import org.mifos.framework.util.DateTimeService;
import org.mifos.framework.util.helpers.Constants;
import org.mifos.framework.util.helpers.Flow;
import org.mifos.framework.util.helpers.FlowManager;
import org.mifos.framework.util.helpers.ServletUtils;
import org.mifos.security.login.util.helpers.LoginConstants;
import org.mifos.security.util.ActivityContext;
import org.mifos.security.util.UserContext;
import org.mifos.ui.core.controller.util.helpers.SitePreferenceHelper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* I am a custom authentication filter implementation of {@link UsernamePasswordAuthenticationFilter}.
*
* A custom filter is needed as in the legacy authentication process, certain things were set in the session
* that are used by the legacy views (jsp pages). When struts and jsp is completely removed, we can revert back to using
* the out of the box authentication filter that is created using the spring security namespace.
*/
public class MifosLegacyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
final NewLoginServiceFacade loginServiceFacade;
public MifosLegacyUsernamePasswordAuthenticationFilter(final NewLoginServiceFacade loginServiceFacade) {
super();
this.loginServiceFacade = loginServiceFacade;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
//LocaleContextHolder.setLocale(Localization.getInstance().getConfiguredLocale());
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
AuthenticationException denied = null;
boolean allowAuthenticationToContinue = true;
if (MifosBatchJob.isBatchJobRunningThatRequiresExclusiveAccess()) {
allowAuthenticationToContinue = false;
HttpSession session = request.getSession(false);
if(session != null) {
session.invalidate();
}
denied = new AuthenticationServiceException(messages.getMessage(LoginConstants.BATCH_JOB_RUNNING,
"You have been logged out of the system because batch jobs are running."));
}
ShutdownManager shutdownManager = (ShutdownManager) ServletUtils.getGlobal(request, ShutdownManager.class.getName());
if (shutdownManager.isShutdownDone()) {
allowAuthenticationToContinue = false;
request.getSession(false).invalidate();
denied = new AuthenticationServiceException(messages.getMessage(LoginConstants.SHUTDOWN,
"You have been logged out of the system because Mifos is shutting down."));
}
if (shutdownManager.isInShutdownCountdownNotificationThreshold()) {
request.setAttribute("shutdownIsImminent", true);
}
if (allowAuthenticationToContinue) {
super.doFilter(request, response, chain);
} else {
unsuccessfulAuthentication(request, response, denied);
}
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
final String username = obtainUsername(request);
request.setAttribute("username", username);
final String password = obtainPassword(request);
if (authenticationIsUnsuccessfulDueToInvalidPassword(failed, username)) {
try {
loginServiceFacade.login(username, password);
} catch (UsernameNotFoundException e) {
// ignore and let spring security handle BadCredentialsException
}
}
super.unsuccessfulAuthentication(request, response, failed);
}
private boolean authenticationIsUnsuccessfulDueToInvalidPassword(AuthenticationException failed, String username) {
return StringUtils.isNotBlank(username) && failed != null;
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
final String username = obtainUsername(request);
request.setAttribute("username", username);
final String password = obtainPassword(request);
handleLegacySuccessfulAuthentication(request, response, username, password);
super.successfulAuthentication(request, response, authResult);
}
private void handleLegacySuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, final String username,
final String password) {
try {
FlowManager flowManager = new FlowManager();
String flowKey = String.valueOf(new DateTimeService().getCurrentDateTime().getMillis());
flowManager.addFLow(flowKey, new Flow(), this.getFilterName());
request.setAttribute(Constants.CURRENTFLOWKEY, flowKey);
request.getSession(false).setAttribute(Constants.FLOWMANAGER, flowManager);
request.getSession(false).setAttribute(Constants.RANDOMNUM, new Random().nextLong());
boolean flag= AccountingRules.getSimpleAccountingStatus();
request.getSession(false).setAttribute("accountingActivationStatus", flag);
LoginDto loginActivity = loginServiceFacade.login(username, password);
PersonnelBO user = ApplicationContextProvider.getBean(LegacyPersonnelDao.class).findPersonnelById(loginActivity.getUserId());
SitePreferenceHelper sitePreferenceHelper = new SitePreferenceHelper();
sitePreferenceHelper.setSitePreferenceCookie(SitePreferenceType.getSitePreference(user.getSitePreference()), response);
ActivityContext activityContext = new ActivityContext(Short.valueOf("0"), user.getOffice().getOfficeId(), user.getPersonnelId());
request.getSession(false).setAttribute(Constants.ACTIVITYCONTEXT, activityContext);
request.setAttribute("activityDto", loginActivity);
Short localeId = user.getPreferredLocale();
Locale preferredLocale = Localization.getInstance().getLocaleById(localeId);
UserContext userContext = new UserContext();
userContext.setPreferredLocale(preferredLocale);
userContext.setLocaleId(localeId);
userContext.setId(user.getPersonnelId());
userContext.setName(user.getDisplayName());
userContext.setLevel(user.getLevelEnum());
userContext.setRoles(user.getRoles());
userContext.setLastLogin(user.getLastLogin());
userContext.setPasswordChanged(user.getPasswordChanged());
userContext.setBranchId(user.getOffice().getOfficeId());
userContext.setBranchGlobalNum(user.getOffice().getGlobalOfficeNum());
userContext.setOfficeLevelId(user.getOffice().getLevel().getId());
request.setAttribute(Constants.USERCONTEXT, userContext);
request.getSession(false).setAttribute(Constants.USERCONTEXT, userContext);
request.removeAttribute("CURRENT_LOCALE_ID");
request.setAttribute("CURRENT_LOCALE_ID", localeId);
if (loginActivity.isPasswordChanged()) {
HttpSession hs = request.getSession(false);
hs.setAttribute(Constants.USERCONTEXT, userContext);
hs.setAttribute(Globals.LOCALE_KEY, userContext.getCurrentLocale());
} else {
flowManager.addObjectToFlow(flowKey, Constants.TEMPUSERCONTEXT, userContext);
}
if (loginActivity.isPasswordChanged()) {
flowManager.removeFlow((String) request.getAttribute(Constants.CURRENTFLOWKEY));
request.setAttribute(Constants.CURRENTFLOWKEY, null);
}
} catch (ApplicationException e1) {
throw new MifosRuntimeException(e1);
}
}
}