/* ====================================================================
* The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
*
* Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by Jcorporate Ltd.
* (http://www.jcorporate.com/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. "Jcorporate" and product names such as "Expresso" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written permission,
* please contact info@jcorporate.com.
*
* 5. Products derived from this software may not be called "Expresso",
* or other Jcorporate product names; nor may "Expresso" or other
* Jcorporate product names appear in their name, without prior
* written permission of Jcorporate Ltd.
*
* 6. No product derived from this software may compete in the same
* market space, i.e. framework, without prior written permission
* of Jcorporate Ltd. For written permission, please contact
* partners@jcorporate.com.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Jcorporate Ltd. Contributions back
* to the project(s) are encouraged when you make modifications.
* Please send them to support@jcorporate.com. For more information
* on Jcorporate Ltd. and its products, please see
* <http://www.jcorporate.com/>.
*
* Portions of this software are based upon other open source
* products and are subject to their respective licenses.
*/
package com.jcorporate.expresso.services.controller;
import com.jcorporate.expresso.core.ExpressoConstants;
import com.jcorporate.expresso.core.controller.Controller;
import com.jcorporate.expresso.core.controller.ControllerException;
import com.jcorporate.expresso.core.controller.ControllerRequest;
import com.jcorporate.expresso.core.controller.ControllerResponse;
import com.jcorporate.expresso.core.controller.ErrorCollection;
import com.jcorporate.expresso.core.controller.Input;
import com.jcorporate.expresso.core.controller.NonHandleableException;
import com.jcorporate.expresso.core.controller.Output;
import com.jcorporate.expresso.core.controller.ServletControllerRequest;
import com.jcorporate.expresso.core.controller.State;
import com.jcorporate.expresso.core.controller.Transition;
import com.jcorporate.expresso.core.controller.session.PersistentSession;
import com.jcorporate.expresso.core.dataobjects.Securable;
import com.jcorporate.expresso.core.db.DBException;
import com.jcorporate.expresso.core.dbobj.DBObject;
import com.jcorporate.expresso.core.dbobj.ValidValue;
import com.jcorporate.expresso.core.i18n.Messages;
import com.jcorporate.expresso.core.misc.ConfigManager;
import com.jcorporate.expresso.core.misc.ConfigurationException;
import com.jcorporate.expresso.core.misc.SerializableString;
import com.jcorporate.expresso.core.misc.StringUtil;
import com.jcorporate.expresso.core.security.User;
import com.jcorporate.expresso.kernel.util.FastStringBuffer;
import com.jcorporate.expresso.services.dbobj.RegistrationDomain;
import com.jcorporate.expresso.services.dbobj.Setup;
import com.jcorporate.expresso.services.validation.AuthValidationException;
import com.jcorporate.expresso.services.validation.ValidationEntry;
import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForward;
import org.apache.struts.config.ForwardConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Vector;
/**
* Main Login Controller - used for login/logout and basic interaction with
* the registration system. This class recognizes the 'registration' classHandler
* name in the expresso-config.xml It uses the classname in that field to
* construct and forward to the appropriate registration class.
*/
public class SimpleLoginController
extends LoginController {
private static Logger log = Logger.getLogger(SimpleLoginController.class);
/**
* LoginController constructor. Sets all the states and parameters
* for the system.
*/
public SimpleLoginController() {
super();
State promptLogin = new State("promptLogin", "Prompt Login");
promptLogin.addOptionalParameter("next"); //Where do we link after login?
promptLogin.addOptionalParameter("immediate"); //Do we even display the
//confirmation page or do we
//just jump straight to the
//page on success? Y or N
promptLogin.setSecure(true);
promptLogin.addOptionalParameter("next"); //Where do we link after login?
promptLogin.addOptionalParameter("immediate"); //Do we even display the
//confirmation page or do we
//just jump straight to the
//page on success?
promptLogin.addOptionalParameter("LoginName");
addState(promptLogin);
State processLogin = new State("processLogin", "Login");
processLogin.setSecure(true);
addState(processLogin);
State processLogout = new State("processLogout", "Logout");
addState(processLogout);
State promptChangePassword = new State("promptChangePassword",
"Prompt Change Password");
promptChangePassword.setSecure(true);
addState(promptChangePassword);
State processChangePassword = new State("processChangePassword",
"Change Password");
processChangePassword.setSecure(true);
addState(processChangePassword);
State emailValidate = new State("emailValidate", "Validate User's Email Address");
emailValidate.addRequiredParameter("db");
emailValidate.addRequiredParameter("UserName");
emailValidate.addOptionalParameter("loginController");
addState(emailValidate);
State promptSendPassword = new State("promptSendPassword",
"Prompt Send Password");
addState(promptSendPassword);
State processSendPassword = new State("processSendPassword",
"Reset & Send Password");
processSendPassword.addParameter("Email",
false,
DBObject.EMAIL_MASK,
"You must enter a valid email address");
addState(processSendPassword);
State s = new State("promptRevalidate", "Prompt Revalidate");
this.addState(s);
s = new State("processRevalidate", "Process Revalidate");
s.addParameter("Email", false,
DBObject.EMAIL_MASK, "You must enter a valid email address");
this.addState(s);
setInitialState("promptLogin");
this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
}
/**
* If the user has validated the email sent to validate change password request,
* then this method actually resets thepassword and sends notification.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
* @throws NonHandleableException upon fatal error
*/
protected void runEmailValidateState(ControllerRequest request,
ControllerResponse response)
throws ControllerException,
NonHandleableException {
// The db context for the user (Note: this is different from the Validation entry context, which
// could very well be in a different DB context)
String dbname = StringUtil.notNull(request.getParameter("db"));
// The login name of the user
String loginName = StringUtil.notNull(request.getParameter("UserName"));
String registrationController = StringUtil.notNull(request.getParameter("RegistrationController"));
if (registrationController.length() == 0) {
registrationController = this.getDefaultRegistrationController().getClass().getName();
}
String loginController = StringUtil.notNull(request.getParameter("LoginController"));
try {
ErrorCollection errors = new ErrorCollection();
// Make sure that the user with this loginName actually exists
User user = new User();
user.setDataContext(dbname);
user.setLoginName(loginName);
if (!user.find()) {
//errors.addError("Account \"" + loginName + "\" not found");
errors.addError("login.accountnotfound", (Object) loginName);
}
// Make sure the User record has not been disabled for some reason
if (errors.isEmpty()) {
if (user.getAccountStatus().equals("D")) {
errors.addError("error.login.accountdisabled", (Object) loginName);
}
}
if (!errors.isEmpty()) {
response.saveErrors(errors);
return;
}
// Reset the user's password and send email
String password = null;
if (errors.isEmpty()) {
password = user.randomPassword();
user.setPassword(password);
user.setAccountStatus("A");
user.update();
FastStringBuffer msg = FastStringBuffer.getInstance();
msg.append(response.getString("passwdReset", loginName,
password,
Setup.getValue(request.getDataContext(),
"CompanyName"),
Setup.getValue(request.getDataContext(),
"HomePageURL")));
user.notify(response.getString("passwdResetSubject"),
msg.toString());
msg.release();
}
// If no errors happened so far, just create an Output to state
// the success and what happened
if (errors.isEmpty()) {
Output o = new Output("successMessage",
"Password succesfully reset and email sent to user \"" +
loginName + "\" ");
response.add(o);
FastStringBuffer msg = FastStringBuffer.getInstance();
try {
msg.append("You may log into the system using the password: \n");
msg.append(password);
msg.append("\n This password has been emailed to you ");
msg.append("and should be kept in a safe place");
response.add(new Output("passwordMessage", msg.toString()));
} finally {
msg.release();
}
Transition login = new Transition();
login.setLabel("Log In");
login.setName("promptLogin");
login.addParam(Controller.CONTROLLER_PARAM_KEY,
loginController);
login.addParam("dbContext", dbname);
response.add(login);
Transition register = new Transition();
register.setLabel("Register");
register.setName("promptSelfRegister");
register.addParam(Controller.CONTROLLER_PARAM_KEY,
registrationController);
register.addParam("dbContext", dbname);
response.add(register);
} else {
// Errors happened, add the error collection to the response
response.saveErrors(errors);
}
} catch (DBException dbe) {
throw new ControllerException("DB error", dbe);
}
}
/**
* @return the title of this controller
*/
public String getTitle() {
return ("Expresso Login");
}
/**
* Processes the "change my password" request.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
* @throws NonHandleableException upon fatal error
*/
protected void runProcessChangePasswordState(ControllerRequest request,
ControllerResponse response)
throws ControllerException,
NonHandleableException {
ErrorCollection errors = new ErrorCollection();
String loginName = request.getUser();
try {
User myUser = new User();
myUser.setDataContext(request.getDataContext());
myUser.setLoginName(loginName);
if (loginName.equals("") || loginName.equals(User.UNKNOWN_USER) ||
!myUser.find()) {
delayLogin(); //Slow 'em down
errors.addError(response.getString("error.login.mustloginchngpaswd"));
} else if (!myUser.passwordEquals(StringUtil.notNull(request.getParameter("oldPassword")))) {
errors.addError(response.getString("error.login.passwordinvalid", loginName));
}
if (errors.getErrorCount() < 1) {
if (!myUser.getAccountStatus().equals("A")) {
log.warn("User \"" + loginName +
"\" attempted changin password, denied because account status is \"" +
myUser.getAccountStatus() + "\"");
delayLogin(); //Slow 'em down
errors.addError(response.getString("error.login.disablednochngpaswd", loginName));
}
}
if (errors.getErrorCount() < 1) {
if (!request.getParameter("Password").equals(request.getParameter("password_verify"))) {
//password and verify do not match. Add an error.
errors.addError("error.login.passwdnomatch");
}
}
if (errors.getErrorCount() < 1) {
User user = new User();
user.setDataContext(request.getDataContext());
user.setUid(request.getUid());
user.retrieve();
user.setPassword(request.getParameter("Password"));
user.update();
}
} catch (DBException dbe) {
throw new ControllerException(dbe);
} finally {
if (errors.getErrorCount() < 1) {
response.clearFormCache();
Output successMessage = new Output("successMessage",
response.getString("PasswordChangeSuccess", loginName));
response.addOutput(successMessage);
response.addTransition(new Transition("promptChangePassword",
this));
response.addTransition(new Transition("promptLogin", this));
response.addTransition(new Transition("processLogout", this));
Transition editPref = new Transition();
editPref.setName("editPreferences");
editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
"com.jcorporate.expresso.services.controller.EditUserPreference");
editPref.addParam(STATE_PARAM_KEY, "edit");
response.add(editPref);
Transition showDBMenu = new Transition();
showDBMenu.setName("showDBMenu");
showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
this.getDefaultRegistrationController().getClass().getName());
showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
response.add(showDBMenu);
} else {
response.saveErrors(errors);
response.setFormCache();
transition("promptChangePassword", request, response);
}
}
}
/**
* Processes the login request.... loops back to the promptLoginState
* if there's an error processing this system.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
* @throws NonHandleableException upon fatal error
*/
protected void runProcessLoginState(ControllerRequest request,
ControllerResponse response)
throws ControllerException,
NonHandleableException {
ErrorCollection errors = new ErrorCollection();
PersistentSession session = request.getSession();
String destination = null;
/* Normally, accessing the HttpServletRequest/Response objects is a very bad
* idea. The fact that this controller does it means that it is non-portable
* outside the servlet environment
*/
ServletControllerRequest sr = (ServletControllerRequest) request;
HttpServletResponse hres = (HttpServletResponse) sr.getServletResponse();
HttpServletRequest hreq = (HttpServletRequest) sr.getServletRequest();
String dbContext = StringUtil.notNull(request.getParameter("dbContext"));
request.setDataContext(dbContext);
//
//Remove wildcards so that it isn't used in finding users.
//
String loginName = StringUtil.replaceAll(StringUtil.notNull(request.getParameter("LoginName"))
, "%", "");
int uid = 0;
try {
uid = attemptLogin(request, response, errors, hreq,
hres, session);
} catch (DBException dbe) {
throw new ControllerException(dbe);
} finally {
if (errors.getErrorCount() > 0) {
log.debug("Transitioning back to login state...");
response.saveErrors(errors);
response.setFormCache();
transition("promptLogin", request, response);
return;
}
///////////////////////////////////////
// good login
///////////////////////////////////////
request.setUser(loginName);
if (log.isDebugEnabled()) {
log.debug("good login for uid: " + uid);
}
// set locale
try {
request.getSession().removePersistentAttribute(Messages.LOCALE_KEY);
request.getSession().removePersistentAttribute(Globals.ERROR_KEY);
Messages.establishLocale(hreq);
} catch (ServletException se) {
log.error("Cannot manipulate local in session", se);
// do not abort entire action since this error is recoverable
}
/* Template method, override in your derived class to do any
work you may want to accomplish after a successful login */
postLoginProcessing(request, response);
String origURL = null;
if (session != null) {
SerializableString originalURL = (SerializableString) session.getPersistentAttribute(
ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY);
if (originalURL != null) {
origURL = originalURL.toString();
session.removePersistentAttribute(ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY);
}
}
String nextURL = StringUtil.notNull(request.getParameter("next"));
if (origURL != null && origURL.length() > 0) {
/** redirect to original destination
* BUT be careful to use an HTTP tag redirection
* so that the login cookie can be planted. we cannot
* simply call sendRedirect because then the cookie
* from the current response (set during attemptLogin)
* would not reach the browser. instead, we send a result
* page, which plants the cookie, and that page has a
* redirect tag.
*/
// provide redirect page with a link to destination in case the browser does
// not redirect properly
hreq.setAttribute("destination", origURL);
} else if (nextURL.length() > 0) {
hreq.setAttribute("destination", nextURL);
} else {
/**
*
if we got here, someone went directly to login page, so there
was no original "destination" besides the login page.
in that case, send them to a some "home" page,
specified as the forward "home" forward
*/
// use the previous status.jsp page if we do not find
// a "home" global forward specification
destination = null;
ActionForward fwd = null;
try {
ServletControllerRequest req = (ServletControllerRequest) request;
ForwardConfig fc = req.getMapping().getModuleConfig().findForwardConfig("home");
fwd = new ActionForward(fc.getName(), fc.getPath(),
fc.getRedirect(), fc.getContextRelative());
} catch (Exception e) {
log.error("cannot cast to get servlet request: ", e);
}
if (fwd == null) {
log.warn("global forward 'home' is missing using status.jsp");
response.addTransition(new Transition("promptChangePassword",
this));
response.addTransition(new Transition("promptLogin", this));
response.addTransition(new Transition("processLogout", this));
Transition editPref = new Transition();
editPref.setName("editPreferences");
editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
com.jcorporate.expresso.services
.controller.EditUserPreference.class.getName());
editPref.addParam(STATE_PARAM_KEY, "edit");
response.add(editPref);
Transition showDBMenu = new Transition();
showDBMenu.setName("showDBMenu");
showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
this.getDefaultRegistrationController()
.getClass().getName());
showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
response.add(showDBMenu);
} else {
destination = ConfigManager.getContextPath() +
fwd.getPath();
hreq.setAttribute("destination", destination);
if (log.isInfoEnabled()) {
log.info("via redirect.jsp, redirecting to: "
+ destination);
}
}
}
}
// redirect.jsp actually handles redirect
}
/**
* Logs a user out of the system and invalidates their session.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
*/
protected void runProcessLogoutState(ControllerRequest request,
ControllerResponse response)
throws ControllerException {
PersistentSession session = request.getSession();
String loginName = request.getUser();
String successMessage = loginName + " has been logged out";
if (loginName.equals("")) {
successMessage = "You were not logged in anyway!";
}
if (request instanceof ServletControllerRequest) {
ServletControllerRequest sreq = (ServletControllerRequest) request;
LoginController.setCookie(null, null,
(HttpServletResponse) sreq.getServletResponse(),
true, request.getDataContext());
}
Output successOutput = new Output();
successOutput.setName("sucessMessage");
successOutput.setContent(successMessage);
response.add(successOutput);
response.setUser(User.UNKNOWN_USER);
Transition pr = new Transition("promptSelfRegister", this.getDefaultRegistrationController());
pr.addParam("dbContext", request.getDataContext());
response.add(pr);
Transition pl = new Transition("promptLogin", this);
pl.addParam("dbContext", request.getDataContext());
response.add(pl);
session.setClientAttribute("UserName", "NONE");
session.setClientAttribute("Password", "NONE");
session.setClientAttribute("dbContext", "NONE");
session.removePersistentAttribute("CurrentLogin");
session.invalidate();
postLogoutProcessing(request, response);
}
/**
* Template Method pattern. override in subclasses as necessary
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
*/
public void postLogoutProcessing(ControllerRequest request, ControllerResponse response)
throws ControllerException {
// * Template Method pattern. override in subclasses as necessary
}
/**
* Process the "Please Send me a new password" state.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
* @throws NonHandleableException upon fatal error
*/
protected void runProcessSendPasswordState(ControllerRequest request,
ControllerResponse response)
throws ControllerException,
NonHandleableException {
//
//Validate input
//
ErrorCollection errors = request.getErrorCollection();
if (errors == null) {
errors = new ErrorCollection();
}
String dbContext = StringUtil.notNull(request.getParameter("dbContext"));
if (!dbContext.equals("")) {
request.setDataContext(dbContext);
}
response.add(new Transition("promptSelfRegister", this.getDefaultRegistrationController()));
response.add(new Transition("promptLogin", this));
String email = StringUtil.replaceAll(StringUtil.notNull(request.getParameter("Email")), "%", "");
if (email == null || email.length() == 0) {
errors.addError("error.login.invalidemail");
}
if (errors.getErrorCount() > 0) {
response.saveErrors(errors);
transition("promptSendPassword", request, response);
return;
}
try {
User myUser = new User();
myUser.setDataContext(request.getDataContext());
myUser.setEmail(email);
if (!myUser.find()) {
errors.addError("error.login.nouseremailfound");
}
String loginName = myUser.getLoginName();
if (errors.getErrorCount() < 1) {
if (!myUser.getAccountStatus().equals("A")) {
log.warn("User \"" + loginName +
"\" attempted password reset, denied because account status is \"" +
myUser.getAccountStatus() + "\"");
errors.addError("error.login.accountdiablednosendpaswd");
}
}
if (errors.getErrorCount() < 1) {
boolean emailValidate = false;
RegistrationDomain rd = null;
rd = new RegistrationDomain();
rd.setDataContext(request.getDataContext());
rd.setField("Name", myUser.getRegistrationDomain());
if (!rd.find()) {
throw new ControllerException("Registration domain \"" +
myUser.getRegistrationDomain() +
"\" has not been defined");
}
if (rd.getField("EmailValidate").equals("Y")) {
emailValidate = true;
}
/* HACK: Even though registration doesn't require */
/* email validate, passwords *always* do */
emailValidate = true;
ServletControllerRequest sparams = (ServletControllerRequest) request;
HttpServletRequest hreq = (HttpServletRequest) sparams.getServletRequest();
if (emailValidate) {
String emailAuthCode = myUser.getEmailAuthCode();
myUser.setEmailValCode(emailAuthCode);
myUser.update();
try {
ValidationEntry ve = new ValidationEntry(request.getDataContext());
ve.setValidationHandler("com.jcorporate.expresso.services.validation.ChangePasswordValidator");
ve.setTitle("Change Password Validation");
ve.setDesc("user=" + loginName + ", db=" +
request.getDataContext());
ve.setServer(hreq.getServerName());
ve.setPort(Integer.toString(hreq.getServerPort()));
ve.setContextPath(hreq.getContextPath());
ve.addParam("db", request.getDataContext());
ve.addParam("UserName", loginName);
ve.addParam("LoginController", this.getClass().getName());
ve.submit();
} catch (AuthValidationException avex) {
throw new ControllerException("Validation framework problem",
avex);
}
Output successMessage = new Output("successMessage",
"Email was sent to \"" +
email +
"\" to verify password change request");
response.addOutput(successMessage);
} else {
String password = myUser.randomPassword();
myUser.setPassword(password);
myUser.update();
FastStringBuffer msg = FastStringBuffer.getInstance();
msg.append(response.getString("passwdReset",
myUser.getLoginName(),
password,
Setup.getValue(request.getDataContext(),
"CompanyName"),
Setup.getValue(request.getDataContext(),
"HomePageURL")));
myUser.notify(response.getString("passwdResetSubject"),
msg.toString());
msg.release();
Output successMessage = new Output("successMessage",
"Password for \"" +
email +
"\" was reset and an email sent");
response.addOutput(successMessage);
}
}
} catch (Exception dbe) {
throw new ControllerException(dbe);
} finally {
if (errors.getErrorCount() < 1) {
response.clearFormCache();
} else {
response.saveErrors(errors);
response.setFormCache();
transition("promptSendPassword", request, response);
return;
}
}
}
/**
* Displays the 'change password' page.
*
* @param request The framework controller request
* @param response The framework ControllerResponse object
* @throws ControllerException upon logic error
*/
protected void runPromptChangePasswordState(ControllerRequest request,
ControllerResponse response)
throws ControllerException {
response.clearFormCache();
Input oldPassword = new Input();
oldPassword.setName("oldPassword");
oldPassword.setLabel(response.getString("CurrentPassword"));
String opw = StringUtil.notNull(response.getFormCache("oldPassword"));
oldPassword.setDefaultValue(opw);
oldPassword.setDisplayLength(15);
oldPassword.setMaxLength(30);
oldPassword.setType("password");
response.addInput(oldPassword);
Input password = new Input();
password.setName("Password");
password.setLabel(response.getString("NewPassword"));
String pw = StringUtil.notNull(response.getFormCache("Password"));
password.setDefaultValue(pw);
password.setDisplayLength(15);
password.setMaxLength(30);
password.setType("password");
response.addInput(password);
Input password_verify = new Input();
password_verify.setName("password_verify");
password_verify.setLabel(response.getString("RetypePassword"));
String pwv = StringUtil.notNull(response.getFormCache("password_verify"));
password_verify.setDefaultValue(pwv);
password_verify.setDisplayLength(15);
password_verify.setMaxLength(30);
password_verify.setType("password");
response.addInput(password_verify);
//Transition change = new Transition(response.getString("changePasswordTitle"), this);
Transition change = new Transition("processChangePassword", this);
change.setLabel(response.getString("changePasswordTitle"));
response.add(change);
response.addTransition(new Transition("promptChangePassword", this));
response.addTransition(new Transition("promptLogin", this));
response.addTransition(new Transition("processLogout", this));
Transition editPref = new Transition();
editPref.setName("editPreferences");
editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
"com.jcorporate.expresso.services.controller.EditUserPreference");
editPref.addParam(STATE_PARAM_KEY, "edit");
response.add(editPref);
Transition showDBMenu = new Transition();
showDBMenu.setName("showDBMenu");
showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
this.getDefaultRegistrationController().getClass().getName());
showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
response.add(showDBMenu);
}
/**
* Prompts the user for login.
*
* @param request The ControllerRequest object
* @param response The ControllerResponse object
*/
protected void runPromptLoginState(ControllerRequest request,
ControllerResponse response)
throws ControllerException {
PersistentSession session = request.getSession();
Input dbContext = new Input("dbContext");
String useDB = StringUtil.notNull(request.getParameter("dbContext"));
if (!useDB.equals("")) {
request.setDataContext(useDB);
response.addOutput(new Output("dbContext", useDB));
} else {
dbContext.setDefaultValue(request.getDataContext());
dbContext.setLabel(response.getString("Context/Database_"));
String oneConfigKey = null;
String oneDescrip = null;
Vector v = new Vector();
for (Enumeration ie = ConfigManager.getAllConfigKeys();
ie.hasMoreElements();) {
oneConfigKey = (String) ie.nextElement();
oneDescrip = "";
try {
oneDescrip = StringUtil.notNull(ConfigManager.getContext(oneConfigKey).getDescription());
if (oneDescrip.equals("")) {
oneDescrip = oneConfigKey;
}
/* If it's not an expresso context, you can't log in to it */
if (ConfigManager.getContext(oneConfigKey).hasSetupTables()) {
v.addElement(new ValidValue(oneConfigKey, oneDescrip));
}
} catch (ConfigurationException ce) {
throw new ControllerException(ce);
}
}
dbContext.setValidValues(v);
response.addInput(dbContext);
}
// Fill in the Login field with values in following priority: form-cache, cookie
Input loginName = new Input();
loginName.setName("LoginName");
String ln = StringUtil.notNull(response.getFormCache("LoginName"));
if (ln.equals("")) {
ln = request.getUser();
}
if (ln.equals(User.UNKNOWN_USER)) {
ln = "";
}
loginName.setDefaultValue(ln);
loginName.setDisplayLength(15);
loginName.setMaxLength(30);
loginName.setLabel("Login");
response.addInput(loginName);
// Fill in the Password field with values in following priority: form-cache, cookie
Input password = new Input();
password.setName("Password");
password.setLabel("Password");
String pw = StringUtil.notNull(response.getFormCache("Password"));
if ("".equals(pw)) {
pw = StringUtil.notNull(session.getClientAttribute("Password"));
}
if ("NONE".equals(pw)) {
pw = "";
}
password.setDefaultValue(pw);
password.setDisplayLength(15);
password.setMaxLength(30);
password.setType("password");
response.addInput(password);
// Fill in the Remember field
Input remember = new Input("Remember");
remember.setLabel("Remember Login");
String rm = response.getFormCache("Remember");
if (rm == null || rm.length() == 0) {
rm = "Y";
}
remember.setType("checkbox");
remember.setDefaultValue(rm);
response.addInput(remember);
//
//Put a hidden element on the form to pass the next parameter
//to process
//
String oneParam = StringUtil.notNull(request.getParameter("next"));
if (oneParam.length() > 0) {
Input nextURL = new Input("next");
nextURL.setType("hidden");
nextURL.setDefaultValue(oneParam);
response.addInput(nextURL);
}
oneParam = StringUtil.notNull(request.getParameter("immediate"));
if (oneParam.length() > 0) {
Input nextURL = new Input("immediate");
nextURL.setType("hidden");
nextURL.setDefaultValue(oneParam);
response.addInput(nextURL);
}
Transition login = new Transition("processLogin", this);
if (!useDB.equals("")) {
login.addParam("dbContext", useDB);
}
response.add(login);
Transition promptChangePassword = new Transition("promptChangePassword", this);
if (!useDB.equals("")) {
promptChangePassword.addParam("dbContext", useDB);
}
response.add(promptChangePassword);
response.add(new Transition("processLogout", this));
Transition promptSendPassword = new Transition("promptSendPassword",
this);
if (!useDB.equals("")) {
promptSendPassword.addParam("dbContext", useDB);
}
response.add(promptSendPassword);
String registerController = this.getDefaultRegistrationController().getClass().getName();
if (registerController != null) {
Transition promptRegister = new Transition();
promptRegister.setControllerObject(registerController);
promptRegister.setState("promptSelfRegister");
promptRegister.setName("promptRegister");
if (!useDB.equals("")) {
promptRegister.addParam("dbContext", useDB);
} else {
promptRegister.addParam("dbContext", "default");
}
response.add(promptRegister);
}
Transition promptLogin = new Transition("promptLogin", this);
if (!useDB.equals("")) {
promptLogin.addParam("dbContext", useDB);
}
response.add(promptLogin);
Transition showDBMenu = new Transition();
showDBMenu.setName("showDBMenu");
showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
this.getDefaultRegistrationController().getClass().getName());
showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
response.add(showDBMenu);
Transition editPref = new Transition();
editPref.setName("editPreferences");
editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
"com.jcorporate.expresso.services.controller.EditUserPreference");
editPref.addParam(STATE_PARAM_KEY, "edit");
response.add(editPref);
//
//Add a revalidate email link to the login screen if the default
//registration domain sends validation emails.
//
try {
String regDomain = Setup.getValue(request.getDataContext(), "defaultRegDomain");
if (regDomain != null && regDomain.length() > 0) {
RegistrationDomain rd = new RegistrationDomain(Securable.SYSTEM_ACCOUNT);
rd.setDataContext(request.getDataContext());
rd.setField("Name", regDomain);
if (rd.find()) {
String emailValidate = rd.getField("EmailValidate");
if (StringUtil.toBoolean(emailValidate)) {
Transition revalidate = new Transition("promptRevalidate", this);
revalidate.setLabel("Resend Email Validation");
response.add(revalidate);
}
}
}
} catch (DBException ex) {
log.error("Error getting default regdomain setup parameter", ex);
}
}
/**
* This function prompts for email revalidation
*
* @param request The <code>ControllerRequest</code> object handed to us
* by the framework.
* @param response The <code>ControllerResponse</code> object handed to us
* by the framework
* @throws ControllerException upon error
*/
protected void runPromptRevalidateState(ControllerRequest request,
ControllerResponse response) throws ControllerException {
response.setTitle("Enter Email For Revalidation Request");
response.addOutput(new Output("If there was a transient error in the email delivery" +
" system, you can request a resend of your email validation request."));
Input i = new Input("Email", "Email Address");
response.add(i);
Transition t = new Transition("processRevalidate", this);
t.setLabel("Resend Validation Email");
response.add(t);
}
/**
* This function processes the revalidation email request, attempts to
* find the user, and if successfull, forwards the control over to the
* RegistrationController to do the actual resending of the validation
* email.
*
* @param request The <code>ControllerRequest</code> object handed to us
* by the framework.
* @param response The <code>ControllerResponse</code> object handed to us
* by the framework
* @throws ControllerException upon error
* @throws NonHandleableException upon fatal error
*/
protected void runProcessRevalidateState(ControllerRequest request,
ControllerResponse response)
throws ControllerException, NonHandleableException {
response.setTitle("Revalidation Processing");
ErrorCollection ec = request.getErrorCollection();
if (ec == null) {
ec = new ErrorCollection();
}
if (ec.getErrorCount() > 0) {
response.setFormCache();
response.saveErrors(ec);
transition("promptRevalidate", request, response);
return;
}
try {
User u = new User();
u.setDBName(request.getDataContext());
u.setEmail(request.getParameter("Email"));
if (!u.find()) {
log.error("Received request for email address: "
+ request.getParameter("Email") +
"but user does not exist");
ec.addError("You entered an invalid email address");
} else if (!"I".equals(u.getAccountStatus())) {
ec.addError("This account is not waiting for email address confirmation");
}
if (ec.getErrorCount() > 0) {
response.setFormCache();
response.saveErrors(ec);
transition("promptRevalidate", request, response);
} else {
Transition reValidate = new Transition("revalidate",
"Click Here To Resend Email Validation",
this.getDefaultRegistrationController().getClass(), "processRevalidate");
reValidate.addParam("Email", u.getEmail());
reValidate.addParam("db", request.getDataContext());
reValidate.addParam("loginController", this.getClass().getName());
reValidate.transition(request, response, false);
}
} catch (DBException ex) {
log.error("Error processing email revalidation", ex);
throw new ControllerException("Error processing email revalidation." +
" The Administrator has been notified");
}
}
protected void runPromptSendPasswordState(ControllerRequest request,
ControllerResponse response)
throws ControllerException {
String dbContext = StringUtil.notNull(request.getParameter("dbContext"));
if (!dbContext.equals("")) {
request.setDataContext(dbContext);
}
Input email = new Input();
email.setName("Email");
email.setLabel("EMail");
String emailValue = StringUtil.notNull(response.getFormCache("Email"));
email.setDefaultValue(emailValue);
email.setDisplayLength(45);
email.setMaxLength(60);
response.addInput(email);
Transition submit = new Transition("processSendPassword", this);
submit.setLabel(response.getString("passwdResetSubject"));
submit.addParam("dbContext", request.getDataContext());
response.add(submit);
Transition pr = new Transition("promptSelfRegister", this.getDefaultRegistrationController());
pr.addParam("dbContext", request.getDataContext());
response.add(pr);
Transition pl = new Transition("promptLogin", this);
pl.addParam("dbContext", request.getDataContext());
response.add(pl);
}
/**
* Override the normal stateAllowed method to always allow
* access to this controller for certain states - otherwise no-one can ever log in :-)
*
* @param newState the state to transition to.
* @param params The controllerRequest object
* @return true if the state is allowed for the currently logged in user.
* @throws ControllerException if there is an error while looking up the sercurity permissions
*/
public synchronized boolean stateAllowed(String newState,
ControllerRequest params)
throws ControllerException {
if (newState.equals("promptChangePW") ||
newState.equals("processChangePW") ||
newState.equals("promptLogout")) {
return super.stateAllowed(newState, params);
}
return true;
} /* stateAllowed(String) */
}
|