/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition 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; version 3 of the License.
//
// This community edition 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 this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.web;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.http.WebRequest;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.projectforge.core.Configuration;
import org.projectforge.core.ConfigurationParam;
import org.projectforge.database.InitDatabaseDao;
import org.projectforge.user.Login;
import org.projectforge.user.LoginResult;
import org.projectforge.user.LoginResultStatus;
import org.projectforge.user.PFUserDO;
import org.projectforge.user.UserDao;
import org.projectforge.user.UserXmlPreferencesCache;
import org.projectforge.web.admin.SetupPage;
import org.projectforge.web.admin.SystemUpdatePage;
import org.projectforge.web.mobile.LoginMobilePage;
import org.projectforge.web.wicket.AbstractUnsecureBasePage;
import org.projectforge.web.wicket.MySession;
import org.projectforge.web.wicket.WicketUtils;
public class LoginPage extends AbstractUnsecureBasePage
{
private static final long serialVersionUID = 4457817484456315374L;
public static final String REQUEST_PARAM_LOGOUT = "logout";
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoginPage.class);
// Used by LoginMobilePage
private static final String PARAMETER_KEY_FORCE_NON_MOBILE = "forceNonMobile";
@SpringBean(name = "configuration")
private Configuration configuration;
@SpringBean(name = "initDatabaseDao")
private InitDatabaseDao initDatabaseDao;
@SpringBean(name = "userDao")
private UserDao userDao;
private WebMarkupContainer errorsContainer;
private String errorMessage;
private LoginForm form = null;
/**
* Add parameter to force non-mobile version. This avoids a redirect to the LoginMobilePage and is used by LoginMobilePage.
* @return PageParameters.
*/
public static PageParameters forceNonMobile()
{
final PageParameters params = new PageParameters();
params.add(PARAMETER_KEY_FORCE_NON_MOBILE, "true");
return params;
}
public static void logout(final MySession mySession, final WebRequest request, final WebResponse response,
final UserXmlPreferencesCache userXmlPreferencesCache, final MenuBuilder menuBuilder)
{
final PFUserDO user = mySession.getUser();
if (user != null) {
userXmlPreferencesCache.flushToDB(user.getId());
userXmlPreferencesCache.clear(user.getId());
if (menuBuilder != null) {
menuBuilder.expireMenu(user.getId());
}
}
mySession.logout();
final Cookie stayLoggedInCookie = UserFilter.getStayLoggedInCookie(WicketUtils.getHttpServletRequest(request));
if (stayLoggedInCookie != null) {
stayLoggedInCookie.setMaxAge(0);
stayLoggedInCookie.setValue(null);
stayLoggedInCookie.setPath("/");
response.addCookie(stayLoggedInCookie);
}
}
public static void logout(final MySession mySession, final WebRequest request, final WebResponse response,
final UserXmlPreferencesCache userXmlPreferencesCache)
{
logout(mySession, request, response, userXmlPreferencesCache, null);
}
public static void logout(final MySession mySession, final HttpServletRequest request, final HttpServletResponse response,
final UserXmlPreferencesCache userXmlPreferencesCache, final MenuBuilder menuBuilder)
{
final PFUserDO user = mySession.getUser();
if (user != null) {
userXmlPreferencesCache.flushToDB(user.getId());
userXmlPreferencesCache.clear(user.getId());
if (menuBuilder != null) {
menuBuilder.expireMenu(user.getId());
}
}
mySession.logout();
final Cookie stayLoggedInCookie = UserFilter.getStayLoggedInCookie(request);
if (stayLoggedInCookie != null) {
stayLoggedInCookie.setMaxAge(0);
stayLoggedInCookie.setValue(null);
stayLoggedInCookie.setPath("/");
response.addCookie(stayLoggedInCookie);
}
}
@Override
protected void thisIsAnUnsecuredPage()
{
}
@SuppressWarnings("serial")
public LoginPage(final PageParameters parameters)
{
super(parameters);
if (getMySession().isMobileUserAgent() == true
&& UserFilter.isUpdateRequiredFirst() == false
&& "true".equals(WicketUtils.getAsString(parameters, PARAMETER_KEY_FORCE_NON_MOBILE)) == false) {
throw new RestartResponseException(LoginMobilePage.class);
}
final PFUserDO wicketSessionUser = getMySession().getUser();
final PFUserDO sessionUser = UserFilter.getUser(WicketUtils.getHttpServletRequest(getRequest()));
// Sometimes the wicket session user is given but the http session user is lost (re-login required).
if (wicketSessionUser != null && sessionUser != null && wicketSessionUser.getId() == sessionUser.getId()) {
throw new RestartResponseException(WicketUtils.getDefaultPage());
}
if (initDatabaseDao.isEmpty() == true) {
log.info("Data-base is empty: redirect to SetupPage...");
throw new RestartResponseException(SetupPage.class);
}
form = new LoginForm(this);
body.add(AttributeModifier.replace("class", "loginpage"));
body.add(form);
form.init();
final WebMarkupContainer administratorLoginNeeded = new WebMarkupContainer("administratorLoginNeeded");
body.add(administratorLoginNeeded);
if (UserFilter.isUpdateRequiredFirst() == false) {
administratorLoginNeeded.setVisible(false);
}
{
final String messageOfTheDay = configuration.getStringValue(ConfigurationParam.MESSAGE_OF_THE_DAY);
final WebMarkupContainer container = new WebMarkupContainer("messageOfTheDay");
body.add(container.setVisible(StringUtils.isNotBlank(messageOfTheDay)));
final Label messageOfTheDayLabel = new Label("msg", messageOfTheDay);
container.add(messageOfTheDayLabel.setEscapeModelStrings(false));
}
errorsContainer = new WebMarkupContainer("errors");
body.add(errorsContainer.setVisible(false));
errorsContainer.add(new Label("msg", new Model<String>() {
@Override
public String getObject()
{
return StringUtils.defaultString(errorMessage);
}
}));
}
void addError(final String msg)
{
errorMessage = msg;
errorsContainer.setVisible(true);
}
public static void internalLogin(final WebPage page, final PFUserDO user)
{
((MySession) page.getSession()).login(user, page.getRequest());
UserFilter.login(WicketUtils.getHttpServletRequest(page.getRequest()), user);
}
/**
* @param page
* @param userDao
* @param dataSource
* @param username
* @param password
* @param userWantsToStayLoggedIn
* @param defaultPage
* @param targetUrlAfterLogin
* @return i18n key of the validation error message if not successfully logged in, otherwise null.
*/
public static LoginResultStatus internalCheckLogin(final WebPage page, final UserDao userDao, final String username, final String password,
final boolean userWantsToStayLoggedIn, final Class< ? extends WebPage> defaultPage)
{
final LoginResult loginResult = Login.getInstance().checkLogin(username, password);
final PFUserDO user = loginResult.getUser();
if (user == null || loginResult.getLoginResultStatus() != LoginResultStatus.SUCCESS) {
return loginResult.getLoginResultStatus();
}
if (UserFilter.isUpdateRequiredFirst() == true) {
internalLogin(page, user);
log.info("Admin login for maintenance (data-base update) successful for user '" + username + "'.");
throw new RestartResponseException(SystemUpdatePage.class);
}
log.info("User successfully logged in: " + user.getDisplayUsername());
if (userWantsToStayLoggedIn == true) {
final PFUserDO loggedInUser = userDao.internalGetById(user.getId());
final Cookie cookie = new Cookie("stayLoggedIn", loggedInUser.getId()
+ ":"
+ loggedInUser.getUsername()
+ ":"
+ userDao.getStayLoggedInKey(user.getId()));
UserFilter.addStayLoggedInCookie(WicketUtils.getHttpServletRequest(page.getRequest()),
WicketUtils.getHttpServletResponse(page.getResponse()), cookie);
}
internalLogin(page, user);
// Do not redirect to requested page in maintenance mode (update required first):
if (UserFilter.isUpdateRequiredFirst() == true) {
throw new RestartResponseException(SystemUpdatePage.class);
}
page.continueToOriginalDestination();
// Redirect only if not a redirect is set by Wicket.
throw new RestartResponseException(defaultPage);
}
protected LoginResultStatus checkLogin()
{
return internalCheckLogin(this, userDao, form.getUsername(), form.getPassword(), form.isStayLoggedIn(), WicketUtils.getDefaultPage());
}
@Override
protected String getTitle()
{
return getString("login.title");
}
}