Removed depcrecated package com.arsdigita.ui.login from ccm-core
parent
b92a41b85f
commit
285e8c977c
|
|
@ -17,12 +17,9 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.ui;
|
package com.arsdigita.ui;
|
||||||
|
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
import com.arsdigita.ui.login.LoginServlet;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* A central location for commonly used UI services and their accessories.</p>
|
* A central location for commonly used UI services and their accessories.</p>
|
||||||
|
|
@ -45,11 +42,13 @@ public abstract class UI {
|
||||||
* URL for systems public top level page (entry or start page).
|
* URL for systems public top level page (entry or start page).
|
||||||
*/
|
*/
|
||||||
private static final String s_rootPageURL = s_config.getRootPageUrl();
|
private static final String s_rootPageURL = s_config.getRootPageUrl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL to page a user should be redirected to after login.
|
* URL to page a user should be redirected to after login.
|
||||||
*/
|
*/
|
||||||
private static final String s_userRedirectURL = s_config
|
private static final String s_userRedirectURL = s_config
|
||||||
.getUserRedirectUrl();
|
.getUserRedirectUrl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Absolute) URL for workspace page.
|
* (Absolute) URL for workspace page.
|
||||||
*/
|
*/
|
||||||
|
|
@ -174,73 +173,4 @@ public abstract class UI {
|
||||||
return getWorkspaceURL();
|
return getWorkspaceURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// Various deprfecated methods, to be removed as soon as invoking code is
|
|
||||||
// refactored.
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL (leading slash) into the system login page. It
|
|
||||||
* is relative to document root without any constant prefix if there is one
|
|
||||||
* configured.
|
|
||||||
*
|
|
||||||
* @return URL for login page as String
|
|
||||||
*
|
|
||||||
* @deprecated use Login.getLoginPageURL()() instead
|
|
||||||
*/
|
|
||||||
public static String getLoginPageURL() {
|
|
||||||
return LoginConstants.LOGIN_PAGE_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL (leading slash) for a cookie explanation page.
|
|
||||||
* It is relative to document root without any constant prefix if there is
|
|
||||||
* one configured.
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*
|
|
||||||
* @deprecated use LoginServlet.getCookiesExplainPageURL() instead
|
|
||||||
*/
|
|
||||||
public static String getCookiesExplainPageURL() {
|
|
||||||
return LoginServlet.getCookiesExplainPageURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL (leading slash) for a password recovery page. It
|
|
||||||
* is relative to document root without any constant prefix if there is one
|
|
||||||
* configured.
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*
|
|
||||||
* @deprecated use LoginServlet.getRecoverPasswordPageURL() instead
|
|
||||||
*/
|
|
||||||
public static String getRecoverPasswordPageURL() {
|
|
||||||
return LoginServlet.getRecoverPasswordPageURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL (leading slash) to a user profile editing page.
|
|
||||||
* It is relative to document root without any constant prefix if there is
|
|
||||||
* one configured.
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*
|
|
||||||
* @deprecated use LoginServlet.getEditUserProfilePageURL() instead
|
|
||||||
*/
|
|
||||||
public static String getEditUserProfilePageURL() {
|
|
||||||
return LoginServlet.getEditUserProfilePageURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL (leading slash) for the system logout page. It
|
|
||||||
* is relative to document root without any constant prefix if there is one
|
|
||||||
* configured.
|
|
||||||
*
|
|
||||||
* @return URL for logout page as String
|
|
||||||
*
|
|
||||||
* @deprecated use LoginServlet.getLogoutPageURL() instead
|
|
||||||
*/
|
|
||||||
public static String getLogoutPageURL() {
|
|
||||||
return LoginServlet.getLogoutPageURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
import com.arsdigita.bebop.SimpleComponent;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
import com.arsdigita.ui.login.LoginServlet;
|
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.web.URL;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
|
@ -120,18 +118,17 @@ public class UserBanner extends SimpleComponent {
|
||||||
|
|
||||||
contentElem.addAttribute("loginURL",
|
contentElem.addAttribute("loginURL",
|
||||||
URL.there(state.getRequest(),
|
URL.there(state.getRequest(),
|
||||||
LoginConstants.LOGIN_PAGE_URL)
|
"register/")
|
||||||
.toString());
|
.toString());
|
||||||
|
|
||||||
contentElem.addAttribute("logoutURL",
|
contentElem.addAttribute("logoutURL",
|
||||||
URL.there(state.getRequest(),
|
URL.there(state.getRequest(),
|
||||||
LoginServlet.getLogoutPageURL())
|
"register/logout")
|
||||||
.toString());
|
.toString());
|
||||||
|
|
||||||
contentElem.addAttribute("changePasswordURL",
|
contentElem.addAttribute("changePasswordURL",
|
||||||
URL.there(state.getRequest(),
|
URL.there(state.getRequest(),
|
||||||
LoginServlet
|
"register/change-password")
|
||||||
.getChangePasswordPageURL())
|
|
||||||
.toString());
|
.toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.form.Hidden;
|
|
||||||
import com.arsdigita.bebop.form.Password;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.URLParameter;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.web.ReturnSignal;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.UserManager;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Form that allows a user to change their password by entering their old
|
|
||||||
* password, a new password, and a confirmation of their new password. Requires
|
|
||||||
* that the user is logged in. Requires that new password differ from old and
|
|
||||||
* meet strong password requirements. If the user is recovering from a lost
|
|
||||||
* password (UserContext.isRecovering() is true), does not require or display
|
|
||||||
* the old password parameter and does not require that new password differ from
|
|
||||||
* old. Mails the user to notify of password change. Redirects user to workspace
|
|
||||||
* or return_url if set.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChangePasswordForm extends Form
|
|
||||||
implements FormProcessListener,
|
|
||||||
FormValidationListener {
|
|
||||||
|
|
||||||
final static String CHANGE_PASSWORD_FORM_NAME = "change-password";
|
|
||||||
final static String OLD_PASSWORD_PARAM_NAME = "old-password";
|
|
||||||
final static String NEW_PASSWORD_PARAM_NAME = "new-password";
|
|
||||||
final static String CONFIRM_PASSWORD_PARAM_NAME = "confirm-password";
|
|
||||||
final static String RETURN_URL_PARAM_NAME
|
|
||||||
= LoginHelper.RETURN_URL_PARAM_NAME;
|
|
||||||
private final UserAuthenticationListener m_listener
|
|
||||||
= new UserAuthenticationListener();
|
|
||||||
private Hidden m_returnURL;
|
|
||||||
// private Hidden m_recovery;
|
|
||||||
private Label m_oldPasswordLabel;
|
|
||||||
private Password m_oldPassword;
|
|
||||||
private Password m_newPassword;
|
|
||||||
private Password m_confirmPassword;
|
|
||||||
|
|
||||||
public ChangePasswordForm() {
|
|
||||||
this(new BoxPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
page.addRequestListener(m_listener);
|
|
||||||
page.addActionListener((final ActionEvent event) -> {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
m_oldPasswordLabel.setVisible(state, true);
|
|
||||||
m_oldPassword.setVisible(state, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangePasswordForm(Container panel) {
|
|
||||||
super(CHANGE_PASSWORD_FORM_NAME, panel);
|
|
||||||
|
|
||||||
setMethod(Form.POST);
|
|
||||||
addValidationListener(this);
|
|
||||||
addProcessListener(this);
|
|
||||||
|
|
||||||
// save the recovery credential as a hidden parameter
|
|
||||||
// m_recovery = new Hidden(new StringParameter(RecoveryLoginModule.getParamName()));
|
|
||||||
// m_recovery.setPassIn(true);
|
|
||||||
// add(m_recovery);
|
|
||||||
// save the return URL as a hidden parameter
|
|
||||||
m_returnURL = new Hidden(new URLParameter(RETURN_URL_PARAM_NAME));
|
|
||||||
m_returnURL.setPassIn(true);
|
|
||||||
add(m_returnURL);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
final Optional<User> user = shiro.getUser();
|
|
||||||
|
|
||||||
final Label greeting;
|
|
||||||
if (user.isPresent()) {
|
|
||||||
greeting = new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.greeting",
|
|
||||||
new Object[]{String.format("%s %s",
|
|
||||||
user.get().getGivenName(),
|
|
||||||
user.get().getFamilyName())}));
|
|
||||||
} else {
|
|
||||||
greeting = new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.greeting",
|
|
||||||
new Object[]{String.format("%s %s",
|
|
||||||
"",
|
|
||||||
"")}));
|
|
||||||
}
|
|
||||||
greeting.setFontWeight(Label.BOLD);
|
|
||||||
greeting.setClassAttr("greeting");
|
|
||||||
add(greeting);
|
|
||||||
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswortForm.introText")));
|
|
||||||
|
|
||||||
// old password
|
|
||||||
m_oldPasswordLabel = new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.oldPasswordLabel"));
|
|
||||||
add(m_oldPasswordLabel);
|
|
||||||
m_oldPassword = new Password(OLD_PASSWORD_PARAM_NAME);
|
|
||||||
// don't use NotNullValidationListener because
|
|
||||||
// old password may be null during password recovery
|
|
||||||
add(m_oldPassword);
|
|
||||||
|
|
||||||
// new password
|
|
||||||
Object[] params = new Object[]{PasswordValidationListener.MIN_LENGTH};
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.newPasswordLabel", params)));
|
|
||||||
m_newPassword = new Password(NEW_PASSWORD_PARAM_NAME);
|
|
||||||
m_newPassword.addValidationListener(new PasswordValidationListener());
|
|
||||||
add(m_newPassword);
|
|
||||||
|
|
||||||
// confirm new password
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.confirmPasswordLabel")));
|
|
||||||
m_confirmPassword = new Password(CONFIRM_PASSWORD_PARAM_NAME);
|
|
||||||
// don't use PasswordValidationListener to avoid duplicate errors
|
|
||||||
m_confirmPassword.addValidationListener(new NotNullValidationListener());
|
|
||||||
add(m_confirmPassword);
|
|
||||||
|
|
||||||
// submit
|
|
||||||
add(new Submit(LoginHelper.getMessage("login.changePasswordForm.submit")),
|
|
||||||
ColumnPanel.CENTER | ColumnPanel.FULL_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
try {
|
|
||||||
// get user object
|
|
||||||
if (!m_listener.isLoggedIn(state)) {
|
|
||||||
// this error should never appear
|
|
||||||
data.addError(LoginHelper.localize(
|
|
||||||
"login.changePasswordForm.noUserError",
|
|
||||||
state.getRequest()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// User user = m_listener.getUser(state);
|
|
||||||
|
|
||||||
// get parameter values
|
|
||||||
String oldPassword = (String) m_oldPassword.getValue(state);
|
|
||||||
String newPassword = (String) m_newPassword.getValue(state);
|
|
||||||
String confirmPassword = (String) m_confirmPassword.getValue(state);
|
|
||||||
|
|
||||||
//check oldPassword
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
final UserManager userManager = cdiUtil.findBean(UserManager.class);
|
|
||||||
|
|
||||||
final User user = shiro.getUser().get();
|
|
||||||
if (!userManager.verifyPassword(user, oldPassword)) {
|
|
||||||
data.addError(OLD_PASSWORD_PARAM_NAME, LoginHelper.getMessage(
|
|
||||||
"login.changePasswordForm.badPasswordError"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check new password
|
|
||||||
if (newPassword.equals(oldPassword)) {
|
|
||||||
data.addError(NEW_PASSWORD_PARAM_NAME, LoginHelper.localize(
|
|
||||||
"login.changePasswordForm.mustDifferError",
|
|
||||||
state.getRequest()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!newPassword.equals(confirmPassword)) {
|
|
||||||
data.addError(CONFIRM_PASSWORD_PARAM_NAME, LoginHelper.localize(
|
|
||||||
"login.changePasswordForm.mustMatchError",
|
|
||||||
state.getRequest()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (!data.isValid()) {
|
|
||||||
// clear passwords from form data
|
|
||||||
m_oldPassword.setValue(state, "");
|
|
||||||
m_newPassword.setValue(state, "");
|
|
||||||
m_confirmPassword.setValue(state, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
|
|
||||||
// get user object
|
|
||||||
if (!m_listener.isLoggedIn(state)) {
|
|
||||||
// this error should never appear (checked in validate)
|
|
||||||
data.addError(LoginHelper.localize(
|
|
||||||
"login.changePasswordForm.noUserError",
|
|
||||||
state.getRequest()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserManager userManager = cdiUtil.findBean(UserManager.class);
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
final User user = shiro.getUser().get();
|
|
||||||
|
|
||||||
final String newPassword = (String) m_newPassword.getValue(state);
|
|
||||||
userManager.updatePassword(user, newPassword);
|
|
||||||
|
|
||||||
final HttpServletRequest req = state.getRequest();
|
|
||||||
|
|
||||||
final String path = UI.getWorkspaceURL(req);
|
|
||||||
|
|
||||||
final URL fallback = URL.there(req, path);
|
|
||||||
|
|
||||||
throw new ReturnSignal(req, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
// import com.arsdigita.kernel.security.LegacyInitializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package-private class that generates the URL for a link dynamically from
|
|
||||||
* the kernel page map. This class will be removed or changes when the page
|
|
||||||
* map is replaced by package parameters.
|
|
||||||
*
|
|
||||||
* 2011-02-04: API change (pboy)
|
|
||||||
* The page map is no retrieved from a set of parameters. The target is now a
|
|
||||||
* String representation of the absolut url (leading slash) relativ to
|
|
||||||
* document root. The target is now a targetUrl, no longer a targetKey.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
class DynamicLink extends Link {
|
|
||||||
|
|
||||||
DynamicLink(final String labelKey, final String targetUrl) {
|
|
||||||
|
|
||||||
super(new Label(LoginHelper.getMessage(labelKey)),
|
|
||||||
new PrintListener() {
|
|
||||||
public void prepare(PrintEvent e) {
|
|
||||||
Link link = (Link) e.getTarget();
|
|
||||||
|
|
||||||
// see {@link com.arsdigita.bebopLink#Link(String,URL)}
|
|
||||||
// Url is now expected without leading context wich is handled
|
|
||||||
// by the new dispatcher. Therefore the req. is not needed.
|
|
||||||
// anymore.
|
|
||||||
// String url = LegacyInitializer.getFullURL
|
|
||||||
// (targetKey, e.getPageState().getRequest());
|
|
||||||
|
|
||||||
link.setTarget(targetUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.parameters.EmailParameter;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.shiro.subject.Subject;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the value of the given parameter to the current user's email
|
|
||||||
* address. If the user is not logged in or the email address is invalid, the
|
|
||||||
* parameter is not modified.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class EmailInitListener implements FormInitListener {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(EmailInitListener.class
|
|
||||||
.getName());
|
|
||||||
|
|
||||||
private EmailParameter m_param;
|
|
||||||
|
|
||||||
public EmailInitListener(EmailParameter param) {
|
|
||||||
m_param = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(FormSectionEvent event) {
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
|
|
||||||
LOGGER.debug("START");
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Subject subject = cdiUtil.findBean(Subject.class);
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
|
|
||||||
if (!subject.isAuthenticated()) {
|
|
||||||
LOGGER.debug("FAILURE not logged in");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final User user = shiro.getUser().get();
|
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
LOGGER.debug("FAILURE no such user");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.getPrimaryEmailAddress() == null) {
|
|
||||||
LOGGER.debug("FAILURE null primary email");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data.put(m_param.getName(), user.getPrimaryEmailAddress().getAddress());
|
|
||||||
|
|
||||||
LOGGER.debug("SUCCESS");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.libreccm.web.ApplicationCreator;
|
|
||||||
import org.libreccm.web.ApplicationRepository;
|
|
||||||
import org.libreccm.web.ApplicationType;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
public class LoginApplicationCreator
|
|
||||||
implements ApplicationCreator<CcmApplication> {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ApplicationRepository appRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CcmApplication createInstance(final String primaryUrl,
|
|
||||||
final ApplicationType type) {
|
|
||||||
if (!LOGIN_PAGE_URL.equals(primaryUrl)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Login is a singleton application"
|
|
||||||
+ "which is mounted at /login");
|
|
||||||
}
|
|
||||||
|
|
||||||
return appRepository.retrieveApplicationForPath(primaryUrl).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.libreccm.modules.InstallEvent;
|
|
||||||
import org.libreccm.web.AbstractCcmApplicationSetup;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class LoginApplicationSetup extends AbstractCcmApplicationSetup {
|
|
||||||
|
|
||||||
public static final String LOGIN_APP_NAME = "Login";
|
|
||||||
|
|
||||||
public LoginApplicationSetup(final InstallEvent event) {
|
|
||||||
super(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setup() {
|
|
||||||
final CcmApplication login = new CcmApplication();
|
|
||||||
login.setUuid(UUID.randomUUID().toString());
|
|
||||||
login.setApplicationType(LoginConstants.LOGIN_APP_TYPE);
|
|
||||||
login.setPrimaryUrl(LoginConstants.LOGIN_PAGE_URL);
|
|
||||||
|
|
||||||
getEntityManager().persist(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants used by Login UI.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface LoginConstants {
|
|
||||||
|
|
||||||
public static final String LOGIN_APP_TYPE = "com.arsdigita.ui.Login";
|
|
||||||
|
|
||||||
public static final String LOGIN_BUNDLE
|
|
||||||
= "com.arsdigita.ui.login.LoginResources";
|
|
||||||
|
|
||||||
public static final String LOGIN_UI_BUNDLE
|
|
||||||
= "org.libreccm.ui.LoginBundle";
|
|
||||||
|
|
||||||
public static final GlobalizedMessage SUBMIT = LoginHelper.getMessage(
|
|
||||||
"login.submit");
|
|
||||||
public static final GlobalizedMessage PRIMARY_EMAIL = LoginHelper
|
|
||||||
.getMessage("login.primaryEmail");
|
|
||||||
public static final GlobalizedMessage ADDITIONAL_EMAIL = LoginHelper
|
|
||||||
.getMessage("login.additionalEmail");
|
|
||||||
public static final GlobalizedMessage SCREEN_NAME = LoginHelper.getMessage(
|
|
||||||
"login.screenName");
|
|
||||||
public static final GlobalizedMessage FIRST_NAME = LoginHelper.getMessage(
|
|
||||||
"login.firstName");
|
|
||||||
public static final GlobalizedMessage LAST_NAME = LoginHelper.getMessage(
|
|
||||||
"login.lastName");
|
|
||||||
public static final GlobalizedMessage PASSWORD = LoginHelper.getMessage(
|
|
||||||
"login.password", new Object[]{
|
|
||||||
PasswordValidationListener.MIN_LENGTH});
|
|
||||||
public static final GlobalizedMessage PASSWORD_CONFIRMATION = LoginHelper
|
|
||||||
.getMessage("login.passwordConfirm");
|
|
||||||
public static final GlobalizedMessage PASSWORD_QUESTION = LoginHelper
|
|
||||||
.getMessage("login.passwordQuestion");
|
|
||||||
public static final GlobalizedMessage PASSWORD_ANSWER = LoginHelper
|
|
||||||
.getMessage("login.passwordAnswer");
|
|
||||||
public static final GlobalizedMessage URL_MSG = LoginHelper.getMessage(
|
|
||||||
"login.url");
|
|
||||||
public static final GlobalizedMessage BIO = LoginHelper.getMessage(
|
|
||||||
"login.bio");
|
|
||||||
|
|
||||||
public static final GlobalizedMessage ERROR_DUPLICATE_SN = LoginHelper
|
|
||||||
.getMessage("login.error.duplicateScreenName");
|
|
||||||
public static final GlobalizedMessage ERROR_DUPLICATE_EMAIL = LoginHelper
|
|
||||||
.getMessage("login.error.duplicateEmail");
|
|
||||||
public static final GlobalizedMessage ERROR_MISMATCH_PASSWORD = LoginHelper
|
|
||||||
.getMessage("login.error.mismatchPassword");
|
|
||||||
public static final GlobalizedMessage ERROR_BAD_PASSWORD = LoginHelper
|
|
||||||
.getMessage("login.error.badPassword");
|
|
||||||
|
|
||||||
public static final GlobalizedMessage ERROR_LOGIN_FAIL = LoginHelper
|
|
||||||
.getMessage("login.error.loginFail");
|
|
||||||
|
|
||||||
public static final GlobalizedMessage ERROR_BAD_ANSWER = LoginHelper
|
|
||||||
.getMessage("login.error.badAnswer");
|
|
||||||
public static final GlobalizedMessage ERROR_BAD_EMAIL = LoginHelper
|
|
||||||
.getMessage("login.error.badEmail");
|
|
||||||
public static final GlobalizedMessage ERROR_BANNED_EMAIL = LoginHelper
|
|
||||||
.getMessage("login.error.bannedEmail");
|
|
||||||
|
|
||||||
public static final String FORM_EMAIL = "emailAddress";
|
|
||||||
public static final String FORM_SCREEN_NAME = "screenName";
|
|
||||||
|
|
||||||
// Should not really be named email. Kept this way due to external tests
|
|
||||||
// depending on this value.
|
|
||||||
public static final String FORM_LOGIN = "email";
|
|
||||||
|
|
||||||
public static final String FORM_ADDITIONAL_EMAIL = "additional_email";
|
|
||||||
public static final String FORM_FIRST_NAME = "firstname";
|
|
||||||
public static final String FORM_LAST_NAME = "lastname";
|
|
||||||
public static final String FORM_GIVEN_NAME = "givenName";
|
|
||||||
public static final String FORM_FAMILY_NAME = "familyName";
|
|
||||||
public static final String FORM_USER_NAME = "username";
|
|
||||||
public static final String FORM_PASSWORD = "password";
|
|
||||||
public static final String FORM_PASSWORD_CONFIRMATION
|
|
||||||
= "password_confirmation";
|
|
||||||
public static final String FORM_PASSWORD_QUESTION = "question";
|
|
||||||
public static final String FORM_PASSWORD_ANSWER = "answer";
|
|
||||||
public static final String FORM_URL = "url";
|
|
||||||
public static final String FORM_URL_DEFAULT = "http://";
|
|
||||||
public static final String FORM_BIO = "biography";
|
|
||||||
public static final String FORM_TIMESTAMP = "timestamp";
|
|
||||||
public static final String FORM_PERSISTENT_LOGIN_P = "persistentCookieP";
|
|
||||||
public static final String FORM_PERSISTENT_LOGIN_P_DEFAULT = "1";
|
|
||||||
|
|
||||||
public static final int TIMESTAMP_LIFETIME_SECS = 300;
|
|
||||||
public static final int MAX_NAME_LEN = 60;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL_MSG stub of Login page in ServletPath format (with leading slash and
|
|
||||||
* without trailing slash
|
|
||||||
*/
|
|
||||||
// Don't modify without adapting instantiation in Loader class and
|
|
||||||
// updating existing databases (table applications)!
|
|
||||||
public static final String LOGIN_PAGE_URL = "/register/";
|
|
||||||
|
|
||||||
public static final String LOGIN_PATH = "/register";
|
|
||||||
|
|
||||||
public static final String LOGIN_SERVLET_PATH = "/login/*";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.globalization.Globalized;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compilation of methods to simplify the handling of globalizing keys.
|
|
||||||
* Basically it adds the name of package's resource bundle files to the
|
|
||||||
* globalize methods and forwards to GlobalizedMessage, shortening the
|
|
||||||
* method invocation in the various application classes.
|
|
||||||
*
|
|
||||||
* @author tosmers
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
*/
|
|
||||||
public class LoginGlobalizationUtil implements Globalized {
|
|
||||||
|
|
||||||
/** Name of Java resource files to handle CMS's globalisation. */
|
|
||||||
private static final String BUNDLE_NAME = "com.arsdigita.ui.admin.LoginResources";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a globalized message using the package specific bundle,
|
|
||||||
* provided by BUNDLE_NAME.
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static GlobalizedMessage globalize(String key) {
|
|
||||||
return new GlobalizedMessage(key, BUNDLE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a globalized message object, using the package specific bundle,
|
|
||||||
* as specified by BUNDLE_NAME. Also takes in an Object[] of arguments to
|
|
||||||
* interpolate into the retrieved message using the MessageFormat class.
|
|
||||||
* @param key
|
|
||||||
* @param args
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static GlobalizedMessage globalize(String key, Object[] args) {
|
|
||||||
return new GlobalizedMessage(key, BUNDLE_NAME, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the package specific resource bundle.
|
|
||||||
*
|
|
||||||
* @return Name of resource bundle as String
|
|
||||||
*/
|
|
||||||
public static String getBundleName() {
|
|
||||||
return BUNDLE_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.web.ReturnSignal;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides helper functions for the login UI.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*/
|
|
||||||
public class LoginHelper {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(LoginHelper.class);
|
|
||||||
|
|
||||||
public static final String RETURN_URL_PARAM_NAME = "return_url";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the login UI resource bundle
|
|
||||||
*
|
|
||||||
* @return the name of the login UI resource bundle
|
|
||||||
**/
|
|
||||||
static String getBundleBaseName() {
|
|
||||||
return "com.arsdigita.ui.login.LoginResources";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new GlobalizedMessage constructed with the given
|
|
||||||
* parameters and the login UI resource bundle.
|
|
||||||
*
|
|
||||||
* @return a new GlobalizedMessage
|
|
||||||
**/
|
|
||||||
static GlobalizedMessage getMessage(String key, Object[] args) {
|
|
||||||
return new GlobalizedMessage(key, getBundleBaseName(), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new GlobalizedMessage constructed with the given
|
|
||||||
* parameters and the login UI resource bundle.
|
|
||||||
*
|
|
||||||
* @return a new GlobalizedMessage
|
|
||||||
**/
|
|
||||||
static GlobalizedMessage getMessage(String key) {
|
|
||||||
return new GlobalizedMessage(key, getBundleBaseName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new GlobalizedMessage with the given parameters and the
|
|
||||||
* login UI resource bundle, then localizes the message with the given
|
|
||||||
* request.
|
|
||||||
*
|
|
||||||
* @return the localized String
|
|
||||||
**/
|
|
||||||
static String localize(String key, Object[] args,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
return (String)getMessage(key, args).localize(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new GlobalizedMessage with the given parameters and the
|
|
||||||
* login UI resource bundle, then localizes the message with the given
|
|
||||||
* request.
|
|
||||||
*
|
|
||||||
* @return the localized String
|
|
||||||
**/
|
|
||||||
static String localize(String key, HttpServletRequest request) {
|
|
||||||
return (String)getMessage(key).localize(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect the client to the URL stored in the return_url request
|
|
||||||
* parameter, or, if that parameter is not set, redirect to the given
|
|
||||||
* default URL.
|
|
||||||
*
|
|
||||||
* @param state the current page state
|
|
||||||
* @param def the default URL
|
|
||||||
**/
|
|
||||||
public static void doReturn(PageState state, String def) {
|
|
||||||
throw new ReturnSignal(state.getRequest(), def);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect the client to the given URL unless the response has
|
|
||||||
* already been committed. Wrapper for {@link
|
|
||||||
* #sendRedirect(HttpServletRequest, HttpServletResponse, String)}
|
|
||||||
* that pulls out the request and response from the PageState.
|
|
||||||
*
|
|
||||||
* @throws IOException if the redirect fails.
|
|
||||||
**/
|
|
||||||
public static void sendRedirect(PageState state, String url)
|
|
||||||
throws IOException {
|
|
||||||
sendRedirect(state.getRequest(), state.getResponse(), url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect the client to the given URL unless the response has already
|
|
||||||
* been committed. Aborts further request processing.
|
|
||||||
*
|
|
||||||
* @throws IOException if the redirect fails.
|
|
||||||
**/
|
|
||||||
public static void sendRedirect(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
String url)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
if (!response.isCommitted()) {
|
|
||||||
LOGGER.debug("Redirecting to: "+url);
|
|
||||||
DispatcherHelper.sendRedirect(request, response, url);
|
|
||||||
response.flushBuffer();
|
|
||||||
DispatcherHelper.abortRequest();
|
|
||||||
} else {
|
|
||||||
LOGGER.debug("Redirect failed because "
|
|
||||||
+"response already committed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,496 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 Peter Boy All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.ElementComponent;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageFactory;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.page.BebopApplicationServlet;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherConfig;
|
|
||||||
import com.arsdigita.kernel.security.SecurityConfig;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
import com.arsdigita.web.ReturnSignal;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.annotation.WebServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login Application Servlet class, central entry point to create and process
|
|
||||||
* the Login application UI.
|
|
||||||
*
|
|
||||||
* It manages user registration page, new user page, user workspace, logout, and
|
|
||||||
* permissions admin pages.
|
|
||||||
*
|
|
||||||
* It just defines a mapping URL_MSG <-> various pages and uses the super class
|
|
||||||
* to actually server the pages. Additionally is provides service methods to
|
|
||||||
* expose various properties, especially the URL_MSG's of public subpages (e.g.
|
|
||||||
* logout) and initializes the creation of the UI.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:pboy@barkhof.uni-bremen.de">Peter Boy</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@WebServlet(urlPatterns = {LOGIN_SERVLET_PATH})
|
|
||||||
public class LoginServlet extends BebopApplicationServlet {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 7783916040158924516L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger instance for debugging
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(LoginServlet.class);
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// Define various URLs to subpages of Login to manage administrative tasks.
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>edit profile</em>
|
|
||||||
* page. Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String EDIT_USER_PROFILE_PATH_INFO = "/edit-profile/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the (optional) <em>new
|
|
||||||
* user</em>
|
|
||||||
* page. Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String NEW_USER_PATH_INFO = "/new-user/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the activate account page.
|
|
||||||
* Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String ACTIVATE_ACCOUNT_PATH_INFO = "/active-account/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>change
|
|
||||||
* password</em> page. Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String CHANGE_USER_PASSWORD_PATH_INFO
|
|
||||||
= "/change-password/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>recover
|
|
||||||
* password</em> page. Ends with "/" because it is a servlet/directory.
|
|
||||||
*/
|
|
||||||
public static final String RECOVER_USER_PASSWORD_PATH_INFO
|
|
||||||
= "/recover-password/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>password reset</em>
|
|
||||||
* page which allows the user to replace a forgotten password with a new one
|
|
||||||
* (using a previously requested one time authentication token). Ends with
|
|
||||||
* "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String RESET_USER_PASSWORD_PATH_INFO = "/reset-password/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>verify email</em>
|
|
||||||
* page (not implemted yet!). Ends with "/" because it is a
|
|
||||||
* servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String VERIFY_EMAIL_PATH_INFO = "/verify-email/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>confirm email</em>
|
|
||||||
* page which allows the user to confirm his/her email address by submitting
|
|
||||||
* a previously requested one time authentication token (not implemented!).
|
|
||||||
* Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String CONFIRM_EMAIL_PATH_INFO = "/verify-email/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the (optional) <em>explain
|
|
||||||
* persistent</em> cookies page page. Ends with "/" because it is a
|
|
||||||
* servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String EXPLAIN_PERSISTENT_COOKIES_PATH_INFO
|
|
||||||
= "/explain-persistent-cookies/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>login
|
|
||||||
* expired-page</em>
|
|
||||||
* page. Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String LOGIN_EXPIRED_PATH_INFO = "/login-expired/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PathInfo into the Login application to access the <em>logout</em>
|
|
||||||
* page. Ends with "/" because it is a servlet/directory
|
|
||||||
*/
|
|
||||||
public static final String LOGOUT_PATH_INFO = "/logout/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base URL_MSG of the Login application for internal use, fetched from
|
|
||||||
* Login domain class.
|
|
||||||
*/
|
|
||||||
private final static String LOGIN_URL = LOGIN_PAGE_URL;
|
|
||||||
|
|
||||||
// define namespace URI
|
|
||||||
final static String SUBSITE_NS_URI = "http://www.arsdigita.com/subsite/1.0";
|
|
||||||
|
|
||||||
public static final String APPLICATION_NAME = "login";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ConfigurationManager confManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private UserRepository userRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User extension point used to create the pages to server and setup a
|
|
||||||
* URL_MSG - page mapping.
|
|
||||||
*
|
|
||||||
* @throws ServletException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void doInit() throws ServletException {
|
|
||||||
final SecurityConfig securityConfig = confManager.findConfiguration(
|
|
||||||
SecurityConfig.class);
|
|
||||||
|
|
||||||
if (userRepository == null) {
|
|
||||||
throw new IllegalStateException("User repository is not available.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow world caching for pages without authentication,
|
|
||||||
// ie, /register, /register/explain-persistent-cookies,
|
|
||||||
// /register/login-expired, /register/recover-password
|
|
||||||
// NB, although you'd think /register is cachable, it
|
|
||||||
// stores a timestamp in the login form :(
|
|
||||||
|
|
||||||
/* Create and add login page (index page of Login application) to the
|
|
||||||
* page map. KernelSecurityConfig determines whether to create a link
|
|
||||||
* to a NewUserRegistrationForm or to skip.
|
|
||||||
*/
|
|
||||||
put("/",
|
|
||||||
buildSimplePage(
|
|
||||||
"login.userRegistrationForm.title",
|
|
||||||
new UserLoginForm(securityConfig.isAutoRegistrationEnabled()),
|
|
||||||
"login"));
|
|
||||||
disableClientCaching("/");
|
|
||||||
|
|
||||||
/* Create and add userEditPage to the page map. */
|
|
||||||
put(EDIT_USER_PROFILE_PATH_INFO,
|
|
||||||
buildSimplePage("login.userEditPage.title",
|
|
||||||
new UserEditForm(), "edit"));
|
|
||||||
disableClientCaching(EDIT_USER_PROFILE_PATH_INFO);
|
|
||||||
|
|
||||||
/* Determines if a NewUserRegistrationForm has to be created by quering
|
|
||||||
* Kernel.getSecurityConfig() and acts appropriately
|
|
||||||
*/
|
|
||||||
if (SecurityConfig.getConfig().isAutoRegistrationEnabled()) {
|
|
||||||
put(NEW_USER_PATH_INFO,
|
|
||||||
buildSimplePage("login.userNewForm.title",
|
|
||||||
new UserNewForm(),
|
|
||||||
"register"));
|
|
||||||
disableClientCaching(NEW_USER_PATH_INFO);
|
|
||||||
|
|
||||||
put(ACTIVATE_ACCOUNT_PATH_INFO,
|
|
||||||
buildSimplePage("login.userActiveActivateAccount.title",
|
|
||||||
new UserAccountActivationForm(),
|
|
||||||
"activate"));
|
|
||||||
disableClientCaching(ACTIVATE_ACCOUNT_PATH_INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create ExplainPersistentCookiesPage and add to the page map
|
|
||||||
*/
|
|
||||||
put(EXPLAIN_PERSISTENT_COOKIES_PATH_INFO,
|
|
||||||
buildSimplePage("login.explainCookiesPage.title",
|
|
||||||
new ElementComponent(
|
|
||||||
"subsite:explainPersistentCookies",
|
|
||||||
SUBSITE_NS_URI),
|
|
||||||
"cookies"));
|
|
||||||
|
|
||||||
//Create ChangeUserPasswordPage and add to the page map
|
|
||||||
put(CHANGE_USER_PASSWORD_PATH_INFO,
|
|
||||||
buildSimplePage("login.changePasswordPage.title",
|
|
||||||
new ChangePasswordForm(),
|
|
||||||
"changepassword"));
|
|
||||||
disableClientCaching(CHANGE_USER_PASSWORD_PATH_INFO);
|
|
||||||
|
|
||||||
//Build the password recover page.
|
|
||||||
put(RECOVER_USER_PASSWORD_PATH_INFO,
|
|
||||||
buildSimplePage("login.recoverPasswordPage.title",
|
|
||||||
new RecoverPasswordForm(),
|
|
||||||
"recover-password"));
|
|
||||||
|
|
||||||
// Build the reset password page.
|
|
||||||
put(RESET_USER_PASSWORD_PATH_INFO,
|
|
||||||
buildSimplePage("login.resetPasswordPage.title",
|
|
||||||
new ResetPasswordForm(),
|
|
||||||
"reset-password"));
|
|
||||||
|
|
||||||
// Build the login expire page, retrieve its URL_MSG and store in map
|
|
||||||
put(LOGIN_EXPIRED_PATH_INFO, buildExpiredPage());
|
|
||||||
|
|
||||||
/* Create Logout Page and add to the page map
|
|
||||||
*/
|
|
||||||
put(LOGOUT_PATH_INFO, buildLogOutPage());
|
|
||||||
disableClientCaching(LOGOUT_PATH_INFO);
|
|
||||||
|
|
||||||
Page workspace = checkForPageSubClass();
|
|
||||||
if (workspace == null) {
|
|
||||||
workspace = buildSimplePage("login.workspacePage.title",
|
|
||||||
new UserInfo(),
|
|
||||||
"workspace");
|
|
||||||
}
|
|
||||||
put(UI.getWorkspaceURL(), workspace); // usually navigation/ or portal/
|
|
||||||
disableClientCaching(UI.getWorkspaceURL());
|
|
||||||
|
|
||||||
// special case to handle pvt/home
|
|
||||||
// String url = LegacyInitializer.getURL(LegacyInitializer.WORKSPACE_PAGE_KEY);
|
|
||||||
// pboy: This page / url seems to be a left over from older versions,
|
|
||||||
// currently not contained in source code.
|
|
||||||
String url = UI.getWorkspaceURL();
|
|
||||||
if (url.equals("pvt/")) {
|
|
||||||
put("pvt/home", workspace);
|
|
||||||
disableClientCaching("pvt/home");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check wether a custom base Page class (top-level container for all Bebop
|
|
||||||
* components and containersPages) is configured and return the appropriate
|
|
||||||
* Page. Here used (only) for UserInfo() workspace.
|
|
||||||
*
|
|
||||||
* @return Page to use for top-level container for all Bebop components and
|
|
||||||
* containersPage, null to use default class
|
|
||||||
*/
|
|
||||||
private static Page checkForPageSubClass() {
|
|
||||||
//check to see if there is subclass of Page defined in Config
|
|
||||||
DispatcherConfig dc = DispatcherConfig.getConfig();
|
|
||||||
String pageClass = dc.getDefaultPageClass();
|
|
||||||
Page p = null;
|
|
||||||
if (!pageClass.equals("com.arsdigita.bebop.Page")) {
|
|
||||||
try {
|
|
||||||
// afraid that we're assuming a no-arg constructor
|
|
||||||
Class c = Class.forName(pageClass);
|
|
||||||
p = (Page) c.newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error(
|
|
||||||
"Unable to instantiate waf.dispatcher.default_page_class", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Page with the given title and body component.
|
|
||||||
*
|
|
||||||
* @return the new Page
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static Page buildSimplePage(String title, Component body, String id) {
|
|
||||||
|
|
||||||
Page page = PageFactory.buildPage(APPLICATION_NAME,
|
|
||||||
new Label(LoginHelper
|
|
||||||
.getMessage(title)),
|
|
||||||
id);
|
|
||||||
page.add(body);
|
|
||||||
page.lock();
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a page informing the user the login has expired. Provides links
|
|
||||||
* to login again, etc.
|
|
||||||
*
|
|
||||||
* @return Page (login expired info)
|
|
||||||
*/
|
|
||||||
private static Page buildExpiredPage() {
|
|
||||||
Page page = PageFactory.buildPage(
|
|
||||||
APPLICATION_NAME,
|
|
||||||
new Label(LoginHelper.getMessage("login.loginExpiredPage.title"))
|
|
||||||
);
|
|
||||||
page.add(new SimpleContainer() {
|
|
||||||
|
|
||||||
{ // constructor
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.loginExpiredPage.before")));
|
|
||||||
add(new DynamicLink("login.loginExpiredPage.link",
|
|
||||||
LOGIN_PAGE_URL));
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.loginExpiredPage.after")));
|
|
||||||
add(new ElementComponent("subsite:explainLoginExpired",
|
|
||||||
SUBSITE_NS_URI));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
page.lock();
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static Page buildLogOutPage() {
|
|
||||||
Page page = PageFactory.buildPage(
|
|
||||||
APPLICATION_NAME,
|
|
||||||
new Label(LoginHelper.getMessage("Logout"))
|
|
||||||
);
|
|
||||||
page.addActionListener(new UserLogoutListener());
|
|
||||||
page.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final HttpServletRequest req = state.getRequest();
|
|
||||||
|
|
||||||
final String path = UI.getRootPageURL(req);
|
|
||||||
|
|
||||||
throw new ReturnSignal(req, URL.there(req, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
page.lock();
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an (absolute) URL_MSG to a user profile edit page. It is
|
|
||||||
* relative to document root without any constant prefix if there is one
|
|
||||||
* configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have to be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return url to EditUserProfile page as String
|
|
||||||
*/
|
|
||||||
public static String getEditUserProfilePageURL() {
|
|
||||||
return LOGIN_URL + EDIT_USER_PROFILE_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getChangePasswordPageURL() {
|
|
||||||
return LOGIN_URL + CHANGE_USER_PASSWORD_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an (absolute URL_MSG) to an optional new user registration page
|
|
||||||
* (accessible only if activated). It is relative to document root without
|
|
||||||
* any constant prefix if there is one configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have to be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return url to new user registration page as String
|
|
||||||
*/
|
|
||||||
public static String getNewUserPageURL() {
|
|
||||||
return LOGIN_URL + NEW_USER_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL_MSG (leading slash) for a password recovery
|
|
||||||
* page. It is relative to document root without any constant prefix if
|
|
||||||
* there is one configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have tp be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*/
|
|
||||||
public static String getRecoverPasswordPageURL() {
|
|
||||||
return LOGIN_URL + RECOVER_USER_PASSWORD_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL_MSG (leading slash) for a cookie explanation
|
|
||||||
* page. It is relative to document root without any constant prefix if
|
|
||||||
* there is one configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have tp be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*/
|
|
||||||
public static String getCookiesExplainPageURL() {
|
|
||||||
return LOGIN_URL + EXPLAIN_PERSISTENT_COOKIES_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL_MSG (leading slash) for a login expired info
|
|
||||||
* page. It is relative to document root without any constant prefix if
|
|
||||||
* there is one configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have tp be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return url String for new user registration page as String
|
|
||||||
*/
|
|
||||||
public static String getLoginExpiredPageURL() {
|
|
||||||
return LOGIN_URL + LOGIN_EXPIRED_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an absolute URL_MSG (leading slash) for the system logout page.
|
|
||||||
* It is relative to document root without any constant prefix if there is
|
|
||||||
* one configured.
|
|
||||||
*
|
|
||||||
* XXX This implementation starts with a leading slash and ends with a
|
|
||||||
* slash. In previous configurations String urls began without a slash in
|
|
||||||
* order to be able to provide a full URL_MSG which also contains the
|
|
||||||
* context part. Since version 5.2 the context part is handled by (new)
|
|
||||||
* dispatcher. The leading slash it API change! It's impacts have tp be
|
|
||||||
* checked. (2011-02)
|
|
||||||
*
|
|
||||||
* @return URL_MSG for logout page as String
|
|
||||||
*/
|
|
||||||
public static String getLogoutPageURL() {
|
|
||||||
return LOGIN_URL.substring(0,
|
|
||||||
LOGIN_URL.length() - 1) + LOGOUT_PATH_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.event.ParameterEvent;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A NotNullValidationListener that checks whether the string value of a
|
|
||||||
* parameter is a strong password.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PasswordValidationListener
|
|
||||||
extends NotNullValidationListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Minimum length for passwords.
|
|
||||||
*/
|
|
||||||
public static final int MIN_LENGTH = 6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum number of character types for passwords. Valid values are on
|
|
||||||
* range [1,4].
|
|
||||||
*/
|
|
||||||
public static final int MIN_TYPES = 1;
|
|
||||||
|
|
||||||
public PasswordValidationListener() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PasswordValidationListener(String label) {
|
|
||||||
super(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the string value of the parameter meets minimum-length
|
|
||||||
* and composition requirements for strong passwords.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void validate(ParameterEvent e) {
|
|
||||||
super.validate(e);
|
|
||||||
|
|
||||||
ParameterData data = e.getParameterData();
|
|
||||||
if (!data.isValid()) {
|
|
||||||
// already has errors from superclass
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check length
|
|
||||||
String password = data.getValue().toString();
|
|
||||||
if (password.length() < MIN_LENGTH) {
|
|
||||||
data.addError(LoginHelper.getMessage
|
|
||||||
("login.passwordValidation.minLengthError",
|
|
||||||
new Object[] { new Integer(MIN_LENGTH) }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for whitespace
|
|
||||||
if (contains(password, whites)) {
|
|
||||||
data.addError(LoginHelper.getMessage
|
|
||||||
("login.passwordValidation.whitespaceError"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check character mix
|
|
||||||
int charSets = 0;
|
|
||||||
if (contains(password, uppers)) {
|
|
||||||
charSets++;
|
|
||||||
}
|
|
||||||
if (contains(password, lowers)) {
|
|
||||||
charSets++;
|
|
||||||
}
|
|
||||||
if (contains(password, digits)) {
|
|
||||||
charSets++;
|
|
||||||
}
|
|
||||||
if (contains(password, others)) {
|
|
||||||
charSets++;
|
|
||||||
}
|
|
||||||
if (charSets < MIN_TYPES) {
|
|
||||||
data.addError(LoginHelper.getMessage
|
|
||||||
("login.passwordValidation.minTypesError",
|
|
||||||
new Object[] { MIN_TYPES}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static interface CharSet {
|
|
||||||
public boolean contains(char c);
|
|
||||||
}
|
|
||||||
private static boolean contains(String s, CharSet set) {
|
|
||||||
for (int i = 0; i < s.length(); i++) {
|
|
||||||
if (set.contains(s.charAt(i))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
private static CharSet whites = new CharSet() {
|
|
||||||
@Override
|
|
||||||
public boolean contains(char c) {
|
|
||||||
return Character.isWhitespace(c);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static CharSet uppers = new CharSet() {
|
|
||||||
@Override
|
|
||||||
public boolean contains(char c) {
|
|
||||||
return (Character.isLetter(c)
|
|
||||||
&& Character.isUpperCase(c));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static CharSet lowers = new CharSet() {
|
|
||||||
@Override
|
|
||||||
public boolean contains(char c) {
|
|
||||||
return (Character.isLetter(c)
|
|
||||||
&& Character.isLowerCase(c));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static CharSet digits = new CharSet() {
|
|
||||||
@Override
|
|
||||||
public boolean contains(char c) {
|
|
||||||
return Character.isDigit(c);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static CharSet others = new CharSet() {
|
|
||||||
@Override
|
|
||||||
public boolean contains(char c) {
|
|
||||||
return !(Character.isLetterOrDigit(c)
|
|
||||||
|| Character.isISOControl(c)
|
|
||||||
|| Character.isWhitespace(c));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.ChallengeManager;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
import static com.arsdigita.ui.login.LoginServlet.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class RecoverPasswordForm extends Form {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
RecoverPasswordForm.class);
|
|
||||||
|
|
||||||
private static final String EMAIL = "email";
|
|
||||||
|
|
||||||
private BoxPanel formPanel;
|
|
||||||
private TextField email;
|
|
||||||
private SaveCancelSection saveCancelSection;
|
|
||||||
private BoxPanel finishedMessagePanel;
|
|
||||||
|
|
||||||
public RecoverPasswordForm() {
|
|
||||||
super("recover-password");
|
|
||||||
|
|
||||||
addWidgets();
|
|
||||||
addListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addWidgets() {
|
|
||||||
formPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
|
|
||||||
email = new TextField(EMAIL);
|
|
||||||
email.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.recover_password.email.label",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.recover_password.email.hint",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setMaxLength(256);
|
|
||||||
email.setSize(48);
|
|
||||||
email.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
email.addValidationListener(new StringLengthValidationListener(256));
|
|
||||||
formPanel.add(email);
|
|
||||||
|
|
||||||
saveCancelSection = new SaveCancelSection();
|
|
||||||
formPanel.add(saveCancelSection);
|
|
||||||
|
|
||||||
add(formPanel);
|
|
||||||
|
|
||||||
finishedMessagePanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
finishedMessagePanel.add(new Label(new GlobalizedMessage(
|
|
||||||
"login.form.recover_password.finished_message", LOGIN_BUNDLE)));
|
|
||||||
final Link link = new Link(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.recover_password.finished_message.link",
|
|
||||||
LOGIN_BUNDLE)),
|
|
||||||
LOGIN_PAGE_URL + RESET_USER_PASSWORD_PATH_INFO);
|
|
||||||
finishedMessagePanel.add(link);
|
|
||||||
add(finishedMessagePanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addListeners() {
|
|
||||||
// addValidationListener(e -> {
|
|
||||||
// final PageState state = e.getPageState();
|
|
||||||
//
|
|
||||||
// if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
// final FormData data = e.getFormData();
|
|
||||||
//
|
|
||||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
// final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
// UserRepository.class);
|
|
||||||
//
|
|
||||||
// final User user = userRepository.findByEmailAddress(
|
|
||||||
// (String) data.get(EMAIL));
|
|
||||||
// if (user == null) {
|
|
||||||
// data.addError(new GlobalizedMessage(
|
|
||||||
// "login.form.recover_password.error", LOGIN_BUNDLE));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
addProcessListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
final Optional<User> user = userRepository.findByEmailAddress(
|
|
||||||
(String) data.get(EMAIL));
|
|
||||||
|
|
||||||
// We don't show an error message if there is no matching user
|
|
||||||
// account. This way we don't provide an attacker with
|
|
||||||
// the valuable information that there is user account for
|
|
||||||
// a particular email address.
|
|
||||||
if (user.isPresent()) {
|
|
||||||
final ChallengeManager challengeManager = cdiUtil.findBean(
|
|
||||||
ChallengeManager.class);
|
|
||||||
try {
|
|
||||||
challengeManager.sendPasswordRecover(user.get());
|
|
||||||
} catch (MessagingException ex) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"Failed to send password recovery instructions.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.recover_password.error.send_challenge_failed",
|
|
||||||
LOGIN_BUNDLE),
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
LOGGER.warn(
|
|
||||||
"Password recover requested for not existing user {}.",
|
|
||||||
data.get(EMAIL));
|
|
||||||
}
|
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
|
||||||
finishedMessagePanel.setVisible(state, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.setVisibleDefault(formPanel, true);
|
|
||||||
page.setVisibleDefault(finishedMessagePanel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,417 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.ElementComponent;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.EmailParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.mail.Mail;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.RandomStringUtils;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiLookupException;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sequence of Forms and Panels that allows a user to recover from a forgotten
|
|
||||||
* password. First form requests the user's email address, and is pre-filled if
|
|
||||||
* the user is logged in. Second form presents the user's password question and
|
|
||||||
* requires the correct answer. Third panel informs the user that a mail has
|
|
||||||
* been sent that will allow them to change their password.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class RecoverPasswordPanel extends SimpleContainer
|
|
||||||
implements LoginConstants {
|
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(
|
|
||||||
RecoverPasswordPanel.class.getName());
|
|
||||||
|
|
||||||
private static ParameterModel DISPLAY_PARAM = new StringParameter("display");
|
|
||||||
private static ParameterModel USERID_PARAM = new BigDecimalParameter(
|
|
||||||
"userID");
|
|
||||||
|
|
||||||
private EnterEmailForm m_enterEmailForm;
|
|
||||||
private AnswerQuestionForm m_answerQuestionForm;
|
|
||||||
private MailSentPane m_mailSentPane;
|
|
||||||
private MailFailedPane m_mailFailedPane;
|
|
||||||
|
|
||||||
public void register(Page p) {
|
|
||||||
super.register(p);
|
|
||||||
p.addComponentStateParam(this, DISPLAY_PARAM);
|
|
||||||
p.addComponentStateParam(this, USERID_PARAM);
|
|
||||||
p.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
String display = (String) state.getValue(DISPLAY_PARAM);
|
|
||||||
s_log.debug("display == " + display);
|
|
||||||
boolean visible = false;
|
|
||||||
visible |= setVisible(state, display, m_enterEmailForm);
|
|
||||||
visible |= setVisible(state, display, m_answerQuestionForm);
|
|
||||||
visible |= setVisible(state, display, m_mailSentPane);
|
|
||||||
visible |= setVisible(state, display, m_mailFailedPane);
|
|
||||||
if (!visible) {
|
|
||||||
// default: show first form
|
|
||||||
m_enterEmailForm.setVisible(state, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setVisible(PageState state,
|
|
||||||
String display,
|
|
||||||
Component component) {
|
|
||||||
boolean visible = component.getClass().getName()
|
|
||||||
.equals(display);
|
|
||||||
component.setVisible(state, visible);
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecoverPasswordPanel() {
|
|
||||||
m_enterEmailForm = new EnterEmailForm();
|
|
||||||
add(m_enterEmailForm);
|
|
||||||
|
|
||||||
m_answerQuestionForm = new AnswerQuestionForm();
|
|
||||||
add(m_answerQuestionForm);
|
|
||||||
|
|
||||||
m_mailSentPane = new MailSentPane();
|
|
||||||
add(m_mailSentPane);
|
|
||||||
|
|
||||||
m_mailFailedPane = new MailFailedPane();
|
|
||||||
add(m_mailFailedPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EnterEmailForm extends Form
|
|
||||||
implements FormValidationListener, FormProcessListener {
|
|
||||||
|
|
||||||
public EnterEmailForm() {
|
|
||||||
super("enter-email", new BoxPanel());
|
|
||||||
addValidationListener(this);
|
|
||||||
addProcessListener(this);
|
|
||||||
add(new Label(PRIMARY_EMAIL));
|
|
||||||
TextField email = new TextField(new EmailParameter(FORM_EMAIL));
|
|
||||||
email.addValidationListener(new NotNullValidationListener());
|
|
||||||
addInitListener(new EmailInitListener((EmailParameter) email
|
|
||||||
.getParameterModel()));
|
|
||||||
add(email);
|
|
||||||
add(new Submit(SUBMIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
if (!data.isValid()) {
|
|
||||||
// data already has errors
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final String email = ((InternetAddress) data.get(FORM_EMAIL))
|
|
||||||
.getAddress();
|
|
||||||
final long userID;
|
|
||||||
// try {
|
|
||||||
// final CdiUtil cdiUtil = new CdiUtil();
|
|
||||||
// final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
// UserRepository.class);
|
|
||||||
// final User user = userRepository.findByEmailAddress(email);
|
|
||||||
// if (user == null) {
|
|
||||||
// data.addError(FORM_EMAIL,
|
|
||||||
// (String) ERROR_BAD_EMAIL.localize(event
|
|
||||||
// .getPageState().getRequest()));
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// userID = user.getSubjectId();
|
|
||||||
// event.getPageState().setValue(USERID_PARAM, userID);
|
|
||||||
//
|
|
||||||
// if (userID != 0) {
|
|
||||||
// if (user.isBanned()) {
|
|
||||||
// data.addError(FORM_EMAIL, (String) ERROR_BANNED_EMAIL
|
|
||||||
// .localize(event.getPageState()
|
|
||||||
// .getRequest()));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (CdiLookupException ex) {
|
|
||||||
// throw new UncheckedWrapperException(
|
|
||||||
// "Failed to lookup UserRepository", ex);
|
|
||||||
// }
|
|
||||||
// if the user exists, we need to make sure they are not banned.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
event.getPageState().setValue(DISPLAY_PARAM,
|
|
||||||
AnswerQuestionForm.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AnswerQuestionForm extends Form
|
|
||||||
implements FormValidationListener, FormProcessListener {
|
|
||||||
|
|
||||||
private final TextField m_answer;
|
|
||||||
|
|
||||||
public AnswerQuestionForm() {
|
|
||||||
super("answer-question", new BoxPanel());
|
|
||||||
addValidationListener(this);
|
|
||||||
addProcessListener(this);
|
|
||||||
add(new Label(PASSWORD_QUESTION));
|
|
||||||
Label question = new Label();
|
|
||||||
question.setIdAttr("question");
|
|
||||||
question.addPrintListener(new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final Label label = (Label) event.getTarget();
|
|
||||||
final long userID = (long) event.getPageState()
|
|
||||||
.getValue(USERID_PARAM);
|
|
||||||
if (userID == 0) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"userID must not be 0");
|
|
||||||
}
|
|
||||||
// try {
|
|
||||||
// final CdiUtil cdiUtil = new CdiUtil();
|
|
||||||
//// final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
//// UserRepository.class);
|
|
||||||
//// final User user = userRepository.findById(userID);
|
|
||||||
//// if (user == null) {
|
|
||||||
//// throw new IllegalStateException(
|
|
||||||
//// "userID must be a valid user");
|
|
||||||
//// }
|
|
||||||
//
|
|
||||||
// String theQuestion = user.getPasswordQuestion();
|
|
||||||
// if (theQuestion == null) {
|
|
||||||
// throw new IllegalStateException(
|
|
||||||
// "password question must not be null "
|
|
||||||
// + "(userID == " + userID + ")");
|
|
||||||
// }
|
|
||||||
// label.setLabel(theQuestion);
|
|
||||||
// } catch (CdiLookupException ex) {
|
|
||||||
// throw new UncheckedWrapperException(
|
|
||||||
// "Failed to lookup user repository", ex);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
add(question);
|
|
||||||
add(new Label(PASSWORD_ANSWER));
|
|
||||||
m_answer = new TextField(new StringParameter(FORM_PASSWORD_ANSWER));
|
|
||||||
m_answer.addValidationListener(new NotNullValidationListener());
|
|
||||||
add(m_answer);
|
|
||||||
add(new Submit(SUBMIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
if (!data.isValid()) {
|
|
||||||
// data already has errors
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final String answer = (String) data.get(FORM_PASSWORD_ANSWER);
|
|
||||||
// FIXME: same as code above; instead save UserAuth object
|
|
||||||
final long userID = (long) event.getPageState().getValue(
|
|
||||||
USERID_PARAM);
|
|
||||||
if (userID == 0) {
|
|
||||||
throw new IllegalStateException("userID must not be 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// final CdiUtil cdiUtil = new CdiUtil();
|
|
||||||
// final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
// UserRepository.class);
|
|
||||||
// final User user = userRepository.findById(userID);
|
|
||||||
// if (user == null) {
|
|
||||||
// throw new IllegalStateException(
|
|
||||||
// "userID must be a valid user");
|
|
||||||
// }
|
|
||||||
// final String correctAnswer = user.getPasswordAnswer();
|
|
||||||
// if (!correctAnswer.equals(answer)) {
|
|
||||||
// data.addError(FORM_PASSWORD_ANSWER,
|
|
||||||
// (String) ERROR_BAD_ANSWER.localize(event
|
|
||||||
// .getPageState().getRequest()));
|
|
||||||
// }
|
|
||||||
// } catch (CdiLookupException ex) {
|
|
||||||
// throw new UncheckedWrapperException(
|
|
||||||
// "Failed to lookup UserRepository", ex);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
final HttpServletRequest req = event.getPageState().getRequest();
|
|
||||||
|
|
||||||
final long userID = (long) event.getPageState().getValue(
|
|
||||||
USERID_PARAM);
|
|
||||||
|
|
||||||
if (userID == 0) {
|
|
||||||
throw new IllegalStateException("userID must not be 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// final CdiUtil cdiUtil = new CdiUtil();
|
|
||||||
// final UserRepository userRepository;
|
|
||||||
// try {
|
|
||||||
// userRepository = cdiUtil.findBean(UserRepository.class);
|
|
||||||
// } catch (CdiLookupException ex) {
|
|
||||||
// throw new UncheckedWrapperException(
|
|
||||||
// "Failed to lookup UserRepository", ex);
|
|
||||||
// }
|
|
||||||
// final User user = userRepository.findById(userID);
|
|
||||||
// if (user == null) {
|
|
||||||
// throw new IllegalStateException("userID must be a valid user");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (user.getEmailAddresses().isEmpty()) {
|
|
||||||
// mailFailed(event, "null email, user ID: " + user.getSubjectId());
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// String to = user.getEmailAddresses().get(0).getAddress();
|
|
||||||
// String from = Mail.getConfig().getDefaultFrom();
|
|
||||||
// // AFAICT this value below is hard coded to "" !
|
|
||||||
// //KernelHelper.getSystemAdministratorEmailAddress();
|
|
||||||
// String subject = LoginHelper.localize(
|
|
||||||
// "login.recoverPassword.mailSubject", req);
|
|
||||||
// String body = getNotification(user, event, req);
|
|
||||||
//
|
|
||||||
// send the message and set next panel to "mail sent" page
|
|
||||||
// try {
|
|
||||||
// Mail.send(to, from, subject, body);
|
|
||||||
// event.getPageState().setValue(DISPLAY_PARAM, MailSentPane.class
|
|
||||||
// .getName());
|
|
||||||
// } catch (MessagingException e) {
|
|
||||||
// mailFailed(event, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log a failure to notify the user and set the next panel to the "mail
|
|
||||||
* failed" page.
|
|
||||||
*/
|
|
||||||
private static void mailFailed(FormSectionEvent event,
|
|
||||||
String reason) {
|
|
||||||
s_log.warn("Could not notify user for recovery: " + reason);
|
|
||||||
event.getPageState().setValue(DISPLAY_PARAM, MailFailedPane.class
|
|
||||||
.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a message that password recovery information has been sent.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static class MailSentPane extends ElementComponent {
|
|
||||||
|
|
||||||
public MailSentPane() {
|
|
||||||
super("subsite:recoverPasswordMailSent",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs the notification to send users when recovering a password.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// private static String getNotification(final User user,
|
|
||||||
// final FormSectionEvent event,
|
|
||||||
// final HttpServletRequest req) {
|
|
||||||
// final CdiUtil cdiUtil = new CdiUtil();
|
|
||||||
// final UserManager userManager;
|
|
||||||
// final UserRepository userRepository;
|
|
||||||
// try {
|
|
||||||
// userManager = cdiUtil.findBean(UserManager.class);
|
|
||||||
// userRepository = cdiUtil.findBean(UserRepository.class);
|
|
||||||
// } catch (CdiLookupException ex) {
|
|
||||||
// throw new UncheckedWrapperException(
|
|
||||||
// "Failed to lookup UserRepository or UserManager", ex);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final String name = user.getName().getGivenName();
|
|
||||||
// String tmpPassword = RandomStringUtils.random(
|
|
||||||
// 16, 0, 0, false, false, null, new SecureRandom());
|
|
||||||
//
|
|
||||||
// userManager.updatePassword(user, tmpPassword);
|
|
||||||
// user.setPasswordResetRequired(true);
|
|
||||||
// userRepository.save(user);
|
|
||||||
//
|
|
||||||
// return LoginHelper.localize("login.recoverPassword.mailBody",
|
|
||||||
// new Object[]{name, tmpPassword},
|
|
||||||
// req);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a message that password recovery information couldn't be sent.
|
|
||||||
* There must be a better way to do this!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static class MailFailedPane extends ElementComponent {
|
|
||||||
|
|
||||||
public MailFailedPane() {
|
|
||||||
super("subsite:recoverPasswordMailFailed",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,282 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
|
||||||
import com.arsdigita.bebop.form.Password;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
import org.libreccm.security.ChallengeFailedException;
|
|
||||||
import org.libreccm.security.ChallengeManager;
|
|
||||||
import org.libreccm.security.OneTimeAuthConfig;
|
|
||||||
import org.libreccm.security.OneTimeAuthManager;
|
|
||||||
import org.libreccm.security.OneTimeAuthToken;
|
|
||||||
import org.libreccm.security.OneTimeAuthTokenPurpose;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ResetPasswordForm extends Form {
|
|
||||||
|
|
||||||
private static final String EMAIL = "email";
|
|
||||||
private static final String AUTH_TOKEN = "authToken";
|
|
||||||
private static final String PASSWORD = "password";
|
|
||||||
private static final String PASSWORD_CONFIRMATION = "passwordconfirmation";
|
|
||||||
|
|
||||||
private BoxPanel formPanel;
|
|
||||||
private TextField email;
|
|
||||||
private TextField authToken;
|
|
||||||
private Password password;
|
|
||||||
private Password passwordConfirmation;
|
|
||||||
private SaveCancelSection saveCancelSection;
|
|
||||||
private BoxPanel successPanel;
|
|
||||||
|
|
||||||
public ResetPasswordForm() {
|
|
||||||
super("reset-password");
|
|
||||||
|
|
||||||
addWidgets();
|
|
||||||
addListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addWidgets() {
|
|
||||||
formPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
|
|
||||||
email = new TextField(EMAIL);
|
|
||||||
email.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.email.label",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.email.hint",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setMaxLength(256);
|
|
||||||
email.setSize(48);
|
|
||||||
email.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
email.addValidationListener(new StringLengthValidationListener(256));
|
|
||||||
formPanel.add(email);
|
|
||||||
|
|
||||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(ConfigurationManager.class);
|
|
||||||
final OneTimeAuthConfig oneTimeAuthConfig = confManager
|
|
||||||
.findConfiguration(OneTimeAuthConfig.class);
|
|
||||||
authToken = new TextField(AUTH_TOKEN);
|
|
||||||
authToken.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.auth_token.label", LOGIN_BUNDLE));
|
|
||||||
authToken.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.auth_token.hint", LOGIN_BUNDLE));
|
|
||||||
authToken.setMaxLength(oneTimeAuthConfig.getTokenLength());
|
|
||||||
authToken.setSize(oneTimeAuthConfig.getTokenLength());
|
|
||||||
formPanel.add(authToken);
|
|
||||||
|
|
||||||
password = new Password(PASSWORD);
|
|
||||||
password.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.password.label", LOGIN_BUNDLE));
|
|
||||||
password.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.password.hint", LOGIN_BUNDLE));
|
|
||||||
password.setMaxLength(256);
|
|
||||||
password.setSize(32);
|
|
||||||
password.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
password.addValidationListener(new StringLengthValidationListener(256));
|
|
||||||
formPanel.add(password);
|
|
||||||
|
|
||||||
passwordConfirmation = new Password(PASSWORD_CONFIRMATION);
|
|
||||||
passwordConfirmation.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.password_confirmation.label",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
passwordConfirmation.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.password_confirmation.hint",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
passwordConfirmation.setMaxLength(256);
|
|
||||||
passwordConfirmation.setSize(32);
|
|
||||||
passwordConfirmation.addValidationListener(
|
|
||||||
new NotEmptyValidationListener());
|
|
||||||
passwordConfirmation.addValidationListener(
|
|
||||||
new StringLengthValidationListener(256));
|
|
||||||
formPanel.add(passwordConfirmation);
|
|
||||||
|
|
||||||
saveCancelSection = new SaveCancelSection();
|
|
||||||
formPanel.add(saveCancelSection);
|
|
||||||
|
|
||||||
add(formPanel);
|
|
||||||
|
|
||||||
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
successPanel.add(new Label(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.scucess", LOGIN_BUNDLE)));
|
|
||||||
successPanel.add(new Link(new Label(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.scucess.login",
|
|
||||||
LOGIN_BUNDLE)),
|
|
||||||
URL.there(LOGIN_PAGE_URL, null).getURL()));
|
|
||||||
|
|
||||||
add(successPanel);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addListeners() {
|
|
||||||
addInitListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
final HttpServletRequest request = state.getRequest();
|
|
||||||
|
|
||||||
final String paramEmail = request.getParameter("email");
|
|
||||||
final String paramToken = request.getParameter("token");
|
|
||||||
|
|
||||||
if (paramEmail != null) {
|
|
||||||
email.setValue(state, paramEmail);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramToken != null) {
|
|
||||||
authToken.setValue(state, paramToken);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addValidationListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final String emailData = data.getString(EMAIL);
|
|
||||||
final String authTokenData = data.getString(AUTH_TOKEN);
|
|
||||||
final String passwordData = data.getString(PASSWORD);
|
|
||||||
final String passwordConfirmationData = data.getString(
|
|
||||||
PASSWORD_CONFIRMATION);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
final Optional<User> user = userRepository.findByEmailAddress(
|
|
||||||
emailData);
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.error", LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final OneTimeAuthManager oneTimeAuthManager = cdiUtil.findBean(
|
|
||||||
OneTimeAuthManager.class);
|
|
||||||
if (!oneTimeAuthManager.validTokenExistsForUser(
|
|
||||||
user.get(), OneTimeAuthTokenPurpose.RECOVER_PASSWORD)) {
|
|
||||||
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.error", LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<OneTimeAuthToken> tokens = oneTimeAuthManager
|
|
||||||
.retrieveForUser(
|
|
||||||
user.get(), OneTimeAuthTokenPurpose.RECOVER_PASSWORD);
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
for (OneTimeAuthToken token : tokens) {
|
|
||||||
if (oneTimeAuthManager.verify(token, authTokenData)) {
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.error", LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!passwordData.equals(passwordConfirmationData)) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.error.password_mismatch",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addProcessListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final String emailData = data.getString(EMAIL);
|
|
||||||
final String authTokenData = data.getString(AUTH_TOKEN);
|
|
||||||
final String passwordData = data.getString(PASSWORD);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
final Optional<User> user = userRepository.findByEmailAddress(
|
|
||||||
emailData);
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"No matching user found. This should not happen because "
|
|
||||||
+ "we verified that just a few moments ago.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.reset_password.error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
final ChallengeManager challengeManager = cdiUtil.findBean(
|
|
||||||
ChallengeManager.class);
|
|
||||||
try {
|
|
||||||
challengeManager.finishPasswordRecover(user.get(),
|
|
||||||
authTokenData,
|
|
||||||
passwordData);
|
|
||||||
} catch (ChallengeFailedException ex) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"Failed to finish password recovery.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.password_reset.error.failed"),
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
|
||||||
successPanel.setVisible(state, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.setVisibleDefault(formPanel, true);
|
|
||||||
page.setVisibleDefault(successPanel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.shiro.subject.Subject;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
|
|
||||||
// Note: Previously used SiteNodeRequestContext, nows using KernelRequestContext
|
|
||||||
// may be one cause that Login doesn't survive if the brwoser window is
|
|
||||||
// closed.
|
|
||||||
/**
|
|
||||||
* Initializes the value of the given parameter to the current user's screen
|
|
||||||
* name. Strangely similar to <code>EmailInitListener</code>.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:cwolfe@redhat.com">Crag Wolfe</a>
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class ScreenNameInitListener implements FormInitListener {
|
|
||||||
|
|
||||||
private static Logger LOGGER = LogManager.getLogger(
|
|
||||||
ScreenNameInitListener.class);
|
|
||||||
private StringParameter m_param;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param param
|
|
||||||
*/
|
|
||||||
public ScreenNameInitListener(StringParameter param) {
|
|
||||||
m_param = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
public void init(FormSectionEvent event) {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
LOGGER.debug("START");
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Subject subject = cdiUtil.findBean(Subject.class);
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
|
|
||||||
if (!subject.isAuthenticated()) {
|
|
||||||
LOGGER.debug("FAILURE not logged in");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final User user = shiro.getUser().get();
|
|
||||||
if (user.getName() == null) {
|
|
||||||
LOGGER.debug("FAILURE null screen name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.put(m_param.getName(), user.getName());
|
|
||||||
LOGGER.debug("SUCCESS");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
import org.libreccm.security.ChallengeFailedException;
|
|
||||||
import org.libreccm.security.ChallengeManager;
|
|
||||||
import org.libreccm.security.OneTimeAuthConfig;
|
|
||||||
import org.libreccm.security.OneTimeAuthManager;
|
|
||||||
import org.libreccm.security.OneTimeAuthToken;
|
|
||||||
import org.libreccm.security.OneTimeAuthTokenPurpose;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class UserAccountActivationForm extends Form {
|
|
||||||
|
|
||||||
private static final String EMAIL = "email";
|
|
||||||
private static final String AUTH_TOKEN = "authtoken";
|
|
||||||
|
|
||||||
private BoxPanel formPanel;
|
|
||||||
private TextField email;
|
|
||||||
private TextField authToken;
|
|
||||||
private SaveCancelSection saveCancelSection;
|
|
||||||
private BoxPanel successPanel;
|
|
||||||
|
|
||||||
public UserAccountActivationForm() {
|
|
||||||
super("user-activate-account");
|
|
||||||
addWidgets();
|
|
||||||
addListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addWidgets() {
|
|
||||||
formPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
|
|
||||||
email = new TextField(EMAIL);
|
|
||||||
email.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.email.label", LOGIN_BUNDLE));
|
|
||||||
email.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.email.hint", LOGIN_BUNDLE));
|
|
||||||
email.setMaxLength(256);
|
|
||||||
email.setSize(48);
|
|
||||||
email.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
email.addValidationListener(new StringLengthValidationListener(256));
|
|
||||||
formPanel.add(email);
|
|
||||||
|
|
||||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(ConfigurationManager.class);
|
|
||||||
final OneTimeAuthConfig oneTimeAuthConfig = confManager
|
|
||||||
.findConfiguration(OneTimeAuthConfig.class);
|
|
||||||
authToken = new TextField(AUTH_TOKEN);
|
|
||||||
authToken.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.auth_token.label", LOGIN_BUNDLE));
|
|
||||||
authToken.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.auth_token.hint", LOGIN_BUNDLE));
|
|
||||||
authToken.setMaxLength(oneTimeAuthConfig.getTokenLength());
|
|
||||||
authToken.setSize(oneTimeAuthConfig.getTokenLength());
|
|
||||||
formPanel.add(authToken);
|
|
||||||
|
|
||||||
saveCancelSection = new SaveCancelSection();
|
|
||||||
formPanel.add(saveCancelSection);
|
|
||||||
|
|
||||||
add(formPanel);
|
|
||||||
|
|
||||||
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
successPanel.add(new Label(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.success", LOGIN_BUNDLE)));
|
|
||||||
successPanel.add(new Link(new Label(
|
|
||||||
new GlobalizedMessage("login.form.account_activation.success.login",
|
|
||||||
LOGIN_BUNDLE)),
|
|
||||||
URL.there(LOGIN_PAGE_URL, null).getURL()));
|
|
||||||
add(successPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addListeners() {
|
|
||||||
addInitListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
final HttpServletRequest request = state.getRequest();
|
|
||||||
|
|
||||||
final String paramEmail = request.getParameter("email");
|
|
||||||
final String paramToken = request.getParameter("token");
|
|
||||||
|
|
||||||
if (paramEmail != null) {
|
|
||||||
email.setValue(state, paramEmail);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramToken != null) {
|
|
||||||
authToken.setValue(state, paramToken);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addValidationListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final String emailData = (String) data.get(EMAIL);
|
|
||||||
final String authTokenData = (String) data.get(AUTH_TOKEN);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
final Optional<User> user = userRepository.findByEmailAddress(
|
|
||||||
emailData);
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.error", LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final OneTimeAuthManager oneTimeAuthManager = cdiUtil.findBean(
|
|
||||||
OneTimeAuthManager.class);
|
|
||||||
if (!oneTimeAuthManager.validTokenExistsForUser(
|
|
||||||
user.get(), OneTimeAuthTokenPurpose.ACCOUNT_ACTIVATION)) {
|
|
||||||
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.error", LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<OneTimeAuthToken> tokens = oneTimeAuthManager
|
|
||||||
.retrieveForUser(
|
|
||||||
user.get(), OneTimeAuthTokenPurpose.ACCOUNT_ACTIVATION);
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
for (OneTimeAuthToken token : tokens) {
|
|
||||||
if (oneTimeAuthManager.verify(token, authTokenData)) {
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.error", LOGIN_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addProcessListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final String emailData = (String) data.get(EMAIL);
|
|
||||||
final String authTokenData = (String) data.get(AUTH_TOKEN);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
final Optional<User> user = userRepository.findByEmailAddress(
|
|
||||||
emailData);
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"No matching user found. This should not happen because "
|
|
||||||
+ "we verified that just a few moments ago.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
final ChallengeManager challengeManager = cdiUtil.findBean(
|
|
||||||
ChallengeManager.class);
|
|
||||||
try {
|
|
||||||
challengeManager.finishAccountActivation(user.get(),
|
|
||||||
authTokenData);
|
|
||||||
} catch (ChallengeFailedException ex) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"Failed to finish account activation.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.account_activation.error.failed"),
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
|
||||||
successPanel.setVisible(state, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.setVisibleDefault(formPanel, true);
|
|
||||||
page.setVisibleDefault(successPanel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.RequestEvent;
|
|
||||||
import com.arsdigita.bebop.event.RequestListener;
|
|
||||||
import com.arsdigita.kernel.security.Util;
|
|
||||||
|
|
||||||
import com.arsdigita.web.Web;
|
|
||||||
import com.arsdigita.web.LoginSignal;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.apache.shiro.subject.Subject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A RequestListener that redirects the user to register if not logged in. The
|
|
||||||
* redirection URL includes a return_url parameter to send the user back to this
|
|
||||||
* page after logging in. Pages must not continue processing if this listener
|
|
||||||
* redirects the user, since the response has already been committed
|
|
||||||
* (isLoggedIn() returns false in this case). In a future version, this listener
|
|
||||||
* will abort processing of the request if the user is not logged in.
|
|
||||||
*
|
|
||||||
* @author Phong Nguyen
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*/
|
|
||||||
public class UserAuthenticationListener implements RequestListener {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
UserAuthenticationListener.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the user is logged in, returns the User object.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return the User object for the logged in user
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if user is not logged in. Call isLoggedIn()
|
|
||||||
* to check for this case.
|
|
||||||
*/
|
|
||||||
public Subject getUser(final PageState state) {
|
|
||||||
if (!isLoggedIn(state)) {
|
|
||||||
throw new IllegalStateException("User is not logged in");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Subject subject = CdiUtil.createCdiUtil().findBean(Subject.class);
|
|
||||||
|
|
||||||
return subject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the user is logged in.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return true if the user is logged in
|
|
||||||
*/
|
|
||||||
public boolean isLoggedIn(final PageState state) {
|
|
||||||
return getUser(state).isAuthenticated();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the user is logged in. If not, redirects the client to the
|
|
||||||
* login page.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void pageRequested(final RequestEvent event) {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (!isLoggedIn(state)) {
|
|
||||||
LOGGER.debug("User is not logged in");
|
|
||||||
redirectToLoginPage(state);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirects the client to the login page.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*/
|
|
||||||
private void redirectToLoginPage(final PageState state) {
|
|
||||||
HttpServletRequest req = state.getRequest();
|
|
||||||
String urlBase = Util.getSecurityHelper().getLoginURL(req);
|
|
||||||
|
|
||||||
// first make sure we're not already looking at the login
|
|
||||||
// page -- if we are, don't redirect!
|
|
||||||
if (urlBase.equals(Web.getWebContext().getRequestURL().getRequestURI())) {
|
|
||||||
LOGGER.debug("preventing cyclic redirect to: " + urlBase);
|
|
||||||
// return without redirect
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new LoginSignal(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
// import com.arsdigita.kernel.security.LegacyInitializer;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.Hidden;
|
|
||||||
import com.arsdigita.bebop.parameters.URLParameter;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
import com.arsdigita.web.ReturnSignal;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.core.EmailAddress;
|
|
||||||
import org.libreccm.security.ChallengeManager;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edits a user. If returnURL is passed in to the form, then redirects to that
|
|
||||||
* URL_MSG; otherwise redirects to the user workspace.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
* @version $Id$
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class UserEditForm extends UserForm
|
|
||||||
implements FormProcessListener {
|
|
||||||
|
|
||||||
// private static final Logger s_log = Logger.getLogger(UserEditForm.class);
|
|
||||||
private UserAuthenticationListener m_listener
|
|
||||||
= new UserAuthenticationListener();
|
|
||||||
private final Hidden m_returnURL;
|
|
||||||
private final RequestLocal m_user = new RequestLocal() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object initialValue(final PageState ps) {
|
|
||||||
final Shiro shiro = CdiUtil.createCdiUtil().findBean(Shiro.class);
|
|
||||||
final User result = shiro.getUser().get();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
public UserEditForm() {
|
|
||||||
super("user-edit", new ColumnPanel(2), false);
|
|
||||||
|
|
||||||
addProcessListener(this);
|
|
||||||
|
|
||||||
// export return URL_MSG
|
|
||||||
m_returnURL = new Hidden(new URLParameter(
|
|
||||||
LoginHelper.RETURN_URL_PARAM_NAME));
|
|
||||||
m_returnURL.setPassIn(true);
|
|
||||||
add(m_returnURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
page.addRequestListener(m_listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected User getUser(final PageState state) {
|
|
||||||
return (User) m_user.get(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final UserRepository userRepository = CdiUtil.createCdiUtil().findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
User user = getUser(state);
|
|
||||||
if (user == null) {
|
|
||||||
throw new UncheckedWrapperException(
|
|
||||||
"Failed to retrieve user from page state");
|
|
||||||
}
|
|
||||||
|
|
||||||
user.setGivenName((String) m_firstName.getValue(state));
|
|
||||||
user.setFamilyName((String) m_lastName.getValue(state));
|
|
||||||
user.setName((String) m_screenName.getValue(state));
|
|
||||||
final String emailValue = (String) data.get(FORM_EMAIL);
|
|
||||||
if (!emailValue.equals(user.getPrimaryEmailAddress().getAddress())) {
|
|
||||||
final EmailAddress newAddress = new EmailAddress();
|
|
||||||
newAddress.setAddress(data.get(FORM_EMAIL).toString());
|
|
||||||
newAddress.setVerified(false);
|
|
||||||
user.setPrimaryEmailAddress(newAddress);
|
|
||||||
|
|
||||||
final ChallengeManager challengeManager = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(ChallengeManager.class);
|
|
||||||
challengeManager.createEmailVerification(user);
|
|
||||||
}
|
|
||||||
userRepository.save(user);
|
|
||||||
|
|
||||||
// redirect to workspace or return URL_MSG, if specified
|
|
||||||
final HttpServletRequest req = state.getRequest();
|
|
||||||
final String path = UI.getWorkspaceURL();
|
|
||||||
final URL fallback = com.arsdigita.web.URL.there(req, path);
|
|
||||||
throw new ReturnSignal(req, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,305 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.FormSection;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.form.Password;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.EmailParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common code for user new / add / edit forms.
|
|
||||||
*
|
|
||||||
* @author Admin UI Team
|
|
||||||
* @version $Id$
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class UserForm extends Form
|
|
||||||
implements LoginConstants, FormInitListener, FormValidationListener {
|
|
||||||
|
|
||||||
private final boolean m_newUser;
|
|
||||||
|
|
||||||
protected TextField m_firstName;
|
|
||||||
protected TextField m_lastName;
|
|
||||||
protected TextField m_email;
|
|
||||||
protected TextField m_screenName;
|
|
||||||
//protected TextField m_additional;
|
|
||||||
protected Password m_password;
|
|
||||||
protected Password m_confirm;
|
|
||||||
protected TextField m_question;
|
|
||||||
protected TextField m_answer;
|
|
||||||
|
|
||||||
protected Label m_securitySectionHeader = new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.securitySectionHeader"), false);
|
|
||||||
protected Label m_securityBlurb = new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.securityBlurb"));
|
|
||||||
protected Label m_passwordBlurb = new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.passwordBlurb"));
|
|
||||||
protected Label m_passwordLabel = new Label(PASSWORD);
|
|
||||||
protected Label m_confirmationLabel = new Label(PASSWORD_CONFIRMATION);
|
|
||||||
protected PasswordValidationListener m_passwordValidationListener
|
|
||||||
= new PasswordValidationListener();
|
|
||||||
protected NotEmptyValidationListener m_confirmationNotEmptyValidationListener
|
|
||||||
= new NotEmptyValidationListener();
|
|
||||||
protected Submit m_submit = new Submit(SUBMIT);
|
|
||||||
protected Label m_firstNameLabel = new Label(FIRST_NAME);
|
|
||||||
protected Label m_lastNameLabel = new Label(LAST_NAME);
|
|
||||||
protected Label m_urlLabel = new Label(URL_MSG);
|
|
||||||
protected Label m_screenNameLabel = new Label(SCREEN_NAME);
|
|
||||||
protected Label m_emailLabel = new Label(PRIMARY_EMAIL);
|
|
||||||
|
|
||||||
protected Container m_profilePart = new FormSection();
|
|
||||||
protected Container m_securityPart = new FormSection();
|
|
||||||
protected Container m_submitPart = new FormSection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a UserForm with the given name and panel.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @param panel
|
|
||||||
* @param newUser
|
|
||||||
*/
|
|
||||||
public UserForm(final String name,
|
|
||||||
final Container panel,
|
|
||||||
final boolean newUser) {
|
|
||||||
super(name, panel);
|
|
||||||
|
|
||||||
m_newUser = newUser;
|
|
||||||
|
|
||||||
setMethod(Form.POST);
|
|
||||||
addInitListener(this);
|
|
||||||
addValidationListener(this);
|
|
||||||
|
|
||||||
if (m_newUser) {
|
|
||||||
m_profilePart.add(new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.aboutYouSectionHeader"),
|
|
||||||
false), ColumnPanel.FULL_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SDM #163373: add length checking for first/last names. We do
|
|
||||||
// this with both maximum length parameters in the user/add form and
|
|
||||||
// with validation of the value that come in for processing.
|
|
||||||
m_firstName = new TextField(new StringParameter(FORM_FIRST_NAME));
|
|
||||||
m_firstName.setMaxLength(MAX_NAME_LEN);
|
|
||||||
m_firstName.setSize(20);
|
|
||||||
m_firstName.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
m_firstName.addValidationListener(new StringLengthValidationListener(
|
|
||||||
MAX_NAME_LEN));
|
|
||||||
|
|
||||||
m_profilePart.add(m_firstNameLabel);
|
|
||||||
m_profilePart.add(m_firstName);
|
|
||||||
|
|
||||||
m_lastName = new TextField(new StringParameter(FORM_LAST_NAME));
|
|
||||||
m_lastName.setMaxLength(MAX_NAME_LEN);
|
|
||||||
m_lastName.setSize(25);
|
|
||||||
m_lastName.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
m_lastName.addValidationListener(new StringLengthValidationListener(
|
|
||||||
MAX_NAME_LEN));
|
|
||||||
|
|
||||||
m_profilePart.add(m_lastNameLabel);
|
|
||||||
m_profilePart.add(m_lastName);
|
|
||||||
|
|
||||||
m_profilePart.add(m_screenNameLabel);
|
|
||||||
m_screenName = new TextField(new StringParameter(FORM_SCREEN_NAME));
|
|
||||||
m_screenName.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
m_profilePart.add(m_screenName);
|
|
||||||
|
|
||||||
// Primary email address
|
|
||||||
m_email = new TextField(new EmailParameter(FORM_EMAIL));
|
|
||||||
m_email.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
|
|
||||||
m_profilePart.add(m_emailLabel);
|
|
||||||
m_profilePart.add(m_email);
|
|
||||||
|
|
||||||
// TODO: support additional emails
|
|
||||||
// Additional email addresses
|
|
||||||
//m_additional = new TextField(new EmailParameter
|
|
||||||
// (FORM_ADDITIONAL_EMAIL));
|
|
||||||
//add(new Label(ADDITIONAL_EMAIL));
|
|
||||||
//add(m_additional);
|
|
||||||
// SDM #162740: disable user bio for now, as there
|
|
||||||
// is no support for User Bio in the kernel level.
|
|
||||||
// add(new Label(BIO));
|
|
||||||
// TextArea bioText = new TextArea(new StringParameter(FORM_BIO));
|
|
||||||
// bioText.setCols(50);
|
|
||||||
// bioText.setRows(10);
|
|
||||||
// add(bioText);
|
|
||||||
// add(new Label(""));
|
|
||||||
if (m_newUser) {
|
|
||||||
m_securityPart.add(new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.securitySectionHeader"),
|
|
||||||
false), ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
m_securityPart.add(new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.securityBlurb")),
|
|
||||||
ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
m_securityPart.add(new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.passwordBlurb")),
|
|
||||||
ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
// Password
|
|
||||||
m_password = new Password(new StringParameter(FORM_PASSWORD));
|
|
||||||
m_password.addValidationListener(new PasswordValidationListener());
|
|
||||||
|
|
||||||
m_securityPart.add(m_passwordLabel);
|
|
||||||
m_securityPart.add(m_password);
|
|
||||||
|
|
||||||
// Password confirmation
|
|
||||||
m_confirm = new Password(new StringParameter(
|
|
||||||
FORM_PASSWORD_CONFIRMATION));
|
|
||||||
m_confirm.addValidationListener(new NotEmptyValidationListener());
|
|
||||||
|
|
||||||
m_securityPart.add(m_confirmationLabel);
|
|
||||||
m_securityPart.add(m_confirm);
|
|
||||||
|
|
||||||
m_securityPart.add(new Label(LoginHelper
|
|
||||||
.getMessage("login.userNewForm.questionBlurb")),
|
|
||||||
ColumnPanel.FULL_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit
|
|
||||||
m_submitPart.add(m_submit, ColumnPanel.CENTER | ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
add(m_profilePart);
|
|
||||||
add(m_securityPart);
|
|
||||||
add(m_submitPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes this form with data from the user.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final User user = getUser(state);
|
|
||||||
if (user == null) {
|
|
||||||
throw new FormProcessException(LoginGlobalizationUtil.globalize(
|
|
||||||
"login.userForm.couldnt_load_user"));
|
|
||||||
}
|
|
||||||
m_firstName.setValue(state, user.getGivenName());
|
|
||||||
m_lastName.setValue(state, user.getFamilyName());
|
|
||||||
m_email.setValue(state, user.getPrimaryEmailAddress().getAddress());
|
|
||||||
m_screenName.setValue(state, user.getName());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current user for initialising the form.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return the current user, if the form should not be initialised with user
|
|
||||||
* data.
|
|
||||||
*/
|
|
||||||
protected abstract User getUser(final PageState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates this form. Verifies that the password and password-confirm
|
|
||||||
* fields match. If not it adds an error to the password-confirm field. Also
|
|
||||||
* verifies that primary email address and screen name are unique among all
|
|
||||||
* users.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
|
|
||||||
final UserRepository userRepository = CdiUtil.createCdiUtil().findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (m_newUser) {
|
|
||||||
// Verify that password and confirmation match
|
|
||||||
String password = (String) m_password.getValue(state);
|
|
||||||
String confirm = (String) m_confirm.getValue(state);
|
|
||||||
|
|
||||||
if ((password != null) && (confirm != null)
|
|
||||||
&& !password.equals(confirm)) {
|
|
||||||
data.addError(FORM_PASSWORD_CONFIRMATION,
|
|
||||||
ERROR_MISMATCH_PASSWORD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Verify that primary email and screen name are unique
|
|
||||||
final User user = getUser(state);
|
|
||||||
|
|
||||||
final String oldScreenName = user.getName();
|
|
||||||
final String screenName = (String) m_screenName.getValue(state);
|
|
||||||
if (screenName != null && !screenName.equals(oldScreenName)) {
|
|
||||||
final Optional<User> result = userRepository.findByName(screenName);
|
|
||||||
if (result.isPresent()) {
|
|
||||||
data.addError(FORM_SCREEN_NAME, ERROR_DUPLICATE_SN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String oldEmail = user.getPrimaryEmailAddress().getAddress();
|
|
||||||
final String email = (String) m_email.getValue(state);
|
|
||||||
if (KernelConfig.getConfig().emailIsPrimaryIdentifier()
|
|
||||||
&& email != null && !email.equals(oldEmail)) {
|
|
||||||
final Optional<User> result = userRepository.findByEmailAddress(email);
|
|
||||||
if (result.isPresent()) {
|
|
||||||
data.addError(FORM_EMAIL, ERROR_DUPLICATE_EMAIL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
// if the form has errors, clear the password fields so we don't
|
|
||||||
// send the passwords back over the network
|
|
||||||
if (m_newUser && !data.isValid()) {
|
|
||||||
m_password.setValue(state, "");
|
|
||||||
m_confirm.setValue(state, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ListPanel;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.web.ApplicationRepository;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A reusable Bebop component to display the primary attributes of the currently
|
|
||||||
* logged in user. Users can extend this class to provide information about
|
|
||||||
* another user by overriding the {@link
|
|
||||||
* UserInfo#register(Page)} and {@link UserInfo#getUser(PageState)} methods.
|
|
||||||
*
|
|
||||||
* @author Michael Bryzek
|
|
||||||
* @author Roger Hsueh
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
* @author Peter Boy (refactored to eliminate old type kernel.Package* /
|
|
||||||
* SiteNode)
|
|
||||||
|
|
||||||
*/
|
|
||||||
public class UserInfo extends SimpleContainer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger instance for debugging support
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(UserInfo.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds a list of content centers (Application instances) that exist on
|
|
||||||
* this installation. Usually there is only ONE installed, but obviously
|
|
||||||
* care is taken that one content-center may be installed per subsite.
|
|
||||||
*/
|
|
||||||
private List<CcmApplication> m_contentCenters;
|
|
||||||
|
|
||||||
private UserAuthenticationListener m_listener
|
|
||||||
= new UserAuthenticationListener();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public UserInfo() {
|
|
||||||
// add list of links
|
|
||||||
ListPanel list = new ListPanel(false);
|
|
||||||
list.add(new DynamicLink("login.userInfo.logoutLink",
|
|
||||||
LoginServlet.getLogoutPageURL()));
|
|
||||||
list.add(new DynamicLink("login.userInfo.editProfileLink",
|
|
||||||
LoginServlet.getEditUserProfilePageURL()));
|
|
||||||
list.add(new DynamicLink("login.userInfo.changePasswordLink",
|
|
||||||
LoginServlet.getRecoverPasswordPageURL()));
|
|
||||||
add(list);
|
|
||||||
|
|
||||||
// add user info text
|
|
||||||
add(new SimpleComponent() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateXML(PageState state, Element parent) {
|
|
||||||
if (!isLoggedIn(state)) {
|
|
||||||
LOGGER.debug("user is not logged in, so no XML generated");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final User user = getUser(state);
|
|
||||||
|
|
||||||
final Element userElement = new Element(
|
|
||||||
"subsite:userInfo", LoginServlet.SUBSITE_NS_URI);
|
|
||||||
|
|
||||||
// check if Content-Center (CMS Workspace) is installed and
|
|
||||||
// instantiated, if so collect all instantiated workspace apps.
|
|
||||||
if (m_contentCenters == null) {
|
|
||||||
|
|
||||||
m_contentCenters = new ArrayList<>();
|
|
||||||
|
|
||||||
final ApplicationRepository appRepo = CdiUtil
|
|
||||||
.createCdiUtil().findBean(ApplicationRepository.class);
|
|
||||||
|
|
||||||
m_contentCenters = appRepo.findByType(
|
|
||||||
"com.arsdigita.cms.ContentCenter");
|
|
||||||
}
|
|
||||||
|
|
||||||
// work on the list of installed (instantiated)
|
|
||||||
// workspaces (content-centers) if any and add some attributes
|
|
||||||
// to XML generator
|
|
||||||
if (m_contentCenters.size() > 0) {
|
|
||||||
|
|
||||||
Element workspaceURL;
|
|
||||||
Element contentCenters = userElement.newChildElement(
|
|
||||||
"subsite:contentCenters",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
|
|
||||||
// step through instantiated workspaces (content-centers)
|
|
||||||
for (CcmApplication application : m_contentCenters) {
|
|
||||||
// for each instance of Workspace = for each installed
|
|
||||||
// (instantiated) Workspace application:
|
|
||||||
// Add an Element
|
|
||||||
final Element center = contentCenters
|
|
||||||
.newChildElement("subsite:center",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
|
|
||||||
// Add attribute name = URL without trailing/leading "/"
|
|
||||||
center.addAttribute("name", application.getTitle()
|
|
||||||
.getValue(DispatcherHelper
|
|
||||||
.getNegotiatedLocale()));
|
|
||||||
|
|
||||||
workspaceURL = center.newChildElement(
|
|
||||||
"subsite:url",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
|
|
||||||
// get URL of Workspace application (instance)
|
|
||||||
final URL url = URL.there(state.getRequest(),
|
|
||||||
application.getPrimaryUrl());
|
|
||||||
workspaceURL.setText(url.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// in any case: add basic user attributes
|
|
||||||
userElement.addAttribute("id",
|
|
||||||
Long.toString(user.getPartyId()));
|
|
||||||
if (!user.getEmailAddresses().isEmpty()) {
|
|
||||||
userElement.addAttribute("email",
|
|
||||||
user.getEmailAddresses().get(0)
|
|
||||||
.getAddress());
|
|
||||||
}
|
|
||||||
userElement.addAttribute(
|
|
||||||
"name", String.format("%s %s",
|
|
||||||
user.getGivenName(),
|
|
||||||
user.getFamilyName()));
|
|
||||||
userElement.addAttribute("screenName", user.getName());
|
|
||||||
|
|
||||||
parent.addContent(userElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a request listener to the page to ensure that the user is logged in.
|
|
||||||
* Subclasses should override this method if they do not require users to be
|
|
||||||
* logged in. This method may be changed as we find more examples of how
|
|
||||||
* people are using this class.
|
|
||||||
*
|
|
||||||
* @pre p != null
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void register(Page p) {
|
|
||||||
super.register(p);
|
|
||||||
p.addRequestListener(m_listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return true if the user is logged in
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected boolean isLoggedIn(final PageState state) {
|
|
||||||
return m_listener.isLoggedIn(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return the User object for which we are generating information
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if user is not logged in. Call
|
|
||||||
* isLoggedIn(state) to check for this case.
|
|
||||||
*
|
|
||||||
* @pre state != null
|
|
||||||
* @post return != null
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected User getUser(final PageState state) {
|
|
||||||
if (!isLoggedIn(state)) {
|
|
||||||
throw new IllegalStateException("user is not logged in");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Shiro shiro = CdiUtil.createCdiUtil().findBean(Shiro.class);
|
|
||||||
final User user = shiro.getUser().get();
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,499 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.ElementComponent;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.form.CheckboxGroup;
|
|
||||||
import com.arsdigita.bebop.form.Hidden;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.Password;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.EmailParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.URLParameter;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
import com.arsdigita.kernel.security.SecurityConfig;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
|
||||||
import com.arsdigita.web.RedirectSignal;
|
|
||||||
import com.arsdigita.web.ReturnSignal;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
|
|
||||||
import org.apache.shiro.subject.Subject;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Bebop form that accepts login and password from the user and attempts to
|
|
||||||
* authenticate and then log in the user.
|
|
||||||
*
|
|
||||||
* Depending on security configuration it may generate a link to a NewUser
|
|
||||||
* registration form, where a new user may register itself. LoginServlet has to
|
|
||||||
* ensure that this page is created appropriately and is available.
|
|
||||||
*
|
|
||||||
* According to documentation in r1230 Simple SSO implementation: /ccm/register
|
|
||||||
* first tries to do SSO login, falling back to normal form-based login. Set
|
|
||||||
* waf.sso_login=true only after you make sure webapp can *only* be accessed
|
|
||||||
* through the frontend webserver doing the authentication.
|
|
||||||
*
|
|
||||||
* To make this work with Tomcat/mod_jk/Apache HTTPD: - use latest mod_jk
|
|
||||||
* (tested with 1.2.15) - add attribute Connector@tomcatAuthentication="false"
|
|
||||||
* to JK definition in server.xml
|
|
||||||
*
|
|
||||||
* @author Roger Hsueh
|
|
||||||
* @author Michael Bryzek
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class UserLoginForm extends Form implements LoginConstants,
|
|
||||||
FormInitListener,
|
|
||||||
FormValidationListener,
|
|
||||||
FormProcessListener {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
UserLoginForm.class);
|
|
||||||
|
|
||||||
// package friendly static form name makes writing HttpUnitTest easier
|
|
||||||
final static String FORM_NAME = "user-login";
|
|
||||||
private final CheckboxGroup m_isPersistent;
|
|
||||||
private final Hidden m_timestamp;
|
|
||||||
private final Hidden m_returnURL;
|
|
||||||
private TextField m_loginName;
|
|
||||||
private final Password m_password;
|
|
||||||
private final boolean m_autoRegistrationOn;
|
|
||||||
private final SecurityConfig securityConfig;// = SecurityConfig.getConfig();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor delegates to a constructor which creates a LoginForm
|
|
||||||
* without a link to a newUserRegistrationForm.
|
|
||||||
*/
|
|
||||||
public UserLoginForm() {
|
|
||||||
this(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserLoginForm(Container panel) {
|
|
||||||
this(panel, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserLoginForm(boolean autoRegistrationOn) {
|
|
||||||
this(new BoxPanel(), autoRegistrationOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor which does the real work, other constructors delegate to it.
|
|
||||||
*
|
|
||||||
* @param panel
|
|
||||||
* @param autoRegistrationOn
|
|
||||||
*/
|
|
||||||
public UserLoginForm(final Container panel,
|
|
||||||
final boolean autoRegistrationOn) {
|
|
||||||
super(FORM_NAME, panel);
|
|
||||||
|
|
||||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(ConfigurationManager.class);
|
|
||||||
securityConfig = confManager.findConfiguration(SecurityConfig.class);
|
|
||||||
|
|
||||||
setMethod(Form.POST);
|
|
||||||
addInitListener(this);
|
|
||||||
addValidationListener(this);
|
|
||||||
addProcessListener(this);
|
|
||||||
|
|
||||||
final KernelConfig kernelConfig = confManager.findConfiguration(
|
|
||||||
KernelConfig.class);
|
|
||||||
|
|
||||||
m_autoRegistrationOn = autoRegistrationOn;
|
|
||||||
|
|
||||||
m_timestamp = new Hidden(new StringParameter(FORM_TIMESTAMP));
|
|
||||||
add(m_timestamp);
|
|
||||||
|
|
||||||
m_returnURL = new Hidden(new URLParameter(
|
|
||||||
LoginHelper.RETURN_URL_PARAM_NAME));
|
|
||||||
m_returnURL.setPassIn(true);
|
|
||||||
add(m_returnURL);
|
|
||||||
|
|
||||||
setupLogin();
|
|
||||||
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.userRegistrationForm.password")));
|
|
||||||
m_password = new Password(new StringParameter(FORM_PASSWORD));
|
|
||||||
// Since new users should not enter a password, allow null.
|
|
||||||
//m_password.addValidationListener(new NotNullValidationListener());
|
|
||||||
add(m_password);
|
|
||||||
|
|
||||||
SimpleContainer cookiePanel = new BoxPanel(BoxPanel.HORIZONTAL);
|
|
||||||
m_isPersistent = new CheckboxGroup(FORM_PERSISTENT_LOGIN_P);
|
|
||||||
Label optLabel = new Label(LoginHelper.getMessage(
|
|
||||||
"login.userRegistrationForm.cookieOption"));
|
|
||||||
Option opt = new Option(FORM_PERSISTENT_LOGIN_P_DEFAULT, optLabel);
|
|
||||||
m_isPersistent.addOption(opt);
|
|
||||||
if (kernelConfig.isRememberLoginEnabled()) {
|
|
||||||
m_isPersistent.setOptionSelected(FORM_PERSISTENT_LOGIN_P_DEFAULT);
|
|
||||||
}
|
|
||||||
cookiePanel.add(m_isPersistent);
|
|
||||||
|
|
||||||
cookiePanel.add(new DynamicLink(
|
|
||||||
"login.userRegistrationForm.explainCookieLink",
|
|
||||||
LoginServlet.getCookiesExplainPageURL()));
|
|
||||||
add(cookiePanel);
|
|
||||||
|
|
||||||
add(new Submit(SUBMIT), ColumnPanel.CENTER | ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
if (securityConfig.isPasswordRecoveryEnabled()) {
|
|
||||||
add(new DynamicLink("login.userRegistrationForm.forgotPasswordLink",
|
|
||||||
LoginServlet.getRecoverPasswordPageURL()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_autoRegistrationOn) {
|
|
||||||
add(new DynamicLink("login.userRegistrationForm.newUserRegister",
|
|
||||||
LoginServlet.getNewUserPageURL()));
|
|
||||||
}
|
|
||||||
|
|
||||||
add(new ElementComponent("subsite:promptToEnableCookiesMsg",
|
|
||||||
LoginServlet.SUBSITE_NS_URI));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the login form parameters
|
|
||||||
*/
|
|
||||||
private void setupLogin() {
|
|
||||||
SimpleContainer loginMessage = new SimpleContainer(
|
|
||||||
"subsite:loginPromptMsg",
|
|
||||||
LoginServlet.SUBSITE_NS_URI);
|
|
||||||
|
|
||||||
final KernelConfig kernelConfig = KernelConfig.getConfig();
|
|
||||||
|
|
||||||
if (kernelConfig.emailIsPrimaryIdentifier()) {
|
|
||||||
loginMessage.setClassAttr("email");
|
|
||||||
} else {
|
|
||||||
loginMessage.setClassAttr("screenName");
|
|
||||||
}
|
|
||||||
|
|
||||||
add(loginMessage);
|
|
||||||
|
|
||||||
if (kernelConfig.emailIsPrimaryIdentifier()) {
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.userRegistrationForm.email")));
|
|
||||||
m_loginName = new TextField(new EmailParameter(FORM_LOGIN));
|
|
||||||
addInitListener(new EmailInitListener((EmailParameter) m_loginName.
|
|
||||||
getParameterModel()));
|
|
||||||
} else {
|
|
||||||
add(new Label(LoginHelper.getMessage(
|
|
||||||
"login.userRegistrationForm.screenName")));
|
|
||||||
m_loginName = new TextField(new StringParameter(FORM_LOGIN));
|
|
||||||
addInitListener(new ScreenNameInitListener(
|
|
||||||
(StringParameter) m_loginName.
|
|
||||||
getParameterModel()));
|
|
||||||
}
|
|
||||||
m_loginName.addValidationListener(new NotNullValidationListener());
|
|
||||||
add(m_loginName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
LOGGER.info("In init");
|
|
||||||
|
|
||||||
final KernelConfig kernelConfig = KernelConfig.getConfig();
|
|
||||||
|
|
||||||
if (kernelConfig.isSsoEnabled()) {
|
|
||||||
// try SSO login
|
|
||||||
LOGGER.info("trying SSO");
|
|
||||||
// try {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"SSO currently not supported");
|
|
||||||
// Web.getUserContext().loginSSO();
|
|
||||||
// s_log.info("loginSSO ok, now processing redirect_url");
|
|
||||||
// process(event);
|
|
||||||
// return;
|
|
||||||
// } catch (LoginException le) {
|
|
||||||
// // continue with standard form-based login
|
|
||||||
// s_log.debug("SSO failed", le);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
// try {
|
|
||||||
// // create timestamp
|
|
||||||
// String value = Credential.create(FORM_TIMESTAMP,
|
|
||||||
// 1000 * TIMESTAMP_LIFETIME_SECS).
|
|
||||||
// toString();
|
|
||||||
// m_timestamp.setValue(event.getPageState(), value);
|
|
||||||
// } catch (CredentialException e) {
|
|
||||||
// s_log.debug("Could not create timestamp", e);
|
|
||||||
// throw new FormProcessException(LoginGlobalizationUtil.globalize(
|
|
||||||
// "login.userLoginForm.couldnt_create_timestamp"));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void validate(FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
LOGGER.debug("In validate");
|
|
||||||
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
try {
|
|
||||||
// check timestamp
|
|
||||||
// try {
|
|
||||||
// Credential.parse((String) m_timestamp.getValue(state));
|
|
||||||
// } catch (CredentialException e) {
|
|
||||||
// s_log.info("Invalid credential");
|
|
||||||
//
|
|
||||||
// final String path = LoginServlet.getLoginExpiredPageURL();
|
|
||||||
// final URL_MSG url = com.arsdigita.web.URL_MSG.there(state.getRequest(),
|
|
||||||
// path);
|
|
||||||
//
|
|
||||||
// throw new RedirectSignal(url, false);
|
|
||||||
// }
|
|
||||||
// log in the user
|
|
||||||
if (m_loginName.getValue(state) != null) {
|
|
||||||
loginUser(event);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (!data.isValid()) {
|
|
||||||
// clear password from form data
|
|
||||||
m_password.setValue(state, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
LOGGER.debug("In process");
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final HttpServletRequest req = state.getRequest();
|
|
||||||
|
|
||||||
// Redirect to workspace or return URL_MSG, if specified.
|
|
||||||
final String path = UI.getUserRedirectURL(req);
|
|
||||||
|
|
||||||
final URL url = com.arsdigita.web.URL.there(req, path);
|
|
||||||
|
|
||||||
throw new ReturnSignal(req, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs in the user using the username, password, and "Remember this login?"
|
|
||||||
* request stored in the given form event. Subclasses can override this
|
|
||||||
* method or just one of the specific case handlers (onLoginSuccess,
|
|
||||||
* onBadPassword, onAccountNotFound, onLoginException).
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws FormProcessException if there is an unexpected login error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void loginUser(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Subject subject = CdiUtil.createCdiUtil().findBean(Subject.class);
|
|
||||||
|
|
||||||
final UsernamePasswordToken token = new UsernamePasswordToken(
|
|
||||||
m_loginName.getValue(state).toString(),
|
|
||||||
(String) m_password.getValue(state)
|
|
||||||
);
|
|
||||||
token.setRememberMe(getPersistentLoginValue(state, false));
|
|
||||||
try {
|
|
||||||
LOGGER.debug("Trying to login user {}...", subject.toString());
|
|
||||||
subject.login(token);
|
|
||||||
LOGGER.debug("User {} logged in successfully.", token.getUsername());
|
|
||||||
} catch (AuthenticationException ex) {
|
|
||||||
onLoginFail(event, ex);
|
|
||||||
LOGGER.debug("Login failed.", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.debug("subject = {}", subject.toString());
|
|
||||||
LOGGER.debug("Current session is: {}",
|
|
||||||
state.getRequest().getSession().getId());
|
|
||||||
LOGGER.debug("Current Shiro session is {}",
|
|
||||||
subject.getSession().getId().toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed when login succeeds. Default implementation does nothing.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void onLoginSuccess(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* @param ex
|
|
||||||
*
|
|
||||||
* @throws FormProcessException
|
|
||||||
*/
|
|
||||||
// protected void onBadPassword(final FormSectionEvent event,
|
|
||||||
// final FailedLoginException ex)
|
|
||||||
// throws FormProcessException {
|
|
||||||
// onLoginFail(event, ex);
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* Executed when login fails with a bad password or when autoLoginOn is set
|
|
||||||
* to false and the user doesn't exist. Default implementation marks
|
|
||||||
* password parameter with an error message.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* @param ex
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void onLoginFail(final FormSectionEvent event,
|
|
||||||
final AuthenticationException ex)
|
|
||||||
throws FormProcessException {
|
|
||||||
LOGGER.debug("Login fail");
|
|
||||||
event.getFormData().addError(ERROR_LOGIN_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed when login fails for an unrecognized problem. Default
|
|
||||||
* implementation logs the error and throws FormProcessException.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* @param ex
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*/
|
|
||||||
// protected void onLoginException(final FormSectionEvent event,
|
|
||||||
// final LoginException ex)
|
|
||||||
// throws FormProcessException {
|
|
||||||
// // unexpected error happened during login
|
|
||||||
// s_log.error("Login failed", ex);
|
|
||||||
// throw new FormProcessException(ex);
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* Determines whether a persistent cookie is requested in the given form.
|
|
||||||
* FORM_PERSISTENT_LOGIN_P whose value is equal to "1". If there is no such
|
|
||||||
* field in the form data, returns the specified default value.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
* @param defaultValue
|
|
||||||
*
|
|
||||||
* @return true if the specified formdata has a field named
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected boolean getPersistentLoginValue(final PageState state,
|
|
||||||
final boolean defaultValue) {
|
|
||||||
// Problem:
|
|
||||||
// getValue(state) returns an Object of type StringArray, if the
|
|
||||||
// Checkbox is marked.
|
|
||||||
// It returns an object of type String if it is not marked / left empty.
|
|
||||||
// Additionally, in some circumstances it may return null
|
|
||||||
// ODD!!
|
|
||||||
|
|
||||||
Object persistentLoginValue = m_isPersistent.getValue(state);
|
|
||||||
|
|
||||||
String value;
|
|
||||||
|
|
||||||
if (persistentLoginValue == null) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (persistentLoginValue instanceof String[]) {
|
|
||||||
value = ((String[]) persistentLoginValue)[0];
|
|
||||||
} else if (persistentLoginValue instanceof String) {
|
|
||||||
value = (String) persistentLoginValue;
|
|
||||||
} else {
|
|
||||||
value = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "1".equals(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*/
|
|
||||||
protected void redirectToNewUserPage(final PageState state) {
|
|
||||||
|
|
||||||
String url = LoginServlet.getNewUserPageURL();
|
|
||||||
|
|
||||||
ParameterMap map = new ParameterMap();
|
|
||||||
map.setParameter(LoginHelper.RETURN_URL_PARAM_NAME,
|
|
||||||
m_returnURL.getValue(state));
|
|
||||||
map.setParameter(FORM_PERSISTENT_LOGIN_P,
|
|
||||||
m_isPersistent.getValue(state));
|
|
||||||
map.setParameter(FORM_EMAIL,
|
|
||||||
m_loginName.getValue(state));
|
|
||||||
|
|
||||||
final URL dest = com.arsdigita.web.URL.there(state.getRequest(),
|
|
||||||
url,
|
|
||||||
map);
|
|
||||||
|
|
||||||
throw new RedirectSignal(dest, true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
|
|
||||||
import org.apache.shiro.subject.Subject;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An ActionListener that logs out the user.
|
|
||||||
*
|
|
||||||
* @author Sameer Ajmani
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class UserLogoutListener implements ActionListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs out the user.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final Subject subject = CdiUtil.createCdiUtil().findBean(Subject.class);
|
|
||||||
subject.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,390 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.ui.login;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
|
||||||
import com.arsdigita.bebop.form.Password;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.kernel.security.SecurityConfig;
|
|
||||||
import com.arsdigita.web.RedirectSignal;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
import org.libreccm.security.RegistrationManager;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.UserRepository;
|
|
||||||
|
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
|
||||||
import static com.arsdigita.ui.login.LoginServlet.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class UserNewForm extends Form {
|
|
||||||
|
|
||||||
// private static final Logger LOGGER = LogManager.getLogger(UserNewForm.class);
|
|
||||||
private static final String USERNAME = "username";
|
|
||||||
private static final String GIVEN_NAME = "givenname";
|
|
||||||
private static final String FAMILY_NAME = "familyname";
|
|
||||||
private static final String EMAIL = "email";
|
|
||||||
private static final String PASSWORD = "password";
|
|
||||||
private static final String PASSWORD_CONFIRMATION = "passwordconfirmation";
|
|
||||||
|
|
||||||
private BoxPanel formPanel;
|
|
||||||
private TextField userName;
|
|
||||||
private TextField givenName;
|
|
||||||
private TextField familyName;
|
|
||||||
private TextField email;
|
|
||||||
private Password password;
|
|
||||||
private Password passwordConfirm;
|
|
||||||
private SaveCancelSection saveCancelSection;
|
|
||||||
private BoxPanel finishedMessagePanel;
|
|
||||||
|
|
||||||
public UserNewForm() {
|
|
||||||
super("user-new");
|
|
||||||
|
|
||||||
addWidgets();
|
|
||||||
addListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addWidgets() {
|
|
||||||
formPanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
|
|
||||||
userName = new TextField(USERNAME);
|
|
||||||
userName.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.username.label", LOGIN_BUNDLE));
|
|
||||||
userName.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.username.hint", LOGIN_BUNDLE));
|
|
||||||
userName.setMaxLength(32);
|
|
||||||
userName.setSize(32);
|
|
||||||
formPanel.add(userName);
|
|
||||||
|
|
||||||
givenName = new TextField(GIVEN_NAME);
|
|
||||||
givenName.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.givenname.label", LOGIN_BUNDLE));
|
|
||||||
givenName.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.givenname.hint", LOGIN_BUNDLE));
|
|
||||||
givenName.setMaxLength(256);
|
|
||||||
givenName.setSize(32);
|
|
||||||
formPanel.add(givenName);
|
|
||||||
|
|
||||||
familyName = new TextField(FAMILY_NAME);
|
|
||||||
familyName.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.familyname.label", LOGIN_BUNDLE));
|
|
||||||
familyName.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.familyname.hint", LOGIN_BUNDLE));
|
|
||||||
familyName.setMaxLength(256);
|
|
||||||
familyName.setSize(32);
|
|
||||||
formPanel.add(familyName);
|
|
||||||
|
|
||||||
email = new TextField(EMAIL);
|
|
||||||
email.setLabel(new GlobalizedMessage("login.form.new_user.email.label",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setHint(new GlobalizedMessage("login.form.new_user.email.hint",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
email.setMaxLength(256);
|
|
||||||
email.setSize(48);
|
|
||||||
formPanel.add(email);
|
|
||||||
|
|
||||||
password = new Password(PASSWORD);
|
|
||||||
password.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.password.label", LOGIN_BUNDLE));
|
|
||||||
password.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.password.hint", LOGIN_BUNDLE));
|
|
||||||
password.setMaxLength(256);
|
|
||||||
password.setSize(32);
|
|
||||||
formPanel.add(password);
|
|
||||||
|
|
||||||
passwordConfirm = new Password(PASSWORD_CONFIRMATION);
|
|
||||||
passwordConfirm.setLabel(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.password_confirmation.label", LOGIN_BUNDLE));
|
|
||||||
passwordConfirm.setHint(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.password_confirmation.hint", LOGIN_BUNDLE));
|
|
||||||
passwordConfirm.setMaxLength(256);
|
|
||||||
passwordConfirm.setSize(32);
|
|
||||||
formPanel.add(passwordConfirm);
|
|
||||||
|
|
||||||
saveCancelSection = new SaveCancelSection();
|
|
||||||
formPanel.add(saveCancelSection);
|
|
||||||
|
|
||||||
add(formPanel);
|
|
||||||
|
|
||||||
finishedMessagePanel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
finishedMessagePanel.add(new Label(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.finshed_message", LOGIN_BUNDLE)));
|
|
||||||
final Link link = new Link(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.finished_message.activate_link",
|
|
||||||
LOGIN_BUNDLE)),
|
|
||||||
LOGIN_PAGE_URL + ACTIVATE_ACCOUNT_PATH_INFO);
|
|
||||||
finishedMessagePanel.add(link);
|
|
||||||
|
|
||||||
add(finishedMessagePanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addListeners() {
|
|
||||||
addSubmissionListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getCancelButton().isSelected(state)) {
|
|
||||||
throw new RedirectSignal(URL.there(state.getRequest(),
|
|
||||||
LOGIN_PAGE_URL),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addValidationListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ConfigurationManager confManager = cdiUtil.findBean(
|
|
||||||
ConfigurationManager.class);
|
|
||||||
final SecurityConfig securityConfig = confManager
|
|
||||||
.findConfiguration(
|
|
||||||
SecurityConfig.class);
|
|
||||||
if (!securityConfig.isAutoRegistrationEnabled()) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.autoregistration_not_enabled",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String userNameData = data.getString(USERNAME);
|
|
||||||
final String givenNameData = data.getString(GIVEN_NAME);
|
|
||||||
final String familyNameData = data.getString(FAMILY_NAME);
|
|
||||||
final String emailData = data.getString(EMAIL);
|
|
||||||
final String passwordData = data.getString(PASSWORD);
|
|
||||||
final String passwordConfirmationData = data.getString(
|
|
||||||
PASSWORD_CONFIRMATION);
|
|
||||||
|
|
||||||
if (Strings.isBlank(userNameData)) {
|
|
||||||
data.addError(
|
|
||||||
USERNAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.username.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (userNameData != null && userNameData.length() > 32) {
|
|
||||||
data.addError(
|
|
||||||
USERNAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.username.too_long",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings.isBlank(givenNameData)) {
|
|
||||||
data.addError(
|
|
||||||
GIVEN_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.givenname.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (givenNameData != null && givenNameData.length() > 256) {
|
|
||||||
data.addError(
|
|
||||||
GIVEN_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.givename.too_long",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings.isBlank(familyNameData)) {
|
|
||||||
data.addError(
|
|
||||||
FAMILY_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.familyname.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (familyNameData != null && familyNameData.length() > 256) {
|
|
||||||
data.addError(
|
|
||||||
FAMILY_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.familyname.too_long",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings.isBlank(emailData)) {
|
|
||||||
data.addError(
|
|
||||||
EMAIL,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.email.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (emailData != null && emailData.length() > 256) {
|
|
||||||
data.addError(
|
|
||||||
EMAIL,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.email.too_long",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings.isBlank(passwordData)) {
|
|
||||||
data.addError(
|
|
||||||
PASSWORD,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.password.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings.isBlank(passwordConfirmationData)) {
|
|
||||||
data.addError(
|
|
||||||
PASSWORD_CONFIRMATION,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.password.is_blank",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
UserRepository.class);
|
|
||||||
//check if there is already an account for the provided email
|
|
||||||
if (userRepository.findByEmailAddress(emailData) != null) {
|
|
||||||
data.addError(
|
|
||||||
EMAIL,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.email_already_registered",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if username is already in use
|
|
||||||
if (userRepository.findByName(userNameData) != null) {
|
|
||||||
data.addError(
|
|
||||||
USERNAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.username_already_in_use",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if password and confirmation match
|
|
||||||
if (!passwordData.equals(passwordConfirmationData)) {
|
|
||||||
data.addError(
|
|
||||||
PASSWORD,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form.new_user.error.passwords_do_not_match",
|
|
||||||
LOGIN_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addProcessListener(e -> {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
//Neuen User anlegen, mit banned = true
|
|
||||||
final FormData data = e.getFormData();
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
shiro.getSystemUser().execute(() -> {
|
|
||||||
// final UserRepository userRepository = cdiUtil.findBean(
|
|
||||||
// UserRepository.class);
|
|
||||||
// final UserManager userManager = cdiUtil.findBean(
|
|
||||||
// UserManager.class);
|
|
||||||
//
|
|
||||||
// final String givenNameData = (String) data.get(
|
|
||||||
// GIVEN_NAME);
|
|
||||||
// final String familyNameData = (String) data
|
|
||||||
// .get(FAMILY_NAME);
|
|
||||||
// final String username = (String) data.get(USERNAME);
|
|
||||||
// final String emailAddress = (String) data.get(EMAIL);
|
|
||||||
// final String passwordData = (String) data.get(PASSWORD);
|
|
||||||
// final User user = userManager.createUser(givenNameData,
|
|
||||||
// familyNameData,
|
|
||||||
// username,
|
|
||||||
// emailAddress,
|
|
||||||
// passwordData);
|
|
||||||
// user.setBanned(true);
|
|
||||||
// userRepository.save(user);
|
|
||||||
//
|
|
||||||
// //challenge erzeugen
|
|
||||||
// final ChallengeManager challengeManager = cdiUtil
|
|
||||||
// .findBean(ChallengeManager.class);
|
|
||||||
// try {
|
|
||||||
// challengeManager.sendAccountActivation(user);
|
|
||||||
// } catch (MessagingException ex) {
|
|
||||||
// throw new FormProcessException(
|
|
||||||
// "Failed to send account activation challenge.",
|
|
||||||
// new GlobalizedMessage(
|
|
||||||
// "login.form_new_user.error.creating_challenge_failed",
|
|
||||||
// LOGIN_BUNDLE), ex);
|
|
||||||
// }
|
|
||||||
|
|
||||||
final RegistrationManager registrationManager = cdiUtil
|
|
||||||
.findBean(RegistrationManager.class);
|
|
||||||
try {
|
|
||||||
registrationManager.registerUser(
|
|
||||||
data.getString(USERNAME),
|
|
||||||
data.getString(FAMILY_NAME),
|
|
||||||
data.getString(GIVEN_NAME),
|
|
||||||
data.getString(EMAIL),
|
|
||||||
data.getString(PASSWORD));
|
|
||||||
} catch (MessagingException ex) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
"Failed to send account activation challenge.",
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"login.form_new_user.error.creating_challenge_failed",
|
|
||||||
LOGIN_BUNDLE), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
|
||||||
finishedMessagePanel.setVisible(state, true);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.setVisibleDefault(formPanel, true);
|
|
||||||
page.setVisibleDefault(finishedMessagePanel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -18,12 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.core;
|
package org.libreccm.core;
|
||||||
|
|
||||||
import com.arsdigita.ui.admin.AdminUiConstants;
|
|
||||||
import com.arsdigita.ui.admin.applications.AdminApplicationCreator;
|
|
||||||
import com.arsdigita.ui.admin.applications.AdminApplicationSetup;
|
import com.arsdigita.ui.admin.applications.AdminApplicationSetup;
|
||||||
import com.arsdigita.ui.login.LoginApplicationCreator;
|
|
||||||
import com.arsdigita.ui.login.LoginApplicationSetup;
|
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
@ -36,7 +31,6 @@ import org.libreccm.modules.ShutdownEvent;
|
||||||
import org.libreccm.modules.UnInstallEvent;
|
import org.libreccm.modules.UnInstallEvent;
|
||||||
|
|
||||||
import org.libreccm.security.SystemUsersSetup;
|
import org.libreccm.security.SystemUsersSetup;
|
||||||
import org.libreccm.web.ApplicationType;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
|
@ -50,20 +44,6 @@ import java.util.Properties;
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
@Module(
|
@Module(
|
||||||
applicationTypes = {
|
|
||||||
@ApplicationType(
|
|
||||||
name = LoginConstants.LOGIN_APP_TYPE,
|
|
||||||
descBundle = "com.arsdigita.ui.login.LoginResources",
|
|
||||||
singleton = true,
|
|
||||||
creator = LoginApplicationCreator.class
|
|
||||||
),
|
|
||||||
@ApplicationType(
|
|
||||||
name = AdminUiConstants.ADMIN_APP_TYPE,
|
|
||||||
descBundle = "com.arsdigita.ui.admin.AdminResources",
|
|
||||||
singleton = true,
|
|
||||||
creator = AdminApplicationCreator.class
|
|
||||||
)
|
|
||||||
},
|
|
||||||
configurations = {
|
configurations = {
|
||||||
com.arsdigita.bebop.BebopConfig.class,
|
com.arsdigita.bebop.BebopConfig.class,
|
||||||
com.arsdigita.dispatcher.DispatcherConfig.class,
|
com.arsdigita.dispatcher.DispatcherConfig.class,
|
||||||
|
|
@ -107,9 +87,6 @@ public class CcmCore implements CcmModule {
|
||||||
adminJsfSetup.setup();
|
adminJsfSetup.setup();
|
||||||
|
|
||||||
LOGGER.info("Setting up login application...");
|
LOGGER.info("Setting up login application...");
|
||||||
final LoginApplicationSetup loginSetup
|
|
||||||
= new LoginApplicationSetup(event);
|
|
||||||
loginSetup.setup();
|
|
||||||
|
|
||||||
LOGGER.info("Importing category domains from bundle (if any)...");
|
LOGGER.info("Importing category domains from bundle (if any)...");
|
||||||
final Properties integrationProps = new Properties();
|
final Properties integrationProps = new Properties();
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
package org.libreccm.pagemodel;
|
package org.libreccm.pagemodel;
|
||||||
|
|
||||||
import com.arsdigita.ui.UI;
|
import com.arsdigita.ui.UI;
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
import com.arsdigita.ui.login.LoginServlet;
|
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
|
|
@ -97,19 +95,21 @@ public abstract class AbstractPageRenderer implements PageRenderer {
|
||||||
);
|
);
|
||||||
currentUserData.put(
|
currentUserData.put(
|
||||||
"loginUrl",
|
"loginUrl",
|
||||||
URL.there(request, LoginConstants.LOGIN_PAGE_URL).toString()
|
URL.there(request, "/login").toString()
|
||||||
);
|
);
|
||||||
currentUserData.put(
|
currentUserData.put(
|
||||||
"logoutUrl",
|
"logoutUrl",
|
||||||
URL.there(
|
URL.there(
|
||||||
request,
|
request,
|
||||||
LoginServlet.getLogoutPageURL()).toString()
|
"register/logout"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
currentUserData.put(
|
currentUserData.put(
|
||||||
"changePasswordUrl",
|
"changePasswordUrl",
|
||||||
URL.there(
|
URL.there(
|
||||||
request,
|
request,
|
||||||
LoginServlet.getLogoutPageURL()).toString()
|
"register/change-password"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ package org.libreccm.security;
|
||||||
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
import com.arsdigita.mail.Mail;
|
import com.arsdigita.mail.Mail;
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
import com.arsdigita.web.ParameterMap;
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
|
|
@ -44,7 +43,7 @@ import javax.inject.Inject;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginServlet.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service class for managing several so called challenges. These challenges
|
* A service class for managing several so called challenges. These challenges
|
||||||
|
|
@ -331,13 +330,13 @@ public class ChallengeManager {
|
||||||
final String path;
|
final String path;
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
case ACCOUNT_ACTIVATION:
|
case ACCOUNT_ACTIVATION:
|
||||||
path = ACTIVATE_ACCOUNT_PATH_INFO;
|
path = "/@login";
|
||||||
break;
|
break;
|
||||||
case EMAIL_VERIFICATION:
|
case EMAIL_VERIFICATION:
|
||||||
path = VERIFY_EMAIL_PATH_INFO;
|
path = "/@login";
|
||||||
break;
|
break;
|
||||||
case RECOVER_PASSWORD:
|
case RECOVER_PASSWORD:
|
||||||
path = RESET_USER_PASSWORD_PATH_INFO;
|
path = "/@login/recover";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
|
|
@ -346,7 +345,7 @@ public class ChallengeManager {
|
||||||
}
|
}
|
||||||
values.put("link",
|
values.put("link",
|
||||||
URL.there(request,
|
URL.there(request,
|
||||||
LoginConstants.LOGIN_PATH + path, null)
|
"/@login" + path, null)
|
||||||
.getURL());
|
.getURL());
|
||||||
|
|
||||||
final ParameterMap params = new ParameterMap();
|
final ParameterMap params = new ParameterMap();
|
||||||
|
|
@ -354,7 +353,7 @@ public class ChallengeManager {
|
||||||
params.setParameter("token", token.getToken());
|
params.setParameter("token", token.getToken());
|
||||||
values.put("full_link",
|
values.put("full_link",
|
||||||
URL.there(request,
|
URL.there(request,
|
||||||
LoginConstants.LOGIN_PATH + path, params)
|
"/@login" + path, params)
|
||||||
.getURL());
|
.getURL());
|
||||||
|
|
||||||
values.put("token", token.getToken());
|
values.put("token", token.getToken());
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,18 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.security;
|
package org.libreccm.security;
|
||||||
|
|
||||||
import com.arsdigita.ui.login.UserNewForm;
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.libreccm.core.CoreConstants;
|
import org.libreccm.core.CoreConstants;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CDI bean encapsulates all steps for registering a user, for example by a
|
* The CDI bean encapsulates all steps for registering a user.
|
||||||
* form provided to the user (like the {@link UserNewForm} of the login
|
|
||||||
* application).
|
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.ui.login;
|
package org.libreccm.ui.login;
|
||||||
|
|
||||||
import com.arsdigita.ui.login.LoginConstants;
|
|
||||||
|
|
||||||
import org.libreccm.ui.AbstractMessagesBean;
|
import org.libreccm.ui.AbstractMessagesBean;
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@ public class LoginMessages extends AbstractMessagesBean {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getMessageBundle() {
|
protected String getMessageBundle() {
|
||||||
return LoginConstants.LOGIN_UI_BUNDLE;
|
return "org.libreccm.ui.LoginBundle";
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue